feat(profiler/behave_shell): emit temporal.lifecycle_markers.landing_ritual
Inspect the first N commands; if at least K of their first_token_hashes match the recon-survey vocabulary (uname/id/whoami/pwd/hostname/w/who), emit present, else absent. Hashes precomputed at module load; PII-safe. v0.1 N=5, K=2.
This commit is contained in:
@@ -26,6 +26,7 @@ from decnet.profiler.behave_shell._features.cognitive import (
|
||||
)
|
||||
from decnet.profiler.behave_shell._features.temporal import (
|
||||
escalation_pattern,
|
||||
landing_ritual,
|
||||
session_duration,
|
||||
)
|
||||
from decnet.profiler.behave_shell._features.motor import (
|
||||
@@ -65,4 +66,5 @@ FEATURES: tuple[FeatureFn, ...] = (
|
||||
error_resilience_fallback_to_man,
|
||||
session_duration,
|
||||
escalation_pattern,
|
||||
landing_ritual,
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@ and computed by the attribution engine, not the extractor.
|
||||
|
||||
Step E.1: ``temporal.session_duration``.
|
||||
Step E.2: ``temporal.escalation_pattern``.
|
||||
Step E.3: ``temporal.lifecycle_markers.landing_ritual``.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -18,6 +19,7 @@ from decnet_behave_core.spec.envelope import Observation
|
||||
|
||||
from decnet.profiler.behave_shell._ctx import SessionContext
|
||||
from decnet.profiler.behave_shell._features._emit import make_observation
|
||||
from decnet.profiler.behave_shell._parse import hash_token
|
||||
from decnet.profiler.behave_shell._thresholds import (
|
||||
ESCALATION_BURSTY_CV,
|
||||
ESCALATION_BURSTY_ZERO_FRAC,
|
||||
@@ -26,12 +28,29 @@ from decnet.profiler.behave_shell._thresholds import (
|
||||
ESCALATION_SUSTAINED_CV,
|
||||
ESCALATION_WINDOW_MIN_S,
|
||||
ESCALATION_WINDOW_TARGET,
|
||||
LANDING_RITUAL_FIRST_N,
|
||||
LANDING_RITUAL_HIT_MIN,
|
||||
LANDING_RITUAL_MIN_COMMANDS,
|
||||
SESSION_DURATION_LONG_MAX,
|
||||
SESSION_DURATION_MEDIUM_MAX,
|
||||
SESSION_DURATION_SHORT_MAX,
|
||||
)
|
||||
|
||||
|
||||
# Precomputed at import time so the per-session check is a set lookup,
|
||||
# not 7 sha256 ops per session. The recon-survey vocabulary an attacker
|
||||
# (or scripted runner) typically opens with on a freshly-landed shell.
|
||||
_LANDING_RITUAL_HASHES: frozenset[str] = frozenset({
|
||||
hash_token("uname"),
|
||||
hash_token("id"),
|
||||
hash_token("whoami"),
|
||||
hash_token("pwd"),
|
||||
hash_token("hostname"),
|
||||
hash_token("w"),
|
||||
hash_token("who"),
|
||||
})
|
||||
|
||||
|
||||
def session_duration(ctx: SessionContext) -> Iterator[Observation]:
|
||||
"""Emit ``temporal.session_duration`` ∈ {short, medium, long, marathon}.
|
||||
|
||||
@@ -113,3 +132,37 @@ def escalation_pattern(ctx: SessionContext) -> Iterator[Observation]:
|
||||
value=value,
|
||||
confidence=confidence,
|
||||
)
|
||||
|
||||
|
||||
def landing_ritual(ctx: SessionContext) -> Iterator[Observation]:
|
||||
"""Emit ``temporal.lifecycle_markers.landing_ritual`` ∈ {present, absent}.
|
||||
|
||||
Inspect the first ``LANDING_RITUAL_FIRST_N`` commands; if at least
|
||||
``LANDING_RITUAL_HIT_MIN`` of their first_token_hashes match the
|
||||
recon-survey vocabulary set (``uname`` / ``id`` / ``whoami`` /
|
||||
``pwd`` / ``hostname`` / ``w`` / ``who``), the operator opened
|
||||
with a landing ritual.
|
||||
|
||||
Skip emission when there are no commands at all — the registry's
|
||||
binary doesn't admit ``unknown`` and emitting ``absent`` from
|
||||
nothing would be dishonest. Below ``LANDING_RITUAL_MIN_COMMANDS``
|
||||
we still emit, but at lower confidence — short sessions can still
|
||||
show or fail to show a ritual.
|
||||
"""
|
||||
n = len(ctx.commands)
|
||||
if n == 0:
|
||||
return
|
||||
head = ctx.commands[:LANDING_RITUAL_FIRST_N]
|
||||
hits = sum(1 for c in head if c.first_token_hash in _LANDING_RITUAL_HASHES)
|
||||
value = "present" if hits >= LANDING_RITUAL_HIT_MIN else "absent"
|
||||
|
||||
if n < LANDING_RITUAL_MIN_COMMANDS:
|
||||
confidence = 0.40
|
||||
else:
|
||||
confidence = 0.65
|
||||
yield make_observation(
|
||||
ctx,
|
||||
primitive="temporal.lifecycle_markers.landing_ritual",
|
||||
value=value,
|
||||
confidence=confidence,
|
||||
)
|
||||
|
||||
@@ -210,6 +210,14 @@ ESCALATION_SUSTAINED_CV: float = 0.50
|
||||
ESCALATION_MIN_WINDOWS: int = 5
|
||||
ESCALATION_MIN_COMMANDS: int = 5
|
||||
|
||||
# ── temporal.lifecycle_markers.landing_ritual (Step E.3) ──────────────────
|
||||
# How many of the first ``LANDING_RITUAL_FIRST_N`` commands must hit
|
||||
# the recon-token set (uname / id / whoami / pwd / hostname / w / who)
|
||||
# for the session to count as having a landing ritual.
|
||||
LANDING_RITUAL_FIRST_N: int = 5
|
||||
LANDING_RITUAL_HIT_MIN: int = 2
|
||||
LANDING_RITUAL_MIN_COMMANDS: int = 3
|
||||
|
||||
# ── 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
|
||||
|
||||
Reference in New Issue
Block a user