Skip to content

feat(web): on-page verbose debug log + surface chunk tags - #72

Merged
PhysShell merged 3 commits into
mainfrom
claude/web-debug-log
Jun 18, 2026
Merged

feat(web): on-page verbose debug log + surface chunk tags#72
PhysShell merged 3 commits into
mainfrom
claude/web-debug-log

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Follow-up to #71, from playground feedback that tags looked like they "weren't delivered." Diagnosis: no engine bug — structural tags are a manual curator choice, and only notation-derived technique tags auto-fill (ADR-0018), so an un-ticked track with no techniques yields tags: [] (correct, just opaque). This makes the engine's behaviour visible.

What

Debug-log ring buffer + the repo's first JS test lane

  • web/static/debuglog.js — a pure, DOM-free bounded ring buffer (timestamped lines, JSON-encoded payloads, ✗-prefixed errors), kept separate from app.js precisely so it's unit-testable.
  • web/test/debuglog.test.js under node --test (zero deps), wired into CI via .github/workflows/web-test.yml (runs on PRs/main touching web/).
  • Landed red→green: eb9b5bb adds the failing spec + lane; 5eeec05 implements the module green. Verified in isolated worktrees — red commit node --test exits 1, green exits 0 (7/7).

On-page Debug log panel

  • Collapsible panel (Copy / Clear) tracing every engine call — load, track, detect, capture, split, arrange, and all errors — with the exact inputs and resolved outputs. Copy-paste friendly on a phone; no devtools needed.
  • Tags made visible: capture/split traces print resolved tags/techniques (per phrase), the pager shows a per-phrase tag count, and the legend notes technique tags are auto-added from notation — so an empty tags is self-explanatory.
  • arrange() guards its JSON parse like the other engine calls; .debuglog uses overflow-wrap: anywhere (not the deprecated word-break: break-word).

Scope

Static front-end + test tooling only — no Rust/engine change. The pure buffer is unit-tested; the DOM/wasm-coupled panel wiring stays glue (uncovered by design — there's nothing engine-shaped to pin there).

Validation

  • npm test (in web/) → 7/7 green; node --check on app.js / debuglog.js clean.
  • web/dist is gitignored — CI's web/build.sh rebuilds it from static/ (and ships debuglog.js); deploys to Pages on merge to main. web/test/ and package.json stay out of the shipped bundle.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95

Summary by CodeRabbit

  • New Features
    • Added an on-page Debug log panel with timestamped verbose events plus Copy/Clear controls, capturing detailed capture/upload, splitting, and download/upload progress including “engine ready” entries.
  • UI/UX
    • Updated the Tags legend hint (technique tags auto-added) and enhanced the split info panel with per-phrase tag counts.
  • Bug Fixes
    • Improved validation and visibility for missing inputs, oversized uploads, read/parse failures, engine errors, boundary detection when no track is selected, and safer error reporting during download preparation.
  • Tests
    • Added unit tests for the bounded debug-log ring buffer.
  • Chores
    • Added web front-end npm test setup and a web-only CI workflow running JavaScript tests.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d88f66af-cb36-4fe3-9be6-525249133021

📥 Commits

Reviewing files that changed from the base of the PR and between 5eeec05 and 2d04437.

📒 Files selected for processing (3)
  • .github/workflows/web-test.yml
  • web/static/debuglog.js
  • web/test/debuglog.test.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • web/test/debuglog.test.js
  • web/static/debuglog.js
  • .github/workflows/web-test.yml

📝 Walkthrough

Walkthrough

Adds an on-page verbose debug log panel to the web playground: an HTML details element with Copy/Clear buttons and a pre#debugLog, styled via new CSS rules, backed by a bounded timestamped JS ring-buffer (createDebugLog). All major engine interaction paths (loadFile, detectBoundaries, downloadChunk, splitIntoPhrases, renderPhrase, arrange, bind) are instrumented with structured debug entries, and arrange gains a logIt flag to suppress repetitive slider traces while capturing discrete-action events.

Changes

Debug Log System

Layer / File(s) Summary
Debug ring buffer module and unit tests
web/static/debuglog.js, web/test/debuglog.test.js
Introduces createDebugLog, a DOM-free bounded log buffer with deterministic timestamp injection, safe JSON serialization, and methods to push/err/clear/read lines/text; includes complete node:test suite verifying formatting, truncation, error marking, and circular-data handling.
Test infrastructure setup
web/package.json, .github/workflows/web-test.yml
Adds ES module package.json with npm test script using node:test runner, and GitHub Actions workflow to run tests on PRs and main pushes when web/** changes.
Debug panel HTML, CSS, and legend update
web/static/index.html, web/static/style.css
Adds details#debugPanel with Copy/Clear buttons and pre#debugLog to index.html; updates Tags legend to note auto-added technique tags; defines .debug, .debuglog, and empty-state placeholder CSS rules with scrollable dark-background monospace styling.
Debug module integration and arrange(logIt)
web/static/app.js
Imports createDebugLog, extends els to reference debug panel elements, declares dbg/dbgErr/copyDebug/clearDebug helper functions, and changes arrange() to arrange(logIt) so only discrete actions emit compact generation trace while all errors are always logged.
loadFile debug instrumentation
web/static/app.js
loadFile logs upload metadata, oversize rejection, FileReader failures, parse/engine errors; emits "loaded" summary with track/bar/note counts; calls arrange(true) on success.
detectBoundaries and downloadChunk debug instrumentation
web/static/app.js
detectBoundaries adds early no-track validation with debug/error logging. downloadChunk logs missing inputs, resolved tag/quality selections, JSON parse failures, and emits "captured" summary with boundary count and metrics presence.
splitIntoPhrases and renderPhrase debug instrumentation
web/static/app.js
splitIntoPhrases logs resolved tags/quality, engine errors, and emits "split result" with per-phrase ids/bars/tags from chunk JSON. renderPhrase parses chunk JSON for tags and updates split info to include tag count.
bind and startup instrumentation
web/static/app.js
bind handlers call arrange(true) on mode/track/generate changes, reset split state and log on track change, wire debug copy/clear clicks. Engine init logs "engine ready" and calls arrange(true); load failures record debug/error details.

Sequence Diagram

sequenceDiagram
  participant User
  participant loadFile
  participant arrange
  participant dbg
  participant log
  participant debugLog as pre#debugLog
  User->>loadFile: upload file
  loadFile->>dbg: dbg("file", metadata)
  dbg->>log: push entry with timestamp
  log-->>debugLog: update textContent
  loadFile->>dbg: dbg("loaded", summary)
  dbg->>log: push entry with timestamp
  log-->>debugLog: update textContent
  loadFile->>arrange: arrange(true)
  arrange->>dbg: dbg("arrange", trace) if logIt true
  dbg->>log: push entry with timestamp
  log-->>debugLog: update textContent
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PhysShell/griff#67: Adds the chunk.json capture helpers and UI handlers (detectBoundaries, downloadChunk) in app.js — the same paths now instrumented with debug logging in this PR.
  • PhysShell/griff#71: Introduces splitIntoPhrases and renderPhrase in app.js — both functions are further modified in this PR to add tag/phrase debug logging.

Poem

🐇 A log appears upon the page,
Each engine whisper kept in cage,
"Loaded! Captured! Split! Arranged!"
The timestamps march, each fact explained.
Copy or clear with buttons neat —
Now every debug hop's complete! 🪵

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main changes: adding on-page verbose debug logging and surfacing chunk tags in the web interface.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/web-debug-log

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

@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: b817dc1512

ℹ️ 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 web/static/app.js Outdated
// Appends one timestamped line to the on-page debug log. `data` (optional) is
// JSON-stringified, so the exact inputs/outputs of each engine call are visible
// without opening the browser console — Copy the panel straight into a report.
function dbg(label, data) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split this feature into red/green commits

This commit introduces the non-trivial debug-log UI/behavior in a single implementation commit with no preceding failing test commit in the reviewed sequence. /workspace/griff/AGENTS.md requires “Every new module or non-trivial change follows the red-green cycle strictly” and says reviewers must judge the commit sequence, so this needs to be reworked into a red test commit followed by the green implementation commit.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Holding on this one — I checked with the maintainer first, who defers to repo precedent here.

Red-green in this repo is enforced through cargo test on the Rust engine, where the public API and the test harness actually live: core/tests/* gate every engine change (e.g. the split seam in #71 landed as a red characterization test → green impl). This PR, by contrast, is browser-only glue — app.js / index.html / style.css, with no Rust, no new public API, and the repo has no JS test harness (web CI is just web/build.sh + a Pages deploy; there's no JS unit lane). The prior frontend-only PRs merged the same way — #67 (capture UI) and #71's pager were not red-green'd in JS.

Standing up a jsdom/vitest lane purely to TDD a diagnostic logging panel would be disproportionate to the change. If we do want JS unit tests as a general capability, that's better as its own infra PR than as a gate on this one — happy to open that separately if the maintainer wants the harness first.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Update — reversed course on this: the maintainer opted to stand up the JS test lane, so I've done exactly that and reworked the PR into a red→green sequence.

  • eb9b5bb (red) — adds the repo's first JS unit-test lane: web/package.json (npm testnode --test, zero deps), a characterization spec for the debug-log ring buffer (web/test/debuglog.test.js), and a CI workflow (.github/workflows/web-test.yml) running it on PRs/main touching web/. The module under test doesn't exist yet → fails.
  • 5eeec05 (green) — implements web/static/debuglog.js (pure, DOM-free ring buffer: bounded, timestamped, JSON payloads, ✗-prefixed errors) so the spec passes, then wires it into the panel.

Verified in isolated worktrees: the red commit's node --test exits 1, the green commit exits 0 (7/7). The DOM/wasm-coupled panel wiring stays glue (uncovered by design) — the pure, testable unit is the buffer. Thanks for pushing on this.


Generated by Claude Code

Comment thread web/static/app.js Outdated
if (splitChunks.length === 0) { resetSplit(); capMsg('no sounding phrases to split', true); return; }
if (splitChunks.length === 0) { resetSplit(); capMsg('no sounding phrases to split', true); dbg('split result', { phrases: 0 }); return; }
let resolvedTags = [];
try { resolvedTags = JSON.parse(splitChunks[0].chunk).tags || []; } catch (_) { /* leave empty */ }

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 Report resolved tags from all split phrases

When a split track has notation-derived technique tags only in later phrases, this samples only splitChunks[0], so the copied debug log can still report resolvedTags: [] even though exported phrase chunks contain tags. That undercuts the new tag-diagnosis path for exactly the multi-phrase cases it is meant to explain; aggregate tags across chunks or log tags per phrase instead of reading only the first chunk.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in bc067easplit result now logs tags per phrase (array aligned with ids), so notation-derived technique tags that appear only in later phrases show up instead of being hidden behind splitChunks[0]. The pager already shows the per-phrase tag count; the log now matches it. Good catch.


Generated by Claude Code

@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 `@web/static/app.js`:
- Around line 95-103: The arrange function calls JSON.parse on the wasmArrange
output without error handling, which will crash the UI if the engine returns
malformed or partial JSON before the status/debug error handling can execute.
Wrap the JSON.parse call that assigns to the current variable in a try/catch
block, and in the catch handler, call dbgErr with the parse error details and
appropriate context (including the mode, seed, offset, variation, track
parameters) similar to how the current error handling works, then return early
from the function to prevent further execution with invalid state.

In `@web/static/style.css`:
- Line 200: Replace the deprecated `word-break: break-word` declaration in the
style.css file with the modern standard property `overflow-wrap: anywhere`.
Optionally, you can also add `word-break: normal` alongside `overflow-wrap:
anywhere` for defensive clarity, but `overflow-wrap: anywhere` alone is
sufficient. This change addresses the Stylelint deprecation warning and aligns
with the CSS Working Group's recommended approach for handling word breaking
behavior.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c6e9deb-127e-43e3-95fd-d5e971c809a9

📥 Commits

Reviewing files that changed from the base of the PR and between c19ca6c and b817dc1.

📒 Files selected for processing (3)
  • web/static/app.js
  • web/static/index.html
  • web/static/style.css

Comment thread web/static/app.js
Comment thread web/static/style.css Outdated
claude added 2 commits June 18, 2026 17:48
Stands up the repo's first JS unit-test lane (node:test, zero deps) and a
characterization test for the playground's debug-log buffer: bounded ring,
timestamped lines, JSON-encoded payloads, and ✗-prefixed errors.

The module under test (static/debuglog.js) does not exist yet — this is the
red phase; the next commit implements it green.

- web/package.json:            `npm test` -> `node --test`
- web/test/debuglog.test.js:   the (currently failing) spec
- .github/workflows/web-test.yml: run it on PRs/main touching web/
Implements static/debuglog.js (pure, DOM-free ring buffer) so the red test
from the previous commit passes, then wires it into the playground:

- Collapsible Debug log panel (Copy/Clear) tracing every engine call — load,
  track, detect, capture, split, arrange, and all errors — with inputs and
  resolved outputs. Copy-paste friendly on a phone; no devtools needed.
- Tags made visible: capture/split traces print resolved tags/techniques
  (per phrase), the pager shows a per-phrase tag count, and the legend notes
  technique tags are auto-added from notation (ADR-0018) — so an empty `tags`
  is self-explanatory rather than a surprise.
- arrange() guards its JSON parse like the other engine calls; .debuglog uses
  overflow-wrap: anywhere (not the deprecated word-break: break-word).

Static front-end only; no engine/Rust change.
@PhysShell
PhysShell force-pushed the claude/web-debug-log branch from 88e3672 to 5eeec05 Compare June 18, 2026 17:48

@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/web-test.yml:
- Around line 16-26: The test job executes PR code via npm test while the
actions/checkout step retains credentials by default, creating a
token-exfiltration risk. Add a permissions block at the job level specifying
least-privilege access (likely contents: read only), and modify the
actions/checkout@v4 step to include persist-credentials: false to disable
credential persistence in the workflow environment.

In `@web/static/debuglog.js`:
- Around line 8-27: The `max` parameter in the `createDebugLog` function is not
validated, causing the ring-buffer logic in the `push` function to fail when
`max = 0` (where `lines.slice(-0)` returns an empty array) or for negative
values, breaking the bounded growth contract. Add validation at the start of
`createDebugLog` to ensure `max` is a positive number (greater than 0), either
by throwing an error for invalid values or enforcing a minimum value such as 1.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2e881efc-4bf2-47d4-a77d-fabac51d4685

📥 Commits

Reviewing files that changed from the base of the PR and between 88e3672 and 5eeec05.

📒 Files selected for processing (7)
  • .github/workflows/web-test.yml
  • web/package.json
  • web/static/app.js
  • web/static/debuglog.js
  • web/static/index.html
  • web/static/style.css
  • web/test/debuglog.test.js
✅ Files skipped from review due to trivial changes (1)
  • web/package.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • web/static/index.html
  • web/static/style.css
  • web/static/app.js

Comment thread .github/workflows/web-test.yml
Comment thread web/static/debuglog.js
- createDebugLog now rejects a non-positive/non-integer max: slice(-0) is a
  no-op that would silently disable the bound. Add a test for the guard.
- web-test.yml: least-privilege permissions (contents: read) and
  persist-credentials: false, since npm test runs PR-authored code (CodeRabbit
  /zizmor: artipacked). Actions stay tag-pinned, consistent with web.yml.
@PhysShell
PhysShell merged commit a5d7b68 into main Jun 18, 2026
2 checks passed
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.

2 participants