Skip to content

v0.7.0: the PM verbs — list PRs, merge-readiness get_pr, issue comments, search-before-filing, body-gated create_issue - #28

Merged
mabry1985 merged 2 commits into
mainfrom
feat/v0.7.0-pm-verbs
Aug 23, 2026
Merged

mabry1985 merged 2 commits into
mainfrom
feat/v0.7.0-pm-verbs

Conversation

@mabry1985

@mabry1985 mabry1985 commented Aug 23, 2026

Copy link
Copy Markdown
Member

v0.7.0 — the PM verbs

The verbs a Project Manager needs that the GitHub rail still lacked after v0.6.0: see the PR board, judge a PR's merge readiness in one call, read a thread, and search before filing — with issue creation held to the same gate /issue already enforces. The repo keeps no CHANGELOG; this body is it (PROTO.md §7).

Deliverables

  1. github_list_prs(repo?, state="open", limit=30) — number / title / author / state / draft / head -> base / reviewDecision / mergeStateStatus / url per row. Reuses api.fetch_prs (its --json field list gained baseRefName + mergeStateStatus; the board's rows ignore the extras) so the tool and the board can never disagree about a PR's state.
  2. github_get_pr now carries the merge-readiness picture: isDraft, reviewDecision, mergeable, mergeStateStatus, statusCheckRollup summarised as N pass / N fail / N pending [/ N skipped] — failing: a, b (both the CheckRun {status, conclusion} and StatusContext {state} shapes, verified against gh 2.92), and reviews (author, state, body ≤ 300 chars, ≤ 10 shown). Total output bounded at 12 000 chars.
  3. github_issue_comments(repo?, number, limit=30)gh issue view --json comments (a PR is an issue, verified live on a PR); the newest limit in chronological order, each body ≤ 1000 chars; null rows tolerated.
  4. github_search_issues(repo?, query, state="open", limit=20)gh search issues --repo R <query> --json number,title,state,url; state: all omits --state (gh only accepts open|closed — verified). Description says DEDUPE BEFORE FILING; github_create_issue's description points the model at it.
  5. github_create_issue is body-gated with the same gh_issue.missing_sections the /issue command uses: a thin body (< 80 chars / no Problem section), a bug without a repro section, or a feature without a direction-or-acceptance section is refused with the scaffold and never posted. New kind arg (generic|bug|feature) picks the gate's sections and adds the type label via labels_for (type label first, like /issue). The existing create-issue tests now pass gate-clearing bodies; a test asserts the tool and the command agree on every refusal.
  6. Inventory recounted from register(): 15 read / 8 write / 3 review = 26 in README + PROTO.md. (The brief said 16 read — three read tools were added; feat: Implement github_create_issue in write_tools.py + test #2 enriches an existing one.) test_inventory_counts_match_the_docs pins the numbers against both docs so they can't drift again.

Also: the no-raise sweep (now 26 tools × 12 gh shapes × 3 spawn failures) caught api.fetch_prs/fetch_issues trusting json.loads without a type check — a non-list body crashed the new tool and, latently, the board route. Both now go through parse_json.

Gates (Python 3.12, pip install -r requirements-dev.txt exactly as CI) — at 7b0632b

$ ruff --version
ruff 0.15.10
$ ruff check . && ruff format --check .
All checks passed!
23 files already formatted
$ pytest -q
271 passed, 1 warning in 4.03s      # was 236; the warning is starlette's pre-existing httpx deprecation

Live smoke against real repos (gh 2.92.0): github_get_pr on protoAgent#2978 → checks: 18 pass / 0 fail / 0 pending / 2 skipped, 1 review rendered; github_list_prs → 2 open rows with draft, UNKNOWN / BLOCKED flags; github_issue_comments on a PR → the coderabbit comment, capped; github_search_issues "default_repo" --state all on this repo → #23; github_create_issue with a thin body → "Not filed — …" + scaffold, no gh call.

Review round 1 — all items addressed (commit 7b0632b)

# Finding Fix
M1 gh search issues --repo R "-label:bug" → "unknown shorthand flag" Flags first, the query LAST after -- (verified live). argv test with -label:bug crash.
M2 github_get_pr showed the OLDEST 10 reviews — bot COMMENTED reviews buried a human CHANGES_REQUESTED Requests latestReviews (one per reviewer, verified on gh 2.92); older gh falls back to the NEWEST reviews. Tested both ways.
M3 dicts(42) raised — statusCheckRollup: 42 / reviews: 42 / comments: 42 escaped dicts() is total (non-list → []). A nested-scalars row joined the sweep — and caught github_get_issue's (author or {}).get on an int; every actor read now goes through _login().
M4 Gate regexes narrower than protoAgent's CI issue gate; labels="bug" not gated as a bug Regexes synced with issue-gate.yml (observed|symptom|idea|current behavior|\bwhat\b, root cause, \bwork\b|plan); infer_kind() promotes a generic call by bug/enhancement label — in the tool AND /issue. A test pins a heading sample per regex alternative.
nit gh_issue.py docstring claimed the two paths share file_issue Now says they share the GATE (missing_sections / infer_kind / labels_for).
nit github_issue_comments unbounded _bounded(…, 12000).
nit bounded test didn't reach the bound Reaches it via long file paths (files are capped at 20, body at 2000, reviews at 10×300 — paths are the only uncapped dimension); asserts the exact truncation suffix.
nit inventory test too loose Pins the literal 15 read / 8 write / 3 review = 26 (PROTO) and **Read** (always, 15) + 26 tools in all (README).
nit agreement test only checked refusals Six (kind, body) cases run through BOTH the tool and /issue against separate gh stubs: both refuse or both file, with the same gh argv head and labels when filing.

🤖 Generated with Claude Code

mabry1985 and others added 2 commits August 22, 2026 16:59
…comments, search-before-filing, body-gated create_issue

The verbs a Project Manager needs that the rail still lacked.

- github_list_prs(repo?, state="open", limit=30): number/title/author/state/
  draft/head->base/reviewDecision/mergeStateStatus/url per row. Reuses
  api.fetch_prs (its --json field list gained baseRefName + mergeStateStatus;
  the board rows ignore extras) so the tool and the board can't disagree.
- github_get_pr now carries the merge-readiness picture: isDraft,
  reviewDecision, mergeable, mergeStateStatus, statusCheckRollup summarised
  (N pass / N fail / N pending [/ N skipped] + the failing check names — both
  the CheckRun and StatusContext shapes, verified against gh 2.92), reviews
  (author, state, body <= 300 chars, <= 10 shown). Output bounded at 12k.
- github_issue_comments(repo?, number, limit=30): `gh issue view --json
  comments` (works on PRs); the newest `limit` in chronological order, each
  body <= 1000 chars, null rows tolerated.
- github_search_issues(repo?, query, state="open", limit=20): `gh search
  issues --repo R`; `all` omits --state (gh only knows open|closed).
  Documented as DEDUPE BEFORE FILING; create_issue's description points at it.
- github_create_issue runs the SAME body gate /issue enforces
  (gh_issue.missing_sections): a thin body / a bug without repro / a feature
  without a direction-or-acceptance section is refused with the scaffold and
  never posted. New `kind` arg picks the gate's sections and adds the type
  label via labels_for (bug / enhancement first, like /issue). Existing
  create-issue tests now pass gate-clearing bodies.
- api.fetch_issues/fetch_prs type-check the gh body via parse_json — the
  no-raise sweep caught `gh pr list` returning a non-list crashing the new
  tool (and, latently, the board route).
- Inventory recounted from register(): 15 read / 8 write / 3 review = 26
  (the brief said 16; three read tools were added, get_pr was enriched).
  A test pins the counts against README/PROTO so they can't drift.
- Version 0.7.0 in manifest + pyproject (lockstep).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gate regex parity + label-inferred kind

Review of #28, all items:
1. github_search_issues: flags first, the query LAST after a -- separator —
   a leading qualifier (-label:bug) was read by gh as an unknown shorthand
   flag (verified live, gh 2.92). argv test with -label:x.
2. github_get_pr shows latestReviews (one per reviewer, their most recent —
   accepted by gh 2.92) so a dozen bot COMMENTED reviews can't bury a human
   CHANGES_REQUESTED; an older gh without the field falls back to the NEWEST
   reviews, never the oldest ten. Tested both ways.
3. dicts() is total: a non-list (statusCheckRollup: 42 / reviews: 42 /
   comments: 42) is []. A nested-scalars row joined the no-raise sweep — and
   caught github_get_issue's (author or {}).get on an int; every actor read
   now goes through _login().
4. Body-gate parity with protoAgent's CI issue gate (issue-gate.yml):
   problem += observed|symptom|idea|current behavior|\bwhat\b, repro +=
   root cause, proposal += \bwork\b|plan. infer_kind(): a generic call with
   a bug / enhancement LABEL is gated as that kind (CI keys on the label) —
   in the tool AND the /issue command. A test pins a sample heading per
   regex alternative.
Nits: gh_issue.py docstring says the two paths share the GATE; _bounded on
github_issue_comments; test_get_pr_output_is_bounded actually reaches 12k;
test_register pins the literal '15 read / 8 write / 3 review = 26'; the
tool/command agreement test exercises both entry points in BOTH directions
(same refusal, same gh argv head + labels when filing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mabry1985
mabry1985 marked this pull request as ready for review August 23, 2026 00:10
@mabry1985
mabry1985 merged commit 4d8c5a7 into main Aug 23, 2026
1 check passed
@mabry1985
mabry1985 deleted the feat/v0.7.0-pm-verbs branch August 23, 2026 00:11

@protoreview protoreview 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.

QA panel review — PASS

code-review-structural · head 7b0632bf2a32 · formal

This round produced no confirmed findings for PR #28, but that's a coverage gap, not a clean bill of health. Correctness and removed-behavior lanes ran and found nothing meeting the confidence bar; cross-file, conventions, and the structural-analysis (protopatch) pass failed to produce usable output at all, so those angles were never actually reviewed. Fix-first item: re-run the cross-file, conventions, and structural-analysis lanes before merge — don't treat this pass as a clean approval. Nothing to disagree on since no findings were submitted, and the verifier had nothing to confirm or refute this round.

No findings — the review came back clean.

findings JSON (machine-readable)
[]

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.

1 participant