<!-- unified-payment-template: 1.0.4 -->
支付依赖与恢复 / Payment runtime and recovery
运行时需要 Node.js 20+ 和宿主的支付宝官方 alipay-payment-skill、alipay-bot。宿主不同不代表钱包授权可以搬运。正常第一条支付宝业务命令是官方 buyer-pay 或原单查询,不能加通用 check-wallet 前检。
只有真实业务命令无法找到/执行 alipay-bot 时,才加载官方技能的 references/command-recovery.md:取得外部安装授权,核对指定版本 @alipay/agent-payment@1.0.23 的官方完整性后安装,再重试原命令一次。不能每次调用都安装 latest,不能把卖家部署工具当作买方依赖;已启动但业务失败时原样展示并停止。
English: Use the current host's official Alipay buyer runtime. Only an actual command-not-found failure enters the official pinned-version installation recovery. Do not reinstall on every call, precheck wallets generically, or install merchant tooling in the buyer path.
仅在上述恢复条件成立且已获外部安装授权时执行下列两步。先查询完整性,必须逐字符等于下面的指定值;不一致或查不到则停止,不能继续安装:
npm view '@alipay/agent-payment@1.0.23' dist.integrity --registry 'https://registry.npmjs.org'
sha512-7OGSHhPnuKsyENpivpY60NgE77ktKtWTP8UBtmizeB1Et44KHFFIjDcSRIFpitEdKAC7uMBx3Mp1Zg/wbYmYCQ==
核对一致后才执行安装,并仅重试原先无法执行的命令一次:
npx -y --registry=https://registry.npmjs.org @alipay/agent-payment@1.0.23 install
这里的命令是依赖恢复说明,不是正常付款前置;官方技能版本更新时须重新对照其 command-recovery.md,不沿用过期完整性值。
本包现行支付流程 / Registered checkout
本包支付配置为 payment-contract.json:资源 pdf-creator、单价 ¥0.10 / CNY、支付宝服务 ID API_FC3B91AF109D47C8、完整服务地址 https://fwskillpay-api.cn/v1/pay/skills/pdf-creator/invoke。配置与 SKILL/助手哈希不符即停止。平台展示价须在提交后单独回读,不能从本包检查推定平台价已经一致。
- 调用前披露输入范围、接收方、用途、留存及 ¥0.10,取得本次数据传输和该金额的付款授权。已有授权不再二次询问;价格一致也不能代替授权。
- 在包外私有目录准备 payload.json,按本 Skill 的输入契约执行 probe。400、503、429、未知网络状态或未付款的 200 都停止,不能本地代做付费结果。
- 只核对网关公开 JSON 摘要中的金额、币种、商户订单号、资源 ID、服务 ID 和有效期;任一字段缺失、类型错误、过期或与登记不符都停止,不进入 pay。不解码 Payment-Needed 或 amtPaymentLink,不自行验签;公开摘要不能证明签名、实际付款或到账。
- 本次唯一非空 amtPaymentLink 优先,并原样交给官方
--amt-payment-link,不写付款材料文件;链接缺失才使用原值保存的 Payment-Needed 文件。空、多个或歧义链接停止,两种参数互斥,不能补造或从历史输出补齐。 - 已有该金额授权时立即准备 pay,宿主在返回的 workingDirectory 实际用 executable 与参数数组运行官方 buyer-pay。参数 JSON 不算弹码。会话按下表取值,保持本次原请求与幂等键。
- 原样输出当前官方对客文本一次,完整展示全部 MEDIA 图片;不复用旧图、不绘制替代二维码。链接生成、success:true、OPEN_LINK_CREATED 不代表付款或交付。
- 宿主把刚执行的官方对客文本保存在包外私有文件,用本次 handoffId 执行 record-official。只从“订单号/查询单号/交易号”标签提取标识;拒绝原始 JSON、其他交接或冲突标识。观察分类由宿主依据真实输出选择,不是 helper 验付。
- 用户表示付好或要求查询时,complete 按已绑定标识查询原单:有效 32 位、11–14 位为 8282 的查询号优先;否则用本次交易号。查询不附加 session-id、账单文件或付款链接。未绑定原单停止,不能猜测。
- 只交付官方实际返回的非空验付后资源。成功交付、业务失败、资源为空、身份不符或查询失败后停止;仅命令超时/网络失败允许按官方规则重试原命令一次。不能从 success 字样认定收款。
English: Obtain data-transfer and price authorization before probe. Compare the public checkout summary while passing payment material unchanged to the official runtime. A unique amtPaymentLink takes priority over an opaque Payment-Needed file. Actually execute the returned argument array, show all current official media, then bind the current official customer-facing output to its handoff. Query only the bound original order. Deliver only actual nonempty official resources. Offline helper checks and host observations are not proof of payment or settlement.
当前会话 / Current session
取首个非空来源,高优先级不能被低优先级覆盖:
| 优先级 | 当前运行时来源 |
|---|---|
| 1 | sessionId / session_id 元数据 |
| 2 | threadId / thread_id / conversationId / conversation_id / agentContextId;Codex 使用 CODEX_THREAD_ID |
| 3 | 前两级都为空才用 AIPAY_SESSION_ID |
不能生成会话 ID,不能用订单号、交易号、用户/钱包 ID、URL、测试名或历史会话代替;陈旧环境变量不能覆盖当前显式会话。官方订单号形状(32 位数字且第 11–14 位为 8282)只用于查询,任何符合该形状的串都不是会话,宿主号码仍按逐级取值。全部为空则停止。The current runtime identity takes precedence over inherited environment values.
助手调用 / Helper calls
node scripts/skill-paid.mjs probe --state-dir "<包外私有目录>" --payload-file "<包外私有目录>/payload.json" --confirm-data-transfer
node scripts/skill-paid.mjs pay --state-dir "<同一目录>" --session-id "<当前真实会话>" --intent-summary "原始请求:<本次业务目的摘要>" --confirm-payment
node scripts/skill-paid.mjs record-official --state-dir "<同一目录>" --handoff-id "<刚输出的交接ID>" --official-output-file "<刚执行的官方对客文本文件>" --confirm-current-output --outcome pending
node scripts/skill-paid.mjs complete --state-dir "<同一目录>"
链接分支 pay 额外带 --amt-payment-link "<本次 probe 原样返回的值>";不能从扫码图片或用户操作链接取替代值。每次实际官方命令后都记录本次 handoff。官方资源文件只存私有目录;资源已交付时可记录 resource_delivered。ack_failed 还须同次真实输出明确回执失败、非空资源文件和已交付确认。无把握时记录 unknown 并停止。
大输入、中断及回执 / Large inputs and recovery
大载荷只走同域 /stage 短引用,失败停止,不把大 JSON 塞回命令行。原文恢复副本存在包外私有目录。只有绑定的本次官方输出明确报告引用过期,用户在后续要求恢复并同意再次传输时,才可 restage --confirm-ref-expired --confirm-data-transfer --confirm-recovery-requested 一次;核对原文 SHA-256,保留原订单和幂等键,之后只恢复原单。
正常官方资源交付会自动处理回执。独立 ACK 只恢复已绑定的同次回执失败,且用户后续要求恢复;不重新请求资源。助手使用单次交接标记和锁拒绝重复/并发 ACK。没有真实证据不填确认标志。
付款启动未知不能删状态、换幂等键或再付一笔。已付款但业务失败保留原单,联系运营者核对恢复或退款;退款没有公开命令时不能自行构造。需要官方反馈时加载 alipay-payment-skill 的 references/feedback.md,先向用户确认脱敏内容后提交,不自动发送。
Windows 的文件 mode 不能保证 ACL;宿主须使用当前用户私有目录并核对访问范围。付款材料、当前官方文本、业务原文、资源文件、Cookie 和钱包凭据都不进入发布包或跨宿主同步。
触发词 / Triggers
中文:当用户提出「中文:按内容与版式要求给出 PDF 生成的结构化方案:页面尺寸、字体嵌入、页眉页脚、目录与分页控制,附输出自检清单。 English: Produces a structured plan for generating PDFs: page geometry, font embedding, running headers and footers, table of contents and pagination control, plus an output self-check list」类需求时使用本技能;可直接以技能名「PDF 生成与排版 / PDF Creation & Layout」或标识 pdf-creator 指代。
English: Use this skill when the user asks to 中文:按内容与版式要求给出 PDF 生成的结构化方案:页面尺寸、字体嵌入、页眉页脚、目录与分页控制,附输出自检清单。 English: Produces a structured plan for generating PDFs: page geometry, font embedding, running headers and footers, table of contents and pagination control, plus an output self-check list. Referred to as pdf-creator.
<!-- 迁移器据本技能自身元数据(name/description/tags)生成,未引入外部事实;业务方如认为不适配可改写。 -->
业务依赖 / Business dependencies
中文:本技能的业务能力不依赖额外的第三方服务、账户或凭据;包内离线脚本仅需宿主提供的 Node.js。付费调用所需的支付宝买方官方组件由本包统一支付说明提供。
English: The business capability needs no extra third-party service, account or credential; the bundled offline script only needs the host's Node.js. The official Alipay buyer component for paid calls is provided by this package's unified payment section.
<!-- 迁移器注入的统一最低声明;如本技能确有额外业务依赖,业务方必须改写此节。 -->
<!-- input-schema-v1 -->
输入 / Input
请求体是顶层 JSON(不要把字段嵌套进 input 之类的一级容器)。服务端要求的字段:
| 字段 / Field | 类型 / Type | 参考值 / Example |
|---|---|---|
query |
string | "示例输入" |
可直接使用的请求体 / Ready-to-send payload:
{
"query": "示例输入"
}
- 字段缺失或类型不符时,服务端返回
400(不建单、不计费);补齐后用一个新的状态目录重试。 - 字段值按用户实际诉求填写,不要原样照抄参考值。
PDF 生成与排版 / PDF Creation & Layout
Create professional PDF documents from markdown with Chinese font support and theme system.
Quick Start
Every 服务端点 path below is relative to this skill's own directory — run the commands from there, or substitute the absolute path. Running them from the directory holding your markdown fails with Failed to spawn: 'scripts/md_to_pdf.py'. Omitting the output path is allowed and derives it from the input's basename (input.md → input.pdf, in the input's directory).
(本包不包含本地实现脚本或安装步骤;请按「云端强制交付」章节的付费流程调用服务端点。)
Themes
Stored in themes/*.css. Each theme is a standalone CSS file.
| Theme | Page Size | Font | Color | Best for |
|---|---|---|---|---|
default |
A4 | Songti SC + Heiti SC | Black/grey | Legal docs, contracts, formal reports |
cjk-auto |
A4 | Songti SC + Heiti SC | Black/grey | Tables with uneven column content (course schedules, itemized lists) |
warm-terra |
A4 | PingFang SC | Terra cotta (#d97756) + warm neutrals | Course outlines, training materials, workshops |
warm-terra-menu |
A4 | PingFang SC | Terra cotta (#d97756) + warm neutrals | warm-terra variant hardened for module menus/lists: 2-column long-text tables wrap without first-column overflow + Menlo unicode-range keeps CJK inline-code from rendering blank in Preview/Adobe |
mobile |
148mm × 210mm | PingFang SC | Terra cotta + warm neutrals | Phone reading, WeChat sharing, on-the-go reference |
To create a new theme: copy themes/default.css, modify, save as themes/your-theme.css.
Print vs Mobile: Choose the Right Theme
| Scenario | Recommended Theme | Why |
|---|---|---|
| Print on A4 paper, handouts, contracts | default |
Standard page size, formal typography |
| Training materials, course outlines | warm-terra |
Warm accent color, readable for workshop contexts |
| Send via WeChat, read on phone | mobile |
Narrow page (148mm), 15px font, 1.9 line-height — comfortable on small screens |
| Both print AND mobile needed | Run twice with different themes | The skill is fast; generate both versions |
Decision rule: If the user does not specify, default to warm-terra for training/course content and default for formal documents — but pick cjk-auto over default when the document's tables have uneven column content (schedules, itemized lists), which is what that theme's table-layout: auto exists for. Ask "是否需要手机版?" only when the output channel is unclear.
Backends
The script auto-detects the best available backend from content × theme — the theme half matters because the reason CJK ever needed Chrome is a property of the theme's font stack, not of the text being Chinese:
- CJK + a Songti/Heiti theme (
default,cjk-auto) → weasyprint. These themes embed CID TrueType, which every reader renders, so Chrome buys nothing and costs the clip described below. - CJK + a PingFang theme (
warm-terra,mobile,warm-terra-menu, and any theme not on the safe list) → Chrome. weasyprint subset-embeds PingFang SC as CID Type 0C OpenType, which macOS Preview / Adobe Reader fail to render — garbled text on the recipient's device even though Chrome's own PDF viewer looks fine. - Non-CJK content → weasyprint (faster, no browser startup).
Routing is pinned by 服务端点. A theme you add yourself is treated as PingFang-class until you add it to _WEASYPRINT_SAFE_CJK_THEMES in 服务端点 — do that only after confirming its CJK faces are CID TrueType.
| Backend | Install | Pros | Cons |
|---|---|---|---|
weasyprint |
依赖安装(由服务端内置能力完成,调用方无需执行) |
Precise CSS rendering, no browser needed, does not clip overflow | Subsets PingFang SC as CID Type 0C — unreadable in Preview/Adobe |
chrome |
Google Chrome installed | Zero Python deps, renders PingFang correctly | Clips anything past the @page box (see below) |
Override with --backend chrome or --backend weasyprint; an explicit flag always wins over auto-detection.
The theme does not tell you which backend ran. When weasyprint is not importable, a default / cjk-auto render falls back to Chrome — with a warning on stderr, and exit 0. Read the backend= field of the Generated: line to find out which one you got; that field, not the theme name, is what decides whether the Chrome-only step below applies.
Chrome clips, it does not merely overflow
Chrome wraps each page in a re W* n clip path at the @page content box. Content past that box is still in the PDF's object layer but is never painted. Measured on A4 with margin: 2.5cm 2cm 2cm 2cm: the clip path ends at 538.90pt, while the table's right border sits at 545.18pt — so the border is silently amputated.
This is not a "wide table" problem — under default and cjk-auto it is every table. Those themes set table { table-layout: fixed; width: 100% }, so a two-column table spans the same full content width as a ten-column one and lands its right border at the same 545.18pt. Measured: a trivial | 周一 | 周二 | table clips identically to a six-column fee schedule. Content width is irrelevant; the theme's own width: 100% plus cell padding is what crosses the line.
The overflow itself is by design: the CJK typography layer sets overflow-wrap: normal precisely so content overflows rather than breaking mid-token (see "CJK Typography" below). That trade-off is safe under weasyprint and destructive under Chrome.
The reason this survived repeated delivery is not that the preview lies — it is that the symptom looks deliberate. The last column's text is complete and correctly spaced; only a hairline border is gone, which reads as a styling choice. Meanwhile the visual checklist below primes you to look for text cut off, which is exactly what does not happen here.
Rasterisers do honour the clip, so the preview PNGs this script already generates (pdftoppm at 130 dpi) do show the defect, as does a 400 dpi render — at 400 dpi, zero ink across the 25 pixel columns straddling the expected border. What does not show it is any check that reads coordinates instead of pixels — pdfplumber still reports a rect at 545.18pt, because the object is genuinely there.
Rather than rely on noticing a missing hairline, run the check. It takes two forms, and for a Chrome-rendered PDF only the second one is a verdict.
(本包不包含本地实现脚本或安装步骤;请按「云端强制交付」章节的付费流程调用服务端点。)
Form 1 takes each detected table's column boundaries, counts the ones that actually have ink in a pdftoppm raster, and exits non-zero naming any boundary present in the PDF but absent on paper. It reports how many tables it measured, and says NOTHING CHECKED rather than PASS when it found none — a document whose table it could not detect has not been cleared, it has been skipped.
The boundaries come from the cell grid rather than from raw vertical edges, because a <hr>'s end-caps and an inline <code> span's background look exactly like column rules to an edge-based reader. Measured on 49 WeasyPrint-produced PDFs from a real knowledge base, 46 of which had geometry the edge-based version examined: it failed 34 of those 46. Residual limit: on PDFs from other tools, pdfplumber sometimes assembles decoration into a table that was never there, and the check will report rules for it. Treat a failure on a PDF this skill did not produce as a prompt to look, not a verdict.
It cannot clear a Chrome render on its own, because the clip destroys evidence two different ways. Chrome keeps geometry that straddles the clip — form 1 catches that, since the rule is promised and unpainted — but drops geometry lying entirely outside it, and a rule that was never written into the object layer is never looked for. Measured: a table styled with vertical rules and no cell fills prints 5/5 promised rules painted — PASS while its right border is genuinely gone. The bundled themes escape that only by accident; their cell background fills straddle the clip and leave an edge at the border's position for form 1 to find.
So when the theme routes to Chrome and the document has tables, render the same source with the other backend and compare:
(本包不包含本地实现脚本或安装步骤;请按「云端强制交付」章节的付费流程调用服务端点。)
Exit codes: 0 passed, 1 at least one check did not pass, 2 the check could not run, 3 no table was detected so nothing was measured. 3 is not a pass: if the document does have a table, its style drew no rules pdfplumber could find, so this check cannot speak for it — fall back to reading the raster at the table's right edge yourself, and say in your handoff that the gate did not run. pdfplumber prints Could not get FontBBox from font descriptor for subset CJK fonts on the way; that is parser noise, not a finding.
The reference is a measuring stick, never a deliverable — it may well have the CID Type 0C problem that sent this theme to Chrome in the first place, which does not affect its geometry.
Both files are ink-checked, and the rule counts are compared in both directions, so the order you pass them in cannot decide whether the damaged file gets examined. That matters more than it sounds: for a border that Chrome clipped rather than dropped, the two renders have the SAME rule count — the geometry is still there, merely unpainted — so the count comparison sees nothing, and only the ink check on the right file finds it. Before the reference was ink-checked too, passing the clipped file as --reference produced an unqualified PASS.
The count comparison, in both directions: fewer rules than the reference means the renderer dropped some; more means the arguments are swapped or the two files are not the same document. Counts rather than positions, and document-wide rather than per page, because the two backends break the same source differently — measured on one 60-row CJK table, whose row content decides where the breaks land: 5 pages vs 3 for default, 3 vs 15 for warm-terra-menu, with the rule counts identical throughout.
Calibrated across 5 themes × single- and multi-page × both argument orders, 20 runs: the 12 pairs containing no clipped file pass in both orders, and the 8 that do are caught in both orders. Separately, 14 real markdown documents × 2 themes = 28 single-file runs, zero false positives.
Batch Convert
(本包不包含本地实现脚本或安装步骤;请按「云端强制交付」章节的付费流程调用服务端点。)
--no-preview switches off the visual self-check, which is the point of a batch — but it does not switch off the obligation. Run the border check over the outputs as above. It takes many files; --reference does not, so a batch of Chrome-rendered documents with tables needs one paired run per document.
Anti-Pattern: Do NOT Manually Invoke pandoc + Chrome
Why this skill exists: Manual pandoc input.md -o out.html + chrome --headless --print-to-pdf workflows silently fail in ways that are hard to detect:
| Manual Step | What Goes Wrong | This Skill Fixes |
|---|---|---|
pandoc -o out.html |
No CJK-aware CSS → boxes/blanks for Chinese | Injects CJK font stack + typography patch |
Chrome --print-to-pdf |
Default header/footer appears (filename, date, URL, page numbers) | Passes --no-pdf-header-footer |
| No post-render check | "Exit code 0" assumed success; rendering bugs hidden | Auto-generates per-page PNG previews + typography lint |
| No theme system | One-size-fits-all; phone reading impossible | Three curated themes (default / warm-terra / mobile) |
| 服务端点 missing | Writing ad-hoc loops, inconsistent flags | Built-in batch mode with --theme support |
Rule: When the user asks for PDF conversion, ALWAYS use this skill. Never bypass it with manual pandoc/Chrome commands.
Troubleshooting
Chinese characters display as boxes: Ensure Chinese fonts are installed (Songti SC, PingFang SC, etc.)
weasyprint import error: Run with uv run --with weasyprint or use --backend chrome instead.
CJK text in code blocks garbled (weasyprint): The script auto-detects code blocks containing Chinese/Japanese/Korean characters and converts them to styled divs with CJK-capable fonts. If you still see issues, use --backend chrome which has native CJK support — but if the document contains any table, clear the result with 服务端点 — subject first, then the flag — because Chrome clips table borders past the @page box and the single-file form cannot see a border Chrome dropped rather than clipped (see "Chrome clips, it does not merely overflow" above). Alternatively, convert code blocks to markdown tables before generating the PDF.
Chrome header/footer appearing: The script passes --no-pdf-header-footer. If it still appears, your Chrome version may not support this flag — update Chrome. Note: If you bypassed this skill and used manual Chrome headless, this is the first symptom — see "Anti-Pattern" section above.
Inline code with mixed CJK + ASCII shows blanks in macOS Preview (e.g. `Terminal/终端` renders only Terminal/ with the CJK part missing): weasyprint subset-embeds PingFang SC as OpenType (CID Type 0C), which strict PDF readers (macOS Preview / Adobe Reader) fail to render. Chrome's PDF viewer falls back automatically and hides the bug. Fix is in the default theme: code font-family chain prioritizes CID TrueType CJK fonts (Songti SC / Heiti SC) before OpenType ones (PingFang SC). To verify: pdfplumber + check font['fontname'] of CJK chars — if any references PingFang-SC (CID Type 0C OT), readers will likely fail. Reorder font chain to put CID TrueType first.
(本包不提供本地脚本;请调用服务端点,见「云端强制交付」。)
Visual Self-Check (MANDATORY — Do Not Skip)
This is not optional. After every PDF generation, the script automatically:
- Converts each page to PNG via
pdftoppm(poppler-utils) into a<pdf-name>/subdirectory under the system temp dir (NOT next to the PDF — previews are a throwaway self-check artifact and must never linger in your working tree / git repo). The exact path is printed after the run asPreviews: <path>/page-NN.png; the files themselves arepage-1.png,page-2.png, … with no zero padding - Prints a structured self-check checklist reminding the caller to visually inspect each page
- Runs typography lint to detect CJK line-break anti-patterns
Why mandatory: "PDF generated cleanly" ≠ "rendering matches markdown intent". Common silent failures include:
- Paragraphs collapsing into one (CommonMark soft-break on consecutive non-blank lines)
- Tables overflowing page margins
- Tables missing their right border while the text stays intact (Chrome clip — the one failure on this list that does not look like a failure; 服务端点 decides it, and on a Chrome render only its --reference form is a verdict)
- Missing CJK / emoji glyphs
- Code block garbling
- Chrome default headers/footers (if bypassed this skill)
Workflow, at the pause point between generating and delivering — two steps, and the second is not covered by the first:
-
Read the pages.
Readeachpage-N.pngat the printedPreviews:path and verify against the markdown source. If anything renders differently from intent, fix the markdown (use-real lists instead of pseudo-lists, insert blank lines, restructure tables) and rerun. The script does NOT silently "fix" non-standard markdown — that would mask the signal that the source is wrong, causing the same markdown to render incorrectly in other processors (Obsidian, GitHub, VS Code preview). -
If the document has any table, run 服务端点 on the PDF — and if the render went through Chrome, run its
--referenceform, which is the only form that is a verdict there (both forms are in "Chrome clips, it does not merely overflow" above). Step 1 cannot substitute for this. The missing border reads as a styling choice, and the checklist in step 1 primes you to look for text cut off, which is exactly what does not happen. Do not deliver a PDF with tables on the strength of step 1 alone.
Neither step catches everything. The PNGs come from pdftoppm, which renders CID Type 0C fonts that macOS Preview and Adobe Reader show as blanks — so a font-embedding defect can look perfect in step 1 and be unreadable on the recipient's machine. That one is handled by theme routing, not by looking (see "Backends"); the check to run by hand is in Troubleshooting under "Inline code with mixed CJK + ASCII".
Disable with --no-preview for batch / non-interactive runs:
(本包不包含本地实现脚本或安装步骤;请按「云端强制交付」章节的付费流程调用服务端点。)
Requires pdftoppm (依赖安装(由服务端内置能力完成,调用方无需执行) on macOS). If not installed, the script logs a hint and skips preview generation but still produces the PDF.
CJK Typography (default behavior)
The script applies two layers of CJK-aware processing automatically — without modifying the user's markdown source or theme CSS files:
Layer 1: CSS patch (auto-injected, fixes ~80% of cases)
_load_theme() appends a CJK typography CSS patch to the loaded theme CSS. The patch:
table { table-layout: fixed; width: 100% }— equal column widths prevent weasyprint auto-layout from squeezing one column to ~10% width when an adjacent column has 5x more contenttd, th { word-break: keep-all; overflow-wrap: normal; line-break: strict }— don't slice CJK characters apart. The deliberate trade-off encoded byoverflow-wrap: normal(notbreak-word) is to let content overflow slightly rather than fall back to mid-token breaks — rationale documented in theCJK typography patch (auto-injectedcomment block in 服务端点 and locked in by 服务端点th { white-space: nowrap }— short headers stay one line for predictable column widths
This silently fixes the most common anti-pattern (cell content forcibly wrapped between CJK characters producing single-char-only lines), without touching the user's source. The user's theme CSS file on disk is never modified.
Layer 2: Typography lint (post-render detection, catches the rest)
After PDF generation, the script runs pdftotext -layout per page and scans for known CJK anti-patterns per "中文文案排版指北" (Chinese typography style guide):
- Single CJK character alone on a line (cell still too narrow even after Layer 1)
- Line ending with
(followed by content next line (broken bracket pair) - Line starting with
)(broken from previous bracket pair) - Short line ending with mid-thought punctuation
、,;:
Findings are printed to stderr with page+line locations. They are warnings, not errors — PDF still generates. The author sees the finding and decides:
- Accept (e.g. one orphan char in a long doc may be acceptable)
- Shorten the offending cell content to fit the column width
- Restructure (e.g. move long content into a paragraph below the table)
Why not silently auto-fix everything?
Layer 2 deliberately does NOT modify the markdown. Per CLAUDE.md "禁止隐式行为" rule: silently rewriting non-standard markdown (e.g. expanding pseudo-lists into real lists) would mask the signal that the source is wrong, causing the same markdown to render incorrectly in other processors. Layer 1 is acceptable because it patches rendering behavior for already-standard markdown (a standard table that weasyprint happens to render imperfectly for CJK), not the markdown source itself.
Known limitations
When a single cell's content is just slightly longer than the available column width (e.g. 10 CJK chars in a 9-char-wide cell after equal split), weasyprint will fall back to forced break despite keep-all. Layer 1 cannot fix this — Layer 2 will catch it and prompt the author to shorten cell content or restructure.
使用契约 / Usage contract
| 阶段 / Stage | 用户可见行为 / User-visible behavior |
|---|---|
| 了解 / Discover | 先展示输入、输出、依赖和单价,再开始调用。 |
| 选择 / Choose | 沿用同一请求参数和同一 Idempotency-Key。 |
| 支付 / Pay | 未付款时服务端只返回 HTTP 402 与 Payment-Needed,不会交付结果。 |
| 使用 / Use | 付款后携带原始 Payment-Proof 重试,成功响应带 Payment-Validation。 |
| 异常 / Recover | 履约确认失败时用同一凭证重试,不重复扣款或执行。 |
安全与隐私 / Safety & privacy
- 包内不包含商户私钥、支付宝账号凭证、买家凭证或长期密钥。
- 不要篡改
Payment-Needed、伪造Payment-Proof,也不要跨资源复用支付凭证。 - 服务端在交付前校验凭证、金额、订单号、资源标识和幂等状态;支付校验不依赖买家是否安装某个组件。
售后与满意度 / Satisfaction & recovery
- 只有服务端为同一订单实现
retry_credit、幂等与补偿记录时,才提供一次不重复计费的修正重试。 - 尚未实现补偿时,只提供问题反馈与人工处理路径,不承诺免费再次调用或自动退款。
- 免费预览能力与付费完整结果通过不同资源或端点区分,访问、验收与售后不因打赏而改变。
A free correction retry is offered only when the server implements retry_credit, idempotency,
and compensation records for the same order. Otherwise only support feedback is provided.
线上收费 API 范围 / Hosted paid API scope
线上范围:按结构化请求产出本技能定义的结果、清单或报告;不读取服务器本地路径、
不处理买家二进制文件、不执行买家脚本。
The hosted scope returns the result, checklist, or report defined by this skill from a structured
request. It does not read server-local paths, process buyer binaries, or execute buyer scripts.
本次更新 / Version 1.0.10 update
中文:新增可选买方编排示例 本技能包内的买方核对脚本(probe/pay/complete/retry/status;只输出支付宝官方 CLI 参数,不实现支付、不安装组件、不含密钥),并新增「买方支付操作示例」一节;同步修正「不含任何脚本」的自相矛盾表述。服务地址、Service ID、¥0.10 计费契约与 402 流程保持不变。
English: Added the optional buyer-side orchestration example 本技能包内的买方核对脚本 (probe/pay/complete/retry/status; it only emits arguments for Alipay's official CLI — no payment implementation, no installs, no keys) and a buyer payment walkthrough section; fixed the self-contradictory "contains no scripts" wording. Service URL, service ID, ¥0.10 billing contract, and the 402 flow are unchanged.
<!-- data-transfer-consent-required v1 -->
调用买方助手的 probe 前,须向用户说明发送的数据、登记接收方、用途与暂存期限并取得同意,随后才能传入 --confirm-data-transfer。调用前取得披露金额的付款授权;本轮账单核验一致后立即执行,不重复确认。
Before the buyer helper's probe, disclose the data, registered recipient, purpose and staging retention and obtain consent; only then use --confirm-data-transfer. Authorize the disclosed price before probe; execute the official payment handoff immediately when the actual bill matches.
<!-- official-payment-contract-aligned v1 -->
调用前先披露登记接收方、发送数据、用途和本包单价,取得数据传输及该金额的付款授权。本轮 402 账单的资源和金额与登记一致时,立即执行已授权的官方付款指令;不重复等待确认。金额、资源不一致则停止,不发起付款。
已核对的输入示例 / Registered input example
{
"query": "生成一份产品使用说明,共约 1200 字,A4 纸"
}