Conversation
* fix(ci): clone @focusmcp/core as sibling before install
The CLI depends on @focusmcp/core via `file:../core/packages/core`.
In CI, that sibling doesn't exist, so `pnpm install --frozen-lockfile`
fails on every job.
Introduce a composite action `.github/actions/setup` that:
- clones focus-mcp/core at the expected sibling path
- installs its deps and builds it (packaging reads dist/)
- installs this repo's deps
Refactor every CI job + the release job to use it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): checkout @focusmcp/core inside workspace first
actions/checkout@v4 refuses any path outside the workspace
("Repository path ... is not under ..."), so the previous
`../core-checkout` target failed immediately. Check it out into a
subdirectory of the workspace and move it to the real sibling after.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(ci): configure npm registry in the setup composite action
Add `registry-url: 'https://registry.npmjs.org'` to the composite's
`actions/setup-node` step. This writes an `.npmrc` that reads
$NODE_AUTH_TOKEN at publish time, which is what Changesets needs.
Drop the separate "Configure npm registry" shell step from release.yml
now that the composite handles it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standardize indentation to 4 spaces across all projects. Biome formatter config updated accordingly. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add CLAUDE.md capturing the post-pivot agent guidance Replaces the former personal memory system under ~/.claude/projects/**/memory/ with an in-repo, version-controlled file that is auto-loaded by Claude Code (and any agents.md-compatible tool). Covers: project overview, 4-repo ecosystem, post-pivot architecture with stdio MCP + @modelcontextprotocol/sdk, the 8 non-negotiable conventions across all repos, this repo's specifics (file: dep on @focusmcp/core via sibling clone in CI, tsup noExternal bundling for publish), and the standard feature workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs(claude.md): address Copilot review - Heading: 3 active repos + 1 archived (table had 3 not 4) - Drop Windows absolute path, describe sibling layout generically - Use @modelcontextprotocol/sdk (matches package.json) - Rule 5 reframed as from-now-on; PRD.md + CLAUDE.md stay French Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add gitleaks secret scanning to pre-commit hook Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fail pre-commit hook when gitleaks detects a secret Add || exit $? after gitleaks protect to prevent commits with leaked secrets from proceeding to lint-staged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: implement focus start — stdio + HTTP MCP transport
Wire FocusMcp core (Registry + EventBus + Router) to MCP SDK server.
Two modes:
- `focus start` → stdio transport (for .mcp.json / Claude Code)
- `focus start --http --port 3000` → HTTP streamable transport
Registers tools from router.listTools() as MCP tool handlers,
dispatches calls via router.callTool(). SIGINT/SIGTERM graceful shutdown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: comprehensive coverage for start command (100%)
10 new tests covering HTTP mode, tool handlers, error paths,
signal handling. All guards explicit (no non-null assertions).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(start): address 6 Copilot issues in startCommand
- stdio mode now blocks indefinitely (`await new Promise<void>(() => {})`)
so the process stays alive after `server.connect(transport)`
- cleanup handler wraps `focusMcp.stop()` in try/catch to avoid
unhandled rejections on shutdown
- HTTP body parsing wrapped in try/catch, returns 400 on invalid JSON
- HTTP body limited to 1 MB (413 on overflow)
- port validated (finite integer, 1–65535) before use
- tests updated: stdio-mode calls no longer awaited (they block forever);
each test runs the promise in the background and checks state after a
microtask tick, mirroring the existing HTTP-mode pattern
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: claude <claude@localhost>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: load bricks from center.json on focus start Read ~/.focus/center.json, resolve enabled bricks from filesystem, pass to createFocusMcp(). Support FOCUSMCP_BRICKS_DIR env var. Graceful fallback if no center.json exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address Copilot review — path traversal, error handling, dist import - Add safeBrickName() and safeBrickPath() guards against path traversal - loadModule() now imports dist/index.js (built JS) instead of src/index.ts - Catch block distinguishes ENOENT (no center.json) from real errors - Log actual error messages for non-ENOENT failures Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Versions are injected at build time via tsup define, reading both package.json files so no runtime file I/O is needed. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
) - FilesystemBrickSource: try dist/index.js first, fallback to src/index.ts - bin/focus.ts: forward raw args (including flags) to subcommands - Enables dogfooding with marketplace bricks without build step Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow LLMs to inspect and manage loaded bricks dynamically: - focus_list: returns loaded bricks and their tools - focus_load: stub (pending core dynamic brick API) - focus_unload: stops brick, removes from registry Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: implement focus_load, focus_reload + tools/list_changed notifications
Dynamic brick management at runtime:
- focus_load: load a brick from filesystem, register, start
- focus_reload: stop → reimport → restart (hot reload)
- All load/unload/reload send notifications/tools/list_changed
- Import cache busting for development workflow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: handle non-ToolResult responses from brick handlers
Bricks may return raw objects (e.g. {message: "hello"}) instead of
ToolResult {content: [...]}. Wrap raw results in JSON.stringify.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test(start): raise function coverage to 100% on start.ts
Add tests for HTTP 400/413 edge cases, cleanup error branch, stdio
started log, and loadSingleBrick failure paths. Exclude minimalLogger
no-op stubs from v8 coverage (/* v8 ignore next 7 */). Functions pct
goes from 37.5% → 100%; global functions threshold now passes (95%).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: claude <claude@localhost>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: add Claude Code Review action * ci: use Claude Max OAuth instead of API key Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): add id-token permission for OIDC auth --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
Author
|
Closing in favour of fix/sync-to-main PR with linear history |
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
🤖 Generated with Claude Code