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.
- cortex/__init__.py +7 -0
- cortex/adapters.py +339 -0
- cortex/blocklist.py +51 -0
- cortex/challenges.py +210 -0
- cortex/cli.py +7 -0
- cortex/core.py +601 -0
- cortex/core_helpers.py +190 -0
- cortex/data/identity_preamble.md +5 -0
- cortex/data/layer1_part_a.md +65 -0
- cortex/data/layer1_part_b.md +17 -0
- cortex/executive.py +295 -0
- cortex/foundation.py +185 -0
- cortex/genome.py +348 -0
- cortex/graveyard.py +226 -0
- cortex/hooks/__init__.py +27 -0
- cortex/hooks/_shared.py +167 -0
- cortex/hooks/post_tool_use.py +13 -0
- cortex/hooks/pre_tool_use.py +13 -0
- cortex/hooks/session_start.py +13 -0
- cortex/hooks/stop.py +13 -0
- cortex/invariants.py +258 -0
- cortex/packs.py +118 -0
- cortex/repomap.py +6 -0
- cortex/requirements.py +497 -0
- cortex/retry.py +312 -0
- cortex/stop_contract.py +217 -0
- cortex/stop_payload.py +122 -0
- cortex/stop_policy.py +100 -0
- cortex/stop_runtime.py +400 -0
- cortex/stop_signals.py +75 -0
- cortex/store.py +793 -0
- cortex/templates/__init__.py +10 -0
- cortex/utils.py +58 -0
- cortex_loop-0.1.0a1.dist-info/METADATA +121 -0
- cortex_loop-0.1.0a1.dist-info/RECORD +52 -0
- cortex_loop-0.1.0a1.dist-info/WHEEL +5 -0
- cortex_loop-0.1.0a1.dist-info/entry_points.txt +3 -0
- cortex_loop-0.1.0a1.dist-info/licenses/LICENSE +21 -0
- cortex_loop-0.1.0a1.dist-info/top_level.txt +3 -0
- cortex_ops_cli/__init__.py +3 -0
- cortex_ops_cli/_adapter_validation.py +119 -0
- cortex_ops_cli/_check_report.py +454 -0
- cortex_ops_cli/_check_report_output.py +270 -0
- cortex_ops_cli/_openai_bridge_probe.py +241 -0
- cortex_ops_cli/_openai_bridge_protocol.py +469 -0
- cortex_ops_cli/_runtime_profile_templates.py +341 -0
- cortex_ops_cli/_runtime_profiles.py +445 -0
- cortex_ops_cli/gemini_hooks.py +301 -0
- cortex_ops_cli/main.py +911 -0
- cortex_ops_cli/openai_app_server_bridge.py +375 -0
- cortex_repomap/__init__.py +1 -0
- cortex_repomap/engine.py +1201 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import hashlib
|
|
5
|
+
import json
|
|
6
|
+
import sqlite3
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from cortex.core import CortexKernel
|
|
12
|
+
from cortex.executive import get_base_executive_function
|
|
13
|
+
|
|
14
|
+
KERNEL_EVENT_NAMES = {"SessionStart", "BeforeTool", "AfterTool", "AfterAgent"}
|
|
15
|
+
RETRY_STOP_REASON = "Cortex stop path failed after retry. Manual review required."
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main(argv: list[str] | None = None) -> int:
|
|
19
|
+
args = _parse_args(argv)
|
|
20
|
+
try:
|
|
21
|
+
payload = _read_payload()
|
|
22
|
+
payload = _ensure_session_id(payload, event=args.event)
|
|
23
|
+
except Exception as exc: # noqa: BLE001
|
|
24
|
+
print(f"[cortex] Gemini bridge error: {exc}", file=sys.stderr)
|
|
25
|
+
return 1
|
|
26
|
+
|
|
27
|
+
if args.event not in KERNEL_EVENT_NAMES:
|
|
28
|
+
if args.event == "BeforeAgent":
|
|
29
|
+
print(json.dumps(_before_agent_output(payload)))
|
|
30
|
+
return 0
|
|
31
|
+
print(json.dumps({}))
|
|
32
|
+
return 0
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
prior_retry_pending = False
|
|
36
|
+
if args.event == "AfterAgent":
|
|
37
|
+
prior_retry_pending = _session_has_pending_after_agent_retry(
|
|
38
|
+
root=Path(args.root),
|
|
39
|
+
db_path=args.db_path,
|
|
40
|
+
session_id=str(payload.get("session_id") or "").strip(),
|
|
41
|
+
)
|
|
42
|
+
kernel = CortexKernel(root=args.root, config_path=args.config_path, db_path=args.db_path)
|
|
43
|
+
result = kernel.dispatch(args.event, payload)
|
|
44
|
+
print(
|
|
45
|
+
json.dumps(
|
|
46
|
+
_to_gemini_output(
|
|
47
|
+
event=args.event,
|
|
48
|
+
payload=payload,
|
|
49
|
+
result=result,
|
|
50
|
+
prior_retry_pending=prior_retry_pending,
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
return 0
|
|
55
|
+
except Exception as exc: # noqa: BLE001
|
|
56
|
+
print(f"[cortex] Gemini bridge error: {exc}", file=sys.stderr)
|
|
57
|
+
return 1
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _parse_args(argv: list[str] | None) -> argparse.Namespace:
|
|
61
|
+
parser = argparse.ArgumentParser(add_help=False)
|
|
62
|
+
parser.add_argument("event")
|
|
63
|
+
parser.add_argument("--root", default=".")
|
|
64
|
+
parser.add_argument("--config-path")
|
|
65
|
+
parser.add_argument("--db-path")
|
|
66
|
+
return parser.parse_args(argv)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _read_payload() -> dict[str, Any]:
|
|
70
|
+
raw = sys.stdin.read().strip()
|
|
71
|
+
if not raw:
|
|
72
|
+
return {}
|
|
73
|
+
data = json.loads(raw)
|
|
74
|
+
if not isinstance(data, dict):
|
|
75
|
+
raise ValueError("Gemini hook payload must be a JSON object")
|
|
76
|
+
return data
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _to_gemini_output(
|
|
80
|
+
*,
|
|
81
|
+
event: str,
|
|
82
|
+
payload: dict[str, Any],
|
|
83
|
+
result: dict[str, Any],
|
|
84
|
+
prior_retry_pending: bool = False,
|
|
85
|
+
) -> dict[str, Any]:
|
|
86
|
+
warnings = [str(item).strip() for item in (result.get("warnings") or []) if str(item).strip()]
|
|
87
|
+
if event == "SessionStart":
|
|
88
|
+
return _session_start_output(result=result, warnings=warnings)
|
|
89
|
+
proceed = bool(result.get("proceed", True))
|
|
90
|
+
if event == "AfterAgent" and _is_stuck_result(result):
|
|
91
|
+
reason = _stuck_reason(result, warnings=warnings)
|
|
92
|
+
return _attach_advisories(
|
|
93
|
+
{"continue": False, "stopReason": reason},
|
|
94
|
+
warnings=warnings,
|
|
95
|
+
primary=reason,
|
|
96
|
+
)
|
|
97
|
+
if event == "AfterAgent" and _needs_after_agent_retry(result, proceed=proceed):
|
|
98
|
+
reason = _retry_reason_from_result(result, warnings=warnings)
|
|
99
|
+
if _requires_session_stop(result):
|
|
100
|
+
return _attach_advisories(
|
|
101
|
+
{"continue": False, "stopReason": reason},
|
|
102
|
+
warnings=warnings,
|
|
103
|
+
primary=reason,
|
|
104
|
+
)
|
|
105
|
+
if bool(payload.get("stop_hook_active")) or prior_retry_pending:
|
|
106
|
+
return _attach_advisories(
|
|
107
|
+
{"continue": False, "stopReason": RETRY_STOP_REASON},
|
|
108
|
+
warnings=warnings,
|
|
109
|
+
primary=RETRY_STOP_REASON,
|
|
110
|
+
)
|
|
111
|
+
return _attach_advisories({"decision": "deny", "reason": reason}, warnings=warnings, primary=reason)
|
|
112
|
+
if not proceed:
|
|
113
|
+
reason = _primary_reason(event=event, warnings=warnings, result=result)
|
|
114
|
+
return _attach_advisories({"decision": "deny", "reason": reason}, warnings=warnings, primary=reason)
|
|
115
|
+
if warnings:
|
|
116
|
+
return {"systemMessage": _warnings_message(warnings)}
|
|
117
|
+
return {}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _before_agent_output(payload: dict[str, Any]) -> dict[str, Any]:
|
|
121
|
+
_part_a, part_b = get_base_executive_function()
|
|
122
|
+
if _payload_already_contains_anchor(payload, part_b):
|
|
123
|
+
return {}
|
|
124
|
+
return {"hookSpecificOutput": {"additionalContext": part_b}}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _payload_already_contains_anchor(payload: dict[str, Any], anchor: str) -> bool:
|
|
128
|
+
if not anchor:
|
|
129
|
+
return False
|
|
130
|
+
candidates = [payload.get("prompt"), payload.get("message"), payload.get("input")]
|
|
131
|
+
for candidate in candidates:
|
|
132
|
+
if isinstance(candidate, str) and anchor in candidate:
|
|
133
|
+
return True
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _session_start_output(*, result: dict[str, Any], warnings: list[str]) -> dict[str, Any]:
|
|
138
|
+
response: dict[str, Any] = {}
|
|
139
|
+
raw_blocks = result.get("context_blocks")
|
|
140
|
+
context_blocks: list[str] = []
|
|
141
|
+
if isinstance(raw_blocks, list):
|
|
142
|
+
context_blocks = [str(item).strip() for item in raw_blocks if isinstance(item, str) and item.strip()]
|
|
143
|
+
if context_blocks:
|
|
144
|
+
response["hookSpecificOutput"] = {"additionalContext": "\n\n".join(context_blocks)}
|
|
145
|
+
if warnings:
|
|
146
|
+
response["systemMessage"] = _warnings_message(warnings)
|
|
147
|
+
return response
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _requires_session_stop(result: dict[str, Any]) -> bool:
|
|
151
|
+
if _is_stuck_result(result):
|
|
152
|
+
return True
|
|
153
|
+
if bool(result.get("terminate_session")):
|
|
154
|
+
return True
|
|
155
|
+
invariant_report = result.get("invariant_report")
|
|
156
|
+
if isinstance(invariant_report, dict) and invariant_report.get("ok") is False:
|
|
157
|
+
return True
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _is_stuck_result(result: dict[str, Any]) -> bool:
|
|
162
|
+
return bool(result.get("stuck_declared")) or str(result.get("feedback_mode") or "") == "stuck"
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _needs_after_agent_retry(result: dict[str, Any], *, proceed: bool) -> bool:
|
|
166
|
+
if not proceed:
|
|
167
|
+
return True
|
|
168
|
+
if bool(result.get("structured_stop_violation")):
|
|
169
|
+
return True
|
|
170
|
+
if bool(result.get("challenge_coverage_missing")):
|
|
171
|
+
return True
|
|
172
|
+
if bool(result.get("requirements_gate_gap")):
|
|
173
|
+
return True
|
|
174
|
+
challenge_report = result.get("challenge_report")
|
|
175
|
+
if isinstance(challenge_report, dict) and challenge_report.get("ok") is False:
|
|
176
|
+
return True
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _retry_reason_from_result(result: dict[str, Any], *, warnings: list[str]) -> str:
|
|
181
|
+
if bool(result.get("structured_stop_violation")):
|
|
182
|
+
return "Structured stop fields are required. Include STOP_FIELDS_JSON in the final response."
|
|
183
|
+
challenge_report = result.get("challenge_report")
|
|
184
|
+
if isinstance(challenge_report, dict) and isinstance(challenge_report.get("missing_categories"), list):
|
|
185
|
+
missing = [str(item).strip() for item in challenge_report["missing_categories"] if str(item).strip()]
|
|
186
|
+
if missing:
|
|
187
|
+
return "Missing challenge coverage for: " + ", ".join(missing)
|
|
188
|
+
if bool(result.get("challenge_coverage_missing")):
|
|
189
|
+
return "Missing challenge_coverage in stop fields. Include all active challenge categories."
|
|
190
|
+
if bool(result.get("requirements_gate_gap")):
|
|
191
|
+
requirement_report = result.get("requirement_audit_report")
|
|
192
|
+
if isinstance(requirement_report, dict):
|
|
193
|
+
req_errors = [str(item).strip() for item in (requirement_report.get("errors") or []) if str(item).strip()]
|
|
194
|
+
if req_errors:
|
|
195
|
+
return "Requirement evidence gaps: " + "; ".join(req_errors[:2])
|
|
196
|
+
truth_claims_report = result.get("truth_claims_report")
|
|
197
|
+
if isinstance(truth_claims_report, dict):
|
|
198
|
+
truth_errors = [str(item).strip() for item in (truth_claims_report.get("errors") or []) if str(item).strip()]
|
|
199
|
+
if truth_errors:
|
|
200
|
+
return "Truth-claim evidence gaps: " + "; ".join(truth_errors[:2])
|
|
201
|
+
if warnings:
|
|
202
|
+
return warnings[0]
|
|
203
|
+
if bool(result.get("requirements_gate_gap")):
|
|
204
|
+
return "Requirement/truth claims are incomplete or unverified. Provide explicit evidence in stop fields."
|
|
205
|
+
return "Cortex stop path failed."
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _stuck_reason(result: dict[str, Any], *, warnings: list[str]) -> str:
|
|
209
|
+
stuck = result.get("stuck_declaration")
|
|
210
|
+
if isinstance(stuck, dict):
|
|
211
|
+
check = str(stuck.get("check") or "").strip()
|
|
212
|
+
obstacle = str(stuck.get("obstacle") or "").strip()
|
|
213
|
+
if check and obstacle:
|
|
214
|
+
return f"Cortex reported stuck on {check}: {obstacle}"
|
|
215
|
+
if obstacle:
|
|
216
|
+
return f"Cortex reported stuck: {obstacle}"
|
|
217
|
+
if warnings:
|
|
218
|
+
return warnings[0]
|
|
219
|
+
return "Cortex reported stuck and could not complete the requested evidence boundary."
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _primary_reason(*, event: str, warnings: list[str], result: dict[str, Any]) -> str:
|
|
223
|
+
if warnings:
|
|
224
|
+
return warnings[0]
|
|
225
|
+
if event == "AfterAgent":
|
|
226
|
+
return "Cortex stop path failed."
|
|
227
|
+
if event == "BeforeTool":
|
|
228
|
+
return "Cortex blocked this tool invocation."
|
|
229
|
+
return f"Cortex denied {event}."
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _warnings_message(warnings: list[str]) -> str:
|
|
233
|
+
return "\n".join(f"[cortex] {warning}" for warning in warnings)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _attach_advisories(response: dict[str, Any], *, warnings: list[str], primary: str) -> dict[str, Any]:
|
|
237
|
+
additional = [warning for warning in warnings if warning and warning != primary]
|
|
238
|
+
if additional:
|
|
239
|
+
response["systemMessage"] = _warnings_message(additional)
|
|
240
|
+
return response
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _session_has_pending_after_agent_retry(*, root: Path, db_path: str | None, session_id: str) -> bool:
|
|
244
|
+
if not session_id:
|
|
245
|
+
return False
|
|
246
|
+
db_file = Path(db_path) if db_path else (root / ".cortex" / "cortex.db")
|
|
247
|
+
if not db_file.exists():
|
|
248
|
+
return False
|
|
249
|
+
try:
|
|
250
|
+
with sqlite3.connect(db_file) as conn:
|
|
251
|
+
row = conn.execute(
|
|
252
|
+
"SELECT metadata_json FROM sessions WHERE session_id = ? LIMIT 1",
|
|
253
|
+
(session_id,),
|
|
254
|
+
).fetchone()
|
|
255
|
+
except sqlite3.Error:
|
|
256
|
+
return False
|
|
257
|
+
if not row or not row[0]:
|
|
258
|
+
return False
|
|
259
|
+
try:
|
|
260
|
+
metadata = json.loads(str(row[0]))
|
|
261
|
+
except (json.JSONDecodeError, TypeError, ValueError):
|
|
262
|
+
return False
|
|
263
|
+
if not isinstance(metadata, dict) or str(metadata.get("hook") or "") != "Stop":
|
|
264
|
+
return False
|
|
265
|
+
if bool(metadata.get("stuck_declared")) or str(metadata.get("feedback_mode") or "") == "stuck":
|
|
266
|
+
return False
|
|
267
|
+
challenge_ok = metadata.get("challenge_ok")
|
|
268
|
+
return (
|
|
269
|
+
bool(metadata.get("structured_stop_violation"))
|
|
270
|
+
or bool(metadata.get("challenge_coverage_missing"))
|
|
271
|
+
or bool(metadata.get("requirements_gate_gap"))
|
|
272
|
+
or challenge_ok is False
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _ensure_session_id(payload: dict[str, Any], *, event: str) -> dict[str, Any]:
|
|
277
|
+
data = dict(payload)
|
|
278
|
+
session_id = str(data.get("session_id") or "").strip()
|
|
279
|
+
if session_id:
|
|
280
|
+
data["session_id"] = session_id
|
|
281
|
+
return data
|
|
282
|
+
basis = "|".join(
|
|
283
|
+
(
|
|
284
|
+
event,
|
|
285
|
+
str(data.get("timestamp") or ""),
|
|
286
|
+
str(data.get("transcript_path") or ""),
|
|
287
|
+
str(data.get("cwd") or ""),
|
|
288
|
+
str(data.get("hook_event_name") or ""),
|
|
289
|
+
)
|
|
290
|
+
)
|
|
291
|
+
fallback = "gemini-fallback-" + hashlib.sha1(basis.encode("utf-8")).hexdigest()[:12]
|
|
292
|
+
data["session_id"] = fallback
|
|
293
|
+
print(
|
|
294
|
+
f"[cortex] warning: Gemini payload missing session_id for {event}; using {fallback}.",
|
|
295
|
+
file=sys.stderr,
|
|
296
|
+
)
|
|
297
|
+
return data
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
if __name__ == "__main__":
|
|
301
|
+
raise SystemExit(main())
|