Skip to content

Name every session by a typed session kind that owns its log token, stage and --session rule - #875

Merged
JacobStephens2 merged 2 commits into
mainfrom
issue-873
Oct 20, 2026
Merged

JacobStephens2 merged 2 commits into
mainfrom
issue-873

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

One module now owns every session kind. It writes and reads the Session-log token, gives the Command record stage and applies the --session rule. Callers pass a typed kind. Below the session runner the token stays a plain label.

 src/session/
+├── kind.rs          # Kind, Logged { kind, resume }: token, read, stage, selects
 ├── recording.rs
 src/session.rs       # Sessions::run(kind: Kind, …) — was kind: &str
 src/logs.rs          # session(): if/else ladder ending `else { return; }`  →  session.stage()
 src/logs/reading/selection.rs   # --session matching  →  kind::selects
-sessions.run_to_final_message(purpose, &format!("security-reproduction-{number}"), &prompt)
+sessions.run_to_final_message(purpose, Kind::SecurityReproduction(number), &prompt)
-Ok((format!("repair-{}", self.repairs), line))
+Ok((Kind::Repair(self.repairs), line))

The stage comes from one exhaustive match. A Resume of the implement session, Spec review, a Repair or Security review enters Resume. Any other Resume keeps its own kind's stage, as on main.

Seams under test:

  • the session::kind interface: round-trip, stage table, --session rules, malformed tokens
  • the session runner's typed interface: existing session.rs / execution_tests.rs tests
  • the Repair loop's and Delivery's recorded calls, now typed kinds

Evidence

  • Before: a token with no matching rung fell through else { return; } and recorded no stage, and nothing at compile time caught it.
    After: cargo test --bin thirdshift session::kind passes 6 tests:

    • every_kind_reads_back_from_its_token_and_its_resumes
    • each_session_enters_its_command_record_stage
    • a_session_word_selects_its_token_its_kind_or_any_repair
    • repair_selects_the_numbers_it_has_always_read_and_no_others
    • an_unreadable_token_is_selected_by_itself_or_without_its_resume
    • malformed_tokens_read_back_as_no_kind
  • No integration test under tests/ changed: Session log names, show/logs --session and Command record stages. Full cargo test: 52 binaries, 2052 passed, 0 failed. cargo clippy --all-targets is clean.

  • Review follow-up: the Spec reviewer's probes failed on the first commit, as the finding said:

    • selects("legacy", "legacy-resume")
    • selects("repair", "repair-+1")
    • !selects("repair-1", "repair-01")

    The fix restores main's --session rules for every token, and the probes are now kept as tests.

Merge Danger

Door: two-way

A refactor with no on-disk change: log file names, Model evidence and Command record stage names are unchanged.

Blast Radius: internal

Only in-crate callers of Sessions::run / run_to_final_message change.

Unaddressed findings

Standards

  • Two-way module dependency (src/session/kind.rs uses crate::logs::Stage; src/logs.rs and src/logs/reading/selection.rs use crate::session). Declined because the plan decided it. Issue Name every session by a typed session kind that owns its log token, stage and --session rule #873 Decision: "The module lives with sessions, and the logs module reads it … the logs module gains a dependency on it for the stage and --session rules."
  • Middle Man: logs::session (src/logs.rs, pub fn session(session: Logged, path: &Path) { record().stage(session.stage(), Some(path)); }). Declined. It still hides the process-wide record(), so session never touches the Command record directly. Issue Name every session by a typed session kind that owns its log token, stage and --session rule #873 keeps the stage recorded through the logs module.
  • Speculative Generality: pub fields plus Logged::of / Logged::resume_of (src/session/kind.rs). Declined because both are used:
    • The constructors name intent at the runner's call sites (Logged::resume_of(kind) in src/session.rs).
    • selects destructures the fields (Logged { kind: Kind::Repair(_), .. }).
  • Fully qualified crate::session::Kind in src/spec_run.rs tests. Declined. Kind there is already crate::child_run::Kind (src/spec_run.rs:19, use crate::child_run::{Ended, Kind, Runs};). The same finding is fixed in src/logs.rs, which now imports Logged.

Spec

None. Both findings were fixed (see Evidence).

Security review outcome

No unaddressed introduced findings.

Review coverage

Both reviewers read every changed file. No generated-output exclusions.

Closes #873

🤖 Generated with Claude Code

Built with claude · claude-opus-5-5 · medium

JacobStephens2 and others added 2 commits October 20, 2026 05:46
…tage and --session rule

One module, src/session/kind.rs, now defines every kind of session thirdshift
runs, writes and reads its Session-log token, gives the Command record stage
it enters through an exhaustive match, and says which --session words select
it. Callers pass the typed kind to the session runner; below it the token
stays a plain label, so log names and Model evidence are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…en in one place

Review follow-up: a token no kind reads is still selected without its
-resume, and the repair word selects the numbers it always read. The
unnumbered kinds' tokens are written once, and labels below the seam are
named as labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit 057afde into main Oct 20, 2026
18 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-873 branch October 20, 2026 10:58
@JacobStephens2 JacobStephens2 mentioned this pull request Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Name every session by a typed session kind that owns its log token, stage and --session rule

1 participant