Skip to content

feat(log): tag Turn-ended diag line with cron task id (task=)#11

Merged
Kyzcreig merged 6 commits into
mainfrom
feat/log-task-id-turn-ended
Jun 4, 2026
Merged

feat(log): tag Turn-ended diag line with cron task id (task=)#11
Kyzcreig merged 6 commits into
mainfrom
feat/log-task-id-turn-ended

Conversation

@Kyzcreig

@Kyzcreig Kyzcreig commented Jun 4, 2026

Copy link
Copy Markdown
Owner

What

Adds task=<id> to the per-turn Turn ended: diagnostic log line in agent/conversation_loop.py.

Why

The cron scheduler already threads the job id into the agent as task_id (cron/scheduler.py:1132run_conversation(task_id=...)effective_task_id), but it was never logged. Surfacing it lets model-fallback-check.py attribute a logged turn to the exact cron job that produced it — detecting when a model-pinned cron silently ran on a fallback model (429/outage), replacing an unreliable time-window heuristic.

Change

  • 2-line additive edit: task=%s in _diag_msg, effective_task_id or "none" in _diag_args.
  • Both logger.info and the pending-tool-result logger.warning branch share the pair, so both gain it.
  • No control-flow change. Format-specifier/arg count kept in lockstep.

Tests

tests/agent/test_turn_ended_task_id_log.py — 3 contract tests (task= present; specifiers==args; last arg is effective_task_id). All green. Empirically verified the format renders ...session=… task=<job_id>.

teknium1 and others added 6 commits June 4, 2026 21:23
… session token (NousResearch#38926)

The documented path for connecting Hermes Desktop to a remote backend was
`--insecure` + a pinned HERMES_DASHBOARD_SESSION_TOKEN — an unauthenticated
bind plus a copy-pasted token. Replace it everywhere with the bundled
username/password dashboard-auth provider: set HERMES_DASHBOARD_BASIC_AUTH_*,
run `hermes dashboard --host 0.0.0.0` (the non-loopback bind engages the auth
gate), and Sign in from the app.

- desktop.md: rewrite 'Connecting to a remote backend' for the user/pass + Sign in flow
- web-dashboard.md: rewrite both remote-backend sections (overview + dedicated);
  reframe the auth-gate section so --insecure is a discouraged escape hatch, not a
  co-equal use case; drop the removed --tui flag from the systemd example
- environment-variables.md: lead with HERMES_DASHBOARD_BASIC_AUTH_*; drop the
  session-token / HERMES_DESKTOP_REMOTE_TOKEN remote-connect entries
- docker.md: mention the username/password provider as the simplest gate provider
…lback (NousResearch#38928)

The classic CLI left its live bottom chrome — the status bar, input box,
and separator rules — frozen in terminal scrollback after exit, on every
exit path (/exit, /quit, Ctrl+C, EOF) and on both Linux and Windows. The
prior erase_when_done=True fix (bf82a7f) routes prompt_toolkit's teardown
through renderer.erase(), but that walks back by the renderer's internal
cursor model and does not reliably wipe the chrome in practice — users still
saw a dead status bar + the rest of the session sitting above the resume
summary.

Clear the screen + scrollback directly at the single exit funnel instead.
All exit paths converge on _print_exit_summary() (called from the run-loop
finally block after app.run() returns and prompt_toolkit has restored
terminal modes), so a new _clear_terminal_on_exit() helper runs there before
the summary prints. It writes ESC[3J ESC[2J ESC[H (erase scrollback, erase
screen, home cursor) on a real TTY, no-ops silently when stdout is not a
terminal (pipes/redirects), and falls back to the platform clear command if
the escape write fails. Works on Linux, macOS, and modern Windows terminals
(Terminal/conhost with VT processing, already enabled by prompt_toolkit).

The resume/goodbye summary now prints at a clean top-left with nothing
stranded above it.

Fixes NousResearch#38252.
…OOT)

The reboot/shutdown family is on the unconditional hardline blocklist —
the correct default for most agents, but a hard blocker for fleet/ops
agents that legitimately need to restart the Linux hosts they manage.

Add an opt-in escape hatch: when HERMES_ALLOW_REBOOT is set truthy, the
reboot/shutdown family downgrades from HARDLINE to the DANGEROUS layer —
still approval-gated, and yolo / approvals.mode=off can pass it through.
Every other catastrophic pattern (root recursive delete, filesystem
format, raw-device overwrite, fork bomb, kill -1) stays unconditionally
hardline.

Default (flag unset) is byte-identical to the historical always-block
behavior. Verified: 129 tests pass including new downgrade and
isolation tests.
The cron scheduler already threads the job id into the agent as task_id
(cron/scheduler.py -> run_conversation(task_id=...) -> effective_task_id).
Surface it in the per-turn 'Turn ended' diagnostic log as task=<id> so cron
turns can be attributed to their job. Enables model-fallback-check.py to detect
when a model-pinned cron silently ran on a fallback model, replacing an
unreliable time-window heuristic with exact job-id attribution.

Additive logging only — no control flow change. Both logger.info and the
'pending tool result' logger.warning branch share _diag_msg/_diag_args, so both
gain the field. Format-specifier/arg count kept in lockstep (guarded by test).

tests/agent/test_turn_ended_task_id_log.py: 3 contract tests (task= present,
specifiers==args, last arg is effective_task_id).
@Kyzcreig Kyzcreig merged this pull request into main Jun 4, 2026
22 of 23 checks passed
@Kyzcreig Kyzcreig deleted the feat/log-task-id-turn-ended branch June 4, 2026 12:56
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown

🔎 Lint report: feat/log-task-id-turn-ended vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9831 on HEAD, 9830 on base (🆕 +1)

🆕 New issues (1):

Rule Count
deprecated 1
First entries
cli.py:12760: [deprecated] deprecated: The function `system` is deprecated: Soft deprecated. Use the subprocess module instead.

✅ Fixed issues: none

Unchanged: 5116 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Kyzcreig added a commit that referenced this pull request Jun 5, 2026
* docs: remote desktop connect uses username/password, not --insecure + session token (NousResearch#38926)

The documented path for connecting Hermes Desktop to a remote backend was
`--insecure` + a pinned HERMES_DASHBOARD_SESSION_TOKEN — an unauthenticated
bind plus a copy-pasted token. Replace it everywhere with the bundled
username/password dashboard-auth provider: set HERMES_DASHBOARD_BASIC_AUTH_*,
run `hermes dashboard --host 0.0.0.0` (the non-loopback bind engages the auth
gate), and Sign in from the app.

- desktop.md: rewrite 'Connecting to a remote backend' for the user/pass + Sign in flow
- web-dashboard.md: rewrite both remote-backend sections (overview + dedicated);
  reframe the auth-gate section so --insecure is a discouraged escape hatch, not a
  co-equal use case; drop the removed --tui flag from the systemd example
- environment-variables.md: lead with HERMES_DASHBOARD_BASIC_AUTH_*; drop the
  session-token / HERMES_DESKTOP_REMOTE_TOKEN remote-connect entries
- docker.md: mention the username/password provider as the simplest gate provider

* fix(cli): clear screen on exit so live chrome isn't stranded in scrollback (NousResearch#38928)

The classic CLI left its live bottom chrome — the status bar, input box,
and separator rules — frozen in terminal scrollback after exit, on every
exit path (/exit, /quit, Ctrl+C, EOF) and on both Linux and Windows. The
prior erase_when_done=True fix (bf82a7f) routes prompt_toolkit's teardown
through renderer.erase(), but that walks back by the renderer's internal
cursor model and does not reliably wipe the chrome in practice — users still
saw a dead status bar + the rest of the session sitting above the resume
summary.

Clear the screen + scrollback directly at the single exit funnel instead.
All exit paths converge on _print_exit_summary() (called from the run-loop
finally block after app.run() returns and prompt_toolkit has restored
terminal modes), so a new _clear_terminal_on_exit() helper runs there before
the summary prints. It writes ESC[3J ESC[2J ESC[H (erase scrollback, erase
screen, home cursor) on a real TTY, no-ops silently when stdout is not a
terminal (pipes/redirects), and falls back to the platform clear command if
the escape write fails. Works on Linux, macOS, and modern Windows terminals
(Terminal/conhost with VT processing, already enabled by prompt_toolkit).

The resume/goodbye summary now prints at a clean top-left with nothing
stranded above it.

Fixes NousResearch#38252.

* feat(approval): env-gated reboot/shutdown downgrade (HERMES_ALLOW_REBOOT)

The reboot/shutdown family is on the unconditional hardline blocklist —
the correct default for most agents, but a hard blocker for fleet/ops
agents that legitimately need to restart the Linux hosts they manage.

Add an opt-in escape hatch: when HERMES_ALLOW_REBOOT is set truthy, the
reboot/shutdown family downgrades from HARDLINE to the DANGEROUS layer —
still approval-gated, and yolo / approvals.mode=off can pass it through.
Every other catastrophic pattern (root recursive delete, filesystem
format, raw-device overwrite, fork bomb, kill -1) stays unconditionally
hardline.

Default (flag unset) is byte-identical to the historical always-block
behavior. Verified: 129 tests pass including new downgrade and
isolation tests.

* feat(log): tag Turn-ended diag line with cron task id (task=)

The cron scheduler already threads the job id into the agent as task_id
(cron/scheduler.py -> run_conversation(task_id=...) -> effective_task_id).
Surface it in the per-turn 'Turn ended' diagnostic log as task=<id> so cron
turns can be attributed to their job. Enables model-fallback-check.py to detect
when a model-pinned cron silently ran on a fallback model, replacing an
unreliable time-window heuristic with exact job-id attribution.

Additive logging only — no control flow change. Both logger.info and the
'pending tool result' logger.warning branch share _diag_msg/_diag_args, so both
gain the field. Format-specifier/arg count kept in lockstep (guarded by test).

tests/agent/test_turn_ended_task_id_log.py: 3 contract tests (task= present,
specifiers==args, last arg is effective_task_id).

---------

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
Co-authored-by: Kyzcreig <9063726+Kyzcreig@users.noreply.github.com>
Co-authored-by: Aegis <aegis@hermes.local>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants