Skip to content

Latest commit

 

History

History
319 lines (252 loc) · 14.5 KB

File metadata and controls

319 lines (252 loc) · 14.5 KB

K1-A — Phase 1 formal freeze (executable)

Status: Frozen, implemented on main, and now publicly released in v3.4.0 for K1-A Phase 1 (adapter-first). Parent: PLAN-K1-A2A-HANDOFF-DELEGATION-ROUTE-EVIDENCE-2026q2.md. Repo snapshot: Current assay-adapter-a2a plus ADR026 A2A fixtures emit typed task, message, and canonical assay.adapter.a2a.task.requested events, and now also emit the first bounded top-level handoff object on main. task.updated remains mapped but is still not a positive source in v1, and the ADR026 fixture set still does not include a dedicated task.updated packet. This freeze defines one bounded top-level handoff contract from existing typed fields only, with explicit negatives and no reuse of payload.discovery.

Contract honesty (product / review)

K1-A v1 is typed, adapter-emitted visibility evidence only. It is grounded in already-shipped A2A task/message fields, but it is not a full delegation graph, target-resolution surface, or handoff-correctness signal. Do not market this as “A2A delegation verified” or “route resolved” in v1. The only honest contract here is that a bounded handoff / delegation-route surface is visible in current typed A2A task-request packets, with limited task/message reference visibility on that same surface.


1. Definitive decision: typed-payload-only v1

Decision: K1-A v1 is typed-payload only.

Positive promotion for the new handoff seam is allowed only when all of the following hold:

  1. the canonical emitted event type is assay.adapter.a2a.task.requested
  2. the typed task payload contains task.kind == "delegation"

Not allowed in v1:

  • attributes
  • payload.discovery
  • unmapped_fields_count
  • unmapped top-level keys
  • heuristics on agent.role, artifact, or generic message fallbacks

Deferred in v1:

  • positive promotion from assay.adapter.a2a.task.updated until fixture-backed freeze evidence exists
  • any target-agent identity, route-hop list, transfer success, or chain completeness

2. Payload placement and default shape (hard contract)

Placement: handoff is a top-level sibling on the emitted canonical adapter payload (same object as agent, task, message, attributes, discovery, and unmapped_fields_count).

Presence: handoff is always present on every emitted event.

Default values (when no rule sets a non-default):

Field Default JSON type
visible false bool
source_kind "unknown" string (enum)
task_ref_visible false bool
message_ref_visible false bool

Enum values for source_kind: typed_payload | unknown

v1 reachability: In this freeze, typed_payload is the only positive source kind. unknown is the default when the positive typed rule does not match. There is no attributes, unmapped, or fallback source kind in v1.


2b. Bounded meaning — may imply / must not imply

Field May imply (visibility / presence only) Must not imply
visible A bounded handoff / delegation-route surface was observed on a typed A2A task-request packet (task.requested + task.kind == "delegation") Delegation succeeded, was allowed, was correct, reached the right target, or completed a full chain
source_kind Which class of source set the seam (typed_payload vs unknown) Confidence, correctness, trust, or protocol-native completeness beyond the frozen rule
task_ref_visible A typed task.id from the upstream packet was visible on a packet that already satisfied handoff.visible Task identity verified, synthetic fallback accepted as real, or route completeness
message_ref_visible A typed message.id from the upstream packet was visible on a packet that already satisfied handoff.visible Message legitimacy, target identity, or delegation success

One-line semantics guardrail: Every handoff.* boolean is a bounded observed visibility flag only. None of these fields mean the handoff was valid, authorized, complete, trusted, or successful.


3. Source rule and decision table

Positive v1 source rule (hard requirement):

Situation Result
Canonical event type is assay.adapter.a2a.task.requested and typed task.kind == "delegation" handoff.visible = true, handoff.source_kind = "typed_payload"
Same as above plus upstream typed task.id present handoff.task_ref_visible = true
Same as above plus upstream typed message.id present handoff.message_ref_visible = true
Lenient mode substituted synthetic task.id = "unknown-task" handoff.task_ref_visible = false
Any other packet shape or event class all defaults; handoff.source_kind = "unknown"

Explicit v1 non-promotion rule: assay.adapter.a2a.task.updated is not a positive source in this freeze, even though the adapter already maps it. A later freeze may widen the source rule only after a fixture-backed update.


4. Filled freeze table (per field)

4.1 handoff.visible

Exact source paths (v1) Canonical event type assay.adapter.a2a.task.requested plus typed payload path task.kind with string value "delegation".
Minimal shape The packet maps to the canonical task-request event, task is an object, and task.kind is a JSON string equal to delegation.
May use attributes? No.
May use payload.discovery? No.
Multiple signals required? Yes. Event class and task.kind == "delegation" are both required.
Explicit negatives (must not promote) (1) artifact.shared even if task.id exists; (2) generic assay.adapter.a2a.message fallback even if message.id exists; (3) agent.capabilities; (4) missing task.kind; (5) non-delegation task.kind; (6) agent.role alone; (7) attributes blobs; (8) payload.discovery; (9) unmapped_fields_count alone; (10) task.updated in v1.

4.2 handoff.source_kind

Exact source rule (v1) typed_payload when §4.1 matches; otherwise unknown.
Enum surface typed_payload
Explicit negatives No other source kind may appear in v1. In particular, attributes, unmapped, and fallback generic-message paths are not valid handoff source kinds.

4.3 handoff.task_ref_visible

Exact source paths (v1) Upstream typed task.id mapped into canonical payload.task.id, and the packet already satisfies §4.1 for handoff.visible.
Minimal shape Upstream task.id is a JSON string and was present before any lenient substitution.
Synthetic fallback rule The current lenient adapter may substitute task.id = "unknown-task" for task events. That synthetic value must not set handoff.task_ref_visible = true.
Explicit negatives (1) synthetic unknown-task; (2) artifact.shared task IDs; (3) any packet where handoff.visible = false.

4.4 handoff.message_ref_visible

Exact source paths (v1) Upstream typed message.id mapped into canonical payload.message.id, and the packet already satisfies §4.1 for handoff.visible.
Minimal shape Upstream message.id is a JSON string.
Explicit negatives (1) generic assay.adapter.a2a.message fallback; (2) packets where handoff.visible = false; (3) synthetic unknown-message on generic fallback packets.

5. Strict vs lenient

  • Strict mode: current adapter behavior already rejects task packets without task.id; that remains true. No emitted handoff object exists because the whole packet is rejected.
  • Lenient mode: handoff.visible may still be true when the typed route surface exists (task.requested + task.kind == "delegation"), even if task.id is missing. In that case:
    • handoff.source_kind = "typed_payload"
    • handoff.task_ref_visible = false
    • handoff.message_ref_visible follows upstream typed message.id only
  • Invalid event-type fallback: packets that fall back to assay.adapter.a2a.message keep the full handoff default object, even if message.id or synthetic unknown-message is present.

6. Complete emitted JSON examples (illustrative)

Build note: adapter_version uses 3.4.0 as an illustration; real emission uses CARGO_PKG_VERSION. Reviewers should treat presence and shape of top-level keys as normative here, not the patch digit.

6.1 Typed positive (task.requested + delegation)

Fixture source: a2a_happy_task_requested.json

{
  "adapter_id": "assay-adapter-a2a",
  "adapter_version": "3.4.0",
  "protocol": "a2a",
  "protocol_name": "a2a",
  "protocol_version": "0.2",
  "upstream_event_type": "task.requested",
  "agent": {
    "id": "agent://coordinator",
    "role": "orchestrator"
  },
  "task": {
    "id": "task-123",
    "status": "requested",
    "kind": "delegation"
  },
  "message": {
    "id": "msg-1",
    "role": "assistant"
  },
  "attributes": {
    "channel": "web",
    "priority": "urgent"
  },
  "discovery": {
    "agent_card_visible": false,
    "agent_card_source_kind": "unknown",
    "extended_card_access_visible": false,
    "signature_material_visible": false
  },
  "handoff": {
    "visible": true,
    "source_kind": "typed_payload",
    "task_ref_visible": true,
    "message_ref_visible": true
  },
  "unmapped_fields_count": 0
}

6.2 Lenient partial visibility (task.id missing)

Fixture source: a2a_negative_missing_task_id.json in lenient mode

{
  "adapter_id": "assay-adapter-a2a",
  "adapter_version": "3.4.0",
  "protocol": "a2a",
  "protocol_name": "a2a",
  "protocol_version": "0.2",
  "upstream_event_type": "task.requested",
  "agent": {
    "id": "agent://coordinator"
  },
  "task": {
    "id": "unknown-task",
    "status": "requested",
    "kind": "delegation"
  },
  "message": {
    "id": "msg-2"
  },
  "discovery": {
    "agent_card_visible": false,
    "agent_card_source_kind": "unknown",
    "extended_card_access_visible": false,
    "signature_material_visible": false
  },
  "handoff": {
    "visible": true,
    "source_kind": "typed_payload",
    "task_ref_visible": false,
    "message_ref_visible": true
  },
  "unmapped_fields_count": 1
}

6.3 Fully default (artifact.shared)

Fixture source: a2a_happy_artifact_shared.json

{
  "adapter_id": "assay-adapter-a2a",
  "adapter_version": "3.4.0",
  "protocol": "a2a",
  "protocol_name": "a2a",
  "protocol_version": "0.3.1",
  "upstream_event_type": "artifact.shared",
  "agent": {
    "id": "agent://worker"
  },
  "task": {
    "id": "task-123"
  },
  "artifact": {
    "id": "artifact-7",
    "name": "plan.md",
    "media_type": "text/markdown"
  },
  "discovery": {
    "agent_card_visible": false,
    "agent_card_source_kind": "unknown",
    "extended_card_access_visible": false,
    "signature_material_visible": false
  },
  "handoff": {
    "visible": false,
    "source_kind": "unknown",
    "task_ref_visible": false,
    "message_ref_visible": false
  },
  "unmapped_fields_count": 0
}

7. Negative test matrix (implemented minimum on main)

# Case Expected handoff
N1 artifact.shared with task.id present all defaults
N2 lenient invalid event_type falling back to assay.adapter.a2a.message all defaults, even if message.id or unknown-message exists
N3 strict task.requested packet missing task.id measurement error; no emitted packet
N4 lenient task.requested packet with task.kind = delegation but missing task.id visible = true, source_kind = "typed_payload", task_ref_visible = false
N5 task.requested packet with missing or non-delegation task.kind all defaults
N6 agent.role, attributes, payload.discovery, or unmapped_fields_count alone all defaults
N7 task.updated packet in v1 all defaults until a later freeze widens the positive rule

Current coverage note: the first K1-A adapter slice on main now includes explicit adapter-level tests for N1, N2, N4, N5, and N7, plus helper-level direct coverage for the source-rule default paths. The ADR026 fixture set itself still does not include a dedicated task.updated packet, so future fixture-parity work remains optional rather than a blocker for the shipped v1 seam.


8. assay-evidence scope

No change to assay-evidence in K1-A v1. This freeze is about canonical adapter-emitted evidence shape only. Any later Trust Basis, Trust Card, or pack follow-up must be justified separately after the handoff seam is real.


9. Link to implementation

  • Implement handoff in the A2A adapter as a separate top-level sibling, not as an extension of payload.discovery.
  • Source logic must be grounded in current typed fields from:
  • Tests must cover:
    • typed positive from a2a_happy_task_requested.json
    • strict failure on missing task.id
    • lenient partial visibility on missing task.id
    • no promotion from artifact.shared
    • no promotion from generic message fallback
    • explicit non-promotion from task.updated in v1
  • Canonical stability should be asserted with repeated conversion plus golden digests over the emitted handoff sub-object.

10. Reviewer checklist (contract closure)

Question Expected answer
Is handoff a single bounded top-level surface? Yes
Does v1 promote only from typed task.requested + task.kind == "delegation"? Yes
Does v1 avoid attributes, payload.discovery, unmapped keys, and heuristics? Yes
Is synthetic unknown-task blocked from counting as task_ref_visible? Yes
Is task.updated explicitly non-promoting in v1? Yes
Does the doc stay at visibility language, not correctness or trust language? Yes