@misterhuydo/sentinel 1.6.2 → 1.6.3

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 CHANGED
@@ -1 +1 @@
1
- 2026-04-24T10:50:33.264Z
1
+ 2026-04-24T11:26:01.385Z
@@ -1,6 +1,6 @@
1
1
  {
2
- "message": "Auto-checkpoint at 2026-04-24T11:12:56.361Z",
3
- "checkpoint_at": "2026-04-24T11:12:56.362Z",
2
+ "message": "Auto-checkpoint at 2026-04-24T11:34:54.330Z",
3
+ "checkpoint_at": "2026-04-24T11:34:54.331Z",
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@misterhuydo/sentinel",
3
- "version": "1.6.2",
3
+ "version": "1.6.3",
4
4
  "description": "Sentinel — Autonomous DevOps Agent installer and manager",
5
5
  "bin": {
6
6
  "sentinel": "./bin/sentinel.js"
@@ -1 +1 @@
1
- __version__ = "1.6.2"
1
+ __version__ = "1.6.3"
@@ -262,6 +262,9 @@ def _is_auth_error(output: str) -> bool:
262
262
  return any(hint in low for hint in _AUTH_ERROR_HINTS)
263
263
 
264
264
 
265
+ _CAIRN_ONLY_MCP_CONFIG = '{"mcpServers":{"cairn":{"command":"cairn-mcp"}}}'
266
+
267
+
265
268
  def _claude_cmd(
266
269
  bin_path: str,
267
270
  prompt: str,
@@ -278,6 +281,14 @@ def _claude_cmd(
278
281
  and MUST be False for the OAuth attempt (otherwise claude refuses to read
279
282
  the cached `claude login` token). The caller picks per attempt.
280
283
 
284
+ For the OAuth path (use_bare=False) we ALSO pass:
285
+ --setting-sources project,local (skip user settings.json — bypasses the
286
+ cairn `minify` / `edit-guard` PreToolUse hooks that block Read/Edit
287
+ with `exit 2` and force Claude to fall back to hand-crafting diffs)
288
+ --mcp-config '{...cairn...}' (re-add cairn MCP tools that we just
289
+ bypassed by skipping user settings — the prompt's cairn_checkpoint
290
+ instruction needs them)
291
+
281
292
  Output is forced to `--output-format json` so the caller can extract the
282
293
  session_id, cost, and result text deterministically.
283
294
  """
@@ -291,6 +302,10 @@ def _claude_cmd(
291
302
  cmd.append("--bare")
292
303
  if skip:
293
304
  cmd.append("--dangerously-skip-permissions")
305
+ if not use_bare:
306
+ # OAuth-mode isolation: skip user-scope cairn hooks, re-load cairn MCP.
307
+ cmd += ["--setting-sources", "project,local"]
308
+ cmd += ["--mcp-config", _CAIRN_ONLY_MCP_CONFIG]
294
309
  if session_id:
295
310
  cmd += ["--resume", session_id]
296
311
  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)