Repository navigation
fix(startup): auto-disable a migrated preset row a plugin registers again - #819
Merged
yaojin3616 merged 1 commit intoOct 29, 2026
Conversation
…gain When an installed plugin registers a preset at runtime and the same id also exists as a legacy directory, the migration row and the registration collide in the registry and abort every startup, and the row regenerates nothing only while it exists, so relaunching never clears it. Extract 'Duplicate agent preset: <id>' from the harness attempt logs, disable that one migrated row in place (a disabled row neither mounts nor joins the startup audit, and existingIds still sees it as migrated), then relaunch — the plugin's own registration remains the single live preset. Fixes dataelement#814
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.
Motivation & Context
A plugin that registers a preset at runtime (
ctx.agentPresets.register({ id: 'aitoearn', ... })) and also ships the old-form preset directory ($DSH_HOME/.agent-presets/aitoearn/) makes every desktop startup abort:migrateLegacyAgentPresets()converts the directory into an inlinepreset-aitoearnrow incordis.patch.ymlwithout knowing the runtime registration exists, the registry rejects the duplicate id (error agent-preset: Error: Duplicate agent preset: aitoearn), the row is required, and startup fails. Relaunching cannot clear it — the migration'sexistingIdscheck keeps the row in place forever. Reported in #814 with a manual workaround (hand-addingdisabled: trueto the generated row), which this PR automates.Description & Review Guide
extractDuplicateAgentPresetId()inharness-runtime.tsreads the duplicate id from the latest stderr attempt logs (same shape as the existingextractDuplicateLoaderEntryId/extractSlotConflictName);disableMigratedLegacyPreset()inlegacy-preset-migration.tslocates that one row inside the# dsh-desktop legacy presetsblock and insertsdisabled: trueat the entry's field indent (both the- id:built-in shape and the- insert: / - id:plugin shape), atomically; the plugin-recovery loop inindex.tschecks this before blaming plugins, auto-disables at most once per id per session, and relaunches vialaunchWithFreshEvidence().auditRowsskipsentry.disabled), whileexistingIdsstill matches the retainedpreset-<id>line so the migration never rewrites or duplicates it. The plugin's own runtime registration stays the single live preset — the legacy copy steps aside instead of the user's plugin being quarantined. Rows outside the migration block are never touched, already-disabled rows are left alone, and a non-matching or missing row leaves the file unchanged so the existing recovery flow takes over.disableMigratedLegacyPreset(entry fields end at the next-row at the entry indent) and the one-shot-per-id session set, which prevents a relaunch loop when the duplicate comes from something other than a migrated row.The tests cover: id extraction from attempt logs (stderr-only, latest attempt); disabling only the named row in both shapes; idempotency (no second
disabled:); and rows outside the block being ignored. Migration and recovery suites pass (32); the 39 office/ppt/docx template failures reproduce identically on a clean checkout of main and are unrelated.Fixes #814