fix(spawn): dry-run-default + path-based update engine — kill #636 branch-scrambler (TDPLAN-0006 P0+P1)

#636: drone @spawn update would scramble every branch's identity/memory in
one command. On a branch created seconds earlier, --dry-run proposed 30 renames
rotating identity dirs (apps->.trinity->.seedgo->.claude->.archive->.aipass),
README->DASHBOARD, and deep-merged stale template into live .trinity/. Root
cause: the CREATE path regenerated template-registry IDs in filesystem-walk
order (!= the master's hand-crafted IDs), so content-hash + rename-detection
saw a mismatch on a pristine branch. update --all would have destroyed all 13
citizens at once.

P0 — safety by default:
- update + repair are now dry-run by default; --apply required to write.
  Forgotten flag = safe preview-only no-op. --dry-run kept as alias.
- doctor_fix.py repair suggestions emit the matching --apply form
  (+ aipass test_doctor_fix updated to the new contract).

P1 — engine rebuild (update_ops.py v2.0):
- Path-based named-managed-files model replaces whole-tree hash-diff +
  rename-detection. ID divergence is moot — IDs are no longer used.
- .trinity/*, DASHBOARD.local.json, artifacts/birth_certificate.json,
  .seedgo/bypass.json = delivered on CREATE only, NEVER touched on update.
- Old ID engine (change_detection.py, reconcile.py) + orphaned tests deleted.

Verified on fresh sandbox: update --dry-run = 0 renames / 0 updates / 0
additions (create==update invariant); no-flag run = dry-run preview, filesystem
byte-identical; 313 spawn tests green; seedgo 100% (all 36 standards).

Closes #636. P2/P3/P4 (shared lib, seam, .recovery relocate) to follow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
AIOSAI
2026-06-06 22:54:09 -07:00
co-authored by Claude Opus 4.8
parent 1ef1e2e89c
commit ccc8d6a97b
16 changed files with 334 additions and 1189 deletions
+5 -3
View File
@@ -38,8 +38,9 @@ def print_help():
console.print()
console.print(" [green]create[/green] [class] <path> Create a new branch from template")
console.print(" [green]passport[/green] <@dirname> Grant birthright citizenship (minimal)")
console.print(" [green]update[/green] <@branch> Update single branch (uses its class)")
console.print(" [green]update[/green] <class> --all Update all branches of a class")
console.print(" [green]update[/green] <@branch> Update single branch (preview-only by default)")
console.print(" [green]update[/green] <@branch> --apply Update single branch (execute changes)")
console.print(" [green]update[/green] <class> --all --apply Update all branches of a class")
console.print(" [green]delete[/green] <@branch> Archive and deregister branch")
console.print(" [green]sync-registry[/green] Repair registry against filesystem")
console.print(" [green]sync-templates[/green] Pull managed files from source")
@@ -60,7 +61,8 @@ def print_help():
warning("--purpose", details="Agent purpose (brief)")
warning("--template", details="Template class name (builder, birthright) or custom directory path")
warning("--registry", details="Path to AIPASS_REGISTRY.json")
warning("--dry-run", details="Preview changes without modifying files")
warning("--apply", details="Execute changes (update/repair are preview-only by default)")
warning("--dry-run", details="Preview changes without modifying files (default for update/repair)")
warning("--trace", details="Enable verbose logging")
console.print()