Gate CI on durable PM tracker health with pm 2026.8.6 - #56
Conversation
Add a 'Verify pm project integrity and merge safety' step to ci.yml immediately after Install dependencies. It runs ./node_modules/.bin/pm health --strict-exit. This closes a hole in multi-agent branch merging: when two agents edit the same scalar field of one item on two branches, the field-aware merge driver picks a winner and records the loser in a clone-local receipt. The resulting .toon has no conflict markers and already holds the winning value, so the naive resolution idiom (git add the marker-free file, commit) succeeds and the peer edit is gone with no trace in any pushed artifact. pm validate returns ok:true on that corrupted result because the file is valid TOON. Only pm health goes red, via integrity.counts.pending_merge_decisions, naming the affected items in pending_merge_decision_items. --strict-exit is load-bearing because a bare pm health exits 0 even when ok:false. Verified green on this repo and proven to exit 1 on the hazard in a throwaway copy.
|
Warning Review limit reached
Next review available in: 49 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
Summary by CodeRabbit
WalkthroughThe PR adds a strict PM health gate to CI, updates PM development dependencies, documents fresh-clone receipt limits, and records release reconciliation results in PM metadata and the changelog. ChangesCI health gate
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Reviewer's GuideAdds a pm health-based integrity gate to CI to prevent silently dropped peer edits from merging, and records the change in project metadata (changelog and pm chore/history items). Flow diagram for new pm health CI gateflowchart TB
A[Checkout repository] --> B[Install dependencies: npm ci]
B --> C[Verify pm project integrity: pm health --strict-exit]
C -->|exit 0| D[Type check: npm run typecheck]
C -->|exit 1| E[Fail CI job]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Greptile SummaryThe PR adds a strict, time-bounded PM tracker-health check to CI while explicitly documenting that fresh checkouts cannot attest clone-local merge receipts.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| .github/workflows/ci.yml | Adds a 120-second strict PM health gate and accurately limits its stated guarantees to durable, checkout-visible state. |
| package.json | Updates PM CLI and changelog development dependency ranges to 2026.8.6. |
| package-lock.json | Pins the updated PM tools and their transitive dependencies with registry integrity hashes. |
| CHANGELOG.md | Regenerates the Unreleased section from the reconciled tracker state. |
Reviews (8): Last reviewed commit: "fix(ci): enforce PM health timeout and c..." | Re-trigger Greptile
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 @.github/workflows/ci.yml:
- Around line 44-56: Update the CI merge-safety gate around pm health
--strict-exit so it verifies persisted evidence of discarded peer edits, not
only the marker-free .toon result. Persist a privacy-safe pending-decision
marker into the committed checkout or execute verification in the merge clone
containing the receipt, and add a regression that commits the marker-free result
then runs the gate from a fresh checkout.
🪄 Autofix
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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 41828243-45b5-4cf5-a439-f1fd32edb319
📒 Files selected for processing (4)
.agents/pm/chores/pm-graph-9qk5.toon.agents/pm/history/pm-graph-9qk5.jsonl.github/workflows/ci.ymlCHANGELOG.md
The step and its tracker item both said this gate blocks a merge that silently discarded a peer agent's edit. Verified today that it does not, and cannot as built: merge-decision receipts live in .agents/pm/runtime/, which pm init gitignores, so they are never pushed. On the same commit, the merge-performing clone reports one receipt and exits 1, while a fresh clone - which is what CI checks out - reports zero and exits 0. The pushed history does not disambiguate it either. Both writes are present in timestamp order and the item matches the latest, so history verification reports ok. Filed upstream as unbraind/pm-cli#922; flagged first by Greptile on every PR in this rollout. The step is kept, because what it does catch is real and CI-observable: conflict markers in item and history files, parse failures, invalid history JSON, hash drift, unknown-author events, stale in-progress work and tracked runtime cache files. Only the overstated claim is removed. A gate whose documentation promises more than it delivers is worse than no gate, because it stops people looking for the hazard it does not cover.
|
Correction pushed — re-review please. @coderabbitai full review Greptile's P1 was correct and is the reason for this push. The gate does not detect a What changed: the overstated claim was removed everywhere it appeared — the step name What is worth checking this round:
GitHub Actions is under a critical outage, so the checks here are absent for external |
Rate Limit Exceeded
|
|
Fresh exact-head review requested for @greptileai |
|
|
|
Exact-head disposition for
Every inline bot finding has been reacted to and answered in-thread. CodeRabbit rate-limit messages are recorded as review limitations, not approvals. @greptileai |
Rate Limit Exceeded
|
|
The exact Actions failure was reproduced and fixed by reconciling the feature branch with the same-day 2026.8.6 release, then regenerating the package-owned changelog against the real merge topology. The full local release gate passes. Please review the new exact head.\n\n@greptileai\n/gemini review\n@coderabbitai full review\n@sourcery-ai review |
Rate Limit Exceeded
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/chores/pm-graph-9qk5.toon:
- Around line 30-32: Update the CI workflow’s health-check execution to enforce
the 120-second limit recorded for `pm health --strict-exit`, using a command
timeout or dedicated job limit. If the workflow intentionally does not enforce
this bound, revise the record to clearly state that `timeout_seconds` applies
only to the recorded verification run.
In @.agents/pm/history/pm-graph-y2ax.jsonl:
- Line 7: Align the pm-graph-y2ax tracker records with the pending exact-head
Node 22/26 Actions acceptance: in .agents/pm/history/pm-graph-y2ax.jsonl lines
7-7 and .agents/pm/issues/pm-graph-y2ax.toon lines 5-5, apply the appropriate
corrective transition from closed if closure was premature, and retain or
restore the closed state only after both required Actions jobs pass.
🪄 Autofix
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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 94c4135d-a520-4a98-a248-9748de58dc57
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (7)
.agents/pm/chores/pm-graph-9qk5.toon.agents/pm/history/pm-graph-9qk5.jsonl.agents/pm/history/pm-graph-y2ax.jsonl.agents/pm/issues/pm-graph-y2ax.toon.github/workflows/ci.ymlCHANGELOG.mdpackage.json
|
Both fresh-review findings are fixed in fbd8299: CI enforces the recorded PM health timeout, and the reconciliation item now contains exact successful Actions evidence for both Node jobs. The full local release gate passes. Please review the new exact head.\n\n@greptileai\n/gemini review\n@coderabbitai full review\n@sourcery-ai review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== HEAD ==='
git rev-parse HEAD
git status --short
echo
echo '=== Merge base and changed files ==='
base="$(git merge-base HEAD origin/main)"
printf 'merge-base: %s\n' "$base"
git diff --stat "$base"...HEAD
git diff --name-status "$base"...HEAD
echo
echo '=== Workflow outline and relevant content ==='
ast-grep outline .github/workflows/ci.yml --items all || true
nl -ba .github/workflows/ci.yml | sed -n '1,280p'
echo
echo '=== package.json relevant sections ==='
node -e 'const p=require("./package.json"); console.log(JSON.stringify({scripts:p.scripts,devDependencies:Object.fromEntries(Object.entries(p.devDependencies||{}).filter(([k])=>k==="`@unbrained/pm-cli`"||k==="pm-changelog"))},null,2))' 2>/dev/null || \
rg -n -C3 '"(`@unbrained/pm-cli`|pm-changelog|release:check|changelog:check)"' package.json
echo
echo '=== Changed PM records ==='
for f in $(git diff --name-only "$base"...HEAD | rg '^\.agents/pm/(issues|chores|history)/'); do
echo "--- $f ---"
nl -ba "$f" | sed -n '1,260p'
done
echo
echo '=== Lockfile versions and changed lockfiles ==='
git diff --name-only "$base"...HEAD | rg '(^|/)(package-lock\.json|npm-shrinkwrap\.json)$' || true
rg -n -C2 '"(`@unbrained/pm-cli`|pm-changelog)"' package-lock.json npm-shrinkwrap.json 2>/dev/null || true
echo
echo '=== All health invocations and timeout configuration ==='
rg -n -C4 --glob '!node_modules/**' '(pm health|strict-exit|timeout)' .github package.json .agents 2>/dev/null || trueLength of output: 2817 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="$(git merge-base HEAD origin/main)"
echo '=== Complete PR patch ==='
git diff --no-ext-diff --unified=80 "$base"...HEAD -- \
.github/workflows/ci.yml \
package.json \
package-lock.json \
CHANGELOG.md \
.agents/pm/chores/pm-graph-9qk5.toon \
.agents/pm/history/pm-graph-9qk5.jsonl \
.agents/pm/history/pm-graph-y2ax.jsonl \
.agents/pm/issues/pm-graph-y2ax.toon
echo
echo '=== Current CI workflow ==='
sed -n '1,320p' .github/workflows/ci.yml
echo
echo '=== Current package manifest: relevant keys ==='
sed -n '/"scripts"[[:space:]]*:/,/"dependencies"[[:space:]]*:/p' package.json
sed -n '/"devDependencies"[[:space:]]*:/,/^[[:space:]]*}/p' package.json
echo
echo '=== PM record contents ==='
for f in .agents/pm/chores/pm-graph-9qk5.toon \
.agents/pm/history/pm-graph-9qk5.jsonl \
.agents/pm/history/pm-graph-y2ax.jsonl \
.agents/pm/issues/pm-graph-y2ax.toon; do
echo "--- $f ---"
sed -n '1,320p' "$f"
done
echo
echo '=== Lockfile package entries ==='
rg -n -A20 -B3 '"node_modules/(`@unbrained/pm-cli`|pm-changelog)"' package-lock.json || true
echo
echo '=== Exact-head GitHub check runs ==='
gh api "repos/unbraind/pm-graph/commits/$(git rev-parse HEAD)/check-runs" \
-H 'Accept: application/vnd.github+json' \
--jq '.check_runs[] | [.name, .status, .conclusion, .details_url] | `@tsv`' || trueLength of output: 136595 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== Diff whitespace check ==='
git diff --check "$(git merge-base HEAD origin/main)"...HEAD
echo 'PASS'
echo
echo '=== JSON syntax checks for changed JSON files ==='
python3 - <<'PY'
import json
for path in [
"package.json",
"package-lock.json",
".agents/pm/history/pm-graph-9qk5.jsonl",
".agents/pm/history/pm-graph-y2ax.jsonl",
]:
with open(path, encoding="utf-8") as f:
if path.endswith(".jsonl"):
for lineno, line in enumerate(f, 1):
json.loads(line)
else:
json.load(f)
print(f"valid: {path}")
PY
echo
echo '=== PM runtime ignore and tracked-state checks ==='
rg -n -C3 '\.agents/pm/runtime|runtime/' .gitignore .git/info/exclude 2>/dev/null || true
git check-ignore -v .agents/pm/runtime/example-receipt.json || true
git ls-files .agents/pm/runtime
echo
echo '=== Health-gate and timeout references in tracked configuration ==='
rg -n -C3 --glob '!package-lock.json' \
'(pm health|strict-exit|timeout_seconds|--kill-after|120s)' \
.github .agents package.json README.md 2>/dev/null || true
echo
echo '=== Changed-file status and credential-pattern scan ==='
git status --short
git diff --no-ext-diff --unified=0 "$(git merge-base HEAD origin/main)"...HEAD | \
rg -n -i '(^\+.*(api[_-]?key|secret|password|token)[[:space:]]*[:=]|ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})' || true
echo
echo '=== Current exact-head workflow run ==='
gh run view 31132827759 --repo unbraind/pm-graph --json status,conclusion,headSha,jobs \
--jq '{status, conclusion, headSha, jobs: [.jobs[] | {name, status, conclusion}]}' || trueLength of output: 74388
The health gate now enforces the recorded 120-second limit with a 10-second kill grace period. The workflow wording correctly limits the gate to durable checkout-visible state. The gitignore rule confirms that The package manifest and lockfile consistently use Exact-head CI verification remains pending. Actions run
|
Outcome
pm health --strict-exitin CI for durable, checkout-visible tracker failures.@unbrained/pm-cli2026.8.6 andpm-changelog2026.8.6.pm merge reconcile, preserves both agents' notes, refreshes the 2026.8.6 merge fence, and regenerates the package-owned changelog.PM evidence
Verification
npm ci --ignore-scriptsnpm run release:checkpm health --strict-exitnpm run changelog:check