git:20260818.6945463 to git:20260821.1a05a80

30 added, 41 removed. Audit A to A.

---
name: debrief-coding
description: "Telemetry report: `$codemap-py:debrief-coding [flags]`; skip integration/index/query."
---
# Debrief Coding
- Reads `.cache/codemap/logs/` JSONL telemetry, analyses usage patterns, writes a diagnostic report. It discovers legacy flat shards plus recursive `claude/`, `codex/`, and `direct/` runtime trees and keeps unattributed legacy records separate. Codex hooks contribute runtime-scoped CLI and tool shards but no skill-start events, so missing skill telemetry and cross-layer joins remain evidence gaps.
+ Read `.cache/codemap/logs/` JSONL, analyse use, and write a diagnostic report. Include recursive `claude/`, `codex/`, and `direct/` shards; keep legacy flat records unattributed. Codex records runtime-scoped CLI/tool shards but no skill starts, so missing skill telemetry and cross-layer joins are evidence gaps.
- NOT for: validating codemap installation health/integration (use `$codemap-py:integration audit`); building or querying the structural index (use `$codemap-py:scan-codebase` or `$codemap-py:query-code`).
+ NOT for: installation/integration health (use `$codemap-py:integration audit`); index build or structural query (use `$codemap-py:scan-codebase` or `$codemap-py:query-code`).
## Runtime note
- Codex has no `bin/` PATH entry and no `$CLAUDE_PLUGIN_ROOT`-equivalent environment variable. Resolve this skill's installed plugin-root path once, substitute it for `PLUGIN_ROOT` below, and keep it in reasoning — shell state does not persist across tool calls. Telemetry evidence source is otherwise identical to the Claude sibling: local JSONL files under `.cache/codemap/logs/`, written regardless of which runtime's session produced them.
+ Codex has no `bin/` PATH entry or plugin-root variable. Resolve the installed root once, substitute it for `PLUGIN_ROOT`, and retain it in reasoning; shell state does not persist. Telemetry otherwise matches Claude: local JSONL under `.cache/codemap/logs/`.
## Flags
- - `--since <YYYY-MM-DD>` — filter to records on or after this date (default: all)
- - `--session <id>` — filter to a single session UUID
- - `--anonymize` — run `anonymize.py` on the log directory before reading; replaces qualified names with stable pseudonyms, preserves runtime topology, pseudonymizes shard stems, and keeps the salt in `.cache/codemap/logs/.salt` (never included in output)
- - `--output <path>` — write the report to this path (default: `.reports/codemap/debrief-<YYYY-MM-DD>.md`)
+ - `--since <YYYY-MM-DD>`: records on/after date; default all.
+ - `--session <id>`: one session UUID.
+ - `--anonymize`: run `anonymize.py`; pseudonymize qualified names and shard stems, preserve topology, store salt only at `.cache/codemap/logs/.salt`.
+ - `--output <path>`: report path; default `.reports/codemap/debrief-<YYYY-MM-DD>.md`.
- ## Step 0: Verify logs exist
+ ## Workflow
+ ### 1. Verify logs
+
```bash
find .cache/codemap/logs -type f -name '*.jsonl' -print 2>/dev/null
```
- No files → stop: "No codemap telemetry found. Run any `$codemap-py:*` skill or `codemap-py query`/`index` command to start collecting logs."
-
- Telemetry is sharded per session below `logs/claude/`, `logs/codex/`, or `logs/direct/`: CLI records use `cli_<session>.jsonl`, skill records use `skills_<session>.jsonl`, and tool-use records use `tools_<session>.jsonl`; older flat shards remain readable as unattributed legacy evidence. Collect every matching shard recursively, not only the legacy root glob. Preserve flat/runtime topology and report overall, per-runtime, and unattributed summaries; `token_measurement` is unavailable because host hooks provide no token usage.
-
- ## Step 1: Optionally anonymize
+ No files: stop: "No codemap telemetry found. Run any `$codemap-py:*` skill or `codemap-py query`/`index` command to start collecting logs." Collect every matching shard recursively; `cli_<session>.jsonl`, `skills_<session>.jsonl`, and `tools_<session>.jsonl` live below each runtime directory. Flat shards remain unattributed; never infer Claude from tool names. `token_measurement` is unavailable because host hooks expose no token usage.
- If `--anonymize` is given, anonymize the complete log directory (never assume the legacy unsuffixed files exist — per-session sharding means they usually don't):
+ ### 2. Anonymize when requested
```bash
python PLUGIN_ROOT/bin/anonymize.py --input .cache/codemap/logs --out-dir .cache/codemap/export
```
- Anonymized copies land in `.cache/codemap/export/` (separated from `.salt` — never target the logs directory itself). Don't mix anonymized and original data in Step 2. No shard present at all → stop: "no CLI or skill logs found — cannot produce an anonymized report." Only one layer present → anonymize it and note the gap.
-
- ## Step 2: Read log files
-
- Read every CLI shard, every skill shard, and every tool shard recursively, concatenating records before analysing — reading only one file misses runtime/session shards and reports a near-empty dataset.
-
- Each line is one JSON record. Filter by `--since` (`ts` field) and `--session` if given.
-
- `--session` guard: a session UUID may be absent from one or both log layers (e.g. `skills.jsonl` records only skill events, not all CLI events). An empty filtered result for one file is expected, not a data-loss signal.
+ Use only anonymized copies after this step; never mix with raw data. They are separated from `.salt`; never target the log directory. With no shard, stop: "no CLI or skill logs found — cannot produce an anonymized report." With one layer, anonymize it and report the gap.
- CLI record fields: `ts`, `layer`, `runtime`, `v`, `session`, `cmd`, `argv`, `result` (nested: `count`, `query_complete`, `completeness_reason`, `stale`, `method`, `not_covered`, `error`; index records also carry `trigger`, `changed_count`, `incremental`, `stale_before`, and `result_currency`), `timing_ms`, `stderr` (optional), `exit_code` (optional).
- Skill record fields: `ts`, `layer`, `runtime`, `v`, `session`, `skill`, `event`, `intent`, `hook_session`.
- Tool record fields (`layer: "tool"`): `ts`, `layer`, `runtime`, `v`, `session`, `skill`, `event`, `tool`, `target`. Flat legacy records are `unattributed`; never assign them to Claude based only on tool names.
+ ### 3. Read and filter records
- ## Step 3: Analyse
+ Read every CLI, skill, and tool shard recursively; one file is incomplete. Each line is JSON. Filter `ts` by `--since` and `session` by `--session`; an empty filter in one layer is expected because a UUID can be absent there.
- **Pre-filter (both layers)**: drop records with `source: "bench"` and CLI records with an empty `cmd` from all organic-usage stats; report their counts separately as "scripted/polluted records excluded: N". When records carry `v` (plugin version, 0.23+), compute headline stats per distinct `v` as well as overall.
+ - CLI: `ts`, `layer`, `runtime`, `v`, `session`, `cmd`, `argv`, `result` (`count`, `query_complete`, `completeness_reason`, `stale`, `method`, `not_covered`, `error`; index also `trigger`, `changed_count`, `incremental`, `stale_before`, `result_currency`), `timing_ms`, optional `stderr`/`exit_code`.
+ - Skill: `ts`, `layer`, `runtime`, `v`, `session`, `skill`, `event`, `intent`, `hook_session`.
+ - Tool: `ts`, `layer`, `runtime`, `v`, `session`, `skill`, `event`, `tool`, `target`.
- **CLI layer**: total invocations, success vs error rate (`exit_code: 0` = success; non-zero = error; absent = treat as success unless `result.error` is non-empty); completeness reasons (`result.index.completeness_reason`); subcommand distribution; timing (median, p95, max `timing_ms`); coverage (fraction with non-empty `not_covered`); top-5 error patterns by prefix; stale-index warning fraction.
+ ### 4. Analyse
- **Skill layer**: total skill starts by name, distinct session count, first/last timestamp in the dataset.
+ Exclude `source: "bench"` and CLI records with empty `cmd` from organic stats; report their count as "scripted/polluted records excluded: N". When present, group headline statistics by distinct `v`, overall, runtime, and unattributed legacy records.
- **Cross-layer**: sessions appearing in both layers → linked chains (skill invoked → N CLI calls); average CLI calls per skill session.
- Aggregate overall and by runtime; report `unattributed` legacy records separately. Include refresh triggers, changed-count distributions, index-only sessions, incomplete-query reasons, and stale/degraded fractions; legacy provenance remains unknown. Do not present debrief as measured token savings or live fresh-session activation evidence.
+ - CLI: invocations; success/error (`exit_code: 0` success; non-zero error; absent success unless `result.error`); completeness reasons; subcommands; median/p95/max `timing_ms`; non-empty `not_covered` fraction; top five error prefixes; stale fraction.
+ - Skill: starts by name, sessions, first/last timestamp.
+ - Cross-layer: linked skill→N CLI chains, average calls per skill session, refresh triggers, changed-count distribution, index-only sessions, incomplete/degraded fractions; legacy provenance unknown.
- **Avoidance join (guard-chain leak rate)**: join the tool layer against the CLI layer — a search/read whose target names a module codemap already answered completely (`query_complete: true`) within the window is an avoidance event, i.e. the model re-derived by hand what the index had already returned exhaustively.
+ Join tool searches/reads to a complete (`query_complete: true`) CLI answer for the same module within the window: a match is an avoidance event, not an incorrect answer.
```bash
python PLUGIN_ROOT/bin/join_avoidance.py --logs .cache/codemap/logs --window-min 10 --json
```
- A high avoidance rate is a dead-chain signal: guard not firing, injected context not read, or the model ignoring both. Preserve `per_runtime` and `unattributed` metrics, add count and rate to the report Overview, and list flagged modules when non-zero.
+ High avoidance means guard/context/model dead-chain risk. Preserve `per_runtime` and `unattributed`; report count/rate in Overview and flagged modules when non-zero. Do not claim measured token savings or live fresh-session activation.
- ## Step 4: Write report
+ ### 5. Write report
- Output path: `--output` if given, else `.reports/codemap/debrief-<YYYY-MM-DD>.md` (today's date). This path is product-level, not runtime-specific — identical to the Claude sibling's default.
+ Default output is `.reports/codemap/debrief-<YYYY-MM-DD>.md`; use `--output` if supplied.
```bash
mkdir -p .reports/codemap
```
- Write the report with these sections: Overview (2–3 sentence summary), Subcommand distribution, Performance (median/p95/max `timing_ms`), Coverage gaps, Error patterns (top-5 with counts, "none" if clean), Skill invocations, Session timeline (first/last ts, distinct sessions; full chronological event list when `--session` was given).
-
- Print the report path on completion.
+ Include Overview (2–3 sentences), subcommand distribution, performance (median/p95/max), coverage gaps, top-five error patterns (`none` when clean), skill invocations, and session timeline (first/last, sessions; full chronology for `--session`). Print the path.
- ## Security note
+ ## Security
- All logs are local to `.cache/codemap/logs/`. The salt file `.cache/codemap/logs/.salt` must stay local — never share it alongside anonymized output. Anonymized log files themselves are safe to share; without the salt, the pseudonyms are not reversible.
+ Logs and salt are local. Never share `.cache/codemap/logs/.salt`; anonymized files are shareable without it.