ADR 002: Explicit routing strategy seam
Status
Section titled “Status”Accepted and partially implemented. Reviewed 2026-05-09; still relevant.
The typed strategy seam, richer dry-run presenter output, and expanded eval fixtures have shipped. The broader guidance remains active for future routing work, especially named-bank or identity-aware routing.
Context
Section titled “Context”Pi Hindsight defaults to safe project-local automatic retain. User Bank automatic retain is disabled unless the user selects a profile or config mode that explicitly enables it. Legacy config/tool aliases still use global for this User Bank route.
The current router is intentionally conservative and heuristic. It classifies candidate memory as project, global, both, or skip, where global is the legacy route name for the configured User Bank. hindsight_route_memory exposes the decision as a dry run in explicit-only mode. This is useful, but the seam needs a clear product contract before adding richer bank topologies such as per-user, per-agent, shared-knowledge, or explicit named banks.
The main safety risk is silent User Bank pollution. Better routing must not make User Bank writes the default.
Decision
Section titled “Decision”Routing remains opt-in for automatic writes. userRetain.mode = "explicit-only" stays the default. globalRetain.mode remains a legacy compatibility alias, not the preferred user-facing term.
Pi Hindsight treats routing as an explicit strategy seam with stable input and output shapes. The default strategy keeps today’s project/User Bank behavior while preserving legacy route values (project, global, both, skip) for compatibility. Future strategies may route to additional bank topologies only behind explicit configuration and dry-run inspection.
Routing input shape
Section titled “Routing input shape”Current implementation uses a compact typed seam:
interface RoutingCandidate { content: string; context?: string; config: ResolvedConfig; cwd?: string; projectBankId?: string; sessionFile?: string;}
interface RoutingStrategyInput { content: string; context?: string; config: ResolvedConfig; missions: { project: string; global: string; // legacy route name for User Bank mission }; cwd?: string; projectBankId?: string; sessionFile?: string;}Future strategies may add normalized identity or channel context only after the source of that identity is documented.
Routing output shape
Section titled “Routing output shape”The dry-run operation returns an explainable decision:
type MemoryRoute = "project" | "global" | "both" | "skip";type RoutingBankRole = "project" | "global";
interface MemoryRouteDecision { route: MemoryRoute; confidence: number; signals: Array<"project" | "global" | "skip">; matchedSignals: string[]; reason: string; mode: "explicit-only" | "router"; writes: RoutingBankRole[]; targets: Array<{ bankRole: RoutingBankRole; bankId: string; tags: string[]; willWrite: boolean; }>; safetyNotes: string[]; projectMission: string; globalMission: string; // legacy route name for User Bank mission}The legacy global route name should be preserved until a compatibility break is intentional. User-facing copy should describe that target as User Bank memory.
Safety policy
Section titled “Safety policy”explicit-onlymeans dry-run only. No automatic User Bank writes.- Router mode must be opt-in and visible in
/hindsightstatus/config. - User Bank writes require high confidence or explicit user action.
- Ambiguous project/User Bank content should prefer
bothwith conservative tags, or ask/dry-run rather than silently picking User Bank. - Secrets, private URLs, bearer tokens, cookies, and transient artifact paths should route to
skipor require redaction before retain. - Metadata records provenance; tags control scope and visibility.
- Recalled memory must not be routed back into retain.
Strategy seam
Section titled “Strategy seam”Implemented strategy:
project-global-default: current project/User Bank/both/skip classifier using missions and heuristics. The implementation keepsglobalin type names as a legacy route value.
Future strategies:
dry-run-only: always produces an explainable decision but writes nothing.named-bank: resolves explicit named bank targets once config supports them.identity-aware: includes per-user/per-agent context only after identity source is documented.
The seam should not know Pi provider internals. It should receive normalized routing input from lifecycle/tool code.
Eval fixture taxonomy
Section titled “Eval fixture taxonomy”Routing evals should continue to cover at least:
- durable User Bank preference
- stable identity preference
- cross-project workflow habit
- project architecture fact
- project implementation decision
- project delivery state
- project-scoped user preference
- identity-like fact embedded in project work
- ambiguous project/User Bank content
- secret or credential-like content
- transient screenshot/artifact
- temporary command/test output
Fixtures should assert:
- route
- confidence band or minimum confidence
- matched signal categories
- safety notes where relevant
- write targets in router mode
- no writes in explicit-only mode
Tool and TUI implications
Section titled “Tool and TUI implications”hindsight_route_memory remains the primary dry-run surface for routing decisions. It should show:
- suggested route
- confidence
- target bank roles and IDs
- tags that would be applied
- reason and matched signals
- safety notes
- whether the current mode would write or only preview
A future /hindsight TUI route preview can call the same operation and should avoid duplicating routing logic.
Consequences
Section titled “Consequences”- Safe defaults remain unchanged.
- Future routing work has a stable contract instead of adding ad hoc conditions to lifecycle retain.
- Richer bank topologies remain possible without coupling core to a specific platform identity model.
- More tests are required before enabling any new automatic route.
Follow-up implementation status
Section titled “Follow-up implementation status”Completed:
- #154: Update
hindsight_route_memorypresenter to include target bank roles, tags, safety notes, and explicit write/no-write status. - #155: Expand router eval fixtures with secret/noise/ambiguous confidence cases and safety-note assertions.
- #156: Add a
RoutingStrategytype and adapter boundary separate from current heuristic implementation.
Still future:
- Add a TUI route-preview action that calls the shared routing operation.
- Design named-bank resolver config before supporting per-user/per-agent/shared-bank targets.