instar 1.3.4 → 1.3.5

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,102 @@
1
+ # Side-Effects Review — FrameworkIssueLedger (Mentor System §19.1 foundation)
2
+
3
+ **Spec:** `docs/specs/FRAMEWORK-ONBOARDING-MENTOR-SPEC.md` (converged 5 iters, approved by Justin)
4
+ **Change:** New SQLite two-table issue ledger (`framework_issues` + `framework_observations`),
5
+ two read-only HTTP routes (`/framework-issues`, `/framework-issues/playbook`), AgentServer
6
+ startup instantiation, RouteContext wiring, CLAUDE.md template row + migrator section, NEXT.md.
7
+ **Files:** `src/monitoring/FrameworkIssueLedger.ts` (new), `src/server/routes.ts`,
8
+ `src/server/AgentServer.ts`, `src/scaffold/templates.ts`, `src/core/PostUpdateMigrator.ts`,
9
+ `tests/unit/FrameworkIssueLedger.test.ts` (new), `tests/integration/framework-issues-routes.test.ts` (new),
10
+ `tests/e2e/framework-issue-ledger-lifecycle.test.ts` (new), `tests/unit/feature-delivery-completeness.test.ts`,
11
+ `upgrades/NEXT.md`.
12
+
13
+ ## Principle check (Phase 1)
14
+
15
+ Does this involve a decision point that gates info flow / blocks actions / filters messages /
16
+ constrains agent behavior? **No.** The ledger is a data store + read-only routes — it records
17
+ observations (signal) and serves queries. It holds zero blocking authority. The decision-bearing
18
+ parts of the mentor system (two-hats enforcement, assignment admission, graduation authority)
19
+ are §19.3–5 and ship later. This PR is a data-model + observability change → **signal-only**,
20
+ the correct posture per `docs/signal-vs-authority.md`.
21
+
22
+ ## The seven questions
23
+
24
+ 1. **Over-block — what legitimate inputs does this reject that it shouldn't?**
25
+ The routes reject unknown `framework` values (returns empty list, not an error) and invalid
26
+ `bucket`/`status` enums (400). An unknown framework returning empty is intentional (allowlist,
27
+ §17); it could surprise a caller who mistypes, but the response includes `knownFrameworks` so
28
+ the caller can self-correct. No legitimate data is rejected on write — `recordObservation`
29
+ accepts any framework string and creates the issue.
30
+
31
+ 2. **Under-block — what failure modes does this still miss?**
32
+ The ledger does not yet have a *writer* (Stage B auto-capture is §19.2), so today it only
33
+ accepts observations from in-process callers (the e2e test writes directly). There is no public
34
+ write route, so there is no untrusted-write surface to under-block. Secret-scanning of evidence
35
+ is pattern-based (api-key/JWT/Slack/GitHub/PEM shapes) — a novel secret format could slip
36
+ through; mitigated by the hard rule that evidence is an opaque reference, not log content, and
37
+ the length cap. The probable-loop flag is a heuristic (12 obs/hr) — a slow loop under that rate
38
+ won't trip it, but episode-collapsing already bounds recurrence inflation structurally.
39
+
40
+ 3. **Level-of-abstraction fit — right layer? smarter gate exists?**
41
+ Yes. It mirrors the established `TokenLedger` (read-only SQLite observability in
42
+ `src/monitoring/`) and reuses `CommitmentTracker`'s transactional-mutate discipline. It does
43
+ NOT duplicate FrameworkParitySentinel (renderings) — it records *behavior*, and §10 has the
44
+ sentinel feed it as an upstream signal in a later PR. No smarter gate exists for this data.
45
+
46
+ 4. **Signal vs authority compliance.**
47
+ Compliant. The ledger produces/serves signal; it never gates. `recordObservation` writes a
48
+ row; `listIssues`/`playbook` read. No method blocks, throttles, kills, or constrains. All
49
+ authority over what to do with an entry (ship a fix, promote to playbook `extracted`, advance
50
+ graduation) is reserved for the human per spec §6/§8 and lands in later PRs.
51
+
52
+ 5. **Interactions — shadow / double-fire / race with cleanup?**
53
+ - DB isolation: a dedicated `framework-issue-ledger.db` under `server-data/`, separate from
54
+ `token-ledger.db` — no shadowing of TokenLedger or its BurnDetector reads.
55
+ - Concurrency: WAL + `busy_timeout=5000` + a single SQLite transaction per write, with a
56
+ `UNIQUE(issue_id, episode_key)` index as the race guard (a concurrent duplicate episode insert
57
+ loses cleanly and is counted as already-recorded). Retention pruning runs inside the same txn.
58
+ - Startup: instantiated in the same `stateDir` guard block as TokenLedger; its own try/catch
59
+ means a ledger failure can't take down TokenLedger or server start.
60
+
61
+ 6. **External surfaces — visible to other agents/users/systems? timing/runtime deps?**
62
+ Two new read-only HTTP routes behind the standard Bearer middleware (verified by e2e: a
63
+ bearer-less request gets 401). New agents get one Registry-First row in CLAUDE.md; existing
64
+ agents get a migrator section (content-sniffed, idempotent). No Codex/Gemini shadow-marker
65
+ (developer-layer observability, not an end-user capability — tracked as a legacyMigratorSection
66
+ so the parity test stays green). No timing/conversation-state dependence.
67
+
68
+ 7. **Rollback cost — if wrong in production, what's the back-out?**
69
+ Low. The feature is dormant (no writer wired yet) and signal-only. Back-out = revert the PR;
70
+ the `framework-issue-ledger.db` file is harmless read-only observability data that can be left
71
+ on disk or deleted (nothing reads it except these routes). No data migration, no agent-state
72
+ repair. The routes fail-soft to 503 if the ledger is unavailable, so even a construction
73
+ failure degrades cleanly rather than breaking server start.
74
+
75
+ ## Phase 5 — second-pass
76
+
77
+ **Not required.** The Phase-5 trigger list is block/allow decisions, session lifecycle,
78
+ compaction, coherence/idempotency/trust gates, and anything named sentinel/guard/gate/watchdog.
79
+ This change is none of those — it is a read-only observability ledger with no blocking authority.
80
+ The decision-bearing components of the mentor system (which WILL trigger Phase 5) ship in §19.3–5.
81
+ The spec itself already passed a 5-iteration adversarial/security/scalability/integration/lessons
82
+ convergence before this build.
83
+
84
+ ## Testing
85
+
86
+ All three tiers, shipped in this PR (no "routes now, migration later"):
87
+ - Tier 1 (unit): 22 tests — CRUD, dedup false-merge resistance, episode collapsing, materialized
88
+ recurrence, impactScore + decay, regression auto-suggest, enum + SQL-injection-literal guard,
89
+ secret-scan redaction, retention pruning, playbook cross-framework semantics, clampLimit.
90
+ - Tier 2 (integration): 9 tests — routes over the HTTP pipeline (503, 200, limit clamp, framework
91
+ allowlist, invalid-enum 400, playbook).
92
+ - Tier 3 (e2e "feature is alive"): 5 tests — real AgentServer boot, DB auto-creates on production
93
+ init path, routes 200-not-503, written observation surfaces end-to-end, 401 without auth.
94
+ - Full push-config suite (vs JKHeadley/main): 3362 tests green, no regressions.
95
+
96
+ ## Post-push CI fix
97
+
98
+ CI shard 1/4 caught `capabilities-discoverability.test.ts`: every registered route prefix must be
99
+ classified in `src/server/CapabilityIndex.ts` (the test reads routes.ts via regex, not import, so
100
+ vitest's `--changed` graph didn't link it locally). Classified `/framework-issues` as a read-only
101
+ observability capability (mirrors the `tokens` entry, `enabled: !!ctx.frameworkIssueLedger`). No
102
+ behavioral change — surfaces the read-only routes in `/capabilities`. 322 capability tests green.