@misterhuydo/sentinel 1.5.8 → 1.5.10

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "message": "Auto-checkpoint at 2026-04-08T10:51:07.409Z",
3
- "checkpoint_at": "2026-04-08T10:51:07.494Z",
2
+ "message": "Auto-checkpoint at 2026-04-08T11:11:26.934Z",
3
+ "checkpoint_at": "2026-04-08T11:11:27.049Z",
4
4
  "active_files": [
5
5
  "J:\\Projects\\Sentinel\\cli\\bin\\sentinel.js",
6
6
  "J:\\Projects\\Sentinel\\cli\\lib\\test.js",
@@ -8,6 +8,8 @@
8
8
  ],
9
9
  "notes": [
10
10
  "[2026-04-08] git-snapshot: .cairn/session.json | 28 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 14 ++-\n cli/.cairn/session.json | 4 +-\n cli/.cairn/views/62a614_bundle.js | 5 +-\n cli/lib/.cairn/minify-map.json | 6 +\n cli/lib/.cairn/views/fb78ac_upgrade.js | 37 +++++-\n cli/lib/.cairn/views/fc4a1a_add.js | 215 +++++++++++++++++++++++++--------\n 9 files changed, 295 insertions(+), 63 deletions(-) | status: M ../.cairn/session.json\n M ../.claude/settings.local.json\n M .cairn/.hint-lock\n M .cairn/minify-map.json\n M .cairn/session.json\n M .cairn/views/62a614_bundle.js\n M lib/.cairn/minify-map.json\n M lib/.cairn/views/fb78ac_upgrade.js\n M lib/.cairn/views/fc4a1a_add.js\n?? ../.cairn/.cairn-project\n?? ../.cairn/memory/\n?? ../.cairn/minify-map.json\n?? ../.cairn/views/\n?? .cairn/views/23edf4_sentinel_boss.py\n?? .cairn/views/5f5141_main.py\n?? .cairn/views/7802b9_cicd_trigger.py\n?? .cairn/views/ac3df4_repo_task_engine.py\n?? lib/.cairn/views/2a85cc_init.js\n?? lib/.cairn/views/e26996_slack-setup.js\n?? ../scripts/fix_ask_codebase_context.py\n?? ../scripts/fix_ask_codebase_stdin.py\n?? ../scripts/fix_chain_slack.py\n?? ../scripts/fix_fstring.py\n?? ../scripts/fix_knowledge_cache.py\n?? ../scripts/fix_knowledge_cache_staleness.py\n?? ../scripts/fix_merge_confirm.py\n?? ../scripts/fix_permission_messages.py\n?? ../scripts/fix_pr_check_head_detect.py\n?? ../scripts/fix_pr_msg_newlines.py\n?? ../scripts/fix_pr_tracking_boss.py\n?? ../scripts/fix_pr_tracking_db.py\n?? ../scripts/fix_pr_tracking_main.py\n?? ../scripts/fix_project_isolation.py\n?? ../scripts/fix_system_prompt.py\n?? ../scripts/fix_two_bugs.py\n?? ../scripts/patch_chain_release.py",
11
+ "[2026-04-08] git-snapshot: .cairn/session.json | 20 ++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 22 +++-\n cli/.cairn/views/62a614_bundle.js | 5 +-\n cli/lib/.cairn/minify-map.json | 6 +\n cli/lib/.cairn/views/fb78ac_upgrade.js | 37 +++++-\n cli/lib/.cairn/views/fc4a1a_add.js | 215 +++++++++++++++++++++++++--------\n 9 files changed, 296 insertions(+), 66 deletions(-) | status: M ../.cairn/session.json\n M ../.claude/settings.local.json\n M .cairn/.hint-lock\n M .cairn/minify-map.json\n M .cairn/session.json\n M .cairn/views/62a614_bundle.js\n M lib/.cairn/minify-map.json\n M lib/.cairn/views/fb78ac_upgrade.js\n M lib/.cairn/views/fc4a1a_add.js\n?? ../.cairn/.cairn-project\n?? ../.cairn/memory/\n?? ../.cairn/minify-map.json\n?? ../.cairn/views/\n?? .cairn/views/23edf4_sentinel_boss.py\n?? .cairn/views/7802b9_cicd_trigger.py\n?? .cairn/views/ac3df4_repo_task_engine.py\n?? lib/.cairn/views/2a85cc_init.js\n?? lib/.cairn/views/e26996_slack-setup.js\n?? ../scripts/fix_ask_codebase_context.py\n?? ../scripts/fix_ask_codebase_stdin.py\n?? ../scripts/fix_chain_slack.py\n?? ../scripts/fix_fstring.py\n?? ../scripts/fix_knowledge_cache.py\n?? ../scripts/fix_knowledge_cache_staleness.py\n?? ../scripts/fix_merge_confirm.py\n?? ../scripts/fix_permission_messages.py\n?? ../scripts/fix_pr_check_head_detect.py\n?? ../scripts/fix_pr_msg_newlines.py\n?? ../scripts/fix_pr_tracking_boss.py\n?? ../scripts/fix_pr_tracking_db.py\n?? ../scripts/fix_pr_tracking_main.py\n?? ../scripts/fix_project_isolation.py\n?? ../scripts/fix_system_prompt.py\n?? ../scripts/fix_two_bugs.py\n?? ../scripts/patch_chain_release.py",
12
+ "[2026-04-08] git-snapshot: .cairn/session.json | 20 ++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 21 +++-\n cli/.cairn/views/62a614_bundle.js | 5 +-\n cli/lib/.cairn/minify-map.json | 6 +\n cli/lib/.cairn/views/fb78ac_upgrade.js | 37 +++++-\n cli/lib/.cairn/views/fc4a1a_add.js | 215 +++++++++++++++++++++++++--------\n 9 files changed, 295 insertions(+), 66 deletions(-) | status: M ../.cairn/session.json\n M ../.claude/settings.local.json\n M .cairn/.hint-lock\n M .cairn/minify-map.json\n M .cairn/session.json\n M .cairn/views/62a614_bundle.js\n M lib/.cairn/minify-map.json\n M lib/.cairn/views/fb78ac_upgrade.js\n M lib/.cairn/views/fc4a1a_add.js\n?? ../.cairn/.cairn-project\n?? ../.cairn/memory/\n?? ../.cairn/minify-map.json\n?? ../.cairn/views/\n?? .cairn/views/23edf4_sentinel_boss.py\n?? .cairn/views/7802b9_cicd_trigger.py\n?? .cairn/views/ac3df4_repo_task_engine.py\n?? lib/.cairn/views/2a85cc_init.js\n?? lib/.cairn/views/e26996_slack-setup.js\n?? ../scripts/fix_ask_codebase_context.py\n?? ../scripts/fix_ask_codebase_stdin.py\n?? ../scripts/fix_chain_slack.py\n?? ../scripts/fix_fstring.py\n?? ../scripts/fix_knowledge_cache.py\n?? ../scripts/fix_knowledge_cache_staleness.py\n?? ../scripts/fix_merge_confirm.py\n?? ../scripts/fix_permission_messages.py\n?? ../scripts/fix_pr_check_head_detect.py\n?? ../scripts/fix_pr_msg_newlines.py\n?? ../scripts/fix_pr_tracking_boss.py\n?? ../scripts/fix_pr_tracking_db.py\n?? ../scripts/fix_pr_tracking_main.py\n?? ../scripts/fix_project_isolation.py\n?? ../scripts/fix_system_prompt.py\n?? ../scripts/fix_two_bugs.py\n?? ../scripts/patch_chain_release.py",
11
13
  "[2026-04-08] git-snapshot: .cairn/session.json | 20 ++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 22 +++-\n cli/.cairn/views/62a614_bundle.js | 5 +-\n cli/lib/.cairn/minify-map.json | 6 +\n cli/lib/.cairn/views/fb78ac_upgrade.js | 37 +++++-\n cli/lib/.cairn/views/fc4a1a_add.js | 215 +++++++++++++++++++++++++--------\n 9 files changed, 296 insertions(+), 66 deletions(-) | status: M ../.cairn/session.json\n M ../.claude/settings.local.json\n M .cairn/.hint-lock\n M .cairn/minify-map.json\n M .cairn/session.json\n M .cairn/views/62a614_bundle.js\n M lib/.cairn/minify-map.json\n M lib/.cairn/views/fb78ac_upgrade.js\n M lib/.cairn/views/fc4a1a_add.js\n?? ../.cairn/.cairn-project\n?? ../.cairn/memory/\n?? ../.cairn/minify-map.json\n?? ../.cairn/views/\n?? .cairn/views/23edf4_sentinel_boss.py\n?? .cairn/views/7802b9_cicd_trigger.py\n?? .cairn/views/ac3df4_repo_task_engine.py\n?? lib/.cairn/views/2a85cc_init.js\n?? lib/.cairn/views/e26996_slack-setup.js\n?? ../scripts/fix_ask_codebase_context.py\n?? ../scripts/fix_ask_codebase_stdin.py\n?? ../scripts/fix_chain_slack.py\n?? ../scripts/fix_fstring.py\n?? ../scripts/fix_knowledge_cache.py\n?? ../scripts/fix_knowledge_cache_staleness.py\n?? ../scripts/fix_merge_confirm.py\n?? ../scripts/fix_permission_messages.py\n?? ../scripts/fix_pr_check_head_detect.py\n?? ../scripts/fix_pr_msg_newlines.py\n?? ../scripts/fix_pr_tracking_boss.py\n?? ../scripts/fix_pr_tracking_db.py\n?? ../scripts/fix_pr_tracking_main.py\n?? ../scripts/fix_project_isolation.py\n?? ../scripts/fix_system_prompt.py\n?? ../scripts/fix_two_bugs.py\n?? ../scripts/patch_chain_release.py"
12
14
  ],
