Skip to content

Show the plan-map synth what the integration actually landed - #2063

Merged
ppXD merged 1 commit into
mainfrom
fix/show-the-synth-what-landed
Nov 7, 2026
Merged

ppXD merged 1 commit into
mainfrom
fix/show-the-synth-what-landed

Conversation

@ppXD

@ppXD ppXD commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • The defect. The plan-map synth narrated a partial integration as a whole deliverable. The integrate step's outputs reached only the done terminal (appliedCount, conflicts and reason were bound nowhere), and a unit withheld before integration (its acceptance Failed or was Waived, or its output review did not approve it) is dropped from the candidate and appears in no output. git.integrate_run now emits, on every pass (clean, conflicted, empty, skipped, resumed), summary (one account of what happened, at most 2,000 chars) and withheld ([{label, reason}], each reason in fixed words). The resumed pass's reviewApproved / reviewComment / reviewedBy are now declared in its OutputSchema, because DefinitionValidator rejects a reference to an undeclared output.
  • The prompt. A repo-bound graph's synth user prompt gains \n\nIntegration outcome:\n{{nodes.integrate.outputs.summary}}; its system prompt gains an instruction to state what landed, to name anything conflicted or withheld as NOT delivered, how to read a label (<node>#map#<i>, i the 0-based position in the results, "subtask N" is i+1), and to report each subtask once. A repo-less graph keeps both halves byte-for-byte (the existing pins are untouched and green). On a clean run the summary is a factual sentence, not the failure furniture the "no failure furniture" pin forbids (that pin is on a repo-less graph). It sits outside the 120k promptBudgetChars; its 2,000-char bound is under 2% of that budget.
  • What the account says (<...> is a per-run id):
    • Clean: Integration: 2 contribution(s) landed on codespace/integration/<runId>: subtask 1 (agent#map#0), subtask 2 (agent#map#1).
    • A subtask that failed after editing files is not withheld by its own grade (it is ungraded, and no review is configured), so its diff rides the candidate while its results entry is an {"error": ...}. How the run ended is read from its agent-run row's status, the column that error entry comes from; a worker the reconciler abandoned after its push is marked Failed with no result at all, and a result-keyed reading would call it whole. Acceptance is graded only for a run that reported its own outcome, so the account separates two shapes, each its own clause appended to the Clean text:
      • Landed although its subtask failed (partial, unverified): subtask 2 (agent#map#1). for a diff nothing checked;
      • Landed although its subtask failed afterwards (acceptance passed): subtask 2 (agent#map#1). for a run whose acceptance passed and which then failed (an executor fault past the grade).
    • Withheld, appended to any account: Withheld before integration: subtask 2 (agent#map#1) — acceptance Failed. The reason is acceptance Failed, acceptance waived by the supervisor (not delivered), output review flagged it or output review did not approve it. The critic's critique and unreviewed reason are model-authored text and never reach the prompt. The descriptions of withheld (the node's OutputSchema, the WithheldContribution record, the renderer and node docs) now name both gates; they described acceptance verdicts only.
    • Conflicted: Integration conflicted: no integrated branch was published, so none of this run's work landed on one (1 of 2 contribution(s) applied cleanly, but integration is all-or-nothing); the work stays on the agents' own branches and patches. Conflicted or held back: subtask 2 (agent#map#1) → codespace/agent/<id>. A reviewer rejected the retry.
    • Applied cleanly but not pushed (no credential, or the remote branch advanced): Integration applied every contribution cleanly but published no branch (<the integrator's reason>), so none of this run's work landed on one; ... — it does not say "conflicted".
    • Skipped: Integration skipped: the run produced no integrable work for this repository.; with no base revision, ... Nothing landed on an integrated branch; the produced work stays on the agents' own branches and patches.
    • A resumed pass says A reviewer approved the retry. / A reviewer rejected the retry. — a fixed sentence placed after the clauses that describe what landed (so a "Landed although..." clause stays beside the list it qualifies) and before the withheld clause; the reviewer's free-text comment stays on the outputs.
    • The account holds its bound by cutting its LISTS, never its prose, least important first (landed/conflicted, then the failed landings with the verified ones before the unverified partials, last the withheld units): … and N more — see conflicts[]. The withheld clause is the last thing cut.
  • Behaviour change in integration. Each unit is now reduced to its LATEST attempt before the verdict gate is applied, in Build, Withheld and the failed-landing view alike (it was the other way round). A unit whose first attempt passed and whose retry flunked used to integrate the first attempt's superseded bytes in place of the retry; now it contributes nothing and is reported as withheld at its latest verdict. This is what RunIntegrationContributions' own doc asks for: one attempt per unit, the abandoned attempts dropped at the input, the verdict a separate gate. "Latest attempt" means the latest attempt that left a manifest row in this repository: a retry that captured nothing writes no row, and the reduction runs per repository, so a multi-repo unit keeps an abandoned attempt's bytes for a repository the surviving attempt never touched. A unit with one attempt, or whose latest attempt passes, integrates exactly as before.
  • Merged with the output-review gate. IsWithheldFromHead(manifest, work) also withholds a unit its output review did not approve. Both verdicts are in the gate for Build, Withheld and the failed-landing view, and a unit the review withholds is named in the withheld clause (it was otherwise exactly the "dropped and mentioned nowhere" case). RunAgentWork gains a trailing optional Status (null claims nothing about how the run ended), loaded from the agent-run row by GitIntegrateRunNode.
  • Design notes. IntegratedBranch is null on every non-Clean status and the integrator resets its clone on abort (IntegrationResult.cs), so a Conflicted account says nothing landed. The instruction is a sibling constant, SynthIntegrationInstruction, appended only when the graph has an integrate node; its label sentence says a subtask named as withheld, or as landed although it failed, is "usually" one of the results' {"error": ...} entries and a conflicted one an ordinary result (in the real conflicted run both items were Succeeded results). The conflicted E2E reads the conflicted unit from the ledger because the two parallel items are applied in no fixed order. The review keys still carry no WaitOutputsSpec (noted in the node's doc). The shared "real failure before bystander" order is one method, GitIntegrateNode.NotApplied. The synth prompt of repo-bound Standard-lane runs changes, so the TaskLaunchStandard qualification arm measures the new prompt; no digest covers it.

Test plan

Counts are main (b64ca1c17, before this change) → this branch, all green on the pushed tip:

Class Tier Count
RunIntegrationSummaryTests (new) Unit 34
RunIntegrationContributionsTests Unit 33 → 72
PlanMapSynthDefinitionBuilderTests Unit 33 → 35
PlanMapDynamicDefinitionBuilderTests Unit 11 → 12
GitIntegrateRunNodeManifestTests (new) Unit 10
GitIntegrateNodeTests Unit 8 → 8 (pins the shared ordering)
GitIntegrateRunNodeFlowTests Integration 14 → 34
PlanMapIntegrateWholeLoopE2ETests E2E 4 → 5 (a failed-but-landed arm; the other four assert what the synth was shown)

The failed-landing cases seed the rows production writes: an abandoned worker as the reconciler leaves it (row Failed, its error stamped, no result), a run that failed after its acceptance passed as UnapprovedUnitShapes.ExecutorFault over a Passed row, and a retried unit as a faulted first attempt followed by a retry that flunked its acceptance. The supervisor's waive is pinned with a supervisor-lane label.

  • Mutations on this tip, each applied to a copy-backed file, rebuilt, run, then restored byte-identically (every one went red):
Mutation Turned red
The ledger stops reporting subtasks that landed although they failed 10 unit, 3 node, E2E partial arm
The failed-landing flag read off the run's result instead of its row 3 unit + 1 node (an abandoned worker with no result)
The node never loads the row's status 3 node, E2E partial arm
The node never passes the failed-landing list to the renderer 3 node, E2E partial arm
The renderer drops the failed-landing clauses 6 unit, 3 node
One qualifier for both shapes (a passed acceptance reads as a partial) 3 unit, 1 node
The acceptance verdict is not carried to the failed landing 2 unit, 1 node
The unverified clause ranks below the verified one when the bound bites 1 unit
The review sentence back before the qualifiers 1 unit
A Clean account drops the landed labels 12 unit, 13 node, E2E clean, flunked, partial and flagged arms
Labels written bare, without "subtask N" 19 unit, 15 node, all 5 E2E
The label / report-once sentence dropped from the instruction both builder tests
The verdict gate back ahead of the latest-attempt reduction unit A_unit_whose_latest_attempt_flunked_contributes_nothing_although_an_earlier_attempt_passed, node A_unit_whose_latest_attempt_flunked_is_withheld_not_integrated_from_an_earlier_attempt
The withheld clause is cut first 2 unit
Lists are never cut 6 unit, 1 node
An integrator's long reason is not clipped 2 unit (incl. the surrogate-pair clip)
The conflicted list says "withheld from the integrated branch" 2 unit, 1 node
A set applied but not pushed reads as a conflict 3 unit, 1 node
The waived reason reverted 2 unit, 1 node
A no-base skip without "where the work stays" 1 unit, 1 node
The reviewer's verdict not stated 3 unit, 2 node
The node never passes the review verdict 2 node, E2E conflicted arm
Withheld keyed on the label only Two_withheld_agents_of_one_supervisor_turn_are_two_entries_not_one
Withheld not deduped per unit The_alias_rows_of_one_withheld_attempt_are_one_entry
The withheld reason ignores the output review 6 unit, 5 node (production-built UnapprovedUnitShapes), E2E flagged-item arm
A flagged review reads as "did not approve" 2 unit, 1 node
Withheld ignores the output-review verdict (a unit neither landed nor withheld) 6 unit, 5 node, E2E flagged-item arm
  • Regression sweep on the rebased tip (86ab15579): the whole CodeSpace.UnitTests project is 13,273 tests, 13,272 passed, 1 skipped (pre-existing), 0 failed. Integration classes that touch the integrate door, plan-map graphs or the output-review flows, all green: GitIntegrateRunNodeFlowTests 34, GitIntegrateRunNodeRealGitFlowTests 5, OutputReviewIntegrityFlowTests 14, SupervisorMergeWithholdFlowTests 15, SupervisorLedgerDirectTerminalOutputFlowTests 10, SupervisorDependencyStagingFlowTests 23, CompletionTerminalAuthorityFlowTests 25, MapPromptBudgetFlowTests 4, TaskLaunchFlowTests 50, TaskLaunchContractFlowTests 10. E2E, all green: PlanMapIntegrateWholeLoopE2ETests 5, PlanMapSynthFanoutFlowTests 2, PlanMapDynamicFanoutFlowTests 1, StandardPlanConfirmFanoutFlowTests 1, ReviseLoopFanoutE2ETests 1, RubricReviseFanoutE2ETests 1, RunPhaseProjectorFlowTests 6. A full non-incremental build has the same 1,406 warnings as main and none in the touched files.
  • The new PartialWorkFakeCli satisfies the fake-CLI convention tests (marker 8, harness 3, collection 2). Its E2E arm zeroes the retry BACKOFF in the built definition and nothing else, because the engine waits the 30 s backoff for real, twice per dying subtask; the retry policy itself still runs.
  • CI

@ppXD
ppXD force-pushed the fix/show-the-synth-what-landed branch 2 times, most recently from 1d9214e to 6825b42 Compare October 12, 2026 01:24
@ppXD
ppXD force-pushed the fix/show-the-synth-what-landed branch 3 times, most recently from 8114eb1 to ebf4a28 Compare November 7, 2026 15:45
The plan-map synth reduces the per-subtask results into the run's combined
answer, but it never saw the integration outcome. The integrate step's
outputs reached only the done terminal, appliedCount, conflicts and reason
were bound nowhere, and a unit withheld before integration (its acceptance
Failed or was Waived, or its output review did not approve it) is dropped
from the candidate and appears in no output at all. A conflicted, partial
or incomplete candidate was narrated as a finished deliverable whatever was
actually on the branch.

git.integrate_run now owns the narrative. Every pass (clean, conflicted,
empty, skipped, resumed) emits summary, one account of what happened,
bounded at 2,000 characters, and withheld, the units the head gate kept
off the candidate, each with a fixed-words reason: the acceptance grade,
the supervisor's waive, or the output review's verdict. The reviewer's
critique is model-authored text and never reaches the account.

A Clean account names which contributions landed, each as "subtask N
(label)" so the reduce can place it among its results, and flags the ones
that landed although their own agent run did not succeed: such a subtask
is not withheld by its own grade, so its diff rides the candidate while
its results entry reads as an error. How the run ended is read from its
agent-run row's status, which is where that error entry comes from; a
worker the reconciler abandoned after its push has no result at all.
A run whose acceptance check passed is flagged "failed (its acceptance
check passed)", with no claim about order (the supervisor lane grades
every staged unit whatever its row says, so a Failed row beside a Passed
grade can be an under-claim), and any other "partial, unverified".

A conflicted set says nothing landed (the integrator publishes no branch
on any non-Clean status, so its applied count is a trial count) and where
each held-back contribution's work stays. A set that applied cleanly but
was not pushed says that instead of claiming a conflict. A resumed pass
states whether a reviewer approved or rejected the retry in a fixed
sentence, after the clauses describing what landed; the free-text comment
never reaches the prompt. The account holds its bound by cutting its
lists, never its prose, and the withheld clause is the last thing cut.
The resumed pass's review keys are now declared in the OutputSchema, which
the validator requires in order to bind them.

A repo-bound graph's synth prompt carries the account under "Integration
outcome:", and its system prompt says to state what landed, to name
anything conflicted or withheld as not delivered, how to read a label,
and to report each subtask once. A repo-less graph keeps both prompt
halves byte-for-byte.

Integration now reduces each unit to its latest attempt before applying
the verdict gate. A unit whose latest attempt was rejected contributes
nothing and is reported as withheld even if an earlier attempt passed;
previously the gate ran first, so the superseded attempt's bytes could
land on the candidate in place of the retry that replaced it.
@ppXD
ppXD merged commit 7010c12 into main Nov 7, 2026
6 checks passed
@ppXD
ppXD deleted the fix/show-the-synth-what-landed branch November 7, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant