Release v1.8.0 — Dogfood Fixes & Bulk Operations #40

Merged
Mike Bros merged 18 commits from release/1.8.0 into main 2026-03-16 13:24:01 +00:00
Contributor

Release v1.8.0 — Dogfood Fixes & Bulk Operations

Changes

  • OP#2270: Fix hardcoded MCP server version string
  • OP#2267: Improve project_id parameter descriptions and coercion
  • OP#2268: Cache activity lookups in log_time
  • OP#2269: Fix log_time activity 404 on project-scoped activities
  • OP#2264: Implement bulk_update_work_packages tool
  • OP#2265: Implement bulk_transition_work_packages tool
  • OP#2266: Add bulk operation tests
  • OP#2274: Improve tool descriptions for top-used tools
  • OP#2275: Deprioritize low-usage tool descriptions
  • OP#2276: Add TTL expiry to name-resolution caches
  • OP#2272: Create CLAUDE.md for agent guidance
  • OP#2271: Create CHANGELOG.md with retroactive entries
  • OP#2273: Update README.md with current state

Highlights

New tools: bulk_update_work_packages, bulk_transition_work_packages — batch operations that process items independently with 409 retry and partial failure handling.

Bug fixes: Dynamic MCP server version, project_id string-to-number coercion, activity caching and project-scoped 404 fallback in log_time.

DX improvements: CLAUDE.md agent guide, CHANGELOG.md, enriched tool descriptions, "Advanced:" prefix on low-usage tools, TTL-based cache expiry (5min default, configurable via CACHE_TTL_MS).

Tests: 253 total (11 new — 9 e2e bulk tool tests with mock API, 2 coercion tests).

Checklist

  • All version tasks closed in Gravity PM
  • Tests passing (253/253)
  • Version file matches Gravity PM version (1.8.0)
  • README and CHANGELOG are current

References

Version: 1.8.0 (Gravity PM)

## Release v1.8.0 — Dogfood Fixes & Bulk Operations ### Changes - OP#2270: Fix hardcoded MCP server version string - OP#2267: Improve project_id parameter descriptions and coercion - OP#2268: Cache activity lookups in log_time - OP#2269: Fix log_time activity 404 on project-scoped activities - OP#2264: Implement bulk_update_work_packages tool - OP#2265: Implement bulk_transition_work_packages tool - OP#2266: Add bulk operation tests - OP#2274: Improve tool descriptions for top-used tools - OP#2275: Deprioritize low-usage tool descriptions - OP#2276: Add TTL expiry to name-resolution caches - OP#2272: Create CLAUDE.md for agent guidance - OP#2271: Create CHANGELOG.md with retroactive entries - OP#2273: Update README.md with current state ### Highlights **New tools:** `bulk_update_work_packages`, `bulk_transition_work_packages` — batch operations that process items independently with 409 retry and partial failure handling. **Bug fixes:** Dynamic MCP server version, project_id string-to-number coercion, activity caching and project-scoped 404 fallback in log_time. **DX improvements:** CLAUDE.md agent guide, CHANGELOG.md, enriched tool descriptions, "Advanced:" prefix on low-usage tools, TTL-based cache expiry (5min default, configurable via CACHE_TTL_MS). **Tests:** 253 total (11 new — 9 e2e bulk tool tests with mock API, 2 coercion tests). ### Checklist - [x] All version tasks closed in Gravity PM - [x] Tests passing (253/253) - [x] Version file matches Gravity PM version (1.8.0) - [x] README and CHANGELOG are current ### References Version: 1.8.0 (Gravity PM)
The McpServer constructor was hardcoded to "1.4.0" despite the package
being at 1.7.0. Use the existing PKG_VERSION constant that already reads
from package.json at startup.

Closes OP#2270

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update all project_id parameter descriptions to include explicit examples
of both formats (numeric ID and slug). Add automatic coercion in
cleanStringParam so string-encoded integers like "8" are converted to
numbers before hitting the API.

Closes OP#2267

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Activity name resolution in log_time was fetching /time_entries/activities
on every call. Add getActivities() using the same getCached pattern as
getStatuses/getTypes/getPriorities to eliminate the redundant round-trip.

Closes OP#2268

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an activity name isn't found in the global cache, try resolving it
via the time entry form endpoint which returns project-scoped allowed
activities. If a resolved activity still returns 404 from the API,
retry without the activity field and include a warning in the response.

Closes OP#2269

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New MCP tool that accepts an array of work package updates and processes
them independently. Each item gets its own lockVersion fetch and 409
retry. Individual failures don't abort the batch — results are collected
and reported as a summary.

Closes OP#2264

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplified bulk tool for the most common pattern: transitioning multiple
WPs to the same status. Resolves the status name once, then applies to
all items with lockVersion fetch and 409 retry per item. Optionally adds
a comment to each WP after transition.

Closes OP#2265

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 9 e2e tests for bulk_update_work_packages and
bulk_transition_work_packages using a mock OpenProject API server.
Tests cover happy path, partial failure, empty input, name-to-ID
resolution, comments, invalid status, mixed results, and single-item
arrays. Also adds tests for cleanStringParam number coercion.

Closes OP#2266

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enhance descriptions for list_work_packages, get_work_package,
create_work_package, update_work_package, and log_time with inline
examples of common parameter patterns to reduce agent errors.

Closes OP#2274

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prefix admin_command, forum tools, and notification tools with
"Advanced:" to signal they exist but are not commonly needed,
reducing scanning noise for agents without removing functionality.

Closes OP#2275

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the never-expiring Map cache with a TTL-based cache that
refetches after 5 minutes (configurable via CACHE_TTL_MS env var).
Uses stale-while-revalidate pattern to prevent concurrent refetches
and returns stale data on fetch errors for resilience.

Closes OP#2276

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add repo-level instructions covering architecture, key patterns,
commands, testing, transports, env vars, and critical notes for
agents working on this codebase.

Closes OP#2272

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add changelog following Keep a Changelog format with entries for all
releases from v1.0.0-alpha through the current unreleased v1.8.0 work.

Closes OP#2271

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update tool count to 64, add bulk operations to feature highlights and
tool table, add CACHE_TTL_MS to config, and add dogfooding section.

Closes OP#2273

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chore(release): bump version to 1.8.0
Some checks failed
CI / lint (pull_request) Failing after 10s
CI / security (pull_request) Failing after 8s
CI / test (pull_request) Successful in 27s
629825b3c6
Refs OP#2277

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Contributor

🤖 PR Review: Release v1.8.0 — Dogfood Fixes & Bulk Operations

Verdict: Acceptable

No blocking findings. The PR is well-engineered with comprehensive error handling and consistent patterns across all changes. Tests pass (253/253). Two important items and several minor items noted below.


Findings Summary

Severity Count
🔴 Blocking 0
🟡 Important 2
🔵 Minor 4
Nitpick 2

🟡 Important

1. Lint violation: delete operator in log_time 404 fallback (index.js:2329)

Biome flags delete body._links.activity as a performance lint error. The suggested fix is body._links.activity = undefined. While functionally equivalent for JSON serialization (both omit the key), this will fail CI if lint is enforced in a pipeline.

// Current (line 2329)
delete body._links.activity;

// Biome recommendation
body._links.activity = undefined;

2. Cache TTL feature has zero test coverage

The new getCached() TTL logic (expiry, pending-flag concurrency prevention, stale-on-error fallback) is untested. This is a meaningful behavioral change — the cache previously never expired, and now it does with three distinct code paths (fresh, stale+pending, stale+refresh). Key scenarios to test:

  • Cache returns same data within TTL window
  • Cache expires and re-fetches after TTL
  • Stale data returned when refresh fails
  • Pending flag prevents concurrent refetches
  • CACHE_TTL_MS env var is respected

🔵 Minor

3. 409 conflict retry logic is untested in bulk operations

Both bulk_update_work_packages and bulk_transition_work_packages implement single-retry on 409 conflict (fetch fresh lockVersion, re-PATCH). The mock API never returns 409, so this entire code path is untested. Consider adding a mock that returns 409 on first PATCH attempt for a specific WP ID.

4. README tool count discrepancy

README line 2 claims "64 tools", but the deployment modes table (line 76) says "API tools (63)". Likely the difference is admin_command (Docker-only), but this should be clarified with a footnote or consistent count.

5. Bulk operation tests use broad assertions

Test assertions like assert.match(text, /Updated 2\/2/) verify counts but not which specific WP IDs succeeded or failed. More precise assertions would catch regressions in output formatting.

6. No test for zIdArray string preprocessing in bulk_transition

work_package_ids accepts CSV strings ("1,2,3") and JSON string arrays ("[1,2,3]") via preprocessing, but no test exercises these input formats.


Nitpick

7. cleanStringParam integer coercion could surprise callers

cleanStringParam("8") now returns 8 (number) instead of "8" (string). This is intentional for project_id union params, but the function name doesn't hint at numeric coercion. A brief JSDoc comment on the function would help future readers.

8. Cache TTL design comment

The stale-on-error strategy in getCached() favors availability over freshness — correct for reference data like statuses/priorities, but worth a one-line comment in the code explaining this design choice.


Smoke Test Results

Check Result
npm test 253/253 pass, 0 fail
npm run lint ⚠️ 2 errors (1 formatting in .claude/settings.local.json — not in PR; 1 delete operator in index.js:2329)

HUMAN REVIEW: Bulk operation batch size limits

The bulk tools accept unbounded arrays. For very large batches (100+ items), sequential processing could time out MCP tool calls. Consider whether a max batch size or warning threshold is warranted. This is a product decision outside the bot's scope.


What Looks Good

  • Cache TTL implementation is architecturally sound: triple-layered (fresh → stale+pending → refresh → stale-on-error)
  • Activity lookup fallback in log_time handles the real OpenProject quirk of project-scoped activities gracefully (global → project form → error, with 404 retry)
  • Bulk operations follow established patterns (lockVersion fetch, 409 retry, independent failure handling, clear reporting)
  • Tool description improvements will meaningfully help LLM tool selection
  • Docs are accurate and comprehensive — CLAUDE.md is an excellent agent guide

Review generated by Gravity Bot

## 🤖 PR Review: Release v1.8.0 — Dogfood Fixes & Bulk Operations **Verdict: Acceptable** No blocking findings. The PR is well-engineered with comprehensive error handling and consistent patterns across all changes. Tests pass (253/253). Two important items and several minor items noted below. --- ### Findings Summary | Severity | Count | |----------|-------| | 🔴 Blocking | 0 | | 🟡 Important | 2 | | 🔵 Minor | 4 | | ⚪ Nitpick | 2 | --- ### 🟡 Important **1. Lint violation: `delete` operator in log_time 404 fallback (`index.js:2329`)** Biome flags `delete body._links.activity` as a performance lint error. The suggested fix is `body._links.activity = undefined`. While functionally equivalent for JSON serialization (both omit the key), this will fail CI if lint is enforced in a pipeline. ```javascript // Current (line 2329) delete body._links.activity; // Biome recommendation body._links.activity = undefined; ``` **2. Cache TTL feature has zero test coverage** The new `getCached()` TTL logic (expiry, pending-flag concurrency prevention, stale-on-error fallback) is untested. This is a meaningful behavioral change — the cache previously never expired, and now it does with three distinct code paths (fresh, stale+pending, stale+refresh). Key scenarios to test: - Cache returns same data within TTL window - Cache expires and re-fetches after TTL - Stale data returned when refresh fails - Pending flag prevents concurrent refetches - `CACHE_TTL_MS` env var is respected --- ### 🔵 Minor **3. 409 conflict retry logic is untested in bulk operations** Both `bulk_update_work_packages` and `bulk_transition_work_packages` implement single-retry on 409 conflict (fetch fresh lockVersion, re-PATCH). The mock API never returns 409, so this entire code path is untested. Consider adding a mock that returns 409 on first PATCH attempt for a specific WP ID. **4. README tool count discrepancy** README line 2 claims "64 tools", but the deployment modes table (line 76) says "API tools (63)". Likely the difference is `admin_command` (Docker-only), but this should be clarified with a footnote or consistent count. **5. Bulk operation tests use broad assertions** Test assertions like `assert.match(text, /Updated 2\/2/)` verify counts but not which specific WP IDs succeeded or failed. More precise assertions would catch regressions in output formatting. **6. No test for `zIdArray` string preprocessing in `bulk_transition`** `work_package_ids` accepts CSV strings (`"1,2,3"`) and JSON string arrays (`"[1,2,3]"`) via preprocessing, but no test exercises these input formats. --- ### ⚪ Nitpick **7. `cleanStringParam` integer coercion could surprise callers** `cleanStringParam("8")` now returns `8` (number) instead of `"8"` (string). This is intentional for project_id union params, but the function name doesn't hint at numeric coercion. A brief JSDoc comment on the function would help future readers. **8. Cache TTL design comment** The stale-on-error strategy in `getCached()` favors availability over freshness — correct for reference data like statuses/priorities, but worth a one-line comment in the code explaining this design choice. --- ### Smoke Test Results | Check | Result | |-------|--------| | `npm test` | ✅ 253/253 pass, 0 fail | | `npm run lint` | ⚠️ 2 errors (1 formatting in .claude/settings.local.json — not in PR; 1 `delete` operator in index.js:2329) | --- ### HUMAN REVIEW: Bulk operation batch size limits The bulk tools accept unbounded arrays. For very large batches (100+ items), sequential processing could time out MCP tool calls. Consider whether a max batch size or warning threshold is warranted. This is a product decision outside the bot's scope. --- ### What Looks Good - **Cache TTL implementation** is architecturally sound: triple-layered (fresh → stale+pending → refresh → stale-on-error) - **Activity lookup fallback** in `log_time` handles the real OpenProject quirk of project-scoped activities gracefully (global → project form → error, with 404 retry) - **Bulk operations** follow established patterns (lockVersion fetch, 409 retry, independent failure handling, clear reporting) - **Tool description improvements** will meaningfully help LLM tool selection - **Docs** are accurate and comprehensive — CLAUDE.md is an excellent agent guide *Review generated by Gravity Bot*
Owner

