cortex-loop 0.1.0a1__py3-none-any.whl

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 (52) hide show
  1. cortex/__init__.py +7 -0
  2. cortex/adapters.py +339 -0
  3. cortex/blocklist.py +51 -0
  4. cortex/challenges.py +210 -0
  5. cortex/cli.py +7 -0
  6. cortex/core.py +601 -0
  7. cortex/core_helpers.py +190 -0
  8. cortex/data/identity_preamble.md +5 -0
  9. cortex/data/layer1_part_a.md +65 -0
  10. cortex/data/layer1_part_b.md +17 -0
  11. cortex/executive.py +295 -0
  12. cortex/foundation.py +185 -0
  13. cortex/genome.py +348 -0
  14. cortex/graveyard.py +226 -0
  15. cortex/hooks/__init__.py +27 -0
  16. cortex/hooks/_shared.py +167 -0
  17. cortex/hooks/post_tool_use.py +13 -0
  18. cortex/hooks/pre_tool_use.py +13 -0
  19. cortex/hooks/session_start.py +13 -0
  20. cortex/hooks/stop.py +13 -0
  21. cortex/invariants.py +258 -0
  22. cortex/packs.py +118 -0
  23. cortex/repomap.py +6 -0
  24. cortex/requirements.py +497 -0
  25. cortex/retry.py +312 -0
  26. cortex/stop_contract.py +217 -0
  27. cortex/stop_payload.py +122 -0
  28. cortex/stop_policy.py +100 -0
  29. cortex/stop_runtime.py +400 -0
  30. cortex/stop_signals.py +75 -0
  31. cortex/store.py +793 -0
  32. cortex/templates/__init__.py +10 -0
  33. cortex/utils.py +58 -0
  34. cortex_loop-0.1.0a1.dist-info/METADATA +121 -0
  35. cortex_loop-0.1.0a1.dist-info/RECORD +52 -0
  36. cortex_loop-0.1.0a1.dist-info/WHEEL +5 -0
  37. cortex_loop-0.1.0a1.dist-info/entry_points.txt +3 -0
  38. cortex_loop-0.1.0a1.dist-info/licenses/LICENSE +21 -0
  39. cortex_loop-0.1.0a1.dist-info/top_level.txt +3 -0
  40. cortex_ops_cli/__init__.py +3 -0
  41. cortex_ops_cli/_adapter_validation.py +119 -0
  42. cortex_ops_cli/_check_report.py +454 -0
  43. cortex_ops_cli/_check_report_output.py +270 -0
  44. cortex_ops_cli/_openai_bridge_probe.py +241 -0
  45. cortex_ops_cli/_openai_bridge_protocol.py +469 -0
  46. cortex_ops_cli/_runtime_profile_templates.py +341 -0
  47. cortex_ops_cli/_runtime_profiles.py +445 -0
  48. cortex_ops_cli/gemini_hooks.py +301 -0
  49. cortex_ops_cli/main.py +911 -0
  50. cortex_ops_cli/openai_app_server_bridge.py +375 -0
  51. cortex_repomap/__init__.py +1 -0
  52. cortex_repomap/engine.py +1201 -0
