Skip to content

release: 7.3#164

Merged
electricessence merged 713 commits into
masterfrom
release/7.3
Apr 28, 2026
Merged

release: 7.3#164
electricessence merged 713 commits into
masterfrom
release/7.3

Conversation

@electricessence
Copy link
Copy Markdown
Collaborator

Release 7.3

New features

  • Hybrid caption-duplication detector (send): When a send includes both audio and text/caption, detects whether the caption restates the audio using Jaccard content-word similarity (≥0.7 threshold, ≥5 content words, 20–300% length-ratio gate). Fires NUDGE_CAPTION_DUPLICATION service message to nudge callers toward correct caption usage. No LLMs — deterministic in-process.

  • Help index topic (help): help('index') now returns a structured overview of all available help topics. help('schema') describe path now also included.

Documentation

  • Session memory save format standardized across docs and help topics.

Fixes

  • Session startup skill: removed a blocking operator-prompt path that could stall startup in non-interactive contexts.

🤖 Generated with Claude Code

Pre-shutdown announcement (cause, session count), per-session closed
lines (graceful + force-close), summary mode for >10 sessions, and
gravestone "🪦 Bridge offline" as final message. All fire-and-forget —
shutdown never blocks on Telegram API. ShutdownCause narrowed to
operator|agent. 14 new tests, regression test for full sequence order.

Sealed-By: Overseer
Adds behavior-registry.ts with rule-based behavioral nudge system.
Wires reaction semantics first-use hint via markFirstUseHintSeen.
Removes isTutorialEnabled/markTutorialToolSeen dependencies.

Sealed-By: Overseer
Adds compression_hint_dm and compression_hint_route first-use nudges
via markFirstUseHintSeen. Resolves import conflict with 15-745
(merged named imports from first-use-hints.js). Adds "audio" to
RICH_TOPICS alongside "behavior" from prior merge.

Sealed-By: Overseer
Adds modality_hint_voice first-use nudge in server.ts via
markFirstUseHintSeen. Adds SERVICE_MESSAGES import. Adds "modality"
and keeps "behavior"/"audio" topics in RICH_TOPICS and help DESCRIPTION.

Sealed-By: Overseer
All three tasks completed API migration from tutorial-mode to
first-use-hints infrastructure. Merged in sequence; conflicts
resolved by combining imports and topic sets.

Sealed-By: Overseer
Removes tutorialEnabled/tutorialSeenTools session fields,
isTutorialEnabled/setTutorialEnabled/markTutorialToolSeen exports,
and tutorial/on + tutorial/off action handlers. Retains firstUseHintsSeen
and getOrInitHintsSeen (used by first-use-hints.ts). Changelog updated.

Sealed-By: Overseer
Adds pending=N hint to buildBatchResult when pending > 0, prompting
agents to use the processing preset. Documents service message vs
envelope hint severity tiers in guide.md.

Sealed-By: Overseer
…zed)

Adds FIFO ordering requirement and async-failure text-fallback requirement
per operator directive. Priority 10 — queues ahead of all current TMCP tasks.
…ments

Updates spec promoted from drafts: status draft→queued, adds two
Curator-directed requirements per operator directive.
Rewrites completionBadge() — shows only non-zero exceptional counts
(failed/skipped), newline separator, no em-dash. Removes duplicate import.

Sealed-By: Overseer
Imports buildHeader from outbound-proxy; prepends formatted header to
cancellation text so animation cancel messages include the agent nametag.

Sealed-By: Overseer
Feature verified present in close_session.ts:25-34. No code changes needed.
Sealed-By: Overseer
Updates "v6 API" → "v7 API" in the action tool description string
and README Version 6 → Version 7 heading/prose.

Sealed-By: Overseer
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 91 out of 129 changed files in this pull request and generated 4 comments.

Comment thread docs/help/guidance.md
Comment thread skills/telegram-mcp-post-compaction-recovery/SKILL.md
Comment thread src/tools/send.ts Outdated
Comment thread src/tools/help.ts
Comment on lines 68 to 72
"Pass topic: 'behavior' for the behavioral-shaping rule registry and severity tier guidance. " +
"Pass topic: 'modality' for the priority axis (buttons > text > audio) and modality-matching rules. " +
"Pass topic: 'events' for the external event system docs (POST /event endpoint, kinds, metrics). " +
"Pass topic: 'guidance' for the guidance delivery reference (what fires when and why). " +
"Pass topic: '<tool_name>' for detailed docs on a specific tool.";
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR title/description indicate this is the 7.3 release, but this diff doesn’t include the expected release artifacts (e.g., updating changelog/unreleased.md and bumping the package version). Please add the release-note entry and version bump (or clarify if those are handled in a separate PR).

Copilot uses AI. Check for mistakes.
…lt shift (15-763)

- animation/status action: returns active animation state per session; governor variant lists all
- Stale-on-idle dequeue warning: animation_stale_warning event after ≥30s idle (120s cooldown)
- Timeout default: 600s → 60s across send, show, animation-state
- Help docs: animation.md + presence.md updated with lifecycle rules

Sealed-By: Overseer
7-row spectrum table (text-only long through audio-only) with trigger conditions.
Audio format rules: natural language, fluid prose, minimal punctuation, no
voice-unfriendly content.

Sealed-By: Overseer
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 99 out of 137 changed files in this pull request and generated 5 comments.

Comment thread docs/help/presence.md Outdated
Comment thread docs/help/animation.md Outdated
Comment thread src/tools/help.test.ts Outdated
Comment thread src/hybrid-duplication-detector.ts Outdated
Comment thread src/hybrid-duplication-detector.ts
electricessence and others added 2 commits April 26, 2026 20:10
…nts (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nts (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 99 out of 137 changed files in this pull request and generated no new comments.

Squashed-from: 10-0859
Sealed-By: Overseer
Docs said service_message with event_type; actual impl returns dequeue
update item with event: animation_stale_warning.

Squashed-from: 10-0860
Sealed-By: Overseer
SID variant implemented by 15-763; docs updated to disambiguate
single-session vs multi-session response shapes.

Squashed-from: 10-0861
Sealed-By: Overseer
@electricessence electricessence merged commit 4747c98 into master Apr 28, 2026
1 check passed
@electricessence electricessence deleted the release/7.3 branch April 28, 2026 13:25
electricessence added a commit that referenced this pull request May 6, 2026
…e stability (#167)

* feat(10-757): compact response_format for dequeue/send/ask/choose/confirm/checklist

* seal: 10-757 — compact response_format phase 2 (2026-04-25)

Sealed-By: Overseer

* task(10-801): clarify Criterion 6 — integration test definition

* feat(10-801): POST /hook/animation REST endpoint for hook-driven animations

* seal: 10-801 — POST /hook/animation REST endpoint (2026-04-25)

Sealed-By: Overseer

* task: move 20-499 to 60-review — Worker 2 complete

* feat(20-499): tool file restructure — namespace subdirectories (session/, reminder/, profile/, etc.)

* seal: 20-499 — tool file namespace restructure (2026-04-25)

Sealed-By: Overseer

* feat: update import paths and fix lint errors in hook-animation tests; remove unused imports in query and delete tests; add async flag to audio-path response_format tests

* chore: update subproject commit reference in .engine file

* feat: implement recording indicator management for async voice sends; suppress typing emission during audio jobs

* docs(release): add release-branching-process; task: 4 new drafts (05-0825, 10-0823, 15-0824, 20-0822)

- docs/release-branching-process.md — codifies dev → release/X.Y → master flow
- 05-0825 — bug: question answer edits text but inline keyboard remains
- 10-0823 — first-dequeue onboarding bundle + presence-cascade companion nudge
- 15-0824 — react fallback for unsupported emojis with caller hint
- 20-0822 — hybrid send caption-restates-audio detector (gated on corpus + FP rate)

* task: promote 05-0825 (button-clear bug) + 15-0824 (emoji fallback) to 40-queued

Both ready for worker pickup — clear scope, well-defined acceptance criteria, no operator-blocking ambiguity.

Held in drafts:
- 10-0823 onboarding bundle (architectural — needs spec audit first)
- 20-0822 duplication detector (gated on corpus + FP rate per operator direction)

* pipeline: claim 05-0825-question-answer-edits-text-but-keyboard-remains.md

* pipeline: claim 15-0824-react-emoji-fallback-with-hint.md

* chore(changelog): clean unreleased.md — drop v7.1.0 carryover, retitle v7.2.0

* pipeline: move 05-0825 to 60-review

* fix(choose): clear inline keyboard after question is answered

Removes highlightedRows arg from ackAndEditSelection in choose.ts
callback hook so reply_markup falls back to {inline_keyboard:[]}
in the same editMessageText call. Buttons now clear immediately on
answer; choice.ts highlight path intentionally unchanged.

2752/2752 tests passing.

Sealed-By: Overseer
Task: 05-0825

* pipeline: seal 05-0825 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 05-0825

* pipeline: move 15-0824 to 60-review

* feat(react): emoji alias fallback with hint for unsupported reactions

Adds UNSUPPORTED_EMOJI_ALIASES map (👂→👀, 🤚→👍, 🧠→🤔, 👁→👀,
🦻→👀). Unsupported-but-aliased emojis remap silently, returning
ok:true + applied:[target] + hint:emoji_alias_applied + hint_detail.
Unmapped unsupported emojis still return REACTION_EMOJI_INVALID.
Temporality rules (temp/permanent/TEMPORARY_BY_DEFAULT) respected.
All 7 alias paths tested; docs/help/reactions.md updated.

2762/2762 tests passing.

Sealed-By: Overseer
Task: 15-0824

* pipeline: seal 15-0824 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 15-0824

* task: 15-0824 completion notes; new draft 05-0826 (recording-indicator findings)

- 70-done/.../15-0824: append Completion section with branch/commit/changes (Worker edit not picked up by seal commit — pipeline gap noted)
- 10-drafts/05-0826: 4 recording-indicator findings from Copilot CLI / GPT-5.3-Codex review of commit 2473daa

* task: 15-0827 — seal commit misses Worker completion notes (3 fix options)

* chore(test): chain typecheck before vitest run; task 05-0828 to fix 99 pre-existing test TS errors

pnpm test now runs `tsc --noEmit -p tsconfig.eslint.json && vitest run`.
This will fail until the 99 errors in 05-0828 are resolved.

Operator direction: "typecheck should always be present as part of pnpm test."

* task: promote 05-0828 (fix 99 TS errors in test files) to 40-queued

* pipeline: claim 05-0828-fix-99-typescript-errors-in-test-files.md

* pipeline: return 05-0828 to 40-queued (Worker 2 unresponsive, zero progress)

* pipeline: claim 05-0828-fix-99-typescript-errors-in-test-files.md

* pipeline: move 05-0828 to 60-review

* fix(test): resolve 99 TypeScript errors across 25 test files

Fixes all pre-existing type errors that were hidden by tsc/vitest/eslint
config gaps. pnpm test now chains typecheck before vitest; all 25 test
files pass strict tsc. Type-only changes — no production code modified.
2762/2762 tests passing.

Sealed-By: Overseer
Task: 05-0828

* pipeline: seal 05-0828 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 05-0828

* task: 05-0829 — investigate worker haiku compaction + cross-worker working-tree bleed (priority 5)

* task: 05-0829 — root cause confirmed (staged-but-uncommitted recovery miss); 2 concrete fixes identified

* task(queue): add 05-0830 choice callback highlight-then-collapse

* pipeline: claim 05-0830-choice-callback-highlight-then-collapse.md

* feat(choice): highlight chosen button then collapse keyboard on callback (05-0830)

* pipeline: seal 05-0830 → 70-done/2026/04/25

Sealed-By: Overseer

* pipeline: remove duplicate 60-review copy of 05-0830 (already in 70-done)

* task(queue): add 05-0831 wire attachHookRoutes into src/index.ts

* pipeline: claim 05-0831-wire-attach-hook-routes-in-index.md

* task(queue): add 10-0831 event system + 15-0832 reporting tool

* pipeline: claim 10-0831-event-system-rest-endpoint.md

* feat(index): wire attachHookRoutes to make POST /hook/animation reachable (05-0831)

Squash-merge of branch 05-0831 — verified APPROVED (0 critical, 0 major, 0 minor).

Note: hook-animation will be removed in a follow-on task as /event subsumes this functionality.

Sealed-By: Overseer

* pipeline: seal 05-0831 → 70-done/2026/04/25

Sealed-By: Overseer
Note: hook-animation teardown follows in subsequent task per /event pivot.

* pipeline: claim 15-0832-event-log-reporting-tool.md

* docs(animation): remove obsolete /hook/animation; point to /event system

* chore(profiles): remove bundled profile examples; replace with docs/profiles.md schema doc

* chore(tasks): return 15-0832 to 40-queued — shutdown interrupted claim

* chore(leakage): scrub cortex.lan refs from graceful-shutdown SKILL + chat/info doc

* feat: Implement various improvements and fixes across multiple tasks

- Remove `log/dump` action and replace with `log/get` and `log/delete` pattern for trace data management.
- Update agent approval system to use tokens and tickets instead of user-controlled names for session approvals.
- Add tests for high-risk branches identified in Codex review, covering voice chunk failures and approval cleanup timeouts.
- Implement cleanup for expired callback buttons in interactive messages to prevent dead UI.
- Fix base reaction overwrites for temporary reactions to ensure proper visibility and behavior.
- Extend recording indicator to remain active until voice message delivery is confirmed.
- Define content spec for TMCP service messages, ensuring ultra-compressed messaging and help breadcrumbs.
- Fix shutdown and session close lifecycle to ensure proper handling of active and inactive sessions.

* feat: Add profiles leakage audit document to address workflow-specific content concerns

* chore(leakage): remove cortex.lan refs from 10-0835 and 10-418

- 10-0835: replaced internal Curator memory key citation with prose
- 10-418: generalized hostname grep pattern in security audit procedure

* Merge remote-tracking branch 'origin/master' into dev

* task(15-0837): draft — rewire /event compacting kind to compacting preset (not working)

* task(15-0837): expand — add recovering preset + compacted side-effect

* task(15-0837): simplify — preset name == event kind, drop KIND_ANIMATION map

* task(15-0837): promote to queued — preset name == event kind

* task(15-0838): draft — Curator shutdown pre-shutdown metrics report

* seal(10-0831): event system REST endpoint — implementation on release/7.2

Sealed-By: Overseer

* pipeline: move 15-0832 to 60-review — verification pending

* seal(15-0832): event-log reporting tool — scripts/event-report.mjs

Sealed-By: Overseer

* pipeline: promote 10-0823 (onboarding bundle) + 10-0835 (profiles hygiene) to 40-queued

* pipeline: claim 10-0835-profiles-leakage-audit.md

* seal(10-0835): profiles leakage audit — fix already applied in 02f4163

Sealed-By: Overseer

* pipeline: claim 10-0823-first-dequeue-onboarding-bundle.md

* pipeline: promote 20-0822 (hybrid duplication detector) — operator priority bump

* fix(skills): correct dequeue parameter name timeout→max_wait across skill docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(onboarding): first-dequeue bundle — hybrid, modality, presence, conditional tail

Adds 3 new onboarding service messages (onboarding_hybrid_messaging,
onboarding_modality_priority, onboarding_presence_signals) and a
conditional tail (onboarding_no_pending_yet, gated on discarded === 0)
to the first-dequeue bundle. Agents now enter context with full protocol
awareness. 2837 tests pass.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 20-0822-hybrid-duplication-detector.md

* skills(spec): author 12 purpose-driven specs for telegram-mcp skill cluster (Curator pass)

* skills(uncompressed): author 12 companion uncompressed.md, reconcile SKILL.md gaps (animation timeout, dequeue event-class table, dump-handling tool name, graceful-shutdown force:true)

* skills(SKILL): generalize fleet role names — Curator/Overseer/Worker/Deputy → governor/supervising/subordinate (TMCP-public hygiene)

* pipeline: icebox 15-0837 — superseded by 7.2.2 BUILTIN_PRESETS implementation

* draft+queue(20-0841): spike — pre-stage node_modules in TMCP worktrees (auto-queued: research with concrete output)

* draft(15-0843): help('shutdown') must carry canonical governor procedure verbatim

Filed at operator request after Curator quiz turn. Worker-delegatable doc-fix
on docs/help/shutdown.md Governor Shutdown section.

* pipeline: claim 20-0841-spike-worktree-node-modules-prestaging.md

* seal: 20-0841 — spike: pre-stage node_modules in TMCP worktrees

Findings: Candidate 4 (worktree-create hook) + Candidate 1 (shared virtual store)
recommended. Per operator guidance: per-repo sanctioned script on Worker allowlist.
5 operator decisions remain open in findings doc for implementation follow-on.

Sealed-By: Overseer

* fix(startup): remove blocking operator-prompt path from session-startup SKILL

* draft: auto-pin blocking questions feature (operator directive 2026-04-26)

* triage: route 6 tasks to curator-only (Curator-authored or delegation: curator)

- 10-0836: TMCP skills overhaul — Curator-led, multi-cycle
- 10-737: hook hash fragility reform — Curator authors design doc directly
- 15-734: hook error disambiguation — Curator authors hook patch directly (trust boundary)
- 20-721: V7 master merge readiness — Curator orchestrates audit + PR
- 30-470: remove dead registerTool calls — Curator must revise spec (premise incorrect per W2)
- friction-pnpm-install-worktree-block: explicit delegation: curator

* triage: route 3 tasks to needs-refinement (require Curator spec before Worker claim)

- 10-733: zombie session reconnect security — needs Curator spec, Worker cannot define security boundary
- 15-736: loud-on-anomaly observability — "Curator should spec anomaly taxonomy before claim"
- 15-349: compaction event logging — multi-phase, deletes hooks (Curator trust boundary)

* queue: 05-0826 recording-indicator-refcount-race-and-suppression-gaps (operator-approved)

* queue: 05-0829 investigate-worker-haiku-compaction-and-handoff-bleed (operator-approved)

* note: 05-0829 — verify-first guidance from operator before implementing fixes

* seal: spike-0841 pnpm-worktree-prestaging (operator-verified, direction set)

* queue: 15-0827 seal-commit-misses-worker-completion-notes (operator-approved)

* queue: 15-0843 help-shutdown-canonical-governor-procedure (operator-approved)

* queue: 15-0848 reply-target-not-active-question-no-skip (operator-approved)

* queue: 15-0838 curator-shutdown-metrics-report (operator-approved)

* queue: 20-draft session-joined-fellow-service-message (operator-approved)

* docs: standardize session memory save format (10-0548)

Update telegram-mcp-session-startup SKILL.md and help session/start.md
to document the two-format standard: Minimal (raw integer in
session.token) and Full (YAML body in session.md). Remove PIN field
references; update token formula to use 'suffix' not 'pin'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(help): add index topic to overview and schema describe (10-0549)

- buildOverview(): mention help(topic: 'index') for categorized skill index
- topic.describe(): add 'index' option so schema introspection surfaces the topic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0826-recording-indicator-refcount-race-and-suppression-gaps.md

* feat(send): hybrid caption-duplication detector (Jaccard-based) (squash 20-0822)

Adds detectCaptionDuplication (Jaccard similarity, content-word tokenisation,
ratio gates) wired into all three send paths. Fires NUDGE_CAPTION_DUPLICATION
when caption appears to restate audio. All 2860 tests pass.

Also: draft task 15-0849 tts-underscore-string-replace (operator-filed 2026-04-26)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal: 20-0822 hybrid-duplication-detector — Jaccard detector merged, all tests pass

Note: ship-criteria corpus validation skipped; conservative thresholds expected
to hold. Monitor for FP noise in production.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* queue: 15-0849 tts-underscore-string-replace (operator-directed, scope confirmed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tasks): normalize 70-done/20260424 → 70-done/2026/04/24 (canonical date format)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0829-investigate-worker-haiku-compaction-and-handoff-bleed.md

* pipeline: claim 15-0849-tts-underscore-string-replace.md

* pipeline: claim 15-0843-help-shutdown-canonical-governor-procedure.md

* seal: 05-0829 Worker recovery investigation — both bugs already fixed, skill promoted

Bug 1 (Overseer recovery staged-state signal): already in context/refresh.md.
Bug 2 (Worker staged-state Worktree Gate): promoted from memory to task-execution/SKILL.md.
Postmortem in Curator repo. All 4 unknowns resolved.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(docs): MD032 blank line before list in session/start help (Copilot #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(recording): epoch guard for refcount race + typing suppression gaps (05-0826)

Squash-merged branch 05-0826. Epoch token prevents stale async callbacks from
corrupting refcount; suppression-gap fixes ensure typing indicator clears reliably.

Sealed-By: Overseer

* fix(help/shutdown): canonical governor shutdown procedure with explicit token path (15-0843)

Squash-merged branch 15-0843. Rewrites shutdown.md into Participant/Governor sections
with verbatim operator-stated sequences; adds wipe-before-shutdown ordering assertion.

Sealed-By: Overseer

* chore: seal 05-0826 and 15-0843 → 70-done/2026/04/26

Sealed-By: Overseer

* fix(button-helpers): off-target reply guard in pollButtonOrTextOrVoice (15-0848)

Squash-merged branch 15-0848. Three-way rule: ambiguous (no reply_to), on-target
(reply matches question), off-target (reply ≠ question → re-enqueue, prompt open).

Sealed-By: Overseer

* chore: seal 15-0848 → 70-done/2026/04/26

Sealed-By: Overseer

* chore: seal 15-0827 (investigation) → 70-done/2026/04/26

Root cause confirmed: Overseer seal renames task file from dev branch which lacks
Worker's Completion section. Fix is Overseer-side (include complete() commit or
copy Completion at seal time). No Worker SKILL change needed.

Sealed-By: Overseer

* feat(tts): normalize ALL_CAPS_WITH_UNDERSCORES identifiers for speech (15-0849)

Squash-merged branch 15-0849. Adds normalizeCapsForTts() — converts identifiers
like SESSION_JOINED to "session joined" in TTS output. Toggle off via
TTS_CAPS_NORMALIZE=false.

Sealed-By: Overseer

* chore: seal 15-0849 → 70-done/2026/04/26

Sealed-By: Overseer

* pipeline: claim 15-0838-curator-shutdown-metrics-report.md

* feat(skill): graceful-shutdown step 6 compaction metrics report (15-0838)

Squash-merged branch 15-0838. Updated graceful-shutdown skill in electrified-cortex
to add Step 6 (pre-shutdown compaction metrics report via event-report.mjs).

Sealed-By: Overseer

* chore: seal 15-0838 → 70-done/2026/04/26

Sealed-By: Overseer

* refactor(session): extract SESSION_JOINED_FELLOW to service-messages.ts (20-draft)

Squash-merged branch 20-draft-fellow. Eliminates hardcoded inline string in
session/start.ts; governor/non-governor paths now both use SERVICE_MESSAGES constants.

Sealed-By: Overseer

* chore: seal 20-draft → 70-done/2026/04/26

Sealed-By: Overseer

* feat(guidance): lazy trigger delivery for onboarding messages (10-0581)

Squash-merged branch 10-0581. Moves 5 session-start onboarding messages to
trigger-based delivery; adds help('guidance') taxonomy topic.

Sealed-By: Overseer

* chore: promote 15-0850 to 40-queued (operator approved 2026-04-26)

* pipeline: claim 15-0850-recovering-animation-replace-with-compacted-notify.md

* feat(compaction): replace recovering animation with compacted notify on first post-compacted activity (15-0850)

Squash-merged from branch 15-0850.
Sealed-By: Overseer

* feat(animation): add status API, stale-on-idle warning, timeout default shift (15-763)

- animation/status action: returns active animation state per session; governor variant lists all
- Stale-on-idle dequeue warning: animation_stale_warning event after ≥30s idle (120s cooldown)
- Timeout default: 600s → 60s across send, show, animation-state
- Help docs: animation.md + presence.md updated with lifecycle rules

Sealed-By: Overseer

* docs(send): add messaging spectrum and audio format rules (20-766)

7-row spectrum table (text-only long through audio-only) with trigger conditions.
Audio format rules: natural language, fluid prose, minimal punctuation, no
voice-unfriendly content.

Sealed-By: Overseer

* fix(lint): address Copilot MD055 + line-length + regex-hoisting comments (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add .code-reviews/ to .gitignore (eval artefacts contain local paths)

* eval(10-0858): haiku-class L1 vs sonnet-class L2 comparison report

Squashed-from: 10-0858
Sealed-By: Overseer

* fix(10-0859): extract deliverCaptionDuplicationNudge helper

Squashed-from: 10-0859
Sealed-By: Overseer

* fix(10-0860): correct presence.md stale animation warning shape

Docs said service_message with event_type; actual impl returns dequeue
update item with event: animation_stale_warning.

Squashed-from: 10-0860
Sealed-By: Overseer

* fix(10-0861): clarify animation/status SID variant return shape in docs

SID variant implemented by 15-763; docs updated to disambiguate
single-session vs multi-session response shapes.

Squashed-from: 10-0861
Sealed-By: Overseer

* seal: task 15-0863 — Verify choose callback cannot fire twice

Static analysis confirms _callbackHooks one-shot de-registration is
synchronous before any await. Node.js single-thread guarantee ensures
exactly one delivery for all interactive modes (choose, confirm, question).

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: move 15-0862 to 60-review

* seal: task 15-0862 — Add 250ms delay between button color-flip and collapse

BUTTON_COLLAPSE_DELAY_MS=250 constant; gated on real button press only
(callbackQueryId truthy). Persistent path passes delayMs=0. All 2930
tests passing. New fake-timer gate test added.

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove async from handleAnimationStatus function and adjust test tick handling

* feat(tasks): file 50-0865 + 50-0866 from Overseer wedge postmortem

- 50-0865: bridge auto-terminate for stuck sessions (no recovery
  after N consecutive unhealthy events)
- 50-0866: TTS render timeout for hybrid sends (prevent silent
  indefinite block)

Both surface from 2026-05-03 5-alarm Overseer wedge incident
where auto-recovery silently gave up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0867 consumer hook setup guidance

Document the loop-guard + compaction-notification hook patterns
for outside TMCP consumers. Operator (2026-05-04): patterns exist
in-house but are poorly documented for fresh integrators.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0868 build per-session touch-file feature

Operator (2026-05-04): ship the bridge-side feature now without
waiting for Monitor wakeup-semantics validation. Per-session touch
file with random-hash filename, leading+trailing-suppressed
debounce, activity-aware reset, lifecycle tied to session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): flip ownership — agent provides path, TMCP just touches

Operator (2026-05-04 late): TMCP doesn't allocate/create/delete the
touch file. Agent owns it, registers path via monitor/register.
TMCP records and touches; nothing else. Cleaner separation,
opt-in by construction, TMCP filesystem stays empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): hybrid opt-in — agent OR TMCP supplies path

Operator (2026-05-04 final): monitor/enable supports two shapes:
- agent-supplied path: TMCP records, never creates/deletes
- TMCP-supplied: TMCP generates random hash, owns lifecycle
Either way: opt-in only. Without enable, zero I/O.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): rename to session-file CRUD, agnostic naming

Operator (2026-05-04): drop the Monitor framing — TMCP exposes a
filesystem hook, consumer chooses how to watch. CRUD verbs:
session-file/create, session-file/edit, session-file/delete,
session-file/get. Path-supplied vs TMCP-generated still both
supported; ownership rules carry through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): correct namespace to session/file/ (under existing session/)

