feat: implement focus_update + focus_upgrade MCP tools + CLI update alias#70
Merged
Conversation
Replace the stub with a real implementation that delegates to upgradeCommand. Schema updated to accept brick (string), all (boolean), check (boolean). Tests cover happy path, single brick, dry-run (--check), and error cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…th MCP tool focus update <brick> and focus update --all now work as aliases for focus upgrade, following npm conventions (npm update / npm upgrade). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…installed error Update the error message so users know both aliases are valid options after the 'update' alias was added to the CLI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both tools share the same upgradeCommand implementation. focus_upgrade returns 'Upgrade failed' prefix vs 'Update failed' for clarity. Tests cover happy path, --check dry-run, and error case for focus_upgrade. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This was referenced Apr 28, 2026
samuelds
added a commit
that referenced
this pull request
Apr 28, 2026
* feat(cli): DX improvements — force reinstall, doctor --fix, actionable errors (1.8.0) (#63) * feat(cli): add --force flag to focus add - AddIO.rmDir? + getBricksDir? optional methods for dir purge - forcePurgeBrick helper: wipes corrupted pkg dir, removes from state, then re-installs — skips the "already installed" guard - addCommand/addManyCommand forward force flag - Tests: force-reinstall, no-already-installed message, rmDir invocation, bundle brick cascade (tools=0, deps>0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add focus reinstall command focus reinstall <X> [Y Z ...] — alias for remove + add --force that preserves the brick's enabled state. Useful for bulk recovery after `focus doctor` detects corrupted installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): focus doctor --fix flag When --fix is passed, doctor auto-remediates: - Corrupted installs (pkg dir missing, dist missing, invalid manifest, lock entry missing) → focus reinstall <name> - Missing declared dependencies → focus add <dep> Version drift is intentionally NOT auto-fixed (use focus upgrade). Prints actions taken and re-runs doctor at the end to show updated state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): actionable error on Missing dependency at start time When loadBricks reports a failure with a 'Missing dependency "X"' message, enrich the stderr output with three actionable commands: focus add X # install the missing dep focus reinstall Y # if Y's install is corrupted focus doctor # full diagnostic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): cascade auto-deps for bundle bricks + wire reinstall/force/doctor-fix to CLI - focus add [-f/--force] <name>: parse force flag, wire rmDir/getBricksDir - focus reinstall <name> [...]: new command wired through runReinstall - focus doctor [--fix]: parse --fix flag, re-run after fixes in text mode - HELP text updated with all new flags and commands - Bundle bricks verified: tools=[] + deps>0 cascades identically to normal bricks (resolveDeps is agnostic to tools count) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): cli 1.8.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): test fix — move enrichStartError test inside startCommand describe (#66) * feat(cli): add --force flag to focus add - AddIO.rmDir? + getBricksDir? optional methods for dir purge - forcePurgeBrick helper: wipes corrupted pkg dir, removes from state, then re-installs — skips the "already installed" guard - addCommand/addManyCommand forward force flag - Tests: force-reinstall, no-already-installed message, rmDir invocation, bundle brick cascade (tools=0, deps>0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add focus reinstall command focus reinstall <X> [Y Z ...] — alias for remove + add --force that preserves the brick's enabled state. Useful for bulk recovery after `focus doctor` detects corrupted installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): focus doctor --fix flag When --fix is passed, doctor auto-remediates: - Corrupted installs (pkg dir missing, dist missing, invalid manifest, lock entry missing) → focus reinstall <name> - Missing declared dependencies → focus add <dep> Version drift is intentionally NOT auto-fixed (use focus upgrade). Prints actions taken and re-runs doctor at the end to show updated state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): actionable error on Missing dependency at start time When loadBricks reports a failure with a 'Missing dependency "X"' message, enrich the stderr output with three actionable commands: focus add X # install the missing dep focus reinstall Y # if Y's install is corrupted focus doctor # full diagnostic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): cascade auto-deps for bundle bricks + wire reinstall/force/doctor-fix to CLI - focus add [-f/--force] <name>: parse force flag, wire rmDir/getBricksDir - focus reinstall <name> [...]: new command wired through runReinstall - focus doctor [--fix]: parse --fix flag, re-run after fixes in text mode - HELP text updated with all new flags and commands - Bundle bricks verified: tools=[] + deps>0 cascades identically to normal bricks (resolveDeps is agnostic to tools count) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): cli 1.8.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): move enrichStartError test inside startCommand describe block The test was outside the describe block and used process.emit('SIGINT'), triggering process.exit(0) and causing vitest to exit with code 1. Moved inside the block where stderr.write is already mocked by beforeEach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): FOCUS_BENCH_MODE env var skips meta tools for bench isolation (#68) When FOCUS_BENCH_MODE=true (or 1), the focus_list, focus_load, focus_unload, focus_reload, focus_search, focus_install, focus_remove, focus_update, focus_catalog_add, focus_catalog_list, and focus_catalog_remove tools are not registered. Brick tools loaded via center.json are still exposed as usual. Default behaviour (env var absent) is unchanged. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: replace aspirational slogan with measured token savings (#69) Remove unverified "200k to ~2k" claim; replace with 65.9% measured benchmark figure with link to full equivalence report. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: implement focus_update + focus_upgrade MCP tools + CLI update alias (#70) * feat(start): implement focus_update MCP tool reusing upgradeCommand Replace the stub with a real implementation that delegates to upgradeCommand. Schema updated to accept brick (string), all (boolean), check (boolean). Tests cover happy path, single brick, dry-run (--check), and error cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add 'update' alias to 'upgrade' command for consistency with MCP tool focus update <brick> and focus update --all now work as aliases for focus upgrade, following npm conventions (npm update / npm upgrade). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(add): mention both 'focus upgrade' and 'focus update' in already-installed error Update the error message so users know both aliases are valid options after the 'update' alias was added to the CLI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(start): add focus_upgrade MCP tool as alias for focus_update Both tools share the same upgradeCommand implementation. focus_upgrade returns 'Upgrade failed' prefix vs 'Update failed' for clarity. Tests cover happy path, --check dry-run, and error case for focus_upgrade. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(ci): add back-merge workflow to auto-sync main → develop (#71) Co-authored-by: claude <claude@localhost> * refactor(upgrade): thin wrapper around core.executeUpgrade (#72) * refactor(upgrade): thin wrapper around core.executeUpgrade Moves orchestration logic to @focus-mcp/core/marketplace/upgrader. CLI command now loads the catalog then delegates to core.executeUpgrade. MCP tools (focus_update, focus_upgrade) in start.ts continue to call upgradeCommand which in turn calls core — no breaking change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): pin @focus-mcp/core to 0.0.0-dev.35 for executeUpgrade Interim until @focus-mcp/core@1.2.0 is released to npm latest. Will be bumped to ^1.2.0 in a follow-up release PR. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): dev-publish uses changeset snapshot for proper next-version preview tags (#73) Replace custom base-version+dev.N versioning with `pnpm changeset version --snapshot dev` so that the dev dist-tag reflects the actual next stable (e.g. 1.9.0-dev-DATE-SHA) instead of a frozen or mismatched base version. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): @focus-mcp/cli 1.8.1 — bench mode + core 1.2.0 (#74) * chore: bump @focus-mcp/core to ^1.2.0 for executeUpgrade/planUpgrade thin wrapper Required for focus_update + focus_upgrade MCP tools (thin wrapper depends on executeUpgrade exported from @focus-mcp/core 1.2.0). * chore(release): bump @focus-mcp/cli to 1.8.1 — bench mode + core 1.2.0 dep --------- Co-authored-by: claude <claude@localhost> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <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
focus_updateMCP tool : remplace le stubnot yet implementedpar une implémentation complète viaupgradeCommand. Acceptebrick(string),all(boolean),check(boolean).focus_upgradeMCP tool : nouveau tool MCP alias defocus_update, même logique, préfixe d'erreur distinct (Upgrade failedvsUpdate failed).update:focus update <brick>etfocus update --allfonctionnent maintenant comme aliases defocus upgrade.add.ts: mise à jour pour mentionner les deux options (focus upgradeetfocus update).4 chemins fonctionnels post-PR
focus upgrade <brick>focus update <brick>focus_updatefocus_upgradeNote d'architecture
Approche fast-path :
upgradeCommandreste danscli/src/commands/upgrade.tspour l'instant. La logique d'upgrade ira dans@focus-mcp/coredans une PR séparée (refacto architectural non bloquant).Test plan
pnpm test)pnpm typecheck)pnpm biome check .)focus_update: happy path, single brick, --check, errorfocus_upgrade: happy path, --check, errorfocus_upgradeabsent quand FOCUS_BENCH_MODE=true🤖 Generated with Claude Code