feat(news): add single news-item page generation and early page-ready wait

Scheduled tasks can finish once the expected HTML is on disk and stable,
instead of waiting for Goose Finish. Adds news-item templates and scripts
for generating a single-event page and committing it as a WeChat draft.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-23 10:07:32 +08:00
parent c36558e0f3
commit 028bb18dc0
7 changed files with 1029 additions and 4 deletions
+57
View File
@@ -18,6 +18,7 @@ import {
resendScheduledTaskWechatForReadyPage,
resolveScheduledTaskDeliveryPollIntervalMs,
resolveScheduledTaskDeliveryRetryDelaysMs,
waitForExpectedPageFile,
} from './scheduled-task-executor.mjs';
test('buildScheduledTaskExecutionPrompt includes task spec and automation marker', () => {
@@ -296,3 +297,59 @@ test('resendScheduledTaskWechatForReadyPage skips suspended users', async () =>
assert.equal(sent, false);
assert.equal(sendCount, 0);
});
test('waitForExpectedPageFile resolves once html file size stabilizes', async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-page-'));
const publishDir = path.join(root, 'MindSpace', 'user-1');
const relativePath = 'public/news-item-demo.html';
const filePath = path.join(publishDir, relativePath);
await fs.mkdir(path.dirname(filePath), { recursive: true });
let polls = 0;
const pending = waitForExpectedPageFile({
publishDir,
relativePath,
pollIntervalMs: 20,
stablePolls: 2,
minBytes: 10,
sleepFn: (delayMs) => new Promise((resolve) => {
polls += 1;
setTimeout(async () => {
if (polls === 2) {
await fs.writeFile(filePath, '<html>draft</html>', 'utf8');
}
resolve(delayMs);
}, 0);
}),
});
assert.equal(await pending, relativePath);
});
test('waitForExpectedPageFile waits until isPageReady passes', async () => {
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduled-page-ready-'));
const publishDir = path.join(root, 'MindSpace', 'user-2');
const relativePath = 'public/news-item-ready.html';
const filePath = path.join(publishDir, relativePath);
await fs.mkdir(path.dirname(filePath), { recursive: true });
let polls = 0;
const pending = waitForExpectedPageFile({
publishDir,
relativePath,
pollIntervalMs: 20,
stablePolls: 2,
minBytes: 10,
isPageReady: (html) => html.includes('DONE'),
sleepFn: (delayMs) => new Promise((resolve) => {
polls += 1;
setTimeout(async () => {
const body = polls >= 4 ? '<html>DONE</html>' : '<html>draft</html>';
await fs.writeFile(filePath, body, 'utf8');
resolve(delayMs);
}, 0);
}),
});
assert.equal(await pending, relativePath);
});