fix(slice-17): default rail item filter

This commit is contained in:
mvschwarz committed 2026-05-11 06:48:12 -07:00
1 parent c9578b381f
commit 189112a3de
2 files changed
+29 -4

No files matched your search

@@ -435,11 +435,13 @@ export class SliceIndexer {
// 2. Substring matches. Terms are chosen so the missionId term
// is INCLUDED only when no typed-tag rows exist (legacy
// compatibility); otherwise the slice-specific terms (sliceName +
// railItem) drive matching. railItem stays in both branches
// because it's slice-scoped, not mission-scoped.
// compatibility); otherwise the slice-specific terms drive
// matching. In mission-folder workspaces, railItem defaults to
// missionId when no explicit rail item is authored, so the typed-tag
// branch must not blindly keep that fallback or mission-only qitems
// leak back into every slice in the mission.
const substringTerms = (typedTagMatchCount > 0
? [sliceName, railItem]
? [sliceName, railItem === missionId ? null : railItem]
: [sliceName, railItem, missionId]
).filter((v): v is string => !!v);
for (const term of Array.from(new Set(substringTerms))) {
@@ -325,6 +325,29 @@ describe("PL-slice-story-view-v0 SliceIndexer", () => {
expect(slice.qitemIds).not.toContain("q-mission-tag-only");
});
it("does not re-include mission-only qitems when railItem defaults to missionId", () => {
const missionsRoot = path.join(cleanup, "missions");
writeSlice(path.join(missionsRoot, "release-fake-default-rail", "slices"), "fake-slice-default-rail", {
"README.md": "---\nstatus: active\n---\n# Fake default rail\n",
});
insertQitem(db, {
qitemId: "q-default-rail-typed-slice-tag",
body: "Body without slice name.",
tags: ["slice:fake-slice-default-rail"],
});
insertQitem(db, {
qitemId: "q-default-rail-mission-tag-only",
body: "Body without slice name.",
tags: ["mission:release-fake-default-rail"],
});
const indexer = new SliceIndexer({ slicesRoot: missionsRoot, dogfoodEvidenceRoot: null, db });
const slice = indexer.get("fake-slice-default-rail")!;
expect(slice.railItem).toBe("release-fake-default-rail");
expect(slice.qitemIds).toEqual(["q-default-rail-typed-slice-tag"]);
expect(slice.qitemIds).not.toContain("q-default-rail-mission-tag-only");
});
it("preserves legacy substring fallback (including mission body) when NO typed slice: tag exists", () => {
// When no qitem has the typed `slice:<name>` tag, the indexer
// falls back to the pre-fix three-term substring union so older