cortex/store.py ADDED
@@ -0,0 +1,793 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ import re
6
+ import sqlite3
7
+ import time
8
+ from contextlib import contextmanager
9
+ from dataclasses import dataclass
10
+ from datetime import datetime, timezone
11
+ from pathlib import Path
12
+ from typing import Any, Callable, Iterator
13
+ from uuid import uuid4
14
+
15
+ DB_SCHEMA_VERSION = 2
16
+
17
+
18
+ def _utc_now() -> str:
19
+ return datetime.now(timezone.utc).isoformat()
20
+
21
+
22
+ _FTS_TOKEN_RE = re.compile(r"^[a-z0-9_]+$")
23
+ _COMPACT_TEXT_FIELDS = ("last_assistant_message", "stdout", "stderr", "output", "message")
24
+ _COMPACT_TEXT_MAX_LEN = 2048
25
+
26
+
27
+ @dataclass(slots=True)
28
+ class SQLiteStore:
29
+ db_path: Path
30
+ lock_retry_attempts: int = 3
31
+ lock_retry_backoff_ms: int = 25
32
+ busy_timeout_ms: int = 5000
33
+
34
+ def initialize(self) -> None:
35
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
36
+ with self.connection() as conn:
37
+ conn.execute("PRAGMA journal_mode = WAL")
38
+ conn.execute("PRAGMA foreign_keys = ON")
39
+ conn.execute(f"PRAGMA user_version = {DB_SCHEMA_VERSION}")
40
+ conn.executescript(
41
+ """
42
+ CREATE TABLE IF NOT EXISTS sessions (
43
+ session_id TEXT PRIMARY KEY,
44
+ started_at TEXT NOT NULL,
45
+ ended_at TEXT,
46
+ status TEXT NOT NULL,
47
+ genome_path TEXT,
48
+ metadata_json TEXT NOT NULL
49
+ );
50
+
51
+ CREATE TABLE IF NOT EXISTS graveyard (
52
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
53
+ session_id TEXT,
54
+ summary TEXT NOT NULL,
55
+ reason TEXT NOT NULL,
56
+ files_json TEXT NOT NULL,
57
+ keywords_json TEXT NOT NULL,
58
+ created_at TEXT NOT NULL
59
+ );
60
+
61
+ CREATE TABLE IF NOT EXISTS invariants (
62
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
63
+ session_id TEXT NOT NULL,
64
+ test_path TEXT NOT NULL,
65
+ status TEXT NOT NULL,
66
+ duration_ms INTEGER NOT NULL,
67
+ stdout TEXT NOT NULL,
68
+ stderr TEXT NOT NULL,
69
+ graduated_from TEXT,
70
+ created_at TEXT NOT NULL
71
+ );
72
+
73
+ CREATE TABLE IF NOT EXISTS challenge_results (
74
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
75
+ session_id TEXT NOT NULL,
76
+ category TEXT NOT NULL,
77
+ covered INTEGER NOT NULL,
78
+ evidence_json TEXT NOT NULL,
79
+ created_at TEXT NOT NULL
80
+ );
81
+
82
+ CREATE TABLE IF NOT EXISTS events (
83
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
84
+ session_id TEXT NOT NULL,
85
+ hook TEXT NOT NULL,
86
+ tool_name TEXT,
87
+ status TEXT,
88
+ payload_json TEXT NOT NULL,
89
+ created_at TEXT NOT NULL
90
+ );
91
+
92
+ CREATE TABLE IF NOT EXISTS retry_budget (
93
+ session_id TEXT PRIMARY KEY,
94
+ attempts INTEGER NOT NULL DEFAULT 0,
95
+ updated_at TEXT NOT NULL
96
+ );
97
+
98
+ CREATE TABLE IF NOT EXISTS retry_reason_budget (
99
+ session_id TEXT NOT NULL,
100
+ reason TEXT NOT NULL,
101
+ attempts INTEGER NOT NULL DEFAULT 0,
102
+ updated_at TEXT NOT NULL,
103
+ PRIMARY KEY (session_id, reason)
104
+ );
105
+
106
+ CREATE TABLE IF NOT EXISTS retry_delta_state (
107
+ session_id TEXT NOT NULL,
108
+ reason TEXT NOT NULL,
109
+ failure_signature TEXT NOT NULL,
110
+ last_delta_hash TEXT NOT NULL,
111
+ updated_at TEXT NOT NULL,
112
+ PRIMARY KEY (session_id, reason, failure_signature)
113
+ );
114
+
115
+ CREATE TABLE IF NOT EXISTS cortex_meta (
116
+ key TEXT PRIMARY KEY,
117
+ value_text TEXT NOT NULL
118
+ );
119
+
120
+ CREATE TABLE IF NOT EXISTS executive_memory (
121
+ id TEXT PRIMARY KEY,
122
+ type TEXT NOT NULL,
123
+ trigger_pattern TEXT NOT NULL,
124
+ error_pattern TEXT NOT NULL,
125
+ resolution TEXT NOT NULL,
126
+ strength INTEGER NOT NULL DEFAULT 1,
127
+ created_at_session INTEGER NOT NULL,
128
+ last_accessed_at_session INTEGER NOT NULL,
129
+ source_session_id TEXT NOT NULL
130
+ );
131
+
132
+ CREATE TABLE IF NOT EXISTS session_counter_allocations (
133
+ session_id TEXT PRIMARY KEY,
134
+ counter INTEGER NOT NULL
135
+ );
136
+
137
+ CREATE TABLE IF NOT EXISTS executive_stop_signatures (
138
+ session_id TEXT PRIMARY KEY,
139
+ signature TEXT NOT NULL,
140
+ updated_at TEXT NOT NULL
141
+ );
142
+
143
+ CREATE INDEX IF NOT EXISTS idx_events_session_hook ON events(session_id, hook);
144
+ CREATE INDEX IF NOT EXISTS idx_graveyard_session ON graveyard(session_id);
145
+ CREATE INDEX IF NOT EXISTS idx_challenge_results_session_category
146
+ ON challenge_results(session_id, category);
147
+ CREATE INDEX IF NOT EXISTS idx_invariants_session_status
148
+ ON invariants(session_id, status);
149
+ CREATE INDEX IF NOT EXISTS idx_executive_memory_type_strength
150
+ ON executive_memory(type, strength DESC);
151
+ """
152
+ )
153
+ self._purge_transient_session_state(conn)
154
+
155
+ @contextmanager
156
+ def connection(self) -> Iterator[sqlite3.Connection]:
157
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
158
+ conn = sqlite3.connect(self.db_path, timeout=5.0)
159
+ conn.row_factory = sqlite3.Row
160
+ conn.execute(f"PRAGMA busy_timeout = {max(0, int(self.busy_timeout_ms))}")
161
+ try:
162
+ yield conn
163
+ conn.commit()
164
+ finally:
165
+ conn.close()
166
+
167
+ def _run_write(self, operation: Callable[[sqlite3.Connection], None]) -> None:
168
+ attempts = max(0, int(self.lock_retry_attempts)) + 1
169
+ backoff = max(0, int(self.lock_retry_backoff_ms)) / 1000.0
170
+ for attempt in range(attempts):
171
+ try:
172
+ with self.connection() as conn:
173
+ operation(conn)
174
+ return
175
+ except sqlite3.OperationalError as exc:
176
+ if not self._is_lock_error(exc) or attempt >= attempts - 1:
177
+ raise
178
+ if backoff > 0:
179
+ time.sleep(backoff * (2**attempt))
180
+
181
+ @staticmethod
182
+ def _is_lock_error(exc: sqlite3.OperationalError) -> bool:
183
+ return any(msg in str(exc).lower() for msg in ("database is locked", "database table is locked"))
184
+
185
+ def upsert_session_start(
186
+ self, session_id: str, status: str, genome_path: str | None, metadata: dict[str, Any] | None = None
187
+ ) -> None:
188
+ self._execute_write(
189
+ """
190
+ INSERT INTO sessions (session_id, started_at, status, genome_path, metadata_json)
191
+ VALUES (?, ?, ?, ?, ?)
192
+ ON CONFLICT(session_id) DO UPDATE SET
193
+ status=excluded.status,
194
+ genome_path=excluded.genome_path,
195
+ metadata_json=excluded.metadata_json
196
+ """,
197
+ (
198
+ session_id,
199
+ _utc_now(),
200
+ status,
201
+ genome_path,
202
+ json.dumps(metadata or {}, sort_keys=True),
203
+ ),
204
+ )
205
+
206
+ def ensure_session_start(
207
+ self, session_id: str, status: str, genome_path: str | None, metadata: dict[str, Any] | None = None
208
+ ) -> None:
209
+ self._execute_write(
210
+ """
211
+ INSERT OR IGNORE INTO sessions (session_id, started_at, status, genome_path, metadata_json)
212
+ VALUES (?, ?, ?, ?, ?)
213
+ """,
214
+ (
215
+ session_id,
216
+ _utc_now(),
217
+ status,
218
+ genome_path,
219
+ json.dumps(metadata or {}, sort_keys=True),
220
+ ),
221
+ )
222
+
223
+ def close_session(self, session_id: str, status: str, metadata: dict[str, Any] | None = None) -> None:
224
+ now = _utc_now()
225
+ closed_filter = "session_id IN (SELECT session_id FROM sessions WHERE status != 'running' OR ended_at IS NOT NULL)"
226
+
227
+ def _op(conn: sqlite3.Connection) -> None:
228
+ conn.execute("BEGIN IMMEDIATE")
229
+ conn.execute(
230
+ """
231
+ UPDATE sessions
232
+ SET ended_at = ?, status = ?, metadata_json = ?
233
+ WHERE session_id = ?
234
+ """,
235
+ (
236
+ now,
237
+ status,
238
+ json.dumps(metadata or {}, sort_keys=True),
239
+ session_id,
240
+ ),
241
+ )
242
+ conn.execute(f"DELETE FROM session_counter_allocations WHERE {closed_filter}")
243
+ conn.execute(
244
+ f"DELETE FROM executive_stop_signatures WHERE session_id <> ? AND {closed_filter}",
245
+ (session_id,),
246
+ )
247
+
248
+ self._run_write(_op)
249
+
250
+ def record_event(
251
+ self,
252
+ session_id: str,
253
+ hook: str,
254
+ payload: dict[str, Any],
255
+ tool_name: str | None = None,
256
+ status: str | None = None,
257
+ ) -> None:
258
+ compacted_payload = self._compact_event_payload(payload)
259
+ self._execute_write(
260
+ """
261
+ INSERT INTO events (session_id, hook, tool_name, status, payload_json, created_at)
262
+ VALUES (?, ?, ?, ?, ?, ?)
263
+ """,
264
+ (
265
+ session_id,
266
+ hook,
267
+ tool_name,
268
+ status,
269
+ json.dumps(compacted_payload, sort_keys=True),
270
+ _utc_now(),
271
+ ),
272
+ )
273
+
274
+ def get_retry_delta_hash(self, session_id: str, reason: str, failure_signature: str) -> str | None:
275
+ reason_token = str(reason or "").strip()
276
+ signature_token = str(failure_signature or "").strip()
277
+ if not reason_token or not signature_token:
278
+ return None
279
+ with self.connection() as conn:
280
+ row = conn.execute(
281
+ """
282
+ SELECT last_delta_hash
283
+ FROM retry_delta_state
284
+ WHERE session_id = ? AND reason = ? AND failure_signature = ?
285
+ LIMIT 1
286
+ """,
287
+ (session_id, reason_token, signature_token),
288
+ ).fetchone()
289
+ if row is None:
290
+ return None
291
+ return str(row["last_delta_hash"] or "")
292
+
293
+ def upsert_retry_delta_hash(
294
+ self,
295
+ session_id: str,
296
+ *,
297
+ reason: str,
298
+ failure_signature: str,
299
+ delta_hash: str,
300
+ ) -> None:
301
+ reason_token = str(reason or "").strip()
302
+ signature_token = str(failure_signature or "").strip()
303
+ if not reason_token or not signature_token:
304
+ return
305
+ self._execute_write(
306
+ """
307
+ INSERT INTO retry_delta_state (session_id, reason, failure_signature, last_delta_hash, updated_at)
308
+ VALUES (?, ?, ?, ?, ?)
309
+ ON CONFLICT(session_id, reason, failure_signature) DO UPDATE SET
310
+ last_delta_hash = excluded.last_delta_hash,
311
+ updated_at = excluded.updated_at
312
+ """,
313
+ (
314
+ session_id,
315
+ reason_token,
316
+ signature_token,
317
+ str(delta_hash or ""),
318
+ _utc_now(),
319
+ ),
320
+ )
321
+
322
+ def get_retry_attempts(self, session_id: str, *, reason: str) -> dict[str, int]:
323
+ reason_token = str(reason or "").strip()
324
+ if not reason_token:
325
+ return {"attempts": 0, "reason_attempts": 0}
326
+ with self.connection() as conn:
327
+ session_row = conn.execute(
328
+ "SELECT attempts FROM retry_budget WHERE session_id = ?",
329
+ (session_id,),
330
+ ).fetchone()
331
+ reason_row = conn.execute(
332
+ "SELECT attempts FROM retry_reason_budget WHERE session_id = ? AND reason = ?",
333
+ (session_id, reason_token),
334
+ ).fetchone()
335
+ return {
336
+ "attempts": int(session_row["attempts"]) if session_row is not None else 0,
337
+ "reason_attempts": int(reason_row["attempts"]) if reason_row is not None else 0,
338
+ }
339
+
340
+ def try_increment_retry_attempts(
341
+ self,
342
+ session_id: str,
343
+ *,
344
+ reason: str,
345
+ expected_attempts: int,
346
+ expected_reason_attempts: int,
347
+ ) -> dict[str, int | bool]:
348
+ reason_token = str(reason or "").strip()
349
+ outcome: dict[str, int | bool] = {
350
+ "consumed": False,
351
+ "attempts": max(0, int(expected_attempts)),
352
+ "reason_attempts": max(0, int(expected_reason_attempts)),
353
+ }
354
+ if not reason_token:
355
+ return outcome
356
+
357
+ def _op(conn: sqlite3.Connection) -> None:
358
+ now = _utc_now()
359
+ conn.execute("BEGIN IMMEDIATE")
360
+ self._ensure_retry_budget_rows(conn, session_id=session_id, reason=reason_token, now=now)
361
+ session_row = conn.execute(
362
+ "SELECT attempts FROM retry_budget WHERE session_id = ?",
363
+ (session_id,),
364
+ ).fetchone()
365
+ reason_row = conn.execute(
366
+ "SELECT attempts FROM retry_reason_budget WHERE session_id = ? AND reason = ?",
367
+ (session_id, reason_token),
368
+ ).fetchone()
369
+ session_attempts = int(session_row["attempts"]) if session_row is not None else 0
370
+ reason_attempts = int(reason_row["attempts"]) if reason_row is not None else 0
371
+
372
+ if (
373
+ session_attempts == max(0, int(expected_attempts))
374
+ and reason_attempts == max(0, int(expected_reason_attempts))
375
+ ):
376
+ conn.execute(
377
+ """
378
+ UPDATE retry_budget
379
+ SET attempts = attempts + 1, updated_at = ?
380
+ WHERE session_id = ?
381
+ """,
382
+ (now, session_id),
383
+ )
384
+ conn.execute(
385
+ """
386
+ UPDATE retry_reason_budget
387
+ SET attempts = attempts + 1, updated_at = ?
388
+ WHERE session_id = ? AND reason = ?
389
+ """,
390
+ (now, session_id, reason_token),
391
+ )
392
+ session_attempts += 1
393
+ reason_attempts += 1
394
+ outcome["consumed"] = True
395
+
396
+ outcome["attempts"] = session_attempts
397
+ outcome["reason_attempts"] = reason_attempts
398
+
399
+ self._run_write(_op)
400
+ return outcome
401
+
402
+ def insert_graveyard(
403
+ self,
404
+ session_id: str | None,
405
+ summary: str,
406
+ reason: str,
407
+ files: list[str],
408
+ keywords: list[str],
409
+ ) -> None:
410
+ self._execute_write(
411
+ """
412
+ INSERT INTO graveyard (session_id, summary, reason, files_json, keywords_json, created_at)
413
+ VALUES (?, ?, ?, ?, ?, ?)
414
+ """,
415
+ (
416
+ session_id,
417
+ summary,
418
+ reason,
419
+ json.dumps(files, sort_keys=True),
420
+ json.dumps(keywords, sort_keys=True),
421
+ _utc_now(),
422
+ ),
423
+ )
424
+
425
+ def list_graveyard(self, limit: int = 100) -> list[dict[str, Any]]:
426
+ rows = self._list_graveyard_rows(limit)
427
+ return [self._graveyard_row_to_item(row) for row in rows]
428
+
429
+ def list_graveyard_fts_candidates(
430
+ self,
431
+ *,
432
+ tokens: list[str],
433
+ limit: int = 200,
434
+ candidate_limit: int = 80,
435
+ ) -> list[dict[str, Any]] | None:
436
+ terms = [t for t in tokens if _FTS_TOKEN_RE.match(t)]
437
+ if not terms or not (rows := self._list_graveyard_rows(limit)):
438
+ return []
439
+ with self.connection() as conn:
440
+ try:
441
+ conn.execute(
442
+ "CREATE TEMP VIRTUAL TABLE IF NOT EXISTS _cortex_graveyard_fts "
443
+ "USING fts5(entry_id UNINDEXED, text)"
444
+ )
445
+ conn.execute("DELETE FROM _cortex_graveyard_fts")
446
+ except sqlite3.OperationalError:
447
+ return None
448
+
449
+ conn.executemany(
450
+ "INSERT INTO _cortex_graveyard_fts(entry_id, text) VALUES (?, ?)",
451
+ [
452
+ (
453
+ str(row["id"]),
454
+ f"{row['summary']} {row['reason']} {row['keywords_json']}",
455
+ )
456
+ for row in rows
457
+ ],
458
+ )
459
+ match_query = " OR ".join(terms[:12])
460
+ matched = conn.execute(
461
+ """
462
+ SELECT entry_id
463
+ FROM _cortex_graveyard_fts
464
+ WHERE _cortex_graveyard_fts MATCH ?
465
+ ORDER BY bm25(_cortex_graveyard_fts), CAST(entry_id AS INTEGER) DESC
466
+ LIMIT ?
467
+ """,
468
+ (match_query, max(1, int(candidate_limit))),
469
+ ).fetchall()
470
+
471
+ if not matched:
472
+ return []
473
+ row_map = {int(row["id"]): row for row in rows}
474
+ ordered_ids = [int(row["entry_id"]) for row in matched]
475
+ return [self._graveyard_row_to_item(row_map[eid]) for eid in ordered_ids if eid in row_map]
476
+
477
+ def record_invariant_result(
478
+ self,
479
+ session_id: str,
480
+ test_path: str,
481
+ status: str,
482
+ duration_ms: int,
483
+ stdout: str,
484
+ stderr: str,
485
+ graduated_from: str | None = None,
486
+ ) -> None:
487
+ self._execute_write(
488
+ """
489
+ INSERT INTO invariants
490
+ (session_id, test_path, status, duration_ms, stdout, stderr, graduated_from, created_at)
491
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
492
+ """,
493
+ (
494
+ session_id,
495
+ test_path,
496
+ status,
497
+ duration_ms,
498
+ stdout,
499
+ stderr,
500
+ graduated_from,
501
+ _utc_now(),
502
+ ),
503
+ )
504
+
505
+ def record_challenge_result(
506
+ self, session_id: str, category: str, covered: bool, evidence: dict[str, Any] | None = None
507
+ ) -> None:
508
+ self._execute_write(
509
+ """
510
+ INSERT INTO challenge_results (session_id, category, covered, evidence_json, created_at)
511
+ VALUES (?, ?, ?, ?, ?)
512
+ """,
513
+ (
514
+ session_id,
515
+ category,
516
+ 1 if covered else 0,
517
+ json.dumps(evidence or {}, sort_keys=True),
518
+ _utc_now(),
519
+ ),
520
+ )
521
+
522
+ def _execute_write(self, sql: str, params: tuple[Any, ...]) -> None:
523
+ self._run_write(lambda conn: conn.execute(sql, params))
524
+
525
+ def increment_session_counter(self) -> int:
526
+ result = {"value": 0}
527
+
528
+ def _op(conn: sqlite3.Connection) -> None:
529
+ conn.execute("BEGIN IMMEDIATE")
530
+ conn.execute("INSERT INTO cortex_meta (key, value_text) VALUES ('session_counter', '0') ON CONFLICT(key) DO NOTHING")
531
+ conn.execute("UPDATE cortex_meta SET value_text = CAST(COALESCE(value_text, '0') AS INTEGER) + 1 WHERE key = 'session_counter'")
532
+ row = conn.execute("SELECT value_text FROM cortex_meta WHERE key = 'session_counter'").fetchone()
533
+ result["value"] = int(row["value_text"]) if row is not None else 0
534
+
535
+ self._run_write(_op)
536
+ return int(result["value"])
537
+
538
+ def allocate_session_counter(self, session_id: str) -> int:
539
+ token = str(session_id or "").strip()
540
+ if not token:
541
+ return self.increment_session_counter()
542
+ result = {"value": 0}
543
+
544
+ def _op(conn: sqlite3.Connection) -> None:
545
+ conn.execute("BEGIN IMMEDIATE")
546
+ existing = conn.execute(
547
+ "SELECT counter FROM session_counter_allocations WHERE session_id = ? LIMIT 1",
548
+ (token,),
549
+ ).fetchone()
550
+ if existing is not None:
551
+ result["value"] = int(existing["counter"])
552
+ return
553
+ conn.execute("INSERT INTO cortex_meta (key, value_text) VALUES ('session_counter', '0') ON CONFLICT(key) DO NOTHING")
554
+ conn.execute("UPDATE cortex_meta SET value_text = CAST(COALESCE(value_text, '0') AS INTEGER) + 1 WHERE key = 'session_counter'")
555
+ counter = conn.execute("SELECT value_text FROM cortex_meta WHERE key = 'session_counter'").fetchone()
556
+ allocated = int(counter["value_text"]) if counter is not None else 0
557
+ conn.execute(
558
+ """
559
+ INSERT INTO session_counter_allocations (session_id, counter)
560
+ VALUES (?, ?)
561
+ ON CONFLICT(session_id) DO NOTHING
562
+ """,
563
+ (token, allocated),
564
+ )
565
+ row = conn.execute(
566
+ "SELECT counter FROM session_counter_allocations WHERE session_id = ? LIMIT 1",
567
+ (token,),
568
+ ).fetchone()
569
+ result["value"] = int(row["counter"]) if row is not None else allocated
570
+
571
+ self._run_write(_op)
572
+ return int(result["value"])
573
+
574
+ def claim_executive_stop_signature(self, session_id: str, signature: str) -> bool:
575
+ sid = str(session_id or "").strip()
576
+ sig = str(signature or "").strip()
577
+ if not sid or not sig:
578
+ return False
579
+ claimed = {"value": False}
580
+
581
+ def _op(conn: sqlite3.Connection) -> None:
582
+ conn.execute("BEGIN IMMEDIATE")
583
+ row = conn.execute(
584
+ "SELECT signature FROM executive_stop_signatures WHERE session_id = ? LIMIT 1",
585
+ (sid,),
586
+ ).fetchone()
587
+ if row is not None and str(row["signature"] or "") == sig:
588
+ claimed["value"] = False
589
+ return
590
+ conn.execute(
591
+ """
592
+ INSERT INTO executive_stop_signatures (session_id, signature, updated_at)
593
+ VALUES (?, ?, ?)
594
+ ON CONFLICT(session_id) DO UPDATE SET
595
+ signature = excluded.signature,
596
+ updated_at = excluded.updated_at
597
+ """,
598
+ (sid, sig, _utc_now()),
599
+ )
600
+ claimed["value"] = True
601
+
602
+ self._run_write(_op)
603
+ return bool(claimed["value"])
604
+
605
+ def get_session_count(self) -> int:
606
+ with self.connection() as conn:
607
+ row = conn.execute(
608
+ "SELECT value_text FROM cortex_meta WHERE key = 'session_counter' LIMIT 1"
609
+ ).fetchone()
610
+ if row is None:
611
+ return 0
612
+ try:
613
+ return int(row["value_text"])
614
+ except (TypeError, ValueError):
615
+ return 0
616
+
617
+ def claim_meta_once(self, key: str, value: str = "1") -> bool:
618
+ token = str(key or "").strip()
619
+ if not token:
620
+ return False
621
+ claimed = {"value": False}
622
+
623
+ def _op(conn: sqlite3.Connection) -> None:
624
+ conn.execute("BEGIN IMMEDIATE")
625
+ existing = conn.execute(
626
+ "SELECT 1 FROM cortex_meta WHERE key = ? LIMIT 1",
627
+ (token,),
628
+ ).fetchone()
629
+ if existing is not None:
630
+ claimed["value"] = False
631
+ return
632
+ conn.execute(
633
+ "INSERT INTO cortex_meta (key, value_text) VALUES (?, ?)",
634
+ (token, str(value)),
635
+ )
636
+ claimed["value"] = True
637
+
638
+ self._run_write(_op)
639
+ return bool(claimed["value"])
640
+
641
+ def record_executive_event(
642
+ self,
643
+ event_type: str,
644
+ trigger: str,
645
+ error: str,
646
+ resolution: str,
647
+ session_id: str,
648
+ ) -> dict[str, Any]:
649
+ current_session = self.get_session_count()
650
+ row = {
651
+ "id": f"exec-{uuid4().hex}",
652
+ "type": str(event_type),
653
+ "trigger_pattern": str(trigger),
654
+ "error_pattern": str(error),
655
+ "resolution": str(resolution),
656
+ "strength": 1,
657
+ "created_at_session": current_session,
658
+ "last_accessed_at_session": current_session,
659
+ "source_session_id": str(session_id),
660
+ }
661
+ self._execute_write(
662
+ "INSERT INTO executive_memory (id, type, trigger_pattern, error_pattern, resolution, strength, created_at_session, last_accessed_at_session, source_session_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
663
+ (
664
+ row["id"],
665
+ row["type"],
666
+ row["trigger_pattern"],
667
+ row["error_pattern"],
668
+ row["resolution"],
669
+ row["strength"],
670
+ row["created_at_session"],
671
+ row["last_accessed_at_session"],
672
+ row["source_session_id"],
673
+ ),
674
+ )
675
+ return row
676
+
677
+ def get_executive_memory(self) -> list[dict[str, Any]]:
678
+ with self.connection() as conn:
679
+ rows = conn.execute("SELECT id, type, trigger_pattern, error_pattern, resolution, strength, created_at_session, last_accessed_at_session, source_session_id FROM executive_memory ORDER BY created_at_session DESC, id ASC").fetchall()
680
+ return [
681
+ {
682
+ "id": str(row["id"]),
683
+ "type": str(row["type"]),
684
+ "trigger_pattern": str(row["trigger_pattern"]),
685
+ "error_pattern": str(row["error_pattern"]),
686
+ "resolution": str(row["resolution"]),
687
+ "strength": int(row["strength"]),
688
+ "created_at_session": int(row["created_at_session"]),
689
+ "last_accessed_at_session": int(row["last_accessed_at_session"]),
690
+ "source_session_id": str(row["source_session_id"]),
691
+ }
692
+ for row in rows
693
+ ]
694
+
695
+ def update_executive_entry(
696
+ self,
697
+ entry_id: str,
698
+ *,
699
+ strength: int | None = None,
700
+ last_accessed_at_session: int | None = None,
701
+ ) -> None:
702
+ updates: list[str] = []
703
+ params: list[Any] = []
704
+ if strength is not None:
705
+ updates.append("strength = ?")
706
+ params.append(max(1, int(strength)))
707
+ if last_accessed_at_session is not None:
708
+ updates.append("last_accessed_at_session = ?")
709
+ params.append(max(0, int(last_accessed_at_session)))
710
+ if not updates:
711
+ return
712
+ params.append(str(entry_id))
713
+ self._execute_write(
714
+ f"UPDATE executive_memory SET {', '.join(updates)} WHERE id = ?",
715
+ tuple(params),
716
+ )
717
+
718
+ def delete_executive_entries(self, ids: list[str]) -> None:
719
+ tokens = [str(item).strip() for item in ids if str(item).strip()]
720
+ if not tokens:
721
+ return
722
+ placeholders = ",".join(["?"] * len(tokens))
723
+ self._execute_write(
724
+ f"DELETE FROM executive_memory WHERE id IN ({placeholders})",
725
+ tuple(tokens),
726
+ )
727
+
728
+ @staticmethod
729
+ def _ensure_retry_budget_rows(conn: sqlite3.Connection, *, session_id: str, reason: str, now: str) -> None:
730
+ conn.execute(
731
+ """
732
+ INSERT INTO retry_budget (session_id, attempts, updated_at)
733
+ VALUES (?, 0, ?)
734
+ ON CONFLICT(session_id) DO NOTHING
735
+ """,
736
+ (session_id, now),
737
+ )
738
+ conn.execute(
739
+ """
740
+ INSERT INTO retry_reason_budget (session_id, reason, attempts, updated_at)
741
+ VALUES (?, ?, 0, ?)
742
+ ON CONFLICT(session_id, reason) DO NOTHING
743
+ """,
744
+ (session_id, reason, now),
745
+ )
746
+
747
+ @staticmethod
748
+ def _purge_transient_session_state(conn: sqlite3.Connection) -> None:
749
+ running = "session_id IN (SELECT session_id FROM sessions WHERE status = 'running' AND ended_at IS NULL)"
750
+ conn.execute(f"DELETE FROM session_counter_allocations WHERE NOT ({running})")
751
+ conn.execute(f"DELETE FROM executive_stop_signatures WHERE NOT ({running})")
752
+
753
+ def _list_graveyard_rows(self, limit: int) -> list[sqlite3.Row]:
754
+ with self.connection() as conn:
755
+ return conn.execute(
756
+ """
757
+ SELECT id, session_id, summary, reason, files_json, keywords_json, created_at
758
+ FROM graveyard
759
+ ORDER BY id DESC
760
+ LIMIT ?
761
+ """,
762
+ (limit,),
763
+ ).fetchall()
764
+
765
+ @staticmethod
766
+ def _graveyard_row_to_item(row: sqlite3.Row) -> dict[str, Any]:
767
+ return {
768
+ "id": row["id"],
769
+ "session_id": row["session_id"],
770
+ "summary": row["summary"],
771
+ "reason": row["reason"],
772
+ "files": json.loads(row["files_json"]),
773
+ "keywords": json.loads(row["keywords_json"]),
774
+ "created_at": row["created_at"],
775
+ }
776
+
777
+ @staticmethod
778
+ def _compact_event_payload(payload: dict[str, Any]) -> dict[str, Any]:
779
+ compacted = dict(payload)
780
+ meta: dict[str, dict[str, Any]] = {}
781
+ for field in _COMPACT_TEXT_FIELDS:
782
+ value = compacted.get(field)
783
+ if not isinstance(value, str) or len(value) <= _COMPACT_TEXT_MAX_LEN:
784
+ continue
785
+ meta[field] = {
786
+ "original_len": len(value),
787
+ "truncated": True,
788
+ "sha256": hashlib.sha256(value.encode("utf-8")).hexdigest(),
789
+ }
790
+ compacted[field] = value[:_COMPACT_TEXT_MAX_LEN]
791
+ if meta:
792
+ compacted["_payload_compaction"] = meta
793
+ return compacted