Skip to content
Project Research
Transcendent95 / 100
Evidence34/35Judgment24/25Structure18/20Usefulness19/20
Three Agents Returned Three Reports. How Do You Keep Acceptance from Charging the Wrong Task?
Digital Employee · Project Research

Three Agents Returned Three Reports. How Do You Keep Acceptance from Charging the Wrong Task?

Display may assist with parenting, but acceptance must verify task identity, execution attempt, supersession, and independent QA.

MANUAL-20260820-REPORT-ATTRIBUTIONCommunity Readability PASS · 2026-08-22中文 →

Three Agents Returned Three Reports. How Do You Keep Acceptance from Charging the Wrong Task?

A development agent, a QA agent, and an operations agent return reports at almost the same time. All three say “success,” so the system produces a reassuring summary: implementation complete, tests passed, deployment healthy.

But QA tested the pre-rework version. The operations report belongs to a different root task in the same thread. The developer report’s filename contradicts the task identifier in its metadata. No file is missing; three real artifacts have been assembled into a delivery that never existed.

The remedy is not another language model reading the prose. The runtime must bind each receipt to a unique task and execution attempt, keep display placement separate from acceptance ownership, and stop when ownership remains ambiguous. This article gives you an identity gate, a report-version state model, and a final-summary checklist that can be applied to your own Agent runtime.

Start with three plain questions:

Attribution questionWhat it meansWhat can establish it
Who did the work?which project, task, and execution produced this reporttask identity, parent, project root, and a runtime-recorded attempt
What proves the claim?whether “success” is backed by machine evidencethe actual command, exit code, raw test output, and captured code version
Which contract accepts it?which task owns the evidence and who may accept itunique task binding, report supersession, independent QA, and final acceptance

These questions prevent three different failures: charging A’s report to B, treating model-written prose as a test log, and allowing the executor to accept its own work. The current CodeFlowMu implementation provides hard checks on selected consequential paths. Runtime injection of every authoritative field remains a target contract.

text
task dispatch
  → bind task and execution context
  → agent invokes tools
  → capture command, exit code, tests, and code version
  → assemble the report envelope
  → verify task, attempt, and report version
  → independent QA
  → authorized acceptance or rejection

Not every arrow is uniformly implemented across every current tool and report path. The article distinguishes existing checks from the target design.

A report can exist without belonging to this task

Multi-agent systems often use four convenient association rules:

  1. attach reports to the same chat thread;
  2. attach them to the most recent task;
  3. scan the body for a task identifier;
  4. match the sender role—for example, attach a DEV report to the nearest development task.

These rules can organize a screen, but none is sufficient for acceptance. A thread may contain multiple root tasks. A rework report may discuss the rejected predecessor. A body can mention both a parent and a child. An old report may be discovered only after a watcher restarts.

Choosing the “most likely” task produces a plausible tree, not deterministic evidence ownership.

A report needs several identities

CodeFlowMu currently uses four kinds of attribution information:

IdentityPurposeTypical failure
report file identityidentifies this receipt occurrencefilename sequence points to another task
task_iddeclares the direct work ownerstill points to the pre-rework task
parent_task_idplaces the report in the task treeattaches to the root instead of the worker child
referencespreserves related tasks and historical linkstreats “mentioned” as “directly owned by”

Direct ownership and historical relevance are different relationships.

If a developer reworks TASK-042-REWORK-01, the report may retain TASK-042 in references to explain why rework occurred. Its direct task_id should identify the current rework task. A resolver that scans references without respecting the direct owner can let the predecessor steal the new report.

Consequential receipts need a hard gate

For one consequential DEV receipt path, CodeFlowMu implements a strict three-way check in reportAttribution.ts:

text
TASK inferred from the REPORT filename
        ==
frontmatter.task_id
        ==
references[0]

Example:

yaml
filename: REPORT-20260820-042-DEV-to-PM.md
task_id: TASK-20260820-042
references:
  - TASK-20260820-042

If the filename identifies 043 while the explicit task and first reference identify 042, attribution fails. The gate does not take a two-out-of-three vote. Missing explicit identity also fails.

This boundary needs precision. It is an application-level CodeFlowMu rule for a key DEV acceptance path, not a universal FCoP naming rule for every report and every role. FCoP defines report envelopes and references; a host runtime may add stricter contracts for consequential workflows.

The check rejects disagreement. It cannot detect three fields that all repeat the same wrong task identifier—for example, when a model copies an old template and changes nothing. A stronger target design lets the Agent submit only the report body and evidence; the runtime injects the filename, direct owner, parent, execution attempt, and logical event sequence from the active execution context. That is a design recommendation, not a claim that every current CodeFlowMu report path already provides this envelope-injection contract.

Task identity and execution attempt bind development facts and QA verification; supersession selects the effective artifact and isolates the wrong owner

