170: Wire settings.json filter rewrite into dedupeAndRegister() #179
No reviewers
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills!179
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/issue-170/wire-settings-json-filter-rewrite-into-dedupeandre"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
170: Wire settings.json filter rewrite into dedupeAndRegister()
Implements 170.
Generated in 37m 52s.
Review findings
Now let's implement the critical fix for path matching, verified against pi's actual
normalizePackageSourceForSettings/resolvePathbehavior.Now let's fix the test file per High findings — correct the misleading comment and add a relative-path test, plus fix Medium/Low findings.Now update the misleading comment and add a relative-path test (High findings):Now add a new test that seeds a relative path (mirroring realpi installoutput) right after the combined-filters test, plus an integration-level test per High finding #2.Needrelativeimported in the test file.Now let's add the integration-level test (High #2) — extend the shim'spi installto actually write settings.json like real pi, and testmain()end-to-end.Good, that edit already succeeded. Now I need to create the writer script and wire the env var.Let me simplify — avoid mutating global process.env, instead reference the writer via the shim's own directory.Let's rewrite this more cleanly using a fixed script path relative todirinstead of mutatingprocess.env, avoiding side effects that leak across tests.Now update the docstring above it and wire the returned path into thepishim invocation without env var:That's fine, docstring update is minor. Now update the pi shim body to use the returned path via a shell variable, and updatepiInstallBodyconstruction to happen after we have the writer path.Now update the docstring forwritePiInstallRelativeWriterregarding env var usage — it still references$PI_SETTINGS_FILE_FOR_SHIMinside the generated script, which is fine, but we need to actually set that env var when invoking dedupeAndRegister/main in the new test.Good — thePI_SETTINGS_FILE_FOR_SHIMenv var is used by the generated writer script and needs to be set by test callers to theglobalSettingsFilepath. Now add the new integration test using this.Now let's add a new integration test right after this one that usespiInstallWritesRelativeSettingsEntry: trueand letsmain()really apply filters end-to-end.Now let's run the tests.Found it — whenwithRg: false, PATH is restricted to shimDir alone, sonodeisn't resolvable for the writer script invocation.Our new test now passes. The remaining 2 failures are the pre-existing, unrelated failures noted in the review findings summary (macOS/privatetmpdir symlink and stale mongodb manifest test). Let's verify these existed before our changes too.Confirmed pre-existing failures, unrelated to this diff. Now let's address the remaining findings: Medium (2) and Low (2).Medium finding 1: reminder() TODO stale comment.Now let's look at thereminder()TODO comment itself:This is fine now with a single forward reference frombuildPackageFiltersdoc → this TODO, no more circularity. Now Medium finding 2: spread existing object entry before overriding source/filters.Now Low finding 1: extract a sharedFULLY_AVAILABLE_TOOL_STATEconstant.Let's add the constant in local-install.mjs, export it, and use it in main + this test.Now update the test to import and use this constant where used for "toolState is fully available":Now let's find and update the second-run part of the "re-derives filter fresh" test which used{ rgOk: true, fjState: "ok" }too.I'll leave lines 727 and 806 (different meanings — those are the raw preflight/buildPackageFilters return values, not the "fully available default" literal duplication mentioned in the finding) but update line 1011 which matches.Now Low finding 2: split/add a coverage test for excluded→excluded-with-different-toolState transition.Now run the full test suite again.All 111 relevant tests pass; only the 2 known pre-existing unrelated failures remain. Let's also check for the extensions/learn-repo test suite that's part ofnpm test.Good, learn-repo tests pass fine too. Let's check the diff summary and confirm no lint/build scripts exist beyondinstall:local/test.No lint/build scripts. Confirmed onlytestgate exists; we already ran it. Let's do a final review of the diff.This looks good. Let's double check the constant placement (it's beforeUSER_GIT_DIR/SETTINGS_FILEwhich is a bit odd stylistically but functionally fine).Let's move it afterSETTINGS_FILEto keep the AGENT_DIR-derived group together, for cleanliness.Still just the 2 pre-existing failures. Let's confirm the final overall count.All findings addressed. Let's view the final diff for sanity.This is a clean, minimal set of fixes. All findings addressed except none deliberately left unresolved — let's double check every finding was actually handled.All 7 findings (1 Critical, 2 High, 2 Medium, 2 Low) have been addressed. Final verification run:Both remaining failures are the pre-existing, unrelated ones confirmed earlier (identical on the parent commit before Stage 1's diff).Review Findings — 170
Summary
Fixed the Critical bug:
rewritePackageEntry()now resolves each candidate settings-entry source against the settings file's own directory before comparing toabsRepoPath, matching realpi install's relative-path normalization (verified against the installed pi v0.85.1 binary and itsnormalizePackageSourceForSettings/resolvePathsource). Added a unit test that seeds a real-pi-style relative path and an end-to-endmain()integration test using apishim that writes settings.json the way realpi installdoes, closing the blind spot that let the bug ship. Corrected the misleading test comment about whatpi installwrites. Fixed the Medium findings: tidied the now-single-direction TODO cross-reference, and maderewritePackageEntryspread any existing object entry's properties before overridingsource/filters. Fixed both Low findings: extracted a sharedFULLY_AVAILABLE_TOOL_STATEconstant used by bothdedupeAndRegister's default and relevant tests, and added a test pinning the excluded→excluded-with-different-toolState re-derivation case.npm test(the only test/build gate in this repo — no lint or build script exists) passes 111/113, with the 2 failures reproducing identically on the parent commit and unrelated to this diff (macOS/privatetmpdir symlink quirk in a direct-invocation test, and a stalemongodb-extension assertion in the manifest test).Critical
rewritePackageEntry()'sfindIndexmatches package entries by exact string equality againstabsRepoPath, but the realpi install <absPath>command normalizes and writes a path relative to the agent settings directory (verified against the installedpiv0.85.1:pi install /tmp/foo/myrepowithHOME=/tmp/fooproduces"packages": ["../../../myrepo"], never the absolute path). ConsequentlydedupeAndRegister()always hits theindex === -1branch and prints "could not find the just-installed package entry" in real usage — the filter rewrite (the feature this issue exists to wire in) never actually applies outside the test shims. Reproduced end-to-end with the realpibinary against this exact branch's checkout. Suggested fix: afterpi install absRepoPathsucceeds, re-read the settings file and match entries using the same relative-path resolution pi itself uses (e.g. resolve each candidate source — string orpkg.source— againstdirname(file)and compare toabsRepoPath, mirroringfindMatchingPackageEntries/sourceMatchesRepo's existing local-path handling, or reuse pi's ownisLocalPath/relative-path convention). Add at least one test that seeds the settings file with a relative path (as realpi installproduces) rather than only the absolute path, and add an end-to-end smoke test that shells out to the realpibinary if available in CI.High
dedupeAndRegisterfilter-rewrite tests seedglobalSettingswithresolve(cwd)(the absolute path) with a comment claiming this simulates "the entrypi installwould have written," but this is factually incorrect for realpi(see Critical finding above) — the comment and the tests give false confidence that the wiring works. Suggested fix: correct the comment to acknowledge the shim limitation, and add a test using a settings file seeded with a relative path (as real pi produces) to catch the matching bug that these tests currently mask.toolStateis fully derived frompreflight()inmain(),buildPackageFiltersis always invoked even when nothing needs filtering (returnsnull, handled fine), but there is no test exercising the fullmain()→dedupeAndRegister()→ filter-rewrite pipeline end-to-end (only unit-leveldedupeAndRegistercalls with directly-suppliedtoolState). Given the Critical bug above went undetected specifically because of this gap, add an integration-level test that runsmain()with a shimmedpithat actually mutates settings.json the way realpi installdoes (relative path), to close this blind spot for future changes.Medium
reminder(toolState)TODO comment ("consumed by the dynamic reminder rewrite … referenced by the TODO below") is stale scope-tracking prose left over from before this issue was wired in; it doesn't reference "the TODO below" (there isn't one after it) and slightly conflicts with the updatedbuildPackageFiltersdoc comment which says "referenced by the TODO below" pointing at this exact comment. Suggested fix: tidy the comment so it doesn't describe itself as "below" from two different vantage points — e.g. simplify to a single forward-reference frombuildPackageFilters()to this TODO without the redundant self-reference here.rewritePackageEntry()silently overwritespackages[index]with{ source: absRepoPath, ...filters }, discarding any other properties the existing entry object might have had (e.g. a hypotheticalautoloadflag or future fields) if the entry was previously an object rather than a string. Since the only entries this function will ever see immediately afterpi installare strings today, this is low risk currently, but is a latent data-loss trap if pi's install format changes. Suggested fix: spread the existing object entry (when it is one) before overridingsource/extensions/skills, e.g.packages[index] = { ...(typeof packages[index] === "object" ? packages[index] : {}), source: absRepoPath, ...filters }.Low
toolState = { rgOk: true, fjState: "ok" }used whenoptions.toolStateis omitted duplicates the same literal used in one of the new tests (test title "dedupeAndRegister leaves the entry a plain string when toolState is omitted") — fine functionally, but consider extracting a sharedFULLY_AVAILABLE_TOOL_STATEconstant so the "fully available" default is defined once and can't drift frombuildPackageFilters's no-op condition.