fix(subagents): route deliverables through the artifact channel - #176
Merged
Conversation
Sub-agent responses were commonly truncated: the parent tool description did not document the two-channel result model, the child-side artifact note was too weak to act on, and cut headlines were invisible. The artifact protocol existed (M1-M3) but nothing steered the LLMs into it. - Description(): two-channel result-delivery contract (headline ~2000 chars + artifacts, artifact_read loop) + guidance schema nudge (A/A2) - childArtifactNote(): loss-fact framing, small-task exemption, flat files only with stated consequence, headline shape (B); identity closing line aligned (B2) - visible truncation marker: summary_truncated/summary_runes (omitempty, wire-compatible) + conditional artifact_read hint gated on artifactReadEnabled (C) - artifact ids: first-wins with probe-increment <id>.t<N> aliases that never evict live entries; task provenance on artifact lines and artifact_read output (D1) - 128 KiB per-call inline budget (largest-first) + per-run registry floor so a collating call's artifacts stay resolvable (F) - gitignore .odek-artifacts/ staging (E) RED-first: subagent_delivery_test.go (14 tests) + flipped dup-id pin. go vet clean; scoped -race and full cmd/odek package green. Docs: docs/SUBAGENTS.md envelope + artifact sections synced.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
odek | 35de194 | Commit Preview URL Branch Preview URL |
Sep 02 2026, 08:27 PM |
The ui-js suite failed 2/3 CI runs today (and once on main): four tests slept fixed real-time windows against a 1s setInterval sweep and a 1.5s friction-gate setTimeout. Under runner load the timers starve past the window and the assertions run too early. Replace all four sleeps with a waitFor(cond) poll (20ms cadence, 15s deadline). The wrong-word friction test now first proves the gate passed via the correct word, so its negative assertion is never vacuous. Test-only; no product code touched.
…rig hygiene, stem collisions Judge pass 1 on the branch diff validated 4 findings: - P1: the collate loop rendered before registering, so an aliased duplicate advertised the plain id and artifact_read(plain) resolved to the WRONG task's bytes. Register first, render second; notes still append after the artifacts block. - P2: byOrig entries now die with their registry entry on eviction (stale alias ids previously rendered as dead ends; long-lived serve leaked one map entry per registration). - P3: same-task stem collisions (report.md + report.txt both report id 'report') now get occurrence-indexed byOrig slots; the render consumes them in envelope order, matching registration order. - P4: the provenance test now uses production order and asserts the effective id positively (- dup.t2 () and the plain id negatively (- dup () — previously vacuous. Adds TestRegisterArtifact_SameTaskStemCollision and TestEvictionCleansEffectiveIDMap.
…lision Judge pass 2 caught a hazard in the occurrence fix: byOrig/occ were keyed by (origID, taskIdx), but every delegate_tasks call has a task 0 — a later call's duplicate id would register at occ>=1 while its render looked up occ=0 and resolved to an EARLIER call's plain id (silent wrong content, same class as the P1 finding). The registry key is now (origID, taskID, occ) with taskID the per-call unique id minted at spawn; the collate loop threads it into registration and rendering. Adds TestEffectiveIDs_NoCrossCallCollision pinning both calls resolving to their own ids.
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.
Closes the sub-agent response truncation workstream (SUBAGENT_ARTIFACT_DELIVERY_PLAN.md v2, adversarially reviewed by 3 sequential sub-agents).
Root cause
The artifact protocol (M1-M3) worked, but nothing steered the LLMs into it: the parent tool description never mentioned the 2048-rune headline cap, the artifact channel, or artifact_read; the child-side note was a weak buried sentence; cut headlines were invisible (bare ellipsis). So children answered in headline text, parents synthesized from the cut believing it was everything.
Changes (plan proposals A+A2, B+B2, C, D1, E, F)
Verification