@leftoff/cli 0.9.17 → 0.9.18-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -2
- package/bin/leftoff-statusline.js +9 -0
- package/bin/leftoff.js +794 -540
- package/bin/pty-host-main.js +66 -0
- package/docs/macos-permissions.md +52 -0
- package/docs/test-plan.md +43 -0
- package/mod/.claude-plugin/plugin.json +1 -1
- package/mod/hooks/core.js +172 -12
- package/mod/hooks/register.js +186 -5
- package/mod/skills/walkthrough/SKILL.md +5 -3
- package/package.json +1 -1
- package/ui/app.css +240 -2
- package/ui/app.js +553 -62
- package/ui/ask.js +6 -3
- package/ui/cp-fold.js +22 -0
- package/ui/decisions.js +235 -0
- package/ui/hook-fix.js +109 -0
- package/ui/live-status.js +68 -2
- package/ui/live-view.js +23 -6
- package/ui/prs.js +15 -5
- package/ui/semdiff.js +165 -22
- package/ui/session-catchup.js +18 -2
- package/ui/session-title.js +88 -0
- package/ui/start.js +87 -12
- package/ui/summary-examples.js +2 -2
- package/ui/term.js +11 -3
- package/ui/testplan.js +162 -0
- package/ui/viewport-fit.js +59 -0
- package/ui/walk-pop.js +3 -0
- package/ui/what-it-did.js +12 -5
package/ui/what-it-did.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// app.js) so they can be checked without a browser.
|
|
6
6
|
import { icon } from './icons.js'
|
|
7
7
|
import { diffBlocks, splitPath } from './diff-view.js'
|
|
8
|
+
import { fileScopeSegHtml, scopeTagHtml, unreadableLines } from './semdiff.js' // 2026-11-03 This session · Whole folder, the walkthrough's own rule
|
|
8
9
|
|
|
9
10
|
const esc = (s) => String(s == null ? '' : s).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]))
|
|
10
11
|
const plural = (n, w) => n + ' ' + w + (n === 1 ? '' : 's')
|
|
@@ -63,12 +64,12 @@ export function fileRowHtml(f, ui, sid) {
|
|
|
63
64
|
const bodyId = 'wid-f-' + esc(encodeURIComponent(f.path).replace(/%/g, '_'))
|
|
64
65
|
const bar = '<span class="gd-bar" aria-hidden="true">' + diffBlocks(f.add, f.del).map((b) => '<i class="gd-b' + b + '"></i>').join('') + '</span>'
|
|
65
66
|
const counts = f.binary ? '<span class="wid-n">binary</span>' : f.big ? '<span class="wid-n">big</span>' : '<span class="wid-add">+' + esc(f.add) + '</span> <span class="wid-del">−' + esc(f.del) + '</span>' + bar
|
|
66
|
-
let h = '<li class="wid-item' + (open ? ' open' : '') + '">'
|
|
67
|
+
let h = '<li class="wid-item' + (open ? ' open' : '') + (f.notSession ? ' nots' : '') + '">'
|
|
67
68
|
h += '<button type="button" class="wid-row wid-file" data-action="wid-file" data-id="' + esc(sid) + '" data-path="' + esc(f.path) + '" aria-expanded="' + open + '" aria-controls="' + bodyId + '">'
|
|
68
69
|
h += '<span class="wid-chev" aria-hidden="true">' + icon(open ? 'chevron-down' : 'chevron-right') + '</span>'
|
|
69
70
|
h += '<span class="wid-st st-' + esc(f.status) + '" data-tip="' + esc(word) + '" aria-label="' + esc(word) + '">' + letter + '</span>'
|
|
70
71
|
const [dir, base] = splitPath(f.path)
|
|
71
|
-
h += '<span class="wid-path mono">' + (dir ? '<span class="wid-dir">' + esc(dir) + '</span>' : '') + '<b class="wid-base">' + esc(base) + '</b
|
|
72
|
+
h += '<span class="wid-path mono">' + (dir ? '<span class="wid-dir">' + esc(dir) + '</span>' : '') + '<b class="wid-base">' + esc(base) + '</b>' + scopeTagHtml(f, { esc }) + '</span><span class="wid-counts">' + counts + '</span></button>'
|
|
72
73
|
if (open) {
|
|
73
74
|
const v = ui.files[f.path]
|
|
74
75
|
h += '<div class="wid-out" id="' + bodyId + '">'
|
|
@@ -91,16 +92,22 @@ export function fileRowHtml(f, ui, sid) {
|
|
|
91
92
|
|
|
92
93
|
function diffHtml(ui, sid) {
|
|
93
94
|
const d = ui.diff
|
|
94
|
-
|
|
95
|
+
// 2026-11-03 scoped like the walkthrough: This session (the default) or Whole folder, counts on both
|
|
96
|
+
const fsc = d && d.fileScope && d.fileScope.session != null ? d.fileScope : null
|
|
97
|
+
const title = fsc && fsc.key !== 'folder' ? 'This session’s changes' : 'This folder’s changes'
|
|
98
|
+
let h = '<div class="wid-sub"><h3>' + title + '</h3>'
|
|
95
99
|
if (d && d.folder && !d.tooBig && !d.noRepo) h += '<span class="wid-meta">' + esc(d.folder) + (d.totals && d.totals.files ? ' · ' + plural(d.totals.files, 'file') + ' · <span class="wid-add">+' + esc(d.totals.add) + '</span> <span class="wid-del">−' + esc(d.totals.del) + '</span>' : '') + '</span>'
|
|
96
100
|
h += '</div>'
|
|
101
|
+
if (fsc) h += '<div class="wid-scope">' + fileScopeSegHtml(fsc, { esc, icon, action: 'wid-files', busy: !!ui.loading }) + '</div>'
|
|
97
102
|
if (ui.diffError) return h + '<p class="wid-note">' + esc(ui.diffError) + '</p>'
|
|
98
103
|
if (!d) return h + '<p class="wid-note">Loading…</p>'
|
|
99
104
|
if (d.tooBig) return h + '<p class="wid-note">Too big to show here.</p>'
|
|
100
105
|
if (d.noRepo) return h + '<p class="wid-note">' + (d.noRepo === 'not_a_repo' ? 'This folder isn’t a git repository.' : d.noRepo === 'no_git' ? 'git isn’t installed on that Mac.' : 'This session’s folder isn’t there any more.') + '</p>'
|
|
101
|
-
|
|
102
|
-
h
|
|
106
|
+
const notes = unreadableLines({ baseNotes: d.baseNotes }).map((l) => '<p class="wid-note wid-scope-n">' + icon('info') + '<span>' + esc(l) + '</span></p>').join('')
|
|
107
|
+
if (!d.files || !d.files.length) return h + notes + '<p class="wid-note">' + (fsc && fsc.key !== 'folder' ? (fsc.folder ? 'No uncommitted changes from this session (' + plural(fsc.folder, 'file') + ' in the whole folder).' : 'No uncommitted changes from this session.') : 'No uncommitted changes.') + '</p>'
|
|
108
|
+
h += notes + '<ul class="wid-list">' + d.files.map((f) => fileRowHtml(f, ui, sid)).join('') + '</ul>'
|
|
103
109
|
if (d.truncated) h += '<p class="wid-note">Showing the first ' + d.files.length + ' of ' + esc(d.totals.files) + ' files.</p>'
|
|
110
|
+
if (fsc && fsc.key !== 'folder') return h + '<p class="wid-foot">Uncommitted changes this session made in its folder. Whole folder shows everything, other sessions’ changes too.</p>'
|
|
104
111
|
return h + '<p class="wid-foot">Uncommitted changes in the session’s folder (staged, unstaged and new files). Other sessions in this folder show the same changes.</p>'
|
|
105
112
|
}
|
|
106
113
|
|