instar 1.3.479 → 1.3.480

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,95 @@
1
+ # Side-Effects Review — Dev-Agent Dark-Gate Enforcement
2
+
3
+ **Version / slug:** `dev-agent-dark-gate-enforcement`
4
+ **Date:** 2026-06-10
5
+ **Author:** echo (Instar Agent)
6
+ **Spec:** `docs/specs/DEV-AGENT-DARK-GATE-ENFORCEMENT-SPEC.md` (converged 3 rounds, approved)
7
+
8
+ ## Summary of the change
9
+
10
+ Two slices. **Slice A** routes the cartographer *zero-cost read surfaces* through
11
+ the existing `resolveDevAgentGate` so they run LIVE on development agents and DARK
12
+ on the fleet (the doc-tree/navigation read + the deterministic conformance audit),
13
+ and removes the redundant `egressAcknowledged` second gate from the freshness
14
+ sweep (the sweep remains an explicit `enabled:true` opt-in even on dev agents —
15
+ NOT dev-gated — because it is the one ongoing-cost surface). **Slice B** closes the
16
+ lint hole that let cartographer ship dark-for-everyone: every `enabled: false` in
17
+ `ConfigDefaults.ts` must now be DECLARED — either dev-gated (omit `enabled` +
18
+ register) or listed in a new `DARK_GATE_EXCLUSIONS` registry with a closed-enum
19
+ category and a ≥12-char reason. A one-shot, dev-agent-only migration lights up
20
+ existing dev agents on update.
21
+
22
+ **Files changed (source):**
23
+ - `src/config/ConfigDefaults.ts` — OMIT `enabled` from `cartographer` and
24
+ `cartographer.conformanceAudit` (gate decides at runtime); comments updated.
25
+ `freshnessSweep`/`llmEnrichment`/`llmRerank` `enabled:false` left as-is.
26
+ - `src/commands/server.ts` — `cartographerEnabled` now via `resolveDevAgentGate`;
27
+ freshness-sweep start predicate drops the `&& egressAcknowledged` term (now
28
+ `enabled` alone). Off-Claude routing probe + per-pass bounds untouched.
29
+ - `src/server/routes.ts` — conformance route gate `cfg?.enabled !== true` →
30
+ `!resolveDevAgentGate(cfg?.enabled, ctx.config)` (the only cartographer/
31
+ conformance ACCESS gate; the `sweepEnabled` status field at ~L4169 is a response
32
+ field, not a gate, deliberately untouched).
33
+ - `src/core/devGatedFeatures.ts` — required `justification` field on
34
+ `DevGatedFeature` (+ on every existing entry); two new dev-gated entries
35
+ (`cartographer`, `cartographerConformanceAudit`); new `DarkGateCategory`,
36
+ `DarkGateExclusion`, `DARK_GATE_EXCLUSIONS` (all 19 remaining dark defaults
37
+ classified).
38
+ - `src/core/PostUpdateMigrator.ts` — `migrateCartographerDevGate`: one-shot
39
+ (`_instar_migrations` marker), dev-agent-only, strips a default-shaped
40
+ `false` at `cartographer.enabled` + `cartographer.conformanceAudit.enabled`
41
+ ONLY; never touches `freshnessSweep`; records `result.upgraded`.
42
+
43
+ **Files changed (lint/infra):**
44
+ - `scripts/lint-dev-agent-dark-gate.js` — Assertion C (unclassified-dark-default +
45
+ registered-but-hardcoded-false), exclusion quality validation (closed category
46
+ enum + ≥12-char reason), brace-in-string loud-fail guard, literal-only limit
47
+ printed in failure header.
48
+ - `scripts/lib/dark-gate-attribution.js` (NEW) — single path-attribution module
49
+ shared by the lint and the golden-path test (so the canary checks the SAME
50
+ attributor the lint uses).
51
+
52
+ **Files changed (tests):** `tests/unit/lint-dev-agent-dark-gate.test.ts`
53
+ (extended: assertion-C cases, hand-authored golden-path map, brace-in-string,
54
+ destructive-not-gated, exclusion-quality), `tests/unit/PostUpdateMigrator-cartographerDevGate.test.ts`
55
+ (NEW), `tests/integration/conformance-dev-gate-route.test.ts` (NEW),
56
+ `tests/e2e/cartographer-dev-gate-lifecycle.test.ts` (NEW).
57
+
58
+ **Files added (docs):** the spec, its `.eli16.md` companion, and the convergence report.
59
+
60
+ ## Decision-point inventory
61
+
62
+ - **`cartographer.enabled`, `cartographer.conformanceAudit.enabled`** → dev-gate
63
+ (omit + register). Zero egress, zero spend — safe to dogfood live on dev agents.
64
+ - **`cartographer.freshnessSweep.enabled`** → NOT dev-gated; explicit opt-in
65
+ everywhere (DARK_GATE_EXCLUSIONS, category `cost-bearing`). Auto-arming recurring
66
+ third-party spend across the dev fleet is a P19 blast-radius risk.
67
+ - **`egressAcknowledged`** → neutralized as a second gate (privacy framing was
68
+ incoherent: source already egresses to a model every turn). Field retained for
69
+ back-compat; now inert on the sweep. Noted in the upgrade guide.
70
+ - **The other 18 existing `enabled:false` blocks** → classified into
71
+ `DARK_GATE_EXCLUSIONS` (destructive / cost-bearing / structural-stub /
72
+ optional-integration / deliberate-fleet-default). NONE retroactively dev-gated
73
+ in this PR — that is a deliberate, bounded scope. Each observe-only sentinel
74
+ would need its own safety judgment before going live on dev agents; this change
75
+ makes that an explicit, lint-visible decision rather than a silent default.
76
+
77
+ ## 1–7. Analysis
78
+
79
+ - **Behavioral change:** on a `developmentAgent:true` agent, cartographer's
80
+ read-only surfaces resolve LIVE (previously dark for everyone). On the fleet,
81
+ unchanged (still dark). The freshness sweep's activation is UNCHANGED for
82
+ everyone except that it no longer requires the second `egressAcknowledged` flag.
83
+ - **Migration:** existing dev agents have `cartographer.enabled:false` on disk; the
84
+ one-shot migration strips the default-shaped value so the gate decides. Run-once
85
+ marker prevents ever re-stripping an operator's later deliberate `false`. Never
86
+ touches the cost-bearing sweep — no surprise spend on update.
87
+ - **Security/cost:** no new egress path (the sweep was already the only egress, and
88
+ its activation conditions only got simpler, not broader — it still needs explicit
89
+ `enabled:true`). No new spend can be auto-armed. The new lint is deterministic,
90
+ reads one file, no network.
91
+ - **Reversibility:** fully reversible by reverting the commit. The migration is
92
+ additive (deletes a default-shaped key); reverting restores prior behavior on the
93
+ next update for agents that hadn't yet run it.
94
+ - **New failure modes:** none introduced. The lint's brace-in-string guard fails
95
+ LOUD (not silent) if an unhandled case is introduced — a safety improvement.