Merge dev → main (automated)#2010
Merged
Merged
Conversation
added 27 commits
July 9, 2026 09:52
…-git-branch guard Changes: - .githooks/post-merge: Fix hardcoded /tmp/Worklog/... path to use $(dirname "$0") - .githooks/post-rewrite: Fix hardcoded /tmp/Worklog/... path to use $(dirname "$0") - .githooks/post-checkout: Add --git-branch refs/worklog/data to wl sync call - .githooks/worklog-post-pull: Add --git-branch refs/worklog/data to wl sync call - src/commands/init.ts: All 5 inline hook generation patterns now use --git-branch refs/worklog/data - docs/branch-protection.md: Document required branch protection rules for dev and main All hooks now explicitly use --git-branch refs/worklog/data to prevent accidental pushes to standard branches (refs/heads/, refs/tags/). The src/sync.ts guard (gitPushDataFileToBranch) already blocks such pushes. The pre-push hook was already fixed to use worktree isolation + --git-branch.
… from .githooks Extend the command to detect and replace outdated git hooks installed in .git/hooks/ from the committed safe versions in .githooks/. This ensures existing installations automatically get the safe hook patterns (using --git-branch refs/worklog/data) without manual re-installation. Changes: - New src/doctor/hook-upgrade.ts module for hook detection and upgrade - Updated doctor upgrade command to check/upgrade hooks alongside database migrations - CLI: dry-run reports outdated hooks, --confirm applies upgrades - JSON output includes hooks info alongside migrations - Unit tests (21 tests) and CLI integration tests (5 tests) - Updated docs/migrations.md with hook upgrade documentation
- Created packages/tui/extensions/Worklog/session-health.ts with:
- SessionHealthState type and state management
- Event handlers for turn_start, message_end, tool_execution_start/end,
model_select, session_start, session_shutdown
- Footer renderer showing status marker (○/●/⚡), elapsed time
(colour-coded), token counts (↑input ↓output), context usage
(percent/window), model ID, and turn count (#N)
- 1-second setInterval ticker for elapsed time updates
- Graceful degradation in non-TUI modes
- Token extraction from session entries, k-suffix formatting
- Truncation for narrow terminals via terminal-utils
- Created session-health.test.ts with 46 tests covering:
- Export constants (SESSION_HEALTH_STATUS_KEY, STATUS_*)
- Event registration (7 lifecycle events)
- Time formatting (elapsed, colour thresholds)
- Token formatting (k/M suffixes)
- Context usage formatting
- Token extraction from session entries
- Footer rendering (idle/streaming/tool/model/turn)
- Integration scenarios
- Edge cases (boundaries, null handling, narrow terminals)
- Updated index.ts: import and call registerSessionHealth(pi)
- Updated README.md: added Session Health Footer documentation
…ealth The updateState() function was calling registerSessionHealth(pi) which re-registered ALL event listeners via pi.on() each time any event fired. This caused exponential listener growth and OOM crash on pi startup. Fix: - Removed the recursive registerSessionHealth() call from updateState() - Changed updateState() to just mutate state and call requestRender() - Stored a requestRender reference from the footer factory's tui param - Merged the duplicate session_start listeners into one - Proper dispose() in the footer component cleans up ticker + branch listener
…in session health footer and move #N before timer Fixes audit rejection: 'The new footer prevents the old footer information from being displayed... There is also no description of what is happening... Move the step number to before the timer' Changes: - Move turn count (#N) from right section to left section, before the elapsed time (so layout reads: marker #N time tokens context model instead of marker time tokens context model #N) - Include extension status entries (from footerData.getExtensionStatuses()) as the first line of the rendered footer, ensuring that ctx.ui.setStatus() entries (model-display provider/model, activity indicator, etc.) remain visible when the custom session health footer is active - Updated README.md documentation to reflect the new two-line footer layout and the position of the turn count
…health footer - Add lastChunkTime property to SessionHealthState, updated on message_update - Add message_update event handler to track last chunk arrival time - Refactor footer into three-section layout: Left: [marker] [#turn] (Last Chunk: Xs ago) [streaming only] Center: [elapsed since stage start] Right: ↑input ↓output [context%/window] [model] - Add formatShortElapsedTime utility for last-chunk timer display - Update tests: 56 existing + 4 new test cases (60 total) - Update README with new three-section layout and message_update event
Add a dedicated third line to the TUI footer showing the provider/model in grey (dim) text, below the session health details. Changes: - model-display.ts: Export getResolvedModel() and getSelectedModel() getters; stop using setStatus() (model now shown on its own line); add onModelChange() callback for reactive updates - session-health.ts: Import model state from model-display; add Line 3 to footer render showing provider/model in grey text (or (pending)); remove ctx.model?.id from session health line (right section); fix pre-existing off-by-one in layout width calculation; add after_provider_response listener to trigger re-render - Updated tests to verify new behavior (23 model-display + 64 session-health tests all pass)
… footer line 3 Changes: - Footer Line 3 now shows both the selected Pi model alias AND the resolved provider/model, e.g. 'code -> openai/gpt-4' (addresses regression where the selected model was no longer visible after removal from the session health line) - When no router-assigned model yet, shows just the alias (e.g. 'code') instead of '(pending)' for more informative feedback - Updated tests to verify the new format
- The model/provider line on the footer is now always visible: shows a grey '—' when no alias or resolved model is available - Replaced '->' with Unicode '→' arrow character for cleaner display - Updated tests to expect the new format and always-present dash
…footer display - Added session_start listener to model-display.ts that reads the Pi model alias from ctx.model?.id and populates _selectedModel. This ensures getSelectedModel() returns the alias even when no model_select event has fired yet (e.g. at startup with a default model). - Guard: only populates if model_select hasn't already set _selectedModel, so explicit user selections take priority. - Added 4 new tests: session_start listener registration, session_start captures alias, session_start does not overwrite model_select, and onModelChange fires on session_start. Total: 91 tests passing.
Add a truncated preview of the session's first user message to Line 3 of the footer alongside the model/provider info. Changes: - Add extractInitialPrompt(entries) to extract first user message text - Add initialPrompt to SessionHealthState for ticker population - Update line 3 render to show both model info and quoted prompt preview - Add 7 unit tests for extractInitialPrompt edge cases - Add 3 integration tests for the prompt display in footer (resolved, alias-only, no-prompt) - 101 total tests passing (27 model-display + 74 session-health)
…te() The ticker's refreshState() captures the initial prompt via extractInitialPrompt(entries) but never calls requestRender(), so the TUI footer is never redrawn with the captured prompt value. This is a one-line fix to add requestRender?.() after the capture. Fixes the bug where the initial prompt preview was captured correctly but never appeared in the TUI footer. Related: WL-0MRF6JXMD003KHLQ (original implementation)
…sed content format
Pi stores user message content as an array of content parts
([{ type: "text", text: "..." }, ...]) — see agent-session.js:788-795.
extractInitialPrompt() only handled string format, so it returned null
for all real Pi session entries and the initial prompt preview never
captured any text.
Fix: handle both string format (backward compat) and array format
by extracting text parts from the array, same approach used by
Pi's own _getUserMessageText() and activity-indicator.ts.
Adds 6 new tests for array content format.
All 80 tests pass (74 existing + 6 new).
Related: WL-0MRF6JR7P005TJU9
When a user invokes /skill:name, Pi expands it to an XML block: <skill name="..." location="...">...</skill> extractInitialPrompt() now detects skill blocks and returns a compact preview like '[skill:audit] WL-123' instead of the raw XML first line. Also refactored to use a helper extractMessageText(content) that matches Pi's own extractTextContent approach (session-manager.js), keeping the skill block logic cleanly separated. Adds 5 new tests for skill block detection. All 85 tests pass (80 existing + 5 new). Related: WL-0MRFH8W4J007HIY5
…remove quotes Two improvements to the initial prompt preview in the footer: 1. Work item title resolution: When the prompt contains a work item ID (e.g. '[skill:audit] WL-0MRF6JXMD003KHLQ'), asynchronously resolve the title via 'wl show' and enrich the preview to '[skill:audit] WL-0MRF6JXMD003KHLQ Show initial prompt...'. Uses fire-and-forget pattern (same as activity-indicator) so the UI shows the raw ID first, then updates once the title arrives. 2. Drop surrounding quotes: The quotes consumed precious character space on the footer line. The preview is now unquoted. 3. Dynamic preview width: Instead of a fixed 40-char limit, calculate available space as Math.max(15, width - 38) so wider terminals show more prompt text. The line is still ultimately truncated to terminal width by truncateToTerminalWidth. Imports added: detectWorkItemId from activity-indicator, runWl from wl-integration. Updates 3 existing tests for quote removal and dynamic truncation. All 85 tests pass. Related: WL-0MRF6JR7P005TJU9
Changes: - Added sessionStartTime field to SessionHealthState interface - Set sessionStartTime=Date.now() in session_start handler - Added formatTotalSessionTime() function for 'Total: Xm Ys' display - Moved elapsed time (color-coded) from center to left section, after state marker - Center section now shows total wall-clock session duration - Right section unchanged - Updated all tests to verify new layout - Added new formatTotalSessionTime tests Acceptance criteria: 1. Center: Total: 5m 42s (or Total: — before session starts) 2. Left: ○ Idle 30s #1 (elapsed time after state label) 3. Right: unchanged 4. Total: updates every second via existing ticker 5. Documentation: code comments updated 6. Tests: all session-health tests pass
…n close
Add lease-release module that detects when a new Pi session is created
(reason 'new') and sends a best-effort POST to the Local Proxy's
{baseUrl}/leases/release endpoint to release the previous session's
model lease, speeding up model reclamation.
Changes:
- New lease-release.ts module:
- Reads ~/.pi/agent/models.json to find Local Proxy baseUrl
- Sends fire-and-forget POST {baseUrl}/leases/release
- Error handling via console.debug (no user-visible errors)
- Caches baseUrl per extension lifecycle
- Exports registerLeaseRelease() for integration
- New lease-release.test.ts with 17 tests covering:
- Happy path (correct endpoint, session ID in body)
- Network failure (no crash, debug log)
- Non-2xx response (no crash, debug log)
- Missing Local Proxy provider (no request sent)
- Missing models.json (no request sent)
- Non-'new' reasons (startup, resume, fork, reload)
- Missing previousSessionFile
- Empty session ID
- Modified index.ts: imports and registers registerLeaseRelease()
- Updated README.md with lease release feature documentation
…r layout The README at packages/tui/extensions/README.md still described the old footer layout (elapsed time in center as 'Stage elapsed time'). Updated: - Section descriptions to show elapsed time in left section - Center section now documents 'total session duration' - Table rows: 'Stage elapsed' → 'Response elapsed', added 'Total session time' - Layout diagram: moved elapsed time (45s) to left, shows Total: 5m 42s in center - Event tracking: 'set stage-start timer' → 'set last-response timer' - Technical notes updated for the three-section layout
Summary of changes: - tests/extensions/worklog-browse-extension.test.ts: Fix 16 emoji icon expectations from ❓ (U+2753) to ❔ (U+2754) to match src/icons.ts - packages/shared/src/persistent-store.ts: Add commentsForItem_ cache prefix invalidation to invalidateWorkItemCaches; add clearCommentCaches() public wrapper method to support cross-connection cache coherence - packages/shared/src/database.ts: Call clearCommentCaches() after triggerSemanticIndex() in create() to prevent stale cached empty comment lists from persisting across database connections - tests/cli/status.test.ts: Update version expectation from 1.0.1 to 1.0.2 - ~/.pi/agent/skills/ralph/SKILL.md (system): Replace 6 legacy skill/plan/ path refs with ../plan/ relative paths - ~/.pi/agent/skills/ship/SKILL.md (system): Replace 1 legacy skill/audit/ path ref with ../audit/ relative path All 165 test files pass (3035 tests), 1 skipped (long-running load test).
This reverts commit 545a02a.
…indicators and truncated work item IDs Changes: - session-health.ts: Changed extractInitialPrompt skill format from [skill:name] to name: (e.g., [skill:implement] → implement:) - terminal-utils.ts: Added truncateWorkItemId() utility that replaces full-length IDs (WL-0MQK0OM6I00168HD) with truncated form (WL...68HD) - session-health.ts: Applied truncateWorkItemId to Line 3 prompt preview - activity-indicator.ts: Applied truncateWorkItemId to displayed work item IDs in showActivityWithTitleLookup - Updated all relevant tests to expect new formats - All 3043 tests pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated release created by ship skill.\n\nIncludes CHANGELOG.md with work-item summaries from this release.