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,375 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import shlex
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from cortex.core import CortexKernel
|
|
13
|
+
from cortex.stop_payload import parse_stop_fields_json
|
|
14
|
+
|
|
15
|
+
from ._openai_bridge_probe import probe_approval_blocking as _probe_approval_blocking_impl
|
|
16
|
+
from ._openai_bridge_probe import probe_model as _probe_model_impl
|
|
17
|
+
from ._openai_bridge_protocol import (
|
|
18
|
+
AppServerClient,
|
|
19
|
+
BridgeError,
|
|
20
|
+
COMMAND_APPROVAL_METHOD,
|
|
21
|
+
DEFAULT_APPROVAL_POLICY_CANDIDATES,
|
|
22
|
+
FILE_CHANGE_APPROVAL_METHOD,
|
|
23
|
+
execute_turn as _protocol_execute_turn,
|
|
24
|
+
initialize_app_server as _initialize_app_server,
|
|
25
|
+
start_thread_with_policy_fallback,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
SCHEMA_VERSION = "openai_app_server_v1"
|
|
29
|
+
_start_thread_with_policy_fallback = start_thread_with_policy_fallback
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
_STOP_RESULT_FORWARD_KEYS = (
|
|
33
|
+
"session_status",
|
|
34
|
+
"proceed",
|
|
35
|
+
"recommend_revert",
|
|
36
|
+
"feedback_mode",
|
|
37
|
+
"stuck_declared",
|
|
38
|
+
"stuck_declaration",
|
|
39
|
+
"structured_stop_violation",
|
|
40
|
+
"challenge_coverage_missing",
|
|
41
|
+
"requirement_audit_gap",
|
|
42
|
+
"truth_claims_gap",
|
|
43
|
+
"requirements_gate_gap",
|
|
44
|
+
"contract_diagnostic",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _extract_stop_fields_from_final_text(final_text: str) -> tuple[dict[str, Any] | None, str, str]:
|
|
49
|
+
parsed, marker_found, parse_error = parse_stop_fields_json(final_text)
|
|
50
|
+
if parsed is not None:
|
|
51
|
+
return dict(parsed), "payload.stop_fields", ""
|
|
52
|
+
if marker_found:
|
|
53
|
+
return None, "none", str(parse_error or "invalid_stop_fields_json")
|
|
54
|
+
return None, "none", ""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _bridge_stop_summary(stop_result: dict[str, Any]) -> dict[str, Any]:
|
|
58
|
+
summary = {"enforcement_pass": bool(stop_result.get("enforcement_pass"))}
|
|
59
|
+
warnings = stop_result.get("warnings")
|
|
60
|
+
if isinstance(warnings, list):
|
|
61
|
+
normalized_warnings = [str(item) for item in warnings if str(item).strip()]
|
|
62
|
+
if normalized_warnings:
|
|
63
|
+
summary["warnings"] = normalized_warnings
|
|
64
|
+
for key in _STOP_RESULT_FORWARD_KEYS:
|
|
65
|
+
if key in stop_result:
|
|
66
|
+
summary[key] = stop_result[key]
|
|
67
|
+
return summary
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _kernel_pretool_decision(
|
|
71
|
+
*,
|
|
72
|
+
kernel: CortexKernel,
|
|
73
|
+
session_id: str,
|
|
74
|
+
method: str,
|
|
75
|
+
params: dict[str, Any],
|
|
76
|
+
) -> tuple[bool, dict[str, Any]]:
|
|
77
|
+
if method == COMMAND_APPROVAL_METHOD:
|
|
78
|
+
command = str(params.get("command") or "")
|
|
79
|
+
tool_name = "command_execution"
|
|
80
|
+
elif method == FILE_CHANGE_APPROVAL_METHOD:
|
|
81
|
+
command = "file_change"
|
|
82
|
+
tool_name = "file_change"
|
|
83
|
+
else:
|
|
84
|
+
return True, {"warnings": [f"unhandled_approval_method:{method}"]}
|
|
85
|
+
|
|
86
|
+
kernel_response = kernel.dispatch(
|
|
87
|
+
"pre_tool_use",
|
|
88
|
+
{
|
|
89
|
+
"session_id": session_id,
|
|
90
|
+
"tool_name": tool_name,
|
|
91
|
+
"command": command,
|
|
92
|
+
"approval_method": method,
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
return bool(kernel_response.get("proceed", True)), kernel_response
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _handle_post_tool(
|
|
99
|
+
*,
|
|
100
|
+
kernel: CortexKernel,
|
|
101
|
+
session_id: str,
|
|
102
|
+
item: dict[str, Any],
|
|
103
|
+
) -> None:
|
|
104
|
+
if str(item.get("type") or "") != "commandExecution":
|
|
105
|
+
return
|
|
106
|
+
status = str(item.get("status") or "").strip().lower()
|
|
107
|
+
mapped_status = "ok"
|
|
108
|
+
if status in {"failed"}:
|
|
109
|
+
mapped_status = "error"
|
|
110
|
+
elif status in {"declined"}:
|
|
111
|
+
mapped_status = "declined"
|
|
112
|
+
kernel.dispatch(
|
|
113
|
+
"post_tool_use",
|
|
114
|
+
{
|
|
115
|
+
"session_id": session_id,
|
|
116
|
+
"tool_name": "command_execution",
|
|
117
|
+
"status": mapped_status,
|
|
118
|
+
"tool_response": {
|
|
119
|
+
"stdout": str(item.get("aggregatedOutput") or ""),
|
|
120
|
+
"stderr": "",
|
|
121
|
+
"exit_code": item.get("exitCode"),
|
|
122
|
+
},
|
|
123
|
+
"command": str(item.get("command") or ""),
|
|
124
|
+
"cwd": str(item.get("cwd") or ""),
|
|
125
|
+
"raw_status": status,
|
|
126
|
+
},
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _normalize_command_for_witness(command: str) -> str:
|
|
131
|
+
raw = str(command or "").strip()
|
|
132
|
+
if not raw:
|
|
133
|
+
return ""
|
|
134
|
+
try:
|
|
135
|
+
tokens = shlex.split(raw)
|
|
136
|
+
except ValueError:
|
|
137
|
+
return raw
|
|
138
|
+
if len(tokens) >= 3 and Path(tokens[0]).name.lower() in {"bash", "sh", "zsh"} and tokens[1] == "-lc":
|
|
139
|
+
inner = str(tokens[2]).strip()
|
|
140
|
+
return inner or raw
|
|
141
|
+
return raw
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _execute_turn(
|
|
145
|
+
*,
|
|
146
|
+
codex_bin: str,
|
|
147
|
+
cwd: Path,
|
|
148
|
+
prompt: str,
|
|
149
|
+
model: str | None,
|
|
150
|
+
timeout_seconds: float,
|
|
151
|
+
approval_policy_candidates: tuple[str, ...] = DEFAULT_APPROVAL_POLICY_CANDIDATES,
|
|
152
|
+
approval_handler: Any,
|
|
153
|
+
) -> dict[str, Any]:
|
|
154
|
+
return _protocol_execute_turn(
|
|
155
|
+
codex_bin=codex_bin,
|
|
156
|
+
cwd=cwd,
|
|
157
|
+
prompt=prompt,
|
|
158
|
+
model=model,
|
|
159
|
+
timeout_seconds=timeout_seconds,
|
|
160
|
+
approval_policy_candidates=approval_policy_candidates,
|
|
161
|
+
approval_handler=approval_handler,
|
|
162
|
+
client_cls=AppServerClient,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _run_mode(args: argparse.Namespace) -> int:
|
|
167
|
+
cwd = Path(args.cwd).resolve()
|
|
168
|
+
kernel = CortexKernel(root=args.root, config_path=args.config_path, db_path=args.db_path)
|
|
169
|
+
coverage_gaps: list[str] = []
|
|
170
|
+
session_id_holder: dict[str, str] = {"value": ""}
|
|
171
|
+
|
|
172
|
+
def _approval_handler(method: str, params: dict[str, Any]) -> tuple[str, dict[str, Any]]:
|
|
173
|
+
thread_id = str(params.get("threadId") or "").strip()
|
|
174
|
+
if thread_id:
|
|
175
|
+
session_id_holder["value"] = thread_id
|
|
176
|
+
session_id = session_id_holder["value"] or thread_id or f"openai-session-{int(time.time())}"
|
|
177
|
+
proceed, kernel_response = _kernel_pretool_decision(
|
|
178
|
+
kernel=kernel,
|
|
179
|
+
session_id=session_id,
|
|
180
|
+
method=method,
|
|
181
|
+
params=params,
|
|
182
|
+
)
|
|
183
|
+
decision = "accept" if proceed else "decline"
|
|
184
|
+
if method not in {COMMAND_APPROVAL_METHOD, FILE_CHANGE_APPROVAL_METHOD}:
|
|
185
|
+
coverage_gaps.append(f"pre_tool_use_coverage_gap:{method}")
|
|
186
|
+
return decision, kernel_response
|
|
187
|
+
|
|
188
|
+
result = _execute_turn(
|
|
189
|
+
codex_bin=args.codex_bin,
|
|
190
|
+
cwd=cwd,
|
|
191
|
+
prompt=args.prompt,
|
|
192
|
+
model=args.model,
|
|
193
|
+
timeout_seconds=float(args.timeout_seconds),
|
|
194
|
+
approval_policy_candidates=_approval_policy_candidates_from_args(args),
|
|
195
|
+
approval_handler=_approval_handler,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
command_surface = result.get("command_surface") if isinstance(result.get("command_surface"), dict) else {}
|
|
199
|
+
command_items_without_approval = [
|
|
200
|
+
str(item)
|
|
201
|
+
for item in command_surface.get("command_items_without_approval", [])
|
|
202
|
+
if str(item).strip()
|
|
203
|
+
]
|
|
204
|
+
nonblocking_declines = [str(item) for item in command_surface.get("nonblocking_declines", []) if str(item).strip()]
|
|
205
|
+
if command_items_without_approval:
|
|
206
|
+
coverage_gaps.append("pre_tool_use_partial_surface_trusted_commands")
|
|
207
|
+
if nonblocking_declines:
|
|
208
|
+
coverage_gaps.append("pre_tool_use_nonblocking_approval")
|
|
209
|
+
|
|
210
|
+
session_id = session_id_holder["value"] or str(result.get("thread_id") or "")
|
|
211
|
+
approval_command_by_item_id: dict[str, dict[str, str]] = {}
|
|
212
|
+
for request in result.get("approval_requests") or []:
|
|
213
|
+
if not isinstance(request, dict):
|
|
214
|
+
continue
|
|
215
|
+
item_id = str(request.get("item_id") or "").strip()
|
|
216
|
+
if not item_id:
|
|
217
|
+
continue
|
|
218
|
+
approval_command_by_item_id[item_id] = {
|
|
219
|
+
"command": str(request.get("command") or "").strip(),
|
|
220
|
+
"cwd": str(request.get("cwd") or "").strip(),
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for item in result.get("command_completion_items") or []:
|
|
224
|
+
if isinstance(item, dict):
|
|
225
|
+
item_id = str(item.get("item_id") or "").strip()
|
|
226
|
+
completion_command = str(item.get("command") or "").strip()
|
|
227
|
+
completion_cwd = str(item.get("cwd") or "").strip()
|
|
228
|
+
fallback_command = approval_command_by_item_id.get(item_id, {}).get("command", "")
|
|
229
|
+
fallback_cwd = approval_command_by_item_id.get(item_id, {}).get("cwd", "")
|
|
230
|
+
resolved_command = completion_command or fallback_command
|
|
231
|
+
resolved_cwd = completion_cwd or fallback_cwd or str(cwd)
|
|
232
|
+
normalized_command = _normalize_command_for_witness(resolved_command)
|
|
233
|
+
_handle_post_tool(
|
|
234
|
+
kernel=kernel,
|
|
235
|
+
session_id=session_id,
|
|
236
|
+
item={
|
|
237
|
+
"type": "commandExecution",
|
|
238
|
+
"status": item.get("status"),
|
|
239
|
+
"exitCode": item.get("exit_code"),
|
|
240
|
+
"aggregatedOutput": item.get("aggregated_output"),
|
|
241
|
+
"command": normalized_command,
|
|
242
|
+
"cwd": resolved_cwd,
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
final_text = str(result.get("text") or "")
|
|
247
|
+
stop_fields, stop_fields_source, stop_fields_parse_error = _extract_stop_fields_from_final_text(final_text)
|
|
248
|
+
stop_payload: dict[str, Any] = {
|
|
249
|
+
"session_id": session_id,
|
|
250
|
+
"last_assistant_message": final_text,
|
|
251
|
+
"final_text": final_text,
|
|
252
|
+
}
|
|
253
|
+
if stop_fields is not None:
|
|
254
|
+
stop_payload["stop_fields"] = stop_fields
|
|
255
|
+
stop_result = kernel.dispatch(
|
|
256
|
+
"stop",
|
|
257
|
+
stop_payload,
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
response = {
|
|
261
|
+
"ok": True,
|
|
262
|
+
"text": final_text,
|
|
263
|
+
"session_id": session_id,
|
|
264
|
+
"thread_id": result.get("thread_id"),
|
|
265
|
+
"turn_id": result.get("turn_id"),
|
|
266
|
+
"approval_policy_used": result.get("approval_policy_used"),
|
|
267
|
+
"coverage_gaps": sorted(set([*coverage_gaps, *[str(v) for v in result.get("coverage_gaps") or []]])),
|
|
268
|
+
"command_items_with_approval_count": len(command_surface.get("command_items_with_approval", [])),
|
|
269
|
+
"command_items_without_approval_count": len(command_items_without_approval),
|
|
270
|
+
"nonblocking_decline_count": len(nonblocking_declines),
|
|
271
|
+
"duplicate_turn_completed_count": int(result.get("duplicate_turn_completed_count") or 0),
|
|
272
|
+
"approval_request_count": len(result.get("approval_requests") or []),
|
|
273
|
+
"command_completion_count": len(result.get("command_completion_items") or []),
|
|
274
|
+
"stop_fields_present": bool(stop_fields is not None),
|
|
275
|
+
"stop_fields_parse_error": stop_fields_parse_error,
|
|
276
|
+
"stop_fields_source": stop_fields_source,
|
|
277
|
+
"elapsed_seconds": result.get("elapsed_seconds"),
|
|
278
|
+
}
|
|
279
|
+
response.update(_bridge_stop_summary(stop_result))
|
|
280
|
+
print(json.dumps(response, sort_keys=True))
|
|
281
|
+
return 0
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _probe_approval_blocking(args: argparse.Namespace) -> int:
|
|
285
|
+
return _probe_approval_blocking_impl(
|
|
286
|
+
args=args,
|
|
287
|
+
command_approval_method=COMMAND_APPROVAL_METHOD,
|
|
288
|
+
execute_turn=_execute_turn,
|
|
289
|
+
approval_policy_candidates_from_args=_approval_policy_candidates_from_args,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _probe_model(args: argparse.Namespace) -> int:
|
|
294
|
+
return _probe_model_impl(
|
|
295
|
+
args=args,
|
|
296
|
+
app_server_client_cls=AppServerClient,
|
|
297
|
+
initialize_app_server=_initialize_app_server,
|
|
298
|
+
bridge_error_cls=BridgeError,
|
|
299
|
+
run_exec=subprocess.run,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
304
|
+
parser = argparse.ArgumentParser()
|
|
305
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
306
|
+
|
|
307
|
+
run = sub.add_parser("run")
|
|
308
|
+
run.add_argument("--schema-version", choices=[SCHEMA_VERSION], default=SCHEMA_VERSION)
|
|
309
|
+
run.add_argument("--codex-bin", default="codex")
|
|
310
|
+
run.add_argument("--cwd", default=".")
|
|
311
|
+
run.add_argument("--root", default=".")
|
|
312
|
+
run.add_argument("--config-path")
|
|
313
|
+
run.add_argument("--db-path")
|
|
314
|
+
run.add_argument("--model")
|
|
315
|
+
run.add_argument("--prompt", required=True)
|
|
316
|
+
run.add_argument("--timeout-seconds", type=float, default=180.0)
|
|
317
|
+
run.add_argument(
|
|
318
|
+
"--approval-policy-candidates",
|
|
319
|
+
default=",".join(DEFAULT_APPROVAL_POLICY_CANDIDATES),
|
|
320
|
+
help="Comma-delimited thread/start approvalPolicy fallback order.",
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
probe = sub.add_parser("probe-approval-blocking")
|
|
324
|
+
probe.add_argument("--schema-version", choices=[SCHEMA_VERSION], default=SCHEMA_VERSION)
|
|
325
|
+
probe.add_argument("--codex-bin", default="codex")
|
|
326
|
+
probe.add_argument("--cwd", default=".")
|
|
327
|
+
probe.add_argument("--model")
|
|
328
|
+
probe.add_argument("--timeout-seconds", type=float, default=180.0)
|
|
329
|
+
probe.add_argument("--prompt", default="")
|
|
330
|
+
probe.add_argument(
|
|
331
|
+
"--approval-policy-candidates",
|
|
332
|
+
default=",".join(DEFAULT_APPROVAL_POLICY_CANDIDATES),
|
|
333
|
+
help="Comma-delimited thread/start approvalPolicy fallback order.",
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
probe_model = sub.add_parser("probe-model")
|
|
337
|
+
probe_model.add_argument("--schema-version", choices=[SCHEMA_VERSION], default=SCHEMA_VERSION)
|
|
338
|
+
probe_model.add_argument("--codex-bin", default="codex")
|
|
339
|
+
probe_model.add_argument("--cwd", default=".")
|
|
340
|
+
probe_model.add_argument("--model", required=True)
|
|
341
|
+
probe_model.add_argument("--timeout-seconds", type=float, default=180.0)
|
|
342
|
+
|
|
343
|
+
return parser.parse_args(argv)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _approval_policy_candidates_from_args(args: argparse.Namespace) -> tuple[str, ...]:
|
|
347
|
+
raw = getattr(args, "approval_policy_candidates", None)
|
|
348
|
+
if raw is None:
|
|
349
|
+
return DEFAULT_APPROVAL_POLICY_CANDIDATES
|
|
350
|
+
if isinstance(raw, str):
|
|
351
|
+
parsed = tuple(token.strip() for token in raw.split(",") if token.strip())
|
|
352
|
+
return parsed or DEFAULT_APPROVAL_POLICY_CANDIDATES
|
|
353
|
+
if isinstance(raw, (list, tuple)):
|
|
354
|
+
parsed = tuple(str(token).strip() for token in raw if str(token).strip())
|
|
355
|
+
return parsed or DEFAULT_APPROVAL_POLICY_CANDIDATES
|
|
356
|
+
return DEFAULT_APPROVAL_POLICY_CANDIDATES
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def main(argv: list[str] | None = None) -> int:
|
|
360
|
+
args = _parse_args(argv)
|
|
361
|
+
try:
|
|
362
|
+
if args.command == "run":
|
|
363
|
+
return _run_mode(args)
|
|
364
|
+
if args.command == "probe-approval-blocking":
|
|
365
|
+
return _probe_approval_blocking(args)
|
|
366
|
+
if args.command == "probe-model":
|
|
367
|
+
return _probe_model(args)
|
|
368
|
+
raise BridgeError(f"Unsupported command: {args.command}")
|
|
369
|
+
except BridgeError as exc:
|
|
370
|
+
print(json.dumps({"ok": False, "error": str(exc)}), file=sys.stderr)
|
|
371
|
+
return 1
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
if __name__ == "__main__":
|
|
375
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .engine import * # noqa: F401,F403
|