Skip to content

Devin: deliver authorized context packets to Devin roles and hosted builder input - #932

Merged
jeffhuber merged 9 commits into
mainfrom
devin/908-context-packets
Sep 12, 2026
Merged

Devin: deliver authorized context packets to Devin roles and hosted builder input#932
jeffhuber merged 9 commits into
mainfrom
devin/908-context-packets

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #908. Part of #901.

  • context_delivery: SUPPORTED_HOSTS = ("claude", "codex", "devin") drives SUPPORTED_RECIPIENTS (<host>:{orchestrator,builder,reviewer}), feedback keys, and public_verdict(provider="Devin"). The CLI (context attach/deliver/feedback), guided prepare/attach/deliver/feedback, and the pre-PR delivery path accept Devin through the same constants; Devin roles therefore go through the unchanged load_authorized()/deliver() identity, expiry, head, recipient, and online-authorization checks and receive the same rendered evidence as Claude/Codex. public_verdict(provider="Devin") forces merge_authority=False (header reads "informational only") regardless of the caller.
  • devin_work_orders: hosted builder input can carry the packet without a local prompt file.
    order = WorkOrder(..., context_policy="none" | "optional" | "required")   # trusted decision, part of the durable binding
    context = packet_context(store, connection, handle, policy, order=order)  # -> PacketContext(store, name, handle, policy, backend); no packet/evidence/identity
    service.run("dispatch" | "clarify" | "fix", order, apply=True, context=context)
    WorkOrder.context_policy is the trusted context decision: packet_context rejects a policy whose required flag disagrees with the order (or any packet on a none order), and _evidence() enforces it even with context=None — a required order without a packet fails closed as context_unavailable; only optional may run omitted/degraded. PacketContext carries only the protected ContextStore (exact type), connection name, packet handle, normalized policy, and backend — no callable, packet, evidence, or identity. _evidence() itself calls load_authorized(store, name, handle, policy, ContextRequest(order.repository, order.work_item, "devin:builder")) immediately before the provider write (selected account, current authorization, revocation/expiry, binding, freshness all rechecked under the store lock), re-checks the returned packet's binding against the order and devin:builder, and renders render_evidence(packet, context.handle) — the exact authorized handle, the same Packet identity the Claude/Codex deliver() path renders (no digest-derived UUID). A synthetic local packet with matching repository/issue/recipient fields therefore never reaches the store lookup; a handle for another ticket, wrong recipients, or a store without an authorizable connection is unavailable; a bare handle/packet/string, look-alike object, ContextStore subclass, or context on a none order is context_binding_mismatch — all with no provider write. Because the handle is part of the rendered text it is bound into the dispatch/message input digests.
    WorkOrder.context_work_item (new, default "") is the tracker-neutral packet work item for context-bearing orders (e.g. a Jira key from the guided session/manifest binding); WorkOrder.work_item returns it or str(issue). WorkOrder.issue remains the integer GitHub delivery issue used for _verify (claim issue, closing linked_issues). from_manifest(..., context_work_item=...) lets a keyed source omit issue_number (a present one must still match); a key on a none order is invalid_work_order. Context-free orders serialize without context_policy/context_work_item, so legacy bindings/prompts are unchanged. Required-unavailable is explicit at the public boundary: run() returns {"outcome": "UNKNOWN", "state": "paused", "reason": "context_unavailable", "context": {"policy": "required", "dispatch"|"message": "unavailable"}, "merge_authority": false} instead of raising, with no record, reservation, round, or provider write. Initial dispatch renders the context and runs the 64 KiB combined check before the work-order record or branch reservation is written; follow-ups do the same before round/claim/request/pending mutation, so a rejected input leaves no undispatched reservation and consumes no round. The chosen state (delivered/degraded/omitted) is persisted per dispatch (record["context"]) and per message intent (record["message"]["context"]) and returned by every command as "context": {"policy", "dispatch", "message"}; replay, acknowledge_delivered, status, reconciliation/restart, and collect return the saved state rather than recomputing or resetting it. Context is never rendered in preview or for status/collect/cancel; only digests plus the enum are persisted. A digest of the complete intended input (prose + evidence + state) is stored with the local dispatch/message intent before it becomes durable and validated on retry, so a stop between the local and remote intent writes cannot turn delivered context into code-only (request_conflict; status keeps reporting the saved state). Backward compatibility: _fields() serializes a context_policy="none" order in the pre-context shape for both the durable binding and the dispatch prompt, and records lacking context/input fields are read as context-free, so pre-upgrade status/collect/cancel/clarify/dispatch replay keep working while optional/required orders bind the field.
  • Devin capability declarations: devin_api_v3.context = agent_handoff (hosted builder input); devin_cli.context stays unavailable because devin_cli_audit_pr.run_audit does not invoke the authorized context lifecycle. Consistent across provider_capabilities.py, the JSON schema, templates/providers*.yml, doctor remediation, docs/sessions.md, and tests (messaging/cancel remain unavailable; no merge authority). Compatibility: LEGACY_CAPABILITIES["devin_api_v3"] holds the one exact pre-D5 template declaration (canonical hosted mapping with context: unavailable); lane_transport() accepts only that mapping and normalize_lane() upgrades it in memory to the current declaration (transport/driver unchanged, files never rewritten). Any other deviation — a different single value, an extra/missing key, or the legacy mapping on devin_cli — still fails capabilities must match.
  • Docs: docs/context-delivery.md ("Hosted Devin builder" section), docs/sessions.md, README.md.

Validation

  • New tests: all nine SUPPORTED_RECIPIENTS render identical evidence; wrong account, revoked authorization, a connection without devin:* recipients, changed head/revision, and refreshed packets are rejected; Devin reviewer feedback/public verdict redaction and forced informational posture; guided Devin host/builder/reviewer flow; hosted work order create/message injection with a private canary present in provider input and absent from every public output, local record, and file under the store; preview never retrieves; status/collect/cancel reject context; ticket‑B packet relabelled as ticket A, other-repo, unbound callable, and context on a none order rejected without a provider write; required order with context=None, failed reauthorization, oversized, or mismatched context leaves no work-order record or branch reservation (work_order_not_found, then the corrected order and the other issue's branch dispatch cleanly); required context fails closed and optional degrades explicitly with no local round consumed; saved degraded/delivered/omitted states survive replay, acknowledge_delivered, status, and the on-disk record; policy/order mismatches rejected at bind time; mixed packet/evidence negatives (ticket‑B packet returned directly for ticket A, forged packet whose recipients exclude devin:builder, string evidence) rejected on dispatch and message; required-unavailable returns the closed UNKNOWN/paused object with work_order_not_found afterwards; crash between local and remote intent then retry with dropped/failed/refreshed context is request_conflict while status still reports delivered; legacy context-free records (fields removed) replay dispatch, status, clarify, collect, cancel with the original binding and prompt; a pre-D5 devin_api_v3 lane with context: unavailable passes normalize_lane, load_config/validate_config/normalize_config/render_dry_run (file bytes unchanged) and session.build_session, while five unrelated drifts, a missing key, and the legacy mapping on devin_cli are rejected.
  • Round 7/8 tests: synthetic packet (verbatim copy and changed text, same binding fields, outside the protected store), wrong account, revoked, expired, changed recipients, unavailable connection, another ticket's handle, store subclass/look-alike/bare inputs — all paused or context_binding_mismatch with zero provider writes; PacketContext field set is exactly (store, name, handle, policy, backend) and packet_context binds no order identity; Jira-key order (context_work_item="EXAMPLE-1", issue=907, source without issue_number): GitHub-issue packet rejected, Jira packet delivered under its handle, the identical handle rendered by peer deliver() for claude/codex/devin recipients, retry digest conflicts on a refreshed handle, collect verifies issue 907 / PR 42 and rejects linked_issues 908.
  • scripts/privacy_scan.py, ruff check ., compileall, unittest discover -s tests (2980 tests, OK), scripts/smoke_easy_mode.py --json (pass).

Risk / Rollback

  • Additive for Claude/Codex paths; Devin recipients are only honored when explicitly listed in the private connection. WorkOrder.context_policy defaults to none, so existing callers keep code-only behaviour; it joins the durable binding, so a policy change is a new work order. Capability declaration change affects only the hosted Devin transport; the exact prior hosted declaration is accepted and interpreted in memory, so no config rewrite is needed. Revert the branch commits to roll back.

Data Or Secret Exposure

  • This change does not add source, raw diffs, raw transcripts, raw provider output, tokens, or machine-specific paths to public artifacts.

Link to Devin session: https://app.devin.ai/sessions/c39dc23c8564443eb22a6c65d2620c69
Open in Devin Desktop: https://app.devin.ai/desktop/session/c39dc23c8564443eb22a6c65d2620c69?variant=devin

…uilder input

Closes #908

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@jeffhuber jeffhuber added builder:devin Experimental Devin builder lane needs-codex-audit labels Sep 12, 2026
@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: cb71a3492ff1e56c311974797103b893c8d08d5b
Findings: P0=0, P1=0, P2=1, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: BLOCKED

Summary:

Oversized context-bearing follow-up messages persist an unsent pending round, disrupting recovery and subsequent work. Input validation needs to precede that state mutation.

Findings:

  • [P2] Validate combined message size before persisting the new round -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-wpczpfkw/wt/src/code_mower/devin_work_orders.py:329
    Finding ID: codex:be894eb350dbb9d4f256
    When a clarify or fix message plus authorized evidence exceeds 64 KiB, _with_evidence raises only after the new round and pending request have been persisted and the previous completion claim cleared. No provider message was sent, but subsequent requests are blocked by inspect_provider_then_acknowledge, and acknowledgment fails because the remote operation does not exist. Build and validate the combined input before mutating the local record so an oversized payload leaves the work order unchanged.

@jeffhuber

Copy link
Copy Markdown
Contributor

Supplemental adversarial review at cb71a3492ff1e56c311974797103b893c8d08d5b

Please resolve these together with the authoritative Codex audit finding before the next exact-head review:

  • Bind authorized context to the exact work order repository and work-item identity. The current opaque callback can render a valid packet for a different ticket or allowed repository into this work order; the new fixture currently demonstrates a mismatched work item and accepts it.
  • Preserve required/optional context semantics. A required context policy must fail closed with a safe unavailable/paused outcome when no valid packet is supplied; only an explicitly optional trusted policy may degrade to code-only.
  • Keep every Devin review verdict informational. public_verdict(provider="Devin") currently inherits merge_authority=True by default, which contradicts the merged Devin capability and reviewer posture.
  • Update the maintained Devin capability and doctor/session reporting to match the context support implemented here, or narrow the public claim. They currently still report context as unavailable.

The formal audit's pre-mutation combined-message size validation remains a blocker as posted.

…nd declare context capability

- Validate the combined follow-up plus context size before any local mutation.
- packet_context derives its request from the WorkOrder; mismatched bindings fail closed.
- Required policy fails closed; optional policy degrades explicitly and reports it.
- public_verdict(provider=Devin) is always informational.
- Devin transports declare context as local_runner/agent_handoff; doctor/session text updated.

Co-Authored-By: bot_apk <apk@cognition.ai>
@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: bcf5aa18ce4d1317d343bce07a8d67f6a886cced
Findings: P0=0, P1=0, P2=2, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: BLOCKED

Summary:

The patch advertises Devin CLI context support without integrating the review runner. Failed hosted dispatch context validation also leaves durable reservations that prevent legitimate corrections.

Findings:

  • [P2] Integrate private context into the Devin CLI review runner -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-6vq0je75/wt/src/code_mower/provider_capabilities.py:62
    Finding ID: codex:9c523f9d8be62f59c4aa
    Declaring context="local_runner" advertises a path that the Devin CLI reviewer does not implement. devin_cli_audit_pr.run_audit builds its prompt from the diff and lenses without calling context_audit.prepare, and never saves private feedback or emits a context review marker. Consequently, selecting Devin as an independent reviewer after attaching a packet still produces a code-only review, and the newly supported guided feedback path has no findings to retrieve. Wire the context lifecycle into that runner before advertising this capability.
  • [P2] Validate dispatch context before persisting reservations -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-6vq0je75/wt/src/code_mower/devin_work_orders.py:328
    Finding ID: codex:a3b92d661099948569bb
    On an initial dispatch with unavailable required context or an oversized combined prompt, these checks run only after the work-order binding and persistent branch reservation have been written. Although no provider session exists, correcting the work-order body then fails with work_order_binding_mismatch, and assigning the branch to another issue fails with branch_writer_conflict. Render and validate the dispatch input before committing these reservations so a rejected context input does not permanently bind an undispatched order.

devin-ai-integration Bot and others added 2 commits September 12, 2026 11:32
- Narrow devin_cli context capability back to unavailable (not wired into the local reviewer).
- Render/validate initial context before the work-order record or branch reservation is written.
- PacketContext carries only a render closure; the loaded packet's own binding is checked against the WorkOrder.
- WorkOrder.context_policy (none/optional/required) decides the outcome, including context=None.
- Persist and report the safe context-state enum for dispatch and each message; acknowledge preserves it.

Co-Authored-By: bot_apk <apk@cognition.ai>
@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: a6305bdb67e5646cca6e11c44f9a663a018814a7
Findings: P0=0, P1=1, P2=1, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: BLOCKED

Summary:

The patch makes existing durable work orders inaccessible after upgrading and permits inconsistent context delivery during crash recovery. Both issues were reproduced with in-memory state and mocked remote calls.

Findings:

  • [P1] Preserve access to existing durable work orders -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-jptm43b9/wt/src/code_mower/devin_work_orders.py:79
    Finding ID: codex:ac4f22c5e37cf0750808
    Adding this field changes both _binding() and _prompt(), which serialize asdict(order), even when context remains disabled. Consequently, every previously dispatched order fails work_order_binding_mismatch on status, collect, cancel, or continuation after upgrading; dispatch replay would also encounter the changed remote input fingerprint. Add backward-compatible handling or migration for existing context-free orders and their original dispatch inputs.
  • [P2] Bind retry evidence before persisting the message intent -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-jptm43b9/wt/src/code_mower/devin_work_orders.py:384
    Finding ID: codex:8dfb7b3663c5447c3a3f
    If execution stops after the local message intent is saved but before RemoteSessions.run() saves its intent, retrying an optional order without context sends a code-only message while retaining the saved delivered state. The local fingerprint excludes evidence, and no remote fingerprint exists yet to reject the changed input. Persist a digest of the complete input with the local intent and validate retries against it, so recovery cannot silently change evidence or misreport its delivery.

…input, keep legacy records readable

- PacketContext now only loads a ValidatedPacket; evidence is rendered inside
  _evidence() from that exact packet after checking repository, work item and
  the devin:builder recipient, so no separately supplied evidence is accepted.
- Required unavailable context returns the closed UNKNOWN/paused outcome at the
  run() boundary with no reservation or consumed round.
- A digest of the complete intended input (prose plus evidence/state) is stored
  before the local dispatch/message intent is durable and validated on retry.
- Context-free orders keep the pre-context binding and prompt serialization;
  legacy records without context/input fields read as context-free.

Co-Authored-By: bot_apk <apk@cognition.ai>
@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: 7cfaece38fc389360b19193193dfafa262891d29
Findings: P0=0, P1=0, P2=1, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: BLOCKED

Summary:

The capability change breaks previously valid hosted Devin configurations without a migration path.

Findings:

  • [P2] Migrate existing hosted Devin capability declarations -- /private/var/folders/f2/g9zqfdjx7z3ckcsx_f46htwm0000gn/T/codex-audit-isnrpmq5/wt/src/code_mower/provider_capabilities.py:70
    Finding ID: codex:58a9d32f65f2e7a30178
    For repositories configured using the previous Devin templates, capabilities.context remains unavailable. Changing the canonical value makes lane_transport() reject those existing configurations because it requires exact capability equality. Consequently, configuration validation and session initialization fail after upgrading, even for workflows without context. This rejection was reproduced through normalize_lane(). Accept or migrate the previous hosted capability declaration before enforcing equality; updating templates only fixes new installations.

…aration

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Re Codex audit finding codex:58a9d32f65f2e7a30178 (head 7cfaece): addressed in 489a460. LEGACY_CAPABILITIES["devin_api_v3"] holds only the exact pre-D5 hosted declaration (context: unavailable); lane_transport() accepts that one mapping and normalize_lane() upgrades it in memory to the current declaration with transport/driver unchanged and no file writes. Any other drift, a missing key, or the legacy mapping on devin_cli still fails. Regression test covers normalize_lane, load_config/validate_config/normalize_config/render_dry_run, and session.build_session for a pre-D5 template plus the negative cases; full suite (2979 tests), ruff, compileall, privacy scan, and easy-mode smoke pass.

@jeffhuber

Copy link
Copy Markdown
Contributor

Supplemental authorization-boundary review

Exact reviewed head: 489a460252536f0e49af1690465238b0fcb914d1.

  • P1 — synthetic packets can bypass authorized loading. PacketContext still accepts an arbitrary callable returning a ValidatedPacket. _evidence() trusts that returned object after checking only its decoded repository/work-item/recipient fields, while ValidatedPacket.private_payload() parses local JSON without proving store provenance, current authorization, selected account, revocation, or evidence freshness. A synthetic same-repository/same-issue/same-recipient packet with changed document text was accepted as delivered and reached provider input. Replace the public packet-loader callback with only the protected store/connection/handle/policy/request inputs needed by this boundary, and call the existing load_authorized() inside the work-order delivery boundary. Do not accept a caller-provided validated packet or rendered evidence as authority. Add negative tests for synthetic packets, wrong account, revoked/expired authorization, changed evidence, and wrong recipient.
  • P2 — Devin packet identity differs from peer delivery. Hosted _evidence() currently derives a UUID-shaped identity from the packet digest, while the authorized Claude/Codex paths render the packet handle. Issue Context: authorize and deliver private packets to Devin roles #908 requires the same packet identity across participants. Render the exact authorized handle used by peer delivery and bind it into retry/durability checks; add a cross-participant identity test.

The legacy hosted-capability migration at this head appears narrowly scoped and the prior formal blocker appears resolved. Preserve that compatibility while fixing these findings. Keep private packet content and authorization details out of public evidence.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Re supplemental authorization-boundary review at 489a460252536f0e49af1690465238b0fcb914d1: acknowledged. Round 6 was scoped by the work order to the hosted-capability compatibility fix only, so the P1 (replace the packet-loader callback with store/connection/handle/policy inputs and call load_authorized() inside the work-order boundary, with synthetic-packet / wrong-account / revoked / changed-evidence / wrong-recipient negatives) and P2 (render the same authorized packet handle as peer delivery and bind it into the retry digest, with a cross-participant identity test) are held for the next work-order round on this same branch; the legacy-capability migration will be preserved.

@jeffhuber

Copy link
Copy Markdown
Contributor

Supplemental context identity finding

Exact head: 489a460252536f0e49af1690465238b0fcb914d1.

  • P2 — hosted context collapses the authoritative work item into the GitHub delivery issue. WorkOrder.issue is an integer GitHub issue used for PR closing and provenance. packet_context() also turns that integer into the context request's work-item identity. Guided sessions preserve tracker-neutral identities such as Jira keys, and their generated work-order source need not contain issue_number, so a context-bearing VinoVoss/Jira session cannot reach hosted Devin with the same authorized packet identity. Bind a separate tracker-neutral context_work_item from trusted session/work-order state for context-bearing orders while retaining the integer GitHub issue for GitHub delivery verification. Preserve backward-compatible context-free serialization. Add tests where the Jira key differs from the GitHub delivery issue and prove repository/work-item/recipient binding remains exact.

…ker-neutral context work item

PacketContext now carries only the protected store, connection name, packet
handle, normalized policy, and backend; _evidence() calls load_authorized()
with a request derived from the order and renders under the exact authorized
handle, the same identity peer Claude/Codex delivery renders. WorkOrder gains
context_work_item for context-bearing orders (a Jira key may differ from the
integer GitHub issue used for PR verification); context-free serialization and
legacy recovery are unchanged.

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Re authorization-boundary P1 (comment 5647438504) — addressed in bd3829b. PacketContext no longer accepts a callable: it carries only (store, name, handle, policy, backend), with the store required to be exactly ContextStore. _evidence() calls load_authorized() itself with a request derived from the trusted order immediately before the provider write, re-checks the returned packet's binding and devin:builder, and renders with render_evidence(packet, context.handle) — the exact authorized handle, matching the Claude/Codex deliver() identity, bound into the dispatch/message input digests. New negatives: synthetic packet (same binding fields, verbatim and changed text), wrong account, revoked, expired, changed recipients, another ticket's handle, store subclass/look-alike/bare inputs, plus a cross-participant identity check.

Re tracker-neutral work item P2 (comment 5647449184) — same commit. WorkOrder.context_work_item is the trusted packet work item for context-bearing orders (work_item property falls back to str(issue)); WorkOrder.issue stays the integer GitHub issue used by _verify. from_manifest(..., context_work_item=) lets a keyed source omit issue_number (a present one must still match). Context-free orders serialize without the field, so legacy bindings/prompts are unchanged. Test: Jira key EXAMPLE-1 on issue 907 — GitHub-issue packet rejected, Jira packet delivered under its handle (identical to the peer deliver() handle), retry digest conflicts on a refreshed handle, collect verifies issue 907/PR 42 and rejects linked_issues 908.

@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: bd3829b4702b251784c82f2f78dee2e679272202
Findings: P0=0, P1=0, P2=0, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: PASS

Summary:

No actionable regressions were identified. Assessment based on static review; tests were not executed.

Findings: none.

@jeffhuber

Copy link
Copy Markdown
Contributor

Supplemental exact-head binding review

Exact reviewed head: bd3829b4702b251784c82f2f78dee2e679272202.

  • P2 — falsey present GitHub issue values are treated as omitted. In WorkOrder.from_manifest, the exception for a tracker-keyed source uses not issue_number. That accepts a present source.issue_number of 0, false, an empty string, or null for an unrelated GitHub delivery issue. The manifest contract and the new comment require every present issue value to match the trusted integer delivery issue; only an actually absent key may use the tracker-neutral exception. Check key presence explicitly, reject every present malformed or nonmatching value, and add regression cases for 0, false, empty, and null.

The three prior authorization and identity findings are resolved at this head, the focused adversarial checks pass, and the Code Mower Codex exact-head audit passed. Preserve those fixes and the context-free compatibility behavior. Run the focused tests and push one corrected head for final audit.

…y may defer to the tracker work item

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Re supplemental binding review P2 (comment 5647549815) — addressed in 6196388. from_manifest now checks key presence explicitly: only "issue_number" not in source (with a context_work_item) uses the tracker-neutral exception; any present value must be a str/int (not bool) whose text equals the trusted integer issue. Regression cases: "908", 908, 0, False, "", None, True, 907.0, [907] all work_order_binding_mismatch; "907"/907 accepted. Context-free behavior is unchanged (the key was already required there).

@jeffhuber

Copy link
Copy Markdown
Contributor

Codex audit (merge-authority lane)

Head SHA: 619638849b32308046342e0d839c58f80ca99edd
Findings: P0=0, P1=0, P2=0, P3=0 (blocker policy: any P0/P1/P2 → BLOCKED)

Codex Audit: PASS

Summary:

No actionable regression was identified in the diff; tests were not executed.

Findings: none.

@jeffhuber

Copy link
Copy Markdown
Contributor

Claude audit (merge-authority lane)

Head SHA: 619638849b32308046342e0d839c58f80ca99edd
Findings: P0=0, P1=0, P2=0, P3=0 (blocker policy: any P0/P1/P2 -> BLOCKED)

Claude Audit: PASS

Summary:

This PR extends the existing Claude/Codex context-delivery contract to Devin (hosted builder/orchestrator/reviewer roles) and adds a new PacketContext mechanism that lets the hosted Devin work-order boundary re-authorize and render private evidence immediately before each paid create/message call. I traced the control flow carefully: evidence/authorization is freshly checked under the store lock before any branch reservation or record write (so rejected/oversized/unauthorized context leaves no dangling reservation and consumes no round), only digests of the dispatch/message input are persisted (never plaintext evidence), required-context failures fail closed to a returned (not raised) UNKNOWN/paused outcome with merge_authority forced false, and legacy context-free work orders keep their pre-existing serialized shape/binding hash for backward compatibility. The capability-declaration and config-migration changes (context: unavailable -> agent_handoff for devin_api_v3, with an explicit legacy-capabilities allowlist for in-memory migration) are consistent across templates, schema, and doctor checks. The accompanying tests are extensive and exercise the injection/impersonation edge cases (synthetic packets, wrong recipients, cross-ticket packets, budget overflow, crash/retry-with-changed-evidence) in ways that match the implementation's actual branching. I did not find a P0/P1/P2 correctness, security, or data-loss defect.

Findings: none.

@jeffhuber
jeffhuber merged commit da475b6 into main Sep 12, 2026
17 checks passed
@jeffhuber
jeffhuber deleted the devin/908-context-packets branch September 12, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Context: authorize and deliver private packets to Devin roles

1 participant