Files
portal/docs/observer/README.md
T
Дмитрий 99c7bac99b feat(brain): observer captures real session data via transcript parse
The Stop-hook was writing empty-shell episodes (task_id "unknown-<ts>",
node_chosen "unknown", events []). Root cause: buildEpisodeFromContext
read fields from the Stop-event stdin that Claude Code never sends
(primary_rationale, node_chosen, ...) and the session field name was
wrong (ctx.sessionId camelCase vs Claude Code's session_id). The hook
never read transcript_path — the only real source of session data.

New tools/observer-transcript-parser.mjs — pure parseTranscript(text,
fallbackSessionId):
- Scopes to the last turn (from the last real user prompt to EOF) —
  one episode == one prompt→response cycle. A tool_result-carrier user
  message is not treated as a turn boundary.
- Extracts task_id (real sessionId), timestamps (real duration),
  skill_invoked events, a tool_summary event with per-tool counts,
  error events (tool_result is_error), node_chosen (first skill, else
  "direct"), hard_floor (invoked when a superpowers:* skill is used),
  path_type (regulated/improvised), task_classification (keyword
  heuristic on the prompt).
- Reasoning fields triggers_matched/candidates_considered/
  boundaries_applied stay [] — not recoverable from a transcript;
  their capture is a separate ADR-011 follow-up.

observer-stop-hook.mjs: reads ctx.transcript_path + ctx.session_id
(camelCase fallback kept), readFileSync best-effort, delegates to
parseTranscript. No transcript → graceful fallback to ctx defaults.
Episode schema (5 mandatory + 7-field primary_rationale) unchanged —
no normative change. Stop-event is never blocked (exit 0 on any error).

TDD: 17 parseTranscript tests + 1 buildEpisodeFromContext transcript
test. Full tools Vitest 70/70 GREEN. CLI smoke against a real 575-entry
transcript: episode populated — real task_id, ~6.5 min duration,
tool_summary {Bash:5,Read:5,Grep:1,Edit:9,Write:1}, error event.

Refs: ADR-011 brain governance §6.2 (observer evidence loop).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 08:11:10 +03:00

37 lines
2.2 KiB
Markdown

# Observer infrastructure
Passive evidence-loop for the Лидерра «brain» per ADR-011.
## Files
- `episodes-YYYY-MM.jsonl` — append-only JSONL, one line per Stop-event (one prompt→response turn). Written by `tools/observer-stop-hook.mjs`, which parses the session transcript (`transcript_path`) via `tools/observer-transcript-parser.mjs`.
- `notes/YYYY-MM-DD-<slug>.md` — optional MD notes for sessions with qualitative history.
- `STATUS.md` — auto-generated dashboard. Regenerated per-commit by `tools/status-md-generator.mjs`.
- `.read-counter.json` — C3 observer-of-observer counter. Updated on Read of observer files.
## Lifecycle
1. **Write**: every Stop-event appends one JSONL line, parsed from the session transcript (Stop-hook).
2. **Aggregate**: `/brain-retro` skill reads JSONL each sprint, proposes regulatory candidates.
3. **Surface**: `STATUS.md` shows controllers + monthly stats.
4. **Self-prune**: C3 warns if 54 weeks pass without any read of observer files.
## Privacy
PII filter (phone numbers, emails, tokens) is applied **before** every write — see `tools/observer-pii-filter.mjs`. gitleaks pre-push also scans observer files as part of full-history sweep.
## Don't
- Don't edit `episodes-*.jsonl` manually — it's append-only.
- Don't write outside `docs/observer/notes/` for hand-curated notes.
- Don't change `.read-counter.json` manually — it's maintained by hooks.
## HK1 pre-check (Pravila ADR-010) — verified 2026-05-19
Before registering `tools/observer-stop-hook.mjs` on Stop event (Task B5), verified collision against 6-component economy/skill-discipline architecture:
- **User-level** `~/.claude/settings.json` already has Stop hook: **agent-type** Sonnet-4.6 economy compliance verifier (analyzes transcript for claim-without-evidence violations).
- **Project-level** `.claude/settings.json` — Stop slot empty.
**Result**: no overwrite. observer-stop-hook will be added as **command-type entry in project-level Stop array**. Project + user scopes are independent slots in Claude Code 2.x — both run on the same Stop event without conflict. The agent verifier (user scope) and the JSONL appender (project scope) have non-overlapping responsibilities.