Figure 1. Attribution from task identity and execution attempt through supersession and QA. Source: author synthesis from the pinned CodeFlowMu implementation and W3C/OpenTelemetry identity-propagation boundaries. Runtime injection of all authoritative metadata remains a target contract.

A practical attribution veto list

A useful gate needs explicit rejection conditions. Rejection here means stale, conflicting, or insufficient evidence—not an accusation of malicious fraud:

  • the report’s code version differs from the workspace that was actually tested: quarantine it as stale or conflicting evidence;
  • the report says “tests passed” but lacks the command, exit code, or raw output: do not admit it to a success summary;
  • filename, task field, and first reference agree with each other but disagree with the runtime’s dispatch record: attribution fails;
  • one task has several reports without an attempt number or explicit supersession relation: do not guess which file wins;
  • file modification time is the only ordering signal: it cannot establish causality;
  • an expired execution right may veto a report only on paths that actually implement such a bounded right; do not invent lease semantics elsewhere.

The safe result is often undetermined. That is preferable to assembling three genuine artifacts into a delivery that never happened.

Propagate identity—but do not confuse tracing with acceptance

Distributed systems already use explicit correlation. W3C Trace Context carries a trace-id across services. Its parent-id identifies the caller’s operation for the incoming request; a downstream participant replaces it with the identifier of its current operation when propagating context. The OpenTelemetry Tracing API gives each span at most one parent; parent and child share a TraceId and form a causal tree.

The useful lesson for agent work is that task identity and parentage should travel with execution. They should not be reconstructed from prose after a report arrives.

The analogy then stops. A trace proves correlation, not correctness. An ended span is not a business acceptance. Agent systems should preserve the same separations:

text
correct correlation

truthful report content

independent verification

business acceptance

Display may make a best effort; acceptance may not guess

CodeFlowMu’s reportParenting.ts must handle incomplete historical data. It prefers explicit source_task_id or task_id. When those are absent, it can inspect references, filename sequence, body overlap, and recent open tasks to place a report in a useful ledger view.

That best-effort reconstruction is valuable: legacy reports do not all become orphans.

It is unsafe as an acceptance rule. Two tasks can mention the same module. “Most recent” is a timing coincidence. One role can own several concurrent tasks.

The system therefore needs two outputs:

text
display_parent = best_effort_match(...)
acceptance_owner = deterministic_contract_or_undetermined(...)

The display parent may be labeled as inferred and corrected by a human. The acceptance owner must be unique, or undetermined. Uncertainty is not a failure to be hidden; it is the result that prevents false accounting.

A thread cannot be the parent when it has multiple roots

One conversation can handle defect A and later introduce independent feature B. If reports carry only the shared thread_key, an old final report can be reused by the new root.

The current parenting code partitions a thread with multiple ADMIN roots by lineage and task prefix. A report enters a root bucket only when references or parentage uniquely identify it. Otherwise it remains isolated rather than attaching to the first root in the thread.

This improves ledger reconstruction; it cannot recover identity that was never recorded. Some legacy artifacts require an authorized human decision. A tidy tree is not worth invented certainty.

Two reports for one task need an explicit winner

The same task may produce a failed report, a corrected report, and a retry after restart. Overwriting the old file destroys evidence. Treating every file as equally current lets an obsolete failure or success leak into the final summary.

CodeFlowMu's current ledger can read submission_attempt, revision_of, supersedes, and superseded_by, while the summary gate excludes reports marked invalid or superseded. These are useful building blocks. They do not prove that every report writer automatically increments attempts or that every competing report is uniquely arbitrated.

A complete target contract needs three separate identities:

text
task identity
    └── execution attempt 1
          ├── report v1 ── rejected
          └── report v2 ── effective, supersedes v1
    └── execution attempt 2 ── starts only after an explicit retry decision

Use the logical event sequence, attempt identity, and explicit supersession relationship to decide which receipt is effective. File modification time can help an operator investigate, but it should not be the sole judge.

Correct attribution still does not authorize a final summary

Even after a developer report is attached to the right task, a project manager cannot automatically declare success. PmSummaryGate also checks whether downstream children are settled; whether an effective worker report exists; whether it postdates the task; whether product work has the required QA report; whether QA returned PASS; whether required browser evidence exists; and whether an effective final summary already exists.

An empty diagnostics list is not attribution success. A DEV report is not QA. A PM summary is not final business acceptance.

This is the engineering value of TMPA’s fact/acceptance separation: executors submit facts, verifiers examine facts, and authorized roles decide acceptance. A single status: done field must not merge all three.

Time also needs a boundary. Current compatibility paths can use explicit artifact timestamps and, for older files, filesystem modification time. Git checkout, archive extraction, cross-device copy, or clock skew can all change physical timestamps. Consequential acceptance should therefore prefer logical sequence, execution attempt, and explicit supersession; wall-clock time remains supporting evidence.

What 44 passing tests cover

For this article we pinned CodeFlowMu Open commit ed5634c718b9e238c44bb70851020c9793546fe6 in an isolated worktree and reran the parenting, attribution, and summary-gate suites. The result was 44 of 44 tests passing.

The cases include a filename identifying task 003 while metadata and references identify 002; missing task identity; a valid three-way match; a rework report staying with its explicit current owner even when it references a predecessor; two roots in one thread; a late report that predates its child task; missing or failing QA; missing browser evidence; and a zero-diagnostic state that still fails because attribution is invalid.

The tests also confirm that best-effort parenting uses body and recent-task fallbacks. We therefore do not claim that every historical CodeFlowMu report is determined exclusively by the three-way gate. The accurate boundary is: compatibility logic helps organize incomplete data; consequential acceptance paths use stricter contracts.

The suite does not prove that three consistently wrong identifiers will be detected, that every writer injects authoritative metadata, or that clock skew and competing attempts are fully arbitrated. Those remain explicit next-test targets.

Six failure cases to copy

Identifier mismatch

Make the filename, explicit task, and first reference disagree. Expected: attribution fails; the original artifact and conflict evidence remain intact.

Consistently wrong identifiers

Copy an old report template so that the filename, task_id, and first reference all agree on the wrong task. Expected target behavior: runtime-owned execution context overrides or rejects model-authored identity. A three-way equality check alone is insufficient.

Late old report

Create a report before the target child exists, then discover it after a watcher restart. Expected: it may appear as historical evidence, but cannot satisfy the current child’s report requirement.

Repeated submission for one task

Submit v1, reject it, then submit v2 for the same task. Expected: both artifacts remain auditable, v2 explicitly supersedes v1, and only one version is effective for the current attempt.

Multiple roots in one thread

Place two independent roots under one thread_key and supply no lineage. Expected: undetermined, not first-root or newest-root attachment.

Missing or failed QA

Provide a correctly attributed DEV report and valid code, but omit required QA or set the verdict to FAIL. Expected: no successful final summary and no downstream publication release.

A report and summary checklist

At task execution:

  1. Put task, parent, and execution-attempt identity into the runtime context when work is claimed.
  2. Let the Agent submit body and evidence; let the runtime inject the filename and authoritative metadata.
  3. Store the direct owner separately from historical references.
  4. Record sender role, attempt identity, logical event sequence, and physical timestamp.
  5. Give rework a new attempt identity and an explicit supersession link while retaining predecessor references.

At report intake:

  1. Parse explicit identity before running heuristic matching.
  2. Return undetermined when candidates tie.
  3. Preserve the original file, parse result, and conflict reason.
  4. Clearly label inferred display placement as unusable for acceptance.

Before final summary:

  1. Use logical sequence, attempt identity, and supersession to select the effective report; use physical time only as supporting evidence.
  2. Verify role, owner, and required evidence.
  3. Block success on missing, failed, or insufficient QA.
  4. Store execution facts, verification decisions, and business acceptance separately.

Limits and open questions

A consistent three-way identifier catches obvious cross-accounting. It does not prove truthful report content. A model can consistently repeat the wrong identity, so runtimes should inject task identity rather than ask models to generate it. The current sources do not prove that this injection contract is universal across CodeFlowMu report writers.

The body-matching heuristic has no measured false-association rate, and this article does not recommend it for acceptance. Cross-repository and cross-organization tasks also need namespaces or globally unique identities; a date plus a three-digit sequence can collide.

The 44 tests are first-party evidence from a pinned commit, not an external audit. A stronger next experiment would generate random task trees, copy consistently wrong metadata, create competing attempts, reorder reports, skew physical timestamps, duplicate watcher events, rebuild after restart, and measure undetermined, false-attachment, and missed-attachment rates.

Conclusion

The most dangerous multi-agent reporting error is not always a missing artifact. It is a plausible artifact charged to the wrong task and then propagated into acceptance.

A display may help a human find a report. An acceptance system has no authority to guess when ownership is unclear.

Propagate task identity and parentage with execution. Apply deterministic attribution to consequential receipts. Keep QA and final acceptance independent. Three reports can then remain three reviewable evidence chains instead of becoming one convincing false delivery.

Primary sources

  1. W3C Trace Context
  2. OpenTelemetry Tracing API
  3. FCoP v3 Chinese specification, pinned commit
  4. CodeFlowMu reportAttribution, pinned commit
  5. CodeFlowMu reportParenting, pinned commit
  6. CodeFlowMu PmSummaryGate, pinned commit
  7. CodeFlowMu LedgerBuilder, pinned commit
  8. TMPA Core Specification S1.0, pinned commit

Accessed 2026-08-20.

Last updated: