Skip to content

fix(brief): forbid weak temporal stitching in digest lead#3769

Merged
koala73 merged 2 commits into
mainfrom
fix/synthesis-no-weak-stitching
May 18, 2026
Merged

fix(brief): forbid weak temporal stitching in digest lead#3769
koala73 merged 2 commits into
mainfrom
fix/synthesis-no-weak-stitching

Conversation

@koala73

@koala73 koala73 commented May 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • May 17 brief shipped a lead that stapled the WHO Ebola declaration and the Israel/Hezbollah escalation into one sentence with "This declaration comes as…" — two unrelated top stories joined by an editorial connective. This was triage item Add pipeline flow disruption signals #5 (lead conflates stories) from the May 17 brief sweep.
  • DIGEST_PROSE_SYSTEM_BASE now explicitly forbids weak temporal connectives ("This comes as", "Meanwhile", "At the same time", "In other news", "Elsewhere", "Across the world", "On another front", "In a separate development") and tells the model to lead with one primary story when two top stories aren't substantively linked (shared actor / causal connection / direct policy consequence / same geographic theatre).
  • Cache prefix bumped v7 → v8 at the two sites in scripts/lib/brief-llm.mjs so stale v7 rows generated against the stitching-tolerant prompt do not serve for the 4h TTL after deploy.

Why prompt-only (not a synthesis-step rewrite)

The conflation was a stylistic failure of the existing instructions, not a missing pipeline stage. Adding a focused "no-stitching" instruction + cache bump is the cheapest fix that addresses the regression without growing prompt surface area or adding a second LLM round-trip. Pattern reference: PR #3751 followed the same prompt-change → cache-prefix-bump → assertion-update shape when category persistence landed (v6 → v7).

Files changed

  • scripts/lib/brief-llm.mjsDIGEST_PROSE_SYSTEM_BASE updated lead instruction + new BANNED stitching section; cache key v7 → v8 (line 962) + matching comment (line 23) + v8 rationale in the version-history block.
  • tests/brief-llm.test.mjs — new forbids weak stitching connectives in the lead (anti-conflation, v8) test asserting the prompt contains the instruction text, the BANNED section, the enumerated phrases, and the substantive-link allowlist; cache-prefix assertion bumped v7 → v8 with an added negative assertion that no v7 rows are written.

Test plan

  • node --test tests/brief-llm.test.mjs — 102/102 pass, including the new anti-stitching assertion and the v8 prefix-bump assertion.
  • Broader tests/brief-*.test.mjs sweep — 664/670 pass; the 6 failures are pre-existing api/brief/*.ts ESM module-resolution issues unrelated to this change.
  • After deploy: spot-check the next 2–3 brief leads for the anchor failure mode (two unrelated top stories joined by a temporal connective).

May 17 brief shipped a lead that stapled the WHO Ebola declaration
and the Israel/Hezbollah escalation into a single sentence with
"This declaration comes as…" — two unrelated top stories joined by
an editorial connective, with no shared actor, causal link, or
geographic theatre.

DIGEST_PROSE_SYSTEM_BASE now:
- Tells the model to lead with ONE primary story and only reference
  a second when there is a substantive link (shared actor, causal
  connection, direct policy consequence, same geographic theatre).
- Carries a dedicated BANNED stitching-phrases section enumerating
  the common offenders ("this comes as", "meanwhile", "in other
  news", "elsewhere", etc.).

Cache prefix bumped v7 → v8 (brief-llm.mjs:23 comment, :962 key)
to invalidate any v7 rows that were generated against the stitching-
tolerant prompt — without the bump, stale stitched leads would
serve for the full 4h TTL after deploy.

Tests:
- New `forbids weak stitching connectives in the lead` test asserts
  the prompt contains the anti-stitching instruction, the BANNED
  section, the enumerated phrases, and the substantive-link
  allowlist.
- Bumped cache-prefix assertion v7 → v8 with an added negative
  assertion that no v7 rows are written.

Pattern reference: PR #3751 followed the same prompt-change → cache-
prefix-bump → assertion-update pattern when category persistence
landed (v6 → v7).
@vercel

vercel Bot commented May 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
worldmonitor Ignored Ignored Preview May 18, 2026 3:43am

Request Review

@greptile-apps

greptile-apps Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses a prompt-quality regression where the May 17 brief joined two unrelated top stories (WHO Ebola declaration and Israel/Hezbollah escalation) with the stitching phrase "This declaration comes as…". The fix adds explicit anti-stitching guidance to DIGEST_PROSE_SYSTEM_BASE — both inline in the lead field spec and as a dedicated BANNED stitching phrases block — and bumps the digest prose cache key from v7 to v8 so stale stitched leads don't serve through the 4 h TTL.

  • DIGEST_PROSE_SYSTEM_BASE now forbids nine specific weak temporal connectives and instructs the model to lead with a single primary story when two top stories lack a substantive link (shared actor, causal connection, direct policy consequence, or same geographic theatre).
  • The cache key is bumped v7 → v8 in both the key-construction expression and the header comment; generateDigestProsePublic is unaffected because it delegates to generateDigestProse.
  • A new regression test verifies the prompt text; the v7 → v8 prefix assertion is also updated with a new negative assertion confirming no v7 rows are written.

Confidence Score: 4/5

Safe to merge — the only change to production code is the prompt text and cache key bump, both of which are self-consistent and low-risk.

The prompt change and cache invalidation are tightly scoped and correct. The one gap is that the new regression test's banned-phrase loop only covers 4 of the 9 enumerated connectives, meaning a future edit that drops one of the untested phrases would pass CI unnoticed. The production change itself is solid; the test coverage is incomplete.

tests/brief-llm.test.mjs — the banned-phrase assertion loop should be extended to cover all nine connectives listed in the BANNED section.

Important Files Changed

Filename Overview
scripts/lib/brief-llm.mjs Cache key bumped v7→v8 in both the header comment and the key construction; DIGEST_PROSE_SYSTEM_BASE extended with inline anti-stitching guidance in the lead field and a dedicated BANNED-stitching block — changes are consistent and well-scoped.
tests/brief-llm.test.mjs New regression test asserts the anti-stitching instruction and BANNED section exist and enumerate key phrases; cache-prefix assertions updated to v8 with a new negative v7 assertion. The banned-phrase loop covers only 4 of 9 enumerated phrases, leaving partial regression coverage.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[generateDigestProse called] --> B{Cache hit?\nbrief:llm:digest:v8:...}
    B -- hit --> C[Re-run shape+grounding validator]
    C -- valid --> D[Return cached result]
    C -- invalid --> E[Call LLM with DIGEST_PROSE_SYSTEM_BASE]
    B -- miss --> E
    E --> F{LLM output\nvalid & grounded?}
    F -- no --> G[Return null\nno cache write]
    F -- yes --> H{Lead contains\nbanned stitching phrase?}
    H -- yes --> I[Model non-compliance\nspot-check after deploy]
    H -- no --> J[Write v8 cache row\n4h TTL]
    J --> K[Return parsed prose]
Loading

Reviews (1): Last reviewed commit: "fix(brief): forbid weak temporal stitchi..." | Re-trigger Greptile

Comment thread tests/brief-llm.test.mjs
Comment on lines +337 to +347
for (const phrase of [
'this comes as',
'meanwhile',
'in other news',
'elsewhere',
]) {
assert.ok(
system.toLowerCase().includes(`"${phrase}"`),
`banned-stitching section must list "${phrase}"`,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Incomplete banned-phrase assertion loop

The test loop only exercises 4 of the 9 phrases enumerated in the BANNED stitching phrases section — "at the same time", "across the world", "on another front", and "in a separate development" are all absent. If any of those phrases were accidentally removed from DIGEST_PROSE_SYSTEM_BASE in a future edit, the test would still pass without surfacing the regression. The PR description explicitly calls out all nine as intentionally added, so they deserve corresponding assertions.

PR #3769 review noted the regression test only checked 4 of the 10
banned phrases and scanned the entire system prompt — so a phrase
removed from the dedicated BANNED section could still pass on a
duplicate mention in the lead-field instructions.

Fix:
- Extract the BANNED stitching phrases section as a bounded substring
  (from the section header up to the next `Threads:` instruction
  bullet).
- Assert all 10 banned phrases appear inside that substring, not
  the broader system prompt. A regression that removes a phrase
  from the section now fires even if the lead instruction still
  mentions it.

102/102 brief-llm tests pass.
@koala73
koala73 merged commit 3f1244c into main May 18, 2026
11 checks passed
@koala73
koala73 deleted the fix/synthesis-no-weak-stitching branch June 25, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant