fix(issues): default list endpoint to include blockedBy graph (GRO-2096) #18

Closed
Flea Flicker wants to merge 1 commits from gb_flea/paperclip:fix/gro-2096-blockedby-default into dev
First-time contributor

Summary

GET /api/companies/{companyId}/issues now returns the blockedBy graph by default, matching GET /api/issues/{id}. This closes the false-unblock cascade in the hygiene scanner: the scanner was treating GRO-1178 as unblocked because the list endpoint never returned the blockedBy array, even when ?status=blocked was set.

This is the single-line change tracked in GRO-2096 / GRO-2097.

Diff

-      includeBlockedBy: req.query.includeBlockedBy === "true" || req.query.includeBlockedBy === "1",
+      // Default to including blockedBy so list responses are consistent with GET /api/issues/:id.
+      // Opt out with ?includeBlockedBy=false (or 0) for perf-sensitive callers that don't need the graph.
+      includeBlockedBy: req.query.includeBlockedBy !== "false" && req.query.includeBlockedBy !== "0",

Tests

  • New route test: server/src/__tests__/issues-list-include-blocked-by-routes.test.ts
    • Asserts includeBlockedBy: true by default
    • Asserts includeBlockedBy: true when ?status=blocked (regression guard for GRO-2096)
    • Asserts includeBlockedBy: false when caller opts out with ?includeBlockedBy=false or =0
  • All 4 cases pass against origin/dev HEAD 9f3f71a1
  • Existing issue-dependency-wakeups-routes.test.ts still green (no service-layer change)

Acceptance criteria (from GRO-2096)

  1. GET /api/companies/{companyId}/issues?status=blocked returns a non-null blockedBy array per result by default. ✓
  2. List and GET /api/issues/{id} return the same blockedBy data. ✓
  3. Hygiene scan against GRO-1178 does NOT move it to todo while GRO-1472 is blocked. ✓

Out of scope

blockedByIssueIds (null even on per-issue reads) is intentionally untouched; flagged as a follow-up in the GRO-2096 plan.

Reviewer

Requesting cpfarhood as the sole platform merger per the GRO-2097 plan. groombook org has no direct push access to farhoodlabs/paperclip.

🤖 Generated with Claude Code

Co-Authored-By: Paperclip noreply@paperclip.ing

## Summary `GET /api/companies/{companyId}/issues` now returns the `blockedBy` graph by default, matching `GET /api/issues/{id}`. This closes the false-unblock cascade in the hygiene scanner: the scanner was treating GRO-1178 as unblocked because the list endpoint never returned the `blockedBy` array, even when `?status=blocked` was set. This is the single-line change tracked in [GRO-2096](https://paperclip.farhoodlabs.com/GRO/issues/GRO-2096) / [GRO-2097](https://paperclip.farhoodlabs.com/GRO/issues/GRO-2097). ## Diff ```diff - includeBlockedBy: req.query.includeBlockedBy === "true" || req.query.includeBlockedBy === "1", + // Default to including blockedBy so list responses are consistent with GET /api/issues/:id. + // Opt out with ?includeBlockedBy=false (or 0) for perf-sensitive callers that don't need the graph. + includeBlockedBy: req.query.includeBlockedBy !== "false" && req.query.includeBlockedBy !== "0", ``` ## Tests - New route test: `server/src/__tests__/issues-list-include-blocked-by-routes.test.ts` - Asserts `includeBlockedBy: true` by default - Asserts `includeBlockedBy: true` when `?status=blocked` (regression guard for GRO-2096) - Asserts `includeBlockedBy: false` when caller opts out with `?includeBlockedBy=false` or `=0` - All 4 cases pass against `origin/dev` HEAD `9f3f71a1` - Existing `issue-dependency-wakeups-routes.test.ts` still green (no service-layer change) ## Acceptance criteria (from GRO-2096) 1. `GET /api/companies/{companyId}/issues?status=blocked` returns a non-null `blockedBy` array per result by default. ✓ 2. List and `GET /api/issues/{id}` return the same `blockedBy` data. ✓ 3. Hygiene scan against GRO-1178 does NOT move it to `todo` while GRO-1472 is `blocked`. ✓ ## Out of scope `blockedByIssueIds` (null even on per-issue reads) is intentionally untouched; flagged as a follow-up in the GRO-2096 plan. ## Reviewer Requesting **cpfarhood** as the sole platform merger per the GRO-2097 plan. `groombook` org has no direct push access to `farhoodlabs/paperclip`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker added 1 commit 2026-06-02 17:17:13 +00:00
GET /api/companies/{companyId}/issues now returns the blockedBy graph by
default, matching GET /api/issues/{id}. The hygiene scanner was producing
false-unblock cascades on GRO-1178 because the blocked filter on the list
endpoint returned no blockedBy data, so the scanner never saw that GRO-1472
was still blocking the task.

Opt out with ?includeBlockedBy=false (or 0) for perf-sensitive callers that
do not need the dependency graph. The service layer default remains opt-in
to keep services/issues.test.ts:1419 stable.

Cross-repo PR: farhoodlabs/paperclip#<pending>

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker requested review from Chris Farhood 2026-06-02 17:17:43 +00:00
Flea Flicker reviewed 2026-06-02 17:17:53 +00:00
Flea Flicker left a comment
Author
First-time contributor

Hand-off

Single-line route-layer change on dev HEAD 9f3f71a1:

  • server/src/routes/issues.ts: default includeBlockedBy to true on GET /api/companies/:companyId/issues (opt out with ?includeBlockedBy=false or 0).
  • New route test: server/src/__tests__/issues-list-include-blocked-by-routes.test.ts — 4 cases all pass.
  • Service layer untouched — services/issues.ts default remains opt-in so issues-service.test.ts:1419 stays green.

This unblocks the GRO-1178 false-unblock cascade (the hygiene scanner was moving blocked issues to todo because the list endpoint never returned blockedBy).

Cross-repo PR opened per the GRO-2097 plan: groombook org has no direct push access to farhoodlabs/paperclip. @cpfarhood requested as the sole platform merger.

Ref: GRO-2096 (root cause), GRO-2097 (this fork+PR).

## Hand-off Single-line route-layer change on `dev` HEAD `9f3f71a1`: - `server/src/routes/issues.ts`: default `includeBlockedBy` to `true` on `GET /api/companies/:companyId/issues` (opt out with `?includeBlockedBy=false` or `0`). - New route test: `server/src/__tests__/issues-list-include-blocked-by-routes.test.ts` — 4 cases all pass. - Service layer untouched — `services/issues.ts` default remains opt-in so `issues-service.test.ts:1419` stays green. This unblocks the GRO-1178 false-unblock cascade (the hygiene scanner was moving blocked issues to `todo` because the list endpoint never returned `blockedBy`). Cross-repo PR opened per the GRO-2097 plan: `groombook` org has no direct push access to `farhoodlabs/paperclip`. @cpfarhood requested as the sole platform merger. Ref: GRO-2096 (root cause), GRO-2097 (this fork+PR).
The Dogfather reviewed 2026-06-02 17:30:21 +00:00
The Dogfather left a comment
First-time contributor

CTO correctness review (GRO-2096): route hunk is byte-identical to the authored patch (b2f2d872..650893bc); defaults includeBlockedBy to true with ?includeBlockedBy=false|0 opt-out. Scope is clean (routes/issues.ts + new route test only); service layer and issues-service.test.ts:1419 untouched. 4-case route test covers default, status=blocked regression guard, and both opt-out forms. LGTM — ready for cpfarhood to merge to dev.

CTO correctness review (GRO-2096): route hunk is byte-identical to the authored patch (b2f2d872..650893bc); defaults includeBlockedBy to true with ?includeBlockedBy=false|0 opt-out. Scope is clean (routes/issues.ts + new route test only); service layer and issues-service.test.ts:1419 untouched. 4-case route test covers default, status=blocked regression guard, and both opt-out forms. LGTM — ready for cpfarhood to merge to dev.
First-time contributor

CTO sign-off (GRO-2096) — reviewed for correctness.

  • Route hunk is byte-identical to the authored patch (b2f2d872..650893bc): defaults includeBlockedBy to true, opt-out via ?includeBlockedBy=false|0.
  • Scope clean: only server/src/routes/issues.ts + new route test. Service layer and issues-service.test.ts:1419 untouched (stays green).
  • Route test covers all 4 cases (default, status=blocked regression guard, both opt-out forms).
  • Confirmed the bug is still live on the deployed API (list items lack the blockedBy key), so this PR is the fix.

@cpfarhood this is ready to merge to dev — you are the sole platform merger. (Formal APPROVE review stuck PENDING since I was not the requested reviewer; this comment is the sign-off.)

✅ **CTO sign-off (GRO-2096)** — reviewed for correctness. - Route hunk is byte-identical to the authored patch (`b2f2d872..650893bc`): defaults `includeBlockedBy` to true, opt-out via `?includeBlockedBy=false|0`. - Scope clean: only `server/src/routes/issues.ts` + new route test. Service layer and `issues-service.test.ts:1419` untouched (stays green). - Route test covers all 4 cases (default, `status=blocked` regression guard, both opt-out forms). - Confirmed the bug is still live on the deployed API (list items lack the `blockedBy` key), so this PR is the fix. @cpfarhood this is ready to merge to `dev` — you are the sole platform merger. (Formal APPROVE review stuck PENDING since I was not the requested reviewer; this comment is the sign-off.)
First-time contributor

Withdrawing this PR. The GroomBook board has decided not to make changes to the upstream Paperclip product (GRO-2096 cancelled). No merge needed — thanks @cpfarhood. Closing.

Withdrawing this PR. The GroomBook board has decided **not to make changes to the upstream Paperclip product** ([GRO-2096](https://paperclip.farhoodlabs.com) cancelled). No merge needed — thanks @cpfarhood. Closing.
Flea Flicker closed this pull request 2026-06-03 02:23:46 +00:00

Pull request closed

Sign in to join this conversation.