specsmd 0.1.53 → 0.1.55
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/lib/dashboard/git/changes.js +2 -2
- package/lib/dashboard/tui/app.js +314 -48
- package/package.json +1 -1
|
@@ -273,7 +273,7 @@ function readUntrackedFileDiff(repoRoot, absolutePath) {
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
const result = runGit(
|
|
276
|
-
['-c', 'color.ui=
|
|
276
|
+
['-c', 'color.ui=false', '--no-pager', 'diff', '--no-index', '--', '/dev/null', absolutePath],
|
|
277
277
|
repoRoot,
|
|
278
278
|
{ acceptedStatuses: [0, 1] }
|
|
279
279
|
);
|
|
@@ -305,7 +305,7 @@ function loadGitDiffPreview(changeEntry) {
|
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
const args = ['-c', 'color.ui=
|
|
308
|
+
const args = ['-c', 'color.ui=false', '--no-pager', 'diff'];
|
|
309
309
|
if (bucket === 'staged') {
|
|
310
310
|
args.push('--cached');
|
|
311
311
|
}
|
package/lib/dashboard/tui/app.js
CHANGED
|
@@ -1172,6 +1172,215 @@ function getGitChangesSnapshot(snapshot) {
|
|
|
1172
1172
|
};
|
|
1173
1173
|
}
|
|
1174
1174
|
|
|
1175
|
+
function readGitCommandLines(repoRoot, args, options = {}) {
|
|
1176
|
+
if (typeof repoRoot !== 'string' || repoRoot.trim() === '' || !Array.isArray(args) || args.length === 0) {
|
|
1177
|
+
return [];
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
const acceptedStatuses = Array.isArray(options.acceptedStatuses) && options.acceptedStatuses.length > 0
|
|
1181
|
+
? options.acceptedStatuses
|
|
1182
|
+
: [0];
|
|
1183
|
+
|
|
1184
|
+
const result = spawnSync('git', args, {
|
|
1185
|
+
cwd: repoRoot,
|
|
1186
|
+
encoding: 'utf8',
|
|
1187
|
+
maxBuffer: 8 * 1024 * 1024
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
if (result.error) {
|
|
1191
|
+
return [];
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
if (typeof result.status === 'number' && !acceptedStatuses.includes(result.status)) {
|
|
1195
|
+
return [];
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
const lines = String(result.stdout || '')
|
|
1199
|
+
.split(/\r?\n/)
|
|
1200
|
+
.map((line) => line.trim())
|
|
1201
|
+
.filter(Boolean);
|
|
1202
|
+
|
|
1203
|
+
const limit = Number.isFinite(options.limit) ? Math.max(1, Math.floor(options.limit)) : null;
|
|
1204
|
+
if (limit == null || lines.length <= limit) {
|
|
1205
|
+
return lines;
|
|
1206
|
+
}
|
|
1207
|
+
return lines.slice(0, limit);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
function buildGitStatusPanelLines(snapshot) {
|
|
1211
|
+
const git = getGitChangesSnapshot(snapshot);
|
|
1212
|
+
if (!git.available) {
|
|
1213
|
+
return [{
|
|
1214
|
+
text: 'Repository unavailable in selected worktree',
|
|
1215
|
+
color: 'red',
|
|
1216
|
+
bold: true
|
|
1217
|
+
}];
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
const tracking = git.upstream
|
|
1221
|
+
? `${git.upstream} (${git.ahead > 0 ? `ahead ${git.ahead}` : 'ahead 0'}, ${git.behind > 0 ? `behind ${git.behind}` : 'behind 0'})`
|
|
1222
|
+
: 'no upstream';
|
|
1223
|
+
|
|
1224
|
+
return [
|
|
1225
|
+
{
|
|
1226
|
+
text: `branch: ${git.branch}${git.detached ? ' [detached]' : ''}`,
|
|
1227
|
+
color: 'green',
|
|
1228
|
+
bold: true
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
text: `tracking: ${tracking}`,
|
|
1232
|
+
color: 'gray',
|
|
1233
|
+
bold: false
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
text: `changes: ${git.counts.total || 0} total`,
|
|
1237
|
+
color: 'gray',
|
|
1238
|
+
bold: false
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
text: `staged ${git.counts.staged || 0} | unstaged ${git.counts.unstaged || 0}`,
|
|
1242
|
+
color: 'yellow',
|
|
1243
|
+
bold: false
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
text: `untracked ${git.counts.untracked || 0} | conflicts ${git.counts.conflicted || 0}`,
|
|
1247
|
+
color: 'yellow',
|
|
1248
|
+
bold: false
|
|
1249
|
+
}
|
|
1250
|
+
];
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function buildGitBranchesPanelLines(snapshot) {
|
|
1254
|
+
const git = getGitChangesSnapshot(snapshot);
|
|
1255
|
+
if (!git.available) {
|
|
1256
|
+
return [{
|
|
1257
|
+
text: 'No branch list (git unavailable)',
|
|
1258
|
+
color: 'gray',
|
|
1259
|
+
bold: false
|
|
1260
|
+
}];
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
const branchLines = readGitCommandLines(git.rootPath, [
|
|
1264
|
+
'-c',
|
|
1265
|
+
'color.ui=false',
|
|
1266
|
+
'for-each-ref',
|
|
1267
|
+
'--sort=-committerdate',
|
|
1268
|
+
'--format=%(if)%(HEAD)%(then)*%(else) %(end) %(refname:short)',
|
|
1269
|
+
'refs/heads'
|
|
1270
|
+
], { limit: 8 });
|
|
1271
|
+
|
|
1272
|
+
const lines = [{
|
|
1273
|
+
text: 'Local branches · Remotes · Tags',
|
|
1274
|
+
color: 'cyan',
|
|
1275
|
+
bold: true
|
|
1276
|
+
}];
|
|
1277
|
+
|
|
1278
|
+
if (branchLines.length === 0) {
|
|
1279
|
+
lines.push({
|
|
1280
|
+
text: 'No local branches found',
|
|
1281
|
+
color: 'gray',
|
|
1282
|
+
bold: false
|
|
1283
|
+
});
|
|
1284
|
+
return lines;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
for (const line of branchLines) {
|
|
1288
|
+
const isCurrent = line.startsWith('*');
|
|
1289
|
+
lines.push({
|
|
1290
|
+
text: line,
|
|
1291
|
+
color: isCurrent ? 'green' : 'gray',
|
|
1292
|
+
bold: isCurrent
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
return lines;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
function buildGitCommitsPanelLines(snapshot) {
|
|
1300
|
+
const git = getGitChangesSnapshot(snapshot);
|
|
1301
|
+
if (!git.available) {
|
|
1302
|
+
return [{
|
|
1303
|
+
text: 'No commit log (git unavailable)',
|
|
1304
|
+
color: 'gray',
|
|
1305
|
+
bold: false
|
|
1306
|
+
}];
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
const reflogLines = readGitCommandLines(git.rootPath, [
|
|
1310
|
+
'-c',
|
|
1311
|
+
'color.ui=false',
|
|
1312
|
+
'reflog',
|
|
1313
|
+
'--date=relative',
|
|
1314
|
+
'--pretty=format:%h %gs'
|
|
1315
|
+
], { limit: 8 });
|
|
1316
|
+
|
|
1317
|
+
const lines = [{
|
|
1318
|
+
text: 'Commits · Reflog',
|
|
1319
|
+
color: 'cyan',
|
|
1320
|
+
bold: true
|
|
1321
|
+
}];
|
|
1322
|
+
|
|
1323
|
+
if (reflogLines.length === 0) {
|
|
1324
|
+
lines.push({
|
|
1325
|
+
text: 'No reflog entries',
|
|
1326
|
+
color: 'gray',
|
|
1327
|
+
bold: false
|
|
1328
|
+
});
|
|
1329
|
+
return lines;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
lines.push(...reflogLines.map((line) => ({
|
|
1333
|
+
text: line,
|
|
1334
|
+
color: 'gray',
|
|
1335
|
+
bold: false
|
|
1336
|
+
})));
|
|
1337
|
+
return lines;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
function buildGitStashPanelLines(snapshot) {
|
|
1341
|
+
const git = getGitChangesSnapshot(snapshot);
|
|
1342
|
+
if (!git.available) {
|
|
1343
|
+
return [{
|
|
1344
|
+
text: 'No stash info (git unavailable)',
|
|
1345
|
+
color: 'gray',
|
|
1346
|
+
bold: false
|
|
1347
|
+
}];
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
const stashLines = readGitCommandLines(git.rootPath, [
|
|
1351
|
+
'-c',
|
|
1352
|
+
'color.ui=false',
|
|
1353
|
+
'stash',
|
|
1354
|
+
'list',
|
|
1355
|
+
'--pretty=format:%gd %s'
|
|
1356
|
+
], {
|
|
1357
|
+
acceptedStatuses: [0],
|
|
1358
|
+
limit: 4
|
|
1359
|
+
});
|
|
1360
|
+
|
|
1361
|
+
const lines = [{
|
|
1362
|
+
text: 'Stash',
|
|
1363
|
+
color: 'cyan',
|
|
1364
|
+
bold: true
|
|
1365
|
+
}];
|
|
1366
|
+
|
|
1367
|
+
if (stashLines.length === 0) {
|
|
1368
|
+
lines.push({
|
|
1369
|
+
text: 'No stashes',
|
|
1370
|
+
color: 'gray',
|
|
1371
|
+
bold: false
|
|
1372
|
+
});
|
|
1373
|
+
return lines;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
lines.push(...stashLines.map((line) => ({
|
|
1377
|
+
text: line,
|
|
1378
|
+
color: 'gray',
|
|
1379
|
+
bold: false
|
|
1380
|
+
})));
|
|
1381
|
+
return lines;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1175
1384
|
function getDashboardWorktreeMeta(snapshot) {
|
|
1176
1385
|
if (!snapshot || typeof snapshot !== 'object') {
|
|
1177
1386
|
return null;
|
|
@@ -1349,7 +1558,7 @@ function getSectionOrderForView(view, options = {}) {
|
|
|
1349
1558
|
return ['standards', 'stats', 'warnings', 'error-details'];
|
|
1350
1559
|
}
|
|
1351
1560
|
if (view === 'git') {
|
|
1352
|
-
return ['git-changes'];
|
|
1561
|
+
return ['git-status', 'git-changes', 'git-branches', 'git-commits', 'git-stash', 'git-diff'];
|
|
1353
1562
|
}
|
|
1354
1563
|
const sections = [];
|
|
1355
1564
|
if (includeWorktrees) {
|
|
@@ -2420,6 +2629,21 @@ function rowToFileEntry(row) {
|
|
|
2420
2629
|
};
|
|
2421
2630
|
}
|
|
2422
2631
|
|
|
2632
|
+
function firstFileEntryFromRows(rows) {
|
|
2633
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
2634
|
+
return null;
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
for (const row of rows) {
|
|
2638
|
+
const entry = rowToFileEntry(row);
|
|
2639
|
+
if (entry) {
|
|
2640
|
+
return entry;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
return null;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2423
2647
|
function rowToWorktreeId(row) {
|
|
2424
2648
|
if (!row || typeof row.key !== 'string') {
|
|
2425
2649
|
return null;
|
|
@@ -2528,7 +2752,7 @@ function buildQuickHelpText(view, options = {}) {
|
|
|
2528
2752
|
}
|
|
2529
2753
|
parts.push('a current', 'f files');
|
|
2530
2754
|
} else if (view === 'git') {
|
|
2531
|
-
parts.push('
|
|
2755
|
+
parts.push('6 status', '7 files', '8 branches', '9 commits', '0 stash', '- diff');
|
|
2532
2756
|
}
|
|
2533
2757
|
parts.push(`tab1 ${activeLabel}`);
|
|
2534
2758
|
|
|
@@ -2540,7 +2764,7 @@ function buildQuickHelpText(view, options = {}) {
|
|
|
2540
2764
|
return parts.join(' | ');
|
|
2541
2765
|
}
|
|
2542
2766
|
|
|
2543
|
-
function
|
|
2767
|
+
function buildGitCommandStrip(view, options = {}) {
|
|
2544
2768
|
const {
|
|
2545
2769
|
hasWorktrees = false,
|
|
2546
2770
|
previewOpen = false
|
|
@@ -2560,7 +2784,7 @@ function buildLazyGitCommandStrip(view, options = {}) {
|
|
|
2560
2784
|
} else if (view === 'health') {
|
|
2561
2785
|
parts.push('s standards', 't stats', 'w warnings');
|
|
2562
2786
|
} else if (view === 'git') {
|
|
2563
|
-
parts.push('
|
|
2787
|
+
parts.push('6 status', '7 files', '8 branches', '9 commits', '0 stash', '- diff', 'space preview');
|
|
2564
2788
|
}
|
|
2565
2789
|
|
|
2566
2790
|
if (previewOpen) {
|
|
@@ -2573,7 +2797,7 @@ function buildLazyGitCommandStrip(view, options = {}) {
|
|
|
2573
2797
|
return parts.join(' | ');
|
|
2574
2798
|
}
|
|
2575
2799
|
|
|
2576
|
-
function
|
|
2800
|
+
function buildGitCommandLogLine(options = {}) {
|
|
2577
2801
|
const {
|
|
2578
2802
|
statusLine = '',
|
|
2579
2803
|
activeFlow = 'fire',
|
|
@@ -2650,7 +2874,7 @@ function buildHelpOverlayLines(options = {}) {
|
|
|
2650
2874
|
{ text: '', color: undefined, bold: false },
|
|
2651
2875
|
{ text: 'Tab 5 Git Changes', color: 'yellow', bold: true },
|
|
2652
2876
|
'select changed files and preview diffs',
|
|
2653
|
-
'
|
|
2877
|
+
'6 status | 7 files | 8 branches | 9 commits | 0 stash | - diff',
|
|
2654
2878
|
{ text: '', color: undefined, bold: false },
|
|
2655
2879
|
{ text: `Current view: ${String(view || 'runs').toUpperCase()}`, color: 'gray', bold: false }
|
|
2656
2880
|
);
|
|
@@ -3277,32 +3501,11 @@ function createDashboardApp(deps) {
|
|
|
3277
3501
|
const gitRows = shouldHydrateSecondaryTabs
|
|
3278
3502
|
? (() => {
|
|
3279
3503
|
const git = getGitChangesSnapshot(snapshot);
|
|
3280
|
-
|
|
3281
|
-
? `${git.upstream} (${git.ahead > 0 ? `ahead ${git.ahead}` : 'ahead 0'}, ${git.behind > 0 ? `behind ${git.behind}` : 'behind 0'})`
|
|
3282
|
-
: 'no upstream';
|
|
3283
|
-
const headerRows = [{
|
|
3284
|
-
kind: 'info',
|
|
3285
|
-
key: 'git:branch',
|
|
3286
|
-
label: git.available
|
|
3287
|
-
? `branch ${git.branch}${git.detached ? ' [detached]' : ''} | ${tracking}`
|
|
3288
|
-
: 'git: repository unavailable in selected worktree',
|
|
3289
|
-
color: git.available ? 'cyan' : 'red',
|
|
3290
|
-
bold: true,
|
|
3291
|
-
selectable: false
|
|
3292
|
-
}, {
|
|
3293
|
-
kind: 'info',
|
|
3294
|
-
key: 'git:counts',
|
|
3295
|
-
label: `changes ${git.counts.total || 0} | staged ${git.counts.staged || 0} | unstaged ${git.counts.unstaged || 0} | untracked ${git.counts.untracked || 0} | conflicts ${git.counts.conflicted || 0}`,
|
|
3296
|
-
color: 'gray',
|
|
3297
|
-
bold: false,
|
|
3298
|
-
selectable: false
|
|
3299
|
-
}];
|
|
3300
|
-
const groups = toExpandableRows(
|
|
3504
|
+
return toExpandableRows(
|
|
3301
3505
|
buildGitChangeGroups(snapshot),
|
|
3302
3506
|
git.available ? 'Working tree clean' : 'No git changes',
|
|
3303
3507
|
expandedGroups
|
|
3304
3508
|
);
|
|
3305
|
-
return [...headerRows, ...groups];
|
|
3306
3509
|
})()
|
|
3307
3510
|
: toLoadingRows('Loading git changes...', 'git-loading');
|
|
3308
3511
|
|
|
@@ -3338,6 +3541,9 @@ function createDashboardApp(deps) {
|
|
|
3338
3541
|
const focusedIndex = selectionBySection[focusedSection] || 0;
|
|
3339
3542
|
const selectedFocusedRow = getSelectedRow(focusedRows, focusedIndex);
|
|
3340
3543
|
const selectedFocusedFile = rowToFileEntry(selectedFocusedRow);
|
|
3544
|
+
const selectedGitRow = getSelectedRow(gitRows, selectionBySection['git-changes'] || 0);
|
|
3545
|
+
const selectedGitFile = rowToFileEntry(selectedGitRow);
|
|
3546
|
+
const firstGitFile = firstFileEntryFromRows(gitRows);
|
|
3341
3547
|
|
|
3342
3548
|
const refresh = useCallback(async (overrideSelectedWorktreeId = null) => {
|
|
3343
3549
|
const now = new Date().toISOString();
|
|
@@ -3691,24 +3897,34 @@ function createDashboardApp(deps) {
|
|
|
3691
3897
|
return;
|
|
3692
3898
|
}
|
|
3693
3899
|
} else if (ui.view === 'git') {
|
|
3694
|
-
if (input === '
|
|
3900
|
+
if (input === '6') {
|
|
3901
|
+
setSectionFocus((previous) => ({ ...previous, git: 'git-status' }));
|
|
3902
|
+
setPaneFocus('main');
|
|
3903
|
+
return;
|
|
3904
|
+
}
|
|
3905
|
+
if (input === '7') {
|
|
3695
3906
|
setSectionFocus((previous) => ({ ...previous, git: 'git-changes' }));
|
|
3907
|
+
setPaneFocus('main');
|
|
3696
3908
|
return;
|
|
3697
3909
|
}
|
|
3698
|
-
if (input === '
|
|
3699
|
-
|
|
3910
|
+
if (input === '8') {
|
|
3911
|
+
setSectionFocus((previous) => ({ ...previous, git: 'git-branches' }));
|
|
3912
|
+
setPaneFocus('main');
|
|
3700
3913
|
return;
|
|
3701
3914
|
}
|
|
3702
|
-
if (input === '
|
|
3703
|
-
|
|
3915
|
+
if (input === '9') {
|
|
3916
|
+
setSectionFocus((previous) => ({ ...previous, git: 'git-commits' }));
|
|
3917
|
+
setPaneFocus('main');
|
|
3704
3918
|
return;
|
|
3705
3919
|
}
|
|
3706
|
-
if (input === '
|
|
3707
|
-
|
|
3920
|
+
if (input === '0') {
|
|
3921
|
+
setSectionFocus((previous) => ({ ...previous, git: 'git-stash' }));
|
|
3922
|
+
setPaneFocus('main');
|
|
3708
3923
|
return;
|
|
3709
3924
|
}
|
|
3710
|
-
if (input === '
|
|
3711
|
-
|
|
3925
|
+
if (input === '-') {
|
|
3926
|
+
setSectionFocus((previous) => ({ ...previous, git: 'git-diff' }));
|
|
3927
|
+
setPaneFocus('main');
|
|
3712
3928
|
return;
|
|
3713
3929
|
}
|
|
3714
3930
|
}
|
|
@@ -4066,6 +4282,16 @@ function createDashboardApp(deps) {
|
|
|
4066
4282
|
fullDocument: overlayPreviewOpen
|
|
4067
4283
|
})
|
|
4068
4284
|
: [];
|
|
4285
|
+
const gitInlineDiffTarget = selectedGitFile || firstGitFile || previewTarget || null;
|
|
4286
|
+
const gitInlineDiffLines = ui.view === 'git'
|
|
4287
|
+
? buildPreviewLines(gitInlineDiffTarget, compactWidth, previewOpen && paneFocus === 'preview' ? previewScroll : 0, {
|
|
4288
|
+
fullDocument: false
|
|
4289
|
+
})
|
|
4290
|
+
: [];
|
|
4291
|
+
const gitStatusPanelLines = ui.view === 'git' ? buildGitStatusPanelLines(snapshot) : [];
|
|
4292
|
+
const gitBranchesPanelLines = ui.view === 'git' ? buildGitBranchesPanelLines(snapshot) : [];
|
|
4293
|
+
const gitCommitsPanelLines = ui.view === 'git' ? buildGitCommitsPanelLines(snapshot) : [];
|
|
4294
|
+
const gitStashPanelLines = ui.view === 'git' ? buildGitStashPanelLines(snapshot) : [];
|
|
4069
4295
|
|
|
4070
4296
|
const shortcutsOverlayLines = buildHelpOverlayLines({
|
|
4071
4297
|
view: ui.view,
|
|
@@ -4083,11 +4309,11 @@ function createDashboardApp(deps) {
|
|
|
4083
4309
|
availableFlowCount: availableFlowIds.length,
|
|
4084
4310
|
hasWorktrees: worktreeSectionEnabled
|
|
4085
4311
|
});
|
|
4086
|
-
const commandStripText =
|
|
4312
|
+
const commandStripText = buildGitCommandStrip(ui.view, {
|
|
4087
4313
|
hasWorktrees: worktreeSectionEnabled,
|
|
4088
4314
|
previewOpen
|
|
4089
4315
|
});
|
|
4090
|
-
const commandLogLine =
|
|
4316
|
+
const commandLogLine = buildGitCommandLogLine({
|
|
4091
4317
|
statusLine,
|
|
4092
4318
|
activeFlow,
|
|
4093
4319
|
watchEnabled,
|
|
@@ -4173,11 +4399,41 @@ function createDashboardApp(deps) {
|
|
|
4173
4399
|
}
|
|
4174
4400
|
} else if (ui.view === 'git') {
|
|
4175
4401
|
panelCandidates = [
|
|
4402
|
+
{
|
|
4403
|
+
key: 'git-status',
|
|
4404
|
+
title: '[6]-Status',
|
|
4405
|
+
lines: gitStatusPanelLines,
|
|
4406
|
+
borderColor: 'green'
|
|
4407
|
+
},
|
|
4176
4408
|
{
|
|
4177
4409
|
key: 'git-changes',
|
|
4178
|
-
title:
|
|
4410
|
+
title: '[7]-Files',
|
|
4179
4411
|
lines: sectionLines['git-changes'],
|
|
4180
4412
|
borderColor: 'yellow'
|
|
4413
|
+
},
|
|
4414
|
+
{
|
|
4415
|
+
key: 'git-branches',
|
|
4416
|
+
title: '[8]-Local branches',
|
|
4417
|
+
lines: gitBranchesPanelLines,
|
|
4418
|
+
borderColor: 'magenta'
|
|
4419
|
+
},
|
|
4420
|
+
{
|
|
4421
|
+
key: 'git-commits',
|
|
4422
|
+
title: '[9]-Commits',
|
|
4423
|
+
lines: gitCommitsPanelLines,
|
|
4424
|
+
borderColor: 'cyan'
|
|
4425
|
+
},
|
|
4426
|
+
{
|
|
4427
|
+
key: 'git-stash',
|
|
4428
|
+
title: '[0]-Stash',
|
|
4429
|
+
lines: gitStashPanelLines,
|
|
4430
|
+
borderColor: 'blue'
|
|
4431
|
+
},
|
|
4432
|
+
{
|
|
4433
|
+
key: 'git-diff',
|
|
4434
|
+
title: '[-]-Unstaged changes',
|
|
4435
|
+
lines: gitInlineDiffLines,
|
|
4436
|
+
borderColor: 'yellow'
|
|
4181
4437
|
}
|
|
4182
4438
|
];
|
|
4183
4439
|
} else {
|
|
@@ -4214,7 +4470,7 @@ function createDashboardApp(deps) {
|
|
|
4214
4470
|
}
|
|
4215
4471
|
}
|
|
4216
4472
|
|
|
4217
|
-
if (!ui.showHelp && previewOpen && !overlayPreviewOpen) {
|
|
4473
|
+
if (!ui.showHelp && previewOpen && !overlayPreviewOpen && ui.view !== 'git') {
|
|
4218
4474
|
panelCandidates.push({
|
|
4219
4475
|
key: 'preview',
|
|
4220
4476
|
title: `Preview: ${effectivePreviewTarget?.label || 'unknown'}`,
|
|
@@ -4225,7 +4481,13 @@ function createDashboardApp(deps) {
|
|
|
4225
4481
|
|
|
4226
4482
|
if (ultraCompact) {
|
|
4227
4483
|
if (previewOpen) {
|
|
4228
|
-
panelCandidates = panelCandidates.filter((panel) =>
|
|
4484
|
+
panelCandidates = panelCandidates.filter((panel) =>
|
|
4485
|
+
panel && (
|
|
4486
|
+
panel.key === focusedSection
|
|
4487
|
+
|| panel.key === 'preview'
|
|
4488
|
+
|| (ui.view === 'git' && panel.key === 'git-diff')
|
|
4489
|
+
)
|
|
4490
|
+
);
|
|
4229
4491
|
} else {
|
|
4230
4492
|
const focusedPanel = panelCandidates.find((panel) => panel?.key === focusedSection);
|
|
4231
4493
|
panelCandidates = [focusedPanel || panelCandidates[0]];
|
|
@@ -4233,7 +4495,8 @@ function createDashboardApp(deps) {
|
|
|
4233
4495
|
}
|
|
4234
4496
|
|
|
4235
4497
|
const panels = allocateSingleColumnPanels(panelCandidates, contentRowsBudget);
|
|
4236
|
-
const
|
|
4498
|
+
const gitHierarchyLayout = ui.view === 'git'
|
|
4499
|
+
&& !ui.showHelp
|
|
4237
4500
|
&& !worktreeOverlayOpen
|
|
4238
4501
|
&& !overlayPreviewOpen
|
|
4239
4502
|
&& !ultraCompact
|
|
@@ -4253,10 +4516,11 @@ function createDashboardApp(deps) {
|
|
|
4253
4516
|
});
|
|
4254
4517
|
|
|
4255
4518
|
let contentNode;
|
|
4256
|
-
if (
|
|
4257
|
-
const preferredRightPanel =
|
|
4258
|
-
|
|
4259
|
-
|
|
4519
|
+
if (gitHierarchyLayout) {
|
|
4520
|
+
const preferredRightPanel = panelCandidates.find((panel) => panel?.key === 'git-diff')
|
|
4521
|
+
|| (previewOpen && !overlayPreviewOpen
|
|
4522
|
+
? panelCandidates.find((panel) => panel?.key === 'preview')
|
|
4523
|
+
: null);
|
|
4260
4524
|
const focusedPanel = panelCandidates.find((panel) => panel?.key === focusedSection);
|
|
4261
4525
|
const rightPanelBase = preferredRightPanel
|
|
4262
4526
|
|| focusedPanel
|
|
@@ -4307,7 +4571,9 @@ function createDashboardApp(deps) {
|
|
|
4307
4571
|
dense: densePanels,
|
|
4308
4572
|
focused: rightPanel.key === 'preview'
|
|
4309
4573
|
? paneFocus === 'preview'
|
|
4310
|
-
: (
|
|
4574
|
+
: (rightPanel.key === 'git-diff'
|
|
4575
|
+
? true
|
|
4576
|
+
: (paneFocus === 'main' && rightPanel.key === focusedSection))
|
|
4311
4577
|
})
|
|
4312
4578
|
)
|
|
4313
4579
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specsmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.55",
|
|
4
4
|
"description": "Multi-agent orchestration system for AI-native software development. Delivers AI-DLC, Agile, and custom SDLC flows as markdown-based agent systems.",
|
|
5
5
|
"main": "lib/installer.js",
|
|
6
6
|
"bin": {
|