feat: enhance session completeness tracking in s3_analyzer and seismo_lab
This commit is contained in:
@@ -140,6 +140,15 @@ class Session:
|
||||
index: int
|
||||
bw_frames: list[AnnotatedFrame]
|
||||
s3_frames: list[AnnotatedFrame]
|
||||
# None = infer from SUB 0x74 presence; True/False = explicitly set by splitter
|
||||
complete: Optional[bool] = None
|
||||
|
||||
def is_complete(self) -> bool:
|
||||
"""A session is complete if explicitly marked, or if it contains SUB 0x74."""
|
||||
if self.complete is not None:
|
||||
return self.complete
|
||||
return any(af.header is not None and af.header.sub == SESSION_CLOSE_SUB
|
||||
for af in self.bw_frames)
|
||||
|
||||
@property
|
||||
def all_frames(self) -> list[AnnotatedFrame]:
|
||||
@@ -384,6 +393,7 @@ def split_sessions_at_marks(
|
||||
session_offset = 0
|
||||
bw_prev = s3_prev = 0
|
||||
|
||||
n_segments = len(bw_cuts)
|
||||
for seg_i, (bw_end, s3_end) in enumerate(zip(bw_cuts, s3_cuts)):
|
||||
bw_chunk = bw_blob[bw_prev:bw_end]
|
||||
s3_chunk = s3_blob[s3_prev:s3_end]
|
||||
@@ -394,11 +404,20 @@ def split_sessions_at_marks(
|
||||
|
||||
seg_sessions = split_into_sessions(bw_frames, s3_frames)
|
||||
|
||||
# A mark-bounded segment is complete by definition — the user placed the
|
||||
# mark after the read finished. Only the last segment (trailing, unbounded)
|
||||
# may be genuinely in-progress.
|
||||
is_last_segment = (seg_i == n_segments - 1)
|
||||
|
||||
# Re-index sessions so they are globally unique
|
||||
for sess in seg_sessions:
|
||||
sess.index = session_offset
|
||||
for f in sess.all_frames:
|
||||
f.session_idx = session_offset
|
||||
# Explicitly mark completeness: mark-bounded segments are complete;
|
||||
# the trailing segment falls back to 0x74 inference.
|
||||
if not is_last_segment:
|
||||
sess.complete = True
|
||||
session_offset += 1
|
||||
all_sessions.append(sess)
|
||||
|
||||
@@ -683,11 +702,7 @@ def render_session_report(
|
||||
n_bw = len(session.bw_frames)
|
||||
n_s3 = len(session.s3_frames)
|
||||
total = n_bw + n_s3
|
||||
is_complete = any(
|
||||
af.header is not None and af.header.sub == SESSION_CLOSE_SUB
|
||||
for af in session.bw_frames
|
||||
)
|
||||
status = "" if is_complete else " [IN PROGRESS]"
|
||||
status = "" if session.is_complete() else " [IN PROGRESS]"
|
||||
|
||||
lines.append(f"{'='*72}")
|
||||
lines.append(f"SESSION {session.index}{status}")
|
||||
@@ -847,11 +862,7 @@ def render_claude_export(
|
||||
lines += ["## Capture Summary", ""]
|
||||
lines.append(f"Sessions found: {len(sessions)}")
|
||||
for sess in sessions:
|
||||
is_complete = any(
|
||||
af.header is not None and af.header.sub == SESSION_CLOSE_SUB
|
||||
for af in sess.bw_frames
|
||||
)
|
||||
status = "complete" if is_complete else "partial/in-progress"
|
||||
status = "complete" if sess.is_complete() else "partial/in-progress"
|
||||
n_bw, n_s3 = len(sess.bw_frames), len(sess.s3_frames)
|
||||
changed = len(diffs[sess.index] or []) if sess.index < len(diffs) else 0
|
||||
changed_str = f" ({changed} SUBs changed vs prev)" if sess.index > 0 else " (baseline)"
|
||||
@@ -1119,14 +1130,7 @@ def live_loop(
|
||||
|
||||
# Check for session close
|
||||
all_sessions = split_into_sessions(bw_annotated, s3_annotated)
|
||||
# A complete session has the closing 0x74
|
||||
complete_sessions = [
|
||||
s for s in all_sessions
|
||||
if any(
|
||||
af.header is not None and af.header.sub == SESSION_CLOSE_SUB
|
||||
for af in s.bw_frames
|
||||
)
|
||||
]
|
||||
complete_sessions = [s for s in all_sessions if s.is_complete()]
|
||||
|
||||
# Emit reports for newly completed sessions
|
||||
for sess in complete_sessions[len(sessions):]:
|
||||
@@ -1157,13 +1161,7 @@ def live_loop(
|
||||
s3_annotated = annotate_frames(s3_frames_raw, "S3")
|
||||
bw_annotated = annotate_frames(bw_frames_raw, "BW")
|
||||
all_sessions = split_into_sessions(bw_annotated, s3_annotated)
|
||||
incomplete = [
|
||||
s for s in all_sessions
|
||||
if not any(
|
||||
af.header is not None and af.header.sub == SESSION_CLOSE_SUB
|
||||
for af in s.bw_frames
|
||||
)
|
||||
]
|
||||
incomplete = [s for s in all_sessions if not s.is_complete()]
|
||||
for sess in incomplete:
|
||||
report = render_session_report(sess, diffs=None, prev_session_index=None)
|
||||
out_path = write_report(sess, report, outdir)
|
||||
|
||||
Reference in New Issue
Block a user