14 Commits

Author SHA1 Message Date
teknium1 23036e20a6 fix(ux): plain-language, actionable user-facing messages (core)
Squashed integration of the user-facing message audit for this surface set.
Full per-finding receipts: /tmp/ux-audit/lanes/*-receipt.md (campaign artifacts).
2026-09-15 04:12:13 -07:00
KeyArgo 302334ff89 fix(gateway): neutral orchestration wording for block-loop triage pings
A repeated-block circuit breaker routes a task to triage and establishes that
orchestration attention is needed — it does not establish that a human
decision exists. The notifier unconditionally rendered every
block_loop_detected event as "needs a human decision", overclaiming owner
intent for dependency waits, capability gaps, and transient failures.

Branch on the typed block kind in the event payload: only needs_input (the
one kind carrying a concrete question for the owner) keeps the decision
wording; dependency/capability/transient/None get neutral orchestration
wording. TRIAGE visibility, the reason, and recurrence count are preserved.

Closes #111125
2026-09-15 03:42:00 -07:00
teknium1 a21747fe4e fix(kanban): an anchorless thread subscription warns once instead of vanishing (#110919)
Follow-up on the salvaged #110928 (CLI `--parent-chat-id` / `--guild-id`):

- `_claim_for_sub` skipped a thread-shaped row that matched no `profile_routes`
  entry at DEBUG on every tick. Legacy rows written before the flags existed can
  never match a channel-level route (no `parent_chat_id`), so the notifier now
  logs ONE WARNING per row naming the task, the thread and the re-subscribe
  command. Still fail-closed: the events stay unclaimed.
- Docs: the kanban user guide explains the anchors and shows the Discord-thread
  subscribe command under `profile_routes`.
- Test (red on origin/main): two collects → exactly one WARNING, events unseen.
2026-09-14 16:14:33 -07:00
yoyodine-industries f3357b5031 fix(kanban): stage review-bound handoff artifacts in request_review
request_review ignored artifacts entirely, so a review-bound card lost every
file its handoff named: the reviewer's complete_task is what runs
_cleanup_workspace over the managed scratch workspace.

Stage declared (explicit artifacts argument or metadata["artifacts"]) and
prose-referenced files into the task's durable attachments dir at the review
handoff, exactly as complete_task already does, carry the staged paths in the
review_requested event payload, and let the gateway notifier upload them (its
guard widens from completed to review_requested). ArtifactPreservationError
still rolls the whole transition back: the task stays running and retryable
with no attachments and no event.
2026-09-13 14:37:17 -07:00
Teknium 284d220ba4 fix(multiplex): cron, kanban, /loop and completion paths for a served profile match its standalone gateway
Under gateway.multiplex_profiles a secondary profile X is ticked, dispatched
and notified from the default profile's process, where os.environ holds the
DEFAULT profile's .env and X's values live only in the per-turn secret scope /
HERMES_HOME override. Every remaining read that skipped that scope made X
behave differently from `hermes -p X gateway run`:

- cron: HERMES_CRON_TIMEOUT, HERMES_MODEL (job/preflight fallback),
  HERMES_CRON_MAX_PARALLEL, inflight allowance, prefill file and the script
  timeout were bare os.getenv → the default profile's values; a job without a
  model silently ran on the default's HERMES_MODEL instead of refusing.
  cron/env_settings.py::cron_env_setting reads the scope (fire) or the ticked
  home's .env (tick thread), plain environ when multiplexing is off.
- child env: the restart-safe cron worker, the Bot Chat delivery child and the
  kanban worker inherited the launch profile's non-credential .env settings
  and bridged TERMINAL_* policy (TERMINAL_ENV=docker, default's image,
  HERMES_MODEL) — X's worker ran in the default's docker image on the
  default's model. tools/environments/local.py::strip_launch_profile_env drops
  them when the child targets another served profile.
- kanban: the worker --toolsets pin was silently dropped for every served
  assignee (toolset probes call get_secret without a scope → swallowed
  UnscopedSecretError); notifier pings, artifact uploads and the wake text ran
  under the default's media policy / display language (only wake() was scoped).
- /loop: _post_turn_loop_completion hopped to the executor without contextvars,
  writing the completed tick into the DEFAULT profile's state.db and leaving
  X's row awaiting_response forever; the --until judge ran with the default's
  aux credentials.
- background processes: a secondary's processes.json (scope-relative since
  adf23550f5) was never read at startup; its processes were not re-adopted
  and notify_on_complete notices were lost. Startup recovers every served
  home under its scope; recovery adopts each session once.
- completion delivery: background_process_notifications was evaluated once per
  drain for the ambient profile (default's mode for everyone; X's `off`
  dropped a sibling's `all` event), recovered watchers used the default's
  mode, HERMES_BACKGROUND_NOTIFICATIONS was read raw from environ;
  _deliver_platform_notice used the default's GatewayConfig so a secondary's
  notice_delivery: private went public.

Not changed: gateway/run.py and tools/async_delegation.py (PR #106742
rewrites both). Known residue left for the env-bridge lane:
HERMES_SESSION_STALL_TIMEOUT is bridged once from the launch config.
scheduler bug, not a parity gap; unchanged here.
2026-09-11 19:58:07 -07:00
Teknium bf1bf7515a fix: retry Kanban wakes until adapter admission 2026-09-07 14:16:57 -07:00
Teknium 30b3ca16f4 fix(kanban): deliver routed profile notifications on the authorized transport
Authorize route-only profiles using the ordered canonical route matcher and
served-profile set at both claim and delivery. Preserve secondary credential
boundaries, retry denied routes, and keep scope/parent anchors plus transport
provenance on synthetic wakes. Install the destination runtime scope rather
than inheriting the notifier's scope; a removed profile cannot wake as primary.

Slim forward-port of the direction in #101196/#101397 and #93863 (#93851).
Canonical scope_id takes precedence over the guild alias and live chat cache.
Two route invariants and two runtime-scope invariants reproduced red first.

Co-authored-by: Brooklyn Nicholson <brooklyn.bb.nicholson@gmail.com>
Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
2026-09-07 14:16:57 -07:00
Teknium e3ab65fe80 simplify(compat): kanban_db — drop 73 re-exports/aliases, repoint 794 callers 2026-09-03 13:48:14 -07:00
Teknium e83816a4d1 review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
2026-09-03 09:44:26 -07:00
Teknium 4dd0c22bd7 refactor(gateway): compact kanban notifier collector and dispatcher log call sites 2026-09-02 19:36:31 -07:00
Teknium 2da1a3cd21 refactor(gateway): compact kanban watcher/notifier call sites and state init 2026-09-02 19:25:50 -07:00
Teknium 320a7caa6a refactor(gateway): kanban notifier collector class, lambda formatters, single wake path 2026-09-02 18:52:31 -07:00
Teknium 7a1a36a12f refactor(gateway): unify kanban watcher settings/lock helpers in kanban_watchers_common, split notifier board collection into phase helpers 2026-09-02 18:28:02 -07:00
Teknium fd2bfa1893 refactor(gateway/kanban): lift notifier delivery into _KanbanNotification + event-formatter table, dispatcher into _DispatcherSettings/_KanbanDispatcher; unify board enumeration/tick sleep 2026-09-02 15:57:11 -07:00