fix: resolve 3 bugs (#3366, #3272, #3222)

- shell-env: detect Git Bash via MSYSTEM env var when SHELL is unset (#3366)
  On some Git Bash installations SHELL is not set but MSYSTEM (MINGW64/MSYS)
  is always present. Check MSYSTEM before PSModulePath to avoid emitting
  PowerShell syntax in bash shells.

- session-state: resolve legacy agent names in resolveRegisteredAgentName (#3272)
  Historical sessions stored agent names like 'Sisyphus (Ultraworker)' which
  don't match the current registered format. Fall back to getAgentConfigKey
  for legacy/parenthesized name resolution before returning the raw name.

- config-migration: skip backup when file content is unchanged (#3222)
  Compare serialized config with existing file content before creating a
  timestamped .bak file. Only create backup when the on-disk content
  actually differs from the migrated content.
This commit is contained in:
YeonGyu-Kim
2026-04-15 10:43:44 +09:00
parent 54a94d4169
commit 0dab3116b7
7 changed files with 172 additions and 13 deletions
+23 -7
View File
@@ -143,20 +143,36 @@ export function migrateConfigFile(
}
if (needsWrite) {
let finalConfig = JSON.parse(JSON.stringify(copy)) as Record<string, unknown>
const newContent = JSON.stringify(finalConfig, null, 2) + "\n"
// Compare with existing file content to skip backup when unchanged.
// The config may still need an in-memory migration even if the file
// content is identical (e.g. removing a deleted hook from disabled_hooks
// results in content that was already written by a prior migration).
let existingContent: string | undefined
try {
existingContent = fs.readFileSync(configPath, "utf-8")
} catch {
// File may not exist yet
}
const contentChanged = existingContent !== newContent
const timestamp = new Date().toISOString().replace(/[:.]/g, "-")
const backupPath = `${configPath}.bak.${timestamp}`
let backupSucceeded = false
try {
fs.copyFileSync(configPath, backupPath)
backupSucceeded = true
} catch {
backupSucceeded = false
if (contentChanged) {
try {
fs.copyFileSync(configPath, backupPath)
backupSucceeded = true
} catch {
backupSucceeded = false
}
}
let writeSucceeded = false
let finalConfig = JSON.parse(JSON.stringify(copy)) as Record<string, unknown>
try {
writeFileAtomically(configPath, JSON.stringify(finalConfig, null, 2) + "\n")
writeFileAtomically(configPath, newContent)
writeSucceeded = true
} catch (err) {
log(`Failed to write migrated config to ${configPath}:`, err)