Skip to content

fix(agent-hosts): adopt receiptless cataloged deploys on install/update - #574

Merged
ScriptedAlchemy merged 5 commits into
codex/tracedecay-total-redesign-planfrom
cursor/cursor-plugin-restamp-adopt-d9a4
Aug 21, 2026
Merged

fix(agent-hosts): adopt receiptless cataloged deploys on install/update#574
ScriptedAlchemy merged 5 commits into
codex/tracedecay-total-redesign-planfrom
cursor/cursor-plugin-restamp-adopt-d9a4

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • tracedecay update-plugin restamps a pre-receipt Cursor plugin bundle to the running binary/product version, and install --agent cursor / install --agent cursor --component core --yes --adopt take over a no-receipt bundle (expected owner tracedecay.cursor-desktop.core.v1) instead of failing the recorded by no receipt ownership conflict.
  • Receiptless adoption is gated on explicit authority (review P1 3826034906): a cataloged deploy path alone never grants ownership. The planner adopts a receiptless file only when the bytes are identical to the staged catalog, the path is inside TraceDecay's own host-bundle-stage namespace, the host adapter recognizes legacy first-party provenance in a durable anchor, or the operator passed --yes --adopt. A custom ~/.config/opencode/plugins/tracedecay.ts is refused untouched with a typed conflict naming the --yes --adopt remedy.
  • Receiptless Cursor adoption sweeps retired artifacts (review P1 3826034908): after the component-set receipt commits, the bounded legacy inventory (rules/tracedecay-memory.mdc, rules/tracedecay-memory-digest.mdc, retired skill dirs) is removed — content-gated and only from a bundle whose own manifest anchor proves tracedecay ownership — on install, update-plugin, and repair, so later updates and uninstall see a clean owned bundle.
  • Codex hook auto-trust and the byte-identical staged hand-over journeys (Codex, Claude, Kimi) are unregressed.

Motivation

The live Cursor bundle at .cursor/plugins/local/tracedecay/ predates host-bundle v2 receipts. The planner's old adoption boundary let Repair adopt any receiptless cataloged path, Install only byte-identical ones, and Update nothing — and cataloged artifacts restamp versions/binary paths each release, so the live bundle could never converge: every install/update-plugin hit the typed OwnershipConflict before the CLI --adopt gate could matter. Review then flagged the first fix attempt's inverse hazard: cataloged_ownership_marker is synthesized from the current manifest, so path-only adoption would silently replace an operator's own file at a cataloged path, and committed receipts drop their backups.

Changes

  • crates/tracedecay-agent-hosts/src/agents/host_bundle_v2.rsadopts_pre_receipt_artifact requires the cataloged path AND an explicit authority (byte identity / first-party stage namespace / adapter-recognized legacy provenance / operator --yes --adopt), for Install, Update, and Repair alike; Uninstall never adopts. HostBundleLifecycleRequestV1.adopt_receiptless and HostComponentSetLifecycleRequestV1.explicit_adoption carry the operator authority; HostComponentSetRegistrationV1::receiptless_component_provenance (default fail-closed false) carries the adapter's. Preview and confirmed execute resolve adoption through the same adapter so plans agree. The refusal message names the contested path and the --yes --adopt remedy.
  • crates/tracedecay-agent-hosts/src/agents/cursor.rsreceiptless_component_provenance recognizes exactly the durable first-party anchors (plugin-dir manifest naming tracedecay; the versioned native-extension package.json); sweep_retired_cursor_plugin_artifacts performs the bounded, ownership-gated retired-inventory cleanup after receipts commit.
  • crates/tracedecay-agent-hosts/src/agents/host_component_registration.rs — the catalog registration authority delegates provenance to the Cursor recognizer; every other host stays on the fail-closed default.
  • src/agent_cmd.rs, src/main.rs--adopt threads from the CLI through install, update-plugin, reinstall, and the --component routes into the set request. The planner is the single adoption boundary: the CLI preview gate that re-litigated adoptions was deleted with its adopted_relative_paths helper (dry-run still labels unrecorded-path mutations adopt). The Cursor retired-artifact sweep runs after every non-uninstall Cursor apply.

Test plan

  • cargo test -p tracedecay-agent-hosts --lib — 720 passed, 0 failed. New/updated: receiptless_adoption_requires_provenance_or_explicit_authority (refusal matrix + staged-namespace and Uninstall boundaries), lifecycle_ops_converge_cataloged_pre_receipt_artifacts_only_with_adoption, cursor_transaction_refuses_unrecognized_receiptless_bytes_without_adoption (Install and Update refuse custom bytes untouched; explicit adopt takes over), cursor_component_transaction_takes_over_a_pre_receipt_bundle (provenance-driven restamp, receipts Doctor-Current), receiptless_provenance_requires_a_first_party_anchor, retired_artifact_sweep_is_bounded_and_ownership_gated, plus the full agents::codex:: auto-trust suite.
  • cargo test --bin tracedecay -- agent_cmd:: — all adoption/sweep tests pass: explicit_component_repair_refuses_adoption_without_the_adopt_flag, component_apply_refuses_receiptless_bytes_without_adoption_authority, default_component_apply_honors_explicit_adoption_authority, cursor_adoption_sweeps_retired_artifacts_and_preserves_user_files (now also covers the Update/update-plugin journey), kimi_native_activated_retry_tracks_staged_source. The 6 remaining failures (codex_native_*, codex_core_rollback_*, kimi_canonical_*, opencode_core_*) fail identically on the unmodified base in this VM and are unrelated.
  • cargo test --test host_bundle_acceptance — 18 passed.
  • cargo check --workspace --all-features --profile test clean; cargo clippy -p tracedecay-agent-hosts --lib --all-features no new warnings.
  • Tested manually (not run: no access to the live Mac per task constraints)

Checklist

  • No secrets, credentials, or .env files included
  • Breaking changes documented (none released: the request structs and registration trait are branch-local contracts changed in place)
Open in Web Open in Cursor 

@changeset-bot

changeset-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4fc06f7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e70ca76362

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/tracedecay-agent-hosts/src/agents/host_bundle_v2.rs
Comment thread crates/tracedecay-agent-hosts/src/agents/host_bundle_v2.rs
@cursor
cursor Bot force-pushed the cursor/cursor-plugin-restamp-adopt-d9a4 branch from e70ca76 to 8c5f8f3 Compare August 20, 2026 23:07
A live pre-receipt bundle (deployed before host-bundle receipts existed)
could never converge: Update refused all receiptless artifacts and
Install adopted only byte-identical ones, while cataloged artifacts
restamp the product version and binary path on every release. On such
installs `tracedecay install --agent cursor` (with or without
--component core --yes --adopt) and `update-plugin` both failed with
'existing file is not owned by this component (observed ownership
marker recorded by no receipt)'.

Install, Update, and Repair now share the same adoption boundary: a
receiptless observation at the component's own cataloged deploy path is
adopted, backing divergent bytes up before replacing them. Receipt-
claimed paths keep the unmodified marker-equality security boundary,
foreign markers still conflict, and Uninstall stays fail-closed. The
explicit --component route still demands --yes --adopt before claiming
unrecorded files.

Co-authored-by: Zack Jackson <ScriptedAlchemy@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/cursor-plugin-restamp-adopt-d9a4 branch from 8c5f8f3 to 3ecb5a0 Compare August 20, 2026 23:52
@ScriptedAlchemy
ScriptedAlchemy merged commit 8c82f0d into codex/tracedecay-total-redesign-plan Aug 21, 2026
4 checks passed
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.

2 participants