13
15
  "mtime_snapshot": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misterhuydo/sentinel",
3
- "version": "1.5.8",
3
+ "version": "1.5.10",
4
4
  "description": "Sentinel — Autonomous DevOps Agent installer and manager",
5
5
  "bin": {
6
6
  "sentinel": "./bin/sentinel.js"
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  import logging
13
13
  import re
14
+ import subprocess
14
15
  from dataclasses import dataclass, field
15
16
  from pathlib import Path
16
17
 
@@ -59,6 +60,69 @@ def get_release_version(local_path: str) -> str:
59
60
  return get_pom_version(local_path).replace("-SNAPSHOT", "")
60
61
 
61
62
 
63
+ def pull_source_repo(repo: RepoConfig) -> bool:
64
+ """
65
+ Pull latest from remote for source repo before reading version info.
66
+ Returns True on success, False on failure (non-fatal — we continue with local state).
67
+ """
68
+ from .git_manager import _git_env
69
+ env = _git_env(repo)
70
+ r = subprocess.run(
71
+ ["git", "pull", "--rebase", "origin", repo.branch],
72
+ cwd=repo.local_path, env=env, capture_output=True, text=True, timeout=60,
73
+ )
74
+ if r.returncode != 0:
75
+ logger.warning("pull_source_repo: git pull failed for %s: %s", repo.repo_name, r.stderr.strip()[:200])
76
+ return False
77
+ logger.debug("pull_source_repo: %s up to date", repo.repo_name)
78
+ return True
79
+
80
+
81
+ def get_latest_released_version(repo: RepoConfig) -> str:
82
+ """
83
+ Return the latest released version of a Maven repo by inspecting git tags.
84
+ Tags are expected in the form '<artifactId>-<version>' or just '<version>',
85
+ e.g. 'Whydah-TypeLib-3.0.15' or '3.0.15'.
86
+
87
+ Falls back to pom.xml SNAPSHOT-stripped version if no tags are found.
88
+ Always pulls from remote first so the tag list is current.
89
+ """
90
+ from .git_manager import _git_env
91
+ env = _git_env(repo)
92
+ local_path = repo.local_path
93
+
94
+ # Pull so tags are up to date
95
+ pull_source_repo(repo)
96
+
97
+ # Fetch tags explicitly (pull --rebase doesn't always fetch all tags)
98
+ subprocess.run(
99
+ ["git", "fetch", "--tags", "--quiet"],
100
+ cwd=local_path, env=env, capture_output=True, text=True, timeout=30,
101
+ )
102
+
103
+ # List tags sorted by version descending
104
+ r = subprocess.run(
105
+ ["git", "tag", "--sort=-version:refname"],
106
+ cwd=local_path, env=env, capture_output=True, text=True, timeout=15,
107
+ )
108
+ tags = [t.strip() for t in r.stdout.splitlines() if t.strip()]
109
+
110
+ # Look for semver-like version in tags (e.g. "3.0.15" or "TypeLib-3.0.15")
111
+ version_re = re.compile(r"\b(\d+\.\d+\.\d+(?:\.\d+)?)\b")
112
+ for tag in tags:
113
+ m = version_re.search(tag)
114
+ if m:
115
+ return m.group(1)
116
+
117
+ # Fallback: strip -SNAPSHOT from pom.xml version
118
+ fallback = get_release_version(local_path)
119
+ logger.warning(
120
+ "get_latest_released_version: no version tags found for %s, falling back to pom: %s",
121
+ repo.repo_name, fallback,
122
+ )
123
+ return fallback
124
+
125
+
62
126
  def _resolve_property(prop_ref: str, text: str) -> str:
63
127
  """Resolve a Maven ${property.name} reference from the <properties> section."""
64
128
  if not prop_ref.startswith("${"):
@@ -1396,6 +1396,16 @@ async def _repo_task_poll_loop(cfg_loader: ConfigLoader, store: StateStore):
1396
1396
 
1397
1397
  def _log_auth_status(cfg: SentinelConfig) -> None:
1398
1398
  """Log Claude auth configuration at startup and post to Slack if nothing is configured."""
1399
+ # ── Slack channel ID check ────────────────────────────────────────────────
1400
+ ch = (cfg.slack_channel or "").lstrip("#")
1401
+ if ch and not (ch.upper().startswith("C") and len(ch) >= 9):
1402
+ logger.warning(
1403
+ "SLACK_CHANNEL='%s' looks like a channel NAME, not an ID. "
1404
+ "Channel names break when renamed — use the Slack channel ID (starts with C, e.g. C0ANPS9GC3C). "
1405
+ "Progress alerts will fail with channel_not_found until this is corrected.",
1406
+ ch,
1407
+ )
1408
+
1399
1409
  has_api_key = bool(cfg.anthropic_api_key)
1400
1410
  has_claude_bin = bool(shutil.which(cfg.claude_code_bin))
1401
1411
  pro_for_tasks = cfg.claude_pro_for_tasks
@@ -1611,7 +1611,8 @@ _TOOLS = [
1611
1611
  "description": (
1612
1612
  "build: trigger Jenkins build only. "
1613
1613
  "release: trigger Maven Release; auto-cascades if AUTO_PUBLISH=true. "
1614
- "update_deps: update dependency version in target repos (source already released). "
1614
+ "update_deps: update dependency version in target repos source is ALREADY released, do NOT trigger a new release. "
1615
+ "Use this when the user says 'update X to version Y' or 'bump X dep to Y in repo Z'. "
1615
1616
  "release_and_cascade: release source_repo then cascade to all dependents."
1616
1617
  ),
1617
1618
  },
@@ -1619,6 +1620,14 @@ _TOOLS = [
1619
1620
  "type": "string",
1620
1621
  "description": "Repo to build/release, or the repo whose artifact is being updated.",
1621
1622
  },
1623
+ "new_version": {
1624
+ "type": "string",
1625
+ "description": (
1626
+ "Explicit version to use for update_deps (e.g. '3.0.15'). "
1627
+ "Only for update_deps when the user specifies an exact version. "
1628
+ "If omitted, reads current release version from source_repo pom.xml."
1629
+ ),
1630
+ },
1622
1631
  "target_repos": {
1623
1632
  "type": "array",
1624
1633
  "items": {"type": "string"},
@@ -4180,15 +4189,19 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
4180
4189
  })
4181
4190
 
4182
4191
  if operation == "update_deps":
4192
+ from .dependency_manager import get_latest_released_version
4183
4193
  cascade_plan = plan_cascade(source_repo, cfg_loader.repos, target_repos or None)
4184
4194
  if "error" in cascade_plan:
4185
4195
  return json.dumps(cascade_plan)
4186
4196
  if not cascade_plan["dependents"]:
4187
4197
  return json.dumps({"note": f"No repos depend on {cascade_plan['artifact_id']} — nothing to update."})
4198
+ # Use explicit version from user if provided; otherwise pull + detect from git tags
4199
+ explicit_ver = (inputs.get("new_version") or "").strip()
4200
+ plan_version = explicit_ver or get_latest_released_version(repo)
4188
4201
  return json.dumps({
4189
- "plan": f"Update {cascade_plan['artifact_id']} to {cascade_plan['new_version']} in dependent repos",
4202
+ "plan": f"Update {cascade_plan['artifact_id']} to {plan_version} in dependent repos (no release triggered)",
4190
4203
  "artifact_id": cascade_plan["artifact_id"],
4191
- "new_version": cascade_plan["new_version"],
4204
+ "new_version": plan_version,
4192
4205
  "targets": cascade_plan["dependents"],
4193
4206
  "confirm_prompt": "Reply with confirmed=true to proceed.",
4194
4207
  })
@@ -4227,8 +4240,10 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
4227
4240
  return json.dumps({"status": "released", "repo": source_repo, "note": "Cascade will run automatically on next poll if AUTO_PUBLISH=true."})
4228
4241
 
4229
4242
  if operation == "update_deps":
4243
+ from .dependency_manager import get_latest_released_version
4230
4244
  artifact_id = get_artifact_id(repo.local_path)
4231
- new_version = get_release_version(repo.local_path)
4245
+ # Prefer explicit version; otherwise pull + detect from git tags (most accurate)
4246
+ new_version = (inputs.get("new_version") or "").strip() or get_latest_released_version(repo)
4232
4247
  if not artifact_id or not new_version:
4233
4248
  return json.dumps({"error": f"Could not read artifact/version from {source_repo}/pom.xml"})
4234
4249
  target_names = target_repos or None