instar 1.3.477 → 1.3.478

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.
@@ -0,0 +1,81 @@
1
+ # Side-Effects Review — Cartographer Subtree Navigation (spec #5, Tier 2)
2
+
3
+ **Version / slug:** `cartographer-subtree-nav`
4
+ **Date:** `2026-06-10`
5
+ **Author:** `Echo`
6
+ **Spec:** `docs/specs/CARTOGRAPHER-SUBTREE-NAV.md` (converged 1 round + a focused buildability review, approved)
7
+ **Second-pass reviewer:** `not required — convergence pinned the collapse rule, the two-phase scoring, batched fresh, and the migrator-only classification; this review covers the seven dimensions on the as-built deterministic code`
8
+
9
+ ## Summary of the change
10
+
11
+ The capstone of cartographer-conformance: a **deterministic recursive navigator** over
12
+ the doc-tree. Given a query, it walks the tree's summaries top-down (a bounded frontier,
13
+ not all N nodes), scores nodes by relevance, and returns the **minimal relevant
14
+ subtree** — the paths a sub-agent should be scoped to instead of the whole repo.
15
+ `GET /cartographer/navigate`. Observe-only, deterministic-first; an optional LLM re-rank
16
+ is a dark structural stub. Dark behind `cartographer.enabled`.
17
+
18
+ ## Files touched
19
+
20
+ - NEW `src/core/CartographerNavigator.ts` (scoring + the bounded recursive walk + collapse + sanitization).
21
+ - MODIFIED (additive): `src/core/CartographerTree.ts` (one public `currentOidMap()` accessor exposing the existing batched `currentOids()` — for batched `fresh`), `src/config/ConfigDefaults.ts` (`cartographer.subtreeNav`), `src/server/routes.ts` (the navigate route), `src/server/CapabilityIndex.ts`, `src/core/PostUpdateMigrator.ts` (CLAUDE.md section), `tests/unit/feature-delivery-completeness.test.ts` (legacy-migrator allowlist entry).
22
+ - TESTS: 32 across 3 tiers.
23
+
24
+ ## 1. Over-block
25
+
26
+ The navigator blocks nothing (observe-only — it returns a suggestion). No gate.
27
+
28
+ ## 2. Under-block / correctness
29
+
30
+ A bounded walk could MISS a relevant deep node if an intermediate dir's provisional
31
+ score gates it out. The build resolved this (a documented decision): the provisional
32
+ dir score peeks at descendant path BASENAMES to a bounded depth (PEEK_DEPTH=2, path-only,
33
+ non-recursive in score — no deadlock), so the spec's own example ("relevant code under
34
+ `src/messaging/`") and the "never-swept tree navigates on path signal" requirement hold.
35
+ A dir never enters `relevantPaths` on a single descendant's strength — only via the
36
+ collapse rule (≥0.6 of VISITED children relevant). `summaryCoverage` is reported so a
37
+ caller knows how much ranking was summary-informed vs path-only (honest on a never-swept
38
+ tree).
39
+
40
+ ## 3. Level-of-abstraction fit
41
+
42
+ Pure scorer + pure walk in `CartographerNavigator`; the route is a thin read surface;
43
+ the tree exposes one new read accessor. No layer reaches across; the navigator takes the
44
+ tree + query and returns a manifest. Fully unit-testable on a fixture tree.
45
+
46
+ ## 4. Determinism / cost (the cartographer-project footgun this avoids)
47
+
48
+ The shipped value is 100% deterministic — local index/summary reads only; zero token
49
+ cost, zero egress, byte-identical run-to-run. The bounded frontier (top-`branchingFactor`
50
+ children to `maxDepth`, capped by `maxNodesVisited`/`maxResults`) means cost is
51
+ O(frontier), not O(tree); `fresh` is one batched `git ls-tree`, not per-node. The LLM
52
+ re-rank ships OFF (Signal vs. Authority — the deterministic score is the authority).
53
+
54
+ ## 5. Security / data-egress
55
+
56
+ - **Zero egress** in the default config (deterministic core). The optional LLM re-rank
57
+ inherits spec #2's posture (off-Claude probe, separate egress-ack) and ships OFF.
58
+ - **Summaries are untrusted on output (the hard safety contract):** every emitted summary
59
+ passes `neutralizeInstructionShapedContent` then `delimitUntrusted` — so a summary that
60
+ smuggled "ignore your instructions" reaches the downstream sub-agent as quoted,
61
+ declawed data, never an instruction. (A Tier-1 test asserts an instruction-shaped
62
+ summary is emitted as `[neutralized: …]`.) The route consumes NO path input (paths are
63
+ produced), so there is no traversal surface; `query` length + numeric bounds are
64
+ validated (400 on violation).
65
+
66
+ ## 6. Failure modes / load
67
+
68
+ No poller, no background work — the navigate is a synchronous read per request, bounded.
69
+ Empty query short-circuits. A never-swept tree degrades gracefully to path navigation.
70
+ No load impact.
71
+
72
+ ## 7. Migration / compatibility (Migration Parity)
73
+
74
+ `cartographer.subtreeNav` nests under `cartographer` (deep-merge backfill — no
75
+ migrateConfig). The CLAUDE.md section ships via `migrateClaudeMd` (own marker 'Scope a
76
+ sub-agent to a subtree', idempotent) and is registered in the feature-completeness test's
77
+ `legacyMigratorSections` allowlist — EXACTLY as specs #1/#2/#3's cartographer sections
78
+ (migrator-only, not `generateClaudeMd`/shadow; verified at convergence). The route is in
79
+ CapabilityIndex. The `currentOidMap()` addition to CartographerTree is purely additive
80
+ (exposes an existing private read). Rollback: disabling `cartographer.enabled` 503s the
81
+ route. No migration reversal.