fix(lifecycle): fail closed on inconclusive npm ghost probes#399
Merged
Conversation
npm global list probing returned undefined on any non-zero exit without parsing stdout, so ghost uninstall recovery could clear tracked state while the managed package was still installed. Use scoped npm list probes with present/absent/unknown outcomes and only recover ghost state when absence is confirmed.
a7ce2d9 to
9925317
Compare
Contributor
Author
There was a problem hiding this comment.
Quantex PR Governance — PR #399
Verdict: No blocking governance issues. Merge-ready after maintainer review. Not approving.
OpenSpec intake
- Correctly classified as behavior change (
agent-updateghost recovery). - Active change
fix-npm-ghost-probe-false-positiveincludes proposal, design, spec delta, and completed tasks. bun run openspec:validatepasses; change status is complete.- Archive closure remains post-merge (expected); OpenSpec Archive agent should merge the new npm inconclusive scenario additively into
openspec/specs/agent-update/spec.md.
Validation
- Surface is lifecycle/package-manager behavior with tests —
lint,format:check,typecheck,test, andmemory:checkare appropriate. - CI is green: classify, lint, full test matrix, sandbox-tests, PR body validation.
- No evidence of blind CI patching; fix is targeted with regression coverage.
PR body / closure
- Template sections present;
bun run pr:body:checkpasses locally. - Release intent
patchmatchesfix(lifecycle):commit metadata. - Closure check correctly states OpenSpec change stays active until archive follow-up.
Non-blocking
- No linked issue for the regression context (acceptable if reproduced on
main). - Validation checklist omits
bun run openspec:validate(change validates cleanly). - Spec delta re-lists existing ghost-recovery scenarios; archive PR must add only the npm inconclusive scenario.
- Final commit is maintainer-authored on a Cursor branch; human maintainer review still owns merge judgment for lifecycle surface.
Post-merge owners
- Archive: OpenSpec Archive agent
- Release: release-please patch via protected
mainCI
Sent by Cursor Automation: Quantex CLI PR Governance
| - **THEN** Quantex does not remove the installed-agent state entry | ||
| - **AND** the uninstall command reports failure | ||
|
|
||
| #### Scenario: Ghost recovery does not run when npm presence probing is inconclusive |
Contributor
Author
There was a problem hiding this comment.
Non-blocking (archive follow-up): this delta re-lists the existing ghost-recovery requirement. Archive agent should merge additively — add only the npm inconclusive-probe scenario to openspec/specs/agent-update/spec.md, without duplicating or dropping prior scenarios.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Fail closed when npm ghost-state recovery cannot conclusively determine whether a tracked package is absent. Scoped npm presence probing now distinguishes
present,absent, andunknown, preserves state on structured npm errors, and treats an existing package entry as present even when its version is unreadable.Linked Artifacts
openspec/changes/fix-npm-ghost-probe-false-positiveValidation
bun run memory:checkbun run lintbun run format:checkbun run typecheckbun run test(if behavior changed)Release Intent
Docs Updated
docs/...openspec/...Scope Check
Closure Check
Notes
Reproduced on current
main: whennpm list -g --depth=0 --jsonexits non-zero while stdout still shows the target package at version2.0.0,getInstalledVersion()returnsundefined; the uninstall ghost-state path interprets that as confirmed absence and removes tracked state.The final branch contains one maintainer-authored commit. Local validation passes with 61 test files and 646 tests.