Implement pin-aware sync gate for Codex Conductor extension pinning#23
Draft
JonahBraun wants to merge 11 commits into
Draft
Implement pin-aware sync gate for Codex Conductor extension pinning#23JonahBraun wants to merge 11 commits into
JonahBraun wants to merge 11 commits into
Conversation
Consistent brace style across extensionVersionChecker, SCMManager, and versionChecker tests. Replace unsafe `as any` cast in getCurrentExtensionVersion with narrower type assertion.
Write syncCompletedAt timestamp to workspaceState after a successful sync. The Codex Conductor observes this via IStorageService to detect mid-session changes to pinnedExtensions in metadata.json.
Foundation layer for extension pinning sync gate: - PinnedExtensionEntry interface and PinnedExtensions type - isPinnedExtensions() type guard for validation - readLocalPinnedExtensions() reads pins from metadata.json - findPinMismatches() compares running vs pinned versions - extensionDisplayName() formats extension IDs for display - Non-modal notification with "Reload Codex" action
Add checkPinnedExtensionsForSync() — checks pin mismatches, respects
the 2-hour notification cooldown, and returns { canSync, pinnedIds }.
Modify checkMetadataVersionsForSync() to call pin check first. Pinned
extensions override requiredExtensions: if an extension is pinned, its
requiredExtensions check is skipped so the pin version takes precedence.
Add handleRemotePinValidation() which writes remote pins to workspaceState for Conductor visibility, then delegates to the shared checkPinnedExtensionsForSync utility. In syncChanges(), call remote pin validation before merge. Skip requiredExtensions version checks for pinned extension IDs so the pin version takes precedence over the ratchet.
Cover findPinMismatches and checkPinnedExtensionsForSync: - Detects mismatched versions between running and pinned - Returns empty when all versions match - Shows non-modal notification and blocks sync on mismatch - Reloads window when user clicks "Reload Codex"
…xtensions Update version checking logic to: - Use exact string equality for pinned version mismatches, ensuring prerelease affixes (like -pr123) are correctly enforced. - Implement checkRequiredVersion to explicitly handle malformed required versions (fail-open) and missing installed versions (fail-closed). - Ignore prerelease affixes during legacy requiredExtensions checks to prevent accidental blocking of development builds. - Add integration tests for malformed metadata and missing version scenarios.
…reload UX
Frontier's "Reload Codex" button called workbench.action.reloadWindow which
bypasses the Conductor's authoritative reload (forceProfile), risking a
profile mismatch loop. The notification is now info-only. The Conductor
handles all reload UX via hostService.reload({ forceProfile }).
checkMetadataVersionsForSync was passing undefined for remotePins, falling through to stale metadata.json on disk. After a conductor profile switch, disk still has the old pin while storage has the new one — blocking sync indefinitely. The post-fetch check in handleRemotePinValidation also read from the raw remote git blob, which is stale when a prior sync was blocked. Both now use the conductor's getEffectivePinnedExtensions command, which reads from IStorageService (always up-to-date). The post-fetch path writes fresh remote pins to workspaceState first so the conductor sees them before validating.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prevent sync when pinned extension versions don't match the running versions, and signal sync completion so the Codex Conductor can detect mid-session pin changes.
See architecture docs:
Changes
syncCompletedAttimestamp to workspaceState after successful sync for Conductor observabilityPinnedExtensionstypes, type guard, and mismatch detection utilitiescheckPinnedExtensionsForSync()with 2-hour notification cooldowncheckMetadataVersionsForSync()— pins overriderequiredExtensionshandleRemotePinValidation()in SCMManager to write remote pins to workspaceState and gate syncrequiredExtensionsversion checks for pinned extension IDsTest plan (current stable Codex — no Conductor)
requiredExtensionsversion checks still work as before (regression)pnpm test— new pinning.test.ts covers mismatch detection and notification behaviorTest plan (Codex beta with Conductor)
requiredExtensionsratchet checkssyncCompletedAtis written to workspaceState after successful sync; Conductor re-evaluates pinsremotePinnedExtensionsis written to workspaceState during remote metadata check, even when sync aborts before merge