Skip to content

Add package install recovery and collision plans - #136

Merged
unbraind merged 3 commits into
mainfrom
feature/pm-e48i-package-recovery-collision-plan
Jun 7, 2026
Merged

Add package install recovery and collision plans#136
unbraind merged 3 commits into
mainfrom
feature/pm-e48i-package-recovery-collision-plan

Conversation

@unbraind

@unbraind unbraind commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Verification

  • node scripts/run-tests.mjs test -- tests/unit/cli-main-errors.spec.ts tests/unit/extension-command.spec.ts tests/unit/error-guidance.spec.ts
  • pnpm typecheck
  • pnpm build
  • pnpm contracts:check
  • pnpm quality:static
  • pnpm security:scan
  • pnpm audit --audit-level low
  • node scripts/run-tests.mjs coverage (2531 tests, 100% statements/branches/functions/lines)
  • PM_AUTHOR=codex-impl-20260607 pm health --check-only --summary --json
  • PM_AUTHOR=codex-impl-20260607 pm validate --check-resolution --check-history-drift (history drift ok; pre-existing resolution warnings remain on older closed items)
  • isolated temp smoke against dist/cli.js at /tmp/pm-e48i-smoke-cQqRP5
  • pnpm changelog:pm:check

Tracker

  • pm-e48i closed and released with linked files/docs/tests/evidence.

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

Bundle pm-e48i for GitHub issues #133 and #134.

Add structured npm 404 recovery for npm:<name> package installs, including fallback_candidates and next_best_command for unpublished first-party packages.

Add package doctor triage.collision_plan for extension registration collisions with deterministic deactivate candidates and command/action feature-loss hints.

Preserve command-specific recovery metadata when the top-level CLI enriches error context, document the new JSON surfaces, and update pm-changelog output.

Verification: focused unit tests, pnpm typecheck, pnpm build, pnpm contracts:check, pnpm quality:static, pnpm security:scan, pnpm audit --audit-level low, full coverage 2531 tests at 100%, pm health, pm validate history drift, and isolated temp smoke.
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@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

unbraind commented Jun 7, 2026

Copy link
Copy Markdown
Owner Author

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

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jun 7, 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 44 minutes and 32 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ 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: bc57308d-cba5-480d-aa8a-7ac48d6ab18e

📥 Commits

Reviewing files that changed from the base of the PR and between fbc7b8e and 5823659.

📒 Files selected for processing (6)
  • .agents/pm/history/pm-e48i.jsonl
  • .agents/pm/tasks/pm-e48i.toon
  • docs/EXTENSIONS.md
  • src/cli/commands/extension/install-sources.ts
  • tests/unit/cli-main-errors.spec.ts
  • tests/unit/extension-command.spec.ts
📝 Walkthrough

Walkthrough

This PR delivers two complementary error-recovery and diagnostics features: (1) deterministic npm 404 fallback hints with structured recovery candidates and next-best commands for missing packages, and (2) machine-readable extension collision planning in doctor output with ranked remediation candidates and feature-loss estimates. Both features share an extended error recovery payload infrastructure and improve autonomous workflow reliability.

Changes

npm install fallback hints and extension collision planning

Layer / File(s) Summary
Error recovery types and public interfaces
src/core/shared/errors.ts, src/cli/commands/extension.ts
PmCliErrorRecoveryPayload adds optional fallback_candidates array (source/command/reason tuples) and next_best_command string. ExtensionTriageSummary adds optional collision_plan field with new ExtensionCollisionPlan type describing collision status, affected extension counts, sorted collision records, and per-extension remediation candidates including feature-loss paths.
npm install fallback recovery implementation
src/cli/commands/extension/install-sources.ts, src/cli/error-guidance.ts, src/cli/main.ts
New npm-spec helpers detect 404 errors from registry lookups and construct recovery payloads with fallback candidates (canonical GitHub source, catalog entries) and next-best command. Error-guidance normalizes and renders fallback candidates and next-best-command fields in recovery text output. Recovery context builder forwards new fields through the CLI error pipeline.
Extension collision plan generation
src/cli/commands/extension/doctor.ts
Collision warning parsing extended to extract surface identifiers from warning text. New buildRegistrationCollisionPlan function transforms parsed collisions into sorted records, counts affected extensions, and builds ordered remediation candidates (deactivate commands with sorted feature-loss action paths). Triage summary integrates collision plan computation and conditionally includes collision_plan when collisions detected.
Test coverage for both features
tests/unit/cli-main-errors.spec.ts, tests/unit/error-guidance.spec.ts, tests/unit/extension-command.spec.ts
Recovery context tests assert fallback_candidates and next_best_command preservation. Error guidance tests verify JSON and display formatting retain recovery structure for npm_package_not_found. Integration tests cover npm install fallback rejection with structured context and extension triage collision plan validation including conflict counts, deactivate candidates, and affected surfaces.
Documentation and task tracking
docs/EXTENSIONS.md, CHANGELOG.md, .agents/pm/tasks/pm-e48i.toon, .agents/pm/history/pm-e48i.jsonl
EXTENSIONS.md documents npm 404 recovery bundle and fallback source priority (GitHub as canonical for first-party packages) and collision plan structure with ranked remediation. CHANGELOG entry and task records capture implementation scope, affected components, tests, and verification evidence.

Sequence Diagram

sequenceDiagram
  participant CLI as CLI/pm install
  participant Resolver as InstallSourceResolver
  participant Registry as npm Registry
  participant ErrorHandler as ErrorHandler
  participant Output as JSON/Display Output
  CLI->>Resolver: resolveInstallSource(npm:spec)
  Resolver->>Registry: npm pack (404)
  Registry-->>Resolver: 404 Not Found error
  Resolver->>Resolver: detectNpmNotFound()
  Resolver->>Resolver: buildRecoveryPayload(fallback_candidates, next_best_command)
  Resolver->>ErrorHandler: throw PmCliError(NOT_FOUND, recovery)
  ErrorHandler->>ErrorHandler: normalizeRecoveryPayload()
  ErrorHandler->>ErrorHandler: renderRecoveryBundle()
  ErrorHandler->>Output: formatted error with recovery hints
  Output-->>CLI: structured recovery (candidates + next command)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 accurately summarizes the two main changes: adding package install recovery hints and collision plans for extension diagnostics.
Description check ✅ Passed The description clearly relates to the changeset, explaining fixes for #133 and #134, recovery metadata preservation, collision planning, and comprehensive verification steps.
Linked Issues check ✅ Passed The PR successfully addresses both #133 (npm 404 fallback recovery with fallback_candidates and next_best_command) and #134 (collision_plan with ranked deactivation candidates and feature-loss hints).
Out of Scope Changes check ✅ Passed All changes align with the stated objectives: recovery payload/guidance updates, collision plan implementation, documentation, tests, and task tracking (pm-e48i).

✏️ 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.

Compress the new package recovery and collision-plan notes plus related-docs links so docs/EXTENSIONS.md stays below the docs-skills gate line limit.
@unbraind

unbraind commented Jun 7, 2026

Copy link
Copy Markdown
Owner Author

Updated after CI docs-size failure; docs gate passes locally now. Re-running review agents for the new head.

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

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/EXTENSIONS.md (1)

1-460: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Public docs length gate is currently blocking this PR.

docs/EXTENSIONS.md is now 460 lines, but CI enforces a max of 450 for public docs, so Docs/skills fails. Please trim or split ~10+ lines (for example, move detailed examples to a secondary doc and link to it) to restore a green gate.

🤖 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 `@docs/EXTENSIONS.md` around lines 1 - 460, The doc exceeds the 450-line public
docs gate; trim ~10+ lines by extracting verbose example blocks or long lists
into a secondary doc and replacing them with brief links. For example, move the
"Runnable Examples" list and/or the long "Package Sources" and "Bundled
first-party packages" install examples into a new appendix doc, then replace
those sections in EXTENSIONS.md with a one-line pointer and update related
references (e.g., the "Runnable Examples" heading, the "Package Sources" code
examples, and the bulleted bundled packages list) so the file drops under 450
lines while preserving links and README anchors.

Sources: Coding guidelines, Pipeline failures

🧹 Nitpick comments (2)
tests/unit/cli-main-errors.spec.ts (1)

58-64: ⚡ Quick win

Assert fallback candidate reason to lock the full recovery contract.

The test claims command-specific fallback recovery is preserved, but it currently doesn’t validate fallback_candidates[].reason, so that field could regress unnoticed.

Proposed assertion tightening
       fallback_candidates: [
         {
           source: "github.com/unbraind/pm-brief",
           command: "pm install --project github.com/unbraind/pm-brief",
+          reason: "canonical first-party GitHub repository fallback",
         },
       ],
🤖 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 `@tests/unit/cli-main-errors.spec.ts` around lines 58 - 64, Add an assertion in
the test that validates the fallback candidate's reason field so the recovery
contract is locked down; locate where the test inspects fallback_candidates (and
next_best_command) in tests/unit/cli-main-errors.spec.ts and assert that
fallback_candidates[0].reason equals the expected descriptive string for the
command-specific fallback (alongside the existing checks for fallback_candidates
and next_best_command) to prevent silent regressions.
tests/unit/extension-command.spec.ts (1)

863-873: ⚡ Quick win

Assert the full recovery payload shape, not just a subset.

The current matcher omits attempted_command, normalized_args, and fallback reason, so regressions in those fields won’t be caught on this runtime path.

Proposed assertion tightening
       context: {
         code: "npm_package_not_found",
         recovery: {
+          attempted_command:
+            "pm install --project npm:pm-definitely-missing-for-fallback-test-zzzzzz",
+          normalized_args: [
+            "install",
+            "--project",
+            "npm:pm-definitely-missing-for-fallback-test-zzzzzz",
+          ],
           next_best_command:
             "pm install --project github.com/unbraind/pm-definitely-missing-for-fallback-test-zzzzzz",
           fallback_candidates: [
             {
               source: "github.com/unbraind/pm-definitely-missing-for-fallback-test-zzzzzz",
               command: "pm install --project github.com/unbraind/pm-definitely-missing-for-fallback-test-zzzzzz",
+              reason:
+                "canonical first-party GitHub repository fallback for unpublished pm packages",
             },
           ],
         },
       },
🤖 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 `@tests/unit/extension-command.spec.ts` around lines 863 - 873, The test
currently only asserts parts of the recovery object; update the assertion in
tests/unit/extension-command.spec.ts to validate the full recovery payload shape
(include attempted_command, normalized_args, and each fallback candidate's
reason in addition to next_best_command and fallback_candidates) instead of a
partial match—locate the expectation that checks the "recovery" object (likely
using toMatchObject or similar) and expand it to assert these exact fields and
their expected values/types so regressions in attempted_command,
normalized_args, and fallback.reason are caught.
🤖 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 `@src/cli/commands/extension/install-sources.ts`:
- Around line 199-207: The current isNpmNotFoundError helper is too broad (it
matches any "not found") and causes unrelated failures to be remapped to
npm_package_not_found; change isNpmNotFoundError to only detect explicit npm
registry signatures (e.g., "npm ERR! code E404", "404 not found", "is not in
this registry") and remove the generic "not found" check, then add a new helper
(e.g., isNpmPackNotFoundError) that includes the broader "not found" string and
use that new helper only in the catch block that wraps the npm pack/extraction
flow (the npm pack failure path), leaving all other call sites to use the
stricter isNpmNotFoundError to avoid mislabeling unrelated errors.
- Around line 214-240: buildNpmNotFoundRecovery is unconditionally emitting a
first-party GitHub fallback (githubSource/nextBestCommand) even for
non-first-party specs; change it to only add the githubSource, next_best_command
and fallback_candidates when the spec is clearly a first-party package (e.g.,
derived packageName has the expected first-party scope or org like "`@unbraind/`"
or otherwise matches your project's first-party naming convention). Use
npmPackageNameFromSpec to derive packageName, check its scope/org or pattern,
and only populate githubSource, nextBestCommand and the
fallback_candidates/recovery fields when that check passes; otherwise omit those
first-party-specific suggestions. Ensure references to githubSource and
nextBestCommand are only used after the guard so you don't emit misleading
commands for third-party packages.

In `@tests/unit/extension-command.spec.ts`:
- Around line 857-876: The test "classifies missing npm package installs with
deterministic fallback recovery" currently relies on a live npm 404; instead
stub or mock the npm resolution path so resolveInstallSource and any underlying
npm resolution function (e.g., the module/function that performs npm registry
lookups or the command runner used by resolveInstallSource) returns a synthetic
"package not found" error with the same shape (exitCode EXIT_CODE.NOT_FOUND and
context.code "npm_package_not_found" plus the expected recovery payload).
Replace the direct
parseExtensionInstallSource("npm:pm-definitely-missing-for-fallback-test-zzzzzz")
live-lookup behavior with a test seam/mocked response for the npm resolution and
assert the identical rejection shape from resolveInstallSource.

---

Outside diff comments:
In `@docs/EXTENSIONS.md`:
- Around line 1-460: The doc exceeds the 450-line public docs gate; trim ~10+
lines by extracting verbose example blocks or long lists into a secondary doc
and replacing them with brief links. For example, move the "Runnable Examples"
list and/or the long "Package Sources" and "Bundled first-party packages"
install examples into a new appendix doc, then replace those sections in
EXTENSIONS.md with a one-line pointer and update related references (e.g., the
"Runnable Examples" heading, the "Package Sources" code examples, and the
bulleted bundled packages list) so the file drops under 450 lines while
preserving links and README anchors.

---

Nitpick comments:
In `@tests/unit/cli-main-errors.spec.ts`:
- Around line 58-64: Add an assertion in the test that validates the fallback
candidate's reason field so the recovery contract is locked down; locate where
the test inspects fallback_candidates (and next_best_command) in
tests/unit/cli-main-errors.spec.ts and assert that fallback_candidates[0].reason
equals the expected descriptive string for the command-specific fallback
(alongside the existing checks for fallback_candidates and next_best_command) to
prevent silent regressions.

In `@tests/unit/extension-command.spec.ts`:
- Around line 863-873: The test currently only asserts parts of the recovery
object; update the assertion in tests/unit/extension-command.spec.ts to validate
the full recovery payload shape (include attempted_command, normalized_args, and
each fallback candidate's reason in addition to next_best_command and
fallback_candidates) instead of a partial match—locate the expectation that
checks the "recovery" object (likely using toMatchObject or similar) and expand
it to assert these exact fields and their expected values/types so regressions
in attempted_command, normalized_args, and fallback.reason are caught.
🪄 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: d55ede82-682e-4e7a-845f-9f2c33166a02

📥 Commits

Reviewing files that changed from the base of the PR and between f8d9f31 and fbc7b8e.

📒 Files selected for processing (13)
  • .agents/pm/history/pm-e48i.jsonl
  • .agents/pm/tasks/pm-e48i.toon
  • CHANGELOG.md
  • docs/EXTENSIONS.md
  • src/cli/commands/extension.ts
  • src/cli/commands/extension/doctor.ts
  • src/cli/commands/extension/install-sources.ts
  • src/cli/error-guidance.ts
  • src/cli/main.ts
  • src/core/shared/errors.ts
  • tests/unit/cli-main-errors.spec.ts
  • tests/unit/error-guidance.spec.ts
  • tests/unit/extension-command.spec.ts

Comment thread src/cli/commands/extension/install-sources.ts Outdated
Comment thread src/cli/commands/extension/install-sources.ts
Comment thread tests/unit/extension-command.spec.ts Outdated
Address CodeRabbit feedback on PR #136.

Narrow npm not-found classification, keep broad generic matching inside the npm-pack wrapper, and only emit first-party GitHub fallback candidates for @unbrained/pm-* or pm-* package names.

Replace the live registry 404 test with synthetic wrapper coverage and assert the full recovery payload, including attempted_command, normalized_args, fallback reason, and next_best_command.

Verification: focused unit tests, typecheck, docs-skills/static/security gates, contracts/changelog checks, isolated temp smoke, and full 100% coverage.
@unbraind

unbraind commented Jun 7, 2026

Copy link
Copy Markdown
Owner Author

Addressed CodeRabbit feedback: narrowed npm 404 classification, gated first-party GitHub fallback suggestions, removed live registry dependency from tests, and tightened recovery payload assertions. Re-running review agents for the new head.

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

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@chatgpt-codex-connector

Copy link
Copy Markdown

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

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

@unbraind Thanks for the update — I'll kick off a fresh review now, incorporating your changes around the narrowed npm 404 classification, the gated first-party GitHub fallback, the offline-safe tests, and the tightened recovery payload assertions.


🧠 Learnings used
Learnt from: CR
Repo: unbraind/pm-cli PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-20T21:10:16.414Z
Learning: Use sandbox-safe commands for verification. For documentation-only work, run at least `pnpm build` and a focused link/content check. For broader work, run linked tests, coverage, validation, and release gates.
✅ 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.

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.

Add collision-aware extension profiles for multi-package installs Improve npm install fallback for unpublished pm packages

1 participant