Skip to content

pm context --depth full + --parent subtree scope; pm list --no-truncate (GH-156, GH-154, GH-155, GH-223) - #234

Merged
unbraind merged 4 commits into
mainfrom
feat/context-depth-full-parent-scope-list-no-truncate
Jun 14, 2026
Merged

unbraind merged 4 commits into
mainfrom
feat/context-depth-full-parent-scope-list-no-truncate

Conversation

@unbraind

Copy link
Copy Markdown
Owner

Summary

Context-retrieval ergonomics that serve the core philosophy project management = context management — surface richer project context in fewer agent round-trips.

pm context (GH-156 / pm-j0vc, pm-ds0m)

  • --depth full — comprehensive snapshot: every known section (ignoring the per-section settings toggles that brief/standard/deep respect) with no per-section row cap (overridable with an explicit --limit). New depth level in CONTEXT_DEPTH_VALUES.
  • --parent <id> — scope the focus items, hierarchy, agenda, and all derived sections to the anchor item plus its transitive descendants — the "what is the status of this epic?" view for large trackers. Reuses the existing buildChildrenByParent/collectDescendants helpers (no duplicate tree walk); case-insensitive anchor match; unknown anchor → NOT_FOUND. filters.parent is echoed and the markdown header gains a scope: subtree of <id> line.

pm list (GH-154 / pm-0c0j)

  • --no-truncate (alias --all) — force the full matched set, overriding any --limit in one call.
  • result.total — pre-pagination match count, emitted only when --limit/--offset actually dropped rows (both compact and verbose paths), so agents know how many remain.

Verified already-shipped + documented

--fields row-level projection from GH-156 is split to a focused follow-up (pm-hnjf) since it requires reshaping ContextResult focus-row types; --section already covers section-level customization.

Wiring

types · register-list-query options · normalize{List,Context}Options · CONTEXT/LIST flag contracts + commander-string-option contracts · MCP pm_context description · zsh/fish completions · contracts golden fixture · docs.

Tests

Unit + integration tests for every new branch (depth full/limit, subtree found/leaf/missing, no-truncate/total/compact-path, normalize mappings). Full coverage gate green (97.7/91.6/97.7/98), static-quality gate, contracts check, and docs-links gate all pass.

Manual verification

Sandbox tracker: context --depth full (10 sections, no cap), context --parent (subtree-scoped focus + scope: markdown line + NOT_FOUND on bad anchor), list --no-truncate/--all (override + no_truncate echo), list --limit (total surfaced), and all existing commands regression-clean.

Closes GH-156, GH-154, GH-155, GH-223.

🤖 Generated with Claude Code

…ate (GH-156, GH-154)

Context-retrieval ergonomics serving the core "project management = context
management" philosophy: surface richer project context in fewer agent calls.

pm context (GH-156 / pm-j0vc, pm-ds0m):
- --depth full: comprehensive snapshot — every known section (ignoring the
  per-section settings toggles brief/standard/deep respect) with no per-section
  row cap (overridable via an explicit --limit). New depth in CONTEXT_DEPTH_VALUES.
- --parent <id>: scope the focus items, hierarchy, agenda, and all derived
  sections to the anchor item plus its transitive descendants — the "status of
  this epic?" view for large trackers. Reuses the existing
  buildChildrenByParent/collectDescendants helpers (no duplicate tree walk);
  case-insensitive anchor match; unknown anchor → NOT_FOUND. filters.parent is
  echoed and the markdown header gains a "scope: subtree of <id>" line.

pm list (GH-154 / pm-0c0j):
- --no-truncate (alias --all): force the full matched set, overriding any --limit.
- result.total: pre-pagination match count, emitted only when --limit/--offset
  actually dropped rows, in both compact and verbose paths.

Already-shipped, verified + documented:
- GH-155 / pm-gcm3: pm get child rollup for Milestone/Epic (count/active/by_status).
- GH-223: --include-body pulls item bodies in bulk in one call (compact JSON stays
  token-light by default); documented prominently in COMMANDS.md / AGENT_GUIDE.md.

Wiring: types, register-list-query options, normalize{List,Context}Options,
CONTEXT/LIST flag contracts + commander-string-option contracts, MCP pm_context
description, zsh/fish completions, contracts golden fixture, docs. Unit +
integration tests for every new branch; full coverage gate green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @unbraind, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@unbraind

Copy link
Copy Markdown
Owner Author

@codex review
/gemini review
@gemini-code-assist please review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@unbraind, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 minutes and 9 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 9a9e89c7-f021-476b-9033-d4e94ee3416b

📥 Commits

Reviewing files that changed from the base of the PR and between e415062 and 63c70a2.

📒 Files selected for processing (2)
  • src/cli/commands/context.ts
  • tests/unit/context-command.spec.ts
📝 Walkthrough

Walkthrough

Adds three new pm CLI capabilities: pm list --no-truncate (alias --all) returns the full matched set overriding any --limit and surfaces a total pre-pagination count when rows are omitted; pm context --depth full removes per-section row caps; and pm context --parent <id> scopes the snapshot to an item's transitive descendant subtree. Shell completions, MCP tool descriptions, contracts, tests, and documentation are updated accordingly.

Changes

pm list --no-truncate/--all, pm context --depth full, and --parent subtree scoping

Layer / File(s) Summary
Shared type and SDK contract additions
src/types.ts, src/sdk/cli-contracts.ts, src/sdk/cli-contracts/commander-types.ts, src/sdk/cli-contracts/tool-option-contracts.ts, src/sdk/cli-contracts/tool-parameter-tables.ts
"full" is added to CONTEXT_DEPTH_VALUES/ContextDepth; --no-truncate (alias --all) is added to LIST_FILTER_FLAG_CONTRACTS; --parent is added to CONTEXT_FLAG_CONTRACTS, CONTEXT_COMMANDER_STRING_OPTION_CONTRACTS, and TOOL_CONTEXT_OPTION_CONTRACTS. Tool parameter tables extend depth enum to include "full" and add noTruncate boolean property/metadata.
pm list --no-truncate/--all with total count
src/cli/commands/list.ts, src/cli/register-list-query.ts, src/cli/registration-helpers.ts
ListOptions gains noTruncate, ListResultBase gains optional total. Pagination logic computes totalMatched and surfaces total only when rows are omitted; noTruncate overrides limit. CLI registration adds --no-truncate and hidden --all alias. normalizeListOptions maps truncate===false or all===true to noTruncate.
pm context --depth full and --parent subtree scoping
src/cli/commands/context.ts
ContextOptions gains parent; ContextResult.filters gains parent. parseContextLimit defaults limit to MAX_SAFE_INTEGER for depth=full; parseContextSections returns all sections for depth=full. collectSubtreeIds computes transitive descendants; parseContextParent validates the anchor id. runContext fetches the full corpus, filters items and agenda events to the subtree, throws NOT_FOUND if anchor is missing, and renders a scope: subtree of <id> line. New helpers exposed in _testOnly.
CLI registration, completion, and MCP wiring
src/cli/register-list-query.ts, src/cli/registration-helpers.ts, src/mcp/tool-definitions.ts, src/cli/commands/completion.ts
Context command gains --parent, --limit, --format, and updated --depth option registrations. normalizeContextOptions forwards parent. pm_context MCP tool description documents options.depth, options.parent, and options.section. Zsh and Fish completions gain --no-truncate/--all for list* and --parent/--limit/--depth for context|ctx.
Unit tests and contract fixture
tests/unit/list-command.spec.ts, tests/unit/context-command.spec.ts, tests/unit/registration-helpers.spec.ts, tests/fixtures/contracts/full.json
list-command.spec tests --no-truncate/total semantics and override behavior. context-command.spec covers parseContextDepth("full"), parseContextParent, collectSubtreeIds, parseContextSections with depth=full, and integration tests for --depth full and --parent. registration-helpers.spec covers noTruncate and parent normalization. full.json contract fixture is updated for all new flags, commander aliases, parent options, and the expanded MCP description.
Docs, changelog, and agent PM metadata
CHANGELOG.md, docs/COMMANDS.md, docs/AGENT_GUIDE.md, .agents/pm/features/..., .agents/pm/history/..., .agents/pm/stories/...
COMMANDS.md documents --no-truncate/total, --depth full, and --parent behaviors with examples. AGENT_GUIDE.md updates the token-minimal retrieval table. CHANGELOG.md records four new feature entries. Agent .toon feature/story files are created or closed (pm-0c0j, pm-ds0m, pm-gcm3, pm-hnjf, pm-j0vc, pm-kp1d) and corresponding .jsonl history records are updated. Extensions manifest timestamp updated.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as CLI (register-list-query)
  participant normalizeListOptions
  participant runList as runList (list.ts)
  participant Result as ListResult

  User->>CLI: pm list --no-truncate --limit 5
  CLI->>normalizeListOptions: truncate=false, limit=5
  normalizeListOptions->>runList: noTruncate=true, limit=5
  runList->>runList: noTruncate overrides limit → fetch all
  runList->>runList: compute totalMatched
  runList-->>Result: count=all_matched, no total field
  Result-->>User: full result set
