@misterhuydo/sentinel 1.5.13 → 1.5.15

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-08T14:01:40.656Z
1
+ 2026-04-08T14:32:32.252Z
@@ -1,6 +1,6 @@
1
1
  {
2
- "message": "Auto-checkpoint at 2026-04-08T13:56:15.763Z",
3
- "checkpoint_at": "2026-04-08T13:56:15.844Z",
2
+ "message": "Auto-checkpoint at 2026-04-08T14:30:49.032Z",
3
+ "checkpoint_at": "2026-04-08T14:30:49.109Z",
4
4
  "active_files": [
5
5
  "J:\\Projects\\Sentinel\\cli\\bin\\sentinel.js",
6
6
  "J:\\Projects\\Sentinel\\cli\\lib\\test.js",
@@ -16,7 +16,11 @@
16
16
  "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 25 +++-\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, 308 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",
17
17
  "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 26 +++-\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, 309 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",
18
18
  "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 27 ++++-\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, 310 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",
19
- "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 28 ++++-\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, 311 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"
19
+ "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 28 ++++-\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, 311 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",
20
+ "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 29 ++++-\n cli/.cairn/views/62a614_bundle.js | 6 +-\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, 313 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",
21
+ "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 30 ++++-\n cli/.cairn/views/62a614_bundle.js | 6 +-\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, 314 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",
22
+ "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 31 ++++-\n cli/.cairn/views/62a614_bundle.js | 6 +-\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, 315 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",
23
+ "[2026-04-08] git-snapshot: .cairn/session.json | 29 ++++-\n .claude/settings.local.json | 47 ++++++-\n cli/.cairn/.hint-lock | 2 +-\n cli/.cairn/minify-map.json | 8 +-\n cli/.cairn/session.json | 32 ++++-\n cli/.cairn/views/62a614_bundle.js | 6 +-\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, 316 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"
20
24
  ],
21
25
  "mtime_snapshot": {
22
26
  "J:\\Projects\\Sentinel\\cli\\bin\\sentinel.js": 1774252515044.4768,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misterhuydo/sentinel",
3
- "version": "1.5.13",
3
+ "version": "1.5.15",
4
4
  "description": "Sentinel — Autonomous DevOps Agent installer and manager",
5
5
  "bin": {
6
6
  "sentinel": "./bin/sentinel.js"
@@ -1 +1 @@
1
- __version__ = "1.5.13"
1
+ __version__ = "1.5.15"
@@ -80,6 +80,7 @@ class SentinelConfig:
80
80
  sentinel_dev_repo_path: str = "" # path to Sentinel source repo for Dev Claude
81
81
  sentinel_dev_soak_minutes: int = 30 # minutes to monitor after a Patch restart before publishing
82
82
  sentinel_dev_auto_publish: bool = False # if True, auto-publish to npm after clean soak
83
+ auto_publish: bool = False # project-level default; repos inherit this if AUTO_PUBLISH not set in their config
83
84
 
84
85
 
85
86
  @dataclass
@@ -108,7 +109,7 @@ class RepoConfig:
108
109
  repo_url: str = ""
109
110
  local_path: str = ""
110
111
  branch: str = "main"
111
- auto_publish: bool = False
112
+ auto_publish: bool | None = None # None = inherit from SentinelConfig.auto_publish; explicit True/False overrides
112
113
  cicd_type: str = ""
113
114
  cicd_job_url: str = ""
114
115
  cicd_user: str = "" # Jenkins username for Basic auth (defaults to "sentinel")
@@ -237,6 +238,8 @@ class ConfigLoader:
237
238
  c.sentinel_dev_repo_path = d.get("SENTINEL_DEV_REPO_PATH", "")
238
239
  c.sentinel_dev_soak_minutes = int(d.get("SENTINEL_DEV_SOAK_MINUTES", 30))
239
240
  c.sentinel_dev_auto_publish = d.get("SENTINEL_DEV_AUTO_PUBLISH", "false").lower() == "true"
241
+ if "AUTO_PUBLISH" in d:
242
+ c.auto_publish = d["AUTO_PUBLISH"].lower() == "true"
240
243
  self.sentinel = c
241
244
 
242
245
  def _load_log_sources(self):
@@ -286,7 +289,7 @@ class ConfigLoader:
286
289
  r.repo_url = d.get("REPO_URL", "")
287
290
  r.local_path = str(Path(self.config_dir).parent / "repos" / r.repo_name)
288
291
  r.branch = d.get("BRANCH", "main")
289
- r.auto_publish = d.get("AUTO_PUBLISH", "false").lower() == "true"
292
+ r.auto_publish = bool(d["AUTO_PUBLISH"].lower() == "true") if "AUTO_PUBLISH" in d else None
290
293
  r.cicd_type = d.get("CICD_TYPE", "")
291
294
  r.cicd_job_url = d.get("CICD_JOB_URL", "")
292
295
  r.cicd_user = d.get("CICD_USER", "")
@@ -312,3 +315,17 @@ class ConfigLoader:
312
315
  def _on_sighup(self, *_):
313
316
  logger.info("SIGHUP received — reloading config")
314
317
  self.load()
318
+
319
+
320
+ def resolve_auto_publish(repo: "RepoConfig", sentinel: "SentinelConfig") -> bool:
321
+ """
322
+ Three-level AUTO_PUBLISH resolution:
323
+ 1. Repo-level explicit value (if AUTO_PUBLISH is set in the repo .properties file)
324
+ 2. Project-level default (AUTO_PUBLISH in sentinel.properties)
325
+ 3. System default: False
326
+
327
+ None on repo.auto_publish means "not explicitly set — inherit from project".
328
+ """
329
+ if repo.auto_publish is not None:
330
+ return repo.auto_publish
331
+ return sentinel.auto_publish
@@ -275,8 +275,8 @@ def plan_cascade(
275
275
  {
276
276
  "repo": r.repo_name,
277
277
  "current_version": v,
278
- "auto_publish": r.auto_publish,
279
- "action": "push to main" if r.auto_publish else "open PR",
278
+ "auto_publish": bool(r.auto_publish),
279
+ "action": "push to main" if r.auto_publish else "open PR (AUTO_PUBLISH not set — inherits project default)",
280
280
  }
281
281
  for r, v in all_dependents
282
282
  ],
@@ -15,7 +15,7 @@ from pathlib import Path
15
15
 
16
16
  import requests
17
17
 
18
- from .config_loader import RepoConfig, SentinelConfig
18
+ from .config_loader import RepoConfig, SentinelConfig, resolve_auto_publish
19
19
  from .log_parser import ErrorEvent
20
20
 
21
21
  logger = logging.getLogger(__name__)
@@ -258,8 +258,9 @@ def push_dep_update(
258
258
  """
259
259
  env = _git_env(repo)
260
260
  local_path = repo.local_path
261
+ auto_publish = resolve_auto_publish(repo, cfg)
261
262
 
262
- if repo.auto_publish:
263
+ if auto_publish:
263
264
  r = _git(["push", "origin", repo.branch], cwd=local_path, env=env)
264
265
  if r.returncode != 0:
265
266
  logger.warning(
@@ -354,8 +355,9 @@ def publish(
354
355
  """
355
356
  env = _git_env(repo)
356
357
  local_path = repo.local_path
358
+ auto_publish = resolve_auto_publish(repo, cfg)
357
359
 
358
- if not repo.auto_publish:
360
+ if not auto_publish:
359
361
  if remote_fix_exists(repo, event.fingerprint, cfg):
360
362
  logger.info(
361
363
  "Remote fix branch already exists for %s — skipping duplicate push",
@@ -363,7 +365,7 @@ def publish(
363
365
  )
364
366
  return "", ""
365
367
 
366
- if repo.auto_publish:
368
+ if auto_publish:
367
369
  r = _git(["push", "origin", repo.branch], cwd=local_path, env=env)
368
370
  if r.returncode != 0:
369
371
  logger.error("git push failed:\n%s", r.stderr)
@@ -21,7 +21,7 @@ from datetime import datetime, timezone
21
21
  from pathlib import Path
22
22
 
23
23
  from .cairn_client import ensure_installed as cairn_installed, index_repo
24
- from .config_loader import ConfigLoader, SentinelConfig
24
+ from .config_loader import ConfigLoader, SentinelConfig, resolve_auto_publish
25
25
  from .fix_engine import generate_fix
26
26
  from .git_manager import apply_and_commit, publish, _git_env, MissingToolError, MavenAuthError, poll_open_prs
27
27
  from .cicd_trigger import trigger as cicd_trigger
@@ -183,6 +183,8 @@ async def _handle_error(event: ErrorEvent, cfg_loader: ConfigLoader, store: Stat
183
183
  if not repo:
184
184
  return
185
185
 
186
+ auto_publish = resolve_auto_publish(repo, sentinel)
187
+
186
188
  # ── Dismissed errors — skip silently (human explicitly said so) ───────────
187
189
  if store.is_dismissed(event.fingerprint):
188
190
  logger.debug("Error %s is dismissed — skipping", event.fingerprint)
@@ -193,8 +195,8 @@ async def _handle_error(event: ErrorEvent, cfg_loader: ConfigLoader, store: Stat
193
195
  return
194
196
 
195
197
  # ── Determine what we can do before alerting ──────────────────────────────
196
- cannot_fix = event.is_infra_issue or (event.severity == "CRITICAL" and repo.auto_publish)
197
- fix_status = "cannot_fix" if cannot_fix else ("will_fix_pr" if not repo.auto_publish else "attempting")
198
+ cannot_fix = event.is_infra_issue or (event.severity == "CRITICAL" and auto_publish)
199
+ fix_status = "cannot_fix" if cannot_fix else ("will_fix_pr" if not auto_publish else "attempting")
198
200
 
199
201
  stack_lines = getattr(event, "stack_trace", None)
200
202
  stack_preview = ""
@@ -227,7 +229,7 @@ async def _handle_error(event: ErrorEvent, cfg_loader: ConfigLoader, store: Stat
227
229
  store.record_fix(event.fingerprint, "skipped", repo_name=repo.repo_name)
228
230
  return
229
231
 
230
- if event.severity == "CRITICAL" and repo.auto_publish:
232
+ if event.severity == "CRITICAL" and auto_publish:
231
233
  logger.warning("CRITICAL in auto-publish repo '%s' — alerted, human review needed", repo.repo_name)
232
234
  store.record_fix(event.fingerprint, "skipped", repo_name=repo.repo_name)
233
235
  return
@@ -303,7 +305,7 @@ async def _handle_error(event: ErrorEvent, cfg_loader: ConfigLoader, store: Stat
303
305
  branch, pr_url = publish(event, repo, sentinel, commit_hash)
304
306
  store.record_fix(
305
307
  event.fingerprint,
306
- "applied" if repo.auto_publish else "pending",
308
+ "applied" if auto_publish else "pending",
307
309
  patch_path=str(patch_path),
308
310
  commit_hash=commit_hash,
309
311
  branch=branch,
@@ -328,11 +330,11 @@ async def _handle_error(event: ErrorEvent, cfg_loader: ConfigLoader, store: Stat
328
330
  "commit_hash": commit_hash,
329
331
  "branch": branch,
330
332
  "pr_url": pr_url,
331
- "auto_publish": repo.auto_publish,
333
+ "auto_publish": auto_publish,
332
334
  "files_changed": [],
333
335
  })
334
336
 
335
- if repo.auto_publish:
337
+ if auto_publish:
336
338
  ok = cicd_trigger(repo, store, event.fingerprint)
337
339
  if ok and repo.cicd_type.lower() in ("jenkins_release", "jenkins-release"):
338
340
  _run_cascade(repo, sentinel, cfg_loader)
@@ -373,6 +375,8 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
373
375
  )
374
376
  return # Leave the file so admin can add the header
375
377
 
378
+ auto_publish = resolve_auto_publish(repo, sentinel)
379
+
376
380
  # Post "working on" to channel and capture thread_ts for progress replies
377
381
  from .notify import slack_alert as _slack_alert, slack_thread_reply as _slack_reply
378
382
  _submitter = getattr(event, "submitter_user_id", "")
@@ -434,7 +438,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
434
438
  branch, pr_url = publish(event, repo, sentinel, commit_hash)
435
439
  store.record_fix(
436
440
  event.fingerprint,
437
- "applied" if repo.auto_publish else "pending",
441
+ "applied" if auto_publish else "pending",
438
442
  patch_path=str(patch_path),
439
443
  commit_hash=commit_hash,
440
444
  branch=branch,
@@ -453,7 +457,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
453
457
  "commit_hash": commit_hash,
454
458
  "branch": branch,
455
459
  "pr_url": pr_url,
456
- "auto_publish": repo.auto_publish,
460
+ "auto_publish": auto_publish,
457
461
  "files_changed": [],
458
462
  })
459
463
  if pr_url:
@@ -463,7 +467,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
463
467
  submitter_user_id=submitter_uid, origin_channel=_origin_channel)
464
468
  mark_done(event.issue_file)
465
469
 
466
- if repo.auto_publish:
470
+ if auto_publish:
467
471
  ok = cicd_trigger(repo, store, event.fingerprint)
468
472
  if ok:
469
473
  _progress(f":rocket: Release triggered via {repo.cicd_type}")
@@ -525,7 +529,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
525
529
  branch, pr_url = publish(event, repo, sentinel, commit_hash)
526
530
  store.record_fix(
527
531
  event.fingerprint,
528
- "applied" if repo.auto_publish else "pending",
532
+ "applied" if auto_publish else "pending",
529
533
  patch_path=str(patch_path), commit_hash=commit_hash,
530
534
  branch=branch, pr_url=pr_url, repo_name=repo.repo_name, sentinel_marker=marker,
531
535
  )
@@ -535,7 +539,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
535
539
  "message": event.message, "stack_trace": event.body,
536
540
  "repo_name": repo.repo_name, "commit_hash": commit_hash,
537
541
  "branch": branch, "pr_url": pr_url,
538
- "auto_publish": repo.auto_publish, "files_changed": [],
542
+ "auto_publish": auto_publish, "files_changed": [],
539
543
  })
540
544
  if pr_url:
541
545
  _progress(f":arrow_right: <{pr_url}|PR opened> — awaiting review")
@@ -543,7 +547,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
543
547
  repo_name=repo.repo_name, branch=branch, pr_url=pr_url,
544
548
  submitter_user_id=submitter_uid, origin_channel=_origin_channel)
545
549
  mark_done(event.issue_file)
546
- if repo.auto_publish:
550
+ if auto_publish:
547
551
  ok = cicd_trigger(repo, store, event.fingerprint)
548
552
  if ok:
549
553
  _progress(f":rocket: Release triggered via {repo.cicd_type}")
@@ -28,7 +28,7 @@ from dataclasses import dataclass, field
28
28
  from datetime import datetime, timezone
29
29
  from pathlib import Path
30
30
 
31
- from .config_loader import RepoConfig, SentinelConfig
31
+ from .config_loader import RepoConfig, SentinelConfig, resolve_auto_publish
32
32
  from .fix_engine import _claude_cmd, _run_claude_attempt, _is_auth_error, _progress_from_line
33
33
  from .git_manager import _git_env
34
34
 
@@ -276,11 +276,12 @@ def run_repo_task(
276
276
  return "skip", "Claude completed but made no changes to the codebase."
277
277
 
278
278
  commit_hash = after_hash
279
+ auto_publish = resolve_auto_publish(repo, cfg)
279
280
 
280
281
  if on_progress:
281
282
  on_progress(f":arrow_up: Pushing to `{repo.repo_name}`...")
282
283
 
283
- if repo.auto_publish:
284
+ if auto_publish:
284
285
  r = subprocess.run(
285
286
  ["git", "push", "origin", repo.branch],
286
287
  cwd=local_path, capture_output=True, text=True, env=env, timeout=60,
@@ -4867,6 +4867,10 @@ async def _handle_with_api(
4867
4867
  api_key = cfg_loader.sentinel.anthropic_api_key or os.environ.get("ANTHROPIC_API_KEY", "")
4868
4868
  client = anthropic.Anthropic(api_key=api_key)
4869
4869
 
4870
+ try:
4871
+ from . import __version__ as _sentinel_version
4872
+ except Exception:
4873
+ _sentinel_version = "unknown"
4870
4874
  paused = Path("SENTINEL_PAUSE").exists()
4871
4875
  repos = list(cfg_loader.repos.keys())
4872
4876
  ts = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
@@ -4904,6 +4908,7 @@ async def _handle_with_api(
4904
4908
  + (f"\nLog sources: {', '.join(log_sources)}" if log_sources else "")
4905
4909
  + (f"\nKnown projects in workspace: {', '.join(known_projects)}" if known_projects else "")
4906
4910
  + f"\nAdmin access for this user: {'YES — admin tools are available' if is_admin else 'NO — admin tools will be refused'}"
4911
+ + f"\nSentinel version: {_sentinel_version} — use this when asked what version you are running."
4907
4912
  )
4908
4913
 
4909
4914
  # Build user content — include attachment blocks if any