- news002 image/structure audit no longer throws: prune empty sections and
publish a best-effort page with a warning
- WeChat push strips images that failed to upload instead of refusing the draft
- forceGenerateOnce is cleared before running, so a failed run cannot loop;
the archived page is restored when generation fails
- degraded-page regeneration runs at most once per day
- content safety rules cover vulgar sexual terms and gossip/adult sites
Co-authored-by: Cursor <cursoragent@cursor.com>
Rules-first safety gate covering adult content, minor protection, legal
compliance (stock tips, crypto promotion, gambling, drugs, source
provenance for political news) and ethics (tragedy tone, discrimination,
gossip). Filters without blocking publication:
- SearXNG prefetch uses safesearch=2 and drops block-level results before
they can be supplemented into the page
- worker sanitizes the page after dedupe and after the image gate, with a
single batched model review; review-level items are removed fail-safe
when the reviewer is unavailable
- sections the gate filtered are exempt from fill/structure audits so
filtering never turns into a failed generation
- push/preview recheck removes block-level items and masks title/digest
- AI-assisted disclosure in page footer and WeChat draft, plus aigc and
content-safety meta markers
Co-authored-by: Cursor <cursoragent@cursor.com>
The proxy now forwards any api.weixin.qq.com/cgi-bin/* path (drafts, material
upload, etc.), binds to the 10.10.0.1 tunnel address, and uses a 120s timeout.
wechat-egress-fetch.mjs rewrites WeChat API URLs to the egress base when
MEMIND_WECHAT_EGRESS_BASE_URL is set.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
Update template version exports and draft worker tests so fast release
guards pass with the news-engine integration branch.
Co-authored-by: Cursor <cursoragent@cursor.com>
Lock scheduled morning news to news002 with section-fill gates, headline lead-card normalization, SearXNG top-up to max, and push that keeps imageless cards as text while requiring uploaded images where present.
Co-authored-by: Cursor <cursoragent@cursor.com>
Reject weak or unreachable source images, auto-promote lead cards for
structure audit, and relax push gates while keeping text-only cards.
Co-authored-by: Cursor <cursoragent@cursor.com>
Integrate news002 image localization and compact wechat layout from main
while keeping SearXNG fallback enrichment in the draft worker.
Co-authored-by: Cursor <cursoragent@cursor.com>
Drop story cards without real images from HTML and WeChat drafts instead
of showing ph placeholders, and remove emptied sections for layout balance.
Co-authored-by: Cursor <cursoragent@cursor.com>
After enrichment fails to resolve og:image, swap out imageless story cards
with SearXNG candidates before the image gate rejects the draft.
Co-authored-by: Cursor <cursoragent@cursor.com>
Allow no-image candidates and create missing section shells so news002
image gate can pass after source-page enrichment on thin agent output.
Co-authored-by: Cursor <cursoragent@cursor.com>
When the post-generation audit fails, supplement missing core sections,
headlines, and brief items from prefetched SearXNG groups before re-running
image enrichment and the push gate.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace all references to the previous Portal host 180.159.29.143 with
114.85.107.50 across release scripts, safety gates, runbooks, and docs.
Also add scripts/push-wechat-news-morning-draft-now.mjs for direct draft
push without waiting on the worker poll interval.
Co-authored-by: Cursor <cursoragent@cursor.com>
Trying to push a WeChat draft locally surfaced two problems.
isNewsMorningContentDegraded matched cards with `class="card(?:\s|")`, which
never matches news002's `class="lead-card"`. Headline cards were therefore
invisible to the check, so a healthy news002 page could be flagged as degraded
and regenerated. Count cards through the shared extractor instead, which
handles card, lead-card and highlight-box alike.
Add scripts/dryrun-news-morning-draft.mjs to run a page through the dedup gate,
degradation check, inline conversion and footer layout without calling the
WeChat API, since local IPs are not in the official account whitelist
(errcode 40164) and a real push would write into the production draft box.
Co-authored-by: Cursor <cursoragent@cursor.com>
Freeze the 2026-09-18 layout as news001 and add news002 alongside it.
Analysis of the 0918 production page found 49 news cards covering only ~20
distinct events (4x "王毅同鲁比奥通电话", 5x "东博会南宁开幕"), citing just 7
URLs that are all section landing pages rather than article permalinks, with
zero images. The root cause is structural: 23 fixed sections with fixed card
quotas force padding when the day yields fewer events.
news002 changes the contract so events decide sections, not the reverse:
core sections always render, flex sections are dropped entirely when they have
no unused event, total story cards are capped at 28, and every card carries a
data-event-key fingerprint.
Add wechat-news-morning-dedup.mjs as a post-generation gate, since the prompt
level "no duplicates" rule is unverifiable. It dedupes by event key, then by
article permalink (deliberately ignoring section landing pages, which would
otherwise delete most of the page), then by CJK bigram title similarity, since
the existing whitespace-tokenised matcher does not work on Chinese titles.
Carry per-item images through normalizeSearchResult into the prefetch brief so
cards can render real article thumbnails with a placeholder fallback.
Teach the WeChat inline converter both DOM variants (lead-card, masthead meta,
lede). Per-card images in the WeChat draft body remain a known gap.
Template selection is config/env driven and still defaults to news001.
Co-authored-by: Cursor <cursoragent@cursor.com>
Record the merged chat-intent work as closed, and mark the leftover local news-morning branch as not reusable.
Co-authored-by: Cursor <cursoragent@cursor.com>
Close the chat-session dead zone without flipping production flags: record 0.72 fallbacks, stop C-2 from treating「先聊聊」as execute, and promote「不对你去执行」after a completed direct turn on both h5direct and date sessions.
Co-authored-by: Cursor <cursoragent@cursor.com>
Finalize the approved 2026-09-18 refined briefing as the production layout and SEO reference for future auto-generation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Default open WeChat draft comments, add SEO/visual template rules with h2 sections and mindspace-geo, and compress inline styles to pack more cards within the 20k HTML budget.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the trending/hot search lane and section, forbid stats summary in page spec, and stop injecting card/section counts into WeChat inline articles.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expand SearXNG prefetch and template with four English-friendly sections so daily news can surface global headlines without copying stale archives.
Co-authored-by: Cursor <cursoragent@cursor.com>
Treat deferred/skipped customer-service sends as failures so reminder worker
does not mark reminders sent, and add a 103 read-only health check script.
Co-authored-by: Cursor <cursoragent@cursor.com>