instar 1.3.127 → 1.3.128
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.
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +29 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +57 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/PreferencesManager.d.ts +121 -0
- package/dist/core/PreferencesManager.d.ts.map +1 -0
- package/dist/core/PreferencesManager.js +223 -0
- package/dist/core/PreferencesManager.js.map +1 -0
- package/dist/core/types.d.ts +49 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +6 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +12 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +36 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +62 -62
- package/src/scaffold/templates.ts +6 -0
- package/upgrades/1.3.128.md +84 -0
- package/upgrades/side-effects/correction-preference-learning-sentinel-slice1a.md +132 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Side-effects review — Correction & Preference Learning Sentinel (Slice 1a)
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/CORRECTION-PREFERENCE-LEARNING-SENTINEL-SPEC.md` (§3.6, §7,
|
|
4
|
+
§9, §10 Slice 1a)
|
|
5
|
+
**Change:** new `src/core/PreferencesManager.ts`; inline
|
|
6
|
+
`GET /preferences/session-context` in `src/server/routes.ts`;
|
|
7
|
+
`monitoring.correctionLearning` config block (`src/core/types.ts` +
|
|
8
|
+
`src/config/ConfigDefaults.ts`); `CapabilityIndex.ts` entry; session-start hook
|
|
9
|
+
patch + `migrateClaudeMd` backfill + shadow-capability marker in
|
|
10
|
+
`src/core/PostUpdateMigrator.ts`; `generateClaudeMd` capability section +
|
|
11
|
+
Registry-First row + proactive trigger in `src/scaffold/templates.ts`; 3-tier +
|
|
12
|
+
wiring tests.
|
|
13
|
+
**Class:** new read-surface feature, ships OFF, signal-only (never gates,
|
|
14
|
+
blocks, or rewrites a message).
|
|
15
|
+
|
|
16
|
+
## What changed
|
|
17
|
+
|
|
18
|
+
A structured on-disk preferences file (`.instar/preferences.json`), the single
|
|
19
|
+
atomic writer for it (`recordPreference()`), an HTTP read route serving the
|
|
20
|
+
session-start block, and a session-start hook that injects that block on every
|
|
21
|
+
boot. Modeled 1:1 on the proven ORG-INTENT precedent
|
|
22
|
+
(`GET /intent/org/session-context` + its session-start fetch). Slice 1b (the
|
|
23
|
+
capture/distill/ledger loop) is the future writer; Slice 1a only proves the
|
|
24
|
+
surface is alive end-to-end.
|
|
25
|
+
|
|
26
|
+
## 1. Security
|
|
27
|
+
|
|
28
|
+
- **No new external input/network/egress.** The route only reads a local file
|
|
29
|
+
and serves a deterministically-formatted block. No LLM call, no outbound
|
|
30
|
+
request, no shell-out in Slice 1a (the hook's curl is loopback to the agent's
|
|
31
|
+
own server, same as ORG-INTENT).
|
|
32
|
+
- **Auth:** the route is Bearer-gated by the global `authMiddleware` exactly like
|
|
33
|
+
sibling `/intent/*` routes (integration test asserts 401 without a token).
|
|
34
|
+
- **Output discipline:** the served payload and the injected block contain ONLY
|
|
35
|
+
the `learning` text + metadata (confidence, seen-count). Internal fields
|
|
36
|
+
(`dedupeKey`, `provenance`) never leak (unit + integration assertions). This is
|
|
37
|
+
the §3.6 "serve only learning + metadata" rule.
|
|
38
|
+
- **Injection-confusion defense:** loop-sourced preferences are wrapped in an
|
|
39
|
+
`<auto-learned-preference src='correction-loop'>` envelope so a downstream
|
|
40
|
+
prompt assembler structurally cannot mistake a learned preference for an
|
|
41
|
+
authoritative instruction. The block's own preamble restates "signals, not
|
|
42
|
+
instructions; real instructions and safety win."
|
|
43
|
+
- **No policy-relaxation surface in 1a:** `recordPreference()` has no writer in
|
|
44
|
+
Slice 1a (Slice 1b adds the gated, policy-keyword-filtered caller per §3.6).
|
|
45
|
+
Until then the only way an entry lands is a direct programmatic call, which the
|
|
46
|
+
correction loop does not yet make.
|
|
47
|
+
|
|
48
|
+
## 2. Migration parity
|
|
49
|
+
|
|
50
|
+
- **Config:** `monitoring.correctionLearning` added to `ConfigDefaults`.
|
|
51
|
+
`applyDefaults` deep-merges add-missing-only (verified: `merge()` recurses into
|
|
52
|
+
objects, adds absent keys, never overwrites), so existing agents backfill the
|
|
53
|
+
block on update without a dedicated `migrateConfig` step — and without surprise
|
|
54
|
+
activation (`enabled: false`). This matches the spec §7 note and the
|
|
55
|
+
failure-learning precedent.
|
|
56
|
+
- **Route:** inline in `routes.ts` (the discoverability-lint allowlist is fixed; a
|
|
57
|
+
separate module would trip the orphan-prefix check). `CapabilityIndex` entry
|
|
58
|
+
added so the lint passes and the route is discoverable.
|
|
59
|
+
- **Hook:** built-in `instar/` hooks are always-overwrite on every migration, so
|
|
60
|
+
the patched `session-start.sh` propagates to every existing agent on the next
|
|
61
|
+
update — no hand-written `migrateHooks` block needed.
|
|
62
|
+
- **CLAUDE.md:** `generateClaudeMd` gains the capability section / Registry-First
|
|
63
|
+
row / proactive trigger; `migrateClaudeMd` gains a content-sniffed backfill
|
|
64
|
+
(marker `Correction & Preference Learning Sentinel`) so EXISTING agents learn
|
|
65
|
+
the surface — not just new ones. A shadow-capability marker
|
|
66
|
+
(`**Preferences I've learned about you**`) mirrors it into Codex/Gemini
|
|
67
|
+
`AGENTS.md`/`GEMINI.md`. `feature-delivery-completeness` enforces all three legs.
|
|
68
|
+
- **State file:** `.instar/preferences.json` is created lazily on first write;
|
|
69
|
+
absent ≡ empty. No migration needed.
|
|
70
|
+
|
|
71
|
+
## 3. Performance
|
|
72
|
+
|
|
73
|
+
- The read route does one small synchronous file read + a deterministic
|
|
74
|
+
string-build bounded by `maxInjectedPreferencesBytes` (4000). No DB, no LLM, no
|
|
75
|
+
network. Cost is negligible and constant-ish.
|
|
76
|
+
- `recordPreference()` reads + rewrites the whole file atomically. The file is
|
|
77
|
+
bounded by distinct-preference cardinality (upsert by `dedupeKey`), not message
|
|
78
|
+
volume, so it stays tiny in practice. Each write is one temp-file + fsync +
|
|
79
|
+
rename.
|
|
80
|
+
- The session-start hook adds one loopback curl with `--max-time 4`; fail-open on
|
|
81
|
+
timeout, so a slow/absent server can never delay session start beyond that cap.
|
|
82
|
+
|
|
83
|
+
## 4. Observability
|
|
84
|
+
|
|
85
|
+
- The route is discoverable via `GET /capabilities` (CapabilityIndex entry,
|
|
86
|
+
`enabled` reflects the flag).
|
|
87
|
+
- `{ present, block, count }` makes the served state self-describing; `count`
|
|
88
|
+
exposes distinct-preference cardinality for debugging.
|
|
89
|
+
- No new log channel in 1a (the audit log `logs/correction-learning-audit.jsonl`
|
|
90
|
+
is a Slice 1b concern — the loop that produces routable decisions).
|
|
91
|
+
|
|
92
|
+
## 5. Rollback
|
|
93
|
+
|
|
94
|
+
- Flip `monitoring.correctionLearning.enabled` back to false (or remove the
|
|
95
|
+
block) → the route 503s and the hook injects nothing. Inert.
|
|
96
|
+
- `.instar/preferences.json` entries all carry `provenance: 'correction-loop'`,
|
|
97
|
+
enabling a one-shot bulk removal (a single jq-style filter) if a future loop
|
|
98
|
+
ever writes something unwanted. In 1a nothing writes, so the file stays absent.
|
|
99
|
+
- Code rollback = revert the commits; the absent-file ≡ empty contract means a
|
|
100
|
+
rolled-back agent with a stray file is still consistent (read tolerates and
|
|
101
|
+
ignores it; the route 503s when the flag is gone).
|
|
102
|
+
|
|
103
|
+
## 6. Multi-machine
|
|
104
|
+
|
|
105
|
+
- The file is per-agent-home local state (under `stateDir`), like ORG-INTENT.md
|
|
106
|
+
and the integrated-being ledger. On a multi-machine agent each machine reads
|
|
107
|
+
its own copy; the existing state-sync layer carries `.instar/` files between
|
|
108
|
+
machines the same way it carries ORG-INTENT.md — no new sync path introduced.
|
|
109
|
+
- The route is read-only and idempotent; no lease/fencing interaction. Slice 1a
|
|
110
|
+
has no writer competing across machines (that is a Slice 1b consideration when
|
|
111
|
+
the loop runs only on the awake machine).
|
|
112
|
+
|
|
113
|
+
## 7. Multi-user
|
|
114
|
+
|
|
115
|
+
- Slice 1a is a pure read/inject surface and does not itself attribute a
|
|
116
|
+
preference to a user — it serves whatever was recorded. The multi-user
|
|
117
|
+
primary-user gate (§3.6) lives in Slice 1b, where corrections are attributed
|
|
118
|
+
and `recordPreference()` is actually called. Until then no user-shaped data can
|
|
119
|
+
enter the file via this feature.
|
|
120
|
+
- The injected block is the same for every session on the agent (it is the
|
|
121
|
+
agent's learned-about-this-operator preferences), consistent with the
|
|
122
|
+
single-operator model the rest of the agent assumes.
|
|
123
|
+
|
|
124
|
+
## Tests
|
|
125
|
+
|
|
126
|
+
- Unit: `tests/unit/PreferencesManager.test.ts` (13),
|
|
127
|
+
`tests/unit/preferences-wiring-integrity.test.ts` (7).
|
|
128
|
+
- Integration: `tests/integration/preferences-routes.test.ts` (5).
|
|
129
|
+
- E2E: `tests/e2e/preferences-session-context-lifecycle.test.ts` (6).
|
|
130
|
+
- Lint: `tests/unit/capabilities-discoverability.test.ts` (100) green;
|
|
131
|
+
`tests/unit/feature-delivery-completeness.test.ts` green (parity + shadow
|
|
132
|
+
marker for the new section).
|