Map the statuses Audience actually emits; pin the vocabulary - #69
Merged
Conversation
…bulary
The Announce lane was wired to a vocabulary Audience has never emitted. Three of
the six mapped strings - approval-pending, published, rejected - do not exist in
its schema, and five of its nine real statuses had no case at all and fell
through to default as "nothing".
The consequence that matters: awaiting_approval, the approve-before-post human
gate, classified as nothing and never blocked. A gate that looks present and
silently no-ops - the same shape as the agentic-os Stop hook.
The origin is the spec, not the adapter. Section 6.2 of the project-dashboard
design took its "native vocabulary" from the Audience DIGEST, a prose summary,
rather than from packages/contracts/src/generated/enums.ts. The adapter
implemented that faithfully and was wrong because it was faithful. Both are
corrected here.
Four places carried the error, and the fourth is the worst:
pipelineFor the per-post switch, now an exhaustive
Record<AudiencePostStatus, ...> so tsc fails if Audience
adds a status and this table does not grow with it
adapters.test.ts asserted on all three fictional strings, so it was green
against an invention
the rollup counted p.status === 'approval-pending' INDEPENDENTLY of
pipelineFor, so it would have kept reporting 0 awaiting
even after the mapping was fixed. It now derives from the
same classification. The rollup is the high-volume case an
operator actually reads, where a missed gate hides the most
AudiencePost declared platforms, which GET /posts does not return, so
every Blocked detail rendered a dangling separator
Two product judgments the spec never contemplated are recorded, not buried:
ready_for_review and partially_published both gate, on the principle that the
board surfaces what needs a person. Change them in CLASSIFY if the intent
differs.
Not a defect, checked while here: unwrap_posts already handles the { items: ... }
envelope Audience actually returns; only its doc comment is stale.
Driven red before keeping:
gate reverted to the old string -> 3 tests red (per-post, gate, rollup)
rollup counts a literal again -> 1 test red
Suite 162 -> 166, typecheck 358 files 0 errors.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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 Announce lane was wired to a vocabulary Audience has never emitted.
command-centerswitched ondraft✅draftgenerating✅generatingapproval-pending❌awaiting_approvalpublished❌fully_published,partially_publishedrejected❌failed✅failedready_for_review,approved,publishinghad no caseawaiting_approval— the approve-before-post gate — classified as nothing and never blocked. A gate that looks present and silently no-ops: the same shape as the agentic-os Stop hook.The origin is the spec, not the adapter
§6.2 took its "native vocabulary" from the Audience digest — a prose summary — rather than from
packages/contracts/src/generated/enums.ts. The adapter implemented that faithfully and was wrong because it was faithful. Both are corrected.Four places carried it, and the fourth is the worst
pipelineFor→ now an exhaustiveRecord<AudiencePostStatus, …>, sotscfails if Audience adds a status and this table doesn't grow with it.adapters.test.ts→ asserted on all three fictional strings. Green against an invention.p.status === 'approval-pending'independently ofpipelineFor, so it would have kept reporting0 awaitingeven after the mapping was fixed. It now derives from the same classification. The rollup is the high-volume case an operator actually reads — where a missed gate hides the most work.AudiencePost.platforms→GET /postsdoesn't return it, so every Blocked detail rendered a dangling separator.Two judgments, recorded not buried
ready_for_reviewandpartially_publishedboth gate — the spec never contemplated either. Gated on the principle that the board surfaces what needs a person;partially_publishedisn'tfailedbecause part of it is live. Change them inCLASSIFYif you disagree.Not a defect
unwrap_postsalready handles the{ items: [...] }envelope Audience returns — only its doc comment is stale.Driven red before keeping
Suite 162 → 166 · typecheck 358 files, 0 errors.
🤖 Generated with Claude Code