instar 1.3.127 → 1.3.129

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.
Files changed (34) hide show
  1. package/.claude/skills/autonomous/hooks/autonomous-stop-hook.sh +36 -0
  2. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  3. package/dist/config/ConfigDefaults.js +29 -0
  4. package/dist/config/ConfigDefaults.js.map +1 -1
  5. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  6. package/dist/core/PostUpdateMigrator.js +64 -5
  7. package/dist/core/PostUpdateMigrator.js.map +1 -1
  8. package/dist/core/PreferencesManager.d.ts +121 -0
  9. package/dist/core/PreferencesManager.d.ts.map +1 -0
  10. package/dist/core/PreferencesManager.js +223 -0
  11. package/dist/core/PreferencesManager.js.map +1 -0
  12. package/dist/core/installCodexHooks.d.ts +7 -0
  13. package/dist/core/installCodexHooks.d.ts.map +1 -1
  14. package/dist/core/installCodexHooks.js +30 -2
  15. package/dist/core/installCodexHooks.js.map +1 -1
  16. package/dist/core/types.d.ts +62 -0
  17. package/dist/core/types.d.ts.map +1 -1
  18. package/dist/core/types.js.map +1 -1
  19. package/dist/scaffold/templates.d.ts.map +1 -1
  20. package/dist/scaffold/templates.js +6 -0
  21. package/dist/scaffold/templates.js.map +1 -1
  22. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  23. package/dist/server/CapabilityIndex.js +12 -0
  24. package/dist/server/CapabilityIndex.js.map +1 -1
  25. package/dist/server/routes.d.ts.map +1 -1
  26. package/dist/server/routes.js +36 -0
  27. package/dist/server/routes.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/data/builtin-manifest.json +62 -62
  30. package/src/scaffold/templates.ts +6 -0
  31. package/upgrades/1.3.128.md +84 -0
  32. package/upgrades/1.3.129.md +55 -0
  33. package/upgrades/side-effects/codex-autonomous-loop-driver.md +91 -0
  34. package/upgrades/side-effects/correction-preference-learning-sentinel-slice1a.md +132 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * PreferencesManager — the structured on-disk substrate for auto-learned user
3
+ * preferences (Correction & Preference Learning Sentinel, Slice 1a).
4
+ *
5
+ * Modeled directly on the ORG-INTENT precedent (`OrgIntentManager` +
6
+ * `formatOrgIntentForSessionStart` + `GET /intent/org/session-context` +
7
+ * the session-start hook fetch). Where ORG-INTENT is a human-authored markdown
8
+ * contract, this file is a machine-written JSON store of preferences the
9
+ * correction loop has learned about THIS user.
10
+ *
11
+ * Design constraints (spec §3.6 / §10 Slice 1a):
12
+ * - `recordPreference()` is the ONLY writer to `.instar/preferences.json`.
13
+ * - Writes are atomic (temp file + rename) and schema-versioned.
14
+ * - Upsert keyed on `dedupeKey` — a recurring learning collapses to ONE entry
15
+ * (its `dedupeCount` increments, `recordedAt` refreshes, `confidence` takes
16
+ * the max of old/new), never a growing pile of duplicates.
17
+ * - Absent file ≡ no preferences (never throws; reads return an empty store).
18
+ * - The session-start block is bounded by `maxInjectedPreferencesBytes` and
19
+ * priority-ordered by recency × confidence × dedupeCount.
20
+ *
21
+ * SIGNAL-ONLY: this surface NEVER blocks or rewrites an outbound message. It
22
+ * only stores preferences, serves them, and the session-start hook injects them
23
+ * so the agent always SEES them. There is no enforcement gate. (The blocking
24
+ * idea was explicitly rejected by the user — see spec frontmatter.)
25
+ */
26
+ /** Current on-disk schema version. Bump only with a paired migration. */
27
+ export declare const PREFERENCES_SCHEMA_VERSION = 1;
28
+ /** Provenance of a preference entry. Slice 1a only ever writes 'correction-loop'. */
29
+ export type PreferenceProvenance = 'correction-loop';
30
+ /** A single learned preference, as persisted in `.instar/preferences.json`. */
31
+ export interface PreferenceEntry {
32
+ /** The distilled, scrubbed lesson — e.g. "Lead with the one action, no preamble." */
33
+ learning: string;
34
+ /** Where this came from. Slice 1a: always 'correction-loop'. */
35
+ provenance: PreferenceProvenance;
36
+ /** Stable key the loop upserts on (kind:normalizedLearningHash). */
37
+ dedupeKey: string;
38
+ /** ISO timestamp of the most recent observation of this preference. */
39
+ recordedAt: string;
40
+ /** Loop-assigned confidence in [0,1]; advisory ordering weight. */
41
+ confidence: number;
42
+ /** How many distinct observations have collapsed into this entry (≥1). */
43
+ dedupeCount: number;
44
+ }
45
+ /** The full on-disk store shape. */
46
+ export interface PreferencesStore {
47
+ schemaVersion: number;
48
+ preferences: PreferenceEntry[];
49
+ }
50
+ /** Input payload for `recordPreference()`. */
51
+ export interface RecordPreferencePayload {
52
+ learning: string;
53
+ dedupeKey: string;
54
+ /** Defaults to 0.5 when omitted; clamped to [0,1]. */
55
+ confidence?: number;
56
+ /** Defaults to 'correction-loop'. */
57
+ provenance?: PreferenceProvenance;
58
+ /** Defaults to now (ISO). Injectable for deterministic tests. */
59
+ recordedAt?: string;
60
+ }
61
+ /** Options for `recordPreference()`. */
62
+ export interface RecordPreferenceOptions {
63
+ /**
64
+ * Priority ordering for the injected block. Mirrors the spec's
65
+ * `preferencesInjectionPriority` config string. Slice 1a supports the single
66
+ * documented form; unknown strings fall back to it.
67
+ */
68
+ injectionPriority?: string;
69
+ }
70
+ /**
71
+ * Render the active preferences into a session-start text block, bounded by
72
+ * `maxBytes` and priority-ordered. Returns the block string (may be empty).
73
+ *
74
+ * Mirrors `formatOrgIntentForSessionStart` — deterministic, no LLM, safe to
75
+ * inject directly. Each preference is wrapped at the section level inside an
76
+ * `<auto-learned-preference src='correction-loop'>` envelope so downstream
77
+ * prompt assemblers structurally cannot mistake a learned preference for an
78
+ * authoritative instruction (spec §3.6).
79
+ */
80
+ export declare function formatPreferencesForSessionStart(store: PreferencesStore, maxBytes?: number): string;
81
+ export declare class PreferencesManager {
82
+ private stateDir;
83
+ private preferencesPath;
84
+ constructor(stateDir: string);
85
+ /** Absolute path to the backing file (for tests / observability). */
86
+ getPath(): string;
87
+ /** Whether the backing file exists on disk. */
88
+ exists(): boolean;
89
+ /**
90
+ * Read the store. Absent file ≡ empty store (never throws). A malformed or
91
+ * unexpected-shape file is also treated as empty — the loop is signal-only,
92
+ * so a corrupt read should never crash a session start.
93
+ */
94
+ read(): PreferencesStore;
95
+ /**
96
+ * recordPreference — the ONLY writer to `.instar/preferences.json`.
97
+ *
98
+ * Upserts the payload keyed on `dedupeKey`:
99
+ * - New key → appended as a fresh entry with `dedupeCount: 1`.
100
+ * - Existing key → `learning` refreshed, `recordedAt` advanced,
101
+ * `confidence` raised to max(old, new), `dedupeCount` incremented.
102
+ *
103
+ * Atomic: writes a temp file then renames over the target so a concurrent
104
+ * reader never observes a partial file. Returns the entry as persisted.
105
+ */
106
+ recordPreference(payload: RecordPreferencePayload, _opts?: RecordPreferenceOptions): PreferenceEntry;
107
+ /**
108
+ * Build the session-context payload served by `GET /preferences/session-context`.
109
+ * Serves ONLY the `learning` text + metadata via the formatted block — never
110
+ * any raw extras. `present` is true iff at least one preference would be
111
+ * injected into the (bounded) block.
112
+ */
113
+ sessionContext(maxBytes?: number): {
114
+ present: boolean;
115
+ block: string;
116
+ count: number;
117
+ };
118
+ /** Atomic write: temp file + fsync + rename. */
119
+ private writeAtomic;
120
+ }
121
+ //# sourceMappingURL=PreferencesManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferencesManager.d.ts","sourceRoot":"","sources":["../../src/core/PreferencesManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH,yEAAyE;AACzE,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AAErD,+EAA+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,UAAU,EAAE,oBAAoB,CAAC;IACjC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,eAAe,EAAE,CAAC;CAChC;AAED,8CAA8C;AAC9C,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AA6BD;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,gBAAgB,EACvB,QAAQ,SAAO,GACd,MAAM,CAmBR;AAID,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,eAAe,CAAS;gBAEZ,QAAQ,EAAE,MAAM;IAIpC,qEAAqE;IACrE,OAAO,IAAI,MAAM;IAIjB,+CAA+C;IAC/C,MAAM,IAAI,OAAO;IAIjB;;;;OAIG;IACH,IAAI,IAAI,gBAAgB;IAqCxB;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,EAAE,KAAK,GAAE,uBAA4B,GAAG,eAAe;IAuCxG;;;;;OAKG;IACH,cAAc,CAAC,QAAQ,SAAO,GAAG;QAC/B,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACf;IAUD,gDAAgD;IAChD,OAAO,CAAC,WAAW;CAcpB"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * PreferencesManager — the structured on-disk substrate for auto-learned user
3
+ * preferences (Correction & Preference Learning Sentinel, Slice 1a).
4
+ *
5
+ * Modeled directly on the ORG-INTENT precedent (`OrgIntentManager` +
6
+ * `formatOrgIntentForSessionStart` + `GET /intent/org/session-context` +
7
+ * the session-start hook fetch). Where ORG-INTENT is a human-authored markdown
8
+ * contract, this file is a machine-written JSON store of preferences the
9
+ * correction loop has learned about THIS user.
10
+ *
11
+ * Design constraints (spec §3.6 / §10 Slice 1a):
12
+ * - `recordPreference()` is the ONLY writer to `.instar/preferences.json`.
13
+ * - Writes are atomic (temp file + rename) and schema-versioned.
14
+ * - Upsert keyed on `dedupeKey` — a recurring learning collapses to ONE entry
15
+ * (its `dedupeCount` increments, `recordedAt` refreshes, `confidence` takes
16
+ * the max of old/new), never a growing pile of duplicates.
17
+ * - Absent file ≡ no preferences (never throws; reads return an empty store).
18
+ * - The session-start block is bounded by `maxInjectedPreferencesBytes` and
19
+ * priority-ordered by recency × confidence × dedupeCount.
20
+ *
21
+ * SIGNAL-ONLY: this surface NEVER blocks or rewrites an outbound message. It
22
+ * only stores preferences, serves them, and the session-start hook injects them
23
+ * so the agent always SEES them. There is no enforcement gate. (The blocking
24
+ * idea was explicitly rejected by the user — see spec frontmatter.)
25
+ */
26
+ import fs from 'node:fs';
27
+ import path from 'node:path';
28
+ // ── Types ────────────────────────────────────────────────────────────
29
+ /** Current on-disk schema version. Bump only with a paired migration. */
30
+ export const PREFERENCES_SCHEMA_VERSION = 1;
31
+ // ── Helpers ──────────────────────────────────────────────────────────
32
+ const EMPTY_STORE = { schemaVersion: PREFERENCES_SCHEMA_VERSION, preferences: [] };
33
+ function clampConfidence(value) {
34
+ if (typeof value !== 'number' || Number.isNaN(value))
35
+ return 0.5;
36
+ if (value < 0)
37
+ return 0;
38
+ if (value > 1)
39
+ return 1;
40
+ return value;
41
+ }
42
+ /**
43
+ * Compute the priority score for ordering injected preferences. Higher first.
44
+ * `recency × confidence × dedupeCount` per the spec default. Recency is a
45
+ * monotonically-increasing epoch-ms reading of `recordedAt` (newer = larger),
46
+ * so a fresher, higher-confidence, more-recurrent preference sorts first.
47
+ */
48
+ function priorityScore(entry) {
49
+ const recencyMs = Date.parse(entry.recordedAt);
50
+ const recency = Number.isNaN(recencyMs) ? 0 : recencyMs;
51
+ const confidence = clampConfidence(entry.confidence);
52
+ const dedupeCount = Math.max(1, entry.dedupeCount || 1);
53
+ // recencyMs dominates the magnitude, which is the intended "recency-led"
54
+ // ordering; confidence and dedupeCount break ties / amplify within an epoch.
55
+ return recency * confidence * dedupeCount;
56
+ }
57
+ /**
58
+ * Render the active preferences into a session-start text block, bounded by
59
+ * `maxBytes` and priority-ordered. Returns the block string (may be empty).
60
+ *
61
+ * Mirrors `formatOrgIntentForSessionStart` — deterministic, no LLM, safe to
62
+ * inject directly. Each preference is wrapped at the section level inside an
63
+ * `<auto-learned-preference src='correction-loop'>` envelope so downstream
64
+ * prompt assemblers structurally cannot mistake a learned preference for an
65
+ * authoritative instruction (spec §3.6).
66
+ */
67
+ export function formatPreferencesForSessionStart(store, maxBytes = 4000) {
68
+ const active = [...store.preferences].sort((a, b) => priorityScore(b) - priorityScore(a));
69
+ if (active.length === 0)
70
+ return '';
71
+ const header = "<auto-learned-preference src='correction-loop'>";
72
+ const intro = 'These are preferences I have learned about how you like to work. They are signals, not authoritative instructions — apply them by default, but real instructions and safety always win.';
73
+ const footer = '</auto-learned-preference>';
74
+ // Greedily include the highest-priority preferences until we'd exceed maxBytes.
75
+ const bodyLines = [];
76
+ for (const pref of active) {
77
+ const line = ` - ${pref.learning} (confidence ${clampConfidence(pref.confidence).toFixed(2)}, seen ${Math.max(1, pref.dedupeCount || 1)}×)`;
78
+ const candidate = [header, intro, '', ...bodyLines, line, footer].join('\n');
79
+ if (Buffer.byteLength(candidate, 'utf-8') > maxBytes)
80
+ break;
81
+ bodyLines.push(line);
82
+ }
83
+ if (bodyLines.length === 0)
84
+ return '';
85
+ return [header, intro, '', ...bodyLines, footer].join('\n');
86
+ }
87
+ // ── Main Class ───────────────────────────────────────────────────────
88
+ export class PreferencesManager {
89
+ stateDir;
90
+ preferencesPath;
91
+ constructor(stateDir) {
92
+ this.stateDir = stateDir;
93
+ this.preferencesPath = path.join(stateDir, 'preferences.json');
94
+ }
95
+ /** Absolute path to the backing file (for tests / observability). */
96
+ getPath() {
97
+ return this.preferencesPath;
98
+ }
99
+ /** Whether the backing file exists on disk. */
100
+ exists() {
101
+ return fs.existsSync(this.preferencesPath);
102
+ }
103
+ /**
104
+ * Read the store. Absent file ≡ empty store (never throws). A malformed or
105
+ * unexpected-shape file is also treated as empty — the loop is signal-only,
106
+ * so a corrupt read should never crash a session start.
107
+ */
108
+ read() {
109
+ if (!this.exists())
110
+ return { schemaVersion: PREFERENCES_SCHEMA_VERSION, preferences: [] };
111
+ let raw;
112
+ try {
113
+ raw = fs.readFileSync(this.preferencesPath, 'utf-8');
114
+ }
115
+ catch {
116
+ // @silent-fallback-ok — unreadable preferences file ≡ no preferences
117
+ return { schemaVersion: PREFERENCES_SCHEMA_VERSION, preferences: [] };
118
+ }
119
+ let parsed;
120
+ try {
121
+ parsed = JSON.parse(raw);
122
+ }
123
+ catch {
124
+ // @silent-fallback-ok — malformed preferences file ≡ no preferences
125
+ return { schemaVersion: PREFERENCES_SCHEMA_VERSION, preferences: [] };
126
+ }
127
+ if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.preferences)) {
128
+ return { schemaVersion: PREFERENCES_SCHEMA_VERSION, preferences: [] };
129
+ }
130
+ const store = parsed;
131
+ const preferences = store.preferences.filter((p) => !!p && typeof p.learning === 'string' && typeof p.dedupeKey === 'string').map((p) => ({
132
+ learning: p.learning,
133
+ provenance: (p.provenance ?? 'correction-loop'),
134
+ dedupeKey: p.dedupeKey,
135
+ recordedAt: typeof p.recordedAt === 'string' ? p.recordedAt : new Date(0).toISOString(),
136
+ confidence: clampConfidence(p.confidence),
137
+ dedupeCount: Math.max(1, Math.floor(p.dedupeCount) || 1),
138
+ }));
139
+ return {
140
+ schemaVersion: typeof store.schemaVersion === 'number' ? store.schemaVersion : PREFERENCES_SCHEMA_VERSION,
141
+ preferences,
142
+ };
143
+ }
144
+ /**
145
+ * recordPreference — the ONLY writer to `.instar/preferences.json`.
146
+ *
147
+ * Upserts the payload keyed on `dedupeKey`:
148
+ * - New key → appended as a fresh entry with `dedupeCount: 1`.
149
+ * - Existing key → `learning` refreshed, `recordedAt` advanced,
150
+ * `confidence` raised to max(old, new), `dedupeCount` incremented.
151
+ *
152
+ * Atomic: writes a temp file then renames over the target so a concurrent
153
+ * reader never observes a partial file. Returns the entry as persisted.
154
+ */
155
+ recordPreference(payload, _opts = {}) {
156
+ if (!payload || typeof payload.learning !== 'string' || !payload.learning.trim()) {
157
+ throw new Error('recordPreference: `learning` is required and must be a non-empty string');
158
+ }
159
+ if (typeof payload.dedupeKey !== 'string' || !payload.dedupeKey.trim()) {
160
+ throw new Error('recordPreference: `dedupeKey` is required and must be a non-empty string');
161
+ }
162
+ const store = this.read();
163
+ const now = payload.recordedAt ?? new Date().toISOString();
164
+ const confidence = clampConfidence(payload.confidence);
165
+ const provenance = payload.provenance ?? 'correction-loop';
166
+ const existing = store.preferences.find((p) => p.dedupeKey === payload.dedupeKey);
167
+ let result;
168
+ if (existing) {
169
+ existing.learning = payload.learning.trim();
170
+ existing.recordedAt = now;
171
+ existing.confidence = Math.max(clampConfidence(existing.confidence), confidence);
172
+ existing.dedupeCount = Math.max(1, existing.dedupeCount || 1) + 1;
173
+ existing.provenance = provenance;
174
+ result = existing;
175
+ }
176
+ else {
177
+ result = {
178
+ learning: payload.learning.trim(),
179
+ provenance,
180
+ dedupeKey: payload.dedupeKey,
181
+ recordedAt: now,
182
+ confidence,
183
+ dedupeCount: 1,
184
+ };
185
+ store.preferences.push(result);
186
+ }
187
+ store.schemaVersion = PREFERENCES_SCHEMA_VERSION;
188
+ this.writeAtomic(store);
189
+ return result;
190
+ }
191
+ /**
192
+ * Build the session-context payload served by `GET /preferences/session-context`.
193
+ * Serves ONLY the `learning` text + metadata via the formatted block — never
194
+ * any raw extras. `present` is true iff at least one preference would be
195
+ * injected into the (bounded) block.
196
+ */
197
+ sessionContext(maxBytes = 4000) {
198
+ const store = this.read();
199
+ const block = formatPreferencesForSessionStart(store, maxBytes);
200
+ return {
201
+ present: block.length > 0,
202
+ block,
203
+ count: store.preferences.length,
204
+ };
205
+ }
206
+ /** Atomic write: temp file + fsync + rename. */
207
+ writeAtomic(store) {
208
+ const dir = path.dirname(this.preferencesPath);
209
+ fs.mkdirSync(dir, { recursive: true });
210
+ const tmp = `${this.preferencesPath}.tmp.${process.pid}.${Date.now()}`;
211
+ const data = JSON.stringify(store, null, 2);
212
+ const fd = fs.openSync(tmp, 'w');
213
+ try {
214
+ fs.writeSync(fd, data);
215
+ fs.fsyncSync(fd);
216
+ }
217
+ finally {
218
+ fs.closeSync(fd);
219
+ }
220
+ fs.renameSync(tmp, this.preferencesPath);
221
+ }
222
+ }
223
+ //# sourceMappingURL=PreferencesManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferencesManager.js","sourceRoot":"","sources":["../../src/core/PreferencesManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,wEAAwE;AAExE,yEAAyE;AACzE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAiD5C,wEAAwE;AAExE,MAAM,WAAW,GAAqB,EAAE,aAAa,EAAE,0BAA0B,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAErG,SAAS,eAAe,CAAC,KAAyB;IAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACjE,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CAAC,KAAsB;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxD,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IACxD,yEAAyE;IACzE,6EAA6E;IAC7E,OAAO,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAC5C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gCAAgC,CAC9C,KAAuB,EACvB,QAAQ,GAAG,IAAI;IAEf,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,MAAM,GAAG,iDAAiD,CAAC;IACjE,MAAM,KAAK,GAAG,yLAAyL,CAAC;IACxM,MAAM,MAAM,GAAG,4BAA4B,CAAC;IAE5C,gFAAgF;IAChF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,QAAQ,gBAAgB,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC;QAC7I,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,QAAQ;YAAE,MAAM;QAC5D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,wEAAwE;AAExE,MAAM,OAAO,kBAAkB;IAGT;IAFZ,eAAe,CAAS;IAEhC,YAAoB,QAAgB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;QAClC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACjE,CAAC;IAED,qEAAqE;IACrE,OAAO;QACL,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,+CAA+C;IAC/C,MAAM;QACJ,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QAC1F,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAE,MAA2B,CAAC,WAAW,CAAC,EAAE,CAAC;YACtG,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACxE,CAAC;QACD,MAAM,KAAK,GAAG,MAA0B,CAAC;QACzC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAwB,EAAE,CAC1B,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAC3E,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,iBAAiB,CAAyB;YACvE,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YACvF,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;YACzC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;SACzD,CAAC,CAAC,CAAC;QACJ,OAAO;YACL,aAAa,EAAE,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,0BAA0B;YACzG,WAAW;SACZ,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,OAAgC,EAAE,QAAiC,EAAE;QACpF,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YACjF,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,UAAU,GAAyB,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC;QAEjF,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;QAClF,IAAI,MAAuB,CAAC;QAC5B,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC5C,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC;YAC1B,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;YACjF,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAClE,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;YACjC,MAAM,GAAG,QAAQ,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG;gBACP,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;gBACjC,UAAU;gBACV,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,UAAU,EAAE,GAAG;gBACf,UAAU;gBACV,WAAW,EAAE,CAAC;aACf,CAAC;YACF,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,KAAK,CAAC,aAAa,GAAG,0BAA0B,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,QAAQ,GAAG,IAAI;QAK5B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,gCAAgC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAChE,OAAO;YACL,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC;YACzB,KAAK;YACL,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM;SAChC,CAAC;IACJ,CAAC;IAED,gDAAgD;IACxC,WAAW,CAAC,KAAuB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC/C,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,eAAe,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACvE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACvB,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -32,6 +32,13 @@
32
32
  */
33
33
  /** Marker that identifies an instar-owned hook command (for merge-safe replace). */
34
34
  export declare const INSTAR_HOOK_PATH_MARKER = ".instar/hooks/instar/";
35
+ /**
36
+ * The autonomous-loop driver hook lives in the autonomous skill, not under
37
+ * `.instar/hooks/instar/`, so it needs its own ownership marker — used both to build
38
+ * its command path and to let groupIsInstarOwned() recognize (and replace, never
39
+ * duplicate) the autonomous Stop group on every re-install.
40
+ */
41
+ export declare const CODEX_AUTONOMOUS_HOOK_MARKER = ".claude/skills/autonomous/hooks/autonomous-stop-hook.sh";
35
42
  interface CodexHookHandler {
36
43
  type: 'command';
37
44
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"installCodexHooks.d.ts","sourceRoot":"","sources":["../../src/core/installCodexHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D,UAAU,gBAAgB;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAMD,2FAA2F;AAC3F,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAyDlC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAwB5D"}
1
+ {"version":3,"file":"installCodexHooks.d.ts","sourceRoot":"","sources":["../../src/core/installCodexHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,4DAA4D,CAAC;AAEtG,UAAU,gBAAgB;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B;AAMD,2FAA2F;AAC3F,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CA4ElC;AAWD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAwB5D"}
@@ -34,6 +34,13 @@ import fs from 'node:fs';
34
34
  import path from 'node:path';
35
35
  /** Marker that identifies an instar-owned hook command (for merge-safe replace). */
36
36
  export const INSTAR_HOOK_PATH_MARKER = '.instar/hooks/instar/';
37
+ /**
38
+ * The autonomous-loop driver hook lives in the autonomous skill, not under
39
+ * `.instar/hooks/instar/`, so it needs its own ownership marker — used both to build
40
+ * its command path and to let groupIsInstarOwned() recognize (and replace, never
41
+ * duplicate) the autonomous Stop group on every re-install.
42
+ */
43
+ export const CODEX_AUTONOMOUS_HOOK_MARKER = '.claude/skills/autonomous/hooks/autonomous-stop-hook.sh';
37
44
  /** Build the instar-owned hook groups for each Codex event, with absolute script paths. */
38
45
  export function buildInstarCodexHookGroups(projectDir) {
39
46
  const node = (script) => ({
@@ -46,6 +53,15 @@ export function buildInstarCodexHookGroups(projectDir) {
46
53
  command: `bash ${path.join(projectDir, INSTAR_HOOK_PATH_MARKER, script)}`,
47
54
  timeout: 5000,
48
55
  });
56
+ // The autonomous-loop driver lives in the autonomous SKILL (not .instar/hooks/instar),
57
+ // so it has its own path constant. `--codex` tells the shared hook it was invoked from
58
+ // codex (vs Claude's settings.json registration) so it can self-gate on the
59
+ // autonomousSessions.codexLoopDriver flag (DARK by default → exits immediately).
60
+ const autonomousLoopHook = () => ({
61
+ type: 'command',
62
+ command: `bash ${path.join(projectDir, CODEX_AUTONOMOUS_HOOK_MARKER)} --codex`,
63
+ timeout: 10000,
64
+ });
49
65
  return {
50
66
  // Pre-action gate. matcher '.*' = all tool calls (Codex treats the matcher as
51
67
  // a regex against the tool name; a bare '*' is an invalid quantifier that
@@ -80,8 +96,18 @@ export function buildInstarCodexHookGroups(projectDir) {
80
96
  // semantics as Claude, NOT a hard termination. scope-coherence defaults to
81
97
  // `approve` and self-throttles (depth threshold + 30-min cooldown), so it
82
98
  // can't loop an autonomous Codex run.
99
+ // End-of-turn chain: the standing review trio, then the autonomous-loop driver as
100
+ // the LAST hook IN THE SAME group (slot stop:0:4) — NOT a separate group. A separate
101
+ // group would emit a stop:1:0 arm slot that codex may never render/trust, which would
102
+ // permanently break armCodexHooks's idempotency (recurring codex-TUI arm spawns on
103
+ // every update, even while the driver is dark). Keeping it in group 0 means it's
104
+ // armed/trusted/fired alongside the trio it already runs. The driver self-gates: with
105
+ // codexLoopDriver disabled (default) it exits immediately, so it's a no-op until the
106
+ // flag is flipped on. (Within-group block precedence vs the trio is verified live
107
+ // before enabling — see the spec's Phase 5; worst case the session still continues
108
+ // via the unjustified-stop router, never strands.)
83
109
  Stop: [
84
- { matcher: '', hooks: [node('stop-gate-router.js'), { ...node('response-review.js'), timeout: 10000 }, node('claim-intercept-response.js'), node('scope-coherence-checkpoint.js')] },
110
+ { matcher: '', hooks: [node('stop-gate-router.js'), { ...node('response-review.js'), timeout: 10000 }, node('claim-intercept-response.js'), node('scope-coherence-checkpoint.js'), autonomousLoopHook()] },
85
111
  ],
86
112
  // Identity/context injection.
87
113
  SessionStart: [
@@ -93,7 +119,9 @@ export function buildInstarCodexHookGroups(projectDir) {
93
119
  };
94
120
  }
95
121
  function groupIsInstarOwned(group) {
96
- return (group.hooks ?? []).some((h) => typeof h.command === 'string' && h.command.includes(INSTAR_HOOK_PATH_MARKER));
122
+ return (group.hooks ?? []).some((h) => typeof h.command === 'string' &&
123
+ (h.command.includes(INSTAR_HOOK_PATH_MARKER) ||
124
+ h.command.includes(CODEX_AUTONOMOUS_HOOK_MARKER)));
97
125
  }
98
126
  /**
99
127
  * Write/merge instar gate hooks into `<projectDir>/.codex/hooks.json`.
@@ -1 +1 @@
1
- {"version":3,"file":"installCodexHooks.js","sourceRoot":"","sources":["../../src/core/installCodexHooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"installCodexHooks.js","sourceRoot":"","sources":["../../src/core/installCodexHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,oFAAoF;AACpF,MAAM,CAAC,MAAM,uBAAuB,GAAG,uBAAuB,CAAC;AAC/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,yDAAyD,CAAC;AAgBtG,2FAA2F;AAC3F,MAAM,UAAU,0BAA0B,CACxC,UAAkB;IAElB,MAAM,IAAI,GAAG,CAAC,MAAc,EAAoB,EAAE,CAAC,CAAC;QAClD,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,uBAAuB,EAAE,MAAM,CAAC,EAAE;QACzE,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,CAAC,MAAc,EAAoB,EAAE,CAAC,CAAC;QAChD,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,uBAAuB,EAAE,MAAM,CAAC,EAAE;QACzE,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IACH,uFAAuF;IACvF,uFAAuF;IACvF,4EAA4E;IAC5E,iFAAiF;IACjF,MAAM,kBAAkB,GAAG,GAAqB,EAAE,CAAC,CAAC;QAClD,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,4BAA4B,CAAC,UAAU;QAC9E,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,OAAO;QACL,8EAA8E;QAC9E,0EAA0E;QAC1E,wEAAwE;QACxE,gFAAgF;QAChF,gFAAgF;QAChF,6EAA6E;QAC7E,oFAAoF;QACpF,4EAA4E;QAC5E,gFAAgF;QAChF,mFAAmF;QACnF,uEAAuE;QACvE,iFAAiF;QACjF,mDAAmD;QACnD,UAAU,EAAE;YACV,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,4BAA4B,CAAC,EAAE,IAAI,CAAC,4BAA4B,CAAC,EAAE,EAAE,CAAC,+BAA+B,CAAC,EAAE,IAAI,CAAC,sBAAsB,CAAC,CAAC,EAAE;SACpK;QACD,mEAAmE;QACnE,2EAA2E;QAC3E,iBAAiB,EAAE;YACjB,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,EAAE;SAC/D;QACD,qEAAqE;QACrE,6DAA6D;QAC7D,yEAAyE;QACzE,gEAAgE;QAChE,yEAAyE;QACzE,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,0EAA0E;QAC1E,2EAA2E;QAC3E,0EAA0E;QAC1E,sCAAsC;QACtC,kFAAkF;QAClF,qFAAqF;QACrF,sFAAsF;QACtF,mFAAmF;QACnF,iFAAiF;QACjF,sFAAsF;QACtF,qFAAqF;QACrF,kFAAkF;QAClF,mFAAmF;QACnF,mDAAmD;QACnD,IAAI,EAAE;YACJ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,6BAA6B,CAAC,EAAE,IAAI,CAAC,+BAA+B,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE;SAC3M;QACD,8BAA8B;QAC9B,YAAY,EAAE;YACZ,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE;SACjD;QACD,gBAAgB,EAAE;YAChB,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,EAAE;SAC1D;KACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAqB;IAC/C,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAC7B,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC1C,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,CACtD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACjD,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEpD,IAAI,MAAM,GAAqB,EAAE,CAAC;IAClC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/D,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,MAAM,GAAG,MAA0B,CAAC;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,0BAA0B,CAAC,UAAU,CAAC,CAAC;IAEvD,KAAK,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5D,MAAM,UAAU,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,YAAY,CAAC,CAAC;IAClD,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpE,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -2018,6 +2018,19 @@ export interface InstarConfig {
2018
2018
  autonomousSessions?: {
2019
2019
  /** Max concurrent autonomous jobs (default 5). New starts beyond this are refused. */
2020
2020
  maxConcurrent?: number;
2021
+ /**
2022
+ * Codex autonomous-loop driver (codex/Claude parity). When enabled, the standing
2023
+ * codex Stop hook (`autonomous-stop-hook.sh --codex`, installed by installCodexHooks)
2024
+ * feeds the task list back so a `codex exec` session sustains a multi-turn autonomous
2025
+ * run instead of exiting after one turn — the codex analog of Claude's Stop-hook loop.
2026
+ * Ships DARK (default `enabled: false`): while off, the standing hook exits immediately
2027
+ * (no behavior change for any codex session), so this is a pure dark-launch flag.
2028
+ * Rollback = set `enabled: false` (instant, no redeploy). Claude autonomous mode is
2029
+ * unaffected either way (its loop hook is registered separately into settings.json).
2030
+ */
2031
+ codexLoopDriver?: {
2032
+ enabled?: boolean;
2033
+ };
2021
2034
  };
2022
2035
  /** Notification preferences for autonomy events */
2023
2036
  notifications?: NotificationPreferences;
@@ -2843,6 +2856,55 @@ export interface MonitoringConfig {
2843
2856
  ciMaxRunsPerTick?: number;
2844
2857
  };
2845
2858
  };
2859
+ /**
2860
+ * Correction & Preference Learning Sentinel
2861
+ * (docs/specs/CORRECTION-PREFERENCE-LEARNING-SENTINEL-SPEC.md). Ships OFF.
2862
+ * Slice 1a wires only the preferences read-surface: when `enabled`, the
2863
+ * `GET /preferences/session-context` route serves the learned-preference
2864
+ * block (else 503) and the session-start hook injects it. SIGNAL-ONLY — it
2865
+ * never blocks or rewrites an outbound message. Slice 1b adds the capture →
2866
+ * distill → ledger → recurrence-gate loop that writes via `recordPreference()`.
2867
+ */
2868
+ correctionLearning?: {
2869
+ /** Master kill switch (default: false). Gates the loop AND the read route. */
2870
+ enabled: boolean;
2871
+ /** Min total occurrences before a learning crosses the recurrence gate (Slice 1b). */
2872
+ minSupport?: number;
2873
+ /** Distinct calendar days required for an infra-gap learning (Slice 1b, restart-proof). */
2874
+ minDistinctDaysInfraGap?: number;
2875
+ /** Distinct calendar days required for an explicit-preference learning (Slice 1b). */
2876
+ minDistinctDaysPreference?: number;
2877
+ /** Distinct topics required for the preference path's second prong (Slice 1b). */
2878
+ minDistinctTopicsPreference?: number;
2879
+ /** Auto-submit infra-gap learnings to /feedback (Slice 1b/3). Default false. */
2880
+ autoFeedback?: boolean;
2881
+ /** Post a periodic Telegram digest of learned preferences (Slice 2). Default false. */
2882
+ telegramDigest?: boolean;
2883
+ /** Drift canary that samples un-classified messages through the LLM (Slice 1b). Default false. */
2884
+ driftCanary?: boolean;
2885
+ /** Per-sentinel LLM daily spend cap in cents (own LlmQueue instance, Slice 1b). */
2886
+ llmDailyCents?: number;
2887
+ /** Max concurrent LLM distillation calls (Slice 1b). */
2888
+ llmMaxConcurrent?: number;
2889
+ /** Per-topic look-back ring depth captured for distillation (Slice 1b). */
2890
+ captureContextTurns?: number;
2891
+ /** Max distinct topics held in the capture map before LRU eviction (Slice 1b). */
2892
+ captureTopicMapMax?: number;
2893
+ /** Idle TTL (minutes) before a topic's capture ring is evicted (Slice 1b). */
2894
+ captureTopicTtlMinutes?: number;
2895
+ /** Per-topic distillation rate ceiling per minute (Slice 1b). */
2896
+ distillPerTopicRatePerMinute?: number;
2897
+ /** Verify-window days for the infra-gap closed loop (Slice 1b/2). */
2898
+ verifyWindowDaysInfraGap?: number;
2899
+ /** Verify-window days for the preference closed loop (Slice 1b). */
2900
+ verifyWindowDaysPreference?: number;
2901
+ /** Byte cap on the injected session-start preferences block (Slice 1a). */
2902
+ maxInjectedPreferencesBytes?: number;
2903
+ /** Priority ordering string for the injected block (Slice 1a). */
2904
+ preferencesInjectionPriority?: string;
2905
+ /** Max times a closed-loop verification may reopen the same dedupeKey (Slice 1b). */
2906
+ maxReopens?: number;
2907
+ };
2846
2908
  /**
2847
2909
  * ReleaseReadinessSentinel (docs/specs/RELEASE-READINESS-VISIBILITY-SPEC.md §4.2)
2848
2910
  * — Layer B. A repo-gated dev-environment watchdog: evaluates the canonical