feat(profiler/behave_shell): F.0 prompt-line detector

Adds PromptLine dataclass + extract_prompt_lines() helper. PromptLine
carries ts, suffix_char ($/#/%/>), raw_line (ANSI-stripped, capped),
is_root flag. Populated during the existing single-pass output-window
walk; SessionContext gains prompt_lines, Command gains
followed_by_prompt.

PII trade-off (ANTI-authorised at Phase F): PS1 text retained on ctx
so F.1 / F.3 / E.4 can read it. Capped at PROMPT_LINE_MAX_CHARS=256.
Observations still only carry derived primitive values.

D.0's regex error helpers stay alongside (NOT subsumed) — they fire
even when PS1 echo is suppressed. F.0 enriches D.0 rather than
replacing it.
This commit is contained in:
2026-05-04 00:29:08 -04:00
parent b7534c311a
commit 1ff02f0c77
4 changed files with 280 additions and 15 deletions

View File

@@ -218,6 +218,16 @@ LANDING_RITUAL_FIRST_N: int = 5
LANDING_RITUAL_HIT_MIN: int = 2
LANDING_RITUAL_MIN_COMMANDS: int = 3
# ── F.0 prompt-line detector ──────────────────────────────────────────────
# A prompt line in the output stream ends with one of these characters
# followed by a space or EOL. ``$`` and ``#`` are sh/bash; ``%`` is zsh;
# ``>`` is fish / cmd.exe / powershell (disambiguated by line content
# at F.1 time). Capped at 256 chars to bound memory; ANTI authorised
# retaining PS1 text on ctx (PII relaxation), but a malicious operator
# inflating the prompt buffer is still bounded.
PROMPT_SUFFIX_CHARS: frozenset[str] = frozenset({"$", "#", "%", ">"})
PROMPT_LINE_MAX_CHARS: int = 256
# ── motor.keystroke_cadence (Step B.1) ──────────────────────────────────────
# Typing bursts split at gaps > IKI_THINK_MAX_S so think-pauses between
# commands don't inflate the within-burst CV. Mirrors the prototype's