Operator (2026-05-04): not session-file/, but session/file/ —
extends the existing session/ namespace (session/start, session/
close, session/list).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): final namespace activity/file/ + decision rationale

Operator (2026-05-04 final): activity/file/ wins. The file signals
activity, doesn't record session state. Top-level namespace
parallel to session/, leaves room for sibling activity hooks
(presence, typing, etc) later.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): auto-shorten dequeue default to 5s on activity/file/create

Operator (2026-05-04): familiar Claude pattern. Reverts on delete.
Per-call override still respected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): clarify max_wait override is temporary, default = 5min

Operator (2026-05-04): activity/file/create applies a TEMPORARY
override (not a profile mutation). activity/file/delete clears it
back to the standard 5min default. Per-call still trumps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note agent can override the override via profile/dequeue-default

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note loop-guard becomes redundant with activity/file in use

Operator (2026-05-04): emergent simplification — loop-guard exists
to catch silent stuck agents during 300s blocking dequeues. With
5s default + kicker, that failure mode shrinks 60x. Future task:
deprecate + remove loop guard once activity/file adopted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0864-session-close-confirm-show-identity.md

* feat(50-0864): session-close confirmation includes name and SID

Squash-merged task/50-0864-session-close-identity.

* pipeline(50-0864): move to 60-review

Task complete per Worker 3 — squash merged, advancing to review stage.

* seal(50-0864): session-close confirmation includes name and SID

Sealed-By: Overseer SID 6
Squash: 3276f1a
Worker: Worker 3 (SID 9)
Verdict: PASS

* pipeline: claim 50-0865-bridge-auto-terminate-stuck-sessions.md

* kill(50-0865): auto-terminate stuck sessions — bogus heuristic

Operator (2026-05-04): no reliable way to determine 'stuck.'
With activity/file (50-0868) coming, peer-liveness is observable
directly. Auto-terminate is redundant or needs new basis.

Moved to icebox with KILLED marker. Branch + worktree pruned.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(50-0866): move to 10-drafts pending operator stamp (postmortem sibling)

Same category as the killed 50-0865 — postmortem-derived
speculative fix. Operator stamps before Worker builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0867-consumer-hook-setup-guidance-loop-guard-compaction.md

* pipeline: move 50-0867 to 60-review — W1 complete, pending verification

* docs: add consumer-hooks.md — loop guard + compaction setup guide (50-0867)

Documents how TMCP consumers wire up loop guard (Stop hook) and
compaction notifications (PreCompact/PostCompact) including settings
JSON, env vars, 6-step checklist, and common pitfalls.

Sealed-By: Overseer

* seal: task 50-0867 — consumer hook setup guidance doc

Sealed-By: Overseer

* pipeline: claim 50-0868-build-per-session-touch-file-feature.md

* pipeline: move 50-0868 to 60-review — W1 complete, pending verification

* feat(activity): per-session touch-file feature for external activity monitoring (50-0868)

Adds activity/file/create|edit|get|delete action paths and session-level
debounced mtime-touch on inbound messages. Enables Overseer/external agents
to monitor session liveness via filesystem mtime without polling Telegram.

Sealed-By: Overseer

* seal: task 50-0868 — per-session activity touch-file feature

Sealed-By: Overseer

* chore(release): cut v7.4.0 release branch

* draft(10-0867): fix text-after-audio message ordering — per-session outbound queue

* review(10-0973): adversarial GPT-5.4 review of TMCP 7.4

Two high, two medium findings:
- H1: arbitrary host-file append primitive via session token
- H2: failed touches recorded as successful (silent wakeup black-hole)
- M1: activity suppression can drop only wakeup edge
- M2: delete/rotation claims success when file is still on disk

No critical bugs. Blast-radius expansion is the main concern.
Dispatched via Copilot Worker runSubagent(model: 'GPT-5.4 (copilot)').

Forced into tasks/notes/ (normally gitignored — one-off audit artifact).

* feat: update closeSessionById mock to include optional name parameter

* feat: update closeSessionById mock to include optional name parameter

* feat: refactor name-tag storage to a single editable string and update default behavior

* task(10-0870): align activity/file/edit response shape with create

Sibling endpoint cleanup task — drop ok+tmcp_owned, add hint field
to match the create-side reshape from this session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity): tighten hint phrasing + queue help-topic + spoon-feed follow-ups

- create.ts hint: 'Configure your watcher to call dequeue() when this file changes' (clearer action than the prior phrasing)
- 10-0870 reword to match new hint string
- 10-0871: replace hint with help('activity/file') pointer + write the help topic (full watcher recipe, mtime caveat, role permissions)
- 10-0872: watcher spoon-feeds dequeue via /mcp HTTP (saves a round-trip per wake)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: queue 10-0870 + 10-0871 (activity/file shape + help topic)

10-0870: align activity/file/edit response with create-side reshape.
10-0871: replace hint with help('activity/file') pointer + write the
help topic (depends on 0870).

10-0872 (watcher spoon-feeds dequeue) stays in drafts — Curator-owned
design with 7 open questions to pin first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: rewrite 10-0872 (watcher pre-drain), file 10-0873 (HTTP dequeue endpoint), capture show-typing nudge friction

10-0872: pivot from round-trip framing to turn-count framing per operator.
Watcher curls the dequeue endpoint, includes drained events in wake notification.
Skip-parameter idea iceboxed (operator: not needed if drain is genuine).

10-0873: sibling Worker-shippable task. Two paths considered:
dedicated /dequeue endpoint vs documented /mcp JSON-RPC use.
Operator leaning toward dedicated endpoint; pending confirmation.

00-ideas/show-typing-...: friction note. behavior_nudge_typing_rate
overfires show-typing on every receipt; operator clarified show-typing
is a composition-imminent signal only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0874 (suppress health-check when activity-file active)

Operator: health-check is misleading when activity-monitor already
maintains presence. Skip the prompt for sessions with active
activity-file registry entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: promote 10-0869 (custom name tags) drafts -> 40-queued

Operator directing Copilot Worker to this. Target 7.4 release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0869): claim — Worker SID 2

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(10-0869): custom name tags — single string, no robot emoji, name-tag action, profile integration

- Remove nametag_emoji from Session, ProfileData, all handlers
- Add Session.name_tag?: string (explicit override) + defaultNameTag() export
- buildHeader: wrap entire name_tag in monospace; color now inside the tag
- New action handlers: name-tag (get/set), name-tag/set alias
- profile/save: persist name_tag only when explicitly set
- profile/apply: apply name_tag from loaded profile
- profile/import: name_tag param (max 64 chars, no newlines)
- action.ts: register name-tag actions, replace nametag_emoji schema field
- Tests: +17 net new; all 2947 pass

* chore(10-0869): advance task to 60-review

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0872): mark superseded — long-poll dequeue is primary

Operator clarified architecture: long-poll dequeue is primary
(handles content delivery), Monitor is just a "kick the loop"
nudge replacing the old Telegram loop guard. Spoon-feeding events
through Monitor is over-design.

Spec kept in 10-drafts as a record. Status: superseded. No work.

See Curator memory feedback_dequeue_long_poll_primary_monitor_nudge.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0875 (remove ACTIVITY_FILE_DEQUEUE_CAP_S = 5)

Operator: long-poll dequeue is primary, Monitor is just a nudge.
The 5s cap added in 50-0868 was for the Monitor-as-primary
framing; that framing is reverted, cap goes too. Default 300s
stays. Per-session dequeueDefault stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0876 (major debounce on activity-file mtime touches)

Operator: mtime bump is an idle kick, not a per-message signal.
Scale ACTIVITY_SUPPRESS_MS from 10s to 60s, reset on any
session-token tool call, suppress while dequeue is in-flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): add one-nudge-per-cycle rule + state machine

Operator: after a nudge fires, no more bumps until a dequeue from
that session is observed. Dequeue is the reset signal. Prevents
nudge-storm if agent is unresponsive; multiple inbound messages
during idle coalesce to one mtime bump.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): broaden activity definition + add per-session configurable debounce

Operator: nudge inhibited by ANY session activity (animations,
typing, in-flight async sends, mid-multi-step turn). Total silence
required.

Add profile/kick-debounce action (parallel to profile/dequeue-default)
to make the window per-session configurable. Default 60_000ms,
range 30s..10min.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0877 (revert onboarding framing) + reframe 10-0871

10-0877: docs-only revert of onboarding service messages + help
docs to dequeue-primary, Monitor-optional-augment framing.
Companion to 10-0875 (cap removal) and 10-0876 (debounce).

10-0871 description updated with operator's framing — Monitor as
optional augment replacing telegram loop guard, NOT primary
delivery. Platform-agnostic help language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: claim 10-0875 — remove activity-file dequeue cap

* fix(dequeue): remove activity-file dequeue cap (ACTIVITY_FILE_DEQUEUE_CAP_S)

Dequeue now always honors session dequeueDefault (fallback 300s) regardless
of activity/file registration status. The 5s cap was introduced in 50-0868
under the premise that Monitor would wake agents frequently — new framing
reverses that: long-poll is the win, Monitor is just a nudge.

Removes:
- ACTIVITY_FILE_DEQUEUE_CAP_S constant from file-state.ts
- import of isActivityFileActive + ACTIVITY_FILE_DEQUEUE_CAP_S in dequeue.ts
- Activity-file override block in dequeue.ts (cap application)

Behavior: dequeue effective timeout = sessionDefault (or explicit max_wait).
No activity-file registration can shorten it below the session default.

Closes 10-0875

* chore: move 10-0875 to 60-review — dequeue cap removed, tests pass

* chore: claim 10-0876 — major debounce on activity-file touch

* tasks: remove duplicate 10-0869 from 10-drafts (canonical at 50-active post merge)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity-file): major debounce — idle-kick state machine

Replaces the leading+trailing 5s debounce with a true idle-kick state
machine. The bridge now waits for >= kickDebounceMs (default 60s) of
complete session silence before bumping the activity file mtime. This
prevents false wake-ups while the agent is actively processing.

State machine:
- nudgeArmed: one kick per dequeue cycle (re-armed on dequeue return)
- inflightDequeue: suppress kicks while agent is blocking in dequeue
- recordActivityTouch: any tool call resets the suppression window
- timer: single scheduled kick when window expires (no storm on bursts)
- setDequeueActive(false): re-arms cycle + resets lastActivityAt

New: profile/kick-debounce action (GET/SET per-session debounce window).
New: getKickDebounceMs/setKickDebounceMs in session-manager.ts.
New: 8 unit tests covering all state transitions.

Closes task 10-0876.

* chore(tasks): move 10-0876 to 60-review

* chore(tasks): claim 10-0877

* docs(onboarding): dequeue-primary framing — activity-file as optional augment

Add ONBOARDING_LOOP_PATTERN service message fired on session/start (both
single- and multi-session paths). Explains dequeue long-poll (300 s) as the
standard heartbeat and presents the activity-file pattern as an opt-in augment
for harnesses with a filesystem watcher.

Update docs/help/start.md Dequeue Loop section with the same opt-in callout.

No existing message text changed. No Monitor-as-primary framing was found in
the codebase — all onboarding messages were already dequeue-primary. This adds
the missing augment note per the operator directive.

Closes #10-0877

* chore(tasks): move 10-0877 to 60-review

* task(10-0878): file robot-emoji removal sweep, promote to queued

Operator authorized 2026-05-05 — strip 🤖 from default name tag
across 9 production surfaces (outbound-proxy, session start/reconnect,
disconnect/promote notices, /sessions header). Tests + docs covered;
input-rejection tests preserved.

Worker can claim.

* pipeline: claim 10-0870-activity-file-edit-response-shape-consistency.md

* pipeline: promote 10-0870 to 60-review, add bug + draft

- 60-review: 10-0870 activity-file/edit response shape (Worker 2 done,
  branch 10-0870 commit 171b1471, build+tests green)
- 00-ideas: checklist/update bug report
- 10-drafts: activity-file monitor onboarding improvement task

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0870): stamp APPROVED

* pipeline: claim 10-0871-activity-file-help-topic-and-hint-pointer.md

* pipeline: claim 10-0878 — robot-emoji sweep

* feat(10-0878): strip 🤖 from all TMCP output surfaces

Remove robot emoji from 9 production surfaces and matching tests.
Emoji fatigue — operator request 2026-05-05.

Surfaces updated:
- outbound-proxy.ts: multi-session header prefix
- tools/session/start.ts: approval dialog, denied reply,
  reconnect dialog, reconnect denied, online announce (pinned), comment
- session-teardown.ts: disconnect notice, governor promotion
- built-in-commands.ts: /sessions header

Tests updated (output assertions only):
- animation-state.test.ts: header mock + assertion
- startup-token-cleanup.test.ts: 3 pinned-message fixtures
- tools/session/close.test.ts: 4 disconnect-notice assertions

Unchanged (input-rejection tests):
- tools/session/start.test.ts:711 (validates robot in user input)
- rename.test.ts:130 (same)
- session-manager.test.ts:655,657 (negative assertion — already correct)

pnpm test: 2955 passed, 0 failed

* pipeline: move 10-0878 to 60-review — merged into release/7.4

* pipeline: claim 10-0873-http-dequeue-endpoint-for-watcher.md

* pipeline: move 10-0871 to 60-review — code review PASS, completion appended

* verify(10-0871, 10-0878): stamps committed — both APPROVED

* feat(10-0871): add activity/file help topic + redirect hint to help()

Adds docs/help/activity/file.md with full wake-nudge guide (purpose,
lifecycle, wake mechanism, watcher patterns, error modes). Registers
activity/file in RICH_TOPICS. Updates hint string in create.ts and edit.ts
to "Call help('activity/file') now". Adds hermetic test for help topic.

Also applies 10-0870 shape alignment to edit.ts (ok+tmcp_owned → hint).
Includes 10-0870 dep since that branch not yet squash-merged to dev.

Squash-merged from branches 10-0871 (includes 10-0870). Sealed-By: Overseer

* seal(10-0870, 10-0871, 10-0878): TMCP batch seal

10-0870: activity/edit shape alignment — included in 10-0871 squash (9453f0b)
10-0871: activity/file help topic + hint redirect — squash on dev
10-0878: robot emoji removal — merged to release/7.4 (commit 2ddd78d)

Sealed-By: Overseer

* verify(10-0875, 10-0876, 10-0877): stamps committed — 0875 APPROVED, 0876 NEEDS_REVISION (inflightDequeue leak), 0877 APPROVED

* seal+return(10-0875, 10-0876, 10-0877):

10-0875: APPROVED — dequeue cap removed, sealed 70-done
10-0877: APPROVED — onboarding augment framing, sealed 70-done
10-0876: NEEDS_REVISION — inflightDequeue leaked on early returns in dequeue.ts; returned to 50-active for fix

Sealed-By: Overseer

* stamp 10-0869 NEEDS_REVISION: missing profile-load tests + dogfood docs

* 10-0869 → 50-active (NEEDS_REVISION)

* stamp 10-0873 NEEDS_REVISION: AC6 help topic not updated (hint text + dequeue HTTP doc missing)

* stamp 10-0873 APPROVED (round 2): AC6 fix confirmed — hint text + dequeue-http help doc

* feat(10-0873): add GET|POST /dequeue HTTP endpoint + extract runDrainLoop

- New src/dequeue-endpoint.ts: GET/POST /dequeue route, token validation, shape parity with MCP tool
- New src/dequeue-endpoint.test.ts: 17 test cases (happy path, 401 paths, instant poll, session_closed)
- src/tools/dequeue.ts: extract runDrainLoop to shared fn; fix setDequeueActive leak (session_closed check before flag set)
- src/tools/activity/create.ts: update hint text to reference GET /dequeue HTTP URL
- docs/help/dequeue-http.md: new help topic with curl/PowerShell/Node fetch examples
- src/tools/help.ts: register dequeue-http in RICH_TOPICS + DESCRIPTION

Squash of branch 10-0873 (493ea987 + 69ea884e)

* seal 10-0873 → 70-done/2026/05/05/ — APPROVED

Sealed-By: Overseer

* fix(10-0876): move setDequeueActive after session_closed guard in dequeue.ts

Extract runDrainLoop() from dequeue handler and guard setDequeueActive(sid, true)
AFTER the session_closed check. Previously the flag was set before the check,
leaving it stuck true for dead sessions (session_closed early return never
reached the finally that resets to false).

Cherry-pick of 493ea987 src/tools/dequeue.ts changes from branch 10-0873.

2955 tests pass.

* stamp 10-0876 APPROVED (round 2): inflightDequeue gap fixed by 10-0873 runDrainLoop

* test(10-0869): add name_tag branch coverage to apply and load tests

* docs(10-0869): curator dogfood walkthrough for custom name tags

* tasks(10-0869): advance to 60-review — fix-pass complete

* move 10-0876 to 60-review: APPROVED stamp committed d398317

* seal 10-0876: Major debounce on activity-file mtime touches

All 7 ACs passed. inflightDequeue gap fixed by 10-0873 runDrainLoop
extraction (setDequeueActive(sid,true) moved to after session_closed
check; try/finally guarantees reset). Cherry-picked to release/7.4
as 6423998.

Sealed-By: Overseer

* stamp 10-0869 APPROVED (round 2): both gaps resolved — name_tag tests + dogfood doc

* seal 10-0869: TMCP custom name tags — fix-pass complete

All 8 ACs satisfied. name_tag tests added to apply.test.ts (3) and
load.test.ts (2). Dogfood walkthrough at docs/dogfood/10-0869-name-tags.md.
Feature on dev + release/7.4 (e191714).

Sealed-By: Overseer

* fix(review): address all PR #167 review findings

Critical fixes:
- dequeue-endpoint: wrap async Express handler in try/catch with next(err)
- dequeue-endpoint: remove connection_token (accepted but silently ignored)
- name-tag: add backtick validation to prevent broken Markdown in headers
- apply.ts: fall back to legacy nametag_emoji field when name_tag missing
- ActivityFileState: remove phantom absorbedCount field (new file, no compat needed)

Moderate fixes:
- file-state.ts: rewrite module doc (removed false MAX_INTERVAL_MS/ACTIVITY_SUPPRESS_MS promises)
- file-state.ts: fix validateFilePath path-traversal check (split on separators, not substring)
- file-state.ts: replace console.warn with dlog('tool', ...)
- import_profile: add backtick/newline regex to name_tag Zod schema

DRY / minor:
- name-tag.ts: extract resolveNameTag() exported helper
- outbound-proxy.ts: use resolveNameTag() from name-tag.ts, remove duplicate expression
- dequeue-endpoint.ts: extract parseIntParam() helper, remove redundant isFinite check

Docs:
- changelog/2026-05-04_v7.4.0.md: add missing entries (name tags, HTTP dequeue, kick-debounce, fixes, breaking changes)
- changelog/unreleased.md: document all review fixes

* feat(10-0880): runtime-conditional onboarding_loop_pattern with Monitor wiring example

* feat(10-0880): refine loop framing — dequeue IS the loop, watcher additive, Claude Code should

* test(10-0880): update start help test assertion — 5 min not 5 minutes

* feat(10-0880): tighten onboarding_loop_pattern phrasing

Replace dense single-paragraph message (with inline bash/PS snippets and
soft "you should also wire up" framing) with two numbered essentials and
a breadcrumb to help topics. Operator directive: imperative, precise,
breadcrumb to depth — agents do not need max_wait values, mtime detail,
or runtime examples in the startup beat.

Before: ~115 words, inline bash + PS, "you should also wire up".
After: ~45 words, two numbered bits, "Details: help('start'),
help('dequeue'), help('activity/file')."

Use template literal with real newlines (avoids hook false-positive on
':\n' Windows-drive-letter pattern). No tests pinned the literal
string. Full suite passes (2978/2978).

* feat(10-0880): trim session/start response to {token, sid, hint}

Operator directive 5/6: response payload was over-stuffed pollution.
Strip to just what an agent needs at the top of the loop.

Drop from fresh-path response: suffix, sessions_active, action, pending,
discarded, fellow_sessions, connection_token. Drop from reconnect-path
response: sessions_active, action, pending. Mutation that set
res.fellow_sessions on multi-session join also removed.

connection_token (duplicate-session detection) is removed from the
visible response. dequeue still accepts the param for legacy callers
(no error path) but new agents will not be passing it. Detection feature
is therefore quiescent — kill it in a follow-up if desired.

DESCRIPTION updated to: "Returns { token, sid, hint } — call dequeue(token)
next to enter the loop." Old self-referential "Call help() first ..."
tail dropped.

Tests in start.test.ts updated for new shape (the two toEqual
assertions). Other start.test.ts cases use field-by-field assertions
and pass unchanged. Other suites that may probe the dropped fields are
operator-acknowledged as breaking ("ignore test failures for now") — to
be cleaned up under the broader test-language audit.

* feat(10-0880): onboarding_loop_pattern v8 — welcome framing, runtime-agnostic

Cold-read assessment surfaced two soft spots:
- "Stay in the loop" presumed the loop already existed (fresh agent had no
  context) → replaced with "Welcome to the loop. Stay in it." which
  establishes the loop AND positions the agent as already inside it.
- Capitalized "(Monitor)" parenthetical was a Claude-Code-specific cue;
  agents in other harnesses might miss it → replaced with "Check your
  tools for an option to monitor a file" which is runtime-agnostic.

Bit 1 also gains the explicit token signature (dequeue(token)) so a fresh
agent does not have to hunt the dequeue tool description for the param.

Same length, same breadcrumbs, same numbered structure.

* fix(10-0885): apply 18 language-conciseness findings from audit 10-0884

High (6): help.ts DESCRIPTION, ONBOARDING_BUTTONS_TEXT, ONBOARDING_MODALITY_PRIORITY,
send.md audio+text, guide.md keyboard taxonomy, start.md activity watcher
Medium (9): ONBOARDING_PROTOCOL, ONBOARDING_PRESENCE_SIGNALS, ONBOARDING_HYBRID_MESSAGING,
send:choice hint, send:animation hint, send.ts MISSING_CONTENT, activity/create hint,
action.ts hint, session/start DESCRIPTION
Low (3): SESSION_DENIED hint, help/index intro, help/animation REST trigger

* fix(10-0887): apply 20 response-payload audit findings from 10-0886

High (5): remove sent/split bool from send, empty dequeue.empty, approved from approve, started/timeout from show-typing, dm/delete/cancel {} confirmed
Medium (8): routed, ok, loaded, saved, rolled, updated, cancelled booleans removed; session/close reason removed; animation/status unwrapped
Low (3): activity/get registered, message/pin unified, animation/cancel false-case preserved

* test(10-0882): scrub content-string assertions and stale payload-field checks

- Remove prose toContain assertions (split:true, cancelled:true, empty:true, action, fellow_sessions, discarded, connection_token, pending)
- Replace doc-string checks with typeof/length guards in first-use-hints, service-messages, shutdown, dequeue, help tests
- All 2978 tests pass

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
electricessence added a commit that referenced this pull request May 7, 2026
… cache fix (#168)

* task: move 20-499 to 60-review — Worker 2 complete

* feat(20-499): tool file restructure — namespace subdirectories (session/, reminder/, profile/, etc.)

* seal: 20-499 — tool file namespace restructure (2026-04-25)

Sealed-By: Overseer

* feat: update import paths and fix lint errors in hook-animation tests; remove unused imports in query and delete tests; add async flag to audio-path response_format tests

* chore: update subproject commit reference in .engine file

* feat: implement recording indicator management for async voice sends; suppress typing emission during audio jobs

* docs(release): add release-branching-process; task: 4 new drafts (05-0825, 10-0823, 15-0824, 20-0822)

- docs/release-branching-process.md — codifies dev → release/X.Y → master flow
- 05-0825 — bug: question answer edits text but inline keyboard remains
- 10-0823 — first-dequeue onboarding bundle + presence-cascade companion nudge
- 15-0824 — react fallback for unsupported emojis with caller hint
- 20-0822 — hybrid send caption-restates-audio detector (gated on corpus + FP rate)

* task: promote 05-0825 (button-clear bug) + 15-0824 (emoji fallback) to 40-queued

Both ready for worker pickup — clear scope, well-defined acceptance criteria, no operator-blocking ambiguity.

Held in drafts:
- 10-0823 onboarding bundle (architectural — needs spec audit first)
- 20-0822 duplication detector (gated on corpus + FP rate per operator direction)

* pipeline: claim 05-0825-question-answer-edits-text-but-keyboard-remains.md

* pipeline: claim 15-0824-react-emoji-fallback-with-hint.md

* chore(changelog): clean unreleased.md — drop v7.1.0 carryover, retitle v7.2.0

* pipeline: move 05-0825 to 60-review

* fix(choose): clear inline keyboard after question is answered

Removes highlightedRows arg from ackAndEditSelection in choose.ts
callback hook so reply_markup falls back to {inline_keyboard:[]}
in the same editMessageText call. Buttons now clear immediately on
answer; choice.ts highlight path intentionally unchanged.

2752/2752 tests passing.

Sealed-By: Overseer
Task: 05-0825

* pipeline: seal 05-0825 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 05-0825

* pipeline: move 15-0824 to 60-review

* feat(react): emoji alias fallback with hint for unsupported reactions

Adds UNSUPPORTED_EMOJI_ALIASES map (👂→👀, 🤚→👍, 🧠→🤔, 👁→👀,
🦻→👀). Unsupported-but-aliased emojis remap silently, returning
ok:true + applied:[target] + hint:emoji_alias_applied + hint_detail.
Unmapped unsupported emojis still return REACTION_EMOJI_INVALID.
Temporality rules (temp/permanent/TEMPORARY_BY_DEFAULT) respected.
All 7 alias paths tested; docs/help/reactions.md updated.

2762/2762 tests passing.

Sealed-By: Overseer
Task: 15-0824

* pipeline: seal 15-0824 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 15-0824

* task: 15-0824 completion notes; new draft 05-0826 (recording-indicator findings)

- 70-done/.../15-0824: append Completion section with branch/commit/changes (Worker edit not picked up by seal commit — pipeline gap noted)
- 10-drafts/05-0826: 4 recording-indicator findings from Copilot CLI / GPT-5.3-Codex review of commit 2473daa

* task: 15-0827 — seal commit misses Worker completion notes (3 fix options)

* chore(test): chain typecheck before vitest run; task 05-0828 to fix 99 pre-existing test TS errors

pnpm test now runs `tsc --noEmit -p tsconfig.eslint.json && vitest run`.
This will fail until the 99 errors in 05-0828 are resolved.

Operator direction: "typecheck should always be present as part of pnpm test."

* task: promote 05-0828 (fix 99 TS errors in test files) to 40-queued

* pipeline: claim 05-0828-fix-99-typescript-errors-in-test-files.md

* pipeline: return 05-0828 to 40-queued (Worker 2 unresponsive, zero progress)

* pipeline: claim 05-0828-fix-99-typescript-errors-in-test-files.md

* pipeline: move 05-0828 to 60-review

* fix(test): resolve 99 TypeScript errors across 25 test files

Fixes all pre-existing type errors that were hidden by tsc/vitest/eslint
config gaps. pnpm test now chains typecheck before vitest; all 25 test
files pass strict tsc. Type-only changes — no production code modified.
2762/2762 tests passing.

Sealed-By: Overseer
Task: 05-0828

* pipeline: seal 05-0828 → 70-done/2026/04/25

Sealed-By: Overseer
Task: 05-0828

* task: 05-0829 — investigate worker haiku compaction + cross-worker working-tree bleed (priority 5)

* task: 05-0829 — root cause confirmed (staged-but-uncommitted recovery miss); 2 concrete fixes identified

* task(queue): add 05-0830 choice callback highlight-then-collapse

* pipeline: claim 05-0830-choice-callback-highlight-then-collapse.md

* feat(choice): highlight chosen button then collapse keyboard on callback (05-0830)

* pipeline: seal 05-0830 → 70-done/2026/04/25

Sealed-By: Overseer

* pipeline: remove duplicate 60-review copy of 05-0830 (already in 70-done)

* task(queue): add 05-0831 wire attachHookRoutes into src/index.ts

* pipeline: claim 05-0831-wire-attach-hook-routes-in-index.md

* task(queue): add 10-0831 event system + 15-0832 reporting tool

* pipeline: claim 10-0831-event-system-rest-endpoint.md

* feat(index): wire attachHookRoutes to make POST /hook/animation reachable (05-0831)

Squash-merge of branch 05-0831 — verified APPROVED (0 critical, 0 major, 0 minor).

Note: hook-animation will be removed in a follow-on task as /event subsumes this functionality.

Sealed-By: Overseer

* pipeline: seal 05-0831 → 70-done/2026/04/25

Sealed-By: Overseer
Note: hook-animation teardown follows in subsequent task per /event pivot.

* pipeline: claim 15-0832-event-log-reporting-tool.md

* docs(animation): remove obsolete /hook/animation; point to /event system

* chore(profiles): remove bundled profile examples; replace with docs/profiles.md schema doc

* chore(tasks): return 15-0832 to 40-queued — shutdown interrupted claim

* chore(leakage): scrub cortex.lan refs from graceful-shutdown SKILL + chat/info doc

* feat: Implement various improvements and fixes across multiple tasks

- Remove `log/dump` action and replace with `log/get` and `log/delete` pattern for trace data management.
- Update agent approval system to use tokens and tickets instead of user-controlled names for session approvals.
- Add tests for high-risk branches identified in Codex review, covering voice chunk failures and approval cleanup timeouts.
- Implement cleanup for expired callback buttons in interactive messages to prevent dead UI.
- Fix base reaction overwrites for temporary reactions to ensure proper visibility and behavior.
- Extend recording indicator to remain active until voice message delivery is confirmed.
- Define content spec for TMCP service messages, ensuring ultra-compressed messaging and help breadcrumbs.
- Fix shutdown and session close lifecycle to ensure proper handling of active and inactive sessions.

* feat: Add profiles leakage audit document to address workflow-specific content concerns

* chore(leakage): remove cortex.lan refs from 10-0835 and 10-418

- 10-0835: replaced internal Curator memory key citation with prose
- 10-418: generalized hostname grep pattern in security audit procedure

* Merge remote-tracking branch 'origin/master' into dev

* task(15-0837): draft — rewire /event compacting kind to compacting preset (not working)

* task(15-0837): expand — add recovering preset + compacted side-effect

* task(15-0837): simplify — preset name == event kind, drop KIND_ANIMATION map

* task(15-0837): promote to queued — preset name == event kind

* task(15-0838): draft — Curator shutdown pre-shutdown metrics report

* seal(10-0831): event system REST endpoint — implementation on release/7.2

Sealed-By: Overseer

* pipeline: move 15-0832 to 60-review — verification pending

* seal(15-0832): event-log reporting tool — scripts/event-report.mjs

Sealed-By: Overseer

* pipeline: promote 10-0823 (onboarding bundle) + 10-0835 (profiles hygiene) to 40-queued

* pipeline: claim 10-0835-profiles-leakage-audit.md

* seal(10-0835): profiles leakage audit — fix already applied in 02f4163

Sealed-By: Overseer

* pipeline: claim 10-0823-first-dequeue-onboarding-bundle.md

* pipeline: promote 20-0822 (hybrid duplication detector) — operator priority bump

* fix(skills): correct dequeue parameter name timeout→max_wait across skill docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(onboarding): first-dequeue bundle — hybrid, modality, presence, conditional tail

Adds 3 new onboarding service messages (onboarding_hybrid_messaging,
onboarding_modality_priority, onboarding_presence_signals) and a
conditional tail (onboarding_no_pending_yet, gated on discarded === 0)
to the first-dequeue bundle. Agents now enter context with full protocol
awareness. 2837 tests pass.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 20-0822-hybrid-duplication-detector.md

* skills(spec): author 12 purpose-driven specs for telegram-mcp skill cluster (Curator pass)

* skills(uncompressed): author 12 companion uncompressed.md, reconcile SKILL.md gaps (animation timeout, dequeue event-class table, dump-handling tool name, graceful-shutdown force:true)

* skills(SKILL): generalize fleet role names — Curator/Overseer/Worker/Deputy → governor/supervising/subordinate (TMCP-public hygiene)

* pipeline: icebox 15-0837 — superseded by 7.2.2 BUILTIN_PRESETS implementation

* draft+queue(20-0841): spike — pre-stage node_modules in TMCP worktrees (auto-queued: research with concrete output)

* draft(15-0843): help('shutdown') must carry canonical governor procedure verbatim

Filed at operator request after Curator quiz turn. Worker-delegatable doc-fix
on docs/help/shutdown.md Governor Shutdown section.

* pipeline: claim 20-0841-spike-worktree-node-modules-prestaging.md

* seal: 20-0841 — spike: pre-stage node_modules in TMCP worktrees

Findings: Candidate 4 (worktree-create hook) + Candidate 1 (shared virtual store)
recommended. Per operator guidance: per-repo sanctioned script on Worker allowlist.
5 operator decisions remain open in findings doc for implementation follow-on.

Sealed-By: Overseer

* fix(startup): remove blocking operator-prompt path from session-startup SKILL

* draft: auto-pin blocking questions feature (operator directive 2026-04-26)

* triage: route 6 tasks to curator-only (Curator-authored or delegation: curator)

- 10-0836: TMCP skills overhaul — Curator-led, multi-cycle
- 10-737: hook hash fragility reform — Curator authors design doc directly
- 15-734: hook error disambiguation — Curator authors hook patch directly (trust boundary)
- 20-721: V7 master merge readiness — Curator orchestrates audit + PR
- 30-470: remove dead registerTool calls — Curator must revise spec (premise incorrect per W2)
- friction-pnpm-install-worktree-block: explicit delegation: curator

* triage: route 3 tasks to needs-refinement (require Curator spec before Worker claim)

- 10-733: zombie session reconnect security — needs Curator spec, Worker cannot define security boundary
- 15-736: loud-on-anomaly observability — "Curator should spec anomaly taxonomy before claim"
- 15-349: compaction event logging — multi-phase, deletes hooks (Curator trust boundary)

* queue: 05-0826 recording-indicator-refcount-race-and-suppression-gaps (operator-approved)

* queue: 05-0829 investigate-worker-haiku-compaction-and-handoff-bleed (operator-approved)

* note: 05-0829 — verify-first guidance from operator before implementing fixes

* seal: spike-0841 pnpm-worktree-prestaging (operator-verified, direction set)

* queue: 15-0827 seal-commit-misses-worker-completion-notes (operator-approved)

* queue: 15-0843 help-shutdown-canonical-governor-procedure (operator-approved)

* queue: 15-0848 reply-target-not-active-question-no-skip (operator-approved)

* queue: 15-0838 curator-shutdown-metrics-report (operator-approved)

* queue: 20-draft session-joined-fellow-service-message (operator-approved)

* docs: standardize session memory save format (10-0548)

Update telegram-mcp-session-startup SKILL.md and help session/start.md
to document the two-format standard: Minimal (raw integer in
session.token) and Full (YAML body in session.md). Remove PIN field
references; update token formula to use 'suffix' not 'pin'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(help): add index topic to overview and schema describe (10-0549)

- buildOverview(): mention help(topic: 'index') for categorized skill index
- topic.describe(): add 'index' option so schema introspection surfaces the topic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0826-recording-indicator-refcount-race-and-suppression-gaps.md

* feat(send): hybrid caption-duplication detector (Jaccard-based) (squash 20-0822)

Adds detectCaptionDuplication (Jaccard similarity, content-word tokenisation,
ratio gates) wired into all three send paths. Fires NUDGE_CAPTION_DUPLICATION
when caption appears to restate audio. All 2860 tests pass.

Also: draft task 15-0849 tts-underscore-string-replace (operator-filed 2026-04-26)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal: 20-0822 hybrid-duplication-detector — Jaccard detector merged, all tests pass

Note: ship-criteria corpus validation skipped; conservative thresholds expected
to hold. Monitor for FP noise in production.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* queue: 15-0849 tts-underscore-string-replace (operator-directed, scope confirmed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tasks): normalize 70-done/20260424 → 70-done/2026/04/24 (canonical date format)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0829-investigate-worker-haiku-compaction-and-handoff-bleed.md

* pipeline: claim 15-0849-tts-underscore-string-replace.md

* pipeline: claim 15-0843-help-shutdown-canonical-governor-procedure.md

* seal: 05-0829 Worker recovery investigation — both bugs already fixed, skill promoted

Bug 1 (Overseer recovery staged-state signal): already in context/refresh.md.
Bug 2 (Worker staged-state Worktree Gate): promoted from memory to task-execution/SKILL.md.
Postmortem in Curator repo. All 4 unknowns resolved.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(docs): MD032 blank line before list in session/start help (Copilot #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(recording): epoch guard for refcount race + typing suppression gaps (05-0826)

Squash-merged branch 05-0826. Epoch token prevents stale async callbacks from
corrupting refcount; suppression-gap fixes ensure typing indicator clears reliably.

Sealed-By: Overseer

* fix(help/shutdown): canonical governor shutdown procedure with explicit token path (15-0843)

Squash-merged branch 15-0843. Rewrites shutdown.md into Participant/Governor sections
with verbatim operator-stated sequences; adds wipe-before-shutdown ordering assertion.

Sealed-By: Overseer

* chore: seal 05-0826 and 15-0843 → 70-done/2026/04/26

Sealed-By: Overseer

* fix(button-helpers): off-target reply guard in pollButtonOrTextOrVoice (15-0848)

Squash-merged branch 15-0848. Three-way rule: ambiguous (no reply_to), on-target
(reply matches question), off-target (reply ≠ question → re-enqueue, prompt open).

Sealed-By: Overseer

* chore: seal 15-0848 → 70-done/2026/04/26

Sealed-By: Overseer

* chore: seal 15-0827 (investigation) → 70-done/2026/04/26

Root cause confirmed: Overseer seal renames task file from dev branch which lacks
Worker's Completion section. Fix is Overseer-side (include complete() commit or
copy Completion at seal time). No Worker SKILL change needed.

Sealed-By: Overseer

* feat(tts): normalize ALL_CAPS_WITH_UNDERSCORES identifiers for speech (15-0849)

Squash-merged branch 15-0849. Adds normalizeCapsForTts() — converts identifiers
like SESSION_JOINED to "session joined" in TTS output. Toggle off via
TTS_CAPS_NORMALIZE=false.

Sealed-By: Overseer

* chore: seal 15-0849 → 70-done/2026/04/26

Sealed-By: Overseer

* pipeline: claim 15-0838-curator-shutdown-metrics-report.md

* feat(skill): graceful-shutdown step 6 compaction metrics report (15-0838)

Squash-merged branch 15-0838. Updated graceful-shutdown skill in electrified-cortex
to add Step 6 (pre-shutdown compaction metrics report via event-report.mjs).

Sealed-By: Overseer

* chore: seal 15-0838 → 70-done/2026/04/26

Sealed-By: Overseer

* refactor(session): extract SESSION_JOINED_FELLOW to service-messages.ts (20-draft)

Squash-merged branch 20-draft-fellow. Eliminates hardcoded inline string in
session/start.ts; governor/non-governor paths now both use SERVICE_MESSAGES constants.

Sealed-By: Overseer

* chore: seal 20-draft → 70-done/2026/04/26

Sealed-By: Overseer

* feat(guidance): lazy trigger delivery for onboarding messages (10-0581)

Squash-merged branch 10-0581. Moves 5 session-start onboarding messages to
trigger-based delivery; adds help('guidance') taxonomy topic.

Sealed-By: Overseer

* chore: promote 15-0850 to 40-queued (operator approved 2026-04-26)

* pipeline: claim 15-0850-recovering-animation-replace-with-compacted-notify.md

* feat(compaction): replace recovering animation with compacted notify on first post-compacted activity (15-0850)

Squash-merged from branch 15-0850.
Sealed-By: Overseer

* feat(animation): add status API, stale-on-idle warning, timeout default shift (15-763)

- animation/status action: returns active animation state per session; governor variant lists all
- Stale-on-idle dequeue warning: animation_stale_warning event after ≥30s idle (120s cooldown)
- Timeout default: 600s → 60s across send, show, animation-state
- Help docs: animation.md + presence.md updated with lifecycle rules

Sealed-By: Overseer

* docs(send): add messaging spectrum and audio format rules (20-766)

7-row spectrum table (text-only long through audio-only) with trigger conditions.
Audio format rules: natural language, fluid prose, minimal punctuation, no
voice-unfriendly content.

Sealed-By: Overseer

* fix(lint): address Copilot MD055 + line-length + regex-hoisting comments (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add .code-reviews/ to .gitignore (eval artefacts contain local paths)

* eval(10-0858): haiku-class L1 vs sonnet-class L2 comparison report

Squashed-from: 10-0858
Sealed-By: Overseer

* fix(10-0859): extract deliverCaptionDuplicationNudge helper

Squashed-from: 10-0859
Sealed-By: Overseer

* fix(10-0860): correct presence.md stale animation warning shape

Docs said service_message with event_type; actual impl returns dequeue
update item with event: animation_stale_warning.

Squashed-from: 10-0860
Sealed-By: Overseer

* fix(10-0861): clarify animation/status SID variant return shape in docs

SID variant implemented by 15-763; docs updated to disambiguate
single-session vs multi-session response shapes.

Squashed-from: 10-0861
Sealed-By: Overseer

* seal: task 15-0863 — Verify choose callback cannot fire twice

Static analysis confirms _callbackHooks one-shot de-registration is
synchronous before any await. Node.js single-thread guarantee ensures
exactly one delivery for all interactive modes (choose, confirm, question).

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: move 15-0862 to 60-review

* seal: task 15-0862 — Add 250ms delay between button color-flip and collapse

BUTTON_COLLAPSE_DELAY_MS=250 constant; gated on real button press only
(callbackQueryId truthy). Persistent path passes delayMs=0. All 2930
tests passing. New fake-timer gate test added.

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove async from handleAnimationStatus function and adjust test tick handling

* feat(tasks): file 50-0865 + 50-0866 from Overseer wedge postmortem

- 50-0865: bridge auto-terminate for stuck sessions (no recovery
  after N consecutive unhealthy events)
- 50-0866: TTS render timeout for hybrid sends (prevent silent
  indefinite block)

Both surface from 2026-05-03 5-alarm Overseer wedge incident
where auto-recovery silently gave up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0867 consumer hook setup guidance

Document the loop-guard + compaction-notification hook patterns
for outside TMCP consumers. Operator (2026-05-04): patterns exist
in-house but are poorly documented for fresh integrators.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0868 build per-session touch-file feature

Operator (2026-05-04): ship the bridge-side feature now without
waiting for Monitor wakeup-semantics validation. Per-session touch
file with random-hash filename, leading+trailing-suppressed
debounce, activity-aware reset, lifecycle tied to session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): flip ownership — agent provides path, TMCP just touches

Operator (2026-05-04 late): TMCP doesn't allocate/create/delete the
touch file. Agent owns it, registers path via monitor/register.
TMCP records and touches; nothing else. Cleaner separation,
opt-in by construction, TMCP filesystem stays empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): hybrid opt-in — agent OR TMCP supplies path

Operator (2026-05-04 final): monitor/enable supports two shapes:
- agent-supplied path: TMCP records, never creates/deletes
- TMCP-supplied: TMCP generates random hash, owns lifecycle
Either way: opt-in only. Without enable, zero I/O.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): rename to session-file CRUD, agnostic naming

Operator (2026-05-04): drop the Monitor framing — TMCP exposes a
filesystem hook, consumer chooses how to watch. CRUD verbs:
session-file/create, session-file/edit, session-file/delete,
session-file/get. Path-supplied vs TMCP-generated still both
supported; ownership rules carry through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): correct namespace to session/file/ (under existing session/)

Operator (2026-05-04): not session-file/, but session/file/ —
extends the existing session/ namespace (session/start, session/
close, session/list).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): final namespace activity/file/ + decision rationale

Operator (2026-05-04 final): activity/file/ wins. The file signals
activity, doesn't record session state. Top-level namespace
parallel to session/, leaves room for sibling activity hooks
(presence, typing, etc) later.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): auto-shorten dequeue default to 5s on activity/file/create

Operator (2026-05-04): familiar Claude pattern. Reverts on delete.
Per-call override still respected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): clarify max_wait override is temporary, default = 5min

Operator (2026-05-04): activity/file/create applies a TEMPORARY
override (not a profile mutation). activity/file/delete clears it
back to the standard 5min default. Per-call still trumps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note agent can override the override via profile/dequeue-default

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note loop-guard becomes redundant with activity/file in use

Operator (2026-05-04): emergent simplification — loop-guard exists
to catch silent stuck agents during 300s blocking dequeues. With
5s default + kicker, that failure mode shrinks 60x. Future task:
deprecate + remove loop guard once activity/file adopted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0864-session-close-confirm-show-identity.md

* feat(50-0864): session-close confirmation includes name and SID

Squash-merged task/50-0864-session-close-identity.

* pipeline(50-0864): move to 60-review

Task complete per Worker 3 — squash merged, advancing to review stage.

* seal(50-0864): session-close confirmation includes name and SID

Sealed-By: Overseer SID 6
Squash: 3276f1a
Worker: Worker 3 (SID 9)
Verdict: PASS

* pipeline: claim 50-0865-bridge-auto-terminate-stuck-sessions.md

* kill(50-0865): auto-terminate stuck sessions — bogus heuristic

Operator (2026-05-04): no reliable way to determine 'stuck.'
With activity/file (50-0868) coming, peer-liveness is observable
directly. Auto-terminate is redundant or needs new basis.

Moved to icebox with KILLED marker. Branch + worktree pruned.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(50-0866): move to 10-drafts pending operator stamp (postmortem sibling)

Same category as the killed 50-0865 — postmortem-derived
speculative fix. Operator stamps before Worker builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0867-consumer-hook-setup-guidance-loop-guard-compaction.md

* pipeline: move 50-0867 to 60-review — W1 complete, pending verification

* docs: add consumer-hooks.md — loop guard + compaction setup guide (50-0867)

Documents how TMCP consumers wire up loop guard (Stop hook) and
compaction notifications (PreCompact/PostCompact) including settings
JSON, env vars, 6-step checklist, and common pitfalls.

Sealed-By: Overseer

* seal: task 50-0867 — consumer hook setup guidance doc

Sealed-By: Overseer

* pipeline: claim 50-0868-build-per-session-touch-file-feature.md

* pipeline: move 50-0868 to 60-review — W1 complete, pending verification

* feat(activity): per-session touch-file feature for external activity monitoring (50-0868)

Adds activity/file/create|edit|get|delete action paths and session-level
debounced mtime-touch on inbound messages. Enables Overseer/external agents
to monitor session liveness via filesystem mtime without polling Telegram.

Sealed-By: Overseer

* seal: task 50-0868 — per-session activity touch-file feature

Sealed-By: Overseer

* chore(release): cut v7.4.0 release branch

* draft(10-0867): fix text-after-audio message ordering — per-session outbound queue

* review(10-0973): adversarial GPT-5.4 review of TMCP 7.4

Two high, two medium findings:
- H1: arbitrary host-file append primitive via session token
- H2: failed touches recorded as successful (silent wakeup black-hole)
- M1: activity suppression can drop only wakeup edge
- M2: delete/rotation claims success when file is still on disk

No critical bugs. Blast-radius expansion is the main concern.
Dispatched via Copilot Worker runSubagent(model: 'GPT-5.4 (copilot)').

Forced into tasks/notes/ (normally gitignored — one-off audit artifact).

* feat: update closeSessionById mock to include optional name parameter

* feat: update closeSessionById mock to include optional name parameter

* feat: refactor name-tag storage to a single editable string and update default behavior

* task(10-0870): align activity/file/edit response shape with create

Sibling endpoint cleanup task — drop ok+tmcp_owned, add hint field
to match the create-side reshape from this session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity): tighten hint phrasing + queue help-topic + spoon-feed follow-ups

- create.ts hint: 'Configure your watcher to call dequeue() when this file changes' (clearer action than the prior phrasing)
- 10-0870 reword to match new hint string
- 10-0871: replace hint with help('activity/file') pointer + write the help topic (full watcher recipe, mtime caveat, role permissions)
- 10-0872: watcher spoon-feeds dequeue via /mcp HTTP (saves a round-trip per wake)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: queue 10-0870 + 10-0871 (activity/file shape + help topic)

10-0870: align activity/file/edit response with create-side reshape.
10-0871: replace hint with help('activity/file') pointer + write the
help topic (depends on 0870).

10-0872 (watcher spoon-feeds dequeue) stays in drafts — Curator-owned
design with 7 open questions to pin first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: rewrite 10-0872 (watcher pre-drain), file 10-0873 (HTTP dequeue endpoint), capture show-typing nudge friction

10-0872: pivot from round-trip framing to turn-count framing per operator.
Watcher curls the dequeue endpoint, includes drained events in wake notification.
Skip-parameter idea iceboxed (operator: not needed if drain is genuine).

10-0873: sibling Worker-shippable task. Two paths considered:
dedicated /dequeue endpoint vs documented /mcp JSON-RPC use.
Operator leaning toward dedicated endpoint; pending confirmation.

00-ideas/show-typing-...: friction note. behavior_nudge_typing_rate
overfires show-typing on every receipt; operator clarified show-typing
is a composition-imminent signal only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0874 (suppress health-check when activity-file active)

Operator: health-check is misleading when activity-monitor already
maintains presence. Skip the prompt for sessions with active
activity-file registry entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: promote 10-0869 (custom name tags) drafts -> 40-queued

Operator directing Copilot Worker to this. Target 7.4 release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0869): claim — Worker SID 2

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(10-0869): custom name tags — single string, no robot emoji, name-tag action, profile integration

- Remove nametag_emoji from Session, ProfileData, all handlers
- Add Session.name_tag?: string (explicit override) + defaultNameTag() export
- buildHeader: wrap entire name_tag in monospace; color now inside the tag
- New action handlers: name-tag (get/set), name-tag/set alias
- profile/save: persist name_tag only when explicitly set
- profile/apply: apply name_tag from loaded profile
- profile/import: name_tag param (max 64 chars, no newlines)
- action.ts: register name-tag actions, replace nametag_emoji schema field
- Tests: +17 net new; all 2947 pass

* chore(10-0869): advance task to 60-review

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0872): mark superseded — long-poll dequeue is primary

Operator clarified architecture: long-poll dequeue is primary
(handles content delivery), Monitor is just a "kick the loop"
nudge replacing the old Telegram loop guard. Spoon-feeding events
through Monitor is over-design.

Spec kept in 10-drafts as a record. Status: superseded. No work.

See Curator memory feedback_dequeue_long_poll_primary_monitor_nudge.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0875 (remove ACTIVITY_FILE_DEQUEUE_CAP_S = 5)

Operator: long-poll dequeue is primary, Monitor is just a nudge.
The 5s cap added in 50-0868 was for the Monitor-as-primary
framing; that framing is reverted, cap goes too. Default 300s
stays. Per-session dequeueDefault stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0876 (major debounce on activity-file mtime touches)

Operator: mtime bump is an idle kick, not a per-message signal.
Scale ACTIVITY_SUPPRESS_MS from 10s to 60s, reset on any
session-token tool call, suppress while dequeue is in-flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): add one-nudge-per-cycle rule + state machine

Operator: after a nudge fires, no more bumps until a dequeue from
that session is observed. Dequeue is the reset signal. Prevents
nudge-storm if agent is unresponsive; multiple inbound messages
during idle coalesce to one mtime bump.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): broaden activity definition + add per-session configurable debounce

Operator: nudge inhibited by ANY session activity (animations,
typing, in-flight async sends, mid-multi-step turn). Total silence
required.

Add profile/kick-debounce action (parallel to profile/dequeue-default)
to make the window per-session configurable. Default 60_000ms,
range 30s..10min.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0877 (revert onboarding framing) + reframe 10-0871

10-0877: docs-only revert of onboarding service messages + help
docs to dequeue-primary, Monitor-optional-augment framing.
Companion to 10-0875 (cap removal) and 10-0876 (debounce).

10-0871 description updated with operator's framing — Monitor as
optional augment replacing telegram loop guard, NOT primary
delivery. Platform-agnostic help language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: claim 10-0875 — remove activity-file dequeue cap

* fix(dequeue): remove activity-file dequeue cap (ACTIVITY_FILE_DEQUEUE_CAP_S)

Dequeue now always honors session dequeueDefault (fallback 300s) regardless
of activity/file registration status. The 5s cap was introduced in 50-0868
under the premise that Monitor would wake agents frequently — new framing
reverses that: long-poll is the win, Monitor is just a nudge.

Removes:
- ACTIVITY_FILE_DEQUEUE_CAP_S constant from file-state.ts
- import of isActivityFileActive + ACTIVITY_FILE_DEQUEUE_CAP_S in dequeue.ts
- Activity-file override block in dequeue.ts (cap application)

Behavior: dequeue effective timeout = sessionDefault (or explicit max_wait).
No activity-file registration can shorten it below the session default.

Closes 10-0875

* chore: move 10-0875 to 60-review — dequeue cap removed, tests pass

* chore: claim 10-0876 — major debounce on activity-file touch

* tasks: remove duplicate 10-0869 from 10-drafts (canonical at 50-active post merge)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity-file): major debounce — idle-kick state machine

Replaces the leading+trailing 5s debounce with a true idle-kick state
machine. The bridge now waits for >= kickDebounceMs (default 60s) of
complete session silence before bumping the activity file mtime. This
prevents false wake-ups while the agent is actively processing.

State machine:
- nudgeArmed: one kick per dequeue cycle (re-armed on dequeue return)
- inflightDequeue: suppress kicks while agent is blocking in dequeue
- recordActivityTouch: any tool call resets the suppression window
- timer: single scheduled kick when window expires (no storm on bursts)
- setDequeueActive(false): re-arms cycle + resets lastActivityAt

New: profile/kick-debounce action (GET/SET per-session debounce window).
New: getKickDebounceMs/setKickDebounceMs in session-manager.ts.
New: 8 unit tests covering all state transitions.

Closes task 10-0876.

* chore(tasks): move 10-0876 to 60-review

* chore(tasks): claim 10-0877

* docs(onboarding): dequeue-primary framing — activity-file as optional augment

Add ONBOARDING_LOOP_PATTERN service message fired on session/start (both
single- and multi-session paths). Explains dequeue long-poll (300 s) as the
standard heartbeat and presents the activity-file pattern as an opt-in augment
for harnesses with a filesystem watcher.

Update docs/help/start.md Dequeue Loop section with the same opt-in callout.

No existing message text changed. No Monitor-as-primary framing was found in
the codebase — all onboarding messages were already dequeue-primary. This adds
the missing augment note per the operator directive.

Closes #10-0877

* chore(tasks): move 10-0877 to 60-review

* task(10-0878): file robot-emoji removal sweep, promote to queued

Operator authorized 2026-05-05 — strip 🤖 from default name tag
across 9 production surfaces (outbound-proxy, session start/reconnect,
disconnect/promote notices, /sessions header). Tests + docs covered;
input-rejection tests preserved.

Worker can claim.

* pipeline: claim 10-0870-activity-file-edit-response-shape-consistency.md

* pipeline: promote 10-0870 to 60-review, add bug + draft

- 60-review: 10-0870 activity-file/edit response shape (Worker 2 done,
  branch 10-0870 commit 171b1471, build+tests green)
- 00-ideas: checklist/update bug report
- 10-drafts: activity-file monitor onboarding improvement task

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0870): stamp APPROVED

* pipeline: claim 10-0871-activity-file-help-topic-and-hint-pointer.md

* pipeline: claim 10-0878 — robot-emoji sweep

* feat(10-0878): strip 🤖 from all TMCP output surfaces

Remove robot emoji from 9 production surfaces and matching tests.
Emoji fatigue — operator request 2026-05-05.

Surfaces updated:
- outbound-proxy.ts: multi-session header prefix
- tools/session/start.ts: approval dialog, denied reply,
  reconnect dialog, reconnect denied, online announce (pinned), comment
- session-teardown.ts: disconnect notice, governor promotion
- built-in-commands.ts: /sessions header

Tests updated (output assertions only):
- animation-state.test.ts: header mock + assertion
- startup-token-cleanup.test.ts: 3 pinned-message fixtures
- tools/session/close.test.ts: 4 disconnect-notice assertions

Unchanged (input-rejection tests):
- tools/session/start.test.ts:711 (validates robot in user input)
- rename.test.ts:130 (same)
- session-manager.test.ts:655,657 (negative assertion — already correct)

pnpm test: 2955 passed, 0 failed

* pipeline: move 10-0878 to 60-review — merged into release/7.4

* pipeline: claim 10-0873-http-dequeue-endpoint-for-watcher.md

* pipeline: move 10-0871 to 60-review — code review PASS, completion appended

* verify(10-0871, 10-0878): stamps committed — both APPROVED

* feat(10-0871): add activity/file help topic + redirect hint to help()

Adds docs/help/activity/file.md with full wake-nudge guide (purpose,
lifecycle, wake mechanism, watcher patterns, error modes). Registers
activity/file in RICH_TOPICS. Updates hint string in create.ts and edit.ts
to "Call help('activity/file') now". Adds hermetic test for help topic.

Also applies 10-0870 shape alignment to edit.ts (ok+tmcp_owned → hint).
Includes 10-0870 dep since that branch not yet squash-merged to dev.

Squash-merged from branches 10-0871 (includes 10-0870). Sealed-By: Overseer

* seal(10-0870, 10-0871, 10-0878): TMCP batch seal

10-0870: activity/edit shape alignment — included in 10-0871 squash (9453f0b)
10-0871: activity/file help topic + hint redirect — squash on dev
10-0878: robot emoji removal — merged to release/7.4 (commit 2ddd78d)

Sealed-By: Overseer

* verify(10-0875, 10-0876, 10-0877): stamps committed — 0875 APPROVED, 0876 NEEDS_REVISION (inflightDequeue leak), 0877 APPROVED

* seal+return(10-0875, 10-0876, 10-0877):

10-0875: APPROVED — dequeue cap removed, sealed 70-done
10-0877: APPROVED — onboarding augment framing, sealed 70-done
10-0876: NEEDS_REVISION — inflightDequeue leaked on early returns in dequeue.ts; returned to 50-active for fix

Sealed-By: Overseer

* stamp 10-0869 NEEDS_REVISION: missing profile-load tests + dogfood docs

* 10-0869 → 50-active (NEEDS_REVISION)

* stamp 10-0873 NEEDS_REVISION: AC6 help topic not updated (hint text + dequeue HTTP doc missing)

* stamp 10-0873 APPROVED (round 2): AC6 fix confirmed — hint text + dequeue-http help doc

* feat(10-0873): add GET|POST /dequeue HTTP endpoint + extract runDrainLoop

- New src/dequeue-endpoint.ts: GET/POST /dequeue route, token validation, shape parity with MCP tool
- New src/dequeue-endpoint.test.ts: 17 test cases (happy path, 401 paths, instant poll, session_closed)
- src/tools/dequeue.ts: extract runDrainLoop to shared fn; fix setDequeueActive leak (session_closed check before flag set)
- src/tools/activity/create.ts: update hint text to reference GET /dequeue HTTP URL
- docs/help/dequeue-http.md: new help topic with curl/PowerShell/Node fetch examples
- src/tools/help.ts: register dequeue-http in RICH_TOPICS + DESCRIPTION

Squash of branch 10-0873 (493ea987 + 69ea884e)

* seal 10-0873 → 70-done/2026/05/05/ — APPROVED

Sealed-By: Overseer

* fix(10-0876): move setDequeueActive after session_closed guard in dequeue.ts

Extract runDrainLoop() from dequeue handler and guard setDequeueActive(sid, true)
AFTER the session_closed check. Previously the flag was set before the check,
leaving it stuck true for dead sessions (session_closed early return never
reached the finally that resets to false).

Cherry-pick of 493ea987 src/tools/dequeue.ts changes from branch 10-0873.

2955 tests pass.

* stamp 10-0876 APPROVED (round 2): inflightDequeue gap fixed by 10-0873 runDrainLoop

* test(10-0869): add name_tag branch coverage to apply and load tests

* docs(10-0869): curator dogfood walkthrough for custom name tags

* tasks(10-0869): advance to 60-review — fix-pass complete

* move 10-0876 to 60-review: APPROVED stamp committed d398317

* seal 10-0876: Major debounce on activity-file mtime touches

All 7 ACs passed. inflightDequeue gap fixed by 10-0873 runDrainLoop
extraction (setDequeueActive(sid,true) moved to after session_closed
check; try/finally guarantees reset). Cherry-picked to release/7.4
as 6423998.

Sealed-By: Overseer

* stamp 10-0869 APPROVED (round 2): both gaps resolved — name_tag tests + dogfood doc

* seal 10-0869: TMCP custom name tags — fix-pass complete

All 8 ACs satisfied. name_tag tests added to apply.test.ts (3) and
load.test.ts (2). Dogfood walkthrough at docs/dogfood/10-0869-name-tags.md.
Feature on dev + release/7.4 (e191714).

Sealed-By: Overseer

* fix(review): address all PR #167 review findings

Critical fixes:
- dequeue-endpoint: wrap async Express handler in try/catch with next(err)
- dequeue-endpoint: remove connection_token (accepted but silently ignored)
- name-tag: add backtick validation to prevent broken Markdown in headers
- apply.ts: fall back to legacy nametag_emoji field when name_tag missing
- ActivityFileState: remove phantom absorbedCount field (new file, no compat needed)

Moderate fixes:
- file-state.ts: rewrite module doc (removed false MAX_INTERVAL_MS/ACTIVITY_SUPPRESS_MS promises)
- file-state.ts: fix validateFilePath path-traversal check (split on separators, not substring)
- file-state.ts: replace console.warn with dlog('tool', ...)
- import_profile: add backtick/newline regex to name_tag Zod schema

DRY / minor:
- name-tag.ts: extract resolveNameTag() exported helper
- outbound-proxy.ts: use resolveNameTag() from name-tag.ts, remove duplicate expression
- dequeue-endpoint.ts: extract parseIntParam() helper, remove redundant isFinite check

Docs:
- changelog/2026-05-04_v7.4.0.md: add missing entries (name tags, HTTP dequeue, kick-debounce, fixes, breaking changes)
- changelog/unreleased.md: document all review fixes

* feat(10-0880): runtime-conditional onboarding_loop_pattern with Monitor wiring example

* feat(10-0880): refine loop framing — dequeue IS the loop, watcher additive, Claude Code should

* test(10-0880): update start help test assertion — 5 min not 5 minutes

* feat(10-0880): tighten onboarding_loop_pattern phrasing

Replace dense single-paragraph message (with inline bash/PS snippets and
soft "you should also wire up" framing) with two numbered essentials and
a breadcrumb to help topics. Operator directive: imperative, precise,
breadcrumb to depth — agents do not need max_wait values, mtime detail,
or runtime examples in the startup beat.

Before: ~115 words, inline bash + PS, "you should also wire up".
After: ~45 words, two numbered bits, "Details: help('start'),
help('dequeue'), help('activity/file')."

Use template literal with real newlines (avoids hook false-positive on
':\n' Windows-drive-letter pattern). No tests pinned the literal
string. Full suite passes (2978/2978).

* feat(10-0880): trim session/start response to {token, sid, hint}

Operator directive 5/6: response payload was over-stuffed pollution.
Strip to just what an agent needs at the top of the loop.

Drop from fresh-path response: suffix, sessions_active, action, pending,
discarded, fellow_sessions, connection_token. Drop from reconnect-path
response: sessions_active, action, pending. Mutation that set
res.fellow_sessions on multi-session join also removed.

connection_token (duplicate-session detection) is removed from the
visible response. dequeue still accepts the param for legacy callers
(no error path) but new agents will not be passing it. Detection feature
is therefore quiescent — kill it in a follow-up if desired.

DESCRIPTION updated to: "Returns { token, sid, hint } — call dequeue(token)
next to enter the loop." Old self-referential "Call help() first ..."
tail dropped.

Tests in start.test.ts updated for new shape (the two toEqual
assertions). Other start.test.ts cases use field-by-field assertions
and pass unchanged. Other suites that may probe the dropped fields are
operator-acknowledged as breaking ("ignore test failures for now") — to
be cleaned up under the broader test-language audit.

* feat(10-0880): onboarding_loop_pattern v8 — welcome framing, runtime-agnostic

Cold-read assessment surfaced two soft spots:
- "Stay in the loop" presumed the loop already existed (fresh agent had no
  context) → replaced with "Welcome to the loop. Stay in it." which
  establishes the loop AND positions the agent as already inside it.
- Capitalized "(Monitor)" parenthetical was a Claude-Code-specific cue;
  agents in other harnesses might miss it → replaced with "Check your
  tools for an option to monitor a file" which is runtime-agnostic.

Bit 1 also gains the explicit token signature (dequeue(token)) so a fresh
agent does not have to hunt the dequeue tool description for the param.

Same length, same breadcrumbs, same numbered structure.

* fix(10-0885): apply 18 language-conciseness findings from audit 10-0884

High (6): help.ts DESCRIPTION, ONBOARDING_BUTTONS_TEXT, ONBOARDING_MODALITY_PRIORITY,
send.md audio+text, guide.md keyboard taxonomy, start.md activity watcher
Medium (9): ONBOARDING_PROTOCOL, ONBOARDING_PRESENCE_SIGNALS, ONBOARDING_HYBRID_MESSAGING,
send:choice hint, send:animation hint, send.ts MISSING_CONTENT, activity/create hint,
action.ts hint, session/start DESCRIPTION
Low (3): SESSION_DENIED hint, help/index intro, help/animation REST trigger

* fix(10-0887): apply 20 response-payload audit findings from 10-0886

High (5): remove sent/split bool from send, empty dequeue.empty, approved from approve, started/timeout from show-typing, dm/delete/cancel {} confirmed
Medium (8): routed, ok, loaded, saved, rolled, updated, cancelled booleans removed; session/close reason removed; animation/status unwrapped
Low (3): activity/get registered, message/pin unified, animation/cancel false-case preserved

* test(10-0882): scrub content-string assertions and stale payload-field checks

- Remove prose toContain assertions (split:true, cancelled:true, empty:true, action, fellow_sessions, discarded, connection_token, pending)
- Replace doc-string checks with typeof/length guards in first-use-hints, service-messages, shutdown, dequeue, help tests
- All 2978 tests pass

* fix: lower kick-debounce minimum to 1s (was 30s)

* release: v7.4.1 — kick-debounce minimum 1s

* fix: address GPT 5.4 review findings — timer generation check + carry runtime state

M1: add generation/identity check in touchActivityFile timer closure (file-state.ts)
    — captures scheduling entry reference; bails if _state maps to a different object
      at callback time, preventing stale timers from firing against replacement entries.

M2: replaceActivityFile now carries over lastActivityAt, inflightDequeue, nudgeArmed
    from oldEntry (file-state.ts) — prevents spurious epoch-0 kick on first post-swap
    message in create.ts and edit.ts.

L1: import KICK_DEBOUNCE_MIN_MS / KICK_DEBOUNCE_MAX_MS into action.ts and use them
    in the ms Zod schema bounds — eliminates duplicated literal constants.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address Copilot review findings — same-path guard, missing tests, changelog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
electricessence added a commit that referenced this pull request May 11, 2026
* seal(10-0835): profiles leakage audit — fix already applied in 02f4163

Sealed-By: Overseer

* pipeline: claim 10-0823-first-dequeue-onboarding-bundle.md

* pipeline: promote 20-0822 (hybrid duplication detector) — operator priority bump

* fix(skills): correct dequeue parameter name timeout→max_wait across skill docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(onboarding): first-dequeue bundle — hybrid, modality, presence, conditional tail

Adds 3 new onboarding service messages (onboarding_hybrid_messaging,
onboarding_modality_priority, onboarding_presence_signals) and a
conditional tail (onboarding_no_pending_yet, gated on discarded === 0)
to the first-dequeue bundle. Agents now enter context with full protocol
awareness. 2837 tests pass.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 20-0822-hybrid-duplication-detector.md

* skills(spec): author 12 purpose-driven specs for telegram-mcp skill cluster (Curator pass)

* skills(uncompressed): author 12 companion uncompressed.md, reconcile SKILL.md gaps (animation timeout, dequeue event-class table, dump-handling tool name, graceful-shutdown force:true)

* skills(SKILL): generalize fleet role names — Curator/Overseer/Worker/Deputy → governor/supervising/subordinate (TMCP-public hygiene)

* pipeline: icebox 15-0837 — superseded by 7.2.2 BUILTIN_PRESETS implementation

* draft+queue(20-0841): spike — pre-stage node_modules in TMCP worktrees (auto-queued: research with concrete output)

* draft(15-0843): help('shutdown') must carry canonical governor procedure verbatim

Filed at operator request after Curator quiz turn. Worker-delegatable doc-fix
on docs/help/shutdown.md Governor Shutdown section.

* pipeline: claim 20-0841-spike-worktree-node-modules-prestaging.md

* seal: 20-0841 — spike: pre-stage node_modules in TMCP worktrees

Findings: Candidate 4 (worktree-create hook) + Candidate 1 (shared virtual store)
recommended. Per operator guidance: per-repo sanctioned script on Worker allowlist.
5 operator decisions remain open in findings doc for implementation follow-on.

Sealed-By: Overseer

* fix(startup): remove blocking operator-prompt path from session-startup SKILL

* draft: auto-pin blocking questions feature (operator directive 2026-04-26)

* triage: route 6 tasks to curator-only (Curator-authored or delegation: curator)

- 10-0836: TMCP skills overhaul — Curator-led, multi-cycle
- 10-737: hook hash fragility reform — Curator authors design doc directly
- 15-734: hook error disambiguation — Curator authors hook patch directly (trust boundary)
- 20-721: V7 master merge readiness — Curator orchestrates audit + PR
- 30-470: remove dead registerTool calls — Curator must revise spec (premise incorrect per W2)
- friction-pnpm-install-worktree-block: explicit delegation: curator

* triage: route 3 tasks to needs-refinement (require Curator spec before Worker claim)

- 10-733: zombie session reconnect security — needs Curator spec, Worker cannot define security boundary
- 15-736: loud-on-anomaly observability — "Curator should spec anomaly taxonomy before claim"
- 15-349: compaction event logging — multi-phase, deletes hooks (Curator trust boundary)

* queue: 05-0826 recording-indicator-refcount-race-and-suppression-gaps (operator-approved)

* queue: 05-0829 investigate-worker-haiku-compaction-and-handoff-bleed (operator-approved)

* note: 05-0829 — verify-first guidance from operator before implementing fixes

* seal: spike-0841 pnpm-worktree-prestaging (operator-verified, direction set)

* queue: 15-0827 seal-commit-misses-worker-completion-notes (operator-approved)

* queue: 15-0843 help-shutdown-canonical-governor-procedure (operator-approved)

* queue: 15-0848 reply-target-not-active-question-no-skip (operator-approved)

* queue: 15-0838 curator-shutdown-metrics-report (operator-approved)

* queue: 20-draft session-joined-fellow-service-message (operator-approved)

* docs: standardize session memory save format (10-0548)

Update telegram-mcp-session-startup SKILL.md and help session/start.md
to document the two-format standard: Minimal (raw integer in
session.token) and Full (YAML body in session.md). Remove PIN field
references; update token formula to use 'suffix' not 'pin'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(help): add index topic to overview and schema describe (10-0549)

- buildOverview(): mention help(topic: 'index') for categorized skill index
- topic.describe(): add 'index' option so schema introspection surfaces the topic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0826-recording-indicator-refcount-race-and-suppression-gaps.md

* feat(send): hybrid caption-duplication detector (Jaccard-based) (squash 20-0822)

Adds detectCaptionDuplication (Jaccard similarity, content-word tokenisation,
ratio gates) wired into all three send paths. Fires NUDGE_CAPTION_DUPLICATION
when caption appears to restate audio. All 2860 tests pass.

Also: draft task 15-0849 tts-underscore-string-replace (operator-filed 2026-04-26)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal: 20-0822 hybrid-duplication-detector — Jaccard detector merged, all tests pass

Note: ship-criteria corpus validation skipped; conservative thresholds expected
to hold. Monitor for FP noise in production.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* queue: 15-0849 tts-underscore-string-replace (operator-directed, scope confirmed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tasks): normalize 70-done/20260424 → 70-done/2026/04/24 (canonical date format)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0829-investigate-worker-haiku-compaction-and-handoff-bleed.md

* pipeline: claim 15-0849-tts-underscore-string-replace.md

* pipeline: claim 15-0843-help-shutdown-canonical-governor-procedure.md

* seal: 05-0829 Worker recovery investigation — both bugs already fixed, skill promoted

Bug 1 (Overseer recovery staged-state signal): already in context/refresh.md.
Bug 2 (Worker staged-state Worktree Gate): promoted from memory to task-execution/SKILL.md.
Postmortem in Curator repo. All 4 unknowns resolved.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(docs): MD032 blank line before list in session/start help (Copilot #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(recording): epoch guard for refcount race + typing suppression gaps (05-0826)

Squash-merged branch 05-0826. Epoch token prevents stale async callbacks from
corrupting refcount; suppression-gap fixes ensure typing indicator clears reliably.

Sealed-By: Overseer

* fix(help/shutdown): canonical governor shutdown procedure with explicit token path (15-0843)

Squash-merged branch 15-0843. Rewrites shutdown.md into Participant/Governor sections
with verbatim operator-stated sequences; adds wipe-before-shutdown ordering assertion.

Sealed-By: Overseer

* chore: seal 05-0826 and 15-0843 → 70-done/2026/04/26

Sealed-By: Overseer

* fix(button-helpers): off-target reply guard in pollButtonOrTextOrVoice (15-0848)

Squash-merged branch 15-0848. Three-way rule: ambiguous (no reply_to), on-target
(reply matches question), off-target (reply ≠ question → re-enqueue, prompt open).

Sealed-By: Overseer

* chore: seal 15-0848 → 70-done/2026/04/26

Sealed-By: Overseer

* chore: seal 15-0827 (investigation) → 70-done/2026/04/26

Root cause confirmed: Overseer seal renames task file from dev branch which lacks
Worker's Completion section. Fix is Overseer-side (include complete() commit or
copy Completion at seal time). No Worker SKILL change needed.

Sealed-By: Overseer

* feat(tts): normalize ALL_CAPS_WITH_UNDERSCORES identifiers for speech (15-0849)

Squash-merged branch 15-0849. Adds normalizeCapsForTts() — converts identifiers
like SESSION_JOINED to "session joined" in TTS output. Toggle off via
TTS_CAPS_NORMALIZE=false.

Sealed-By: Overseer

* chore: seal 15-0849 → 70-done/2026/04/26

Sealed-By: Overseer

* pipeline: claim 15-0838-curator-shutdown-metrics-report.md

* feat(skill): graceful-shutdown step 6 compaction metrics report (15-0838)

Squash-merged branch 15-0838. Updated graceful-shutdown skill in electrified-cortex
to add Step 6 (pre-shutdown compaction metrics report via event-report.mjs).

Sealed-By: Overseer

* chore: seal 15-0838 → 70-done/2026/04/26

Sealed-By: Overseer

* refactor(session): extract SESSION_JOINED_FELLOW to service-messages.ts (20-draft)

Squash-merged branch 20-draft-fellow. Eliminates hardcoded inline string in
session/start.ts; governor/non-governor paths now both use SERVICE_MESSAGES constants.

Sealed-By: Overseer

* chore: seal 20-draft → 70-done/2026/04/26

Sealed-By: Overseer

* feat(guidance): lazy trigger delivery for onboarding messages (10-0581)

Squash-merged branch 10-0581. Moves 5 session-start onboarding messages to
trigger-based delivery; adds help('guidance') taxonomy topic.

Sealed-By: Overseer

* chore: promote 15-0850 to 40-queued (operator approved 2026-04-26)

* pipeline: claim 15-0850-recovering-animation-replace-with-compacted-notify.md

* feat(compaction): replace recovering animation with compacted notify on first post-compacted activity (15-0850)

Squash-merged from branch 15-0850.
Sealed-By: Overseer

* feat(animation): add status API, stale-on-idle warning, timeout default shift (15-763)

- animation/status action: returns active animation state per session; governor variant lists all
- Stale-on-idle dequeue warning: animation_stale_warning event after ≥30s idle (120s cooldown)
- Timeout default: 600s → 60s across send, show, animation-state
- Help docs: animation.md + presence.md updated with lifecycle rules

Sealed-By: Overseer

* docs(send): add messaging spectrum and audio format rules (20-766)

7-row spectrum table (text-only long through audio-only) with trigger conditions.
Audio format rules: natural language, fluid prose, minimal punctuation, no
voice-unfriendly content.

Sealed-By: Overseer

* fix(lint): address Copilot MD055 + line-length + regex-hoisting comments (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add .code-reviews/ to .gitignore (eval artefacts contain local paths)

* eval(10-0858): haiku-class L1 vs sonnet-class L2 comparison report

Squashed-from: 10-0858
Sealed-By: Overseer

* fix(10-0859): extract deliverCaptionDuplicationNudge helper

Squashed-from: 10-0859
Sealed-By: Overseer

* fix(10-0860): correct presence.md stale animation warning shape

Docs said service_message with event_type; actual impl returns dequeue
update item with event: animation_stale_warning.

Squashed-from: 10-0860
Sealed-By: Overseer

* fix(10-0861): clarify animation/status SID variant return shape in docs

SID variant implemented by 15-763; docs updated to disambiguate
single-session vs multi-session response shapes.

Squashed-from: 10-0861
Sealed-By: Overseer

* seal: task 15-0863 — Verify choose callback cannot fire twice

Static analysis confirms _callbackHooks one-shot de-registration is
synchronous before any await. Node.js single-thread guarantee ensures
exactly one delivery for all interactive modes (choose, confirm, question).

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: move 15-0862 to 60-review

* seal: task 15-0862 — Add 250ms delay between button color-flip and collapse

BUTTON_COLLAPSE_DELAY_MS=250 constant; gated on real button press only
(callbackQueryId truthy). Persistent path passes delayMs=0. All 2930
tests passing. New fake-timer gate test added.

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove async from handleAnimationStatus function and adjust test tick handling

* feat(tasks): file 50-0865 + 50-0866 from Overseer wedge postmortem

- 50-0865: bridge auto-terminate for stuck sessions (no recovery
  after N consecutive unhealthy events)
- 50-0866: TTS render timeout for hybrid sends (prevent silent
  indefinite block)

Both surface from 2026-05-03 5-alarm Overseer wedge incident
where auto-recovery silently gave up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0867 consumer hook setup guidance

Document the loop-guard + compaction-notification hook patterns
for outside TMCP consumers. Operator (2026-05-04): patterns exist
in-house but are poorly documented for fresh integrators.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0868 build per-session touch-file feature

Operator (2026-05-04): ship the bridge-side feature now without
waiting for Monitor wakeup-semantics validation. Per-session touch
file with random-hash filename, leading+trailing-suppressed
debounce, activity-aware reset, lifecycle tied to session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): flip ownership — agent provides path, TMCP just touches

Operator (2026-05-04 late): TMCP doesn't allocate/create/delete the
touch file. Agent owns it, registers path via monitor/register.
TMCP records and touches; nothing else. Cleaner separation,
opt-in by construction, TMCP filesystem stays empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): hybrid opt-in — agent OR TMCP supplies path

Operator (2026-05-04 final): monitor/enable supports two shapes:
- agent-supplied path: TMCP records, never creates/deletes
- TMCP-supplied: TMCP generates random hash, owns lifecycle
Either way: opt-in only. Without enable, zero I/O.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): rename to session-file CRUD, agnostic naming

Operator (2026-05-04): drop the Monitor framing — TMCP exposes a
filesystem hook, consumer chooses how to watch. CRUD verbs:
session-file/create, session-file/edit, session-file/delete,
session-file/get. Path-supplied vs TMCP-generated still both
supported; ownership rules carry through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): correct namespace to session/file/ (under existing session/)

Operator (2026-05-04): not session-file/, but session/file/ —
extends the existing session/ namespace (session/start, session/
close, session/list).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): final namespace activity/file/ + decision rationale

Operator (2026-05-04 final): activity/file/ wins. The file signals
activity, doesn't record session state. Top-level namespace
parallel to session/, leaves room for sibling activity hooks
(presence, typing, etc) later.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): auto-shorten dequeue default to 5s on activity/file/create

Operator (2026-05-04): familiar Claude pattern. Reverts on delete.
Per-call override still respected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): clarify max_wait override is temporary, default = 5min

Operator (2026-05-04): activity/file/create applies a TEMPORARY
override (not a profile mutation). activity/file/delete clears it
back to the standard 5min default. Per-call still trumps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note agent can override the override via profile/dequeue-default

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note loop-guard becomes redundant with activity/file in use

Operator (2026-05-04): emergent simplification — loop-guard exists
to catch silent stuck agents during 300s blocking dequeues. With
5s default + kicker, that failure mode shrinks 60x. Future task:
deprecate + remove loop guard once activity/file adopted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0864-session-close-confirm-show-identity.md

* feat(50-0864): session-close confirmation includes name and SID

Squash-merged task/50-0864-session-close-identity.

* pipeline(50-0864): move to 60-review

Task complete per Worker 3 — squash merged, advancing to review stage.

* seal(50-0864): session-close confirmation includes name and SID

Sealed-By: Overseer SID 6
Squash: 3276f1a
Worker: Worker 3 (SID 9)
Verdict: PASS

* pipeline: claim 50-0865-bridge-auto-terminate-stuck-sessions.md

* kill(50-0865): auto-terminate stuck sessions — bogus heuristic

Operator (2026-05-04): no reliable way to determine 'stuck.'
With activity/file (50-0868) coming, peer-liveness is observable
directly. Auto-terminate is redundant or needs new basis.

Moved to icebox with KILLED marker. Branch + worktree pruned.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(50-0866): move to 10-drafts pending operator stamp (postmortem sibling)

Same category as the killed 50-0865 — postmortem-derived
speculative fix. Operator stamps before Worker builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0867-consumer-hook-setup-guidance-loop-guard-compaction.md

* pipeline: move 50-0867 to 60-review — W1 complete, pending verification

* docs: add consumer-hooks.md — loop guard + compaction setup guide (50-0867)

Documents how TMCP consumers wire up loop guard (Stop hook) and
compaction notifications (PreCompact/PostCompact) including settings
JSON, env vars, 6-step checklist, and common pitfalls.

Sealed-By: Overseer

* seal: task 50-0867 — consumer hook setup guidance doc

Sealed-By: Overseer

* pipeline: claim 50-0868-build-per-session-touch-file-feature.md

* pipeline: move 50-0868 to 60-review — W1 complete, pending verification

* feat(activity): per-session touch-file feature for external activity monitoring (50-0868)

Adds activity/file/create|edit|get|delete action paths and session-level
debounced mtime-touch on inbound messages. Enables Overseer/external agents
to monitor session liveness via filesystem mtime without polling Telegram.

Sealed-By: Overseer

* seal: task 50-0868 — per-session activity touch-file feature

Sealed-By: Overseer

* chore(release): cut v7.4.0 release branch

* draft(10-0867): fix text-after-audio message ordering — per-session outbound queue

* review(10-0973): adversarial GPT-5.4 review of TMCP 7.4

Two high, two medium findings:
- H1: arbitrary host-file append primitive via session token
- H2: failed touches recorded as successful (silent wakeup black-hole)
- M1: activity suppression can drop only wakeup edge
- M2: delete/rotation claims success when file is still on disk

No critical bugs. Blast-radius expansion is the main concern.
Dispatched via Copilot Worker runSubagent(model: 'GPT-5.4 (copilot)').

Forced into tasks/notes/ (normally gitignored — one-off audit artifact).

* feat: update closeSessionById mock to include optional name parameter

* feat: update closeSessionById mock to include optional name parameter

* feat: refactor name-tag storage to a single editable string and update default behavior

* task(10-0870): align activity/file/edit response shape with create

Sibling endpoint cleanup task — drop ok+tmcp_owned, add hint field
to match the create-side reshape from this session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity): tighten hint phrasing + queue help-topic + spoon-feed follow-ups

- create.ts hint: 'Configure your watcher to call dequeue() when this file changes' (clearer action than the prior phrasing)
- 10-0870 reword to match new hint string
- 10-0871: replace hint with help('activity/file') pointer + write the help topic (full watcher recipe, mtime caveat, role permissions)
- 10-0872: watcher spoon-feeds dequeue via /mcp HTTP (saves a round-trip per wake)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: queue 10-0870 + 10-0871 (activity/file shape + help topic)

10-0870: align activity/file/edit response with create-side reshape.
10-0871: replace hint with help('activity/file') pointer + write the
help topic (depends on 0870).

10-0872 (watcher spoon-feeds dequeue) stays in drafts — Curator-owned
design with 7 open questions to pin first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: rewrite 10-0872 (watcher pre-drain), file 10-0873 (HTTP dequeue endpoint), capture show-typing nudge friction

10-0872: pivot from round-trip framing to turn-count framing per operator.
Watcher curls the dequeue endpoint, includes drained events in wake notification.
Skip-parameter idea iceboxed (operator: not needed if drain is genuine).

10-0873: sibling Worker-shippable task. Two paths considered:
dedicated /dequeue endpoint vs documented /mcp JSON-RPC use.
Operator leaning toward dedicated endpoint; pending confirmation.

00-ideas/show-typing-...: friction note. behavior_nudge_typing_rate
overfires show-typing on every receipt; operator clarified show-typing
is a composition-imminent signal only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0874 (suppress health-check when activity-file active)

Operator: health-check is misleading when activity-monitor already
maintains presence. Skip the prompt for sessions with active
activity-file registry entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: promote 10-0869 (custom name tags) drafts -> 40-queued

Operator directing Copilot Worker to this. Target 7.4 release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0869): claim — Worker SID 2

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(10-0869): custom name tags — single string, no robot emoji, name-tag action, profile integration

- Remove nametag_emoji from Session, ProfileData, all handlers
- Add Session.name_tag?: string (explicit override) + defaultNameTag() export
- buildHeader: wrap entire name_tag in monospace; color now inside the tag
- New action handlers: name-tag (get/set), name-tag/set alias
- profile/save: persist name_tag only when explicitly set
- profile/apply: apply name_tag from loaded profile
- profile/import: name_tag param (max 64 chars, no newlines)
- action.ts: register name-tag actions, replace nametag_emoji schema field
- Tests: +17 net new; all 2947 pass

* chore(10-0869): advance task to 60-review

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0872): mark superseded — long-poll dequeue is primary

Operator clarified architecture: long-poll dequeue is primary
(handles content delivery), Monitor is just a "kick the loop"
nudge replacing the old Telegram loop guard. Spoon-feeding events
through Monitor is over-design.

Spec kept in 10-drafts as a record. Status: superseded. No work.

See Curator memory feedback_dequeue_long_poll_primary_monitor_nudge.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0875 (remove ACTIVITY_FILE_DEQUEUE_CAP_S = 5)

Operator: long-poll dequeue is primary, Monitor is just a nudge.
The 5s cap added in 50-0868 was for the Monitor-as-primary
framing; that framing is reverted, cap goes too. Default 300s
stays. Per-session dequeueDefault stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0876 (major debounce on activity-file mtime touches)

Operator: mtime bump is an idle kick, not a per-message signal.
Scale ACTIVITY_SUPPRESS_MS from 10s to 60s, reset on any
session-token tool call, suppress while dequeue is in-flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): add one-nudge-per-cycle rule + state machine

Operator: after a nudge fires, no more bumps until a dequeue from
that session is observed. Dequeue is the reset signal. Prevents
nudge-storm if agent is unresponsive; multiple inbound messages
during idle coalesce to one mtime bump.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): broaden activity definition + add per-session configurable debounce

Operator: nudge inhibited by ANY session activity (animations,
typing, in-flight async sends, mid-multi-step turn). Total silence
required.

Add profile/kick-debounce action (parallel to profile/dequeue-default)
to make the window per-session configurable. Default 60_000ms,
range 30s..10min.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0877 (revert onboarding framing) + reframe 10-0871

10-0877: docs-only revert of onboarding service messages + help
docs to dequeue-primary, Monitor-optional-augment framing.
Companion to 10-0875 (cap removal) and 10-0876 (debounce).

10-0871 description updated with operator's framing — Monitor as
optional augment replacing telegram loop guard, NOT primary
delivery. Platform-agnostic help language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: claim 10-0875 — remove activity-file dequeue cap

* fix(dequeue): remove activity-file dequeue cap (ACTIVITY_FILE_DEQUEUE_CAP_S)

Dequeue now always honors session dequeueDefault (fallback 300s) regardless
of activity/file registration status. The 5s cap was introduced in 50-0868
under the premise that Monitor would wake agents frequently — new framing
reverses that: long-poll is the win, Monitor is just a nudge.

Removes:
- ACTIVITY_FILE_DEQUEUE_CAP_S constant from file-state.ts
- import of isActivityFileActive + ACTIVITY_FILE_DEQUEUE_CAP_S in dequeue.ts
- Activity-file override block in dequeue.ts (cap application)

Behavior: dequeue effective timeout = sessionDefault (or explicit max_wait).
No activity-file registration can shorten it below the session default.

Closes 10-0875

* chore: move 10-0875 to 60-review — dequeue cap removed, tests pass

* chore: claim 10-0876 — major debounce on activity-file touch

* tasks: remove duplicate 10-0869 from 10-drafts (canonical at 50-active post merge)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity-file): major debounce — idle-kick state machine

Replaces the leading+trailing 5s debounce with a true idle-kick state
machine. The bridge now waits for >= kickDebounceMs (default 60s) of
complete session silence before bumping the activity file mtime. This
prevents false wake-ups while the agent is actively processing.

State machine:
- nudgeArmed: one kick per dequeue cycle (re-armed on dequeue return)
- inflightDequeue: suppress kicks while agent is blocking in dequeue
- recordActivityTouch: any tool call resets the suppression window
- timer: single scheduled kick when window expires (no storm on bursts)
- setDequeueActive(false): re-arms cycle + resets lastActivityAt

New: profile/kick-debounce action (GET/SET per-session debounce window).
New: getKickDebounceMs/setKickDebounceMs in session-manager.ts.
New: 8 unit tests covering all state transitions.

Closes task 10-0876.

* chore(tasks): move 10-0876 to 60-review

* chore(tasks): claim 10-0877

* docs(onboarding): dequeue-primary framing — activity-file as optional augment

Add ONBOARDING_LOOP_PATTERN service message fired on session/start (both
single- and multi-session paths). Explains dequeue long-poll (300 s) as the
standard heartbeat and presents the activity-file pattern as an opt-in augment
for harnesses with a filesystem watcher.

Update docs/help/start.md Dequeue Loop section with the same opt-in callout.

No existing message text changed. No Monitor-as-primary framing was found in
the codebase — all onboarding messages were already dequeue-primary. This adds
the missing augment note per the operator directive.

Closes #10-0877

* chore(tasks): move 10-0877 to 60-review

* task(10-0878): file robot-emoji removal sweep, promote to queued

Operator authorized 2026-05-05 — strip 🤖 from default name tag
across 9 production surfaces (outbound-proxy, session start/reconnect,
disconnect/promote notices, /sessions header). Tests + docs covered;
input-rejection tests preserved.

Worker can claim.

* pipeline: claim 10-0870-activity-file-edit-response-shape-consistency.md

* pipeline: promote 10-0870 to 60-review, add bug + draft

- 60-review: 10-0870 activity-file/edit response shape (Worker 2 done,
  branch 10-0870 commit 171b1471, build+tests green)
- 00-ideas: checklist/update bug report
- 10-drafts: activity-file monitor onboarding improvement task

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0870): stamp APPROVED

* pipeline: claim 10-0871-activity-file-help-topic-and-hint-pointer.md

* pipeline: claim 10-0878 — robot-emoji sweep

* feat(10-0878): strip 🤖 from all TMCP output surfaces

Remove robot emoji from 9 production surfaces and matching tests.
Emoji fatigue — operator request 2026-05-05.

Surfaces updated:
- outbound-proxy.ts: multi-session header prefix
- tools/session/start.ts: approval dialog, denied reply,
  reconnect dialog, reconnect denied, online announce (pinned), comment
- session-teardown.ts: disconnect notice, governor promotion
- built-in-commands.ts: /sessions header

Tests updated (output assertions only):
- animation-state.test.ts: header mock + assertion
- startup-token-cleanup.test.ts: 3 pinned-message fixtures
- tools/session/close.test.ts: 4 disconnect-notice assertions

Unchanged (input-rejection tests):
- tools/session/start.test.ts:711 (validates robot in user input)
- rename.test.ts:130 (same)
- session-manager.test.ts:655,657 (negative assertion — already correct)

pnpm test: 2955 passed, 0 failed

* pipeline: move 10-0878 to 60-review — merged into release/7.4

* pipeline: claim 10-0873-http-dequeue-endpoint-for-watcher.md

* pipeline: move 10-0871 to 60-review — code review PASS, completion appended

* verify(10-0871, 10-0878): stamps committed — both APPROVED

* feat(10-0871): add activity/file help topic + redirect hint to help()

Adds docs/help/activity/file.md with full wake-nudge guide (purpose,
lifecycle, wake mechanism, watcher patterns, error modes). Registers
activity/file in RICH_TOPICS. Updates hint string in create.ts and edit.ts
to "Call help('activity/file') now". Adds hermetic test for help topic.

Also applies 10-0870 shape alignment to edit.ts (ok+tmcp_owned → hint).
Includes 10-0870 dep since that branch not yet squash-merged to dev.

Squash-merged from branches 10-0871 (includes 10-0870). Sealed-By: Overseer

* seal(10-0870, 10-0871, 10-0878): TMCP batch seal

10-0870: activity/edit shape alignment — included in 10-0871 squash (9453f0b)
10-0871: activity/file help topic + hint redirect — squash on dev
10-0878: robot emoji removal — merged to release/7.4 (commit 2ddd78d)

Sealed-By: Overseer

* verify(10-0875, 10-0876, 10-0877): stamps committed — 0875 APPROVED, 0876 NEEDS_REVISION (inflightDequeue leak), 0877 APPROVED

* seal+return(10-0875, 10-0876, 10-0877):

10-0875: APPROVED — dequeue cap removed, sealed 70-done
10-0877: APPROVED — onboarding augment framing, sealed 70-done
10-0876: NEEDS_REVISION — inflightDequeue leaked on early returns in dequeue.ts; returned to 50-active for fix

Sealed-By: Overseer

* stamp 10-0869 NEEDS_REVISION: missing profile-load tests + dogfood docs

* 10-0869 → 50-active (NEEDS_REVISION)

* stamp 10-0873 NEEDS_REVISION: AC6 help topic not updated (hint text + dequeue HTTP doc missing)

* stamp 10-0873 APPROVED (round 2): AC6 fix confirmed — hint text + dequeue-http help doc

* feat(10-0873): add GET|POST /dequeue HTTP endpoint + extract runDrainLoop

- New src/dequeue-endpoint.ts: GET/POST /dequeue route, token validation, shape parity with MCP tool
- New src/dequeue-endpoint.test.ts: 17 test cases (happy path, 401 paths, instant poll, session_closed)
- src/tools/dequeue.ts: extract runDrainLoop to shared fn; fix setDequeueActive leak (session_closed check before flag set)
- src/tools/activity/create.ts: update hint text to reference GET /dequeue HTTP URL
- docs/help/dequeue-http.md: new help topic with curl/PowerShell/Node fetch examples
- src/tools/help.ts: register dequeue-http in RICH_TOPICS + DESCRIPTION

Squash of branch 10-0873 (493ea987 + 69ea884e)

* seal 10-0873 → 70-done/2026/05/05/ — APPROVED

Sealed-By: Overseer

* fix(10-0876): move setDequeueActive after session_closed guard in dequeue.ts

Extract runDrainLoop() from dequeue handler and guard setDequeueActive(sid, true)
AFTER the session_closed check. Previously the flag was set before the check,
leaving it stuck true for dead sessions (session_closed early return never
reached the finally that resets to false).

Cherry-pick of 493ea987 src/tools/dequeue.ts changes from branch 10-0873.

2955 tests pass.

* stamp 10-0876 APPROVED (round 2): inflightDequeue gap fixed by 10-0873 runDrainLoop

* test(10-0869): add name_tag branch coverage to apply and load tests

* docs(10-0869): curator dogfood walkthrough for custom name tags

* tasks(10-0869): advance to 60-review — fix-pass complete

* move 10-0876 to 60-review: APPROVED stamp committed d398317

* seal 10-0876: Major debounce on activity-file mtime touches

All 7 ACs passed. inflightDequeue gap fixed by 10-0873 runDrainLoop
extraction (setDequeueActive(sid,true) moved to after session_closed
check; try/finally guarantees reset). Cherry-picked to release/7.4
as 6423998.

Sealed-By: Overseer

* stamp 10-0869 APPROVED (round 2): both gaps resolved — name_tag tests + dogfood doc

* seal 10-0869: TMCP custom name tags — fix-pass complete

All 8 ACs satisfied. name_tag tests added to apply.test.ts (3) and
load.test.ts (2). Dogfood walkthrough at docs/dogfood/10-0869-name-tags.md.
Feature on dev + release/7.4 (e191714).

Sealed-By: Overseer

* fix(review): address all PR #167 review findings

Critical fixes:
- dequeue-endpoint: wrap async Express handler in try/catch with next(err)
- dequeue-endpoint: remove connection_token (accepted but silently ignored)
- name-tag: add backtick validation to prevent broken Markdown in headers
- apply.ts: fall back to legacy nametag_emoji field when name_tag missing
- ActivityFileState: remove phantom absorbedCount field (new file, no compat needed)

Moderate fixes:
- file-state.ts: rewrite module doc (removed false MAX_INTERVAL_MS/ACTIVITY_SUPPRESS_MS promises)
- file-state.ts: fix validateFilePath path-traversal check (split on separators, not substring)
- file-state.ts: replace console.warn with dlog('tool', ...)
- import_profile: add backtick/newline regex to name_tag Zod schema

DRY / minor:
- name-tag.ts: extract resolveNameTag() exported helper
- outbound-proxy.ts: use resolveNameTag() from name-tag.ts, remove duplicate expression
- dequeue-endpoint.ts: extract parseIntParam() helper, remove redundant isFinite check

Docs:
- changelog/2026-05-04_v7.4.0.md: add missing entries (name tags, HTTP dequeue, kick-debounce, fixes, breaking changes)
- changelog/unreleased.md: document all review fixes

* feat(spike): add investigation into `unrenderable_chars_warning` validity

* task(10-0880): promote onboarding-monitor-wiring to queued + assign ID

Operator-prioritized for ASAP merge into release/7.4 — biggest
just-works gap for new Claude Code users.

* feat(10-0880): runtime-conditional onboarding_loop_pattern with Monitor wiring example

* feat(10-0880): refine loop framing — dequeue IS the loop, watcher additive, Claude Code should

* test(10-0880): update start help test assertion — 5 min not 5 minutes

* tasks(7.4): file 10-0881 (help/onboarding audit) + 10-0882 (test content audit)

Operator surfaced (msg 50386 + 50387 + 50388) that help/start.md
Dequeue Loop section is over-explained, onboarding service msg
duplicates exposition, and tests assert on copy strings instead of
logic. Both Worker-claimable for dev.

* task(10-0883): file activity-file-touch regression — release blocker

Activity file mtime stopped bumping after 10-0876+10-0880 merges to
release/7.4. TMCP otherwise healthy. P10 release blocker.

* task(10-0883): refine — first verify TMCP running latest code before bisecting

* task(10-0883): close — stale-process verdict, rebuilt from release/7.4@a664ae26

Root cause: dist built at 13:13 PDT before 6423998 was committed.
setDequeueActive(true) before session_closed guard -> inflightDequeue
stuck permanently -> all activity file touches suppressed.

Fix: rebuilt from release/7.4 (includes 6423998 guard-first ordering).

* task(10-0883): move to 60-review — awaits Overseer/Curator verification

Incorrectly moved to 70-done; task pipeline requires review stage before done.

* task(10-0883): done — nothing-done verdict, stale process not a code bug

* feat(10-0880): tighten onboarding_loop_pattern phrasing

Replace dense single-paragraph message (with inline bash/PS snippets and
soft "you should also wire up" framing) with two numbered essentials and
a breadcrumb to help topics. Operator directive: imperative, precise,
breadcrumb to depth — agents do not need max_wait values, mtime detail,
or runtime examples in the startup beat.

Before: ~115 words, inline bash + PS, "you should also wire up".
After: ~45 words, two numbered bits, "Details: help('start'),
help('dequeue'), help('activity/file')."

Use template literal with real newlines (avoids hook false-positive on
':\n' Windows-drive-letter pattern). No tests pinned the literal
string. Full suite passes (2978/2978).

* task(10-0884): file language conciseness audit — service msgs, hints, help topics

* task(10-0884): queue — worktree ready at tmcp-language-audit

* feat(10-0880): trim session/start response to {token, sid, hint}

Operator directive 5/6: response payload was over-stuffed pollution.
Strip to just what an agent needs at the top of the loop.

Drop from fresh-path response: suffix, sessions_active, action, pending,
discarded, fellow_sessions, connection_token. Drop from reconnect-path
response: sessions_active, action, pending. Mutation that set
res.fellow_sessions on multi-session join also removed.

connection_token (duplicate-session detection) is removed from the
visible response. dequeue still accepts the param for legacy callers
(no error path) but new agents will not be passing it. Detection feature
is therefore quiescent — kill it in a follow-up if desired.

DESCRIPTION updated to: "Returns { token, sid, hint } — call dequeue(token)
next to enter the loop." Old self-referential "Call help() first ..."
tail dropped.

Tests in start.test.ts updated for new shape (the two toEqual
assertions). Other start.test.ts cases use field-by-field assertions
and pass unchanged. Other suites that may probe the dropped fields are
operator-acknowledged as breaking ("ignore test failures for now") — to
be cleaned up under the broader test-language audit.

* task(10-0885): file 10-0884 audit follow-up — apply 18 findings

Curator-reviewed audit at audit/language-conciseness.md is sound. Filing
the implementation task for Worker. Direct on release/7.4 per operator
("as much as we can get into release/7.4"). Two prior-commit caveats
called out (items #6 docs/help/start.md and #15 session/start.ts
DESCRIPTION). 90 min bailout.

* task(10-0886): file response payload audit task — tool response bloat

* feat(10-0880): onboarding_loop_pattern v8 — welcome framing, runtime-agnostic

Cold-read assessment surfaced two soft spots:
- "Stay in the loop" presumed the loop already existed (fresh agent had no
  context) → replaced with "Welcome to the loop. Stay in it." which
  establishes the loop AND positions the agent as already inside it.
- Capitalized "(Monitor)" parenthetical was a Claude-Code-specific cue;
  agents in other harnesses might miss it → replaced with "Check your
  tools for an option to monitor a file" which is runtime-agnostic.

Bit 1 also gains the explicit token signature (dequeue(token)) so a fresh
agent does not have to hunt the dequeue tool description for the param.

Same length, same breadcrumbs, same numbered structure.

* task(10-0885): claim — applying 18 language-conciseness findings to release/7.4

* task(10-0887): file 10-0886 audit follow-up — apply 20 findings

Curator-reviewed audit at audit/response-payload.md is sound. Filing
implementation task for Worker. Direct on release/7.4. 90 min bailout.
Two design-call caveats called out (items #18 activity/get, #19
message/pin).

* task(10-0887): drop 90-min cap — use presence protocol (5/10 min status)

Operator-stated norm: workers typically finish in <10 min, often <1 min.
Wrong tool: time cap. Right tool: presence checklist + 5-min/10-min
status messages explaining progress. Codification into Worker refresh
context follows in a separate change.

* fix(10-0885): apply 18 language-conciseness findings from audit 10-0884

High (6): help.ts DESCRIPTION, ONBOARDING_BUTTONS_TEXT, ONBOARDING_MODALITY_PRIORITY,
send.md audio+text, guide.md keyboard taxonomy, start.md activity watcher
Medium (9): ONBOARDING_PROTOCOL, ONBOARDING_PRESENCE_SIGNALS, ONBOARDING_HYBRID_MESSAGING,
send:choice hint, send:animation hint, send.ts MISSING_CONTENT, activity/create hint,
action.ts hint, session/start DESCRIPTION
Low (3): SESSION_DENIED hint, help/index intro, help/animation REST trigger

* task(10-0885): review — 18 findings applied at ffb4fd5 on release/7.4

* task(10-0887): claim — applying 20 response payload audit findings to release/7.4

* fix(10-0887): apply 20 response-payload audit findings from 10-0886

High (5): remove sent/split bool from send, empty dequeue.empty, approved from approve, started/timeout from show-typing, dm/delete/cancel {} confirmed
Medium (8): routed, ok, loaded, saved, rolled, updated, cancelled booleans removed; session/close reason removed; animation/status unwrapped
Low (3): activity/get registered, message/pin unified, animation/cancel false-case preserved

* task(10-0887): review — 20 findings applied at fd06edf on release/7.4

* task(10-0882): bump P10 + retarget release/7.4 — CI blocker

Operator (msg 50562): CI failing on content-string assertions. This task
is now the merge gate for release/7.4. Worker should follow the new
NO STRING-CONTENT TESTS rule (b797e64 in worker submodule) and scrub
existing tests retroactively. Presence protocol replaces 90-min cap.

* task(10-0882): claim — scrub content-string assertions, CI gate for PR #167

* test(10-0882): scrub content-string assertions and stale payload-field checks

- Remove prose toContain assertions (split:true, cancelled:true, empty:true, action, fellow_sessions, discarded, connection_token, pending)
- Replace doc-string checks with typeof/length guards in first-use-hints, service-messages, shutdown, dequeue, help tests
- All 2978 tests pass

* pipeline: promote 10-0867 to 40-queued (operator GO msg 50751)

Text-after-audio message ordering — small UX bug. Hybrid sends sometimes
land caption before audio renders. Worker-claimable.

* task: 50-0866 promote to 40-queued + 60s minimum timeout (operator msg 50761)

Operator-directed timeout floor: 60s minimum, never lower. Cancelling
too early on legitimate long TTS renders is the bigger risk than the
hang we're trying to catch. Default 60s; configurable; 90-120 ceiling
acceptable.

* task: 50-0866 step 1 = research timeout cause; dynamic scaling (operator msg 50768 + 50766)

Step 1 reframed: don't wrap a timeout blindly — first investigate
whether it's server-side timeout (errors bubble) or client-side hang
(no response). Different failure modes, different fixes.

Step 3 spec extended with dynamic word-count scaling formula:
timeout = max(60s, words/100 * 60s). Examples in body.

* task(10-0888): add startup monitor-guidance service message to queue

* fix: lower kick-debounce minimum to 1s (was 30s)

* release: v7.4.1 — kick-debounce minimum 1s

* pipeline: claim 10-0867-fix-text-after-audio-message-ordering.md

* pipeline: claim 10-0880-onboarding-activity-file-monitor-wiring.md

* pipeline(10-0880): move to 60-review — onboarding monitor guidance complete

* pipeline: claim 10-0881-help-and-onboarding-text-audit.md

* pipeline: claim 10-0888-startup-monitor-guidance-service-message.md

* pipeline: claim 50-0866-tts-render-timeout-hybrid-sends.md

* pipeline: move 10-0867, 10-0881, 10-0888 to 60-review

* task(10-0889): spike — streaming text output from agents to Telegram (operator P1)

* task(10-0889): deepen spike — v7.5/v8 target, core token-routing question, prior attempts noted

* seal: 6 TMCP tasks shipped in PR #168 (v7.4.1)

* close: 10-0884 and 10-0886 superseded by 10-0885/10-0887 (shipped in PR #168)

* task(10-0890): spike — @mention agent-to-agent messaging (operator 2026-05-07)

* task(90-0890): lower priority to 90 — not a near-term push

* pipeline: return 50-0866 to 40-queued — orphaned, no branch/worktree created

* pipeline: promote 10-0882 to 60-review — work shipped in PR #167 (v7.4), no active branch found

* claim(50-0866): TTS render timeout — Copilot Worker

* review(50-0866): TTS render timeout implemented — moving to 60-review

* review(50-0866): revision 2 — TimeoutError fix, docs added (74 tests pass)

* feat(50-0866): TTS synthesis timeout — dynamic AbortSignal.timeout, tts_timeout error code, send docs

Squashed from feat/50-0866-tts-render-timeout.
Root cause: synthesizeHttpToOgg() had no client-side fetch timeout.
Fix: computeTtsSynthesisTimeoutMs(text) = max(60s, ceil(words/100)*60s),
AbortSignal.timeout() on fetch, TimeoutError|AbortError caught as tts_timeout.
NaN guards on env vars. 74/74 tests passing.

* seal(50-0866): TTS render timeout — squash 119d852 on TMCP dev

Sealed-By: Overseer

* chore(10-0889): claim streaming spike

* review(10-0889): streaming spike complete — Option A prototyped, findings doc, follow-on 20-1047 filed

* feat(10-0889): streaming spike — Option A prototype (stream/start, stream/chunk, stream/flush)

Squashed from feat/10-0889-streaming-spike.
Verdict: real LLM token streaming not possible (Claude Code SDK opaque to MCP).
Prototype: 3-action streaming protocol. Rate limit ~1 edit/sec, 2.5x token cost.
Findings: docs/spikes/10-0889-streaming-findings.md. 11/11 tests passing.
Follow-on: 20-1047 (production hardening — rate limit guard, timeout, overflow guard).

* seal(10-0889): streaming spike — squash 65f9063 on TMCP dev

Sealed-By: Overseer

* pipeline(10-0882): return to 40-queued — NEEDS_REVISION, ~30 violations documented, target dev

* refactor(10-0882): replace prose content-string assertions with structural assertions (2992 tests passing)

* review(10-0882): promote to 60-review — tests content-string audit complete

Worker (SID 2) replaced ~44 prose assertions with structural checks across
9 test files. 136/136 files, 2992/2992 tests passing. Committed at 3d16c1d.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0882): APPROVED — content-string audit complete

Opus verification: all violations fixed, structural replacements verified,
2992/2992 tests passing at commit 3d16c1d.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal(10-0882): done — content-string test audit

APPROVED by Opus. All prose copy assertions replaced with structural
checks. 2992/2992 tests passing at 3d16c1d on TMCP dev.

Sealed-by: Overseer 2026-05-07

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* task(10-0891): file activity-file monitor-arm reminder idea

Filed 2026-05-09 from Curator session that omitted the Monitor arm
step at session start and the operator caught the gap on review.

Bridge currently provisions an activity file via
action(type: 'activity/file/create') and returns the path, but does
not nudge the caller to arm a Monitor tool against it. Two-prong
fix proposed: (1) response hint pointing at Monitor arming, (2)
one-time service message on next dequeue with event_type
activity_file_monitor_reminder, acked when first post-create
dequeue served.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0892): file v7 tag backfill as Worker dogfood candidate

Per operator 2026-05-10: prior v7.x releases (7.0 through 7.4)
shipped via PR merge but never got git tags. Latest tag is v5.0.1
despite codebase being on v7.4.1 (tagged manually 2026-05-10).

Bounded mechanical task on a single repo — ideal first real-task
candidate for the ephemeral Worker once the engineering chain is
dialed in.

Includes the source commit list (one per version) so the eventual
Worker has a deterministic input.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(10-0893): recordActivityTouch must not cancel pending kick timer

recordActivityTouch was clearing entry.debounceTimer on every agent tool call.
Any pending kick (scheduled by touchActivityFile when an inbound message arrived
within the debounce window) was silently cancelled the moment the agent made its
next tool call. Active agents never saw kicks; only fully idle agents did.

Fix: remove the clearTimeout block from recordActivityTouch. Agent tool calls
now only update lastActivityAt (extending the suppression window for the NEXT
inbound) without cancelling the existing timer.

The timer's recursive touchActivityFile re-evaluation already handles all gating
correctly when it fires. The only legitimate timer-cancel sites are clearActivityFile,
replaceActivityFile, and setDequeueActive — all of which remain unchanged.

Test 4 updated to assert the correct behavior (timer preserved after tool calls).
Test 11 added as a regression guard for the active-agent scenario.

* task(10-0893): move to 70-done after worker merge

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
electricessence added a commit that referenced this pull request May 11, 2026
* pipeline: icebox 15-0837 — superseded by 7.2.2 BUILTIN_PRESETS implementation

* draft+queue(20-0841): spike — pre-stage node_modules in TMCP worktrees (auto-queued: research with concrete output)

* draft(15-0843): help('shutdown') must carry canonical governor procedure verbatim

Filed at operator request after Curator quiz turn. Worker-delegatable doc-fix
on docs/help/shutdown.md Governor Shutdown section.

* pipeline: claim 20-0841-spike-worktree-node-modules-prestaging.md

* seal: 20-0841 — spike: pre-stage node_modules in TMCP worktrees

Findings: Candidate 4 (worktree-create hook) + Candidate 1 (shared virtual store)
recommended. Per operator guidance: per-repo sanctioned script on Worker allowlist.
5 operator decisions remain open in findings doc for implementation follow-on.

Sealed-By: Overseer

* fix(startup): remove blocking operator-prompt path from session-startup SKILL

* draft: auto-pin blocking questions feature (operator directive 2026-04-26)

* triage: route 6 tasks to curator-only (Curator-authored or delegation: curator)

- 10-0836: TMCP skills overhaul — Curator-led, multi-cycle
- 10-737: hook hash fragility reform — Curator authors design doc directly
- 15-734: hook error disambiguation — Curator authors hook patch directly (trust boundary)
- 20-721: V7 master merge readiness — Curator orchestrates audit + PR
- 30-470: remove dead registerTool calls — Curator must revise spec (premise incorrect per W2)
- friction-pnpm-install-worktree-block: explicit delegation: curator

* triage: route 3 tasks to needs-refinement (require Curator spec before Worker claim)

- 10-733: zombie session reconnect security — needs Curator spec, Worker cannot define security boundary
- 15-736: loud-on-anomaly observability — "Curator should spec anomaly taxonomy before claim"
- 15-349: compaction event logging — multi-phase, deletes hooks (Curator trust boundary)

* queue: 05-0826 recording-indicator-refcount-race-and-suppression-gaps (operator-approved)

* queue: 05-0829 investigate-worker-haiku-compaction-and-handoff-bleed (operator-approved)

* note: 05-0829 — verify-first guidance from operator before implementing fixes

* seal: spike-0841 pnpm-worktree-prestaging (operator-verified, direction set)

* queue: 15-0827 seal-commit-misses-worker-completion-notes (operator-approved)

* queue: 15-0843 help-shutdown-canonical-governor-procedure (operator-approved)

* queue: 15-0848 reply-target-not-active-question-no-skip (operator-approved)

* queue: 15-0838 curator-shutdown-metrics-report (operator-approved)

* queue: 20-draft session-joined-fellow-service-message (operator-approved)

* docs: standardize session memory save format (10-0548)

Update telegram-mcp-session-startup SKILL.md and help session/start.md
to document the two-format standard: Minimal (raw integer in
session.token) and Full (YAML body in session.md). Remove PIN field
references; update token formula to use 'suffix' not 'pin'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(help): add index topic to overview and schema describe (10-0549)

- buildOverview(): mention help(topic: 'index') for categorized skill index
- topic.describe(): add 'index' option so schema introspection surfaces the topic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0826-recording-indicator-refcount-race-and-suppression-gaps.md

* feat(send): hybrid caption-duplication detector (Jaccard-based) (squash 20-0822)

Adds detectCaptionDuplication (Jaccard similarity, content-word tokenisation,
ratio gates) wired into all three send paths. Fires NUDGE_CAPTION_DUPLICATION
when caption appears to restate audio. All 2860 tests pass.

Also: draft task 15-0849 tts-underscore-string-replace (operator-filed 2026-04-26)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal: 20-0822 hybrid-duplication-detector — Jaccard detector merged, all tests pass

Note: ship-criteria corpus validation skipped; conservative thresholds expected
to hold. Monitor for FP noise in production.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* queue: 15-0849 tts-underscore-string-replace (operator-directed, scope confirmed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(tasks): normalize 70-done/20260424 → 70-done/2026/04/24 (canonical date format)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: claim 05-0829-investigate-worker-haiku-compaction-and-handoff-bleed.md

* pipeline: claim 15-0849-tts-underscore-string-replace.md

* pipeline: claim 15-0843-help-shutdown-canonical-governor-procedure.md

* seal: 05-0829 Worker recovery investigation — both bugs already fixed, skill promoted

Bug 1 (Overseer recovery staged-state signal): already in context/refresh.md.
Bug 2 (Worker staged-state Worktree Gate): promoted from memory to task-execution/SKILL.md.
Postmortem in Curator repo. All 4 unknowns resolved.

Sealed-By: Overseer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(docs): MD032 blank line before list in session/start help (Copilot #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(recording): epoch guard for refcount race + typing suppression gaps (05-0826)

Squash-merged branch 05-0826. Epoch token prevents stale async callbacks from
corrupting refcount; suppression-gap fixes ensure typing indicator clears reliably.

Sealed-By: Overseer

* fix(help/shutdown): canonical governor shutdown procedure with explicit token path (15-0843)

Squash-merged branch 15-0843. Rewrites shutdown.md into Participant/Governor sections
with verbatim operator-stated sequences; adds wipe-before-shutdown ordering assertion.

Sealed-By: Overseer

* chore: seal 05-0826 and 15-0843 → 70-done/2026/04/26

Sealed-By: Overseer

* fix(button-helpers): off-target reply guard in pollButtonOrTextOrVoice (15-0848)

Squash-merged branch 15-0848. Three-way rule: ambiguous (no reply_to), on-target
(reply matches question), off-target (reply ≠ question → re-enqueue, prompt open).

Sealed-By: Overseer

* chore: seal 15-0848 → 70-done/2026/04/26

Sealed-By: Overseer

* chore: seal 15-0827 (investigation) → 70-done/2026/04/26

Root cause confirmed: Overseer seal renames task file from dev branch which lacks
Worker's Completion section. Fix is Overseer-side (include complete() commit or
copy Completion at seal time). No Worker SKILL change needed.

Sealed-By: Overseer

* feat(tts): normalize ALL_CAPS_WITH_UNDERSCORES identifiers for speech (15-0849)

Squash-merged branch 15-0849. Adds normalizeCapsForTts() — converts identifiers
like SESSION_JOINED to "session joined" in TTS output. Toggle off via
TTS_CAPS_NORMALIZE=false.

Sealed-By: Overseer

* chore: seal 15-0849 → 70-done/2026/04/26

Sealed-By: Overseer

* pipeline: claim 15-0838-curator-shutdown-metrics-report.md

* feat(skill): graceful-shutdown step 6 compaction metrics report (15-0838)

Squash-merged branch 15-0838. Updated graceful-shutdown skill in electrified-cortex
to add Step 6 (pre-shutdown compaction metrics report via event-report.mjs).

Sealed-By: Overseer

* chore: seal 15-0838 → 70-done/2026/04/26

Sealed-By: Overseer

* refactor(session): extract SESSION_JOINED_FELLOW to service-messages.ts (20-draft)

Squash-merged branch 20-draft-fellow. Eliminates hardcoded inline string in
session/start.ts; governor/non-governor paths now both use SERVICE_MESSAGES constants.

Sealed-By: Overseer

* chore: seal 20-draft → 70-done/2026/04/26

Sealed-By: Overseer

* feat(guidance): lazy trigger delivery for onboarding messages (10-0581)

Squash-merged branch 10-0581. Moves 5 session-start onboarding messages to
trigger-based delivery; adds help('guidance') taxonomy topic.

Sealed-By: Overseer

* chore: promote 15-0850 to 40-queued (operator approved 2026-04-26)

* pipeline: claim 15-0850-recovering-animation-replace-with-compacted-notify.md

* feat(compaction): replace recovering animation with compacted notify on first post-compacted activity (15-0850)

Squash-merged from branch 15-0850.
Sealed-By: Overseer

* feat(animation): add status API, stale-on-idle warning, timeout default shift (15-763)

- animation/status action: returns active animation state per session; governor variant lists all
- Stale-on-idle dequeue warning: animation_stale_warning event after ≥30s idle (120s cooldown)
- Timeout default: 600s → 60s across send, show, animation-state
- Help docs: animation.md + presence.md updated with lifecycle rules

Sealed-By: Overseer

* docs(send): add messaging spectrum and audio format rules (20-766)

7-row spectrum table (text-only long through audio-only) with trigger conditions.
Audio format rules: natural language, fluid prose, minimal punctuation, no
voice-unfriendly content.

Sealed-By: Overseer

* fix(lint): address Copilot MD055 + line-length + regex-hoisting comments (PR #164)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add .code-reviews/ to .gitignore (eval artefacts contain local paths)

* eval(10-0858): haiku-class L1 vs sonnet-class L2 comparison report

Squashed-from: 10-0858
Sealed-By: Overseer

* fix(10-0859): extract deliverCaptionDuplicationNudge helper

Squashed-from: 10-0859
Sealed-By: Overseer

* fix(10-0860): correct presence.md stale animation warning shape

Docs said service_message with event_type; actual impl returns dequeue
update item with event: animation_stale_warning.

Squashed-from: 10-0860
Sealed-By: Overseer

* fix(10-0861): clarify animation/status SID variant return shape in docs

SID variant implemented by 15-763; docs updated to disambiguate
single-session vs multi-session response shapes.

Squashed-from: 10-0861
Sealed-By: Overseer

* seal: task 15-0863 — Verify choose callback cannot fire twice

Static analysis confirms _callbackHooks one-shot de-registration is
synchronous before any await. Node.js single-thread guarantee ensures
exactly one delivery for all interactive modes (choose, confirm, question).

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* pipeline: move 15-0862 to 60-review

* seal: task 15-0862 — Add 250ms delay between button color-flip and collapse

BUTTON_COLLAPSE_DELAY_MS=250 constant; gated on real button press only
(callbackQueryId truthy). Persistent path passes delayMs=0. All 2930
tests passing. New fake-timer gate test added.

Sealed-By: Overseer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove async from handleAnimationStatus function and adjust test tick handling

* feat(tasks): file 50-0865 + 50-0866 from Overseer wedge postmortem

- 50-0865: bridge auto-terminate for stuck sessions (no recovery
  after N consecutive unhealthy events)
- 50-0866: TTS render timeout for hybrid sends (prevent silent
  indefinite block)

Both surface from 2026-05-03 5-alarm Overseer wedge incident
where auto-recovery silently gave up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0867 consumer hook setup guidance

Document the loop-guard + compaction-notification hook patterns
for outside TMCP consumers. Operator (2026-05-04): patterns exist
in-house but are poorly documented for fresh integrators.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(tasks): file 50-0868 build per-session touch-file feature

Operator (2026-05-04): ship the bridge-side feature now without
waiting for Monitor wakeup-semantics validation. Per-session touch
file with random-hash filename, leading+trailing-suppressed
debounce, activity-aware reset, lifecycle tied to session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): flip ownership — agent provides path, TMCP just touches

Operator (2026-05-04 late): TMCP doesn't allocate/create/delete the
touch file. Agent owns it, registers path via monitor/register.
TMCP records and touches; nothing else. Cleaner separation,
opt-in by construction, TMCP filesystem stays empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): hybrid opt-in — agent OR TMCP supplies path

Operator (2026-05-04 final): monitor/enable supports two shapes:
- agent-supplied path: TMCP records, never creates/deletes
- TMCP-supplied: TMCP generates random hash, owns lifecycle
Either way: opt-in only. Without enable, zero I/O.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): rename to session-file CRUD, agnostic naming

Operator (2026-05-04): drop the Monitor framing — TMCP exposes a
filesystem hook, consumer chooses how to watch. CRUD verbs:
session-file/create, session-file/edit, session-file/delete,
session-file/get. Path-supplied vs TMCP-generated still both
supported; ownership rules carry through.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): correct namespace to session/file/ (under existing session/)

Operator (2026-05-04): not session-file/, but session/file/ —
extends the existing session/ namespace (session/start, session/
close, session/list).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): final namespace activity/file/ + decision rationale

Operator (2026-05-04 final): activity/file/ wins. The file signals
activity, doesn't record session state. Top-level namespace
parallel to session/, leaves room for sibling activity hooks
(presence, typing, etc) later.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): auto-shorten dequeue default to 5s on activity/file/create

Operator (2026-05-04): familiar Claude pattern. Reverts on delete.
Per-call override still respected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): clarify max_wait override is temporary, default = 5min

Operator (2026-05-04): activity/file/create applies a TEMPORARY
override (not a profile mutation). activity/file/delete clears it
back to the standard 5min default. Per-call still trumps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note agent can override the override via profile/dequeue-default

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(50-0868): note loop-guard becomes redundant with activity/file in use

Operator (2026-05-04): emergent simplification — loop-guard exists
to catch silent stuck agents during 300s blocking dequeues. With
5s default + kicker, that failure mode shrinks 60x. Future task:
deprecate + remove loop guard once activity/file adopted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0864-session-close-confirm-show-identity.md

* feat(50-0864): session-close confirmation includes name and SID

Squash-merged task/50-0864-session-close-identity.

* pipeline(50-0864): move to 60-review

Task complete per Worker 3 — squash merged, advancing to review stage.

* seal(50-0864): session-close confirmation includes name and SID

Sealed-By: Overseer SID 6
Squash: 3276f1a
Worker: Worker 3 (SID 9)
Verdict: PASS

* pipeline: claim 50-0865-bridge-auto-terminate-stuck-sessions.md

* kill(50-0865): auto-terminate stuck sessions — bogus heuristic

Operator (2026-05-04): no reliable way to determine 'stuck.'
With activity/file (50-0868) coming, peer-liveness is observable
directly. Auto-terminate is redundant or needs new basis.

Moved to icebox with KILLED marker. Branch + worktree pruned.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore(50-0866): move to 10-drafts pending operator stamp (postmortem sibling)

Same category as the killed 50-0865 — postmortem-derived
speculative fix. Operator stamps before Worker builds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* pipeline: claim 50-0867-consumer-hook-setup-guidance-loop-guard-compaction.md

* pipeline: move 50-0867 to 60-review — W1 complete, pending verification

* docs: add consumer-hooks.md — loop guard + compaction setup guide (50-0867)

Documents how TMCP consumers wire up loop guard (Stop hook) and
compaction notifications (PreCompact/PostCompact) including settings
JSON, env vars, 6-step checklist, and common pitfalls.

Sealed-By: Overseer

* seal: task 50-0867 — consumer hook setup guidance doc

Sealed-By: Overseer

* pipeline: claim 50-0868-build-per-session-touch-file-feature.md

* pipeline: move 50-0868 to 60-review — W1 complete, pending verification

* feat(activity): per-session touch-file feature for external activity monitoring (50-0868)

Adds activity/file/create|edit|get|delete action paths and session-level
debounced mtime-touch on inbound messages. Enables Overseer/external agents
to monitor session liveness via filesystem mtime without polling Telegram.

Sealed-By: Overseer

* seal: task 50-0868 — per-session activity touch-file feature

Sealed-By: Overseer

* chore(release): cut v7.4.0 release branch

* draft(10-0867): fix text-after-audio message ordering — per-session outbound queue

* review(10-0973): adversarial GPT-5.4 review of TMCP 7.4

Two high, two medium findings:
- H1: arbitrary host-file append primitive via session token
- H2: failed touches recorded as successful (silent wakeup black-hole)
- M1: activity suppression can drop only wakeup edge
- M2: delete/rotation claims success when file is still on disk

No critical bugs. Blast-radius expansion is the main concern.
Dispatched via Copilot Worker runSubagent(model: 'GPT-5.4 (copilot)').

Forced into tasks/notes/ (normally gitignored — one-off audit artifact).

* feat: update closeSessionById mock to include optional name parameter

* feat: update closeSessionById mock to include optional name parameter

* feat: refactor name-tag storage to a single editable string and update default behavior

* task(10-0870): align activity/file/edit response shape with create

Sibling endpoint cleanup task — drop ok+tmcp_owned, add hint field
to match the create-side reshape from this session.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity): tighten hint phrasing + queue help-topic + spoon-feed follow-ups

- create.ts hint: 'Configure your watcher to call dequeue() when this file changes' (clearer action than the prior phrasing)
- 10-0870 reword to match new hint string
- 10-0871: replace hint with help('activity/file') pointer + write the help topic (full watcher recipe, mtime caveat, role permissions)
- 10-0872: watcher spoon-feeds dequeue via /mcp HTTP (saves a round-trip per wake)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: queue 10-0870 + 10-0871 (activity/file shape + help topic)

10-0870: align activity/file/edit response with create-side reshape.
10-0871: replace hint with help('activity/file') pointer + write the
help topic (depends on 0870).

10-0872 (watcher spoon-feeds dequeue) stays in drafts — Curator-owned
design with 7 open questions to pin first.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: rewrite 10-0872 (watcher pre-drain), file 10-0873 (HTTP dequeue endpoint), capture show-typing nudge friction

10-0872: pivot from round-trip framing to turn-count framing per operator.
Watcher curls the dequeue endpoint, includes drained events in wake notification.
Skip-parameter idea iceboxed (operator: not needed if drain is genuine).

10-0873: sibling Worker-shippable task. Two paths considered:
dedicated /dequeue endpoint vs documented /mcp JSON-RPC use.
Operator leaning toward dedicated endpoint; pending confirmation.

00-ideas/show-typing-...: friction note. behavior_nudge_typing_rate
overfires show-typing on every receipt; operator clarified show-typing
is a composition-imminent signal only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0874 (suppress health-check when activity-file active)

Operator: health-check is misleading when activity-monitor already
maintains presence. Skip the prompt for sessions with active
activity-file registry entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: promote 10-0869 (custom name tags) drafts -> 40-queued

Operator directing Copilot Worker to this. Target 7.4 release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0869): claim — Worker SID 2

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(10-0869): custom name tags — single string, no robot emoji, name-tag action, profile integration

- Remove nametag_emoji from Session, ProfileData, all handlers
- Add Session.name_tag?: string (explicit override) + defaultNameTag() export
- buildHeader: wrap entire name_tag in monospace; color now inside the tag
- New action handlers: name-tag (get/set), name-tag/set alias
- profile/save: persist name_tag only when explicitly set
- profile/apply: apply name_tag from loaded profile
- profile/import: name_tag param (max 64 chars, no newlines)
- action.ts: register name-tag actions, replace nametag_emoji schema field
- Tests: +17 net new; all 2947 pass

* chore(10-0869): advance task to 60-review

* tasks: lock 10-0873 (dedicated /dequeue endpoint), promote to queued, icebox REST-mirror

Operator decision 2026-05-05: dedicated /dequeue route, not /mcp.
/mcp is gated by mcp-session-id header from MCP SDK transport;
raw curl returns 400. Direct Express handler bypasses transport,
shares internal drain handler with MCP tool, response shape identical.

REST-mirror-all-tools idea iceboxed in 00-ideas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0873): GET as primary shape, platform-agnostic help

Operator: keep the help OS-agnostic — Windows, Mac, Linux.
Express intent (call this URL), not one shell.
GET /dequeue?token=... is the simplest shape.
POST also accepted for richer args.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0872): mark superseded — long-poll dequeue is primary

Operator clarified architecture: long-poll dequeue is primary
(handles content delivery), Monitor is just a "kick the loop"
nudge replacing the old Telegram loop guard. Spoon-feeding events
through Monitor is over-design.

Spec kept in 10-drafts as a record. Status: superseded. No work.

See Curator memory feedback_dequeue_long_poll_primary_monitor_nudge.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0875 (remove ACTIVITY_FILE_DEQUEUE_CAP_S = 5)

Operator: long-poll dequeue is primary, Monitor is just a nudge.
The 5s cap added in 50-0868 was for the Monitor-as-primary
framing; that framing is reverted, cap goes too. Default 300s
stays. Per-session dequeueDefault stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0876 (major debounce on activity-file mtime touches)

Operator: mtime bump is an idle kick, not a per-message signal.
Scale ACTIVITY_SUPPRESS_MS from 10s to 60s, reset on any
session-token tool call, suppress while dequeue is in-flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): add one-nudge-per-cycle rule + state machine

Operator: after a nudge fires, no more bumps until a dequeue from
that session is observed. Dequeue is the reset signal. Prevents
nudge-storm if agent is unresponsive; multiple inbound messages
during idle coalesce to one mtime bump.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks(10-0876): broaden activity definition + add per-session configurable debounce

Operator: nudge inhibited by ANY session activity (animations,
typing, in-flight async sends, mid-multi-step turn). Total silence
required.

Add profile/kick-debounce action (parallel to profile/dequeue-default)
to make the window per-session configurable. Default 60_000ms,
range 30s..10min.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: file 10-0877 (revert onboarding framing) + reframe 10-0871

10-0877: docs-only revert of onboarding service messages + help
docs to dequeue-primary, Monitor-optional-augment framing.
Companion to 10-0875 (cap removal) and 10-0876 (debounce).

10-0871 description updated with operator's framing — Monitor as
optional augment replacing telegram loop guard, NOT primary
delivery. Platform-agnostic help language.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* chore: claim 10-0875 — remove activity-file dequeue cap

* fix(dequeue): remove activity-file dequeue cap (ACTIVITY_FILE_DEQUEUE_CAP_S)

Dequeue now always honors session dequeueDefault (fallback 300s) regardless
of activity/file registration status. The 5s cap was introduced in 50-0868
under the premise that Monitor would wake agents frequently — new framing
reverses that: long-poll is the win, Monitor is just a nudge.

Removes:
- ACTIVITY_FILE_DEQUEUE_CAP_S constant from file-state.ts
- import of isActivityFileActive + ACTIVITY_FILE_DEQUEUE_CAP_S in dequeue.ts
- Activity-file override block in dequeue.ts (cap application)

Behavior: dequeue effective timeout = sessionDefault (or explicit max_wait).
No activity-file registration can shorten it below the session default.

Closes 10-0875

* chore: move 10-0875 to 60-review — dequeue cap removed, tests pass

* chore: claim 10-0876 — major debounce on activity-file touch

* tasks: remove duplicate 10-0869 from 10-drafts (canonical at 50-active post merge)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(activity-file): major debounce — idle-kick state machine

Replaces the leading+trailing 5s debounce with a true idle-kick state
machine. The bridge now waits for >= kickDebounceMs (default 60s) of
complete session silence before bumping the activity file mtime. This
prevents false wake-ups while the agent is actively processing.

State machine:
- nudgeArmed: one kick per dequeue cycle (re-armed on dequeue return)
- inflightDequeue: suppress kicks while agent is blocking in dequeue
- recordActivityTouch: any tool call resets the suppression window
- timer: single scheduled kick when window expires (no storm on bursts)
- setDequeueActive(false): re-arms cycle + resets lastActivityAt

New: profile/kick-debounce action (GET/SET per-session debounce window).
New: getKickDebounceMs/setKickDebounceMs in session-manager.ts.
New: 8 unit tests covering all state transitions.

Closes task 10-0876.

* chore(tasks): move 10-0876 to 60-review

* chore(tasks): claim 10-0877

* docs(onboarding): dequeue-primary framing — activity-file as optional augment

Add ONBOARDING_LOOP_PATTERN service message fired on session/start (both
single- and multi-session paths). Explains dequeue long-poll (300 s) as the
standard heartbeat and presents the activity-file pattern as an opt-in augment
for harnesses with a filesystem watcher.

Update docs/help/start.md Dequeue Loop section with the same opt-in callout.

No existing message text changed. No Monitor-as-primary framing was found in
the codebase — all onboarding messages were already dequeue-primary. This adds
the missing augment note per the operator directive.

Closes #10-0877

* chore(tasks): move 10-0877 to 60-review

* task(10-0878): file robot-emoji removal sweep, promote to queued

Operator authorized 2026-05-05 — strip 🤖 from default name tag
across 9 production surfaces (outbound-proxy, session start/reconnect,
disconnect/promote notices, /sessions header). Tests + docs covered;
input-rejection tests preserved.

Worker can claim.

* pipeline: claim 10-0870-activity-file-edit-response-shape-consistency.md

* pipeline: promote 10-0870 to 60-review, add bug + draft

- 60-review: 10-0870 activity-file/edit response shape (Worker 2 done,
  branch 10-0870 commit 171b1471, build+tests green)
- 00-ideas: checklist/update bug report
- 10-drafts: activity-file monitor onboarding improvement task

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0870): stamp APPROVED

* pipeline: claim 10-0871-activity-file-help-topic-and-hint-pointer.md

* pipeline: claim 10-0878 — robot-emoji sweep

* feat(10-0878): strip 🤖 from all TMCP output surfaces

Remove robot emoji from 9 production surfaces and matching tests.
Emoji fatigue — operator request 2026-05-05.

Surfaces updated:
- outbound-proxy.ts: multi-session header prefix
- tools/session/start.ts: approval dialog, denied reply,
  reconnect dialog, reconnect denied, online announce (pinned), comment
- session-teardown.ts: disconnect notice, governor promotion
- built-in-commands.ts: /sessions header

Tests updated (output assertions only):
- animation-state.test.ts: header mock + assertion
- startup-token-cleanup.test.ts: 3 pinned-message fixtures
- tools/session/close.test.ts: 4 disconnect-notice assertions

Unchanged (input-rejection tests):
- tools/session/start.test.ts:711 (validates robot in user input)
- rename.test.ts:130 (same)
- session-manager.test.ts:655,657 (negative assertion — already correct)

pnpm test: 2955 passed, 0 failed

* pipeline: move 10-0878 to 60-review — merged into release/7.4

* pipeline: claim 10-0873-http-dequeue-endpoint-for-watcher.md

* pipeline: move 10-0871 to 60-review — code review PASS, completion appended

* verify(10-0871, 10-0878): stamps committed — both APPROVED

* feat(10-0871): add activity/file help topic + redirect hint to help()

Adds docs/help/activity/file.md with full wake-nudge guide (purpose,
lifecycle, wake mechanism, watcher patterns, error modes). Registers
activity/file in RICH_TOPICS. Updates hint string in create.ts and edit.ts
to "Call help('activity/file') now". Adds hermetic test for help topic.

Also applies 10-0870 shape alignment to edit.ts (ok+tmcp_owned → hint).
Includes 10-0870 dep since that branch not yet squash-merged to dev.

Squash-merged from branches 10-0871 (includes 10-0870). Sealed-By: Overseer

* seal(10-0870, 10-0871, 10-0878): TMCP batch seal

10-0870: activity/edit shape alignment — included in 10-0871 squash (9453f0b)
10-0871: activity/file help topic + hint redirect — squash on dev
10-0878: robot emoji removal — merged to release/7.4 (commit 2ddd78d8)

Sealed-By: Overseer

* verify(10-0875, 10-0876, 10-0877): stamps committed — 0875 APPROVED, 0876 NEEDS_REVISION (inflightDequeue leak), 0877 APPROVED

* seal+return(10-0875, 10-0876, 10-0877):

10-0875: APPROVED — dequeue cap removed, sealed 70-done
10-0877: APPROVED — onboarding augment framing, sealed 70-done
10-0876: NEEDS_REVISION — inflightDequeue leaked on early returns in dequeue.ts; returned to 50-active for fix

Sealed-By: Overseer

* stamp 10-0869 NEEDS_REVISION: missing profile-load tests + dogfood docs

* 10-0869 → 50-active (NEEDS_REVISION)

* stamp 10-0873 NEEDS_REVISION: AC6 help topic not updated (hint text + dequeue HTTP doc missing)

* stamp 10-0873 APPROVED (round 2): AC6 fix confirmed — hint text + dequeue-http help doc

* feat(10-0873): add GET|POST /dequeue HTTP endpoint + extract runDrainLoop

- New src/dequeue-endpoint.ts: GET/POST /dequeue route, token validation, shape parity with MCP tool
- New src/dequeue-endpoint.test.ts: 17 test cases (happy path, 401 paths, instant poll, session_closed)
- src/tools/dequeue.ts: extract runDrainLoop to shared fn; fix setDequeueActive leak (session_closed check before flag set)
- src/tools/activity/create.ts: update hint text to reference GET /dequeue HTTP URL
- docs/help/dequeue-http.md: new help topic with curl/PowerShell/Node fetch examples
- src/tools/help.ts: register dequeue-http in RICH_TOPICS + DESCRIPTION

Squash of branch 10-0873 (493ea987 + 69ea884e)

* seal 10-0873 → 70-done/2026/05/05/ — APPROVED

Sealed-By: Overseer

* fix(10-0876): move setDequeueActive after session_closed guard in dequeue.ts

Extract runDrainLoop() from dequeue handler and guard setDequeueActive(sid, true)
AFTER the session_closed check. Previously the flag was set before the check,
leaving it stuck true for dead sessions (session_closed early return never
reached the finally that resets to false).

Cherry-pick of 493ea987 src/tools/dequeue.ts changes from branch 10-0873.

2955 tests pass.

* stamp 10-0876 APPROVED (round 2): inflightDequeue gap fixed by 10-0873 runDrainLoop

* test(10-0869): add name_tag branch coverage to apply and load tests

* docs(10-0869): curator dogfood walkthrough for custom name tags

* tasks(10-0869): advance to 60-review — fix-pass complete

* move 10-0876 to 60-review: APPROVED stamp committed d3983170

* seal 10-0876: Major debounce on activity-file mtime touches

All 7 ACs passed. inflightDequeue gap fixed by 10-0873 runDrainLoop
extraction (setDequeueActive(sid,true) moved to after session_closed
check; try/finally guarantees reset). Cherry-picked to release/7.4
as 6423998d.

Sealed-By: Overseer

* stamp 10-0869 APPROVED (round 2): both gaps resolved — name_tag tests + dogfood doc

* seal 10-0869: TMCP custom name tags — fix-pass complete

All 8 ACs satisfied. name_tag tests added to apply.test.ts (3) and
load.test.ts (2). Dogfood walkthrough at docs/dogfood/10-0869-name-tags.md.
Feature on dev + release/7.4 (e1917141).

Sealed-By: Overseer

* fix(review): address all PR #167 review findings

Critical fixes:
- dequeue-endpoint: wrap async Express handler in try/catch with next(err)
- dequeue-endpoint: remove connection_token (accepted but silently ignored)
- name-tag: add backtick validation to prevent broken Markdown in headers
- apply.ts: fall back to legacy nametag_emoji field when name_tag missing
- ActivityFileState: remove phantom absorbedCount field (new file, no compat needed)

Moderate fixes:
- file-state.ts: rewrite module doc (removed false MAX_INTERVAL_MS/ACTIVITY_SUPPRESS_MS promises)
- file-state.ts: fix validateFilePath path-traversal check (split on separators, not substring)
- file-state.ts: replace console.warn with dlog('tool', ...)
- import_profile: add backtick/newline regex to name_tag Zod schema

DRY / minor:
- name-tag.ts: extract resolveNameTag() exported helper
- outbound-proxy.ts: use resolveNameTag() from name-tag.ts, remove duplicate expression
- dequeue-endpoint.ts: extract parseIntParam() helper, remove redundant isFinite check

Docs:
- changelog/2026-05-04_v7.4.0.md: add missing entries (name tags, HTTP dequeue, kick-debounce, fixes, breaking changes)
- changelog/unreleased.md: document all review fixes

* feat(spike): add investigation into `unrenderable_chars_warning` validity

* task(10-0880): promote onboarding-monitor-wiring to queued + assign ID

Operator-prioritized for ASAP merge into release/7.4 — biggest
just-works gap for new Claude Code users.

* feat(10-0880): runtime-conditional onboarding_loop_pattern with Monitor wiring example

* feat(10-0880): refine loop framing — dequeue IS the loop, watcher additive, Claude Code should

* test(10-0880): update start help test assertion — 5 min not 5 minutes

* tasks(7.4): file 10-0881 (help/onboarding audit) + 10-0882 (test content audit)

Operator surfaced (msg 50386 + 50387 + 50388) that help/start.md
Dequeue Loop section is over-explained, onboarding service msg
duplicates exposition, and tests assert on copy strings instead of
logic. Both Worker-claimable for dev.

* task(10-0883): file activity-file-touch regression — release blocker

Activity file mtime stopped bumping after 10-0876+10-0880 merges to
release/7.4. TMCP otherwise healthy. P10 release blocker.

* task(10-0883): refine — first verify TMCP running latest code before bisecting

* task(10-0883): close — stale-process verdict, rebuilt from release/7.4@a664ae26

Root cause: dist built at 13:13 PDT before 6423998d was committed.
setDequeueActive(true) before session_closed guard -> inflightDequeue
stuck permanently -> all activity file touches suppressed.

Fix: rebuilt from release/7.4 (includes 6423998d guard-first ordering).

* task(10-0883): move to 60-review — awaits Overseer/Curator verification

Incorrectly moved to 70-done; task pipeline requires review stage before done.

* task(10-0883): done — nothing-done verdict, stale process not a code bug

* feat(10-0880): tighten onboarding_loop_pattern phrasing

Replace dense single-paragraph message (with inline bash/PS snippets and
soft "you should also wire up" framing) with two numbered essentials and
a breadcrumb to help topics. Operator directive: imperative, precise,
breadcrumb to depth — agents do not need max_wait values, mtime detail,
or runtime examples in the startup beat.

Before: ~115 words, inline bash + PS, "you should also wire up".
After: ~45 words, two numbered bits, "Details: help('start'),
help('dequeue'), help('activity/file')."

Use template literal with real newlines (avoids hook false-positive on
':\n' Windows-drive-letter pattern). No tests pinned the literal
string. Full suite passes (2978/2978).

* task(10-0884): file language conciseness audit — service msgs, hints, help topics

* task(10-0884): queue — worktree ready at tmcp-language-audit

* feat(10-0880): trim session/start response to {token, sid, hint}

Operator directive 5/6: response payload was over-stuffed pollution.
Strip to just what an agent needs at the top of the loop.

Drop from fresh-path response: suffix, sessions_active, action, pending,
discarded, fellow_sessions, connection_token. Drop from reconnect-path
response: sessions_active, action, pending. Mutation that set
res.fellow_sessions on multi-session join also removed.

connection_token (duplicate-session detection) is removed from the
visible response. dequeue still accepts the param for legacy callers
(no error path) but new agents will not be passing it. Detection feature
is therefore quiescent — kill it in a follow-up if desired.

DESCRIPTION updated to: "Returns { token, sid, hint } — call dequeue(token)
next to enter the loop." Old self-referential "Call help() first ..."
tail dropped.

Tests in start.test.ts updated for new shape (the two toEqual
assertions). Other start.test.ts cases use field-by-field assertions
and pass unchanged. Other suites that may probe the dropped fields are
operator-acknowledged as breaking ("ignore test failures for now") — to
be cleaned up under the broader test-language audit.

* task(10-0885): file 10-0884 audit follow-up — apply 18 findings

Curator-reviewed audit at audit/language-conciseness.md is sound. Filing
the implementation task for Worker. Direct on release/7.4 per operator
("as much as we can get into release/7.4"). Two prior-commit caveats
called out (items #6 docs/help/start.md and #15 session/start.ts
DESCRIPTION). 90 min bailout.

* task(10-0886): file response payload audit task — tool response bloat

* feat(10-0880): onboarding_loop_pattern v8 — welcome framing, runtime-agnostic

Cold-read assessment surfaced two soft spots:
- "Stay in the loop" presumed the loop already existed (fresh agent had no
  context) → replaced with "Welcome to the loop. Stay in it." which
  establishes the loop AND positions the agent as already inside it.
- Capitalized "(Monitor)" parenthetical was a Claude-Code-specific cue;
  agents in other harnesses might miss it → replaced with "Check your
  tools for an option to monitor a file" which is runtime-agnostic.

Bit 1 also gains the explicit token signature (dequeue(token)) so a fresh
agent does not have to hunt the dequeue tool description for the param.

Same length, same breadcrumbs, same numbered structure.

* task(10-0885): claim — applying 18 language-conciseness findings to release/7.4

* task(10-0887): file 10-0886 audit follow-up — apply 20 findings

Curator-reviewed audit at audit/response-payload.md is sound. Filing
implementation task for Worker. Direct on release/7.4. 90 min bailout.
Two design-call caveats called out (items #18 activity/get, #19
message/pin).

* task(10-0887): drop 90-min cap — use presence protocol (5/10 min status)

Operator-stated norm: workers typically finish in <10 min, often <1 min.
Wrong tool: time cap. Right tool: presence checklist + 5-min/10-min
status messages explaining progress. Codification into Worker refresh
context follows in a separate change.

* fix(10-0885): apply 18 language-conciseness findings from audit 10-0884

High (6): help.ts DESCRIPTION, ONBOARDING_BUTTONS_TEXT, ONBOARDING_MODALITY_PRIORITY,
send.md audio+text, guide.md keyboard taxonomy, start.md activity watcher
Medium (9): ONBOARDING_PROTOCOL, ONBOARDING_PRESENCE_SIGNALS, ONBOARDING_HYBRID_MESSAGING,
send:choice hint, send:animation hint, send.ts MISSING_CONTENT, activity/create hint,
action.ts hint, session/start DESCRIPTION
Low (3): SESSION_DENIED hint, help/index intro, help/animation REST trigger

* task(10-0885): review — 18 findings applied at ffb4fd5e on release/7.4

* task(10-0887): claim — applying 20 response payload audit findings to release/7.4

* fix(10-0887): apply 20 response-payload audit findings from 10-0886

High (5): remove sent/split bool from send, empty dequeue.empty, approved from approve, started/timeout from show-typing, dm/delete/cancel {} confirmed
Medium (8): routed, ok, loaded, saved, rolled, updated, cancelled booleans removed; session/close reason removed; animation/status unwrapped
Low (3): activity/get registered, message/pin unified, animation/cancel false-case preserved

* task(10-0887): review — 20 findings applied at fd06edf8 on release/7.4

* task(10-0882): bump P10 + retarget release/7.4 — CI blocker

Operator (msg 50562): CI failing on content-string assertions. This task
is now the merge gate for release/7.4. Worker should follow the new
NO STRING-CONTENT TESTS rule (b797e64 in worker submodule) and scrub
existing tests retroactively. Presence protocol replaces 90-min cap.

* task(10-0882): claim — scrub content-string assertions, CI gate for PR #167

* test(10-0882): scrub content-string assertions and stale payload-field checks

- Remove prose toContain assertions (split:true, cancelled:true, empty:true, action, fellow_sessions, discarded, connection_token, pending)
- Replace doc-string checks with typeof/length guards in first-use-hints, service-messages, shutdown, dequeue, help tests
- All 2978 tests pass

* pipeline: promote 10-0867 to 40-queued (operator GO msg 50751)

Text-after-audio message ordering — small UX bug. Hybrid sends sometimes
land caption before audio renders. Worker-claimable.

* task: 50-0866 promote to 40-queued + 60s minimum timeout (operator msg 50761)

Operator-directed timeout floor: 60s minimum, never lower. Cancelling
too early on legitimate long TTS renders is the bigger risk than the
hang we're trying to catch. Default 60s; configurable; 90-120 ceiling
acceptable.

* task: 50-0866 step 1 = research timeout cause; dynamic scaling (operator msg 50768 + 50766)

Step 1 reframed: don't wrap a timeout blindly — first investigate
whether it's server-side timeout (errors bubble) or client-side hang
(no response). Different failure modes, different fixes.

Step 3 spec extended with dynamic word-count scaling formula:
timeout = max(60s, words/100 * 60s). Examples in body.

* task(10-0888): add startup monitor-guidance service message to queue

* fix: lower kick-debounce minimum to 1s (was 30s)

* release: v7.4.1 — kick-debounce minimum 1s

* pipeline: claim 10-0867-fix-text-after-audio-message-ordering.md

* pipeline: claim 10-0880-onboarding-activity-file-monitor-wiring.md

* pipeline(10-0880): move to 60-review — onboarding monitor guidance complete

* pipeline: claim 10-0881-help-and-onboarding-text-audit.md

* pipeline: claim 10-0888-startup-monitor-guidance-service-message.md

* pipeline: claim 50-0866-tts-render-timeout-hybrid-sends.md

* pipeline: move 10-0867, 10-0881, 10-0888 to 60-review

* task(10-0889): spike — streaming text output from agents to Telegram (operator P1)

* task(10-0889): deepen spike — v7.5/v8 target, core token-routing question, prior attempts noted

* seal: 6 TMCP tasks shipped in PR #168 (v7.4.1)

* close: 10-0884 and 10-0886 superseded by 10-0885/10-0887 (shipped in PR #168)

* task(10-0890): spike — @mention agent-to-agent messaging (operator 2026-05-07)

* task(90-0890): lower priority to 90 — not a near-term push

* pipeline: return 50-0866 to 40-queued — orphaned, no branch/worktree created

* pipeline: promote 10-0882 to 60-review — work shipped in PR #167 (v7.4), no active branch found

* claim(50-0866): TTS render timeout — Copilot Worker

* review(50-0866): TTS render timeout implemented — moving to 60-review

* review(50-0866): revision 2 — TimeoutError fix, docs added (74 tests pass)

* feat(50-0866): TTS synthesis timeout — dynamic AbortSignal.timeout, tts_timeout error code, send docs

Squashed from feat/50-0866-tts-render-timeout.
Root cause: synthesizeHttpToOgg() had no client-side fetch timeout.
Fix: computeTtsSynthesisTimeoutMs(text) = max(60s, ceil(words/100)*60s),
AbortSignal.timeout() on fetch, TimeoutError|AbortError caught as tts_timeout.
NaN guards on env vars. 74/74 tests passing.

* seal(50-0866): TTS render timeout — squash 119d852 on TMCP dev

Sealed-By: Overseer

* chore(10-0889): claim streaming spike

* review(10-0889): streaming spike complete — Option A prototyped, findings doc, follow-on 20-1047 filed

* feat(10-0889): streaming spike — Option A prototype (stream/start, stream/chunk, stream/flush)

Squashed from feat/10-0889-streaming-spike.
Verdict: real LLM token streaming not possible (Claude Code SDK opaque to MCP).
Prototype: 3-action streaming protocol. Rate limit ~1 edit/sec, 2.5x token cost.
Findings: docs/spikes/10-0889-streaming-findings.md. 11/11 tests passing.
Follow-on: 20-1047 (production hardening — rate limit guard, timeout, overflow guard).

* seal(10-0889): streaming spike — squash 65f9063e on TMCP dev

Sealed-By: Overseer

* pipeline(10-0882): return to 40-queued — NEEDS_REVISION, ~30 violations documented, target dev

* refactor(10-0882): replace prose content-string assertions with structural assertions (2992 tests passing)

* review(10-0882): promote to 60-review — tests content-string audit complete

Worker (SID 2) replaced ~44 prose assertions with structural checks across
9 test files. 136/136 files, 2992/2992 tests passing. Committed at 3d16c1df.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* verify(10-0882): APPROVED — content-string audit complete

Opus verification: all violations fixed, structural replacements verified,
2992/2992 tests passing at commit 3d16c1df.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* seal(10-0882): done — content-string test audit

APPROVED by Opus. All prose copy assertions replaced with structural
checks. 2992/2992 tests passing at 3d16c1df on TMCP dev.

Sealed-by: Overseer 2026-05-07

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* task(10-0891): file activity-file monitor-arm reminder idea

Filed 2026-05-09 from Curator session that omitted the Monitor arm
step at session start and the operator caught the gap on review.

Bridge currently provisions an activity file via
action(type: 'activity/file/create') and returns the path, but does
not nudge the caller to arm a Monitor tool against it. Two-prong
fix proposed: (1) response hint pointing at Monitor arming, (2)
one-time service message on next dequeue with event_type
activity_file_monitor_reminder, acked when first post-create
dequeue served.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* task(10-0892): file v7 tag backfill as Worker dogfood candidate

Per operator 2026-05-10: prior v7.x releases (7.0 through 7.4)
shipped via PR merge but never got git tags. Latest tag is v5.0.1
despite codebase being on v7.4.1 (tagged manually 2026-05-10).

Bounded mechanical task on a single repo — ideal first real-task
candidate for the ephemeral Worker once the engineering chain is
dialed in.

Includes the source commit list (one per version) so the eventual
Worker has a deterministic input.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(10-0893): recordActivityTouch must not cancel pending kick timer

recordActivityTouch was clearing entry.debounceTimer on every agent tool call.
Any pending kick (scheduled by touchActivityFile when an inbound message arrived
within the debounce window) was silently cancelled the moment the agent made its
next tool call. Active agents never saw kicks; only fully idle agents did.

Fix: remove the clearTimeout block from recordActivityTouch. Agent tool calls
now only update lastActivityAt (extending the suppression window for the NEXT
inbound) without cancelling the existing timer.

The timer's recursive touchActivityFile re-evaluation already handles all gating
correctly when it fires. The only legitimate timer-cancel sites are clearActivityFile,
replaceActivityFile, and setDequeueActive — all of which remain unchanged.

Test 4 updated to assert the correct behavior (timer preserved after tool calls).
Test 11 added as a regression guard for the active-agent scenario.

* task(10-0893): move to 70-done after worker merge

* tasks: file 10-0894 + 10-0895 targeting release/7.4.3

- 10-0894 (40-queued): stopped HTTP event for instant kick flush.
  Foreman-ready.
- 10-0895 (50-active): activity-file kick still broken post-7.4.2.
  Curator DIY per operator direction.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* tasks: add audits for agent language conciseness and tool response payload bloat

* tasks: add spike for streaming text output from agents to Telegram

* feat(10-0894): add stopped HTTP event kind — instant activity-file kick flush

Add `stopped` to the POST /event allow-list. When a session POSTs
`kind: stopped`, the server cancels any pending debounce timer, re-arms
the nudge cycle (nudgeArmed=true), and issues an immediate doTouch to
the activity file — signaling the external watcher that the session is
available before the resumed agent re-enters its loop.

New exports:
  - handleSessionStopped(sid) in src/tools/activity/file-state.ts

Changes:
  - src/event-endpoint.ts: added stopped to VALID_KINDS; wired handler;
    stopped does not trigger governor animation
  - src/tools/activity/file-state.ts: exported handleSessionStopped
  - docs/help/events.md: documented stopped kind and its side effects

Tests:
  - src/event-endpoint.test.ts: 4 new tests for stopped kind
  - src/tools/activity/file-state.test.ts: 2 new tests (12, 13)

Agent-side wiring (firing stopped on TaskStop) is deferred per AC3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(10-0894): add stopped HTTP event kind — instant activity-file kick flush

Add `stopped` to the POST /event allow-list. When a session POSTs
`kind: stopped`, the server cancels any pending debounce timer, re-arms
the nudge cycle (nudgeArmed=true), and issues an immediate doTouch to
the activity file — signaling the external watcher that the session is
available before the resumed agent re-enters its loop.

New exports:
  - handleSessionStopped(sid) in src/tools/activity/file-state.ts

Changes:
  - src/event-endpoint.ts: added stopped to VALID_KINDS; wired handler;
    stopped does not trigger governor animation
  - src/tools/activity/file-state.ts: exported handleSessionStopped
  - docs/help/events.md: documented stopped kind and its side effects

Tests:
  - src/event-endpoint.test.ts: 4 new tests for stopped kind
  - src/tools/activity/file-state.test.ts: 2 new tests (12, 13)

Agent-side wiring (firing stopped on TaskStop) is deferred per AC3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* task(10-0894): move to 70-done after worker merge

* fix(10-0895): dequeue must clear inflightDequeue on early-return paths

The dequeue handler calls setDequeueActive(sid, true) at the start, but
the matching setDequeueActive(sid, false) only fires inside a finally
block that doesn't begin until after the immediate-batch return and the
timeout=0 empty-poll return. Both early returns bypass the finally and
leave inflightDequeue stuck at true.

Effect: after the first dequeue, every inbound message hits the
inflightDequeue gate in touchActivityFile and is silently suppressed.
The activity-file kick never fires again for that session — defeating
the entire purpose of the file-state state machine.

This is the second-order bug behind 10-0895 (kick still broken
post-7.4.2). PR #172 fixed recordActivityTouch but left this latent
defect because the file-state unit tests cover only file-state in
isolation; no test exercises the dequeue tool's lifecycle effect on
inflightDequeue.

Fix: add setDequeueActive(sid, false) calls before each early return.
A regression test exercising the dequeue lifecycle is a follow-up.

Also includes the foreman's 10-0894 task move to 70-done (stopped
HTTP event handler, separate work shipped on this branch).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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