@ai wrote in #40 (comment):

HUMAN REVIEW: Bulk operation batch size limits

The bulk tools accept unbounded arrays. For very large batches (100+ items), sequential processing could time out MCP tool calls. Consider whether a max batch size or warning threshold is warranted. This is a product decision outside the bot's scope.

I do think a max batch size is justified. I think that 100-250 would be plenty high while not being too high that a lot of heavy requests would break the http calls.

@ai wrote in https://git.bros.ninja/mike/open-project-sidecar-mcp/pulls/40#issuecomment-982: > ### [](#human-review-bulk-operation-batch-size-limits)HUMAN REVIEW: Bulk operation batch size limits > > The bulk tools accept unbounded arrays. For very large batches (100+ items), sequential processing could time out MCP tool calls. Consider whether a max batch size or warning threshold is warranted. This is a product decision outside the bot's scope. I do think a max batch size is justified. I think that 100-250 would be plenty high while not being too high that a lot of heavy requests would break the http calls.
fix(review): resolve lint violation and add cache TTL tests
Some checks failed
CI / lint (pull_request) Successful in 11s
CI / security (pull_request) Failing after 10s
CI / test (pull_request) Successful in 23s
1b55494f0b
Replace `delete` operator with undefined assignment in log_time 404
fallback to satisfy Biome linter (OP#2283). Export getCached/clearCache
and add 6 unit tests covering TTL expiry, stale-on-error fallback, and
concurrent refetch prevention (OP#2284).

Closes OP#2283 OP#2284

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Contributor

PR Review Followup

Responding to review posted on 2026-03-16 (review comment).

Review verdict was Acceptable — no blocking findings.

Triage Summary

Severity Count Action
Blocking 0
Important 2 Fixed in this branch
Minor 4 Deferred to v1.9.0
Nitpick 2 Deferred to v1.9.0
Human Review 1 Flagged — requires human judgment

Fixes Applied

The following findings have been resolved on this branch:

  1. [IMPORTANT] Lint violation: delete operator in log_time 404 fallback — fixed in 1b55494
    • OP#2283: fix: replace delete operator with undefined assignment (index.js:2329)
  2. [IMPORTANT] Cache TTL feature has zero test coverage — fixed in 1b55494
    • OP#2284: test: add unit tests for getCached TTL expiry logic

Deferred to v1.9.0

The following items have been tracked for the next version:

  1. [MINOR] 409 conflict retry logic is untested in bulk operations
    • OP#2285: test: add 409 conflict retry tests for bulk operations
  2. [MINOR] README tool count discrepancy (63 vs 64)
    • OP#2286: docs: clarify tool count discrepancy in README
  3. [MINOR] Bulk operation tests use broad assertions
    • OP#2287: test: improve bulk operation test assertion precision
  4. [MINOR] No test for zIdArray string preprocessing in bulk_transition
    • OP#2288: test: add zIdArray string preprocessing tests
  5. [NITPICK] cleanStringParam integer coercion could surprise callers
    • OP#2289: refactor: add JSDoc to cleanStringParam
  6. [NITPICK] Cache TTL design comment
    • OP#2290: refactor: add design comment to getCached

Human Review Items (Unchanged)

These items require human judgment and were not auto-triaged:

  1. HUMAN REVIEW: Bulk operation batch size limits — the bulk tools accept unbounded arrays; consider whether a max batch size or warning threshold is warranted.

Test Results

  • Tests: 259 passed, 0 failed, 0 skipped
  • All fixes verified: Yes

This followup was generated by the gr-pr-followup skill.

## PR Review Followup Responding to review posted on 2026-03-16 ([review comment](https://git.bros.ninja/mike/open-project-sidecar-mcp/pulls/40#issuecomment-982)). Review verdict was **Acceptable** — no blocking findings. ### Triage Summary | Severity | Count | Action | | -------- | ----- | ------ | | Blocking | 0 | — | | Important | 2 | Fixed in this branch | | Minor | 4 | Deferred to v1.9.0 | | Nitpick | 2 | Deferred to v1.9.0 | | Human Review | 1 | Flagged — requires human judgment | ### Fixes Applied The following findings have been resolved on this branch: 1. **[IMPORTANT]** Lint violation: `delete` operator in log_time 404 fallback — fixed in 1b55494 - [OP#2283](https://project.bros.ninja/work_packages/2283): fix: replace delete operator with undefined assignment (index.js:2329) 2. **[IMPORTANT]** Cache TTL feature has zero test coverage — fixed in 1b55494 - [OP#2284](https://project.bros.ninja/work_packages/2284): test: add unit tests for getCached TTL expiry logic ### Deferred to v1.9.0 The following items have been tracked for the next version: 1. **[MINOR]** 409 conflict retry logic is untested in bulk operations - [OP#2285](https://project.bros.ninja/work_packages/2285): test: add 409 conflict retry tests for bulk operations 2. **[MINOR]** README tool count discrepancy (63 vs 64) - [OP#2286](https://project.bros.ninja/work_packages/2286): docs: clarify tool count discrepancy in README 3. **[MINOR]** Bulk operation tests use broad assertions - [OP#2287](https://project.bros.ninja/work_packages/2287): test: improve bulk operation test assertion precision 4. **[MINOR]** No test for zIdArray string preprocessing in bulk_transition - [OP#2288](https://project.bros.ninja/work_packages/2288): test: add zIdArray string preprocessing tests 5. **[NITPICK]** cleanStringParam integer coercion could surprise callers - [OP#2289](https://project.bros.ninja/work_packages/2289): refactor: add JSDoc to cleanStringParam 6. **[NITPICK]** Cache TTL design comment - [OP#2290](https://project.bros.ninja/work_packages/2290): refactor: add design comment to getCached ### Human Review Items (Unchanged) These items require human judgment and were not auto-triaged: 1. **HUMAN REVIEW:** Bulk operation batch size limits — the bulk tools accept unbounded arrays; consider whether a max batch size or warning threshold is warranted. ### Test Results - **Tests:** 259 passed, 0 failed, 0 skipped - **All fixes verified:** Yes --- _This followup was generated by the gr-pr-followup skill._
fix(review): resolve all PR review findings and audit vulnerabilities
All checks were successful
CI / lint (pull_request) Successful in 12s
CI / security (pull_request) Successful in 8s
CI / test (pull_request) Successful in 25s
ea5e4fb5f8
- Add 409 conflict retry tests with mock simulation (OP#2285)
- Fix README tool count discrepancy: 64 tools, clarify admin_command (OP#2286)
- Improve bulk operation test assertions to verify specific WP IDs (OP#2287)
- Add zIdArray string preprocessing tests for CSV and JSON formats (OP#2288)
- Add JSDoc to cleanStringParam documenting numeric coercion (OP#2289)
- Add design comment to getCached explaining stale-on-error strategy (OP#2290)
- Fix npm audit vulnerabilities (hono, ajv, express-rate-limit)

Closes OP#2285 OP#2286 OP#2287 OP#2288 OP#2289 OP#2290

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Contributor

PR Review Followup (Updated)

Responding to review posted on 2026-03-16 (review comment).

All 8 findings have been resolved on this branch. No items deferred.

Triage Summary

Severity Count Action
Blocking 0
Important 2 Fixed in 1b55494
Minor 4 Fixed in ea5e4fb
Nitpick 2 Fixed in ea5e4fb
Human Review 1 Flagged — requires human judgment

Fixes Applied

  1. [IMPORTANT] Lint violation: delete operator in log_time 404 fallback — fixed in 1b55494
    • OP#2283: fix: replace delete operator with undefined assignment
  2. [IMPORTANT] Cache TTL feature has zero test coverage — fixed in 1b55494
    • OP#2284: test: add unit tests for getCached TTL expiry logic (6 tests)
  3. [MINOR] 409 conflict retry logic is untested in bulk operations — fixed in ea5e4fb
    • OP#2285: test: add 409 conflict retry tests (3 tests with mock 409 simulation)
  4. [MINOR] README tool count discrepancy (63 vs 64) — fixed in ea5e4fb
    • OP#2286: docs: clarify tool count and admin_command availability
  5. [MINOR] Bulk operation tests use broad assertions — fixed in ea5e4fb
    • OP#2287: test: assertions now verify specific WP IDs in output
  6. [MINOR] No test for zIdArray string preprocessing — fixed in ea5e4fb
    • OP#2288: test: add CSV string and JSON string array tests
  7. [NITPICK] cleanStringParam integer coercion could surprise callers — fixed in ea5e4fb
    • OP#2289: refactor: add JSDoc to cleanStringParam
  8. [NITPICK] Cache TTL design comment — fixed in ea5e4fb
    • OP#2290: refactor: add availability-over-freshness design comment

Additional Fix

  • npm audit vulnerabilities resolved: updated hono, ajv, @hono/node-server, express-rate-limit (0 vulnerabilities remaining)

Human Review Items (Unchanged)

  1. HUMAN REVIEW: Bulk operation batch size limits — the bulk tools accept unbounded arrays; consider whether a max batch size or warning threshold is warranted.

Test Results

  • Tests: 264 passed, 0 failed, 0 skipped (+11 from review start)
  • Lint: Clean (0 errors on project files)
  • Audit: Clean (0 vulnerabilities)
  • All fixes verified: Yes

This PR should now be ready for re-review.


This followup was generated by the gr-pr-followup skill.

## PR Review Followup (Updated) Responding to review posted on 2026-03-16 ([review comment](https://git.bros.ninja/mike/open-project-sidecar-mcp/pulls/40#issuecomment-982)). All 8 findings have been resolved on this branch. No items deferred. ### Triage Summary | Severity | Count | Action | | -------- | ----- | ------ | | Blocking | 0 | — | | Important | 2 | Fixed in `1b55494` | | Minor | 4 | Fixed in `ea5e4fb` | | Nitpick | 2 | Fixed in `ea5e4fb` | | Human Review | 1 | Flagged — requires human judgment | ### Fixes Applied 1. **[IMPORTANT]** Lint violation: `delete` operator in log_time 404 fallback — fixed in `1b55494` - [OP#2283](https://project.bros.ninja/work_packages/2283): fix: replace delete operator with undefined assignment 2. **[IMPORTANT]** Cache TTL feature has zero test coverage — fixed in `1b55494` - [OP#2284](https://project.bros.ninja/work_packages/2284): test: add unit tests for getCached TTL expiry logic (6 tests) 3. **[MINOR]** 409 conflict retry logic is untested in bulk operations — fixed in `ea5e4fb` - [OP#2285](https://project.bros.ninja/work_packages/2285): test: add 409 conflict retry tests (3 tests with mock 409 simulation) 4. **[MINOR]** README tool count discrepancy (63 vs 64) — fixed in `ea5e4fb` - [OP#2286](https://project.bros.ninja/work_packages/2286): docs: clarify tool count and admin_command availability 5. **[MINOR]** Bulk operation tests use broad assertions — fixed in `ea5e4fb` - [OP#2287](https://project.bros.ninja/work_packages/2287): test: assertions now verify specific WP IDs in output 6. **[MINOR]** No test for zIdArray string preprocessing — fixed in `ea5e4fb` - [OP#2288](https://project.bros.ninja/work_packages/2288): test: add CSV string and JSON string array tests 7. **[NITPICK]** cleanStringParam integer coercion could surprise callers — fixed in `ea5e4fb` - [OP#2289](https://project.bros.ninja/work_packages/2289): refactor: add JSDoc to cleanStringParam 8. **[NITPICK]** Cache TTL design comment — fixed in `ea5e4fb` - [OP#2290](https://project.bros.ninja/work_packages/2290): refactor: add availability-over-freshness design comment ### Additional Fix - **npm audit vulnerabilities** resolved: updated hono, ajv, @hono/node-server, express-rate-limit (0 vulnerabilities remaining) ### Human Review Items (Unchanged) 1. **HUMAN REVIEW:** Bulk operation batch size limits — the bulk tools accept unbounded arrays; consider whether a max batch size or warning threshold is warranted. ### Test Results - **Tests:** 264 passed, 0 failed, 0 skipped (+11 from review start) - **Lint:** Clean (0 errors on project files) - **Audit:** Clean (0 vulnerabilities) - **All fixes verified:** Yes This PR should now be ready for re-review. --- _This followup was generated by the gr-pr-followup skill._
feat(bulk): add max batch size limit of 200 to bulk operations
All checks were successful
CI / lint (pull_request) Successful in 10s
CI / security (pull_request) Successful in 9s
CI / test (pull_request) Successful in 25s
dddf39be0b
Both bulk_update_work_packages and bulk_transition_work_packages now
enforce a maximum batch size of 200 items via Zod .max() validation.
Prevents timeout issues from unbounded sequential API calls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Contributor

PR Review (Updated)

Verdict: Acceptable

This review was conducted from a fresh context against the current branch state (17 commits, 7 files). Focuses on findings not previously identified in the prior 4 comments.


Findings Summary

Severity Count
Blocking 0
Important 0
Minor 1
Nitpick 2

Minor

1. MCP_FOOTER duplication risk in bulk_update_work_packages (index.js:1712)

bulk_update_work_packages appends MCP_FOOTER unconditionally to descriptions. Sequential MCP updates to the same work package will accumulate duplicate footers. This is a pre-existing pattern shared with create_work_package and update_work_package, but bulk operations amplify the risk since batch workflows are more likely to re-update WPs.

Suggested fix: Strip existing footer before appending, or check whether the description already ends with it:

const raw = unescapeDescription(item.description);
const stripped = raw.replace(/\n\n---\n_Created via OpenProject MCP \(AI-assisted\)_$/, "");
body.description = { format: "markdown", raw: stripped + MCP_FOOTER };

Nitpick

2. CSV preprocessing produces opaque errors for non-numeric values (index.js:1796)

In bulk_transition_work_packages, the CSV string preprocessor val.split(",").map(s => Number(s.trim())) converts non-numeric values to NaN. Zod's .int() validator catches this, but the resulting error message won't indicate which element was invalid. For a bulk tool accepting user input, a more descriptive parse error would improve DX.

3. Pre-existing lint warnings (not introduced by this PR)

Biome reports 2 noUselessEscapeInRegex errors (lines 4814, 5198 — \Z in regex) and 2 noTemplateCurlyInString warnings (lines 5036, 5040 — intentional YAML template variables in the setup wizard). None are in code changed by this PR. Noting for awareness; these could be cleaned up in a future pass.


Test Results

  • Tests: 266 passed, 0 failed, 0 skipped
  • Lint: 3 errors, 2 warnings (all pre-existing, not in PR scope)

Previously Identified

8 findings from the prior review cycle have been resolved on this branch. These are not repeated as new findings.

Fixed in this branch:

  • OP#2283: Lint violation — delete operator replaced with undefined assignment
  • OP#2284: Cache TTL tests added (6 tests)
  • OP#2285: 409 conflict retry tests added (3 tests with mock 409 simulation)
  • OP#2286: README tool count clarified
  • OP#2287: Bulk test assertions now verify specific WP IDs
  • OP#2288: CSV/JSON string preprocessing tests added
  • OP#2289: JSDoc added to cleanStringParam
  • OP#2290: Availability-over-freshness design comment added

Human review item resolved:

  • Bulk operation batch size limit of 200 added in dddf39b (responding to reviewer feedback)

What Looks Good

  • All prior findings addressed — the branch is in markedly better shape than the first review
  • Batch size limit implementation is clean: MAX_BULK_BATCH_SIZE constant with Zod .max() enforcement and descriptive error message
  • Cache TTL tests thoroughly cover all code paths: fresh, expired, stale+pending, stale-on-error, first-fetch-error
  • 409 retry tests use mock server that simulates conflict on first PATCH attempt — realistic coverage
  • Test count grew from 253 → 266 (+13) across two fix commits, all passing
  • Code follows established patterns consistently — bulk tools mirror the lockVersion/retry pattern from update_work_package

Updated review — previous reviews posted on 2026-03-16. This is review cycle 2.


Review generated by Gravity Bot

## PR Review (Updated) **Verdict: Acceptable** This review was conducted from a fresh context against the current branch state (17 commits, 7 files). Focuses on findings not previously identified in the prior 4 comments. --- ### Findings Summary | Severity | Count | |----------|-------| | Blocking | 0 | | Important | 0 | | Minor | 1 | | Nitpick | 2 | --- ### Minor **1. `MCP_FOOTER` duplication risk in bulk_update_work_packages (`index.js:1712`)** `bulk_update_work_packages` appends `MCP_FOOTER` unconditionally to descriptions. Sequential MCP updates to the same work package will accumulate duplicate footers. This is a pre-existing pattern shared with `create_work_package` and `update_work_package`, but bulk operations amplify the risk since batch workflows are more likely to re-update WPs. **Suggested fix:** Strip existing footer before appending, or check whether the description already ends with it: ```javascript const raw = unescapeDescription(item.description); const stripped = raw.replace(/\n\n---\n_Created via OpenProject MCP \(AI-assisted\)_$/, ""); body.description = { format: "markdown", raw: stripped + MCP_FOOTER }; ``` --- ### Nitpick **2. CSV preprocessing produces opaque errors for non-numeric values (`index.js:1796`)** In `bulk_transition_work_packages`, the CSV string preprocessor `val.split(",").map(s => Number(s.trim()))` converts non-numeric values to `NaN`. Zod's `.int()` validator catches this, but the resulting error message won't indicate which element was invalid. For a bulk tool accepting user input, a more descriptive parse error would improve DX. **3. Pre-existing lint warnings (not introduced by this PR)** Biome reports 2 `noUselessEscapeInRegex` errors (lines 4814, 5198 — `\Z` in regex) and 2 `noTemplateCurlyInString` warnings (lines 5036, 5040 — intentional YAML template variables in the setup wizard). None are in code changed by this PR. Noting for awareness; these could be cleaned up in a future pass. --- ### Test Results - **Tests:** 266 passed, 0 failed, 0 skipped - **Lint:** 3 errors, 2 warnings (all pre-existing, not in PR scope) --- ### Previously Identified 8 findings from the prior review cycle have been resolved on this branch. These are not repeated as new findings. **Fixed in this branch:** - [OP#2283](https://project.bros.ninja/work_packages/2283): Lint violation — `delete` operator replaced with `undefined` assignment - [OP#2284](https://project.bros.ninja/work_packages/2284): Cache TTL tests added (6 tests) - [OP#2285](https://project.bros.ninja/work_packages/2285): 409 conflict retry tests added (3 tests with mock 409 simulation) - [OP#2286](https://project.bros.ninja/work_packages/2286): README tool count clarified - [OP#2287](https://project.bros.ninja/work_packages/2287): Bulk test assertions now verify specific WP IDs - [OP#2288](https://project.bros.ninja/work_packages/2288): CSV/JSON string preprocessing tests added - [OP#2289](https://project.bros.ninja/work_packages/2289): JSDoc added to `cleanStringParam` - [OP#2290](https://project.bros.ninja/work_packages/2290): Availability-over-freshness design comment added **Human review item resolved:** - Bulk operation batch size limit of 200 added in `dddf39b` (responding to reviewer feedback) --- ### What Looks Good - **All prior findings addressed** — the branch is in markedly better shape than the first review - **Batch size limit** implementation is clean: `MAX_BULK_BATCH_SIZE` constant with Zod `.max()` enforcement and descriptive error message - **Cache TTL tests** thoroughly cover all code paths: fresh, expired, stale+pending, stale-on-error, first-fetch-error - **409 retry tests** use mock server that simulates conflict on first PATCH attempt — realistic coverage - **Test count grew from 253 → 266** (+13) across two fix commits, all passing - **Code follows established patterns** consistently — bulk tools mirror the lockVersion/retry pattern from `update_work_package` *Updated review — previous reviews posted on 2026-03-16. This is review cycle 2.* --- *Review generated by Gravity Bot*
fix(review): resolve re-review findings — footer dedup, CSV errors, regex lint
All checks were successful
CI / lint (pull_request) Successful in 9s
CI / security (pull_request) Successful in 11s
CI / test (pull_request) Successful in 25s
c7cb0cbb8f
- Strip existing MCP_FOOTER before appending in bulk_update_work_packages
  to prevent duplicate footers on sequential updates
- Improve CSV preprocessing in bulk_transition to throw descriptive errors
  with position for non-numeric values instead of opaque NaN/Zod errors
- Replace useless \Z regex escape with $ in setup wizard (2 occurrences)

OP#2301 OP#2302 OP#2303

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Contributor

PR Review Followup

Responding to review posted on 2026-03-16 (review comment).

All 3 findings have been resolved on this branch. No items deferred.

Triage Summary

Severity Count Action
Blocking 0
Important 0
Minor 1 Fixed in this branch
Nitpick 2 Fixed in this branch
Human Review 0

Fixes Applied

  1. [MINOR] MCP_FOOTER duplication risk in bulk_update_work_packages — fixed in c7cb0cb
    • OP#2301: fix: strip duplicate MCP_FOOTER before appending in bulk_update (index.js)
  2. [NITPICK] CSV preprocessing produces opaque errors for non-numeric values — fixed in c7cb0cb
    • OP#2302: fix: improve CSV preprocessing error messages in bulk_transition (index.js)
  3. [NITPICK] Pre-existing useless regex escapes (\Z) in setup wizard — fixed in c7cb0cb
    • OP#2303: fix: remove useless regex escapes in setup wizard (index.js)

Test Results

  • Tests: 266 passed, 0 failed, 0 skipped
  • Lint: Reduced from 3 errors to 1 (remaining: pre-existing import ordering)
  • All fixes verified: Yes

This PR should now be ready for merge.


This followup was generated by the gr-pr-followup skill.

## PR Review Followup Responding to review posted on 2026-03-16 ([review comment](https://git.bros.ninja/mike/open-project-sidecar-mcp/pulls/40#issuecomment-997)). All 3 findings have been resolved on this branch. No items deferred. ### Triage Summary | Severity | Count | Action | | -------- | ----- | ------ | | Blocking | 0 | — | | Important | 0 | — | | Minor | 1 | Fixed in this branch | | Nitpick | 2 | Fixed in this branch | | Human Review | 0 | — | ### Fixes Applied 1. **[MINOR]** `MCP_FOOTER` duplication risk in `bulk_update_work_packages` — fixed in `c7cb0cb` - [OP#2301](https://project.bros.ninja/work_packages/2301): fix: strip duplicate MCP_FOOTER before appending in bulk_update (index.js) 2. **[NITPICK]** CSV preprocessing produces opaque errors for non-numeric values — fixed in `c7cb0cb` - [OP#2302](https://project.bros.ninja/work_packages/2302): fix: improve CSV preprocessing error messages in bulk_transition (index.js) 3. **[NITPICK]** Pre-existing useless regex escapes (`\Z`) in setup wizard — fixed in `c7cb0cb` - [OP#2303](https://project.bros.ninja/work_packages/2303): fix: remove useless regex escapes in setup wizard (index.js) ### Test Results - **Tests:** 266 passed, 0 failed, 0 skipped - **Lint:** Reduced from 3 errors to 1 (remaining: pre-existing import ordering) - **All fixes verified:** Yes This PR should now be ready for merge. --- _This followup was generated by the gr-pr-followup skill._
Mike Bros approved these changes 2026-03-16 13:23:53 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
mike/open-project-sidecar-mcp!40
No description provided.