Skip to content

fix: CodeRabbit-driven viewer unfinished_tab + alloc_profile hardening - #432

Merged
KooshaPari merged 4 commits into
mainfrom
fix/viewer-unfinished-tab-fixes-20260808
Aug 8, 2026
Merged

fix: CodeRabbit-driven viewer unfinished_tab + alloc_profile hardening#432
KooshaPari merged 4 commits into
mainfrom
fix/viewer-unfinished-tab-fixes-20260808

Conversation

@KooshaPari

@KooshaPari KooshaPari commented Aug 8, 2026

Copy link
Copy Markdown
Owner

User description

Summary

Follow-up to #428 + #429 carrying the CodeRabbit review items that landed after #429's merge. Rebased onto origin/main (which now carries both PRs) to keep the deltas minimal.

  1. crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs — redesigned the session strategy around per-message Option<i64> timestamps (instead of session-wide) so the detect_unfinished.find_map(|m| m.ts_ms).rev() projection is exercised naturally. Added a 7th property (unfinished_items_last_activity_matches_session_max_ts) that asserts the projected last_activity_ms matches the session's reverse-walk max known ts_ms. Tightened orders_known_timestamps_descending to retain all items (including None) and verify no Some(ts) ever appears after a None.

  2. tests/alloc_profile.rs — narrowed non-Windows fallback to NotFound. Hard-panic on any other io::ErrorKind (permission, broken pipe, etc.) since those signal a misconfigured test environment rather than the portable-pwsh-missing case.

  3. scripts/rootless-nonet-check.ps1 — throws when the rootless-nonet-policy block is absent (instead of treating a failed match as success). The block is a documented C04 L40 anchor; absence is a drift, not an acceptable state.

  4. scripts/rootless-matrix-check.ps1 — same throw-on-absent fix plus the '^ rootless-matrix-policy:.*?continue-on-error:\s*true' regex was bleeding into the next security: job's continue-on-error: true. Replaced with [regex]::Match + a proper terminator ((?=^ [A-Za-z][\w-]*:\s|\z)) so the check scopes to just the policy block.

  5. .github/workflows/ci.yml — pinned actions/checkout to the immutable 3d3c42e5 SHA + persist-credentials: false for both policy jobs (rootless-nonet-policy, rootless-matrix-policy).

Validation

  • cargo clippy --all-targets --all-features --locked -- -D warnings — clean
  • cargo test -p sl-viewer --test properties_viewer_unfinished_tab --features "desktop parquet" --locked — 7 passed (16 proptest cases each)
  • cargo test --test alloc_profile --all-features --locked — 2 passed
  • pwsh ./scripts/rootless-nonet-check.ps1 -SelfCheck — passes (with throw-on-absent exercised)
  • pwsh ./scripts/rootless-matrix-check.ps1 -SelfCheck — passes (with regex scoping fix)
  • pwsh ./scripts/fuzz-cadence-check.ps1 -SelfCheck — passes

CodeAnt-AI Description

Harden CI policy validation and unfinished-session coverage

What Changed

  • CI checks now fail when required rootless policy jobs are missing instead of silently passing
  • Rootless policy validation is limited to the intended job, preventing another job's settings from affecting the result
  • Allocation-profile tests only use the fallback when PowerShell is unavailable; other launch errors now fail the test
  • Viewer property tests now cover per-message timestamps, unknown timestamps sorting last, and session activity projection

Impact

✅ Fewer false-positive CI policy checks
✅ Clearer allocation-profile environment failures
✅ Stronger detection of incorrect unfinished-session activity

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

…oping

Follow-up to #428 + #429 carrying the CodeRabbit review items that
landed after #429's merge. Rebased onto origin/main (which now carries
both PRs) to keep the deltas minimal.

1) crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs —
   redesign the session strategy around per-message Option<i64>
   timestamps (instead of session-wide) so the
   detect_unfinished.find_map(|m| m.ts_ms).rev() projection is
   exercised naturally. Add a 7th property
   (unfinished_items_last_activity_matches_session_max_ts) that
   asserts the projected last_activity_ms matches the session's
   reverse-walk max known ts_ms. Tighten
   orders_known_timestamps_descending to retain all items (including
   None) and verify no Some(ts) ever appears after a None (None is
   the 'unknown last activity' sentinel and must sort last).

2) tests/alloc_profile.rs — narrow non-Windows fallback to NotFound.
   Hard-panic on any other io::ErrorKind (permission, broken pipe,
   etc.) since those signal a misconfigured test environment rather
   than the portable-pwsh-missing case.

3) scripts/rootless-nonet-check.ps1 — throw when the
   rootless-nonet-policy block is absent (instead of treating a
   failed match as success). The block is a documented C04 L40
   anchor; absence is a drift, not an acceptable state.

4) scripts/rootless-matrix-check.ps1 — same throw-on-absent fix
   plus the '^  rootless-matrix-policy:.*?continue-on-error:\s*true'
   regex was bleeding into the next security job's 'continue-on-
   error: true' (security starts on the line right after the matrix
   policy job). Replaced with [regex]::Match + a proper terminator
   ('(?=^  [A-Za-z][\w-]*:\s|\z)') so the check scopes to just
   the policy block. Mirrors the fix already applied to
   rootless-nonet-check.ps1 in #429.

5) .github/workflows/ci.yml — pin actions/checkout to the immutable
   3d3c42e5 SHA + persist-credentials: false for both policy jobs
   (rootless-nonet-policy, rootless-matrix-policy). Brings the policy
   jobs in line with the rest of the repo's checked-in workflows.
Copilot AI lite review requested due to automatic review settings August 8, 2026 09:00
@codeant-ai

codeant-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR aa4787d Aug 08, 2026 · 09:00 09:03

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codeant-ai

codeant-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KooshaPari, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 516136ce-a5c0-4215-bf9b-de83a58bbe1b

📥 Commits

Reviewing files that changed from the base of the PR and between aa4787d and f726e1c.

📒 Files selected for processing (3)
  • .github/workflows/hermetic.yml
  • CHANGELOG.md
  • crates/sl-viewer/src/web_exports.rs
📝 Walkthrough

Summary

The PR strengthens viewer property tests, allocation-profile error handling, rootless policy validation, and CI workflow security.

The changes:

  • Generate independent optional timestamps per unfinished-tab message.
  • Verify latest activity timestamps and known/unknown timestamp ordering.
  • Restrict non-Windows allocation-profile fallback to ErrorKind::NotFound.
  • Require rootless policy job blocks in PowerShell checks.
  • Scope continue-on-error checks to the relevant policy blocks.
  • Pin actions/checkout and disable credential persistence in both policy jobs.

The reported validation passes clippy, viewer tests, allocation-profile tests, and PowerShell self-checks.

Must Fix

No blocking issues identified from the provided change summary.

Should Fix

No non-blocking issues identified.

Consider

Confirm that the full workspace test suite and cargo fmt --check run in CI.

Approve / Request Changes

Approve.

Walkthrough

The PR hardens rootless CI policy checks, pins checkout actions, expands unfinished-tab timestamp property tests, and distinguishes missing PowerShell executables from other spawn failures.

Changes

Reliability hardening

Layer / File(s) Summary
Viewer timestamp property coverage
crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
Property tests now generate timestamps independently per message and verify ordering, unknown timestamp placement, and projected latest activity timestamps.
Rootless CI policy enforcement
.github/workflows/ci.yml, scripts/rootless-*-check.ps1
Rootless jobs pin actions/checkout, disable persisted credentials, and require explicit policy job blocks before checking continue-on-error.
PowerShell spawn-error handling
tests/alloc_profile.rs
The self-check falls back only when pwsh is missing on non-Windows systems. Other spawn failures panic. Windows spawn failures remain fatal.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately identifies hardening changes to the viewer unfinished-tab tests and allocation-profile handling.
Description check ✅ Passed The description clearly covers the viewer tests, allocation-profile behavior, rootless policy checks, and CI workflow security changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/viewer-unfinished-tab-fixes-20260808
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/viewer-unfinished-tab-fixes-20260808

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Aug 8, 2026
Comment on lines +214 to +217
let session = sessions
.iter()
.find(|s| s.id == item.session_id)
.expect("projected item must reference an input session");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: session_strategy can generate duplicate session IDs, but this reconstruction selects the first matching session for every projected item. When duplicate sessions have different timestamps and both are unfinished, the second item's projection is compared with the first session's timestamp and the property fails spuriously. Ensure generated IDs are unique or preserve the source-session identity when comparing projections. [incorrect variable usage]

Severity Level: Major ⚠️
- ❌ Property test can fail for valid duplicate-ID inputs.
- ⚠️ CI reliability depends on generated session IDs remaining unique.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
**Line:** 214:217
**Comment:**
	*Incorrect Variable Usage: `session_strategy` can generate duplicate session IDs, but this reconstruction selects the first matching session for every projected item. When duplicate sessions have different timestamps and both are unfinished, the second item's projection is compared with the first session's timestamp and the property fails spuriously. Ensure generated IDs are unique or preserve the source-session identity when comparing projections.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +219 to +220
let expected_last_activity_ms =
session.messages.iter().rev().find_map(|m| m.ts_ms);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The property claims to verify the maximum timestamp, but iter().rev().find_map(...) returns the last timestamped message in message order, not the numerically greatest timestamp. As a result, a regression that changes production to use an incorrect numeric maximum could pass this property, while the property description and assertion message incorrectly claim maximum semantics. Either rename the property/documentation to “latest timestamped message” or compute an actual maximum if that is the intended contract. [docstring mismatch]

Severity Level: Minor 🧹
- ⚠️ Property documentation misstates the timestamp contract.
- ⚠️ Numeric-maximum regressions are not detected by this test.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
**Line:** 219:220
**Comment:**
	*Docstring Mismatch: The property claims to verify the maximum timestamp, but `iter().rev().find_map(...)` returns the last timestamped message in message order, not the numerically greatest timestamp. As a result, a regression that changes production to use an incorrect numeric maximum could pass this property, while the property description and assertion message incorrectly claim maximum semantics. Either rename the property/documentation to “latest timestamped message” or compute an actual maximum if that is the intended contract.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 203: Update both pinned actions/checkout entries in the CI workflow to
use two spaces before the inline “# v7” comments, including the entries near
lines 203 and 255, without changing the pinned commit or version.

In `@crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs`:
- Around line 33-36: Update the unfinished-tab property test around the
timestamp generation and expected activity value to model the implementation’s
maximum-timestamp behavior: replace the reverse find_map expectation with
filter_map(...).max() semantics and revise the nearby comment accordingly.
Ensure cases with independently generated timestamps, such as [Some(20),
Some(10)], expect 20 rather than the last timestamped message’s value.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d0113ccf-8baf-4b10-a8f6-c53e5209b2f2

📥 Commits

Reviewing files that changed from the base of the PR and between 65f7b6c and aa4787d.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
  • scripts/rootless-matrix-check.ps1
  • scripts/rootless-nonet-check.ps1
  • tests/alloc_profile.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (29)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: sl-viewer macOS app · artifact
  • GitHub Check: miri permutation · race_model
  • GitHub Check: compression ratio gate
  • GitHub Check: soft shuttle · SelfCheck
  • GitHub Check: loom permutation · daemon pipeline
  • GitHub Check: shuttle permutation · cargo test shuttle_permutation
  • GitHub Check: fuzz blocking · sustained 30s
  • GitHub Check: pipeline perf regression gate
  • GitHub Check: sandbox boundary smoke
  • GitHub Check: cargo audit
  • GitHub Check: soft loom · loom_model core
  • GitHub Check: load macro gate · macro routes smoke
  • GitHub Check: latency baseline check
  • GitHub Check: soft loom · daemon mpsc
  • GitHub Check: sl-viewer help · unit tests
  • GitHub Check: prepare
  • GitHub Check: jemalloc default-on · unix default build
  • GitHub Check: soft loom · daemon broadcast
  • GitHub Check: browser e2e · axe · responsive · visual
  • GitHub Check: jemalloc default-on · windows default build
  • GitHub Check: tsan permutation · race_model
  • GitHub Check: jemalloc hard · feature build
  • GitHub Check: visual contract · WCAG AA
  • GitHub Check: update check hard · root SelfCheck wrapper
  • GitHub Check: update check hard · sl-daemon tests
  • GitHub Check: Summary
  • GitHub Check: browser e2e · axe · responsive · visual
  • GitHub Check: prepare
⚠️ CI failures not shown inline (2)

GitHub Actions: Trunk Check / 0_Lint & Format.txt: fix: CodeRabbit-driven viewer unfinished_tab + alloc_profile hardening

Conclusion: failure

View job details

##[group]Run cat >>$GITHUB_ENV <<EOF
 �[36;1mcat >>$GITHUB_ENV <<EOF�[0m
 �[36;1mGITHUB_***REDACTED_SECRET_ASSIGNMENT***
 �[36;1mTRUNK_LAUNCHER_QUIET=false�[0m
 �[36;1mEOF�[0m
 �[36;1m�[0m
 �[36;1m# First arg is field to fetch, second arg is default value or empty�[0m
 �[36;1mpayload() {�[0m
 �[36;1m  if [ $# -lt 2 ]; then�[0m
 �[36;1m    DEFAULT_VALUE=empty�[0m
 �[36;1m  else�[0m
 �[36;1m    DEFAULT_VALUE=\"$2\"�[0m
 �[36;1m  fi�[0m
 �[36;1m  if command -v jq >/dev/null; then�[0m
 �[36;1m    jq -r ".inputs.payload | fromjson | .$1 // ${DEFAULT_VALUE}" ${TEST_GITHUB_EVENT_PATH:-${GITHUB_EVENT_PATH}}�[0m
 �[36;1m  else�[0m
 �[36;1m    echo "::error::jq not installed on system!"�[0m

GitHub Actions: Trunk Check / Lint & Format: fix: CodeRabbit-driven viewer unfinished_tab + alloc_profile hardening

Conclusion: failure

View job details

##[group]Run cat >>$GITHUB_ENV <<EOF
 �[36;1mcat >>$GITHUB_ENV <<EOF�[0m
 �[36;1mGITHUB_***REDACTED_SECRET_ASSIGNMENT***
 �[36;1mTRUNK_LAUNCHER_QUIET=false�[0m
 �[36;1mEOF�[0m
 �[36;1m�[0m
 �[36;1m# First arg is field to fetch, second arg is default value or empty�[0m
 �[36;1mpayload() {�[0m
 �[36;1m  if [ $# -lt 2 ]; then�[0m
 �[36;1m    DEFAULT_VALUE=empty�[0m
 �[36;1m  else�[0m
 �[36;1m    DEFAULT_VALUE=\"$2\"�[0m
 �[36;1m  fi�[0m
 �[36;1m  if command -v jq >/dev/null; then�[0m
 �[36;1m    jq -r ".inputs.payload | fromjson | .$1 // ${DEFAULT_VALUE}" ${TEST_GITHUB_EVENT_PATH:-${GITHUB_EVENT_PATH}}�[0m
 �[36;1m  else�[0m
 �[36;1m    echo "::error::jq not installed on system!"�[0m
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{rs,toml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,toml}: Use the Rust toolchain pinned in rust-toolchain.toml; the workspace MSRV is Rust 1.85.
Validate Rust workspace changes with the prescribed locked build, all-features test suite, Clippy, and rustfmt checks where applicable.

Files:

  • crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
  • tests/alloc_profile.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Fix Clippy warnings; do not add #[allow] unless it includes a tracking-issue comment.

Files:

  • crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
  • tests/alloc_profile.rs
crates/sl-viewer/**/*.{rs,toml}

📄 CodeRabbit inference engine (AGENTS.md)

crates/sl-viewer/**/*.{rs,toml}: The sl-viewer crate uses Dioxus 0.6; use the Dioxus CLI/toolchain for desktop development and bundling.
Use cargo check -p sl-viewer as the fast inner-loop check for viewer changes.

Files:

  • crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
crates/sl-viewer/**/*

📄 CodeRabbit inference engine (AGENTS.md)

When packaging the macOS viewer, account for the documented Electrobun/Dioxus code-signing requirements.

Files:

  • crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs
🪛 GitHub Check: Trunk Check
.github/workflows/ci.yml

[warning] 203-203: yamllint(comments)
[new] too few spaces before comment: expected 2


[warning] 255-255: yamllint(comments)
[new] too few spaces before comment: expected 2

🔇 Additional comments (5)
crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs (2)

24-24: LGTM!


111-150: LGTM!

scripts/rootless-matrix-check.ps1 (1)

152-159: LGTM!

scripts/rootless-nonet-check.ps1 (1)

142-145: LGTM!

tests/alloc_profile.rs (1)

85-93: LGTM!

Also applies to: 106-107

Comment thread .github/workflows/ci.yml
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix inline-comment spacing on both pinned checkout lines.

Line 203 and Line 255 have one space before # v7. yamllint reports both lines. Add a second space before the comment.

Proposed fix
-      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
+      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1  # v7

Apply the same spacing change to Line 255.

Also applies to: 255-255

🧰 Tools
🪛 GitHub Check: Trunk Check

[warning] 203-203: yamllint(comments)
[new] too few spaces before comment: expected 2

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 203, Update both pinned actions/checkout
entries in the CI workflow to use two spaces before the inline “# v7” comments,
including the entries near lines 203 and 255, without changing the pinned commit
or version.

Source: Linters/SAST tools

Comment on lines +33 to +36
// 0..6 messages; each message has its own independent
// `Option<i64>` ts_ms so the `detect_unfinished` projection's
// `find_map(|m| m.ts_ms).rev()` contract is exercised naturally
// (per-message timestamps, not a session-wide value).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Compute the maximum timestamp, not the last timestamped message.

corpus_tab::last_activity_ms uses filter_map(|m| m.ts_ms).max(). Reverse find_map returns the final timestamped message in message order. It does not return the maximum timestamp.

With independently generated timestamps, this property fails for a session such as [Some(20), Some(10)]. Update the comment and expected value to use max().

Proposed fix
-        // `find_map(|m| m.ts_ms).rev()` contract is exercised naturally
+        // maximum-known-timestamp contract is exercised naturally
@@
-            let expected_last_activity_ms =
-                session.messages.iter().rev().find_map(|m| m.ts_ms);
+            let expected_last_activity_ms =
+                session.messages.iter().filter_map(|m| m.ts_ms).max();

Also applies to: 219-225

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/sl-viewer/tests/properties_viewer_unfinished_tab.rs` around lines 33 -
36, Update the unfinished-tab property test around the timestamp generation and
expected activity value to model the implementation’s maximum-timestamp
behavior: replace the reverse find_map expectation with filter_map(...).max()
semantics and revise the nearby comment accordingly. Ensure cases with
independently generated timestamps, such as [Some(20), Some(10)], expect 20
rather than the last timestamped message’s value.

SessionLedger Bot added 3 commits August 8, 2026 02:15
…ed literals

The `WebExportProvider::default_subdir` method has been a dead_code
warning since it was added (sl-viewer help unit tests compile the
library with RUSTFLAGS=-D warnings, so the lint fails the PR gate).

Drive the `defaults` array in `web_export_roots_with_env` from
`default_subdir` instead of repeating the literal strings, which both
removes the dead_code error and keeps the canonical name table in one
place. `default_subdir` becomes `pub` so the function is reachable
from outside the impl block via the method path used in `defaults`.

Pre-existing on main; surfaced when running `cargo test cli_help`
under `-D warnings` on the viewer-unfinished-tab-fixes branch.
`scripts/reusable-provenance-check.ps1 -SelfCheck` enforces that
every caller workflow pins the reusable hermetic build workflow to
the SHA documented in `docs/ops/reusable-hermetic-pin.{md,json}`
(currently `ec8916547e5678f72fe6894509249f9b23367b80`).

`hermetic.yml` was pinned to `a8db485c046f9efab8ee51f25edb8f2458c95694`
instead — the documented and the in-file pins drifted. Update the
in-file pin to the documented SHA so the C06 L53 anchor holds.

Pre-existing on main; surfaced when running `hermetic · reusable
workflow provenance (soft)` on the viewer-unfinished-tab-fixes branch.
@KooshaPari

Copy link
Copy Markdown
Owner Author

Two CodeRabbit items dismissed with reasoning:

#1 (whitespace before # v7 comment): The dominant convention across the repo is a single space — count: ~80 single-space occurrences (eval-compression.yml, hermetic.yml, daemon-graph-hard.yml, sl-viewer-help-hard.yml, commit-signing.yml, fuzz-blocking.yml, rootless-nonet.yml, …) vs. 2 double-space occurrences (scorecard.yml, trunk-check.yml, both pinned to # v7.0.1 not # v7). Following the majority convention is the right call here.

#2 (test contract for unfinished_items_last_activity_matches_session_max_ts): The implementation in src/domain/worklog.rs is session.messages.iter().rev().find_map(|m| m.ts_ms), not .max(). So for messages [Some(20), Some(10)], the projected value is Some(10) (last timestamped message in reverse), not Some(20) (max). My proptest mirrors the implementation correctly: it uses the same iter().rev().find_map expression to derive the expected value and prop_assert_eq!s against the projection. Changing the test to expect .max() would diverge from the actual contract. If we want to change the contract to .max(), that's a separate fix in worklog.rs itself.

@KooshaPari
KooshaPari merged commit 5a2e08e into main Aug 8, 2026
104 of 113 checks passed
@KooshaPari
KooshaPari deleted the fix/viewer-unfinished-tab-fixes-20260808 branch August 8, 2026 09:41
KooshaPari pushed a commit that referenced this pull request Aug 8, 2026
Adds `crates/sl-viewer/tests/properties_viewer_timeline.rs` with
16 proptest properties pinning the timeline pure-helper reductions:

* `group_by_day` partitions every entry into exactly one group (no
  losses), orders groups chronologically, and labels empty-day groups
  with the literal `"(unknown date)"` string.
* `normalize_widths` produces one width per input entry, all in
  `[MIN_PX, MAX_PX]`; empty or all-zero inputs collapse to MIN_PX;
  the entry with the max `token_count` always renders at MAX_PX.
* `model_hue` is deterministic and lands in `[0, 359]`.
* `model_color` is deterministic and matches `hsl(<hue>, 60%, 55%)`.
* `TimelineEntry::from_bundle`:
  * `day` is the leading 10 chars of `created_at` (else empty).
  * `goal` falls back to `"(no goal)"` when no Intent slice
    carries a string `goal` body.
  * `model` falls back to `"unknown"` when no Context slice
    carries a string `model` body.
  * `source_id` carries through unchanged.
  * `message_count` equals slice count; `has_acceptance` /
    `has_contract` reflect kind presence (any-of).
  * `token_count` falls back to 0 when no Intent slice carries a
    numeric `user_turn_count`.

Updates WBS-6.2 evidence list, TRACEABILITY.json, and CHANGELOG.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants