Skip to content

feat: split hevy-mcp into runtime-boundary packages - #715

Merged
chrisdoc merged 5 commits into
mainfrom
codex/four-package-runtime-boundaries
Jul 22, 2026
Merged

feat: split hevy-mcp into runtime-boundary packages#715
chrisdoc merged 5 commits into
mainfrom
codex/four-package-runtime-boundaries

Conversation

@chrisdoc

@chrisdoc chrisdoc commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Primary changes

  • Introduce four workspace packages with enforced runtime boundaries:
    • @hevy-mcp/hevy-client
    • @hevy-mcp/core
    • hevy-mcp (public Node package)
    • @hevy-mcp/worker
  • Move generated Hevy client ownership, runtime-neutral MCP construction, Node telemetry/stdio, and Worker HTTP/OAuth code into their respective packages.
  • Make the repository root a private orchestration workspace and keep only the Node package publishable.
  • Add boundary, export-map, release-candidate, manifest, package-smoke, Docker, and Worker bundle checks.
  • Add the new Node API: createNodeMcpServer and runStdioServer.
  • Preserve the existing MCP tools, stdio behavior, Worker routes, OAuth behavior, retry semantics, and privacy guarantees.

Reviewer walkthrough

  • Review packages/hevy-client for generated API client ownership and the package export surface.
  • Review packages/core for runtime-neutral MCP construction, tools, resources, prompts, and shared utilities.
  • Review packages/node for the public Node package, createNodeMcpServer, runStdioServer, telemetry, and stdio wiring.
  • Review packages/worker for the Worker HTTP and OAuth entrypoints, then finish with the root workspace orchestration, compatibility facade, and release/package checks.

Correctness and invariants

  • Generated Hevy client code remains owned by @hevy-mcp/hevy-client, while runtime-neutral MCP construction remains in @hevy-mcp/core.
  • Node-only telemetry and stdio code stays in hevy-mcp; Worker HTTP/OAuth code stays in @hevy-mcp/worker.
  • Existing MCP tools, stdio behavior, Worker routes, OAuth behavior, retry semantics, and privacy guarantees remain preserved.
  • The root compatibility source remains temporarily for legacy tests and migration safety; it is tracked as the final cleanup step after consumers fully migrate.

Testing and QA

  • npm run check
  • npm run check:workspaces
  • npm run check:boundaries
  • npm run check:exports
  • npm run check:types
  • npm run test:unit
  • npm run test:mcp
  • npm run test:contract
  • npm run test:stdio
  • npm run test:worker-http
  • npm run test:pack
  • npm run worker:dry-run
  • Docker build and non-root runtime smoke

✨ PR Description

Purpose: Reorganize hevy-mcp monorepo into four runtime-boundary packages with explicit dependency graph and published Node distribution.

Main changes:

  • Split monolithic src/ into @hevy-mcp/hevy-client, @hevy-mcp/core, hevy-mcp (Node), @hevy-mcp/worker packages under packages/
  • Refactored createServer/runServer to createNodeMcpServer/runStdioServer with factory-based client injection pattern
  • Added runtime boundary enforcement, package export validation, and comprehensive integration test suite for workspace topology

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 157 files, which is 57 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e61a46c2-b668-42cd-afe9-b3f2844454d7

📥 Commits

Reviewing files that changed from the base of the PR and between bc01bb5 and 29399e3.

⛔ Files ignored due to path filters (208)
  • package-lock.json is excluded by !**/package-lock.json
  • packages/hevy-client/src/generated/.kubb/config.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/.kubb/fetch.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1BodyMeasurements.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1ExerciseHistoryExercisetemplateid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1ExerciseTemplates.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1ExerciseTemplatesExercisetemplateid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1RoutineFolders.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1RoutineFoldersFolderid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1Routines.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1UserInfo.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1Workouts.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1WorkoutsCount.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1WorkoutsEvents.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/getV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/index.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/postV1BodyMeasurements.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/postV1ExerciseTemplates.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/postV1RoutineFolders.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/postV1Routines.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/postV1Workouts.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/putV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/putV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/api/putV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/bodyMeasurement.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/createCustomExerciseRequestBody.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/customExerciseType.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/deletedWorkout.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/equipmentCategory.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/exercise.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/exerciseHistoryEntry.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/exerciseTemplate.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/muscleGroup.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/paginatedWorkoutEvents.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postRoutineFolderRequestBody.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postRoutinesRequestBody.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postRoutinesRequestExercise.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postRoutinesRequestSet.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postWorkoutsRequestBody.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postWorkoutsRequestExercise.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/postWorkoutsRequestSet.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/putBodyMeasurement.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/putRoutinesRequestBody.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/putRoutinesRequestExercise.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/putRoutinesRequestSet.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/routine.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/routineFolder.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/bodyMeasurementSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/createCustomExerciseRequestBodySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/customExerciseTypeSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/deletedWorkoutSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/equipmentCategorySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/exerciseHistoryEntrySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/exerciseSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/exerciseTemplateSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1BodyMeasurementsDateSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1BodyMeasurementsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1ExerciseHistoryExercisetemplateidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1ExerciseTemplatesExercisetemplateidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1ExerciseTemplatesSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1RoutineFoldersFolderidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1RoutineFoldersSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1RoutinesRoutineidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1RoutinesSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1UserInfoSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1WorkoutsCountSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1WorkoutsEventsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1WorkoutsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/getV1WorkoutsWorkoutidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/index.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/muscleGroupSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/paginatedWorkoutEventsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postRoutineFolderRequestBodySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postRoutinesRequestBodySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postRoutinesRequestExerciseSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postRoutinesRequestSetSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postV1BodyMeasurementsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postV1ExerciseTemplatesSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postV1RoutineFoldersSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postV1RoutinesSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postV1WorkoutsSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postWorkoutsRequestBodySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postWorkoutsRequestExerciseSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/postWorkoutsRequestSetSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putBodyMeasurementSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putRoutinesRequestBodySchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putRoutinesRequestExerciseSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putRoutinesRequestSetSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putV1BodyMeasurementsDateSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putV1RoutinesRoutineidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/putV1WorkoutsWorkoutidSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/routineFolderSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/routineSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/setSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/updatedWorkoutSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/userInfoResponseSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/userInfoSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/schemas/workoutSchema.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/set.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/BodyMeasurement.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/CreateCustomExerciseRequestBody.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/CustomExerciseType.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/DeletedWorkout.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/EquipmentCategory.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/Exercise.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/ExerciseHistoryEntry.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/ExerciseTemplate.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1BodyMeasurements.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1ExerciseHistoryExercisetemplateid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1ExerciseTemplates.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1ExerciseTemplatesExercisetemplateid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1RoutineFolders.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1RoutineFoldersFolderid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1Routines.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1UserInfo.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1Workouts.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1WorkoutsCount.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1WorkoutsEvents.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/GetV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/MuscleGroup.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PaginatedWorkoutEvents.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostRoutineFolderRequestBody.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostRoutinesRequestBody.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostRoutinesRequestExercise.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostRoutinesRequestSet.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostV1BodyMeasurements.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostV1ExerciseTemplates.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostV1RoutineFolders.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostV1Routines.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostV1Workouts.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostWorkoutsRequestBody.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostWorkoutsRequestExercise.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PostWorkoutsRequestSet.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutBodyMeasurement.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutRoutinesRequestBody.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutRoutinesRequestExercise.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutRoutinesRequestSet.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/PutV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/Routine.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/RoutineFolder.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/Set.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/UpdatedWorkout.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/UserInfo.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/UserInfoResponse.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/Workout.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/types/index.ts is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/updatedWorkout.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/userInfo.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/userInfoResponse.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/client/workout.json is excluded by !**/generated/**
  • packages/hevy-client/src/generated/index.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createBodyMeasurement.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createCreateCustomExerciseRequestBody.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createCustomExerciseType.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createDeletedWorkout.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createEquipmentCategory.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createExercise.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createExerciseHistoryEntry.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createExerciseTemplate.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1BodyMeasurements.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1ExerciseHistoryExercisetemplateid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1ExerciseTemplates.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1ExerciseTemplatesExercisetemplateid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1RoutineFolders.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1RoutineFoldersFolderid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1Routines.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1UserInfo.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1Workouts.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1WorkoutsCount.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1WorkoutsEvents.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createGetV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createMuscleGroup.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPaginatedWorkoutEvents.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostRoutineFolderRequestBody.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostRoutinesRequestBody.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostRoutinesRequestExercise.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostRoutinesRequestSet.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostV1BodyMeasurements.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostV1ExerciseTemplates.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostV1RoutineFolders.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostV1Routines.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostV1Workouts.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostWorkoutsRequestBody.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostWorkoutsRequestExercise.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPostWorkoutsRequestSet.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutBodyMeasurement.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutRoutinesRequestBody.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutRoutinesRequestExercise.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutRoutinesRequestSet.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutV1BodyMeasurementsDate.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutV1RoutinesRoutineid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createPutV1WorkoutsWorkoutid.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createRoutine.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createRoutineFolder.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createSet.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createUpdatedWorkout.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createUserInfo.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createUserInfoResponse.ts is excluded by !**/generated/**
  • src/generated/client/mocks/createWorkout.ts is excluded by !**/generated/**
  • src/generated/client/mocks/index.ts is excluded by !**/generated/**
📒 Files selected for processing (172)
  • .changeset/config.json
  • .changeset/eleven-eyes-stick.md
  • .changeset/loud-beds-like.md
  • .changeset/seven-regions-work.md
  • .dockerignore
  • .github/copilot-instructions.md
  • .github/workflows/build-and-test.yml
  • .github/workflows/nightly-mcp-test.yml
  • .github/workflows/release.yml
  • AGENTS.md
  • CONTRIBUTING.md
  • Dockerfile
  • README.md
  • REVIEW_RULES.md
  • codecov.yml
  • docs/TYPE_SAFETY_GUIDE.md
  • docs/telemetry-dashboards.md
  • docs/telemetry-data-dictionary.md
  • docs/testing-strategy.md
  • kubb.config.ts
  • package.json
  • packages/core/package.json
  • packages/core/src/index.ts
  • packages/core/src/observation.test.ts
  • packages/core/src/observation.ts
  • packages/core/src/prompts/workouts.test.ts
  • packages/core/src/prompts/workouts.ts
  • packages/core/src/resources/hevy.test.ts
  • packages/core/src/resources/hevy.ts
  • packages/core/src/server-metadata.test.ts
  • packages/core/src/server-metadata.ts
  • packages/core/src/server.ts
  • packages/core/src/tools/annotations.test.ts
  • packages/core/src/tools/body-measurements.test.ts
  • packages/core/src/tools/body-measurements.ts
  • packages/core/src/tools/define-tool.ts
  • packages/core/src/tools/folders.test.ts
  • packages/core/src/tools/folders.ts
  • packages/core/src/tools/input-schemas.ts
  • packages/core/src/tools/payload-mappers.test.ts
  • packages/core/src/tools/payload-mappers.ts
  • packages/core/src/tools/register.test.ts
  • packages/core/src/tools/register.ts
  • packages/core/src/tools/routine-discovery.test.ts
  • packages/core/src/tools/routine-discovery.ts
  • packages/core/src/tools/routines.test.ts
  • packages/core/src/tools/routines.ts
  • packages/core/src/tools/templates.test.ts
  • packages/core/src/tools/templates.ts
  • packages/core/src/tools/tool-runtime.test.ts
  • packages/core/src/tools/tool-runtime.ts
  • packages/core/src/tools/user.test.ts
  • packages/core/src/tools/user.ts
  • packages/core/src/tools/workflows.test.ts
  • packages/core/src/tools/workflows.ts
  • packages/core/src/tools/workouts.test.ts
  • packages/core/src/tools/workouts.ts
  • packages/core/src/utils/cache.test.ts
  • packages/core/src/utils/cache.ts
  • packages/core/src/utils/error-handler.test.ts
  • packages/core/src/utils/error-handler.ts
  • packages/core/src/utils/error-policy.ts
  • packages/core/src/utils/exercise-template-catalog.test.ts
  • packages/core/src/utils/exercise-template-catalog.ts
  • packages/core/src/utils/formatters.test.ts
  • packages/core/src/utils/json-parser.test.ts
  • packages/core/src/utils/json-parser.ts
  • packages/core/src/utils/mcp-client-logger.test.ts
  • packages/core/src/utils/mcp-client-logger.ts
  • packages/core/src/utils/output-schemas.test.ts
  • packages/core/src/utils/pagination.test.ts
  • packages/core/src/utils/pagination.ts
  • packages/core/src/utils/response-formatter.test.ts
  • packages/core/src/utils/response-formatter.ts
  • packages/core/src/utils/result-telemetry.ts
  • packages/core/src/utils/safe-error-diagnostic.test.ts
  • packages/core/src/utils/safe-error-diagnostic.ts
  • packages/core/src/utils/schemas.test.ts
  • packages/core/src/utils/schemas.ts
  • packages/core/src/utils/tool-annotations.ts
  • packages/core/src/utils/tool-descriptions.ts
  • packages/core/src/utils/tool-helpers.ts
  • packages/core/src/utils/tool-taxonomy.ts
  • packages/core/tsconfig.json
  • packages/hevy-client/kubb.config.ts
  • packages/hevy-client/package.json
  • packages/hevy-client/src/hevy-client-kubb.ts
  • packages/hevy-client/src/hevy-client.test.ts
  • packages/hevy-client/src/hevy-client.ts
  • packages/hevy-client/src/hevy-http-error.ts
  • packages/hevy-client/src/index.ts
  • packages/hevy-client/src/schemas.ts
  • packages/hevy-client/src/types.ts
  • packages/hevy-client/tsconfig.json
  • packages/node/README.md
  • packages/node/package.json
  • packages/node/server.json
  • packages/node/src/cli.ts
  • packages/node/src/index.test.ts
  • packages/node/src/index.ts
  • packages/node/src/utils/config.test.ts
  • packages/node/src/utils/config.ts
  • packages/node/src/utils/debug.test.ts
  • packages/node/src/utils/debug.ts
  • packages/node/src/utils/graceful-shutdown.child-process.test.ts
  • packages/node/src/utils/graceful-shutdown.test.ts
  • packages/node/src/utils/graceful-shutdown.ts
  • packages/node/src/utils/hevy-client-observability.test.ts
  • packages/node/src/utils/hevy-client-observability.ts
  • packages/node/src/utils/mcp-session-observability.test.ts
  • packages/node/src/utils/mcp-session-observability.ts
  • packages/node/src/utils/metrics.ts
  • packages/node/src/utils/result-telemetry.ts
  • packages/node/src/utils/sentry-privacy.ts
  • packages/node/src/utils/stdio-observability.test.ts
  • packages/node/src/utils/stdio-observability.ts
  • packages/node/src/utils/telemetry.test.ts
  • packages/node/src/utils/telemetry.ts
  • packages/node/src/utils/tool-observer.test.ts
  • packages/node/src/utils/tool-observer.ts
  • packages/node/src/utils/version-check.test.ts
  • packages/node/src/utils/version-check.ts
  • packages/node/tsconfig.json
  • packages/node/tsdown.config.ts
  • packages/worker/package.json
  • packages/worker/src/index.ts
  • packages/worker/src/worker-oauth.test.ts
  • packages/worker/src/worker-oauth.ts
  • packages/worker/src/worker.test.ts
  • packages/worker/src/worker.ts
  • packages/worker/tsconfig.json
  • scripts/check-package-boundaries.d.mts
  • scripts/check-package-boundaries.mjs
  • scripts/check-package-exports.mjs
  • scripts/check-release-candidates.mjs
  • scripts/check-worker-bundle.mjs
  • scripts/check-workspaces.mjs
  • scripts/measure-token-cost.ts
  • scripts/server-manifest.mjs
  • src/cli.ts
  • src/index.test.ts
  • src/tools/tool-runtime.ts
  • src/utils/config.test.ts
  • src/utils/error-classification.ts
  • src/utils/graceful-shutdown.test.ts
  • src/utils/hevyClient.test.ts
  • src/utils/hevyClientKubb.test.ts
  • src/utils/mcp-session-observability.test.ts
  • src/utils/observability-wrapper.test.ts
  • src/utils/observability-wrapper.ts
  • src/utils/stdio-observability.test.ts
  • src/utils/telemetry-wrapper.test.ts
  • src/utils/telemetry-wrapper.ts
  • tests/fixtures/graceful-shutdown-child.ts
  • tests/fixtures/package-boundary-syntax.cts
  • tests/integration/hevy-mcp.integration.test.ts
  • tests/integration/mocked/get-workout-count-events-mocked.integration.test.ts
  • tests/integration/mocked/hevy-mcp.mocked.integration.test.ts
  • tests/nightly/diagnostics.test.mjs
  • tests/package/npm-pack-smoke.mjs
  • tests/performance/harness.ts
  • tests/performance/report.ts
  • tests/unit/index.test.ts
  • tests/unit/package-boundaries.test.ts
  • tests/unit/package-readme.test.ts
  • tests/unit/performance-report.test.ts
  • tests/unit/response-contract-architecture.test.ts
  • tests/unit/server-manifest.test.ts
  • tsconfig.base.json
  • tsconfig.json
  • wrangler.jsonc
  • wrangler.preview.jsonc

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/four-package-runtime-boundaries

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

MCP tool token cost

Measured with o200k_base over the complete json-serialized mcp tools/list result payload: { tools }.
Targets are advisory and never fail CI.

Metric Current Target Status
Tools 25 ≤ 20 Above target
Total tokens 12667
Average tokens/tool 506.68 < 600 Within target

Change from baseline

Metric Baseline Current Delta
Tools 25 25 0
Total tokens 12667 12667 0
Average tokens/tool 506.68 506.68 0

Per-tool changes

Tool Baseline Current Delta
create-body-measurement 669 669 0
create-exercise-template 421 421 0
create-routine 564 564 0
create-routine-folder 166 166 0
create-workout 655 655 0
get-body-measurement 628 628 0
get-body-measurements 629 629 0
get-exercise-history 808 808 0
get-exercise-template 276 276 0
get-exercise-templates 308 308 0
get-routine 552 552 0
get-routine-folder 245 245 0
get-routine-folders 270 270 0
get-routines 586 586 0
get-training-summary 923 923 0
get-user-info 244 244 0
get-workout 522 522 0
get-workout-count 195 195 0
get-workout-events 670 670 0
get-workouts 540 540 0
search-exercise-templates 426 426 0
search-routines 465 465 0
update-body-measurement 667 667 0
update-routine 562 562 0
update-workout 672 672 0

Per-tool breakdown

Tool Tokens Share of total
get-training-summary 923 7.29%
get-exercise-history 808 6.38%
update-workout 672 5.31%
get-workout-events 670 5.29%
create-body-measurement 669 5.28%
update-body-measurement 667 5.27%
create-workout 655 5.17%
get-body-measurements 629 4.97%
get-body-measurement 628 4.96%
get-routines 586 4.63%
create-routine 564 4.45%
update-routine 562 4.44%
get-routine 552 4.36%
get-workouts 540 4.26%
get-workout 522 4.12%
search-routines 465 3.67%
search-exercise-templates 426 3.36%
create-exercise-template 421 3.32%
get-exercise-templates 308 2.43%
get-exercise-template 276 2.18%
get-routine-folders 270 2.13%
get-routine-folder 245 1.93%
get-user-info 244 1.93%
get-workout-count 195 1.54%
create-routine-folder 166 1.31%

Per-tool counts encode each complete tool object independently. The total encodes the complete { tools } envelope, so punctuation and separators mean the per-tool values need not sum exactly to the total.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Unit Test Results

  1 files   52 suites   4s ⏱️
615 tests 615 ✅ 0 💤 0 ❌
619 runs  619 ✅ 0 💤 0 ❌

Results for commit 29399e3.

♻️ This comment has been updated with latest results.

@charliecreates charliecreates Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actionable findings.

I reviewed the runtime-boundary package split across the generated client, core server, Node stdio/telemetry path, Worker HTTP/OAuth path, package manifests and export maps, release/Docker configuration, compatibility facades, and the associated CI coverage for this head. The completed checks provide coverage for the Node 24/26 builds and tests, boundary/export/release checks, Worker HTTP and preview behavior, stdio/contract baselines, packaging, Docker smoke, CodeQL, and security scans.

@chrisdoc
chrisdoc marked this pull request as ready for review July 22, 2026 17:33
@mergify

mergify Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@charliecreates charliecreates Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actionable findings.

Reviewed head b84707b72ca9c67efed7eed2480c6d53eb4da003 across the runtime-boundary package split, generated client relocation, core/Node/Worker entrypoints and export maps, Docker/release/changeset wiring, OAuth/security/privacy paths, and boundary/packaging checks. GitHub reports successful Node 24/26 build and test checks, Worker preview, Docker smoke, CodeQL, GitGuardian, and unit-test results (615 tests, 619 runs).

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Split hevy-mcp into runtime-boundary workspaces (core / hevy-client / node / worker)

✨ Enhancement ⚙️ Configuration changes 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Split the repo into four workspace packages with enforced runtime boundaries.
• Add explicit Node API entrypoints while preserving stdio/Worker behavior and privacy guarantees.
• Introduce CI/local checks for boundaries, exports, release candidates, pack smoke, and Worker
 bundle safety.
Diagram

graph TD
  A["Repository root"] --> B["@hevy-mcp/hevy-client"] --> C["@hevy-mcp/core"] --> D["hevy-mcp (Node)"]
  C --> E["@hevy-mcp/worker"]
  A --> F["Boundary/export checks"]
  D --> G["Node stdio + telemetry"]
  E --> H["Worker HTTP/OAuth"]

  subgraph Legend
    direction LR
    _repo["Workspace"] ~~~ _pkg["Package"] ~~~ _chk["Check/CI"]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Single package with conditional exports + runtime shims
  • ➕ Fewer workspaces/package.json/CI moving parts
  • ➕ No temporary multi-package migration overhead
  • ➖ Weaker enforcement; runtime-only imports can leak into shared code
  • ➖ Harder to ensure the Worker bundle stays free of Node-only deps over time
2. Publish multiple packages publicly (core/hevy-client/worker)
  • ➕ Allows external reuse of core or generated client
  • ➕ Clear semver boundaries for each layer
  • ➖ Increases release coordination and long-term support surface area
  • ➖ Forces early API stability commitments during migration
3. Rely primarily on bundling (no hard boundaries)
  • ➕ Minimal source re-org; bundler can prune runtime-specific code
  • ➖ Boundary violations discovered late (bundle/runtime), not at review/CI time
  • ➖ Higher risk of subtle Worker/Node incompatibilities and privacy regressions

Recommendation: The chosen approach (workspace split + strict boundary/export checks + Worker bundle scanning) is the best option to sustain runtime separation and prevent regressions. If external reuse becomes a priority, consider publishing @hevy-mcp/core later once APIs stabilize, without relaxing the current enforcement tooling.

Files changed (28) +1938 / -138

Enhancement (9) +789 / -22
package.jsonIntroduce @hevy-mcp/hevy-client workspace with constrained exports +27/-0

Introduce @hevy-mcp/hevy-client workspace with constrained exports

• Adds a private workspace for the generated Hevy client with a strict export map limited to '.', './types', and './schemas', plus scripts for client generation and type-checking.

packages/hevy-client/package.json

package.jsonIntroduce @hevy-mcp/core runtime-neutral workspace +21/-0

Introduce @hevy-mcp/core runtime-neutral workspace

• Adds a private core workspace that depends on the generated client and MCP SDK, exporting only its entrypoint to keep runtime boundaries crisp.

packages/core/package.json

package.jsonAdd @hevy-mcp/worker workspace for Cloudflare runtime +25/-0

Add @hevy-mcp/worker workspace for Cloudflare runtime

• Creates a private Worker workspace exporting its entrypoint and depending on the Worker OAuth provider + MCP SDK, consuming core/client via workspace devDependencies.

packages/worker/package.json

index.tsDefine core public exports (server constructor, observation, diagnostics) +23/-0

Define core public exports (server constructor, observation, diagnostics)

• Exports 'createHevyMcpServer' and related types, tool observation interfaces, safe diagnostics, and telemetry helpers as the runtime-neutral API surface for adapters.

packages/core/src/index.ts

observation.tsAdd privacy-safe tool observation model for adapters +123/-0

Add privacy-safe tool observation model for adapters

• Introduces a runtime-neutral observation API for tool invocation/result/completion capturing only safe argument presence/buckets and summary metrics, with memoization to ensure observation cannot affect behavior.

packages/core/src/observation.ts

tool-runtime.tsImplement observed tool runtime with safe telemetry extraction +213/-0

Implement observed tool runtime with safe telemetry extraction

• Adds a tool runtime that can optionally emit observations around handler execution, capturing duration/outcome and safe result summaries while preserving error semantics and non-interference guarantees.

packages/core/src/tools/tool-runtime.ts

index.tsExpose generated client factory and error helpers +22/-0

Expose generated client factory and error helpers

• Defines the public API surface for the generated client workspace: 'createHevyClient', client logging types, and 'HevyHttpError'/'isHevyHttpError' helpers.

packages/hevy-client/src/index.ts

index.tsAdd Node API entrypoints and wire core+client construction +22/-22

Add Node API entrypoints and wire core+client construction

• Replaces internal shared-server construction with '@hevy-mcp/core' + '@hevy-mcp/hevy-client', adds 'createNodeMcpServer({ apiKey })' and 'runStdioServer()', and plugs in a Node 'ToolObserver' for telemetry while keeping stdio behavior intact.

packages/node/src/index.ts

tool-observer.tsAdd Node ToolObserver emitting spans, metrics, and safe Sentry events +313/-0

Add Node ToolObserver emitting spans, metrics, and safe Sentry events

• Implements a 'ToolObserver' that records invocation and completion attributes (taxonomy, safe argument buckets, safe result summaries) to OpenTelemetry and emits privacy-preserving Sentry diagnostics for failures.

packages/node/src/utils/tool-observer.ts

Refactor (4) +89 / -56
server.tsRefactor server creation to injectable client + optional decorators +24/-33

Refactor server creation to injectable client + optional decorators

• Replaces a Node-key-based server constructor with 'createHevyMcpServer({ createClient, observer, decorateServer })', enabling Node/Worker runtimes to supply the correct client and instrumentation without leaking runtime-specific imports into core.

packages/core/src/server.ts

hevy-client.tsRename client factory to createHevyClient and refine options typing +18/-10

Rename client factory to createHevyClient and refine options typing

• Renames the exported factory to 'createHevyClient({ apiKey, baseUrl, ... })' and introduces request-scoped options typing to support consistent Node/Worker construction patterns.

packages/hevy-client/src/hevy-client.ts

cli.tsMove CLI entrypoint into Node workspace +18/-0

Move CLI entrypoint into Node workspace

• Adds a Node workspace CLI entrypoint that calls 'runStdioServer', preserves error handling (including missing API key messaging), and flushes telemetry before exiting on fatal errors.

packages/node/src/cli.ts

worker.tsUpdate Worker runtime to use core server factory + injected client creation +29/-13

Update Worker runtime to use core server factory + injected client creation

• Switches Worker MCP server creation to 'createHevyMcpServer({ createClient })' and builds per-request Hevy clients via 'createHevyClient({ apiKey, baseUrl, onLog })', maintaining existing HTTP/OAuth semantics while respecting runtime boundaries.

packages/worker/src/worker.ts

Tests (2) +334 / -4
package-boundaries.test.tsAdd unit tests for boundary checker edge cases +96/-0

Add unit tests for boundary checker edge cases

• Adds tests validating compiler-based inspection, detection of escaped relative imports and non-literal dynamic imports, enforcement of runtime forbiddance (Node builtins, 'cloudflare:'), and a guard against reintroducing root 'src/*' implementation files.

tests/unit/package-boundaries.test.ts

npm-pack-smoke.mjsUpdate npm pack smoke test to pack the hevy-mcp workspace +238/-4

Update npm pack smoke test to pack the hevy-mcp workspace

• Switches 'npm pack' to target the 'hevy-mcp' workspace and expands harness utilities for stronger packaging/install/runtime smoke verification consistent with the new workspace layout.

tests/package/npm-pack-smoke.mjs

Other (13) +726 / -56
package.jsonConvert root into private orchestration workspace +38/-42

Convert root into private orchestration workspace

• Renames the root package to '@hevy-mcp/repository', marks it private, declares 'packages/*' workspaces, and rewires scripts to run builds/tests/checks against workspace packages. Adds new check scripts for workspaces, boundaries, exports, release candidates, and Worker bundle validation.

package.json

package.jsonCreate publishable hevy-mcp Node workspace with export map +57/-0

Create publishable hevy-mcp Node workspace with export map

• Adds the public 'hevy-mcp' workspace with 'bin' wiring, a dist-only export map, and Node-only telemetry dependencies. Establishes this workspace as the sole publishable package.

packages/node/package.json

check-package-boundaries.mjsAdd AST-based package boundary checker with runtime rules +315/-0

Add AST-based package boundary checker with runtime rules

• Introduces a boundary enforcement script that inspects imports (via TypeScript compiler AST where possible) and enforces per-package allowed/forbidden dependencies, builtin import restrictions, dynamic import rules, and escape-proof relative import handling.

scripts/check-package-boundaries.mjs

check-package-exports.mjsValidate package export maps (no wildcards, stable targets) +77/-0

Validate package export maps (no wildcards, stable targets)

• Adds an export-map validator enforcing required export keys per workspace, forbidding wildcard exports, and requiring the public Node package exports to target built './dist/*' files only.

scripts/check-package-exports.mjs

check-workspaces.mjsEnforce single publishable workspace and root metadata rules +52/-0

Enforce single publishable workspace and root metadata rules

• Adds a workspace topology check ensuring the root is private, workspaces are exactly 'packages/*', and only 'hevy-mcp' is publishable; also forbids publish-related fields on the root package.json.

scripts/check-workspaces.mjs

check-release-candidates.mjsPrevent changesets from targeting private workspaces +41/-0

Prevent changesets from targeting private workspaces

• Adds a guard that fails CI if any changeset includes private workspace package names, and asserts only 'hevy-mcp' is publishable in the workspace tree.

scripts/check-release-candidates.mjs

check-worker-bundle.mjsScan Worker dry-run output for unresolved private imports +33/-0

Scan Worker dry-run output for unresolved private imports

• Adds a Worker bundle scan that fails if wrangler output contains private workspace specifiers (e.g., '@hevy-mcp/core') indicating unresolved workspace imports in the deployed artifact.

scripts/check-worker-bundle.mjs

server-manifest.mjsSupport syncing/checking server.json for packages/node during migration +43/-3

Support syncing/checking server.json for packages/node during migration

• Extends the server manifest tooling to optionally read/write 'packages/node/server.json' alongside the root 'server.json', and detects drift across both when present.

scripts/server-manifest.mjs

build-and-test.ymlAdd CI validations for boundaries/exports/topology and Worker bundle scan +16/-0

Add CI validations for boundaries/exports/topology and Worker bundle scan

• Adds parallel CI steps for workspace topology, package boundary enforcement, export-map validation, and release-candidate checks, plus a Worker dry-run build and post-scan step.

.github/workflows/build-and-test.yml

release.ymlUpdate release workflow to use Node workspace artifacts and pack verification +4/-2

Update release workflow to use Node workspace artifacts and pack verification

• Adds 'test:pack' as a release gate, updates diagnostics invocation to use 'packages/node/dist/cli.mjs', and fixes version extraction when multiple changesets are published.

.github/workflows/release.yml

DockerfileUpdate Docker build to consume Node workspace standalone output +11/-6

Update Docker build to consume Node workspace standalone output

• Updates build/runtime stages to Node 24 Alpine, copies workspace package manifests for install caching, builds standalone via workspace scripts, and copies the standalone artifact from 'packages/node/dist'.

Dockerfile

.dockerignoreAdjust Docker ignore rules for workspace-based builds +10/-3

Adjust Docker ignore rules for workspace-based builds

• Updates ignore/whitelist rules so the Docker build context includes the new 'packages/*' workspaces and required TS config files.

.dockerignore

server.jsonAdd workspace-local server.json manifest for publishable package +29/-0

Add workspace-local server.json manifest for publishable package

• Introduces a 'packages/node/server.json' copy aligned with the root manifest to support packaging/distribution checks while migration tooling keeps both in sync.

packages/node/server.json

@qodo-code-review

qodo-code-review Bot commented Jul 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 65 rules

Grey Divider


Remediation recommended

1. Missing package prepack build ✓ Resolved 🐞 Bug ☼ Reliability
Description
The publishable workspace package (packages/node) declares files: ["dist", ...] but has no
prepack/prepare lifecycle to ensure dist/ exists and is fresh when packing/publishing. This
makes npm pack --workspace hevy-mcp / npm publish --workspace hevy-mcp correctness depend on
external workflow ordering rather than the package’s own lifecycle.
Code

packages/node/package.json[R26-30]

+	"scripts": {
+		"build": "tsdown -c tsdown.config.ts",
+		"check:types": "tsc --noEmit -p tsconfig.json",
+		"build:standalone": "cross-env HEVY_MCP_BUILD_MODE=standalone tsdown -c tsdown.config.ts"
+	},
Relevance

⭐⭐ Medium

Repo already uses root prepack to build dist (PR574); no history for workspace publish packages/new
path.

PR-#574

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
packages/node/package.json requires dist to be present in the published tarball but only defines
manual build scripts; the pack smoke test explicitly runs npm run build before npm pack,
indicating artifacts are expected to be generated rather than committed. The root prepack exists
but is attached to a now-private root package, not the publishable workspace.

packages/node/package.json[9-30]
tests/package/npm-pack-smoke.mjs[100-113]
package.json[55-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`packages/node` is the publishable package and lists `dist` in `files`, but it does not define `prepack`/`prepare` to build `dist` automatically during `npm pack`/`npm publish`. This can produce missing/stale artifacts if someone packs/publishes without running `npm run build` first.

## Issue Context
The repo root is now a private orchestration workspace; its `prepack` won’t reliably protect workspace-level packing/publishing.

## Fix Focus Areas
- packages/node/package.json[1-57]

## Suggested fix
Add one of:
- `"prepack": "npm run build"` (minimal)
- or `"prepare": "npm run build"` (if you want installs-from-git to work too)

Optionally also run the manifest check in the same lifecycle (if desired for publishing): `node ../../scripts/server-manifest.mjs check`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. engines.node allows Node <24 📘 Rule violation § Compliance
Description
packages/node/package.json declares engines.node as >=20.0.0, which conflicts with the
requirement to set Node.js 24+ as the minimum supported runtime and may permit installations that
will fail at runtime. This mismatch is especially risky because repo scripts/tests use
import.meta.dirname, so on Node versions where it is undefined CI checks like
check:exports/check:release-candidates (and related tests) can crash before running validations.
Code

packages/node/package.json[R53-55]

+	"engines": {
+		"node": ">=20.0.0"
+	},
Relevance

⭐ Low

Team recently lowered engines.node to >=20 (PR491) and aligned docs (PR529); likely won’t raise to
24.

PR-#491
PR-#529

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2033932 requires the minimum Node.js engine to be 24.0.0 or higher, yet
packages/node/package.json explicitly sets engines.node to >=20.0.0, which allows unsupported
Node versions. At the same time, newly added scripts/tests compute repo paths via
import.meta.dirname while the repo engine range remains >=20.0.0, demonstrating a concrete
runtime expectation that can be stricter than what is advertised and creating a mismatch for
supported installations and CI execution.

Rule 2033932: Declare Node.js >= 24 as the minimum engine version
packages/node/package.json[53-55]
scripts/check-package-exports.mjs[1-5]
scripts/check-release-candidates.mjs[1-6]
tests/unit/package-readme.test.ts[1-6]
package.json[127-129]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The publishable Node workspace package (`packages/node`) declares `"engines": { "node": ">=20.0.0" }`, but compliance requires Node.js >= 24, and the repo now contains scripts/tests that rely on `import.meta.dirname` which can be undefined on some Node versions permitted by the current engine range; this can cause CI checks (e.g., `check:exports`, `check:release-candidates`) and related tests to crash before performing validations.

## Issue Context
PR Compliance ID 2033932 mandates declaring Node.js 24.0.0 or higher as the minimum engine. This PR introduces a new publishable Node workspace package (`packages/node`), so its `engines.node` semver range must reflect the true minimum runtime. Additionally, several scripts/tests compute paths using `import.meta.dirname` and are executed in CI via `npm run check:exports` and `npm run check:release-candidates`, with tests referencing those scripts as well.

## Fix Focus Areas
- packages/node/package.json[53-55]
- scripts/check-package-exports.mjs[1-10]
- scripts/check-release-candidates.mjs[1-6]
- tests/unit/package-readme.test.ts[1-7]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread packages/node/package.json
@chrisdoc chrisdoc changed the title feat!: split hevy-mcp into runtime-boundary packages feat: split hevy-mcp into runtime-boundary packages Jul 22, 2026

@gitstream-cm gitstream-cm Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨ PR Review

LGTM

Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Review using Guidelines Learn how

@chrisdoc
chrisdoc merged commit 7ae82c7 into main Jul 22, 2026
27 checks passed
@chrisdoc
chrisdoc deleted the codex/four-package-runtime-boundaries branch July 22, 2026 18:38
@github-actions github-actions Bot mentioned this pull request Jul 22, 2026
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 983 bytes (0.57%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
hevy-mcp-esm 173.22kB 983 bytes (0.57%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: hevy-mcp-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
src-CviK7j4l.mjs (New) 171.22kB 171.22kB 100.0% 🚀
cli.mjs 87 bytes 1.01kB 9.39% ⚠️
index.mjs -34 bytes 696 bytes -4.66%
index.d.mts -313 bytes 276 bytes -53.14%
src-Ch2aS5wP.mjs (Deleted) -169.98kB 0 bytes -100.0% 🗑️

Files in src-CviK7j4l.mjs:

  • ./src/index.ts → Total Size: 6.14kB

@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.73156% with 106 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.76%. Comparing base (bc01bb5) to head (29399e3).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
scripts/check-package-boundaries.mjs 58.97% 38 Missing and 10 partials ⚠️
packages/node/src/utils/tool-observer.ts 62.06% 11 Missing and 33 partials ⚠️
scripts/server-manifest.mjs 61.11% 4 Missing and 3 partials ⚠️
packages/core/src/tools/tool-runtime.ts 89.13% 3 Missing and 2 partials ⚠️
packages/core/src/observation.ts 92.30% 0 Missing and 1 partial ⚠️
packages/hevy-client/src/hevy-client-kubb.ts 87.50% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #715      +/-   ##
==========================================
- Coverage   94.52%   85.76%   -8.77%     
==========================================
  Files          50       51       +1     
  Lines        2266     2452     +186     
  Branches      639      689      +50     
==========================================
- Hits         2142     2103      -39     
- Misses         51      184     +133     
- Partials       73      165      +92     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant