voyage/tests/fixtures/jsonl-schemas.md
Kjell Tore Guttormsen 1989656a9c
feat(run): the run step names Claude Code's run; owner=run is a built-in owner (A2)
The coupling to Claude Code's built-in run skill (wave 4, order A2,
decisions 54 and 64). The plan's "run the thing" step, the executor's
End to end part and the plan template each say in one sentence that the
app is seen and driven with run, and that the verdict is still the
End-to-end: command, because run gives no exit code. The template quotes
the name instead of backticking it: every backticked span on a template
step bullet is read as a runnable example.

R2: lib/skills/routing.mjs keeps a short fixed list of Claude Code's own
skills a quiet case may name as owner (BUILTIN_OWNERS, only run, seen in
2.1.303). For such an owner only "not taken" is checked, and the report
says so; ROUTING_NEGATIVE_WON stands, and an owner on no list is still
ROUTING_UNKNOWN_OWNER. skill-writing-criteria-quiet-2 gets owner=run.

The trekplan.md paragraph is reflowed to its old line count so the stats
line_ref there does not move (order B edits the same file); the
trekexecute Phase 9 line_ref fixture moves by two lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:26:10 +02:00

80 lines
6.2 KiB
Markdown

# Voyage JSONL stats — schema audit (v4.1 input)
> **Purpose:** Field-allowlist input for v4.1 OTel exporter (Step 11). Lists every
> field every voyage stats JSONL writer emits today, plus the additive fields v4.1
> introduces. Load-bearing for Step 11 (field-allowlist) and Step 8 (stats plumbing).
>
> **PII-flag:** `command_excerpt` from `hooks/scripts/post-bash-stats.mjs` slices
> the first 120 chars of an arbitrary Bash command — may contain operator paths,
> branch names, or fragments of secrets that survived the secrets-hook. CWE-212
> (Improper Cross-boundary Removal of Sensitive Data). The OTel exporter MUST
> NOT export this field unless the operator explicitly opts in via
> `VOYAGE_EXPORT_INCLUDE_COMMAND_EXCERPT=1` (deferred to v4.2 — v4.1 hard-excludes).
>
> **Additive v4.1 fields:** `profile`, `phase_models`, `parallel_agents`,
> `external_research_enabled`, `profile_source`. All are forward-compat: existing
> v4.0 consumers ignore unknown keys, v4.1 consumers get richer signal.
## Field table per JSONL writer
| schema_id | fields | writer_path | line_ref | v4.1 additive | PII |
|-----------|--------|-------------|----------|---------------|-----|
| trekbrief-stats | ts, task, slug, mode, interview_turns, review_iterations, brief_quality, research_topics, auto_research, auto_result, intent_approved, project_dir, order_id, order_claimed_at, order_reason | commands/trekbrief.md (orchestrator-emit Phase 7; order_* added by lib/stats/stats-append.mjs) | trekbrief.md:1128-1152 | profile, phase_models, profile_source | none |
| trekresearch-stats | ts, question, mode, scope, engine, slug, project_dir, brief_path, dimensions, dimensions_baseline, dimensions_baseline_preserved, effort, conv_turns, empty_turns, unique_sources, agents_local, agents_external, gemini_used, confidence, contradictions, open_questions | lib/stats/stats-append.mjs (trekresearch.md Stats tracking) | trekresearch.md:782-808 | profile, phase_models, parallel_agents, external_research_enabled, profile_source | none |
| trekplan-stats | ts, task, mode, slug, brief_path, project_dir, codebase_size, codebase_files, agents_deployed, deep_dives, research_briefs_used, research_scout_used, critic_verdict, guardian_verdict, outcome | lib/stats/stats-append.mjs (trekplan.md Phase 12) | trekplan.md:1277-1305 | profile, phase_models, parallel_agents, profile_source | none |
| trekexecute-stats (Phase 9 record) | ts, plan, plan_type, mode, result, steps_total, steps_passed, steps_failed, steps_skipped, failed_at_step | lib/stats/stats-append.mjs (trekexecute.md Phase 9) | trekexecute.md:2909-2931 | profile, phase_models, profile_source | none |
| trekexecute-stats (autonomy events) | ts, event, known_event, payload | lib/stats/event-emit.mjs `emit()` | event-emit.mjs:78-99 | payload.profile, payload.phase_models, payload.profile_source | none |
| trekexecute-stats (PostToolUse Bash) | ts, session_id, command_excerpt, duration_ms, success | hooks/scripts/post-bash-stats.mjs (Bash PostToolUse) | post-bash-stats.mjs:42-54 | none (hook is plugin-level, not profile-aware) | command_excerpt (CWE-212) |
| trekreview-stats | ts, slug, verdict, counts (BLOCKER/MAJOR/MINOR/SUGGESTION), reviewed_files_count, mode, duration_ms | lib/stats/stats-append.mjs (trekreview.md Phase 8) | trekreview.md:636-686 | profile, phase_models, profile_source | none |
| trekcontinue-stats | ts, project, next_session_label, status | lib/stats/stats-append.mjs (trekcontinue.md Phase 5) | trekcontinue.md:293-297 | profile, profile_source | none |
| token-usage | ts, session_id, scope, model, tokens_input, tokens_output, tokens_cache_creation, tokens_cache_read, cost_usd, is_estimate, price_table_version | lib/stats/token-usage.mjs `captureTokenUsage` (via hooks/scripts/otel-export.mjs Stop hook, opt-in `VOYAGE_TOKEN_METER`) | token-usage.mjs:buildRecord | n/a (SKAL-2 schema) | session_id (stripped at export) |
## Field-allowlist input for Step 11
The OTel exporter (Step 11 `lib/exporters/field-allowlist.mjs`) MUST inline the
following static const arrays (NOT load from this file at runtime — Step 11
explicit constraint: INLINE static const, IKKE runtime fra tests/fixtures):
**EXPORT_ALLOWLIST** (numeric/bool/short-string fields safe for OTel metric labels):
```
ts, slug, mode, brief_quality, auto_research, auto_result,
codebase_size, codebase_files, agents_deployed, deep_dives,
agents_local, agents_external, gemini_used, dimensions, confidence,
contradictions, open_questions, interview_turns, review_iterations,
research_topics, research_briefs_used, research_scout_used,
critic_verdict, guardian_verdict, outcome, plan_type, result,
steps_total, steps_passed, steps_failed, steps_skipped, failed_at_step,
verdict, reviewed_files_count, duration_ms, status, next_session_label,
event, known_event, success, scope,
profile, profile_source, parallel_agents, external_research_enabled,
model, tokens_input, tokens_output, tokens_cache_creation, tokens_cache_read,
cost_usd, is_estimate, price_table_version
```
**EXPORT_DENYLIST** (PII or high-cardinality, never export):
```
task, question, project_dir, project, plan, brief_path, command_excerpt, payload, counts, phase_models, session_id,
order_id, order_claimed_at, order_reason
```
> Notes:
> - `task` and `question` may contain user-content prose → high-cardinality + PII risk.
> - `project_dir` and paths leak filesystem layout.
> - `command_excerpt` per CWE-212 above.
> - `phase_models` is a structured object (6 keys) — too high-cardinality for label;
> profile name (`profile`) is the safe summary. v4.2 may revisit if operators ask.
> - `counts` (review BLOCKER/MAJOR/MINOR/SUGGESTION) is a nested object — Step 11
> exporter flattens to `voyage_review_counts_blocker`/`_major`/`_minor`/`_suggestion`
> metrics rather than a label.
> - `session_id` is a UUID — high-cardinality, not useful as a label, log-only.
## Cross-reference
- Step 8 (stats plumbing) — adds `profile` + `phase_models` + `profile_source` to all
6 orchestrator-emit sites listed above.
- Step 11 (field-allowlist) — codifies the EXPORT_ALLOWLIST/DENYLIST arrays above
as inline static consts in `lib/exporters/field-allowlist.mjs`.
- Step 9 (Prometheus textfile) — emits one metric line per allowlist-numeric field
per JSONL writer; PII-flagged fields are dropped at format-layer, not export-layer.