From 42931d6294c00b6601f8621725b7c72038f4127b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jim=20Liu=20=E5=AE=9D=E7=8E=89?= Date: Thu, 5 Mar 2026 00:55:56 -0600 Subject: [PATCH] feat(baoyu-post-to-x): add post-composition verification and improve stability Add automatic check after article images are inserted: verifies remaining XIMGPH placeholders and expected vs actual image count. Increase CDP timeout to 60s and add 3s DOM stabilization delay between image insertions. --- skills/baoyu-post-to-x/SKILL.md | 6 +++ skills/baoyu-post-to-x/references/articles.md | 8 +++- skills/baoyu-post-to-x/scripts/x-article.ts | 42 ++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/skills/baoyu-post-to-x/SKILL.md b/skills/baoyu-post-to-x/SKILL.md index b61605e..48ea876 100644 --- a/skills/baoyu-post-to-x/SKILL.md +++ b/skills/baoyu-post-to-x/SKILL.md @@ -172,6 +172,12 @@ npx -y bun ${SKILL_DIR}/scripts/x-article.ts article.md --cover ./cover.jpg **Note**: Script opens browser with article filled in. User reviews and publishes manually. +**Post-Composition Check**: The script automatically verifies after all images are inserted: +- Remaining `XIMGPH_` placeholders in editor content +- Expected vs actual image count + +If the check fails (warnings in output), alert the user with the specific issues before they publish. + --- ## Troubleshooting diff --git a/skills/baoyu-post-to-x/references/articles.md b/skills/baoyu-post-to-x/references/articles.md index bca7d03..1626579 100644 --- a/skills/baoyu-post-to-x/references/articles.md +++ b/skills/baoyu-post-to-x/references/articles.md @@ -132,8 +132,12 @@ JSON output: - Select the placeholder - Copy image to clipboard - Paste to replace selection -9. **Review**: Browser stays open for 60s preview -10. **Publish**: Only with `--submit` flag +9. **Post-Composition Check** (automatic): + - Scan editor for remaining `XIMGPH_` placeholders + - Compare expected vs actual image count + - Warn if issues found +10. **Review**: Browser stays open for 60s preview +11. **Publish**: Only with `--submit` flag ## Example Session diff --git a/skills/baoyu-post-to-x/scripts/x-article.ts b/skills/baoyu-post-to-x/scripts/x-article.ts index d2c7215..cb78c2a 100644 --- a/skills/baoyu-post-to-x/scripts/x-article.ts +++ b/skills/baoyu-post-to-x/scripts/x-article.ts @@ -130,7 +130,7 @@ export async function publishArticle(options: ArticleOptions): Promise { try { const wsUrl = await waitForChromeDebugPort(port, 30_000, { includeLastError: true }); - cdp = await CdpConnection.connect(wsUrl, 30_000, { defaultTimeoutMs: 30_000 }); + cdp = await CdpConnection.connect(wsUrl, 30_000, { defaultTimeoutMs: 60_000 }); // Get page target const targets = await cdp.send<{ targetInfos: Array<{ targetId: string; url: string; type: string }> }>('Target.getTargets'); @@ -148,7 +148,7 @@ export async function publishArticle(options: ArticleOptions): Promise { await cdp.send('DOM.enable', {}, { sessionId }); console.log('[x-article] Waiting for articles page...'); - await sleep(3000); + await sleep(1000); // Wait for and click "create" button const waitForElement = async (selector: string, timeoutMs = 60_000): Promise => { @@ -644,6 +644,8 @@ export async function publishArticle(options: ArticleOptions): Promise { if (imgUploadOk) { console.log(`[x-article] Image upload verified (${expectedImgCount} image block(s))`); + // Wait for DraftEditor DOM to stabilize after image insertion + await sleep(3000); } else { console.warn(`[x-article] Image upload not detected after 15s`); if (i === 0) { @@ -653,6 +655,42 @@ export async function publishArticle(options: ArticleOptions): Promise { } console.log('[x-article] All images processed.'); + + // Final verification: check placeholder residue and image count + console.log('[x-article] Running post-composition verification...'); + const finalEditorContent = await cdp.send<{ result: { value: string } }>('Runtime.evaluate', { + expression: `document.querySelector('.DraftEditor-editorContainer [data-contents="true"]')?.innerText || ''`, + returnByValue: true, + }, { sessionId }); + + const remainingPlaceholders: string[] = []; + for (const img of parsed.contentImages) { + const regex = new RegExp(img.placeholder + '(?!\\d)'); + if (regex.test(finalEditorContent.result.value)) { + remainingPlaceholders.push(img.placeholder); + } + } + + const finalImgCount = await cdp.send<{ result: { value: number } }>('Runtime.evaluate', { + expression: `document.querySelectorAll('section[data-block="true"][contenteditable="false"] img[src^="blob:"]').length`, + returnByValue: true, + }, { sessionId }); + + const expectedCount = parsed.contentImages.length; + const actualCount = finalImgCount.result.value; + + if (remainingPlaceholders.length > 0 || actualCount < expectedCount) { + console.warn('[x-article] ⚠ POST-COMPOSITION CHECK FAILED:'); + if (remainingPlaceholders.length > 0) { + console.warn(`[x-article] Remaining placeholders: ${remainingPlaceholders.join(', ')}`); + } + if (actualCount < expectedCount) { + console.warn(`[x-article] Image count: expected ${expectedCount}, found ${actualCount}`); + } + console.warn('[x-article] Please check the article before publishing.'); + } else { + console.log(`[x-article] ✓ Verification passed: ${actualCount} image(s), no remaining placeholders.`); + } } // Before preview: blur editor to trigger save