You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge F13: extract Session.isDescendantOf from auto-reply walk
Move the lineage walk from SessionAutoReply (where it was inline) to
Session.Interface.isDescendantOf. AutoReply still owns its policy
(MAX_LINEAGE_DEPTH=32, per-make-call cache); the helper is generic
(default maxDepth=64) and reusable by ACP/TUI.
The helper auto-seeds root into the cache, guards against cross-root
cache reuse (dies if non-empty cache lacks root), and accumulates
walked descendants for amortized O(1) repeated lookups against the
same lineage.
Diamond: codex-5.3 spec APPROVE, Opus quality APPROVE.
Copilot 4 rounds:
- R1 1 substantive: cache footgun (callers had to remember to seed root)
→ fixed by unconditionally adding root to known at call entry.
- R2 1 substantive + 1 nit: cross-root cache aliasing → fixed by guard
that dies on non-empty cache missing root; test wording → fixed.
- R3 1 substantive + 1 nit: JSDoc overstated guard scope → tightened to
match what the code actually enforces; lost AutoReply trace span →
restored via Effect.fn wrapper.
- R4 clean.
PR (review-only): #16
Refs: F13 in docs/superpowers/plans/2026-04-23-audit-remediation.md
// Defend against accidental cache sharing across different roots: if a
706
+
// caller passes a non-empty cache that lacks `root`, those entries were
707
+
// populated under a different lineage and `known.has(sid)` could
708
+
// short-circuit to true with the wrong answer. Fail loudly instead of
709
+
// returning a silently wrong result.
710
+
if(known.size>0&&!known.has(root)){
711
+
returnyield*Effect.die(
712
+
newError(
713
+
`Session.isDescendantOf: opts.cache appears to belong to a different root (size=${known.size}, missing root=${root}). Caches must not be shared across roots.`,
714
+
),
715
+
)
716
+
}
717
+
// Always seed `root` into the working set so the parent walk has a
718
+
// termination anchor and the next cross-root reuse check still works.
719
+
known.add(root)
720
+
if(sid===root)returntrue
721
+
if(known.has(sid))returntrue
722
+
// Walk parent chain. Track the chain so we can promote every visited
723
+
// node into the cache once we hit a known descendant — turns repeated
724
+
// calls against the same lineage into O(1) after the first walk.
0 commit comments