Loading
sequenceDiagram
  participant User
  participant CLI as CLI (register-list-query)
  participant normalizeContextOptions
  participant runContext as runContext (context.ts)
  participant collectSubtreeIds
  participant Corpus as Item Corpus + Agenda

  User->>CLI: pm context --parent epic-1 --depth deep
  CLI->>normalizeContextOptions: parent="epic-1", depth="deep"
  normalizeContextOptions->>runContext: parentScope="epic-1"
  runContext->>Corpus: fetch full item corpus
  runContext->>collectSubtreeIds: "epic-1" + fullItems
  collectSubtreeIds-->>runContext: subtreeIds (transitive)
  alt anchor not found
    runContext-->>User: PmCliError NOT_FOUND
  end
  runContext->>Corpus: filter items to subtreeIds
  runContext->>Corpus: filter agenda.events to subtreeIds
  runContext-->>User: snapshot with "scope: subtree of epic-1"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • unbraind/pm-cli#188 — Adds MCP integration assertions for pm_context depth/compact projection behavior, directly intersecting with the pm_context depth option changes and MCP tool description updates in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: pm context new depth/parent options and pm list no-truncate flag, with associated issue references.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the objectives, implementation details, verified features, wiring, and test coverage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several context-retrieval and list ergonomics improvements to the pm CLI. Key additions include the pm context --depth full option to provide a comprehensive snapshot of all sections without per-section row caps, and pm context --parent <id> to scope the context snapshot to a single epic or parent subtree. Additionally, it adds pm list --no-truncate (alias --all) to override configured limits and surface a pre-pagination total count when results are truncated. The changes are accompanied by updated documentation, shell completions, MCP tool definitions, CLI contracts, and comprehensive unit tests. There are no review comments, so no further feedback is provided.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several context-retrieval ergonomics improvements to the pm CLI, including a new --depth full option for pm context to retrieve a comprehensive snapshot without per-section caps, a --parent <id> option to scope snapshots to a single epic/parent subtree, and a --no-truncate (alias --all) flag for pm list to override limits and return all matched rows. Additionally, it surfaces pre-pagination totals when results are truncated. The feedback suggests defensively checking that item.id is a string before calling .trim() in collectSubtreeIds to prevent potential runtime crashes on malformed user-defined front matter.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

