Skip to content

[Web] Fix report session truncation#304

Merged
bitflicker64 merged 3 commits into
bitflicker64:mainfrom
floze-the-genius:bugfix/issue-300-web-session-limit
Jul 20, 2026
Merged

[Web] Fix report session truncation#304
bitflicker64 merged 3 commits into
bitflicker64:mainfrom
floze-the-genius:bugfix/issue-300-web-session-limit

Conversation

@floze-the-genius

@floze-the-genius floze-the-genius commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Unifies session limit logic for web reports under named constants, adds transparent truncation metadata, and displays a visible notice when reports are truncated.

Changes

Core

  • Extracted WEB_REPORT_SESSION_LIMIT = 500 and AI_HIGHLIGHT_LIMIT = 15 constants in termstory/web.py to replace inline magic numbers
  • Removed redundant if/else branch in session query that both applied LIMIT 500, replaced with single parameterized query using WEB_REPORT_SESSION_LIMIT
  • Parameterized AI highlights query to use AI_HIGHLIGHT_LIMIT instead of inline LIMIT 15
  • Added session_window metadata to returned dict with limit, returned, total, and truncated fields

UI

  • Added CSS for .session-window-notice with .visible modifier class
  • Added HTML notice element with role="status" and aria-live="polite" attributes
  • Added JavaScript to display "Showing X of Y sessions." notice when sessionWindow.truncated is true

Tests

  • Added session_window assertion to test_get_web_data_empty_db
  • Added test_get_web_data_does_not_truncate_unfiltered_sessions_at_30 to verify 31 sessions return without truncation
  • Updated test_generate_and_open_report to verify notice HTML and JavaScript wiring
  • Updated test_swarm_audit_fixes to derive overflow fixture from WEB_REPORT_SESSION_LIMIT instead of hardcoding 1000/1005

Architecture / Flow

flowchart LR
    A[get_web_data] --> B[Query Sessions]
    B --> C[Apply WEB_REPORT_SESSION_LIMIT]
    C --> D[Build session_window Metadata]
    D --> E[Return to Frontend]
    E --> F{truncated?}
    F -->|Yes| G[Show Notice]
    F -->|No| H[Hide Notice]
Loading

Fixes

Testing

  • python -m pytest tests/test_web.py -q --timeout=60 — 9 passed
  • uvx ruff check termstory/web.py — passed
  • git diff --check — passed

Notes

  • Rebased onto upstream/main@1996a2f and resolved conflict by retaining upstream's unified 500-session cap through WEB_REPORT_SESSION_LIMIT while preserving the PR's parameterized query, session_window metadata, truncation notice, and regression coverage.

@git-miku git-miku Bot added the needs-triage Awaiting human triage — run /triage to mark as triaged label Jul 18, 2026
@git-miku git-miku Bot added size/S PR changes ~38 lines area/web area/web kind/tests kind/tests labels Jul 18, 2026
@git-miku

git-miku Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Tip

👋 Hey @floze-the-genius — Miku's on it. Here are the most useful commands for this PR:

💬 Command What it does
:miku /review 🔍 Line-by-line review
:miku /review-sc ✏️ Inline suggested changes
:miku /security 🛡️ Security scan
:miku /perf ⚡ Performance notes
:miku /test 🧪 Test suggestions
:miku /summarize 📝 TL;DR

Note

🎓 This repo is part of ECSOC26. Run :miku /ecsoc to add the ECSOC26 label to this PR.

Note

⭐ Star this repo to unlock all commands. Say :miku /help for the full list.

📖 All commands
🤖 AI-powered — 14 commands
Command Description Works on
:miku /ask <question> Answer a question about the codebase Issues & PRs
:miku /review Full code review (auto-fetches diff) PRs only
:miku /review-sc Post inline suggested-change comments PRs only
:miku /security OWASP security review (injection, auth, crypto…) PRs only
:miku /perf Performance & efficiency analysis PRs only
:miku /docs Generate docstrings for changed code PRs only
:miku /test Suggest unit tests for changed code PRs only
:miku /roast Humorous but constructive code roast 🔥 PRs only
:miku /checklist Smart diff-aware PR checklist PRs only
:miku /summarize TL;DR of this issue or PR Issues & PRs
:miku /explain <target> Explain a file, function, or concept Issues & PRs
:miku /changelog Draft a CHANGELOG entry PRs only
:miku /estimate Story-point effort estimate Issues only
:miku /chat <message> General conversation Issues & PRs
🔧 Issue & PR management — 18 commands
Command Description Works on
:miku /assign [@user] Assign to yourself or another user Issues & PRs
:miku /unassign [@user] Remove yourself or another user Issues & PRs
:miku /label <name> Add a label Issues & PRs
:miku /remove-label <name> Remove a label Issues & PRs
:miku /close [reason] Close this issue or PR Issues & PRs
:miku /reopen Reopen a closed issue or PR Issues & PRs
:miku /approve [message] Submit an approving review on a PR PRs only
:miku /retitle <new title> Change the title Issues & PRs
:miku /duplicate #N Mark as duplicate of #N and close Issues & PRs
:miku /milestone [name] Set or list open milestones Issues & PRs
:miku /ship [version] Mark PR as shipped / deployed PRs only
:miku /lock [reason] Lock conversation (resolved / off-topic / spam) Issues & PRs
:miku /unlock Unlock conversation Issues & PRs
:miku /cc @user1 [@user2] Request reviews PRs only
:miku /lgtm [cancel] Signal "Looks Good To Me" Issues & PRs
:miku /hold [cancel] Block merge; :miku /hold cancel releases it Issues & PRs
:miku /wip Toggle WIP (converts PR to draft) Issues & PRs
:miku /merge Merge this PR (CI + approval required) PRs only
🎉 Community & utility — 9 commands
Command Description Works on
:miku /vote Open a 👍 👎 🚀 reaction poll Issues & PRs
:miku /kudos @user [msg] Give public kudos to a contributor Issues & PRs
:miku /stats Repo stars, forks, top contributors Issues & PRs
:miku /remind <dur> <msg> Schedule a reminder (e.g. 2h, 30m, 1d) Issues & PRs
:miku /size Show PR size breakdown PRs only
:miku /ping [@user ...] Ping contributors with an AI message Issues & PRs
:miku /joke Tell a programming joke Issues & PRs
:miku /shrug Add ¯_(ツ)_/¯ label Issues & PRs
:miku /help Show this message Issues & PRs

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR unifies the session-fetch path for filtered and unfiltered web reports under a named WEB_REPORT_SESSION_LIMIT constant (500), eliminates the duplicated branch that was previously redundant, and adds a session_window metadata block to the returned dict along with a small HTML notice rendered when the report is truncated.

  • Constants extracted: WEB_REPORT_SESSION_LIMIT = 500 and AI_HIGHLIGHT_LIMIT = 15 replace inline magic numbers in the session and AI-highlight queries.
  • session_window metadata added: the return value now carries limit, returned, total, and truncated fields, and the HTML template conditionally shows a "Showing X of Y sessions" banner.
  • truncated logic is incorrect under date filters: total is sourced from stats["total_sessions"], which is the unfiltered DB count; when a date range is active and fewer sessions exist in range than the limit, truncated is True and total is wrong — a filtered COUNT query is needed instead.

Confidence Score: 4/5

Safe to merge if the codebase is only used without date filters in practice; the session_window metadata is incorrect whenever a date range is supplied and fewer sessions match the range than the 500-session limit.

The session_window.truncated flag and session_window.total field compare against the unfiltered database total rather than the count of sessions matching the active date filter. In date-filtered views with a small result set the UI will incorrectly report truncation and show a misleading total. The rest of the change is clean and correct.

termstory/web.py lines 248–253: the session_window total and truncated computation needs a filtered COUNT query rather than stats["total_sessions"].

Important Files Changed

Filename Overview
termstory/web.py Introduces WEB_REPORT_SESSION_LIMIT / AI_HIGHLIGHT_LIMIT constants and a session_window metadata block; the truncated flag and total count are incorrect when date filters are active because they compare against the unfiltered DB total rather than the filtered session count.
tests/test_web.py Adds session_window assertions and imports WEB_REPORT_SESSION_LIMIT; all tests exercise the unfiltered path or a filtered path where all sessions fall within the filter range, so the date-filtered truncation bug goes untested.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant get_web_data
    participant analyze_all
    participant DB

    Caller->>get_web_data: get_web_data(db, start_ts, end_ts)
    get_web_data->>analyze_all: analyze_all(db)
    analyze_all->>DB: "COUNT(*) — no date filter"
    DB-->>analyze_all: total_sessions (unfiltered)
    analyze_all-->>get_web_data: "stats{total_sessions}"

    get_web_data->>DB: SELECT id FROM sessions [WHERE …] LIMIT WEB_REPORT_SESSION_LIMIT
    DB-->>get_web_data: session_ids (filtered + limited)

    Note over get_web_data: session_window.total = stats[total_sessions] (unfiltered!)
    Note over get_web_data: truncated = total_sessions > len(sessions_data) ⚠ wrong under date filter

    get_web_data-->>Caller: "{stats, sessions, session_window, …}"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant get_web_data
    participant analyze_all
    participant DB

    Caller->>get_web_data: get_web_data(db, start_ts, end_ts)
    get_web_data->>analyze_all: analyze_all(db)
    analyze_all->>DB: "COUNT(*) — no date filter"
    DB-->>analyze_all: total_sessions (unfiltered)
    analyze_all-->>get_web_data: "stats{total_sessions}"

    get_web_data->>DB: SELECT id FROM sessions [WHERE …] LIMIT WEB_REPORT_SESSION_LIMIT
    DB-->>get_web_data: session_ids (filtered + limited)

    Note over get_web_data: session_window.total = stats[total_sessions] (unfiltered!)
    Note over get_web_data: truncated = total_sessions > len(sessions_data) ⚠ wrong under date filter

    get_web_data-->>Caller: "{stats, sessions, session_window, …}"
Loading

Reviews (4): Last reviewed commit: "fix(web): surface truncated session repo..." | Re-trigger Greptile

Comment thread termstory/web.py
@floze-the-genius

Copy link
Copy Markdown
Contributor Author

Addressed the Greptile P2 in the latest commit: the regression tests now import WEB_REPORT_SESSION_LIMIT, derive the overflow fixture from it, and no longer hardcode 1000/1005. Focused validation remains green: 9 passed; production Ruff and git diff --check also pass.

@bitflicker64

Copy link
Copy Markdown
Owner

Addressed the Greptile P2 in the latest commit: the regression tests now import WEB_REPORT_SESSION_LIMIT, derive the overflow fixture from it, and no longer hardcode 1000/1005. Focused validation remains green: 9 passed; production Ruff and git diff --check also pass.

Makes sense. I’ll triage it by the end of the day. Thanks for the contribution.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd18a5e01b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread termstory/web.py Outdated

logger = logging.getLogger(__name__)

WEB_REPORT_SESSION_LIMIT = 1000

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid exceeding SQLite's bind-variable cap

When an unfiltered database has at least 1000 sessions, this limit now flows into db.get_sessions_by_ids(session_ids), and that path builds WHERE id IN (...) queries over all returned IDs (including _build_sessions' batched command fetch). On SQLite builds that still use the common 999 host-parameter cap, the new unfiltered report path raises sqlite3.OperationalError: too many SQL variables instead of generating the report; chunking the fetches or keeping the window below the cap would avoid that runtime failure.

Useful? React with 👍 / 👎.

@bitflicker64

Copy link
Copy Markdown
Owner

@codex did i trigger you ?

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@bitflicker64 bitflicker64 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approve with minor suggestions — correct fix for silent 30-session unfiltered truncation; good constants + metadata + tests.

Intent

Unfiltered web reports were capped at 30 sessions while filtered used 1000. Unify on a named WEB_REPORT_SESSION_LIMIT (1000), parameterize LIMIT, and expose session_window metadata (issue #300).

Impact

  • Unfiltered path no longer special-cased to 30 — real bugfix.
  • AI_HIGHLIGHT_LIMIT named constant — clarity win.
  • Tests: empty window metadata, 31-session unfiltered no-truncation, and limit+5 truncated path updated to use the constant.

What’s correct

  • Single ORDER BY ... LIMIT ? path for both filtered and unfiltered.
  • truncated uses stats total vs returned length; when a date range is applied, stats are overridden to the filtered counts first — so metadata stays coherent.
  • Parameter binding for LIMIT avoids injection and is SQLite-safe (single bind, not a 1000-id IN list).

Suggestions

  1. Template/UI consumptionsession_window is returned in JSON but (if the HTML template doesn’t read it yet) users still won’t see truncation. Either wire a small banner in the report UI or note a follow-up issue so metadata isn’t dead API.
  2. Optional: also return filtered_total via COUNT(*) with the same WHERE (without LIMIT) so total doesn’t depend on the stats override path — more direct, same result.
  3. Performance note only: loading 1000 full sessions (commands/commits) can be heavy on large DBs; acceptable for the stated product choice, but worth watching.

Verdict

Comment / soft approve — core fix is right and well tested; template surfacing is the main follow-up.

Comment thread termstory/web.py
"returned": len(sessions_data),
"total": total_sessions,
"truncated": total_sessions > len(sessions_data),
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Good metadata shape. Confirm the embedded report template actually reads session_window (banner like “Showing 1000 of 4500 sessions”). If not, either wire it in this PR or open a follow-up so this field isn’t unused JSON.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in df859cc. The embedded report now renders an aria-live status banner when session_window.truncated is true (for example, “Showing 1000 of 4500 sessions”), and tests/test_web.py asserts both the banner wiring and truncated metadata. Focused web suite passes locally.

Comment thread termstory/web.py Outdated

logger = logging.getLogger(__name__)

WEB_REPORT_SESSION_LIMIT = 1000

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Nice named constants. Using LIMIT ? with a single bound int is correct — no SQLite bind-variable explosion here (that concern applies to huge IN (...) lists, not this).

@bitflicker64

Copy link
Copy Markdown
Owner

/triage

@git-miku git-miku Bot removed the needs-triage Awaiting human triage — run /triage to mark as triaged label Jul 18, 2026
@git-miku

git-miku Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

miku /triage

✅ Marked as triaged (triage/triaged applied, needs-triage removed).

@git-miku git-miku Bot added the triage/triaged This PR has been triaged by a maintainer label Jul 18, 2026
@bitflicker64

Copy link
Copy Markdown
Owner

:miku /check-star

@git-miku git-miku Bot added the do-not-merge/needs-star PR author has not starred this repo — run /check-star after starring label Jul 18, 2026
@git-miku

git-miku Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

miku /check-star

@floze-the-genius still hasn't starred this repo. Applied do-not-merge/needs-star.

Star this repo first, then run :miku /check-star again. ⭐

@floze-the-genius

Copy link
Copy Markdown
Contributor Author

:miku /check-star

@git-miku git-miku Bot added needs-triage Awaiting human triage — run /triage to mark as triaged and removed do-not-merge/needs-star PR author has not starred this repo — run /check-star after starring labels Jul 18, 2026
@git-miku

git-miku Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Tip

👋 Hey @floze-the-genius — Miku's on it. Here are the most useful commands for this PR:

💬 Command What it does
:miku /review 🔍 Line-by-line review
:miku /review-sc ✏️ Inline suggested changes
:miku /security 🛡️ Security scan
:miku /perf ⚡ Performance notes
:miku /test 🧪 Test suggestions
:miku /summarize 📝 TL;DR

Note

🎓 This repo is part of ECSOC26. Run :miku /ecsoc to add the ECSOC26 label to this PR.

Note

⭐ Star this repo to unlock all commands. Say :miku /help for the full list.

📖 All commands
🤖 AI-powered — 14 commands
Command Description Works on
:miku /ask <question> Answer a question about the codebase Issues & PRs
:miku /review Full code review (auto-fetches diff) PRs only
:miku /review-sc Post inline suggested-change comments PRs only
:miku /security OWASP security review (injection, auth, crypto…) PRs only
:miku /perf Performance & efficiency analysis PRs only
:miku /docs Generate docstrings for changed code PRs only
:miku /test Suggest unit tests for changed code PRs only
:miku /roast Humorous but constructive code roast 🔥 PRs only
:miku /checklist Smart diff-aware PR checklist PRs only
:miku /summarize TL;DR of this issue or PR Issues & PRs
:miku /explain <target> Explain a file, function, or concept Issues & PRs
:miku /changelog Draft a CHANGELOG entry PRs only
:miku /estimate Story-point effort estimate Issues only
:miku /chat <message> General conversation Issues & PRs
🔧 Issue & PR management — 18 commands
Command Description Works on
:miku /assign [@user] Assign to yourself or another user Issues & PRs
:miku /unassign [@user] Remove yourself or another user Issues & PRs
:miku /label <name> Add a label Issues & PRs
:miku /remove-label <name> Remove a label Issues & PRs
:miku /close [reason] Close this issue or PR Issues & PRs
:miku /reopen Reopen a closed issue or PR Issues & PRs
:miku /approve [message] Submit an approving review on a PR PRs only
:miku /retitle <new title> Change the title Issues & PRs
:miku /duplicate #N Mark as duplicate of #N and close Issues & PRs
:miku /milestone [name] Set or list open milestones Issues & PRs
:miku /ship [version] Mark PR as shipped / deployed PRs only
:miku /lock [reason] Lock conversation (resolved / off-topic / spam) Issues & PRs
:miku /unlock Unlock conversation Issues & PRs
:miku /cc @user1 [@user2] Request reviews PRs only
:miku /lgtm [cancel] Signal "Looks Good To Me" Issues & PRs
:miku /hold [cancel] Block merge; :miku /hold cancel releases it Issues & PRs
:miku /wip Toggle WIP (converts PR to draft) Issues & PRs
:miku /merge Merge this PR (CI + approval required) PRs only
🎉 Community & utility — 9 commands
Command Description Works on
:miku /vote Open a 👍 👎 🚀 reaction poll Issues & PRs
:miku /kudos @user [msg] Give public kudos to a contributor Issues & PRs
:miku /stats Repo stars, forks, top contributors Issues & PRs
:miku /remind <dur> <msg> Schedule a reminder (e.g. 2h, 30m, 1d) Issues & PRs
:miku /size Show PR size breakdown PRs only
:miku /ping [@user ...] Ping contributors with an AI message Issues & PRs
:miku /joke Tell a programming joke Issues & PRs
:miku /shrug Add ¯_(ツ)_/¯ label Issues & PRs
:miku /help Show this message Issues & PRs

@git-miku

git-miku Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

miku /check-star

@floze-the-genius has starred the repo — removed do-not-merge/needs-star and applied needs-triage. This PR is now in the triage queue and area labels have been applied. ✨

@git-miku git-miku Bot added size/M PR changes ~109 lines and removed size/S PR changes ~38 lines labels Jul 18, 2026
@floze-the-genius

Copy link
Copy Markdown
Contributor Author

Implemented the template/UI suggestion in df859cc: truncated reports now show a visible Showing <returned> of <total> sessions. status notice, while complete reports remain unchanged. The values are assigned with textContent, and the generated-report test covers the notice wiring. Validation: web tests 9 passed, production Ruff and git diff --check green. The full local suite reached 505 passed; its one test_cli_error_states foreign-key failure reproduces unchanged on a detached clean upstream/main worktree.

@floze-the-genius
floze-the-genius force-pushed the bugfix/issue-300-web-session-limit branch from df859cc to 90dea0b Compare July 19, 2026 11:41
@floze-the-genius

Copy link
Copy Markdown
Contributor Author

Rebased onto upstream/main@1996a2f and resolved the termstory/web.py conflict by retaining upstream’s unified 500-session cap through WEB_REPORT_SESSION_LIMIT, while preserving the PR’s parameterized query, session_window metadata, truncation notice, and regression coverage. Validation: tests/test_web.py 9 passed; ruff check termstory/web.py and git diff --check passed; full suite 524 passed with only test_cli_error_states failing identically on a detached clean upstream/main@1996a2f worktree.

Comment thread termstory/web.py
Comment on lines +248 to +254
total_sessions = stats["total_sessions"]
session_window = {
"limit": WEB_REPORT_SESSION_LIMIT,
"returned": len(sessions_data),
"total": total_sessions,
"truncated": total_sessions > len(sessions_data),
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 truncated and total are wrong when a date filter is active

stats["total_sessions"] comes from analyze_all(db) on line 23, which counts every session in the database with no date filter. When start_ts/end_ts are supplied and the matching window holds fewer than WEB_REPORT_SESSION_LIMIT sessions, total_sessions will be larger than len(sessions_data) even though no truncation occurred — so truncated is True and total shows the full-DB count instead of the in-range count. Concretely: 600 sessions in DB, 50 match the date filter → UI shows "Showing 50 of 600 sessions" even though all 50 were returned. A separate COUNT(*) query that applies the same WHERE conditions as the session fetch is needed to populate total accurately before computing truncated.

@bitflicker64

Copy link
Copy Markdown
Owner

/review

@bitflicker64

Copy link
Copy Markdown
Owner

/rewrite

@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /review

This looks solid. The unification of the session limit logic is clean—removing the redundant if/else branch that both applied LIMIT 500 and replacing it with a single parameterized query using WEB_REPORT_SESSION_LIMIT is a good simplification . The same pattern applied to the AI highlights query with AI_HIGHLIGHT_LIMIT is consistent .

The session_window metadata addition is a nice UX improvement—giving the frontend visibility into truncation status with the limit, returned count, and total count makes the behavior transparent rather than silent . The CSS and JavaScript wiring for the notice banner are minimal and appropriately scoped .

Test coverage is good—the new regression test for 31 sessions confirms the fix for the original issue, and updating test_swarm_audit_fixes to derive from WEB_REPORT_SESSION_LIMIT instead of hardcoding 1005 prevents future drift .

Ready to merge.

@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /rewrite

✅ PR description rewritten! Check the PR body above.

Preview

Summary

Unifies session limit logic for web reports under named constants, adds transparent truncation metadata, and displays a visible notice when reports are truncated.

Changes

Core

  • Extracted WEB_REPORT_SESSION_LIMIT = 500 and AI_HIGHLIGHT_LIMIT = 15 constants in termstory/web.py to replace inline magic numbers
  • Removed redundant if/else branch in session query that both applied LIMIT 500, replaced with single parameterized query using WEB_REPORT_SESSION_LIMIT
  • Parameterized AI highlights query to use AI_HIGHLIGHT_LIMIT instead of inline LIMIT 15
  • Added session_window metadata to returned dict with limit, returned, total, and truncated fields

UI

  • Added CSS for .session-window-notice with .visible modifier class
  • Added HTML notice element with role="status" and aria-live="polite" attributes
  • Added JavaScript to display "Showing X of Y sessions." notice when sessionWindow.truncated is true

Tests

  • Added session_window assertion to test_get_web_data_empty_db
  • Added test_get_web_data_does_not_truncate_unfiltered_sessions_at_30 to verify 31 sessions return without truncation
  • Updated test_generate_and_open_report to verify notice HTML and JavaScript wiring
  • Updated test_swarm_audit_fixes to derive overflow fixture from WEB_REPORT_SESSION_LIMIT instead of hardcoding 1000/1005

Architecture / Flow

flowchart LR
    A[get_web_data] --> B[Query Sessions]
    B --> C[Apply WEB_REPORT_SESSION_LIMIT]
    C --> D[Build session_window Metadata]
    D --> E[Return to Frontend]
    E --> F{truncated?}
    F -->|Yes| G[Show Notice]
    F -->|No| H[Hide Notice]
Loading

Fixes

Testing

  • python -m pytest tests/test_web.py -q --timeout=60 — 9 passed
  • uvx ruff check termstory/web.py — passed
  • git diff --check — passed

Notes

  • Rebased onto upstream/main@1996a2f and resolved conflict by retaining upstream's unified 500-session cap through WEB_REPORT_SESSION_LIMIT while preserving the PR's parameterized query, session_window metadata, truncation notice, and regression coverage.

@bitflicker64

Copy link
Copy Markdown
Owner

/lgtm /approve

@git-miku git-miku Bot added the lgtm This PR has been approved by a maintainer label Jul 20, 2026

@git-miku git-miku Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved via Miku.

@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /lgtm

✅ LGTM! Label added by @bitflicker64.

Use :miku /lgtm cancel to retract.


miku /approve

✅ Approved! 🎉

@bitflicker64

Copy link
Copy Markdown
Owner

/ecsoc

@git-miku git-miku Bot added the ECSoC26 label Jul 20, 2026
@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /ecsoc

🏷️ Added ECSOC26.

@bitflicker64

Copy link
Copy Markdown
Owner

/applaud @floze-the-genius

@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /applaud

🏆 @floze-the-genius — you absolutely killed it. 🎉

Behind every great PR is someone who cared enough to get the details right — that's you.

Nominated by @bitflicker64 🙌✨

@bitflicker64
bitflicker64 merged commit d4de512 into bitflicker64:main Jul 20, 2026
6 checks passed
@bitflicker64

Copy link
Copy Markdown
Owner

/label good-pr

@git-miku git-miku Bot added the good-pr good-pr label Jul 20, 2026
@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /label

🏷️ Added label good-pr.

@bitflicker64

Copy link
Copy Markdown
Owner

/label good-backend

@git-miku git-miku Bot added the good-backend good-backend label Jul 20, 2026
@git-miku

git-miku Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

miku /label

🏷️ Added label good-backend.

@bitflicker64

Copy link
Copy Markdown
Owner

Please ask the ECSoC admin to check why the bot didn’t apply the ECSoC label. If you don’t have any connections, I’ll look into it myself. Just say the word or mention me here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/web area/web ECSoC26 good-backend good-backend good-pr good-pr kind/tests kind/tests lgtm This PR has been approved by a maintainer needs-triage Awaiting human triage — run /triage to mark as triaged size/M PR changes ~109 lines triage/triaged This PR has been triaged by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Medium] web.py: unfiltered report caps at 30 sessions, filtered at 1000 — silent inconsistent truncation

2 participants