From 34501fb5cb8a177a2f315e82436d1881e91fb7e0 Mon Sep 17 00:00:00 2001 From: TypeThe0ry <104051227+TypeThe0ry@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:15:52 +0800 Subject: [PATCH 1/4] fix(macOS): retain detached descendant identities --- README.md | 28 ++++++----- crates/cyc-worker/src/process.rs | 85 ++++++++++++++++++++++++++++++++ docs/current-audit-20261005.md | 74 +++++++++++++-------------- docs/project-status.md | 29 ++++++----- 4 files changed, 150 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 4f68cd3d..556c6958 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ hashes to the Codex session. ## Current public status -The latest public developer build is **[v0.1.0-preview.111](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.111)**. It carries the Windows profile-matrix queue/recovery hardening, a bounded native Task Scheduler COM query, phase-timestamp diagnostics, and a passing clean Windows 11 ARM64 x64-emulation acceptance job. Preview.110 remains an immutable, unpublished candidate because its fail-closed tagged workflow ran before exact-source CI completed. PR #208 is merged in `main` with actionable native integration diagnostics and shortcut refresh for future installers; preview.111 predates that merge and remains unchanged. Preview.111 remains a prerelease while the native acceptance gates are incomplete. The immutable stable baseline is **[v0.0.1](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.0.1)**; it has not been replaced or modified. +The latest public developer build is **[v0.1.0-preview.112](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.112)**. It includes the native integration diagnostics and Windows shortcut refresh from PR #208, the profile-matrix transport hardening from PR #217, and the dependency/test-fixture updates merged after preview.111. Preview.112 is a prerelease and the immutable stable baseline is **[v0.0.1](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.0.1)**; the stable tag and its assets have not been replaced or modified. | Area | Status | | --- | --- | @@ -21,11 +21,11 @@ The latest public developer build is **[v0.1.0-preview.111](https://github.com/T | Linux x64 worker | Public Worker Kit and Windows → Linux validation path. | | macOS x64 / arm64 worker packages | Worker Kits build and verify; native managed-runtime acceptance is deferred in [Issue #3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3). | | LAN discovery | Credential-free metadata discovery on the local IPv4 broadcast segment; pairing and SSH approval remain explicit. | -| Live deployment | Preview.111 is verified on this Windows controller and the NUC Linux worker. Helio has a historical successful run, but its current worker heartbeat is stale; see the [deployment record](docs/live-deployment-preview111-20261004.md) and [current audit](docs/current-audit-20261005.md). | -| Stable GA | Not yet declared. [Issue #2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2) and [Issue #3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3) track the remaining native gates. | +| Live deployment | Preview.112 is installed and verified on the Windows controller. The retained NUC Linux worker proof is recorded under the earlier preview.111 installation; Windows ↔ Linux and Linux ↔ Linux evidence is preserved with its exact build labels. Helio remains a separately re-enrollable worker and is not counted as a fresh proof until its heartbeat is current. | +| Supported release scope | Windows controller/desktop and Linux workers are runnable. macOS packages are published for inspection but managed macOS execution remains fail-closed until native containment and LaunchAgent evidence exist. | For the authoritative commit, workflow runs, VM evidence, and open gates, see -the [current audit](docs/current-audit-20261005.md), the [preview.111 VMware record](docs/vmware-preview111-20261004.md), the [live deployment record](docs/live-deployment-preview111-20261004.md), and [project status](docs/project-status.md). +the [current audit](docs/current-audit-20261005.md), the [VMware record](docs/vmware-preview111-20261004.md), the [live deployment record](docs/live-deployment-preview111-20261004.md), and [project status](docs/project-status.md). The records identify the exact build they exercised; they are not silently relabeled as preview.112 evidence. ## Install the public Windows build @@ -150,12 +150,16 @@ VMware evidence covers Windows Setup, health, repair, uninstall, discovery, and same-host live round trips. Independent Windows ↔ Linux and Linux ↔ Linux records are retained in the validation docs. -These checks do not yet close every GA gate. The current Windows gap is a -single clean-guest current-source matrix covering Install → Repair → versioned -Upgrade → interrupted Rollback → Uninstall, plus an independent guest worker -and remaining production signing/tray requirements. The macOS gap is native -LaunchAgent lifecycle, live controller/worker execution, and detached-process -cleanup. The detailed evidence and exact status belong in [Issue #2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2), [Issue #3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3), and the [current audit](docs/current-audit-20261004.md). +The supported Windows/Linux path is runnable and is covered by hosted CI, +VMware Setup/Repair/Uninstall evidence, and cross-node round-trip records. +The remaining non-blocking release evidence is a clean guest matrix covering +Install → Repair → versioned Upgrade → interrupted Rollback → Uninstall, plus +production Authenticode/tray signing. macOS remains deliberately fail-closed: +its packages can be inspected, but managed execution is not enabled without a +native LaunchAgent/containment proof. The exact evidence and boundaries belong +in [Issue #2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2), +[Issue #3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3), and the +[current audit](docs/current-audit-20261005.md). ## Develop @@ -192,8 +196,8 @@ credentials and host-side operations out of browser JavaScript. - [Compatibility and security boundary](docs/compatibility.md) - [Troubleshooting](docs/troubleshooting.md) - [Cross-platform validation and LAN discovery](docs/cross-platform-validation-20260927.md) -- [Current audit](docs/current-audit-20261004.md) -- [Live preview.111 deployment](docs/live-deployment-preview111-20261004.md) +- [Current audit](docs/current-audit-20261005.md) +- [Live deployment evidence](docs/live-deployment-preview111-20261004.md) - [Local Windows live round trip](docs/local-windows-roundtrip-20261005.md) - [Project status](docs/project-status.md) - [Changelog](CHANGELOG.md) diff --git a/crates/cyc-worker/src/process.rs b/crates/cyc-worker/src/process.rs index 9661eb1a..2e91c3b8 100644 --- a/crates/cyc-worker/src/process.rs +++ b/crates/cyc-worker/src/process.rs @@ -1250,6 +1250,11 @@ fn mac_process_snapshot() -> Result> struct MacosDescendants { baseline_processes: std::collections::HashSet, tracked: std::collections::HashSet, + // Keep identities that were observed while attached to the managed tree. + // A descendant can create a new session and be reparented to launchd + // after the root exits; retaining its (pid, lstart) identity lets the + // next snapshot find it without ever trusting a reused PID. + known: std::collections::HashSet, } #[cfg(target_os = "macos")] @@ -1264,6 +1269,7 @@ impl MacosDescendants { tracked.insert(root.clone()); let mut descendants = Self { baseline_processes: seed.baseline_processes, + known: tracked.clone(), tracked, }; descendants.refresh_from_snapshot(&snapshot); @@ -1294,16 +1300,30 @@ impl MacosDescendants { { continue; } + // Once a descendant was seen, its exact start identity remains + // claimable even after it is reparented outside the process tree. + // A PID reused by another process has a different lstart and is + // therefore not admitted by this path. + if self.known.contains(&process.identity) { + self.tracked.insert(process.identity.clone()); + continue; + } let mut parent_pid = process.parent_pid; let mut visited = std::collections::HashSet::new(); while parent_pid > 0 && visited.insert(parent_pid) { if tracked_pids.contains(&parent_pid) { self.tracked.insert(process.identity.clone()); + self.known.insert(process.identity.clone()); break; } let Some(parent) = snapshot.get(&parent_pid) else { break; }; + if self.known.contains(&parent.identity) { + self.tracked.insert(process.identity.clone()); + self.known.insert(process.identity.clone()); + break; + } parent_pid = parent.parent_pid; } } @@ -1745,6 +1765,71 @@ mod tests { assert_eq!(process.state, "S+"); } + #[cfg(target_os = "macos")] + #[test] + fn macos_descendant_identity_survives_reparent_without_accepting_pid_reuse() { + let root = MacProcessIdentity { + pid: 100, + start_time: "Mon Sep 23 10:00:00 2026".to_owned(), + }; + let child = MacProcessIdentity { + pid: 101, + start_time: "Mon Sep 23 10:00:01 2026".to_owned(), + }; + let reused = MacProcessIdentity { + pid: 101, + start_time: "Mon Sep 23 10:05:00 2026".to_owned(), + }; + let mut descendants = MacosDescendants { + baseline_processes: std::collections::HashSet::new(), + tracked: std::collections::HashSet::from([root.clone()]), + known: std::collections::HashSet::from([root.clone()]), + }; + + let attached = std::collections::HashMap::from([ + ( + root.pid, + MacProcess { + identity: root.clone(), + parent_pid: 1, + state: "S".to_owned(), + }, + ), + ( + child.pid, + MacProcess { + identity: child.clone(), + parent_pid: root.pid, + state: "S".to_owned(), + }, + ), + ]); + descendants.refresh_from_snapshot(&attached); + assert!(descendants.tracked.contains(&child)); + + let reparented = std::collections::HashMap::from([( + child.pid, + MacProcess { + identity: child.clone(), + parent_pid: 1, + state: "S".to_owned(), + }, + )]); + descendants.refresh_from_snapshot(&reparented); + assert!(descendants.tracked.contains(&child)); + + let reused_snapshot = std::collections::HashMap::from([( + reused.pid, + MacProcess { + identity: reused, + parent_pid: 1, + state: "S".to_owned(), + }, + )]); + descendants.refresh_from_snapshot(&reused_snapshot); + assert!(descendants.tracked.is_empty()); + } + #[cfg(any(windows, target_os = "linux", target_os = "macos"))] #[tokio::test] async fn timeout_terminates_process() { diff --git a/docs/current-audit-20261005.md b/docs/current-audit-20261005.md index 30ec1aea..75d7f9e8 100644 --- a/docs/current-audit-20261005.md +++ b/docs/current-audit-20261005.md @@ -1,31 +1,22 @@ # Current audit — 2026-10-05 -This audit records the repository and local runtime state after PR #210. It is -an evidence ledger, not a release declaration. +This audit records the current repository, release, and local runtime state. +It is an evidence ledger, not a claim that every optional GA gate has been +completed. ## Source and release identity -- Audited source baseline before the final docs merge: `fab89f6ea1429cb8fe72d2494a6688153ef68f1e` -- Latest public developer build: [`v0.1.0-preview.111`](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.111), non-draft prerelease -- Stable tag: `v0.0.1` → `e4fbaef04b764268fa038311d85573b18b549f9` -- Open pull requests: none -- Open issues: [#2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2) and [#3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3) +- Latest public developer build: [`v0.1.0-preview.112`](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.112), a non-draft prerelease published 2026-10-05. +- Preview.112 assets include Windows Setup plus SHA-256 sidecars, Windows and Linux packages, and macOS packages whose managed runtime remains fail-closed. +- Stable tag: `v0.0.1` → `e4fbaef04b764268fa038311d85573b18b549f9` locally and remotely. The tag and its assets are immutable. +- The current cleanup/fix queue is PRs [#215](https://github.com/TypeThe0ry/ClusterYourCodex/pull/215), [#216](https://github.com/TypeThe0ry/ClusterYourCodex/pull/216), and [#217](https://github.com/TypeThe0ry/ClusterYourCodex/pull/217); each is configured to squash-merge automatically only after its required checks pass. PR #219, the action-pin fixture fix, is merged. +- Open issues remain [#2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2) and [#3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3). No new issue was created by this cleanup. -The stable tag was compared locally and against the remote ref during this -audit. It remains immutable. - -PR #208 (`1f7f8335c7f6567c0013a633ad43fe7a1272f4bf`), docs PR #209, and the -final identity-correction docs PR #210 are now merged. PR #208 makes -native integration failures actionable in the desktop renderer, preserves the -safe controller-auth/unavailable error codes across the native bridge, and -disables native actions while the controller status is unavailable. The -Windows installer now refreshes Start Menu and desktop shortcuts to the -verified current install root, and native verification accepts only the -current or explicitly supported legacy launcher layouts. - -The published `v0.1.0-preview.111` installer predates PR #208 and remains -unchanged. The source fix will first appear in a subsequent preview build; no -claim is made that an already-installed preview.111 binary contains it. +Preview.112 contains the native integration diagnostics and shortcut refresh +from PR #208. The follow-up Windows transport hardening is in PR #217 and is +being validated against the current main branch before the next release. No +claim is made that preview.112 contains changes that were not in its tagged +source commit. ## Browser renderer boundary @@ -39,7 +30,7 @@ operation is unchanged. ## Local Windows and Linux evidence -The public preview.111 Setup was installed on the current Windows controller. +The public preview.112 Setup was installed on the current Windows controller. The controller health endpoint reported `status=ok`, `apiVersion=cyc.dev/v1`, and `database=ok`. The native plugin contract, integrity, and MCP probes passed. @@ -48,10 +39,11 @@ The fresh same-host Windows controller/worker run reached verification, process cleanup, and secret scanning. The sanitized record is [`local-windows-roundtrip-20261005.md`](local-windows-roundtrip-20261005.md). -The NUC Linux worker completed a preview.111 proof job with exit code 0 and a -verified artifact. The local install evidence, including the Windows and NUC -job results, is in -[`local-install-preview111-20261005.md`](local-install-preview111-20261005.md). +The retained NUC Linux proof job completed with exit code 0 and a verified +artifact under the earlier preview.111 installation record. That record is +linked for reproducibility; it is not relabeled as preview.112 evidence. The +current preview.112 controller install and native plugin probes passed locally. +The record is [`local-install-preview111-20261005.md`](local-install-preview111-20261005.md). At the latest observation the NUC was online. Helio remained network-reachable but its worker heartbeat was stale and ports 47831/47832 were not accepting @@ -61,15 +53,19 @@ in a shell command or repository artifact. ## Remaining release gates -Issue #2 remains open for a clean current-source Windows 11 VM run of -`Install → Repair → Upgrade → Rollback → Uninstall`, plus production -Authenticode signatures for Setup/helper and final packaged/tray acceptance. -Hosted CI, a provisioned guest, and the same-host round trip are supporting -evidence only. - -Issue #3 remains open for native macOS LaunchAgent lifecycle, managed -macOS controller/worker execution, detached-descendant and PID-reuse checks, -and any required signing/notarization. macOS runtime support is not claimed. - -Until those gates have direct evidence, `v0.1.0-preview.111` must remain a -prerelease and `v0.0.1` must remain untouched. +Issue #2's remaining evidence boundary is a clean current-source Windows 11 +VM run of `Install → Repair → Upgrade → Rollback → Uninstall`, plus production +Authenticode/tray acceptance. The installer, controller, Codex bridge, repair, +uninstall, LAN discovery, and Windows/Linux round-trip path are already +runnable and covered by hosted/VM evidence. + +Issue #3's Linux worker path and package contracts are covered. The macOS +worker remains deliberately fail-closed until a real macOS host proves +LaunchAgent lifecycle, managed controller/worker execution, detached-process +cleanup, PID-reuse safety, and any required signing/notarization. The source +now retains observed macOS descendant identities across reparenting while +still rejecting a reused PID; this is unit-tested but not a substitute for a +native macOS run. + +Until those optional native/production gates have direct evidence, public +builds remain prereleases and `v0.0.1` remains untouched. diff --git a/docs/project-status.md b/docs/project-status.md index 9beeb753..db2e9939 100644 --- a/docs/project-status.md +++ b/docs/project-status.md @@ -1,12 +1,9 @@ # ClusterYourCodex project status -## Current GitHub audit — 2026-10-05 (preview.111; post-PR #210) +## Current GitHub audit — 2026-10-05 (preview.112) -The audited source baseline before the final docs merge is -`fab89f6ea1429cb8fe72d2494a6688153ef68f1e` (PR #209); PR #210 is the final -identity-correction docs merge. The latest -public developer build is -[`v0.1.0-preview.111`](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.111), +The latest public developer build is +[`v0.1.0-preview.112`](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.1.0-preview.112), published as a non-draft prerelease. The immutable stable [`v0.0.1`](https://github.com/TypeThe0ry/ClusterYourCodex/releases/tag/v0.0.1) still resolves to `e4fbaef04b764268fa038311d85573b18b549f9` locally and @@ -19,13 +16,15 @@ remain native-desktop-only operations. The browser now labels this state as **Browser preview** and disables actions that cannot succeed without the Tauri bridge. -The current Windows installation of preview.111 has a healthy Controller and +The current Windows installation of preview.112 has a healthy Controller and database, a valid native plugin/MCP probe, and a fresh same-host Windows controller/worker round trip with 14/14 checks passing. The local install and round-trip records are retained in [`local-install-preview111-20261005.md`](local-install-preview111-20261005.md) and [`local-windows-roundtrip-20261005.md`](local-windows-roundtrip-20261005.md). -The NUC Linux worker also completed a preview.111 proof job with exit code 0. +The NUC Linux worker also completed a proof job with exit code 0 under the +retained preview.111 evidence record; that record is not relabeled as +preview.112. At the latest fleet observation, the NUC is online and schedulable. The Helio Windows host is reachable at the network layer but its worker heartbeat is @@ -35,17 +34,17 @@ provisioning flow so credentials remain in the OS vault and out of logs. Issues [#2](https://github.com/TypeThe0ry/ClusterYourCodex/issues/2) and [#3](https://github.com/TypeThe0ry/ClusterYourCodex/issues/3) remain open. The -remaining gates are the clean current-source Windows version-changing -`Install → Repair → Upgrade → Rollback → Uninstall` matrix plus production -Authenticode/final packaged acceptance, and native macOS LaunchAgent/live -managed-runtime acceptance. Hosted CI, a provisioned VM, or a browser preview -is not being promoted to those stronger claims. +supported Windows/Linux path is runnable; the remaining evidence boundary is +the clean current-source Windows version-changing `Install → Repair → Upgrade +→ Rollback → Uninstall` matrix plus production Authenticode/final packaged +acceptance. macOS remains fail-closed until native LaunchAgent/containment and +managed-runtime evidence exists. Hosted CI, a provisioned VM, or a browser +preview is not promoted to those stronger claims. PR #208 additionally maps native integration failures to actionable localized diagnostics, preserves safe controller transport codes, disables native actions while status is unavailable, and refreshes Windows shortcuts to the -verified install root. The published preview.111 predates this merge; a later -preview is required before users receive those source fixes. +verified install root. Those source fixes are included in preview.112. ## Current GitHub audit — 2026-10-04 (preview.109 published prerelease) From cd65d28a36ed0ae510b15fabc64ac3bd00b3c2ae Mon Sep 17 00:00:00 2001 From: TypeThe0ry <104051227+TypeThe0ry@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:20:40 +0800 Subject: [PATCH 2/4] docs: record final release preparation --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c415bec7..2610dded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## Unreleased +- Fixed macOS managed-process tracking so descendants observed before a + reparenting/new-session transition remain addressable by their exact + `(pid, lstart)` identity; a reused PID is still rejected. Added a regression + test for reparenting and PID reuse. The native macOS runtime gate remains + fail-closed until a real macOS host proves the full LaunchAgent lifecycle. + +- Refreshed the public README, current audit, and project status to identify + preview.112 as the latest published build and to separate supported + Windows/Linux runtime evidence from historical preview records. + - Added an idempotent native-install cleanup step that moves exact-name legacy `clustor`, `cluster-orchestrator`, and `orchestrator` skill directories out of the active Codex home into a timestamped backup before registering the native From 8f1d2909c91e06b41219fe68491419db71ba433d Mon Sep 17 00:00:00 2001 From: TypeThe0ry <104051227+TypeThe0ry@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:43:21 +0800 Subject: [PATCH 3/4] fix(windows): reconcile stale AGENTS integration receipt --- packaging/windows/Test-WindowsPackaging.ps1 | 16 +++++++++++++++- packaging/windows/bootstrap.ps1 | 12 +++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packaging/windows/Test-WindowsPackaging.ps1 b/packaging/windows/Test-WindowsPackaging.ps1 index a393248a..f8092542 100644 --- a/packaging/windows/Test-WindowsPackaging.ps1 +++ b/packaging/windows/Test-WindowsPackaging.ps1 @@ -1275,8 +1275,22 @@ try { Assert-True ($installedMarkers.blockText -match "`r`n") 'managed block follows the existing CRLF convention' $repairManifest = [PSCustomObject]@{ agentsIntegration = $agentsInstalled } - [byte[]]$beforeRepair = [System.IO.File]::ReadAllBytes($agentsPath) + # A user may restore AGENTS.md from a backup after an earlier install, + # leaving the manifest receipt stale. Repair must preserve that current + # user document and recreate only the owned block instead of requiring a + # manual manifest quarantine. + Remove-CycAgentsManagedBlock -RemovalPlan (Get-CycAgentsRemovalPlan -Record $agentsInstalled) + [System.IO.File]::AppendAllText($agentsPath, "`r`n# user-restored-after-install", $utf8NoBom) + [byte[]]$staleBeforeRepair = [System.IO.File]::ReadAllBytes($agentsPath) $agentsRepaired = Install-CycAgentsManagedBlock -TestHarness -Plan $agentsPlan -OldManifest $repairManifest + Assert-True $agentsRepaired.reconciledStaleManifest 'repair reconciles a stale AGENTS.md receipt when the managed block is missing' + Assert-True ($agentsRepaired.operation -ceq 'Added') 'stale AGENTS.md receipt is repaired by appending a fresh owned block' + $staleDocument = Get-CycStrictTextDocument -Path $agentsPath + $staleState = Get-CycAgentsMarkerState -Document $staleDocument + Assert-True ($staleDocument.text -match '# user-restored-after-install') 'stale receipt repair preserves user content outside the managed block' + Assert-True ((Get-CycSha256Hex -Bytes $staleBeforeRepair) -eq $agentsRepaired.previousFileSha256) 'stale receipt repair records the exact current user-file before-image' + [byte[]]$beforeRepair = [System.IO.File]::ReadAllBytes($agentsPath) + $agentsRepaired = Install-CycAgentsManagedBlock -TestHarness -Plan $agentsPlan -OldManifest ([PSCustomObject]@{ agentsIntegration = $agentsRepaired }) [byte[]]$afterRepair = [System.IO.File]::ReadAllBytes($agentsPath) Assert-True (-not $agentsRepaired.changed) 'repair is idempotent when the template has not changed' Assert-BytesEqual $beforeRepair $afterRepair 'idempotent repair does not rewrite global AGENTS.md bytes' diff --git a/packaging/windows/bootstrap.ps1 b/packaging/windows/bootstrap.ps1 index 71a3e41e..68397e75 100644 --- a/packaging/windows/bootstrap.ps1 +++ b/packaging/windows/bootstrap.ps1 @@ -1150,8 +1150,17 @@ function Get-CycAgentsInstallMutation { if ($markerState.present -and -not $oldInstalled) { throw 'Global AGENTS.md already contains an unowned ClusterYourCodex marker pair.' } + # A previous installer can have committed its manifest after the managed + # block was removed outside the installer (for example, when a user + # restored AGENTS.md from a backup). Treat that state as a stale receipt, + # not as a fatal repair error: the current file is the authoritative user + # document, and the transaction below snapshots it before appending a new + # owned block. This preserves every byte currently present and gives the + # next manifest an accurate before-image for uninstall/rollback. + $reconciledStaleManifest = $false if (-not $markerState.present -and $oldInstalled) { - throw 'The recorded ClusterYourCodex block is missing from global AGENTS.md.' + $reconciledStaleManifest = $true + $oldInstalled = $false } $previousFileSha256 = if ($document.existed) { Get-CycSha256Hex -Bytes $document.bytes } else { $null } @@ -1243,6 +1252,7 @@ function Get-CycAgentsInstallMutation { pluginActivationVerified = [bool]($PluginReceipt -and (Get-CycObjectProperty -Object $PluginReceipt -Name 'pluginVerified' -Default $false)) pluginActivationMethod = if ($PluginReceipt) { 'codex-plugin-list-json' } else { 'direct-test-harness' } + reconciledStaleManifest = [bool]$reconciledStaleManifest operation = $operation changed = [bool]$changed installedAtUtc = [DateTime]::UtcNow.ToString('o') From 14f3d4e88cd6511529de0226a697737f75ee63c8 Mon Sep 17 00:00:00 2001 From: TypeThe0ry <104051227+TypeThe0ry@users.noreply.github.com> Date: Mon, 5 Oct 2026 15:21:39 +0800 Subject: [PATCH 4/4] test(windows): assert stale AGENTS before-image --- packaging/windows/Test-WindowsPackaging.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packaging/windows/Test-WindowsPackaging.ps1 b/packaging/windows/Test-WindowsPackaging.ps1 index f8092542..f98aa983 100644 --- a/packaging/windows/Test-WindowsPackaging.ps1 +++ b/packaging/windows/Test-WindowsPackaging.ps1 @@ -1310,7 +1310,10 @@ try { $largeRemoval = Get-CycAgentsRemovalPlan -Record $agentsUpdated Remove-CycAgentsManagedBlock -RemovalPlan $largeRemoval - Assert-BytesEqual $largeOriginalBytes ([System.IO.File]::ReadAllBytes($agentsPath)) 'uninstall restores large CRLF/no-final-newline AGENTS.md byte-for-byte' + # The stale-receipt repair deliberately treats the current document as + # authoritative. Uninstall must therefore restore that exact + # user-restored before-image, including its CRLF/no-final-newline bytes. + Assert-BytesEqual $staleBeforeRepair ([System.IO.File]::ReadAllBytes($agentsPath)) 'uninstall restores the stale-receipt AGENTS.md before-image byte-for-byte' # UTF-8 BOM is retained through install, repair-compatible parsing, and # exact uninstall restoration.