User pushback: "Агент должен делать осмысленные выводы! С утра должен
быть отчет и пусть он приходит куда-то! На телеграмм, например, лучше
сразу после фазы сна, бот есть"
Wires the @KeiSeiBot Telegram bot as the delivery channel for nightly
Phase B reports, with a Claude Sonnet 4.6 reasoning step in front to
distil the multi-section markdown into a single actionable brief.
NEW — `hooks/sleep-report-tg.sh` (130 LOC POSIX bash)
Pipeline:
1. Source ~/.claude/secrets/.env (umbrella SSoT — RULE 0.8)
2. POST report markdown to Claude API messages endpoint with a
system prompt mandating: TL;DR + numbers + 3-5 actionable
findings + rule-candidates if any cross-session pattern ≥3×.
Sonnet 4.6, max_tokens=1500, 120s timeout.
3. Send distilled summary via Telegram sendMessage to whitelisted
chat_id (defaults to TELEGRAM_ALLOWED_CHAT_ID env, falls back
to 86059912).
4. Cap message at 3900 chars (TG limit 4096).
5. Fallback if Markdown parse_mode fails (orphan * / [ in body) →
retry without parse_mode so the user still sees the report.
6. Defensive on every step: missing API key → send raw excerpt;
missing curl/jq → log + exit 0; HTTP failure → log + exit 0.
7. Bypass: SLEEP_REPORT_TG_BYPASS=1.
WIRE — `hooks/phase-b-rem.sh`
Step 7 (new) calls sleep-report-tg.sh after the existing commit/push
step. Failure of TG delivery never affects Phase B's exit code —
the local report + memory-repo push remain the source-of-truth;
TG is convenience.
CONFIG (already done outside this commit, documented for completeness)
- ~/.claude/secrets/.env now has TELEGRAM_BOT_TOKEN +
TELEGRAM_ALLOWED_CHAT_ID (single-user whitelist 86059912).
- ~/.claude/tg-webhook.py whitelist locked to {86059912}; group
chat (-1003758632751) and partner (10954083) removed per
user request "сделай боту только один вайт адрес". Blocked
senders land in /var/log/tg-webhook/blocked.jsonl, no auto-reply.
- ~/.claude/tg-contacts.json shrunk from 3 contacts to 1.
Smoke verified: today's sleep-2026-05-02.md → cloud agent emitted
TL;DR ("Opus burned $1239 across 117 runs with 100% unknown outcomes")
+ 5 findings + 3 rule-candidates → delivered to chat_id 86059912 as
msg_id 1129 (HTTP 200). Cost: 3955 in + 897 out tokens on Sonnet
≈ $0.025/run. At 1 run/night that is ~$0.75/month for full reasoning
on every nightly report.
What this does NOT yet do:
- No retry on Telegram rate-limit (429). Single nightly call
is well below the 30/sec limit, but if the system ever bursts
multiple reports it would lose them.
- No multi-day digest mode (each run is independent; future:
weekly Sunday recap aggregating 7 reports).
- Cloud agent prompt is hard-coded inline; future: extract to
a path-atom-style block (post-2026-05-02 substrate work).
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: NOT-RUN (pure shell)
behaviour-verified: yes
follow-up-required:
- Phase B prompt template extracted to atom (low priority)
- Weekly recap mode (Sunday)
- 429 rate-limit retry (defensive)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User pushback: "что теперь делает сон? все связано?" — Sleep Phase B
was reading only `traces/`, ignoring the four tracking journals shipped
in the previous commit. Cloud agent had a partial view of what happened.
This commit closes the loop. Sleep now sees everything that's tracked.
PUSH SIDE — `kei-sleep-sync.sh` (called on every Stop event)
Now mirrors the full observability surface into the memory-repo:
~/.claude/memory/time-metrics/sessions.jsonl → time-metrics/
~/.claude/memory/time-metrics/tasks.jsonl → time-metrics/
~/.claude/memory/time-metrics/numeric-claims.jsonl → time-metrics/
~/.claude/memory/time-metrics/agent-toolstats.jsonl→ time-metrics/
~/.claude/agents/ledger.sqlite agents table → ledger/agents.jsonl
~/.claude/agents/ledger.sqlite skill_invocations → ledger/skill_invocations.jsonl
Format: JSONL (one row per object). The two ledger tables are dumped
via `sqlite3 + json_object()` so cloud agents can stream-parse into
pandas / duckdb without binary-file handling.
First sync moved 6 files / 638 rows from local to remote — verified
by `git show --stat` of the resulting `memory: session traces` commit.
CONSUME SIDE — `phase-b-rem.sh` REM-consolidation report
Each nightly `reports/sleep-YYYY-MM-DD.md` now ends with a "Tracking
observability (last 7 days)" section containing four jq-aggregated
digests:
1. Agent outcomes — per-model: n, functional/partial/scaffolding/fail
counts + total_cost_usd. Lets the agent see whether the model-tier
refactor (50c9e76) actually paid off and whether Sonnet success
rate justifies routing more task classes to it.
2. Skill success rates — per-skill: n, successes, rate_pct. Drives
Phase D nightly decisions (archive unused / re-extract failing /
mark validated). Empty until Skill tool is invoked in the next
session.
3. Numeric-claims tier breakdown — REAL / FROM-JOURNAL / ESTIMATE-HTC
counts. High ESTIMATE-HTC ratio = orchestrator under-calibrated.
Cloud agent's job: spot frequent ESTIMATE-HTC categories and
propose conversion to FROM-JOURNAL via measured runs.
4. Agent tool-call patterns — mean tool_use_count, mean duration_ms,
per-tool total calls. Lets the agent see "this code-implementer
spawn made 30 Read but 1 Edit — was tier-allocation correct?".
All four sections gracefully skip if the source JSONL is missing or
empty. jq is the only new dependency (already present per existing
phase-b checks).
What is NOT yet automated:
- The cloud agent's prompt template doesn't yet INSTRUCT it to act
on these digests. Currently the digest is data; whether the agent
proposes rule + hook codification based on it depends on the
free-text instructions in the schedule. Follow-up: codify a Phase B
instruction block that maps each digest to a recommendation pattern.
- Idempotency on `cp` for time-metrics: I use plain `cp` (not `cp -n`)
so the latest local state always overwrites remote. The journals are
append-only on the local side, so this is safe — but if two machines
ever share one memory-repo it would corrupt. Out of scope for
single-machine setup.
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: NOT-RUN (pure shell)
behaviour-verified: yes
follow-up-required:
- Phase B prompt template — instruct cloud agent to act on the four
digests (codify recurring patterns, calibrate ESTIMATE-HTC).
- skill_invocations.jsonl will populate from next session onward.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>