Refuse incomplete pm corpora before GitHub sync - #46
Conversation
Replace the 10,000-row ceiling and permissive cast with a strict full unbounded list-all contract. Validate source, omission, pagination, budget, count, identity, and consumed row fields before import, export, sync, project, or search planning. Add adversarial and fresh-tracker installed-CLI acceptance, document the safety behavior, pin the development CLI to 2026.8.17, regenerate the changelog, and record separate exact-coverage and historical-privacy follow-ups in the package tracker.
Reviewer's GuideReplaces the permissive pm workspace reader with a strict, fully-validated Sequence diagram for strict complete pm list-all workspace readssequenceDiagram
actor GitHubSync
participant pmGithub as pm-github
participant pmCli as pm CLI process
GitHubSync->>pmGithub: readPmItems(pmRoot)
pmGithub->>pmGithub: pmJsonMaxBuffer()
pmGithub->>pmGithub: completePmListArgs(pmRoot)
pmGithub->>pmGithub: pmListSpawnOptions(maxBuffer)
pmGithub->>pmCli: spawnSync("pm", args, options)
pmCli-->>pmGithub: stdout (pm list-all JSON envelope)
pmGithub->>pmGithub: JSON.parse(stdout)
pmGithub->>pmGithub: decodeCompletePmItems(parsed)
pmGithub-->>GitHubSync: PmItem[]
alt [incomplete or unverifiable corpus]
pmGithub->>pmGithub: requireCompletePmField(...)
pmGithub-->>GitHubSync: CommandError("Refusing unverifiable pm list-all output")
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 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 |
|
@coderabbitai full review Please review exact head |
|
@greptileai please review exact head |
|
/gemini review |
|
@sourcery-ai review Please review exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Repository and requested commit =='
git rev-parse HEAD
git show -s --format='%H%n%P%n%s' HEAD
git rev-parse --verify 6c88b6e^{commit}
printf '%s\n' '== Changed files against first parent =='
base="$(git rev-parse HEAD^)"
git diff --name-status "$base" HEAD
printf '%s\n' '== Diff stat =='
git diff --stat "$base" HEAD
printf '%s\n' '== Candidate symbols =='
rg -n -C 3 --glob '!node_modules/**' \
'completePmListArgs|decodeCompletePmItems|readPmItems|PM_JSON_MAX_BUFFER|list-all|spawn|execFile|child_process' .
printf '%s\n' '== TypeScript outlines for changed source/tests =='
git diff --name-only --diff-filter=AM "$base" HEAD |
rg '\.(ts|tsx|js|mjs|cjs)$' |
while IFS= read -r f; do
printf '\n-- %s --\n' "$f"
ast-grep outline "$f" --items all --type function,class,interface,type --view expanded || true
doneLength of output: 53110 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="$(git rev-parse HEAD^)"
printf '%s\n' '== index.ts change diff =='
git diff --unified=80 "$base" HEAD -- index.ts
printf '%s\n' '== Whole-corpus implementation =='
sed -n '790,1098p' index.ts
printf '%s\n' '== PmItem field consumers and constructors =='
rg -n -C 5 --glob 'index.ts' \
'\bPmItem\b|\.body\b|\.description\b|\.tags\b|\.title\b|\.status\b|\.id\b' index.ts
printf '%s\n' '== Complete-corpus tests =='
cat -n test/complete-corpus.test.ts
printf '%s\n' '== Package/toolchain metadata =='
cat package.json
printf '\n-- installed pm packages --\n'
fd -HI -t f 'package.json' node_modules 2>/dev/null |
rg '/(`@unbrained`|unbrained)/|/pm/' |
head -80 |
while IFS= read -r f; do
printf '\n-- %s --\n' "$f"
sed -n '1,160p' "$f"
done
printf '%s\n' '== Installed CLI contract candidates =='
rg -n -C 4 -i --hidden \
'omission_receipt|read_output|pagination|strict-read|output_budget|requested_dimensions' \
node_modules 2>/dev/null | head -500 || trueLength of output: 100687 🏁 Script executed: #!/bin/bash
set -u -o pipefail
printf '%s\n' '== Changed non-index files =='
base="$(git rev-parse HEAD^)"
git diff --unified=30 "$base" HEAD -- CHANGELOG.md README.md package.json package-lock.json test/complete-corpus.test.ts || true
printf '%s\n' '== Lockfile pm package resolution =='
rg -n -C 5 '"node_modules/@unbrained/pm-cli"|`@unbrained/pm-cli`|2026\.8\.17' package-lock.json package.json || true
printf '%s\n' '== Public npm package metadata =='
curl --fail --silent --show-error --location \
'https://registry.npmjs.org/@unbrained%2fpm-cli/2026.8.17' \
-o /tmp/pm-cli-package.json &&
python3 - <<'PY'
import json
p=json.load(open('/tmp/pm-cli-package.json'))
for k in ('name','version','dist','repository','bin','types','main'):
print(f'{k}: {p.get(k)!r}')
PY
printf '%s\n' '== Download and inspect the pinned package archive =='
tarball="$(python3 - <<'PY'
import json
print(json.load(open('/tmp/pm-cli-package.json'))['dist']['tarball'])
PY
)"
curl --fail --silent --show-error --location "$tarball" -o /tmp/pm-cli.tgz
rm -rf /tmp/pm-cli-package
mkdir -p /tmp/pm-cli-package
tar -xzf /tmp/pm-cli.tgz -C /tmp/pm-cli-package
fd -HI -t f . /tmp/pm-cli-package | head -100
printf '%s\n' '== Authoritative receipt/schema occurrences =='
rg -n -C 8 -i \
'output_budget_truncation|output_budget_exceeded|omission_receipt|read_output|requested_dimensions|strict-read' \
/tmp/pm-cli-package || true
printf '%s\n' '== Windows executable entries =='
find /tmp/pm-cli-package -maxdepth 4 -type f \( -name 'package.json' -o -name '*.cmd' -o -name 'pm' \) -print | sortLength of output: 202102 🏁 Script executed: #!/bin/bash
set -euo pipefail
pkg=/tmp/pm-cli-package/package
printf '%s\n' '== Pinned CLI package launcher metadata =='
python3 - <<'PY'
import json
p=json.load(open('/tmp/pm-cli-package/package/package.json'))
print('name:', p.get('name'))
print('version:', p.get('version'))
print('bin:', json.dumps(p.get('bin'), indent=2, sort_keys=True))
PY
printf '%s\n' '== List result declarations and implementation =='
rg -n -C 12 --glob '*.d.ts' \
'interface ListResult|type ListResult|ListResult' "$pkg/dist" "$pkg/sdk" | head -300 || true
rg -n -C 12 --glob '*.js' \
'strictRead|strict_read|unreadable_item_count|unreadable_directory_count|list-all|listAll' \
"$pkg/dist" | head -500 || true
printf '%s\n' '== Exact changed production process calls and line numbers =='
nl -ba index.ts | sed -n '850,1095p'
printf '\n== Existing Windows-aware process examples ==\n'
nl -ba test/smoke.test.ts | sed -n '1156,1175p'
nl -ba test/complete-corpus.test.ts | sed -n '59,67p'
printf '%s\n' '== Search for exact `readPmItems` injection/use coverage =='
rg -n -C 4 '\breadPmItems\s*\(|readItems\s*\?\?' index.ts test --glob '*.ts'Length of output: 201834
Finding
Verified areas
You are interacting with an AI system. |
Greptile SummaryThe PR replaces permissive, capped workspace reads with a strict complete-corpus contract and repairs Windows execution by relaunching the host CLI directly without shell parsing.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| index.ts | Introduces strict complete-corpus decoding and a shell-free Windows host-CLI launcher; the previously reported path-rewriting issue is resolved. |
| test/complete-corpus.test.ts | Adds adversarial envelope validation and installed-CLI coverage, including workspace paths containing shell metacharacters. |
| package.json | Pins the development pm CLI toolchain to 2026.8.17 while retaining the existing runtime compatibility floor. |
| package-lock.json | Synchronizes the resolved CLI development dependency with the new exact manifest pin. |
| README.md | Documents fail-closed whole-workspace reads and the configurable 64 MiB subprocess transport guard. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[GitHub import, export, sync, project, or search] --> B[readPmItems]
B --> C{Windows?}
C -->|No| D[Execute pm with argv]
C -->|Yes| E[Resolve host package bin.pm]
E --> F[Execute with Node and literal argv]
D --> G[Strict unbounded list-all]
F --> G
G --> H[Decode JSON envelope]
H --> I{All completeness contracts valid?}
I -->|No| J[Fail closed]
I -->|Yes| K[Return complete workspace corpus]
Reviews (4): Last reviewed commit: "fix: relaunch through the pm host packag..." | Re-trigger Greptile
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The decoder currently hardcodes a large number of individual field checks via
requireCompletePmField; consider grouping related envelope contracts into small helper functions or typed structures to make the completeness logic easier to evolve and reason about as the CLI contract changes. - Tests assert against specific error message fragments for many failure modes, which tightly couples behavior to exact wording; you might want to centralize error codes or identifiers to keep the negative-path coverage robust while allowing more flexible user-facing text changes.
decodeCompletePmItemsintentionally whitelists a minimal set of item fields and drops everything else; if future integration paths need additional pm fields, it may be helpful to document this truncation or provide a clear extension point so those new fields are not accidentally lost.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The decoder currently hardcodes a large number of individual field checks via `requireCompletePmField`; consider grouping related envelope contracts into small helper functions or typed structures to make the completeness logic easier to evolve and reason about as the CLI contract changes.
- Tests assert against specific error message fragments for many failure modes, which tightly couples behavior to exact wording; you might want to centralize error codes or identifiers to keep the negative-path coverage robust while allowing more flexible user-facing text changes.
- `decodeCompletePmItems` intentionally whitelists a minimal set of item fields and drops everything else; if future integration paths need additional pm fields, it may be helpful to document this truncation or provide a clear extension point so those new fields are not accidentally lost.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Enable the Windows command shell only when invoking the npm-installed pm shim, preserving direct execution on other platforms. Add a platform-contract regression test and record the exact-head bot review evidence in the package tracker.
|
@coderabbitai Fixed the Windows launcher finding in exact head |
|
@greptileai Thank you for verifying the completeness and data-safety boundary. The only subsequent code change is the Windows npm-shim correction in exact head |
|
@sourcery-ai Thank you. Exact head |
|
/gemini review Please review exact head |
|
Sure! I'm generating a new review now. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
requested="$(git rev-parse --verify 3bb84d7^{commit})"
head="$(git rev-parse HEAD)"
base="$(git rev-parse "${requested}^")"
printf 'requested=%s\nhead=%s\nbase=%s\n' "$requested" "$head" "$base"
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$requested"
printf '\n== Changed files ==\n'
git diff --name-status "$base" "$requested"
printf '\n== Diff stat ==\n'
git diff --stat "$base" "$requested"
printf '\n== Changed TypeScript outlines ==\n'
git diff --name-only --diff-filter=AM "$base" "$requested" |
rg '\.(ts|tsx|js|mjs|cjs)$' |
while IFS= read -r file; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --type function,class,interface,type --view expanded || true
done
printf '\n== Process, corpus-reader, and decoder diffs ==\n'
git diff --unified=100 "$base" "$requested" -- index.ts test/complete-corpus.test.ts
printf '\n== Relevant production call sites ==\n'
rg -n -C 6 --glob '!node_modules/**' \
'\b(readPmItems|decodeCompletePmItems|completePmListArgs|spawnSync|spawn|execFile|PM_JSON_MAX_BUFFER)\b' \
index.ts test || trueLength of output: 80630 🏁 Script executed: #!/bin/bash
set -euo pipefail
head="$(git rev-parse --verify 3bb84d7^{commit})"
printf '== PR metadata and comparison base ==\n'
gh pr view 46 --repo unbraind/pm-github --json baseRefOid,headRefOid,commits,files \
--jq '{baseRefOid, headRefOid, commits: [.commits[] | {oid: .oid, messageHeadline}], files: [.files[] | {path, additions, deletions}]}' || true
base="$(git merge-base "$head" "$(gh pr view 46 --repo unbraind/pm-github --json baseRefOid --jq .baseRefOid 2>/dev/null || git rev-parse "$head^")")"
printf '\nreview_base=%s\nhead=%s\n' "$base" "$head"
printf '\n== Complete PR file list ==\n'
git diff --name-status "$base" "$head"
printf '\n== Complete PR stat ==\n'
git diff --stat "$base" "$head"
printf '\n== Process-option and reader source ==\n'
nl -ba index.ts | sed -n '860,1120p'
printf '\n== pmRoot origins and complete-reader callers ==\n'
rg -n -C 5 --glob 'index.ts' \
'(ctx\.pm_root|pmRoot|pm_root|readPmItems\s*\(|completePmListArgs\s*\()' index.ts
printf '\n== Existing Windows shell use and argument safety comments ==\n'
rg -n -C 5 --glob '*.{ts,js,mjs,cjs}' \
'(shell:\s*process\.platform\s*===\s*["'\'']win32["'\'']|shell:\s*true|cmd\.exe|\.cmd|CVE-2024-27980)' \
. -g '!node_modules/**'
printf '\n== Node child_process declarations and documentation candidates ==\n'
node_types="$(npm root 2>/dev/null)/@types/node"
if [ -d "$node_types" ]; then
rg -n -C 8 'shell.*[Ss]pawn|[Ss]pawn.*shell|metacharacter|unsanitized user input' \
"$node_types/child_process.d.ts" "$node_types"/*.md 2>/dev/null || true
fi
printf '\n== PM history artifact diff ==\n'
git diff --unified=30 "$base" "$head" -- .agents/pm/history/pm-github-ep0u.jsonl .agents/pm/issues/pm-github-ep0u.toonLength of output: 4535 🏁 Script executed: #!/bin/bash
set -euo pipefail
head="$(git rev-parse --verify 3bb84d7^{commit})"
base="f7315e2521d28558a2db3b38e89724ad98875a8c"
printf '%s\n' '== Reader and Windows process path =='
sed -n '860,1120p' index.ts
printf '%s\n' '== pmRoot sources and reader callers =='
rg -n -C 5 --glob 'index.ts' \
'(ctx\.pm_root|pmRoot|pm_root|readPmItems\s*\(|completePmListArgs\s*\()' index.ts
printf '%s\n' '== Existing Windows shell calls and safety notes =='
rg -n -C 5 --glob '*.{ts,js,mjs,cjs}' \
'(shell:\s*process\.platform\s*===\s*["'\'']win32["'\'']|shell:\s*true|cmd\.exe|\.cmd|CVE-2024-27980)' \
. -g '!node_modules/**' || true
printf '%s\n' '== Local Node child_process API declarations =='
node_types="$(npm root 2>/dev/null)/@types/node"
if [ -f "$node_types/child_process.d.ts" ]; then
rg -n -C 10 'shell.*[Ss]pawn|[Ss]pawn.*shell|metacharacter|unsanitized user input' \
"$node_types/child_process.d.ts" || true
fi
printf '%s\n' '== Complete production diff =='
git diff --unified=40 "$base" "$head" -- index.ts
printf '%s\n' '== Tests, docs, dependencies, and tracker artifacts =='
git diff --unified=30 "$base" "$head" -- \
test/complete-corpus.test.ts README.md CHANGELOG.md package.json package-lock.json \
.agents/pm/history/pm-github-9cjx.jsonl \
.agents/pm/history/pm-github-ep0u.jsonl \
.agents/pm/history/pm-github-zqad.jsonl \
.agents/pm/issues/pm-github-ep0u.toon \
.agents/pm/issues/pm-github-zqad.toon \
.agents/pm/tasks/pm-github-9cjx.toonLength of output: 142799 🤖 web_search executed:
Length of output: 14020
The original Windows npm-shim finding is addressed. Finding
Verified areas
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
Resolve the installed pm package entry point and execute it directly with Node on Windows, avoiding cmd.exe interpretation of user-selected workspace paths. Exercise the production Windows strategy against a real tracker path containing shell metacharacters and record the review correction.
|
@coderabbitai Fixed the command-injection finding in exact head |
|
@greptileai The previous re-review check failed without an explanatory summary or review thread, so there was no actionable detail to address. Exact head |
|
@sourcery-ai The head advanced to |
|
/gemini review Please review exact head |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The
decodeCompletePmItemsenvelope validation is tightly coupled to the current CLI schema (e.g.,contract_version === 1, exactread_output.command, specific completeness fields); consider centralizing these constants and adding a small compatibility layer so future CLI contract additions or version bumps don’t break all GitHub operations by default. - To avoid accidental future misuse, you might constrain
requireCompletePmField’sexpected/actualtypes to primitives (e.g.,string | number | boolean | null) rather thanunknown, which would make it harder to call it with structured objects where===comparison would be fragile.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `decodeCompletePmItems` envelope validation is tightly coupled to the current CLI schema (e.g., `contract_version === 1`, exact `read_output.command`, specific completeness fields); consider centralizing these constants and adding a small compatibility layer so future CLI contract additions or version bumps don’t break all GitHub operations by default.
- To avoid accidental future misuse, you might constrain `requireCompletePmField`’s `expected`/`actual` types to primitives (e.g., `string | number | boolean | null`) rather than `unknown`, which would make it harder to call it with structured objects where `===` comparison would be fragile.
## Individual Comments
### Comment 1
<location path="test/complete-corpus.test.ts" line_range="123-132" />
<code_context>
+test("decoder refuses every independent incomplete, omitted, paginated, compacted, or contradictory receipt", () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Add a few more adversarial envelope cases, especially around type/contract drift in receipts
To further harden the decoder against future CLI/protocol drift, consider adding a few targeted cases:
- A `read_output.contract_version` mismatch (e.g. `contract_version: 2`) to confirm we reject unexpected protocol versions, not just missing contracts.
- Non-object receipts currently normalized via `isJsonRecord`, e.g. `completeness: null` or `omission_receipt: []`, to assert we fail closed on structurally invalid shapes.
- A non-array `omitted_field_groups` (e.g. `omitted_field_groups: "body"`) to ensure the explicit empty-array guard is exercised, not just the length check.
These cases would strengthen the guarantee that `decodeCompletePmItems` rejects structural or version drift in the JSON envelope, not only value-level changes.
Suggested implementation:
```typescript
test("decoder refuses every independent incomplete, omitted, paginated, compacted, or contradictory receipt", () => {
const completeReadOutput = completeEnvelope().read_output as Record<string, unknown>;
const cases: Array<[string, unknown, RegExp]> = [
["bare array", [], /top-level object/],
["missing items", withoutField("items"), /items must be an array/],
["truncated", completeEnvelope({ truncated: true }), /truncated must be false/],
["has more", completeEnvelope({ has_more: true }), /has_more must be false/],
["cursor", completeEnvelope({ next_cursor: "next" }), /next_cursor must be null/],
["missing completeness", withoutField("completeness"), /completeness.status must be "complete"/],
["partial completeness", completeEnvelope({ completeness: { status: "partial", unreadable_item_count: 1, unreadable_directory_count: 0 } }), /completeness.status must be "complete"/],
["unreadable item", completeEnvelope({ completeness: { status: "complete", unreadable_item_count: 1, unreadable_directory_count: 0 } }), /unreadable_item_count must be 0/],
[
"contract version mismatch",
completeEnvelope({ read_output: { ...completeReadOutput, contract_version: 2 } }),
/contract_version must be 1/,
],
[
"null completeness",
completeEnvelope({ completeness: null }),
/completeness must be an object/,
],
[
"array omission_receipt",
completeEnvelope({ omission_receipt: [] }),
/omission_receipt must be an object/,
],
[
"string omitted_field_groups",
completeEnvelope({ omitted_field_groups: "body" }),
/omitted_field_groups must be an array/,
],
```
If the actual decoder error messages differ from the regexes used here, you will need to update the `/contract_version must be 1/`, `/completeness must be an object/`, `/omission_receipt must be an object/`, and `/omitted_field_groups must be an array/` patterns to match the real error text emitted by `decodeCompletePmItems`. Otherwise, the structural test cases will work as written.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Hey @unbraind, I've posted a new review for you! |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
requested="$(git rev-parse --verify 496cb11^{commit})"
head="$(git rev-parse HEAD)"
printf 'requested=%s\nhead=%s\n' "$requested" "$head"
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$requested"
printf '\n== PR metadata and review base ==\n'
gh pr view 46 --repo unbraind/pm-github --json baseRefOid,headRefOid,commits,files \
--jq '{baseRefOid,headRefOid,commits:[.commits[]|{oid,messageHeadline}],files:[.files[]|{path,additions,deletions}]}' || true
base="$(gh pr view 46 --repo unbraind/pm-github --json baseRefOid --jq .baseRefOid 2>/dev/null || git rev-parse "${requested}^")"
printf 'base=%s\n' "$base"
printf '\n== Full PR file changes ==\n'
git diff --name-status "$base" "$requested"
printf '\n== Full PR stat ==\n'
git diff --stat "$base" "$requested"
printf '\n== Changed TypeScript structure ==\n'
git diff --name-only --diff-filter=AM "$base" "$requested" |
rg '\.(ts|tsx|js|mjs|cjs)$' |
while IFS= read -r file; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --type function,class,interface,type --view expanded || true
done
printf '\n== Reader, launcher, and decoder source ==\n'
rg -n -C 8 --glob 'index.ts' \
'readPmItems|decodeCompletePmItems|completePmListArgs|pmListSpawnOptions|process\.execPath|require\.resolve|createRequire|`@unbrained/pm-cli`|spawnSync|execFileSync' .
printf '\n== Focused production source ranges ==\n'
nl -ba index.ts | sed -n '830,1160p'
printf '\n== Reader callers and pmRoot origins ==\n'
rg -n -C 6 --glob 'index.ts' \
'readPmItems\s*\(|pmRoot|pm_root|workspace.*root|ctx\.' index.ts
printf '\n== Complete-corpus tests and Windows tests ==\n'
fd -t f . test | sort | while IFS= read -r file; do
if rg -q 'completePmListArgs|decodeCompletePmItems|readPmItems|process\.execPath|win32|metacharacter|spawnSync|pm-cli' "$file"; then
printf '\n-- %s --\n' "$file"
cat -n "$file"
fi
done
printf '\n== Package metadata and lock resolution ==\n'
cat package.json
rg -n -C 5 '`@unbrained/pm-cli`|2026\.8\.17' package-lock.json package.json || true
printf '\n== Full relevant diff ==\n'
git diff --unified=60 "$base" "$requested" -- index.ts test README.md CHANGELOG.md package.json package-lock.jsonLength of output: 28357 🏁 Script executed: #!/bin/bash
set -euo pipefail
requested="$(git rev-parse --verify 496cb11^{commit})"
base="$(gh pr view 46 --repo unbraind/pm-github --json baseRefOid --jq .baseRefOid 2>/dev/null || git merge-base "$requested" "$(git rev-parse "$requested^")")"
printf '%s\n' '== Imports, complete-reader implementation, and buffer guard =='
sed -n '1,70p' index.ts
sed -n '850,1130p' index.ts
sed -n '1168,1208p' index.ts
printf '%s\n' '== Exact complete-corpus test structure =='
ast-grep outline test/complete-corpus.test.ts --items all --view expanded || true
printf '%s\n' '== Complete-corpus test source =='
cat test/complete-corpus.test.ts
printf '%s\n' '== Full code diff for this PR =='
git diff --unified=80 "$base" "$requested" -- index.ts test/complete-corpus.test.ts
printf '%s\n' '== Dependency declarations =='
cat package.json
printf '%s\n' '== Lockfile package resolution context =='
rg -n -C 8 '"node_modules/@unbrained/pm-cli"|"`@unbrained/pm-cli`"|2026\.8\.17' package-lock.json
printf '%s\n' '== Runtime package-resolution assumptions =='
rg -n -C 5 --glob '!node_modules/**' \
'createRequire\(|require\.resolve|`@unbrained/pm-cli/package`\.json|peerDependencies|dependencies|devDependencies|bundl|standalone-installed' \
README.md index.ts package.json test
printf '%s\n' '== All modified non-code files =='
git diff --unified=40 "$base" "$requested" -- README.md CHANGELOG.md package.json package-lock.json \
.agents/pm/history/pm-github-9cjx.jsonl \
.agents/pm/history/pm-github-ep0u.jsonl \
.agents/pm/history/pm-github-zqad.jsonl \
.agents/pm/issues/pm-github-ep0u.toon \
.agents/pm/issues/pm-github-zqad.toon \
.agents/pm/tasks/pm-github-9cjx.toonLength of output: 157819 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Extension manifest and runtime packaging references =='
fd -t f 'manifest.json' . -E node_modules -E .git -x sh -c 'echo "-- $1"; cat "$1"' sh {} || true
rg -n -C 8 --glob '!node_modules/**' \
'pm install|extensions|extension.*load|extension.*path|runtime|dist/index|peerDependencies|pm_min_version' \
README.md manifest.json index.ts test package.json || true
printf '%s\n' '== Pinned pm-cli package metadata from npm registry =='
curl --fail --silent --show-error --location \
'https://registry.npmjs.org/@unbrained%2fpm-cli/2026.8.17' \
-o /tmp/pm-cli-package.json
python3 - <<'PY'
import json
p=json.load(open('/tmp/pm-cli-package.json'))
for key in ('name','version','bin','main','files','dependencies','peerDependencies'):
print(f'{key}: {p.get(key)!r}')
print('tarball:', p['dist']['tarball'])
PY
printf '%s\n' '== Pinned pm-cli package extension installation references =='
tarball="$(python3 - <<'PY'
import json
print(json.load(open('/tmp/pm-cli-package.json'))['dist']['tarball'])
PY
)"
rm -rf /tmp/pm-cli-package
mkdir -p /tmp/pm-cli-package
curl --fail --silent --show-error --location "$tarball" -o /tmp/pm-cli.tgz
tar -xzf /tmp/pm-cli.tgz -C /tmp/pm-cli-package
rg -n -C 8 --glob '*.{js,mjs,cjs,json}' \
'npm:|install.*extension|extensionsDir|extension.*install|node_modules|copy.*dist|import\(.*index|loadExtension' \
/tmp/pm-cli-package/package/dist | head -1000 || true
printf '%s\n' '== Pinned CLI bin declaration =='
cat /tmp/pm-cli-package/package/package.json | sed -n '1,180p'Length of output: 202100
The command-injection finding is addressed. The Windows reader now uses Finding
Verified areas
You are interacting with an AI system. |
Use the host-owned PM_CLI_PACKAGE_ROOT contract for shell-free Windows corpus reads instead of resolving the CLI peer from a standalone extension. Validate the declared entry stays inside the host package, harden receipt drift tests and primitive contracts, and record packed-install acceptance evidence.
|
@coderabbitai Fixed the standalone-layout finding in exact head |
|
@sourcery-ai Applied the concrete hardening from your latest review in exact head |
|
@greptileai Exact head |
|
/gemini review Please review exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
requested="$(git rev-parse --verify 45759bd^{commit})"
head="$(git rev-parse HEAD)"
base="$(gh pr view 46 --repo unbraind/pm-github --json baseRefOid --jq .baseRefOid 2>/dev/null || git rev-parse "${requested}^")"
printf 'requested=%s\nhead=%s\nbase=%s\n' "$requested" "$head" "$base"
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$requested"
printf '\n== Complete PR changes ==\n'
git diff --name-status "$base" "$requested"
git diff --stat "$base" "$requested"
printf '\n== Changed source and test outlines ==\n'
git diff --name-only --diff-filter=AM "$base" "$requested" |
rg '\.(ts|tsx|js|mjs|cjs)$' |
while IFS= read -r file; do
printf '\n-- %s --\n' "$file"
ast-grep outline "$file" --items all --type function,class,interface,type --view expanded || true
done
printf '\n== Launcher, reader, decoder, and environment contract ==\n'
rg -n -C 8 --glob '!node_modules/**' \
'PM_CLI_PACKAGE_ROOT|readPmItems|decodeCompletePmItems|completePmListArgs|pmListSpawnOptions|process\.execPath|spawnSync|createRequire|requireCompletePmField|list-all' \
index.ts test package.json README.md
printf '\n== Focused production ranges ==\n'
nl -ba index.ts | sed -n '840,1180p'
printf '\n== Complete-corpus test file ==\n'
cat -n test/complete-corpus.test.ts 2>/dev/null || true
printf '\n== PR diff for source, tests, package metadata, and docs ==\n'
git diff --unified=70 "$base" "$requested" -- \
index.ts test/complete-corpus.test.ts package.json package-lock.json README.md CHANGELOG.mdLength of output: 76023 🏁 Script executed: #!/bin/bash
set -euo pipefail
requested="$(git rev-parse --verify 45759bd^{commit})"
base="f7315e2521d28558a2db3b38e89724ad98875a8c"
printf '%s\n' '== Exact Windows launcher and error path =='
sed -n '1070,1160p' index.ts
printf '%s\n' '== Full complete-corpus tests =='
sed -n '1,320p' test/complete-corpus.test.ts
printf '%s\n' '== Exact changes introduced by requested commit =='
git diff --unified=80 "${requested}^" "$requested" -- index.ts test/complete-corpus.test.ts README.md package.json package-lock.json
printf '%s\n' '== Package contents and pack configuration =='
sed -n '1,220p' package.json
git ls-tree -r --name-only "$requested" | sed -n '1,240p'
git diff --unified=30 "$base" "$requested" -- package.json package-lock.json
printf '%s\n' '== Pinned `@unbrained/pm-cli` registry metadata =='
curl --fail --silent --show-error --location \
'https://registry.npmjs.org/@unbrained%2fpm-cli/2026.8.17' \
-o /tmp/pm-cli-package.json
python3 - <<'PY'
import json
p = json.load(open('/tmp/pm-cli-package.json'))
for key in ('name', 'version', 'bin', 'main', 'files', 'dependencies', 'peerDependencies'):
print(f'{key}: {p.get(key)!r}')
print('tarball:', p['dist']['tarball'])
PY
printf '%s\n' '== Pinned pm CLI implementation of host package root propagation =='
tarball="$(python3 - <<'PY'
import json
print(json.load(open('/tmp/pm-cli-package.json'))['dist']['tarball'])
PY
)"
rm -rf /tmp/pm-cli-package
mkdir -p /tmp/pm-cli-package
curl --fail --silent --show-error --location "$tarball" -o /tmp/pm-cli.tgz
tar -xzf /tmp/pm-cli.tgz -C /tmp/pm-cli-package
rg -n -C 10 'PM_CLI_PACKAGE_ROOT|packageRoot|package_root|spawnSync|execFile|extension' /tmp/pm-cli-package/package \
-g '*.{js,mjs,cjs,json,d.ts}' || trueLength of output: 202275 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== PM_CLI_PACKAGE_ROOT occurrences in the pinned host package =='
rg -n -l -F 'PM_CLI_PACKAGE_ROOT' /tmp/pm-cli-package/package -g '*.{js,mjs,cjs,json,d.ts}' | sort
rg -n -F -C 2 'PM_CLI_PACKAGE_ROOT' /tmp/pm-cli-package/package \
-g '!dist/cli-bundle/sdk-core.js' -g '*.{js,mjs,cjs,json,d.ts}' || true
printf '%s\n' '== Short context for minified bundle occurrences =='
python3 - <<'PY'
from pathlib import Path
for p in Path('/tmp/pm-cli-package/package').rglob('*'):
if not p.is_file():
continue
try:
text = p.read_text(errors='ignore')
except OSError:
continue
needle = 'PM_CLI_PACKAGE_ROOT'
start = 0
while True:
pos = text.find(needle, start)
if pos < 0:
break
print(f'\n-- {p} offset={pos} --')
print(text[max(0, pos-700):pos+1000])
start = pos + len(needle)
PY
printf '%s\n' '== Exact new Windows and installed-artifact tests =='
sed -n '70,280p' test/complete-corpus.test.ts
printf '%s\n' '== Test references to package archives, isolated installs, and PM_CLI_PACKAGE_ROOT =='
rg -n -C 10 \
'npm pack|pack |fresh|install|node_modules|PM_CLI_PACKAGE_ROOT|readPmItems\(' \
test package.json README.md -g '*.{ts,js,mjs,cjs,json,md}'
printf '%s\n' '== Complete requested-commit diff, limited to the new launcher and tests =='
git diff --unified=50 496cb11b3d5f45d30307a827ac80461174a81feb 45759bd277a73b18234a7490ae2bb03733f67894 \
-- index.ts test/complete-corpus.test.ts
printf '%s\n' '== Host package bin declaration and package-root entries =='
python3 - <<'PY'
import json
p=json.load(open('/tmp/pm-cli-package/package/package.json'))
print('bin =', repr(p.get('bin')))
print('files =', repr(p.get('files')))
PY
find /tmp/pm-cli-package/package -maxdepth 3 -type f | sed -n '1,120p'Length of output: 151481 🏁 Script executed: #!/bin/bash
set -euo pipefail
pkg=/tmp/pm-cli-package/package
printf '%s\n' '== Exact host-root assignments in normal host entrypoints =='
for file in \
"$pkg/dist/cli.js" \
"$pkg/dist/cli/main.js" \
"$pkg/dist/mcp/server.js" \
"$pkg/dist/sdk/extension.js" \
"$pkg/dist/sdk/extension/loader.js"
do
if [ -f "$file" ]; then
echo "-- $file --"
rg -n -C 6 -F 'PM_CLI_PACKAGE_ROOT' "$file" || true
fi
done
printf '%s\n' '== All non-minified PM_CLI_PACKAGE_ROOT occurrence locations =='
rg -n -l -F 'PM_CLI_PACKAGE_ROOT' "$pkg" \
-g '!dist/cli-bundle/sdk-core.js' -g '*.{js,mjs,cjs}' | sort
printf '%s\n' '== Host root resolver implementation =='
rg -n -l 'resolvePmPackageRootFromModule' "$pkg/dist" -g '*.{js,mjs,cjs}' |
while IFS= read -r file; do
echo "-- $file --"
rg -n -C 5 'resolvePmPackageRootFromModule' "$file" || true
done
printf '%s\n' '== Path containment behavior for relevant edge cases =='
python3 - <<'PY'
import posixpath
root = '/opt/pm'
for target in ['/opt/pm/dist/cli.js', '/opt/pm-other/cli.js', '/opt/pm/../outside/cli.js']:
resolved = posixpath.normpath(target)
rel = posixpath.relpath(resolved, root)
print(f'root={root!r} target={target!r} resolved={resolved!r} relative={rel!r} rejected={rel.startswith("..") or posixpath.isabs(rel)}')
PY
printf '%s\n' '== Full PR changed production regions and regression-test names =='
git diff --unified=20 f7315e2521d28558a2db3b38e89724ad98875a8c 45759bd277a73b18234a7490ae2bb03733f67894 -- index.ts |
sed -n '1,2200p'
rg -n '^test\(' test/complete-corpus.test.tsLength of output: 140451
I found no new actionable findings. The prior standalone-layout finding is addressed.
I did not run the test suite in this review environment. The environment permits static inspection only. You are interacting with an AI system. |
|
@coderabbitai Acknowledged and verified against the same exact head: the full local release gate, real packed-install acceptance, and both Node CI jobs pass. Thank you for confirming that the host-root fix closes the Windows security and standalone-layout findings with no new actionable issue. |
|
Tip For best results, initiate chat on the files or code changes.
🐇 ✅ You are interacting with an AI system. |
|
Acknowledged. This closes the exact-head CodeRabbit loop: three successive Windows findings were fixed, the final static re-review found no actionable issue, local and GitHub gates pass, and the packed standalone artifact was exercised successfully. Greptile, Sourcery, Semgrep, and both Node jobs are green; Cubic skipped and Gemini produced no response after repeated exact-head triggers. |
Summary
Why
Import idempotency, export, state sync, Projects v2 sync, and search fallback all rely on seeing every item. The previous reader accepted arrays and loosely shaped envelopes, defaulted missing rows to an empty array, ignored truthfulness receipts, and silently capped the corpus at 10,000 rows. A partial read could therefore recreate a closed imported issue or omit remote updates.
Project-management evidence
Verification
npm ci --ignore-scripts: 73 packages, 0 vulnerabilitiesnpm run release:check: pass (typecheck, build, 85/85 docstrings, behavioral coverage gate, production audit, package dry-run, changelog check)bun install --no-save: passpm validate: storage/history integrity pass; pre-existing metadata/file warnings remainpm health --strict-exit: pass with three pre-existing legacy provenance advisoriesIndependent remaining gates
This PR does not claim the separate exact-coverage mandate: current measured production coverage is 91.83% lines, 82.14% branches, and 91.75% functions, and operational scripts remain outside measurement.
pm-github-9cjxowns that work.The current tree contains no absolute host paths, but historical Git objects contain pre-existing path metadata and one machine-local commit identity.
pm-github-zqadrecords the required forward gate and the maintainer decision needed before any destructive rewrite of already-published history/tags.Summary by Sourcery
Enforce strict, complete whole-workspace pm reads before performing any GitHub import, export, or sync, failing closed on partial or unverifiable corpora.
Bug Fixes:
pm list-allcontract and reject truncated, paginated, compacted, or otherwise incomplete outputs instead of treating them as partial workspaces.pmCLI by enabling shell execution only on that platform while preserving direct execution elsewhere.Enhancements:
Build:
Documentation:
Tests:
Chores:
Summary by cubic
Refuses incomplete pm item corpora before any GitHub import, export, or sync, and hardens Windows execution to preserve argument boundaries. Previously we accepted loose arrays/envelopes and capped reads at 10,000 rows; now we require a strict, full, unbounded
pm list-allcontract and fail closed on any unverifiable output.process.execPathusing hostPM_CLI_PACKAGE_ROOTto locate@unbrained/pm-cli’s declaredbin.pm, verifies it resides inside the host package root, and never uses a shell; acceptance covers metacharacter paths and packed installs.completePmListArgsanddecodeCompletePmItemsand routesreadPmItemsthrough them; documents behavior in README; pins the development toolchain to@unbrained/pm-cli2026.8.17; expands adversarial/installed-CLI tests.Required actions
pmCLI is >= 2026.8.3.PM_JSON_MAX_BUFFERto a larger value.PM_CLI_PACKAGE_ROOTfor the installed@unbrained/pm-cli; reads will fail if it is missing.Written for commit 45759bd. Summary will update on new commits.