feat(jobs): a job may emit content, as a sibling of progress #739
No reviewers
Labels
No labels
move-to-repo
coilyco-bridge-deploy
move-to-repo
coilyco-flight-deck-agent-compose
move-to-repo
coilyco-gaming-eco-app
move-to-repo
coilysiren-inbox
move-to-repo
unknown
🔒⚠️📦⚠️🔒 SANDBOXED 🔒⚠️📦⚠️🔒
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/sirens-echo!739
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/a-job-may-emit-content"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The seam issue 356 asks for, and nothing else. Kai said "make it so" on issue 236 and the design there is settled; this is the piece the rest sits on.
What lands
JobContentReporteris a sibling ofJobProgressReporter, not a change to it. Progress keeps its single editable line, its 20-second rate limit, and the notice alphabet. That was the acceptance row easiest to break by widening the existing interface, so the existing interface is untouched.contentForreturns an emitter that returns an error rather than dropping. A dropped status line costs nothing; a dropped paragraph is a hole in an answer.EmitJobContenton the Discord sink always posts, never edits. Editing is what makes progress one line, and it is what would overwrite part one with part two.maxJobContentMessages = 10, which is the ceiling Kai decided on 236. Per job, and it refuses withErrJobContentExhausted.Fail closed, deliberately
ValidateContentis nil-refuses, not nil-allows. An unwired validator that silently becomes an unchecked path to a member is the exact shape issue 621 records, and this is a new path to a member.validateJobContentrunsParseReply,ValidateNoToolCallMarkup, the identifier guard,ValidateIdentityClaimandValidateResponseStyle, inrunReplyChecksorder. Grounding and self-attribution are absent by construction, not oversight: both read a turn's supplied context and executed tools, and a job has neither. That is stated in the code rather than left to be discovered.Acceptance
TestEveryContentMessageArrivesInOrderTestContentIsRefusedForTheSameReasonAReplyIsTestContentAndProgressDoNotShareABoundTestAJobThatEmitsNothingTouchesNothingTestTheFloodBoundRefusesRatherThanDroppingward exec gatePASS on all six steps.Two mutations, both in runs where the package compiles:
TestContentWithoutAValidatorIsRefusedTestTheFloodBoundRefusesRatherThanDroppingNot in this change, and named so nobody assumes it
The ceiling's ten-minute half, threading, and file upload from 236. Each is a small change on top of this seam and none was buildable before it.
Idempotency. 621 records that
RecordEffectandEffectAppliedhave no production caller, sojob.Effectsis empty and resume redoes everything. A job that emits ten ordered messages and then resumes emits some of them twice. This seam does not pretend otherwise, and 621 is a precondition for the ceiling rather than unrelated cleanup.closes #356