Show candidate body in the Atlas review artifact#137
Merged
Conversation
The approval artifact rendered each candidate as a checkbox showing only the canonical-key marker, title, and flag badge — never c.content, the distilled why/how prose. A reviewer could not read the text they were approving or rejecting. Render c.content as a collapsible toggle child (labeled "Content (why/how)") of both the approvable to_do and the unverified note, placed before the provenance callout and evidence bullets. The body flows through the existing richText() helper (2000-char run split, 100-run cap, surrogate safety) and is split across multiple paragraph children when it exceeds one paragraph's run budget, so nothing is dropped. Guarded on non-empty trimmed content so an empty candidate gets no dead toggle.
…dget blockCost counted a block plus only its DIRECT children, assuming children are one level deep. The new content toggle adds a second nesting level (to_do → toggle → paragraphs), whose grandchildren went uncounted — a large run could silently exceed Notion's ~1000-block-per-request cap and 400 the whole append. Make blockCost recurse over all descendants so the batcher budgets the true total block count at every depth.
The content-toggle chunker sliced c.content at a fixed 200000 code units, then fed each slice to richText. Two defects for astral-heavy bodies: - Surrogate split: a slice boundary could cut a surrogate PAIR in half; richText's toWellFormedUtf16 then sanitized each lone half to U+FFFD, corrupting the astral char across the chunk seam. - Tail-drop: 200000 = RICH_TEXT_RUN_MAX x RICH_TEXT_MAX_RUNS assumed richText renders a full 200k chunk losslessly, but its per-run surrogate backoff shortens runs, pushing the tail past the char cap and tripping the truncation branch — silently dropping ~2000 chars per chunk. Iterate c.content by code point (never splitting a pair) and cap each chunk at the guaranteed-lossless floor (RICH_TEXT_RUN_MAX-1) x RICH_TEXT_MAX_RUNS, which absorbs a worst-case one-unit backoff on every run. Added red-green tests: an astral char straddling the chunk boundary stays intact (no U+FFFD), and an astral-heavy body >1 chunk round-trips with every code point preserved. Also restore the console.warn spy after each test in the rule-bullet delimiter-tolerance suite (restoreMocks is not globally on, so the spy was leaking into later suites).
Update the stale batchBlocks comment (a candidate now nests a content toggle whose paragraph children add a second level, so a block's recursive cost is no longer a small constant), and throw a clear error when one block's blockCost alone exceeds NOTION_MAX_TOTAL_BLOCKS_PER_REQUEST — such a block can never fit any batch and would 400 the append, so surface it here rather than at the API.
…for exclusions The S16 review artifact renders each candidate's distilled body inside a "Content (why/how)" toggle whose paragraph children hold the prose, but the sync-side extractor (fetchChildProse) read only the to_do's direct children. For the toggle that captured its static label, not the body — so the on-approval credential/exclusion re-check (§11) judged title + label, never the body a reviewer actually sees. A clean-titled candidate whose body leaked a credential was approved, and the constant "Content (why/how)" leaked into the payload. fetchChildProse now descends one level into a toggle child, folding its paragraph grandchildren (with the same canonical-key marker filter) and skipping the toggle's own label. Non-toggle children stay depth-1 as before. Adds a real build->fetch->reconstruct->applyExclusions round-trip test proving a body-only ghp_ token is caught and the toggle label never enters the payload.
The test titled "budgets by TOTAL block count (top-level + nested)" summed only self + DIRECT children (childCountOf), so it never verified grandchild counting — the deep/toggle-paragraph budget is covered by the sibling "budgets by DEEP block count" test. Retitle and reword to "top-level + DIRECT children" so the title is true and points at the sibling for the deep case.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Atlas harvest Notion review artifact rendered only each candidate's title + tags + provenance — never the distilled body (
content). So a human reviewer couldn't see the text they were approving or rejecting, which defeats the purpose of a human-ratification gate. (Found while inspecting the eval artifact and asking how one is supposed to judge content for approval.)What this does
fetchChildProse), so the body is both human-visible and machine-re-checked for credentials/exclusions on approval — closing the code's own §11 contract (previously the body was never on the page, so it was never re-checked).Verification
to_do → toggle → paragraphnesting is accepted (200) and the toggle + body render, astral chars intact. (Unit tests check block structure; this proves Notion accepts the shape.)deepBlockCountbudget over nested children; and a credential-in-body → excluded round-trip proving the descent feeds the body to the exclusion engine.Review
Tier-2 CR, 3 rounds — the review caught and fixed three real bugs this feature introduced or exposed: (1) surrogate-pair corruption at the chunk boundary, (2) silent tail-drop on large astral bodies, (3) the sync round-trip not descending into the toggle (body shown but not re-checked). Converged with zero new in-subject findings.
Follow-ups (non-blocking, in the CR ledger)
exclude.ts) misses modern OpenAI keys —sk-proj-/sk-svcacct-/sk-admin-(the/\bsk-[A-Za-z0-9]{20,}\b/pattern stops at the hyphen). Worth its own quick PR. Also lacks shapes forxox*/github_pat_/AIza/gho_/bearer.clampTitlecode-unit comment, arichTextparam shadow,generate.tspage.idguard,buildExclusionRuleBlocksrawrt()vsrichText().