@misterhuydo/sentinel 1.6.2 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cairn/.hint-lock +1 -1
- package/.cairn/session.json +2 -2
- package/package.json +1 -1
- package/python/sentinel/__init__.py +1 -1
- package/python/sentinel/__pycache__/__init__.cpython-311.pyc +0 -0
- package/python/sentinel/__pycache__/fix_engine.cpython-311.pyc +0 -0
- package/python/sentinel/fix_engine.py +20 -4
- package/python/tests/test_fix_engine_cmd.py +37 -0
package/.cairn/.hint-lock
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-04-
|
|
1
|
+
2026-04-24T12:01:49.183Z
|
package/.cairn/session.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"message": "Auto-checkpoint at 2026-04-
|
|
3
|
-
"checkpoint_at": "2026-04-
|
|
2
|
+
"message": "Auto-checkpoint at 2026-04-24T12:05:54.299Z",
|
|
3
|
+
"checkpoint_at": "2026-04-24T12:05:54.301Z",
|
|
4
4
|
"active_files": [
|
|
5
5
|
"J:\\Projects\\Sentinel\\cli\\bin\\sentinel.js",
|
|
6
6
|
"J:\\Projects\\Sentinel\\cli\\lib\\test.js",
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.6.
|
|
1
|
+
__version__ = "1.6.4"
|
|
Binary file
|
|
Binary file
|
|
@@ -220,10 +220,11 @@ def _build_prompt(
|
|
|
220
220
|
" BOSS_ESCALATE: <description of what needs to change in Sentinel>",
|
|
221
221
|
" This escalates to Patch, the Sentinel dev agent, who will implement it.",
|
|
222
222
|
"",
|
|
223
|
-
"FINAL
|
|
224
|
-
"
|
|
225
|
-
"
|
|
226
|
-
"
|
|
223
|
+
"CRITICAL — your FINAL message must be the patch itself",
|
|
224
|
+
" The unified diff (with the `# Affected repos:` header for multi-repo) MUST be",
|
|
225
|
+
" the very last text you emit. Do NOT call any tool (including cairn_checkpoint)",
|
|
226
|
+
" after the diff — Sentinel only reads the FINAL assistant message and a trailing",
|
|
227
|
+
" tool call leaves the result field empty.",
|
|
227
228
|
]
|
|
228
229
|
return "\n".join(lines_out)
|
|
229
230
|
|
|
@@ -262,6 +263,9 @@ def _is_auth_error(output: str) -> bool:
|
|
|
262
263
|
return any(hint in low for hint in _AUTH_ERROR_HINTS)
|
|
263
264
|
|
|
264
265
|
|
|
266
|
+
_CAIRN_ONLY_MCP_CONFIG = '{"mcpServers":{"cairn":{"command":"cairn-mcp"}}}'
|
|
267
|
+
|
|
268
|
+
|
|
265
269
|
def _claude_cmd(
|
|
266
270
|
bin_path: str,
|
|
267
271
|
prompt: str,
|
|
@@ -278,6 +282,14 @@ def _claude_cmd(
|
|
|
278
282
|
and MUST be False for the OAuth attempt (otherwise claude refuses to read
|
|
279
283
|
the cached `claude login` token). The caller picks per attempt.
|
|
280
284
|
|
|
285
|
+
For the OAuth path (use_bare=False) we ALSO pass:
|
|
286
|
+
--setting-sources project,local (skip user settings.json — bypasses the
|
|
287
|
+
cairn `minify` / `edit-guard` PreToolUse hooks that block Read/Edit
|
|
288
|
+
with `exit 2` and force Claude to fall back to hand-crafting diffs)
|
|
289
|
+
--mcp-config '{...cairn...}' (re-add cairn MCP tools that we just
|
|
290
|
+
bypassed by skipping user settings — the prompt's cairn_checkpoint
|
|
291
|
+
instruction needs them)
|
|
292
|
+
|
|
281
293
|
Output is forced to `--output-format json` so the caller can extract the
|
|
282
294
|
session_id, cost, and result text deterministically.
|
|
283
295
|
"""
|
|
@@ -291,6 +303,10 @@ def _claude_cmd(
|
|
|
291
303
|
cmd.append("--bare")
|
|
292
304
|
if skip:
|
|
293
305
|
cmd.append("--dangerously-skip-permissions")
|
|
306
|
+
if not use_bare:
|
|
307
|
+
# OAuth-mode isolation: skip user-scope cairn hooks, re-load cairn MCP.
|
|
308
|
+
cmd += ["--setting-sources", "project,local"]
|
|
309
|
+
cmd += ["--mcp-config", _CAIRN_ONLY_MCP_CONFIG]
|
|
294
310
|
if session_id:
|
|
295
311
|
cmd += ["--resume", session_id]
|
|
296
312
|
cmd += ["--output-format", "json", "--print", prompt]
|
|
@@ -51,3 +51,40 @@ def test_print_and_prompt_are_last():
|
|
|
51
51
|
cmd = _claude_cmd("claude", "the actual prompt", use_bare=False)
|
|
52
52
|
assert cmd[-2] == "--print"
|
|
53
53
|
assert cmd[-1] == "the actual prompt"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ── OAuth-mode isolation (skip user settings, keep cairn MCP) ─────────────────
|
|
57
|
+
|
|
58
|
+
def test_oauth_mode_skips_user_settings_to_avoid_cairn_hooks():
|
|
59
|
+
"""Cairn PreToolUse hooks live in user settings.json and block Read/Edit
|
|
60
|
+
for OAuth mode. --setting-sources project,local bypasses them."""
|
|
61
|
+
cmd = _claude_cmd("claude", "x", use_bare=False)
|
|
62
|
+
assert "--setting-sources" in cmd
|
|
63
|
+
i = cmd.index("--setting-sources")
|
|
64
|
+
assert cmd[i + 1] == "project,local"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_bare_mode_does_not_set_setting_sources():
|
|
68
|
+
"""--bare already skips hooks; no need for --setting-sources, and avoiding
|
|
69
|
+
it keeps the cmd surface identical to legacy behaviour."""
|
|
70
|
+
cmd = _claude_cmd("claude", "x", use_bare=True)
|
|
71
|
+
assert "--setting-sources" not in cmd
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_oauth_mode_loads_cairn_mcp_via_inline_config():
|
|
75
|
+
"""When user settings are skipped, cairn MCP tools must be re-enabled
|
|
76
|
+
explicitly via --mcp-config so the prompt's cairn_checkpoint instruction works."""
|
|
77
|
+
cmd = _claude_cmd("claude", "x", use_bare=False)
|
|
78
|
+
# Either --mcp-config <json> or --mcp-config=<json>
|
|
79
|
+
found = False
|
|
80
|
+
for i, tok in enumerate(cmd):
|
|
81
|
+
if tok == "--mcp-config" and i + 1 < len(cmd) and "cairn" in cmd[i + 1]:
|
|
82
|
+
found = True; break
|
|
83
|
+
if tok.startswith("--mcp-config=") and "cairn" in tok:
|
|
84
|
+
found = True; break
|
|
85
|
+
assert found, f"--mcp-config with cairn missing from cmd: {cmd}"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_bare_mode_does_not_set_mcp_config():
|
|
89
|
+
cmd = _claude_cmd("claude", "x", use_bare=True)
|
|
90
|
+
assert not any(tok.startswith("--mcp-config") for tok in cmd)
|