Summary
On an insufficient_evidence verdict, the headline reason counts source warnings (the symptom) while the one actionable gap is demoted to a secondary line — and the Next action: line printed immediately below actively contradicts it, telling the user no machine-actionable fix exists and to "gather deeper evidence."
Evidence (reproduced 2026-08-10, CLI 0.16.0b7)
Stage-2 stdout, verbatim, three consecutive lines:
Reason: Evidence coverage below threshold (6 source warning(s)); scan results are not
trustworthy enough to gate release.
Improve evidence: Add a reviewed closed-world binding declaration and rerun verification.
Target: shipgate.yaml#agent_bindings.declarations.
Next action: Evidence coverage below threshold (6 source warning(s)); ... Surface this to
the user and gather deeper evidence (e.g. MCP/OpenAPI inputs, eval traces,
additional source files) before re-running the scan; applying patches does not
clear an evidence verdict, so no machine-applicable fix is available.
Line 2 is specific and correct. Line 3 is generic, contradicts line 2, and is the field a coding agent is contractually told to read (agent_summary.first_recommended_action). The six warnings named in lines 1 and 3 are not independently fixable — they are the same fact ("ADK static analysis cannot resolve imported tool symbols") restated six times, and they persist unchanged after the binding gap is closed (still 6 at the final blocked verdict).
Secondary evidence — the wrong lever gets no correction signal. Declaring tool_identity.bindings against a source that produced zero observations raised source_warning_count from 6 to 12 with six copies of:
Invalid tool binding 'bind_spraay_batch_eth': member source_id='adk_crypto_payroll_agent',
tool='spraay_batch_eth' matched 0 observations
No message states the actual rule (a source with no observations cannot be a binding member; agent_bindings is the surface for this).
Impact
The gating engine is right; the ranking is wrong. A consumer that reads reason and first_recommended_action — which is exactly what docs/agent-contract-current.md instructs — gets "no fix available, go gather more evidence" when a precise one-block fix is available and already computed. For a coding agent this is a dead end, and the cheap escape routes from a dead end are the ones enumerated in forbidden_actions.
Proposal
- Rank the
reason by actionability: when at least one gap has a concrete next_action.path, lead with that gap; report source-warning counts as context, not as the headline cause.
- Make
agent_summary.first_recommended_action agree with Improve evidence: — same gap, same path. Never emit "no machine-applicable fix is available" while a gap carries a non-null path.
- Deduplicate source warnings by mechanism: one warning naming the cause and the fix, with the affected symbols listed.
- On a binding member matching zero observations, state the rule and the correct surface.
Before / After
Before: Evidence coverage below threshold (6 source warning(s)); ... no machine-applicable fix is available.
After: Insufficient evidence: the agent's tool bindings are unproven. Declare them at shipgate.yaml#agent_bindings.declarations (scaffold: agents-shipgate-reports/suggested-declarations.yaml). Context: 6 ADK tool symbols are imported and not statically resolvable.
Acceptance criteria
Scope / non-goals
Verdict logic is untouched — insufficient_evidence stays exactly as strict, and source warnings still count toward the IE threshold (_MAX_TOLERATED_SOURCE_WARNINGS = 3, frozen). This is ranking and copy only. Deduplication must not change source_warning_count semantics used by evidence_below_ie_threshold; dedupe at render time, or count distinct mechanisms and update CALIBRATION.md if the counted value changes.
Headline metric
Cold-start iterations to first gating verdict: 5 → 2, and eliminates the contradiction on the field agents are contractually routed to. No schema bump; string and ordering changes plus one consistency invariant.
Summary
On an
insufficient_evidenceverdict, the headlinereasoncounts source warnings (the symptom) while the one actionable gap is demoted to a secondary line — and theNext action:line printed immediately below actively contradicts it, telling the user no machine-actionable fix exists and to "gather deeper evidence."Evidence (reproduced 2026-08-10, CLI 0.16.0b7)
Stage-2 stdout, verbatim, three consecutive lines:
Line 2 is specific and correct. Line 3 is generic, contradicts line 2, and is the field a coding agent is contractually told to read (
agent_summary.first_recommended_action). The six warnings named in lines 1 and 3 are not independently fixable — they are the same fact ("ADK static analysis cannot resolve imported tool symbols") restated six times, and they persist unchanged after the binding gap is closed (still 6 at the finalblockedverdict).Secondary evidence — the wrong lever gets no correction signal. Declaring
tool_identity.bindingsagainst a source that produced zero observations raisedsource_warning_countfrom 6 to 12 with six copies of:No message states the actual rule (a source with no observations cannot be a binding member;
agent_bindingsis the surface for this).Impact
The gating engine is right; the ranking is wrong. A consumer that reads
reasonandfirst_recommended_action— which is exactly whatdocs/agent-contract-current.mdinstructs — gets "no fix available, go gather more evidence" when a precise one-block fix is available and already computed. For a coding agent this is a dead end, and the cheap escape routes from a dead end are the ones enumerated inforbidden_actions.Proposal
reasonby actionability: when at least one gap has a concretenext_action.path, lead with that gap; report source-warning counts as context, not as the headline cause.agent_summary.first_recommended_actionagree withImprove evidence:— same gap, same path. Never emit "no machine-applicable fix is available" while a gap carries a non-nullpath.Before / After
Before:
Evidence coverage below threshold (6 source warning(s)); ... no machine-applicable fix is available.After:
Insufficient evidence: the agent's tool bindings are unproven. Declare them at shipgate.yaml#agent_bindings.declarations (scaffold: agents-shipgate-reports/suggested-declarations.yaml). Context: 6 ADK tool symbols are imported and not statically resolvable.Acceptance criteria
reasonnames the binding gap; the warning count appears as context.first_recommended_actionandImprove evidence:reference the same gap and path.next_action.path(invariant test).tool_identity.bindingson a zero-observation source yields one message namingagent_bindings.Scope / non-goals
Verdict logic is untouched —
insufficient_evidencestays exactly as strict, and source warnings still count toward the IE threshold (_MAX_TOLERATED_SOURCE_WARNINGS = 3, frozen). This is ranking and copy only. Deduplication must not changesource_warning_countsemantics used byevidence_below_ie_threshold; dedupe at render time, or count distinct mechanisms and update CALIBRATION.md if the counted value changes.Headline metric
Cold-start iterations to first gating verdict: 5 → 2, and eliminates the contradiction on the field agents are contractually routed to. No schema bump; string and ordering changes plus one consistency invariant.