@akagilnc/pi-workflow-roles 0.1.2181 → 0.1.2203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -401,7 +401,9 @@ async function classifyScopedRun(input: {
401
401
  /**
402
402
  * Scan ledger home books/<book>/runs for runs in the issue scope.
403
403
  * #399: scope = book × optional ticket.
404
- * - bookKey set → that book only; whole-book when no ticket; ticket filters alone.
404
+ * - bookKey set → that book only; whole-book when no ticket and no projectRoot;
405
+ * ticket filters alone; bookKey + projectRoot (cohort ensure, #412) narrows
406
+ * to that root inside the book.
405
407
  * - projectRoot without bookKey (sweep/legacy): git-resolved → whole that book;
406
408
  * non-git → path-narrow across books (fixture isolation).
407
409
  * Damaged required sources become unreadable exclusions.
@@ -429,8 +431,16 @@ export async function scanTaishiIssueRuns(input: {
429
431
 
430
432
  if (input.bookKey !== undefined && input.bookKey.trim() !== "") {
431
433
  bookNames = [input.bookKey];
432
- // CLI book scope: whole book unless ticket filters. Never path-narrow.
433
- wholeBook = true;
434
+ if (input.projectRoot !== undefined) {
435
+ // Cohort ensure conjunction (#412): the index join already selected the
436
+ // row — a cache-miss recompute must stay inside this root of this book,
437
+ // never inhale sibling roots' runs into one issue page.
438
+ wholeBook = false;
439
+ scopeRootIdentity = physicalPathIdentity(input.projectRoot);
440
+ } else {
441
+ // CLI book scope: whole book unless ticket filters. Never path-narrow.
442
+ wholeBook = true;
443
+ }
434
444
  } else if (input.projectRoot !== undefined) {
435
445
  const resolved = tryResolveBookKeyFromProjectRoot(input.projectRoot);
436
446
  if (resolved !== undefined) {