// section relies on, so subtree membership stays consistent across the snapshot.
function collectSubtreeIds(corpus: ItemFrontMatter[], parentId: string): { ids: Set<string>; found: boolean } {
const target = parentId.trim().toLowerCase();
const anchor = corpus.find((item) => item.id.trim().toLowerCase() === target);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Defensively check that item.id is a string before calling .trim() on it. Since the CLI parses user-defined front matter from markdown files, a malformed file could have a missing or non-string id field, which would cause a runtime TypeError and crash the command.

Suggested change
const anchor = corpus.find((item) => item.id.trim().toLowerCase() === target);
const anchor = corpus.find((item) => typeof item.id === "string" && item.id.trim().toLowerCase() === target);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Declining: ItemFrontMatter.id is a non-optional string (src/types.ts:128) — the primary key derived from the item filename by the store loader, not arbitrary user front matter. It is consumed unguarded throughout this file (toContextFocusItem line 541, collectDescendants line 554, itemMap.set line 608, buildWorkload line 794/813), so a guard only in collectSubtreeIds would be inconsistent and wouldn't prevent a downstream crash anyway. Adding it would introduce an unreachable branch. The user-supplied --parent value is already trimmed/validated in parseContextParent.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agents/pm/features/pm-j0vc.toon:
- Line 3: Update the description field in this closed feature record to remove
the reference to the split-off `--fields` scope. The feature is closed as `pm
context --depth full` only, while the `--fields` functionality has been moved to
pm-hnjf. Edit the description to only describe what was shipped in this scope
(depth=full for context output and GitHub issue `#156`), removing any mention of
`--fields` customization. Apply the same cleanup to line 12 where this
description also appears.

In `@docs/COMMANDS.md`:
- Around line 120-125: The documentation in both files incorrectly states that
pm list* returns every matched row when no --limit is set, but this omits that
--offset alone also causes truncation. In docs/COMMANDS.md lines 120-125, change
the opening sentence to state "when neither --limit nor --offset is set" instead
of "when no --limit is set". Apply the identical wording change to
docs/AGENT_GUIDE.md lines 120-125 in the token-minimal retrieval note to ensure
both files accurately describe pagination behavior.

In `@src/cli/commands/context.ts`:
- Around line 1175-1178: When parent subtree scoping is needed (when
needsAllItems or parentScope is defined), the code must retrieve the complete
set of items without pagination constraints to accurately resolve parent
relationships. Currently, the allListOptions object inherits pagination controls
from baseListOptions, causing runList to return truncated results which leads to
incomplete or incorrect parent scope resolution. Remove pagination controls
(limit and offset) from allListOptions when parent scoping is required so that
the full item set is available for parent subtree evaluation. This same issue
applies at the other affected locations (around lines 1183-1190 and 1220-1231)
where agenda.events are similarly built with inherited pagination controls that
need to be disabled when parent scoping is active.

In `@tests/fixtures/contracts/full.json`:
- Around line 1601-1603: The schema definitions for action "context" and action
"ctx" in the contract fixture file need to be updated to match the newly added
command flags. For both the action: "context" and action: "ctx" schema blocks
(at lines 1601-1603 and also at lines 1990-1992 and 5898-5903), add the parent
property to the schema and update the depth enum constraint to include "full" in
addition to the existing "brief", "standard", and "deep" values. With
additionalProperties set to false, these schema changes are necessary to make
the new --parent flag and depth=full option valid according to the contract.
- Around line 2795-2800: The list-family action schemas in full.json have strict
validation (additionalProperties: false) but are missing the `--no-truncate` and
`--all` flag definitions that are present in the command_flags section. Add the
`--no-truncate` flag with alias `--all` to the schema definitions for all eight
list-family action blocks (list, list-all, list-draft, list-open,
list-in-progress, list-blocked, list-closed, list-canceled) by including the
flag object with its aliases in each action's schema oneOf block, matching the
structure shown in the command_flags section.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: f3828979-1ec2-43de-a631-b1168571004c

📥 Commits

Reviewing files that changed from the base of the PR and between ded3744 and c316a41.

📒 Files selected for processing (29)
  • .agents/pm/extensions/.managed-extensions.json
  • .agents/pm/features/pm-0c0j.toon
  • .agents/pm/features/pm-ds0m.toon
  • .agents/pm/features/pm-gcm3.toon
  • .agents/pm/features/pm-hnjf.toon
  • .agents/pm/features/pm-j0vc.toon
  • .agents/pm/history/pm-0c0j.jsonl
  • .agents/pm/history/pm-ds0m.jsonl
  • .agents/pm/history/pm-gcm3.jsonl
  • .agents/pm/history/pm-hnjf.jsonl
  • .agents/pm/history/pm-j0vc.jsonl
  • .agents/pm/history/pm-kp1d.jsonl
  • .agents/pm/stories/pm-kp1d.toon
  • CHANGELOG.md
  • docs/AGENT_GUIDE.md
  • docs/COMMANDS.md
  • src/cli/commands/completion.ts
  • src/cli/commands/context.ts
  • src/cli/commands/list.ts
  • src/cli/register-list-query.ts
  • src/cli/registration-helpers.ts
  • src/mcp/tool-definitions.ts
  • src/sdk/cli-contracts.ts
  • src/sdk/cli-contracts/commander-types.ts
  • src/types.ts
  • tests/fixtures/contracts/full.json
  • tests/unit/context-command.spec.ts
  • tests/unit/list-command.spec.ts
  • tests/unit/registration-helpers.spec.ts

Comment thread .agents/pm/features/pm-j0vc.toon Outdated
id: pm-j0vc
title: pm context --depth full and --fields projection customization (GH-156)
title: "pm context --depth full: comprehensive snapshot (all sections, no per-section cap) (GH-156)"
description: "Add depth=full (all items with status) and --fields to customize per-row projection in context output. GitHub issue #156. Related: pm-ds0m (subtree scoping)."

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Drop the split-off --fields scope from this closed feature.

This record is closed as pm context --depth full, but the description still claims --fields belongs to GH-156. Since pm-hnjf now owns that follow-up, the closed feature metadata should only describe the shipped scope.

Proposed cleanup
-description: "Add depth=full (all items with status) and --fields to customize per-row projection in context output. GitHub issue `#156`. Related: pm-ds0m (subtree scoping)."
+description: "Add depth=full (all items with status) in context output. GitHub issue `#156`. Related: pm-ds0m (subtree scoping)."

Also applies to: 12-12

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agents/pm/features/pm-j0vc.toon at line 3, Update the description field in
this closed feature record to remove the reference to the split-off `--fields`
scope. The feature is closed as `pm context --depth full` only, while the
`--fields` functionality has been moved to pm-hnjf. Edit the description to only
describe what was shipped in this scope (depth=full for context output and
GitHub issue `#156`), removing any mention of `--fields` customization. Apply the
same cleanup to line 12 where this description also appears.

Comment thread docs/COMMANDS.md Resolved
Comment thread src/cli/commands/context.ts Resolved
Comment thread tests/fixtures/contracts/full.json Resolved
Comment thread tests/fixtures/contracts/full.json Resolved
… full/no-truncate in strict action schemas (CodeRabbit)

Addresses CodeRabbit review on PR #234:

- MAJOR: --parent subtree scoping ran against paginated reads. The structural
  corpus fetches (allItems, the active set when scoping, and the agenda) still
  inherited --limit/--offset, so `pm context --parent X --limit N` could resolve
  the subtree against a truncated corpus → false NOT_FOUND for an anchor that
  paginated out of view, plus incomplete agenda. --limit/--offset are per-section
  display caps (applied later via .slice), not corpus filters, so the structural
  reads now run unpaginated; the agenda pulls the full set before subtree filter.
- MAJOR: strict MCP action schemas (additionalProperties:false) rejected the new
  options. Added `parent` to TOOL_CONTEXT_OPTION_CONTRACTS, `noTruncate` to the
  list-family contract keys + parameter property/metadata, and `full` to the
  shared `depth` enum (+ description). Regenerated the contract golden fixture.
- Docs: clarify list returns every row only when neither --limit nor --offset is
  set (offset alone also truncates).
- pm-j0vc description: drop the split-off --fields scope (now owned by pm-hnjf).

Coverage gate green (97.7/91.7/97.7/98); static/contracts/docs-links gates pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@unbraind

Copy link
Copy Markdown
Owner Author

Thanks @coderabbitai — all findings addressed in e415062:

  1. [Major] --parent after paginated reads — fixed. The structural corpus reads (allItems, the active set when scoping, and the agenda) now run unpaginated (noTruncate, limit/offset stripped). --limit/--offset are per-section display caps applied later via .slice, not corpus filters. Verified: pm context --parent <epic> --limit 1 now resolves the anchor instead of a false NOT_FOUND.
  2. [Major] strict action schemas reject new options — fixed at the source (not the fixture). Added parent to TOOL_CONTEXT_OPTION_CONTRACTS, noTruncate to the list-family contract keys + parameter property/metadata, and full to the shared depth enum. Regenerated tests/fixtures/contracts/full.json (pnpm contracts:update) — context/ctx now expose parent + depth: full, all 8 list actions expose noTruncate.
  3. [Minor] docs offset truncation — fixed: "returns every matched row when neither --limit nor --offset is set" in both COMMANDS.md and AGENT_GUIDE.md.
  4. [Minor] pm-j0vc description — fixed: dropped the split-off --fields scope (now owned by pm-hnjf). Kept the close_reason mention since it accurately documents the split.

For the Gemini item.id string-guard: declined — ItemFrontMatter.id is a non-optional string (the store-derived primary key) consumed unguarded throughout context.ts; a lone guard would be inconsistent and unreachable.

@coderabbitai review
@codex review
/gemini review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

@unbraind Thanks for the thorough rundown of fixes in e415062! All four items look well-resolved:

  1. --parent + paginated reads — Correct approach: pulling the full corpus unpaginated for anchor resolution and then applying --limit/--offset as display-only caps via .slice is the right separation of concerns.
  2. Strict action schemas — Fixing at the source (contracts + regenerated fixture) is cleaner than patching just the fixture.
  3. Docs offset clarification — Good catch, the --offset-alone truncation case was worth calling out explicitly.
  4. pm-j0vc description — Makes sense to drop the --fields scope now that it lives under pm-hnjf.

The item.id guard decline is also sound — adding an isolated guard for a non-optional store-derived key would be inconsistent with the rest of context.ts.

Kicking off a fresh review of the updated branch now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several context-retrieval ergonomics improvements, including a new --depth full option for pm context to provide a comprehensive snapshot without per-section caps, a --parent <id> option to scope context snapshots to a single subtree, and a --no-truncate (alias --all) flag for pm list to override limits and return all matched rows. It also updates shell completions, MCP tool definitions, and documentation. A critical issue was identified in the implementation of --parent where filtering allItems globally to the subtree will break metadata resolution for blockers/dependencies outside the subtree and cause incorrect unparented/hygiene warnings; it is recommended to keep allItems unfiltered as a reference corpus and only filter a copy for specific rollups.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/cli/commands/context.ts Outdated
Comment on lines +1203 to +1204
listedFrontMatter = listedFrontMatter.filter((item) => subtreeIds?.has(item.id));
allItems = allItems.filter((item) => subtreeIds?.has(item.id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Filtering allItems globally to only contain subtree items will cause issues in other sections of the context snapshot:

  1. Blockers/Dependencies: Any blocker or dependency pointing to an item outside the subtree will fail to resolve its metadata (title, status) because that item is no longer in allItems. This results in them being rendered as unknown <id>.
  2. Unparented/Hygiene Checks: The anchor item (or other top-level items in the subtree) may be incorrectly flagged as 'unparented' or having invalid parent links because their parents (which lie outside the subtree) are filtered out of allItems.

Suggestion: Keep the full, unfiltered allItems as the reference corpus for resolving item metadata (like blockers and parent links), and only filter a copy of it (e.g., subtreeItems) when passing it to sections that specifically build hierarchical or progress rollups (like hierarchy or progress).

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in f9f9a54. Point 1 (blocker cross-references) was valid: itemMap now builds from the unfiltered fullCorpus so a subtree item blocked by an item outside the subtree keeps its blocked_by title/status; only the enumeration sets stay subtree-scoped. Added an integration test verifying the cross-subtree blocker resolves. Point 2 (anchor flagged unparented) does not occur — buildUnparented only flags items with no parent (!normalizedParentId(item.parent)), and the anchor has a parent.

…us (Gemini)

Addresses Gemini high-priority review on PR #234: filtering allItems globally to
the subtree dropped cross-subtree blocker references. A subtree item blocked by an
item OUTSIDE the subtree lost its blocked_by title/status (rendered as a bare id),
because itemMap was built from the subtree-filtered set.

Keep the unfiltered corpus (`fullCorpus`) as the reference for cross-item metadata
resolution and build itemMap from it, while the enumeration sets (focus/hierarchy/
progress/recently_created/unparented/workload/staleness) stay subtree-scoped.

(Gemini's second point — anchor flagged "unparented" — does not occur:
buildUnparented only flags items with no parent, and the anchor has one.)

Adds integration coverage for cross-subtree blocker resolution and for the
unpaginated-corpus fix (tight --limit no longer triggers a false NOT_FOUND).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@unbraind

Copy link
Copy Markdown
Owner Author

Pushed f9f9a54 addressing the Gemini high-priority finding (cross-subtree blocker metadata now resolves against the full corpus). Re-requesting review.

@coderabbitai review
/gemini review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

@unbraind Understood — blocker metadata resolution against the full corpus rather than the scoped subtree is the right fix for that cross-subtree reference case. Kicking off a fresh review of commit f9f9a54 now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several context-retrieval ergonomics improvements, including the --depth full option for pm context to retrieve a comprehensive snapshot without per-section caps, the --parent <id> option to scope context snapshots to a single subtree, and the --no-truncate (alias --all) flag for pm list to override limits and surface pre-pagination totals. It also updates documentation, shell completions, MCP tool definitions, and unit tests. The review feedback highlights a critical improvement opportunity to ensure robust case-insensitive matching by normalizing and trimming IDs to lowercase when building and querying the subtreeIds set across collectSubtreeIds, list filters, and agenda event filters.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +402 to +412
function collectSubtreeIds(corpus: ItemFrontMatter[], parentId: string): { ids: Set<string>; found: boolean } {
const target = parentId.trim().toLowerCase();
const anchor = corpus.find((item) => item.id.trim().toLowerCase() === target);
if (!anchor) {
return { ids: new Set<string>(), found: false };
}
const childrenByParent = buildChildrenByParent(corpus);
const descendants = collectDescendants(anchor.id, childrenByParent);
const ids = new Set<string>([anchor.id, ...descendants.map((item) => item.id)]);
return { ids, found: true };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

To ensure robust case-insensitive matching and prevent potential bugs where mixed-case IDs in the corpus fail to match, the ids set returned by collectSubtreeIds should store normalized (lowercase and trimmed) IDs. This guarantees that case-sensitive .has() checks on the resulting set work reliably regardless of the original casing in the files.

function collectSubtreeIds(corpus: ItemFrontMatter[], parentId: string): { ids: Set<string>; found: boolean } {
  const target = parentId.trim().toLowerCase();
  const anchor = corpus.find((item) => item.id.trim().toLowerCase() === target);
  if (!anchor) {
    return { ids: new Set<string>(), found: false };
  }
  const childrenByParent = buildChildrenByParent(corpus);
  const descendants = collectDescendants(anchor.id, childrenByParent);
  const ids = new Set<string>([
    anchor.id.trim().toLowerCase(),
    ...descendants.map((item) => item.id.trim().toLowerCase())
  ]);
  return { ids, found: true };
}

Comment thread src/cli/commands/context.ts Outdated
Comment on lines +1207 to +1208
listedFrontMatter = listedFrontMatter.filter((item) => subtreeIds?.has(item.id));
allItems = allItems.filter((item) => subtreeIds?.has(item.id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Since subtreeIds now stores normalized lowercase IDs, we must normalize the lookup keys to lowercase as well to ensure the case-sensitive Set.has() check succeeds.

Suggested change
listedFrontMatter = listedFrontMatter.filter((item) => subtreeIds?.has(item.id));
allItems = allItems.filter((item) => subtreeIds?.has(item.id));
listedFrontMatter = listedFrontMatter.filter((item) => subtreeIds?.has(item.id.trim().toLowerCase()));
allItems = allItems.filter((item) => subtreeIds?.has(item.id.trim().toLowerCase()));

Comment thread src/cli/commands/context.ts Outdated
Comment on lines +1248 to +1251
const scopedAgenda =
subtreeIds === undefined
? agenda.events
: agenda.events.filter((event) => subtreeIds.has(event.item_id));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Normalize the event.item_id to lowercase when checking against subtreeIds to ensure case-insensitive matching for agenda events.

Suggested change
const scopedAgenda =
subtreeIds === undefined
? agenda.events
: agenda.events.filter((event) => subtreeIds.has(event.item_id));
const scopedAgenda =
subtreeIds === undefined
? agenda.events
: agenda.events.filter((event) => subtreeIds.has(event.item_id.trim().toLowerCase()));

…o-end (Gemini)

collectSubtreeIds now stores trimmed-lowercase ids and the listed/all/agenda
membership checks lowercase their lookup keys, making --parent subtree matching
explicitly case-insensitive regardless of id casing in the corpus. Behaviour is
unchanged for the canonical lowercase ids pm emits; this just removes any latent
case-sensitivity assumption.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@unbraind

Copy link
Copy Markdown
Owner Author

@gemini-code-assist follow-up addressed in 63c70a2 + f9f9a54:

  • Cross-subtree blocker metadata (allItems filter) — fixed in f9f9a54: itemMap is now built from the unfiltered fullCorpus, so a subtree item whose blocked_by points outside the subtree still resolves its title/status. Only the enumeration sets (focus/hierarchy/progress/etc.) stay subtree-scoped. The "anchor flagged unparented" case does not occur — buildUnparented only flags items with no parent (!normalizedParentId(item.parent)), and the anchor has a parent.
  • Case-insensitive subtree ids — applied in 63c70a2: collectSubtreeIds stores trimmed-lowercase ids and the listed/all/agenda membership checks lowercase their lookup keys, so matching is case-insensitive end-to-end.

@coderabbitai review
/gemini review

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

@unbraind Both follow-up fixes look well-reasoned:

  • Cross-subtree blocker metadata — Building itemMap from the unfiltered fullCorpus while keeping the enumeration sets (focus/hierarchy/progress/etc.) subtree-scoped is the correct separation of concerns. Blockers pointing outside the subtree will now resolve title/status correctly.
  • Case-insensitive subtree IDs — Storing trimmed-lowercase ids in collectSubtreeIds and lowercasing lookup keys at membership-check sites is a clean, consistent approach.

Kicking off a fresh review of the updated branch now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several context-retrieval ergonomics improvements, including the --depth full option for pm context to provide a comprehensive snapshot of all sections without per-section row caps, and the --parent <id> option to scope the context snapshot to a single epic or parent subtree. Additionally, it adds the --no-truncate (alias --all) flag to pm list commands to override any limits and return all matched rows, while also reporting the pre-pagination total when results are truncated. Review feedback highlights a potential TypeError when filtering calendar events with null or undefined item_id values, and suggests slicing the ranked focus items by the specified limit when scoping by parent to ensure user-specified limits are respected.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

const scopedAgenda =
subtreeIds === undefined
? agenda.events
: agenda.events.filter((event) => subtreeIds.has(event.item_id.trim().toLowerCase()));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

If event.item_id is null or undefined (which can happen for external or generic calendar events), calling event.item_id.trim() will throw a TypeError and crash the command. We should add a safety guard to ensure event.item_id is defined before calling .trim().

Suggested change
: agenda.events.filter((event) => subtreeIds.has(event.item_id.trim().toLowerCase()));
: agenda.events.filter((event) => event.item_id && subtreeIds.has(event.item_id.trim().toLowerCase()));

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Declining — false positive. CalendarRow.item_id is a non-optional string (calendar.ts:66), always set from item.id when each row is built (calendar.ts:599/622/667) and consumed unguarded elsewhere (calendar.ts:851, 932). It cannot be null/undefined, so .trim() is safe here.

allItems = allItems.filter((item) => subtreeIds?.has(item.id.trim().toLowerCase()));
}

const ranked = [...listedFrontMatter].sort((left, right) => compareCriticalItems(left, right, statusRegistry));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

When parentScope is defined, listedFrontMatter is fetched without a limit. If the high_level and low_level focus sections are not sliced by limit during their construction from ranked, they will display all active items in the subtree, overriding any user-specified --limit. To guarantee that the limit is respected, we should slice ranked by limit when parentScope is defined.

Suggested change
const ranked = [...listedFrontMatter].sort((left, right) => compareCriticalItems(left, right, statusRegistry));
const sortedRanked = [...listedFrontMatter].sort((left, right) => compareCriticalItems(left, right, statusRegistry));
const ranked = parentScope === undefined ? sortedRanked : sortedRanked.slice(0, limit);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Declining — false positive. --limit is already respected: highLevel and lowLevel each .slice(0, limit) (lines 1228/1232), and agendaEvents slices too. Verified: pm context --parent <epic> --limit 1 returns 2 focus rows (1 high + 1 low), not the whole subtree. The unpaginated listedFrontMatter only ensures correct subtree resolution before the per-section slice.

@unbraind
unbraind merged commit b7fa83c into main Jun 14, 2026
15 checks passed
unbraind added a commit that referenced this pull request Jun 14, 2026
…drift

- pm-ldr1: follow-up Feature for the remaining GH-157 asks not covered by #238
  (structured inline tag:/status: query syntax + matched-text highlighting).
- pm history-repair pm-j0vc: re-anchor a pre-existing single-item hash mismatch
  (from #234) so `pm health` is ok:true again. Audited, verify_ok:true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@unbraind
unbraind deleted the feat/context-depth-full-parent-scope-list-no-truncate branch June 15, 2026 06:06
@unbraind

unbraind commented Aug 4, 2026

Copy link
Copy Markdown
Owner Author

PM context: pm-0c0j. Historical linkage verified during the 2026-08-04 ecosystem review. This comment records canonical context only; it does not reopen or change this artifact.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pm context: Support --depth full and --fields customization for comprehensive project snapshots

1 participant