Bundle two-root cleanup: PAI docs sweep + pack sources + commands architecture (#108, #113, #114)#135
Merged
virtualian merged 3 commits intomainfrom Apr 15, 2026
Merged
Conversation
Fix remaining stale CODE-root references in Releases/v4.0.3+/.claude/PAI/ docs and tool comments. Per-occurrence judgment preserves legitimate ~/.claude/settings.json KEEP refs. - FeatureRegistry.ts:10: usage comment ~/.claude/Tools/ → ~/.pai/PAI/Tools/ - THENOTIFICATIONSYSTEM.md: notifications.ts path hooks/ → ~/.pai/hooks/ - THEHOOKSYSTEM.md: 16 hook-path refs ~/.claude/hooks/ → ~/.pai/hooks/ - README.md: prose + ASCII tree rewritten for post-#101 two-root split (CONFIG at ~/.claude/, CODE at ~/.pai/) Fixes #108 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix remaining stale ~/.claude/{hooks,commands}/ refs in Packs/ sources and
their Releases/ mirrors. Per-occurrence judgment; KEEP list (settings.json,
projects/, keybindings.json) preserved throughout.
Real repo-side surface was 16 refs across 5 files, not the 446/138 that
issue #114 described — those counted the runtime tree (~/.pai/skills/**),
which mostly self-corrects on next install since most refs there come from
already-fixed pack sources.
- Packs/Utilities/PAIUpgrade/SKILL.md + Workflows/Upgrade.md: hooks path
- Packs/Telos/Workflows/Update.md: update-telos.ts commands path
canonicalized to ~/.pai/commands/ (harness still reads via symlink)
- Packs/Research/MigrationNotes.md: 5 command refs canonicalized
- Mirrored fixes in Releases/v4.0.3+/.claude/skills/** copies
Out of scope: Packs/ContextSearch/INSTALL.md bash-script rewrite (handled
in #113 commit with transition note).
Fixes #114
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Slash commands were forgotten by the two-root split (#101): no canonical home under ~/.pai/, installer never touched commands/, pack wizards were the only placement mechanism. This commit lands the Option B architecture: ~/.pai/commands/ becomes the single source of truth, symlinked into ~/.claude/commands/ so the harness scan path still works. - New: engine/command-migration.ts — migratePerPackCommands(), peer of skill-migration.ts scaled for flat .md files. Same state machine, same rollback semantics, same drift-backup pattern. 6.81 KB bundled. - engine/actions.ts: import + invocation after migratePerPackSymlinks in runRepository. Runs on both fresh installs and upgrades. - New: Releases/v4.0.3+/.claude/commands/.gitkeep — placeholder so the canonical dir ships with the release template. - Packs/ContextSearch/INSTALL.md: architecture transition note at top documenting the new model. Wizard bash scripts are left functional (they still copy to ~/.claude/commands/); the next main-installer run detects drift and converts real files into symlinks via the new migrator. Full wizard rewrite is follow-up work. Restores /cs as a slash command: cs.md exists in Packs/ContextSearch/src/ commands/, and the new migrator guarantees it reaches ~/.pai/commands/cs.md with a symlink at ~/.claude/commands/cs.md on the next install. Peer of #110 (skills migration). Architecture confirmed with user: Option B + /cs as slash command + leave stale ~/.claude/PAI/ mirror alone. Fixes #113 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
virtualian
added a commit
that referenced
this pull request
Apr 15, 2026
Patterned off command-migration.ts (PR #135). Ships engine/memory-migration.ts with a single entry point migrateMemoryDirectory(claudeConfigDir, paiDir, emit, options?), wired into runRepository immediately after user-context migration and before the skill/command migrators. Semantics: - Idempotent via marker file at <dest>/STATE/migration.json. Second run sees the marker and noops regardless of source state. - Refuses with a diagnostic (both paths + file counts + latest mtime) if both source and dest contain meaningful content without a marker. Merging is a data-integrity decision outside installer scope. - renameSync first, cpSync+rmSync fallback on EXDEV. Preserves mode and timestamps. Marker written inside the new location after the move. - Meaningful-content filter ignores .DS_Store and dotfile cruft so empty stub directories don't trip ambiguity detection. - Dry-run mode (options.dryRun=true) reports the intended action without touching the filesystem and without writing telemetry. - Telemetry logged to <paiDir>/MEMORY/LEARNING/SYSTEM/memory-migration-*.json so the outcome surfaces in the learning digest, not stdout where users miss it. Tests (engine/memory-migration.test.ts, 8 cases): - fresh install: noop-nothing-to-migrate - source has only .DS_Store: noop - upgrade: renames source into dest, writes marker, preserves nested files - second run: noop-already-migrated regardless of source state - ambiguity: refused-ambiguous, neither side mutated, telemetry written - dry-run would-migrate: filesystem untouched - dry-run would-refuse-ambiguous: no telemetry written - post-migration telemetry entry exists in LEARNING/SYSTEM/ All 8 pass. Regression-checked skill-migration.test.ts (17/17 pass). install.sh and PAI-Install/install.sh pass bash -n. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
10 tasks
virtualian
added a commit
that referenced
this pull request
Apr 15, 2026
#121, #107) (#136) * Promote tryExec into shared engine/exec.ts (#121) Extract the triplicated safe-subprocess helper into a leaf utility module with zero imports from the installer tree, so any consumer (current or future) can depend on it without circular-import risk. Replace the three hand-rolled copies: - actions.ts: delete local tryExec, import from ./exec - detect.ts: delete local tryExec, import from ./exec, pass explicit 5000ms timeout at every call site to preserve the historical detect probe bound (tryExec default is 30000ms, matching actions.ts) - repo-url.ts: rewrite readOriginRemote around tryExec, preserving the .git existsSync short-circuit Zero behavioral change — purely structural consolidation. Flagged by the /simplify review in PR #120 (#115 fix) as pre-existing debt. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Automate MEMORY migration for v4.0.2 → v4.0.3+ upgraders (#107) Patterned off command-migration.ts (PR #135). Ships engine/memory-migration.ts with a single entry point migrateMemoryDirectory(claudeConfigDir, paiDir, emit, options?), wired into runRepository immediately after user-context migration and before the skill/command migrators. Semantics: - Idempotent via marker file at <dest>/STATE/migration.json. Second run sees the marker and noops regardless of source state. - Refuses with a diagnostic (both paths + file counts + latest mtime) if both source and dest contain meaningful content without a marker. Merging is a data-integrity decision outside installer scope. - renameSync first, cpSync+rmSync fallback on EXDEV. Preserves mode and timestamps. Marker written inside the new location after the move. - Meaningful-content filter ignores .DS_Store and dotfile cruft so empty stub directories don't trip ambiguity detection. - Dry-run mode (options.dryRun=true) reports the intended action without touching the filesystem and without writing telemetry. - Telemetry logged to <paiDir>/MEMORY/LEARNING/SYSTEM/memory-migration-*.json so the outcome surfaces in the learning digest, not stdout where users miss it. Tests (engine/memory-migration.test.ts, 8 cases): - fresh install: noop-nothing-to-migrate - source has only .DS_Store: noop - upgrade: renames source into dest, writes marker, preserves nested files - second run: noop-already-migrated regardless of source state - ambiguity: refused-ambiguous, neither side mutated, telemetry written - dry-run would-migrate: filesystem untouched - dry-run would-refuse-ambiguous: no telemetry written - post-migration telemetry entry exists in LEARNING/SYSTEM/ All 8 pass. Regression-checked skill-migration.test.ts (17/17 pass). install.sh and PAI-Install/install.sh pass bash -n. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
Bundled fix for three peer issues from the post-#101 two-root split:
~/.claude/{hooks,Tools}/refs inReleases/v4.0.3+/.claude/PAI/docs/tool comments~/.pai/commands/home, no installer supportThree separate commits, one per issue, for a clean revert story.
User decisions received before execution
~/.pai/commands/+ symlinks into~/.claude/commands/(peer of #110 skills fix)/csfate~/.pai/commands/cs.mdsymlinked from~/.claude/commands/cs.md~/.claude/PAI/mirror deletionWhat's in each commit
3f4e937 — Sweep stale
~/.claude/refs in release-templatePAI/tree (#108)FeatureRegistry.ts:10: usage comment~/.claude/Tools/→~/.pai/PAI/Tools/THENOTIFICATIONSYSTEM.md:notifications.tspath →~/.pai/hooks/THEHOOKSYSTEM.md: 16 hook-path refs swept via targeted replace_allREADME.md: prose + ASCII tree rewritten to document the post-Implement CLAUDE_CONFIG_DIR + PAI_DIR two-root separation #101 split (CONFIG at~/.claude/, CODE at~/.pai/)Note:
RebuildPAI.ts:16,CLAUDE.mdalgorithm anchor, andAlgorithm/v3.7.0.mdwere already fixed in the repo on an earlier commit — the runtime files at~/.pai/PAI/are stale because they came from a pre-fix install, and will self-correct on the next install run.c60aedf — Sweep stale CODE-root refs in pack sources + release skills (#114)
Packs/Utilities/PAIUpgrade/SKILL.md+Workflows/Upgrade.md: hooks pathPacks/Telos/Workflows/Update.md: 3update-telos.tscommands-path refs canonicalized to~/.pai/commands/(harness still reads via symlink)Packs/Research/MigrationNotes.md: 5 command refs canonicalizedReleases/v4.0.3+/.claude/skills/**copiesScope reality check: The real repo-side surface was 16 refs across 5 files, not the 446/138 #114 described. #114's count was against the runtime tree
~/.pai/skills/**; most of those runtime refs come from pack sources that were already fixed in earlier commits, so they'll self-correct on reinstall.50cb0b7 — Add canonical
~/.pai/commands/home and installer migration (#113)Releases/v4.0.3+/.claude/PAI-Install/engine/command-migration.ts—migratePerPackCommands(), direct peer ofskill-migration.tsscaled for flat.mdfiles. Same state machine (move / link-only / drift modes), same rollback, same drift-backup pattern, samegetPaiCommandsDir()env-var resolution. Bundled 6.81 KB, compiles clean.actions.ts: import + invocation right aftermigratePerPackSymlinksinrunRepository. Runs on both fresh installs and upgrades.Releases/v4.0.3+/.claude/commands/.gitkeep— placeholder so the canonical dir ships with the release template.Packs/ContextSearch/INSTALL.md: architecture transition note at the top documenting the new model. Wizard bash scripts stay functional as-is — the next main-installer run detects drift from any direct copies and converts them into symlinks via the new migrator.cs.mdis already present inPacks/ContextSearch/src/commands/— the new migrator guarantees it reaches~/.pai/commands/cs.mdwith a symlink at~/.claude/commands/cs.mdon the next install, restoring/csas a first-class slash command.Explicitly NOT in this PR (follow-up work)
Packs/ContextSearch/INSTALL.mdto delegate command placement to the main installer. Transition note added instead; wizards remain functional and self-correct on next main-installer run.~/.claude/PAI/mirror tree — per user direction, out of scope (maintainer call for a separate PR).~/.pai/skills/**(433 refs) and~/.pai/PAI/**(178 refs) — those self-correct on the next install run because the repo sources are already correct.cs-as-skill workaround — I searched the repo and only thecontext-searchskill exists by that name in the skill listing; no removablecsskill declaration was found.Verification
RebuildPAI.ts:bun build→ 3.97 KB, 0 errorsactions.ts:bun build→ 59.49 KB, 7 modules, 0 errorscommand-migration.ts:bun build→ 6.81 KB, 1 module, 0 errorsGetCounts.ts,actions.ts,skill-migration.ts, the newcommand-migration.ts)Packs/ContextSearch/INSTALL.md, all in bash-wizard scripts that are functional under Option B (harness scan path~/.claude/commands/resolves via symlink to canonical~/.pai/commands/)~/.claude/settings.jsonrefs preserved inTHENOTIFICATIONSYSTEM.md:109, 207andPAIUpgrade/SKILL.md:351Test plan
~/.pai/tree — verify~/.pai/commands/is created and populated from pack sources~/.claude/commands/— verify they're moved to~/.pai/commands/and replaced with symlinks/csslash command is invocable after install/context-searchstill works after installgrep -rE '~/\.claude/(PAI\|MEMORY\|hooks\|agents\|commands\|Tools\|skills)/' Releases/ Packs/ --include='*.md' --include='*.ts'returns only KEEP-list matchesCloses #108
Closes #113
Closes #114
🤖 Generated with Claude Code