4runr-os 1.4.2 → 2.0.2
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/dist/ui/v3/commands/commandEngine.js +203 -0
- package/dist/ui/v3/commands/commandEngine.js.map +1 -1
- package/dist/ui/v3/tui/geometry.d.ts +56 -0
- package/dist/ui/v3/tui/geometry.d.ts.map +1 -0
- package/dist/ui/v3/tui/geometry.js +124 -0
- package/dist/ui/v3/tui/geometry.js.map +1 -0
- package/dist/ui/v3/ui/debugUtils.d.ts +61 -0
- package/dist/ui/v3/ui/debugUtils.d.ts.map +1 -0
- package/dist/ui/v3/ui/debugUtils.js +226 -0
- package/dist/ui/v3/ui/debugUtils.js.map +1 -0
- package/dist/ui/v3/ui/layout/phase1Layout.d.ts +21 -5
- package/dist/ui/v3/ui/layout/phase1Layout.d.ts.map +1 -1
- package/dist/ui/v3/ui/layout/phase1Layout.js +110 -55
- package/dist/ui/v3/ui/layout/phase1Layout.js.map +1 -1
- package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts +5 -0
- package/dist/ui/v3/ui/layout/phase1Layout.test.d.ts.map +1 -0
- package/dist/ui/v3/ui/layout/phase1Layout.test.js +92 -0
- package/dist/ui/v3/ui/layout/phase1Layout.test.js.map +1 -0
- package/dist/ui/v3/ui/phase1RuntimeClean.d.ts +4 -0
- package/dist/ui/v3/ui/phase1RuntimeClean.d.ts.map +1 -1
- package/dist/ui/v3/ui/phase1RuntimeClean.js +111 -37
- package/dist/ui/v3/ui/phase1RuntimeClean.js.map +1 -1
- package/dist/ui/v3/v1Adapters/connect.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI Geometry - Single Source of Truth for Terminal Dimensions
|
|
3
|
+
*
|
|
4
|
+
* RULES (NEVER VIOLATE):
|
|
5
|
+
* 1. Always return integers
|
|
6
|
+
* 2. Clamp to minimums (prevents 0/undefined during resize)
|
|
7
|
+
* 3. Account for margins/borders
|
|
8
|
+
* 4. Never exceed these dimensions in any widget
|
|
9
|
+
*/
|
|
10
|
+
// Absolute minimums (below this, TUI is unusable)
|
|
11
|
+
const MIN_COLS = 40;
|
|
12
|
+
const MIN_ROWS = 15;
|
|
13
|
+
// Margins (space reserved for borders/padding)
|
|
14
|
+
const HORIZONTAL_MARGIN = 0; // Blessed handles borders internally
|
|
15
|
+
const VERTICAL_MARGIN = 0; // Blessed handles borders internally
|
|
16
|
+
let lastGeometry = null;
|
|
17
|
+
/**
|
|
18
|
+
* Get current terminal geometry
|
|
19
|
+
*
|
|
20
|
+
* Priority:
|
|
21
|
+
* 1. Blessed screen object (most accurate)
|
|
22
|
+
* 2. process.stdout (fallback)
|
|
23
|
+
* 3. Clamped minimums (safety)
|
|
24
|
+
*/
|
|
25
|
+
export function getTerminalGeometry(screen) {
|
|
26
|
+
let cols;
|
|
27
|
+
let rows;
|
|
28
|
+
let source;
|
|
29
|
+
// Try blessed screen first (most accurate)
|
|
30
|
+
if (screen && typeof screen.width === 'number' && typeof screen.height === 'number') {
|
|
31
|
+
cols = screen.width;
|
|
32
|
+
rows = screen.height;
|
|
33
|
+
source = 'screen';
|
|
34
|
+
}
|
|
35
|
+
// Fallback to stdout
|
|
36
|
+
else if (process.stdout.columns && process.stdout.rows) {
|
|
37
|
+
cols = process.stdout.columns;
|
|
38
|
+
rows = process.stdout.rows;
|
|
39
|
+
source = 'stdout';
|
|
40
|
+
}
|
|
41
|
+
// Safety fallback
|
|
42
|
+
else {
|
|
43
|
+
cols = MIN_COLS;
|
|
44
|
+
rows = MIN_ROWS;
|
|
45
|
+
source = 'clamped';
|
|
46
|
+
}
|
|
47
|
+
// Clamp to minimums (prevents transient 0/undefined during resize)
|
|
48
|
+
cols = Math.max(MIN_COLS, Math.floor(cols));
|
|
49
|
+
rows = Math.max(MIN_ROWS, Math.floor(rows));
|
|
50
|
+
// Calculate safe dimensions (accounting for margins)
|
|
51
|
+
const safeCols = Math.max(MIN_COLS, cols - HORIZONTAL_MARGIN);
|
|
52
|
+
const safeRows = Math.max(MIN_ROWS, rows - VERTICAL_MARGIN);
|
|
53
|
+
const geometry = {
|
|
54
|
+
cols,
|
|
55
|
+
rows,
|
|
56
|
+
safeCols,
|
|
57
|
+
safeRows,
|
|
58
|
+
source,
|
|
59
|
+
timestamp: Date.now(),
|
|
60
|
+
};
|
|
61
|
+
lastGeometry = geometry;
|
|
62
|
+
return geometry;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get last known geometry (useful for comparisons)
|
|
66
|
+
*/
|
|
67
|
+
export function getLastGeometry() {
|
|
68
|
+
return lastGeometry;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if geometry has changed significantly
|
|
72
|
+
*/
|
|
73
|
+
export function hasGeometryChanged(screen) {
|
|
74
|
+
if (!lastGeometry)
|
|
75
|
+
return true;
|
|
76
|
+
const current = getTerminalGeometry(screen);
|
|
77
|
+
return (current.cols !== lastGeometry.cols ||
|
|
78
|
+
current.rows !== lastGeometry.rows);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Validate geometry is stable (not in resize storm)
|
|
82
|
+
*/
|
|
83
|
+
export function isGeometryStable(screen) {
|
|
84
|
+
const geo = getTerminalGeometry(screen);
|
|
85
|
+
// Reject impossible sizes (transient during resize)
|
|
86
|
+
if (geo.cols < 20 || geo.rows < 10) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fit text to width (truncate with ellipsis, never exceed)
|
|
93
|
+
*/
|
|
94
|
+
export function fitText(text, width) {
|
|
95
|
+
if (width <= 0)
|
|
96
|
+
return '';
|
|
97
|
+
if (text.length <= width)
|
|
98
|
+
return text;
|
|
99
|
+
// Reserve 3 chars for ellipsis
|
|
100
|
+
if (width <= 3)
|
|
101
|
+
return text.substring(0, width);
|
|
102
|
+
return text.substring(0, width - 3) + '...';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Clamp panel width to safe bounds
|
|
106
|
+
*/
|
|
107
|
+
export function clampPanelWidth(width, minWidth = 10) {
|
|
108
|
+
const geo = lastGeometry || getTerminalGeometry();
|
|
109
|
+
return Math.max(minWidth, Math.min(width, geo.safeCols));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clamp panel height to safe bounds
|
|
113
|
+
*/
|
|
114
|
+
export function clampPanelHeight(height, minHeight = 3) {
|
|
115
|
+
const geo = lastGeometry || getTerminalGeometry();
|
|
116
|
+
return Math.max(minHeight, Math.min(height, geo.safeRows));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Format geometry for debug output
|
|
120
|
+
*/
|
|
121
|
+
export function formatGeometry(geo) {
|
|
122
|
+
return `cols=${geo.cols} rows=${geo.rows} safeCols=${geo.safeCols} safeRows=${geo.safeRows} source=${geo.source}`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../../../src/ui/v3/tui/geometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug utilities for TUI lifecycle investigation
|
|
3
|
+
*
|
|
4
|
+
* Enable with TUI_DEBUG=1
|
|
5
|
+
* All debug output goes to Operations/eventBus, never stdout
|
|
6
|
+
*/
|
|
7
|
+
import type { Widgets } from 'neo-blessed';
|
|
8
|
+
export declare const BOOT_ID: string;
|
|
9
|
+
export declare const isDebugMode: () => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Step 1A: Track widget creation
|
|
12
|
+
*/
|
|
13
|
+
export declare function trackWidget(widget: any, type: string): void;
|
|
14
|
+
/**
|
|
15
|
+
* Step 1B: UI inventory dump
|
|
16
|
+
*/
|
|
17
|
+
export declare function dumpUIInventory(screen: Widgets.Screen): void;
|
|
18
|
+
/**
|
|
19
|
+
* Step 2A: Track listener binding
|
|
20
|
+
*/
|
|
21
|
+
export declare function trackListenerBinding(type: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Step 2B: Dump listener bindings
|
|
24
|
+
*/
|
|
25
|
+
export declare function dumpListenerBindings(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Step 3A: Track blocked stdout/stderr writes
|
|
28
|
+
*/
|
|
29
|
+
export declare function trackBlockedWrite(stream: 'stdout' | 'stderr', content: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Step 3B: Dump blocked writes
|
|
32
|
+
*/
|
|
33
|
+
export declare function dumpBlockedWrites(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Monkeypatch stdout/stderr to catch writes
|
|
36
|
+
*/
|
|
37
|
+
export declare function installStdoutMonkeypatch(): () => void;
|
|
38
|
+
export interface ResizeStats {
|
|
39
|
+
eventCount: number;
|
|
40
|
+
applyCount: number;
|
|
41
|
+
handlerBound: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Update resize stats (called from phase1RuntimeClean)
|
|
45
|
+
*/
|
|
46
|
+
export declare function updateResizeStats(stats: Partial<ResizeStats>): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get resize stats (exported for debug commands)
|
|
49
|
+
*/
|
|
50
|
+
export declare function getResizeStats(): ResizeStats;
|
|
51
|
+
/**
|
|
52
|
+
* Get current statistics
|
|
53
|
+
*/
|
|
54
|
+
export declare function getDebugStats(): {
|
|
55
|
+
bootId: string;
|
|
56
|
+
widgetCount: number;
|
|
57
|
+
listenerCount: number;
|
|
58
|
+
blockedWriteCount: number;
|
|
59
|
+
resizeStats: ResizeStats;
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=debugUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugUtils.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/ui/debugUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,eAAO,MAAM,OAAO,QAAgE,CAAC;AAkCrF,eAAO,MAAM,WAAW,QAAO,OAE9B,CAAC;AAUF;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAsB3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAqC5D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAqBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA2B3C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAsBpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAcxC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,IAAI,CAkCrD;AAGD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAQD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;CAC1B,CAQA"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug utilities for TUI lifecycle investigation
|
|
3
|
+
*
|
|
4
|
+
* Enable with TUI_DEBUG=1
|
|
5
|
+
* All debug output goes to Operations/eventBus, never stdout
|
|
6
|
+
*/
|
|
7
|
+
import { eventBus } from '../core/eventBus.js';
|
|
8
|
+
// Step 5: Single source of truth boot marker
|
|
9
|
+
export const BOOT_ID = `${Math.random().toString(36).substring(2, 8).toUpperCase()}`;
|
|
10
|
+
const widgetRegistry = new Map();
|
|
11
|
+
const listenerBindings = [];
|
|
12
|
+
let resizeHandlerCount = 0;
|
|
13
|
+
const blockedWrites = [];
|
|
14
|
+
const MAX_BLOCKED_WRITES = 50;
|
|
15
|
+
export const isDebugMode = () => {
|
|
16
|
+
return process.env.TUI_DEBUG === '1';
|
|
17
|
+
};
|
|
18
|
+
const log = (msg, level = 'INFO') => {
|
|
19
|
+
eventBus.emit({
|
|
20
|
+
tag: 'DBG',
|
|
21
|
+
msg: `[boot=${BOOT_ID}] ${msg}`,
|
|
22
|
+
level
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Step 1A: Track widget creation
|
|
27
|
+
*/
|
|
28
|
+
export function trackWidget(widget, type) {
|
|
29
|
+
if (!isDebugMode())
|
|
30
|
+
return;
|
|
31
|
+
const id = Math.random().toString(36).substring(2, 8);
|
|
32
|
+
const stack = new Error().stack || '';
|
|
33
|
+
const createdBy = stack.split('\n').slice(2, 5).join('\n ');
|
|
34
|
+
const meta = {
|
|
35
|
+
__id: id,
|
|
36
|
+
__createdAt: Date.now(),
|
|
37
|
+
__createdBy: createdBy,
|
|
38
|
+
__type: type
|
|
39
|
+
};
|
|
40
|
+
widget.__id = id;
|
|
41
|
+
widget.__createdAt = meta.__createdAt;
|
|
42
|
+
widget.__createdBy = meta.__createdBy;
|
|
43
|
+
widget.__type = type;
|
|
44
|
+
widgetRegistry.set(id, meta);
|
|
45
|
+
log(`created ${type} id=${id}`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Step 1B: UI inventory dump
|
|
49
|
+
*/
|
|
50
|
+
export function dumpUIInventory(screen) {
|
|
51
|
+
const children = screen.children || [];
|
|
52
|
+
const totalChildren = children.length;
|
|
53
|
+
log(`=== UI INVENTORY ===`);
|
|
54
|
+
log(`Total children: ${totalChildren}`);
|
|
55
|
+
// Count widgets by type
|
|
56
|
+
const typeCounts = new Map();
|
|
57
|
+
for (const child of children) {
|
|
58
|
+
const type = child.__type || 'unknown';
|
|
59
|
+
const id = child.__id || 'no-id';
|
|
60
|
+
const createdAt = child.__createdAt || 0;
|
|
61
|
+
const createdBy = child.__createdBy || 'unknown';
|
|
62
|
+
if (!typeCounts.has(type)) {
|
|
63
|
+
typeCounts.set(type, []);
|
|
64
|
+
}
|
|
65
|
+
typeCounts.get(type).push({ id, createdAt, createdBy });
|
|
66
|
+
}
|
|
67
|
+
// Report counts and duplicates
|
|
68
|
+
for (const [type, instances] of typeCounts.entries()) {
|
|
69
|
+
const count = instances.length;
|
|
70
|
+
log(`${type}: ${count} instance(s)`);
|
|
71
|
+
if (count > 1) {
|
|
72
|
+
log(` ⚠️ DUPLICATE DETECTED for ${type}:`, 'WARN');
|
|
73
|
+
for (const inst of instances) {
|
|
74
|
+
log(` - id=${inst.id} created at ${new Date(inst.createdAt).toISOString()}`);
|
|
75
|
+
log(` stack: ${inst.createdBy}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
log(`=== END INVENTORY ===`);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Step 2A: Track listener binding
|
|
83
|
+
*/
|
|
84
|
+
export function trackListenerBinding(type) {
|
|
85
|
+
if (!isDebugMode())
|
|
86
|
+
return;
|
|
87
|
+
if (type === 'resize') {
|
|
88
|
+
resizeHandlerCount++;
|
|
89
|
+
}
|
|
90
|
+
const stack = new Error().stack || '';
|
|
91
|
+
const boundBy = stack.split('\n').slice(2, 5).join('\n ');
|
|
92
|
+
const binding = {
|
|
93
|
+
type,
|
|
94
|
+
handlerNum: type === 'resize' ? resizeHandlerCount : listenerBindings.filter(b => b.type === type).length + 1,
|
|
95
|
+
boundAt: Date.now(),
|
|
96
|
+
stack: boundBy
|
|
97
|
+
};
|
|
98
|
+
listenerBindings.push(binding);
|
|
99
|
+
log(`bound ${type} handler#${binding.handlerNum} at ${new Date(binding.boundAt).toISOString()}`);
|
|
100
|
+
log(` stack: ${boundBy}`);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Step 2B: Dump listener bindings
|
|
104
|
+
*/
|
|
105
|
+
export function dumpListenerBindings() {
|
|
106
|
+
log(`=== LISTENER BINDINGS ===`);
|
|
107
|
+
log(`Total bindings: ${listenerBindings.length}`);
|
|
108
|
+
// Group by type
|
|
109
|
+
const byType = new Map();
|
|
110
|
+
for (const binding of listenerBindings) {
|
|
111
|
+
if (!byType.has(binding.type)) {
|
|
112
|
+
byType.set(binding.type, []);
|
|
113
|
+
}
|
|
114
|
+
byType.get(binding.type).push(binding);
|
|
115
|
+
}
|
|
116
|
+
for (const [type, bindings] of byType.entries()) {
|
|
117
|
+
log(`${type}: ${bindings.length} binding(s)`);
|
|
118
|
+
if (bindings.length > 1) {
|
|
119
|
+
log(` ⚠️ MULTIPLE BINDINGS for ${type}:`, 'WARN');
|
|
120
|
+
}
|
|
121
|
+
for (const binding of bindings) {
|
|
122
|
+
log(` - handler#${binding.handlerNum} at ${new Date(binding.boundAt).toISOString()}`);
|
|
123
|
+
log(` stack: ${binding.stack}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
log(`=== END LISTENER BINDINGS ===`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Step 3A: Track blocked stdout/stderr writes
|
|
130
|
+
*/
|
|
131
|
+
export function trackBlockedWrite(stream, content) {
|
|
132
|
+
const stack = new Error().stack || '';
|
|
133
|
+
const caller = stack.split('\n').slice(2, 5).join('\n ');
|
|
134
|
+
const blocked = {
|
|
135
|
+
ts: Date.now(),
|
|
136
|
+
content: content.substring(0, 120),
|
|
137
|
+
stack: caller,
|
|
138
|
+
stream
|
|
139
|
+
};
|
|
140
|
+
blockedWrites.push(blocked);
|
|
141
|
+
// Keep only last MAX_BLOCKED_WRITES
|
|
142
|
+
if (blockedWrites.length > MAX_BLOCKED_WRITES) {
|
|
143
|
+
blockedWrites.shift();
|
|
144
|
+
}
|
|
145
|
+
// Emit to operations (rate limited to prevent spam)
|
|
146
|
+
if (isDebugMode()) {
|
|
147
|
+
log(`[${stream.toUpperCase()} BLOCKED] "${blocked.content}" from: ${caller}`, 'WARN');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Step 3B: Dump blocked writes
|
|
152
|
+
*/
|
|
153
|
+
export function dumpBlockedWrites() {
|
|
154
|
+
log(`=== BLOCKED STDOUT/STDERR WRITES ===`);
|
|
155
|
+
log(`Total tracked: ${blockedWrites.length} (showing last 10)`);
|
|
156
|
+
const recent = blockedWrites.slice(-10);
|
|
157
|
+
for (let i = 0; i < recent.length; i++) {
|
|
158
|
+
const write = recent[i];
|
|
159
|
+
log(`${i + 1}. [${write.stream}] at ${new Date(write.ts).toISOString()}`);
|
|
160
|
+
log(` content: "${write.content}"`);
|
|
161
|
+
log(` stack: ${write.stack}`);
|
|
162
|
+
}
|
|
163
|
+
log(`=== END BLOCKED WRITES ===`);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Monkeypatch stdout/stderr to catch writes
|
|
167
|
+
*/
|
|
168
|
+
export function installStdoutMonkeypatch() {
|
|
169
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
170
|
+
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
171
|
+
// Patch stdout
|
|
172
|
+
process.stdout.write = function (chunk, ...args) {
|
|
173
|
+
const content = String(chunk);
|
|
174
|
+
// Allow ANSI escape codes (cursor control) and blessed writes
|
|
175
|
+
const stack = new Error().stack || '';
|
|
176
|
+
const isBlessed = stack.includes('neo-blessed') || stack.includes('Program.prototype');
|
|
177
|
+
const isAnsiEscape = /^\x1b\[[\d;]*[A-Za-z]/.test(content);
|
|
178
|
+
if (isBlessed || isAnsiEscape) {
|
|
179
|
+
return originalStdoutWrite(chunk, ...args);
|
|
180
|
+
}
|
|
181
|
+
// Block and track
|
|
182
|
+
trackBlockedWrite('stdout', content);
|
|
183
|
+
return true; // Pretend success
|
|
184
|
+
};
|
|
185
|
+
// Patch stderr (less strict - allow it but track)
|
|
186
|
+
process.stderr.write = function (chunk, ...args) {
|
|
187
|
+
const content = String(chunk);
|
|
188
|
+
trackBlockedWrite('stderr', content);
|
|
189
|
+
return originalStderrWrite(chunk, ...args);
|
|
190
|
+
};
|
|
191
|
+
// Return cleanup function
|
|
192
|
+
return () => {
|
|
193
|
+
process.stdout.write = originalStdoutWrite;
|
|
194
|
+
process.stderr.write = originalStderrWrite;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
let resizeStats = {
|
|
198
|
+
eventCount: 0,
|
|
199
|
+
applyCount: 0,
|
|
200
|
+
handlerBound: false
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Update resize stats (called from phase1RuntimeClean)
|
|
204
|
+
*/
|
|
205
|
+
export function updateResizeStats(stats) {
|
|
206
|
+
resizeStats = { ...resizeStats, ...stats };
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get resize stats (exported for debug commands)
|
|
210
|
+
*/
|
|
211
|
+
export function getResizeStats() {
|
|
212
|
+
return { ...resizeStats };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get current statistics
|
|
216
|
+
*/
|
|
217
|
+
export function getDebugStats() {
|
|
218
|
+
return {
|
|
219
|
+
bootId: BOOT_ID,
|
|
220
|
+
widgetCount: widgetRegistry.size,
|
|
221
|
+
listenerCount: listenerBindings.length,
|
|
222
|
+
blockedWriteCount: blockedWrites.length,
|
|
223
|
+
resizeStats: getResizeStats()
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=debugUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugUtils.js","sourceRoot":"","sources":["../../../../src/ui/v3/ui/debugUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Phase 1 Layout Calculator
|
|
2
|
+
* Phase 1 Layout Calculator - FINAL BULLETPROOF EDITION
|
|
3
3
|
*
|
|
4
4
|
* Fixed hub layout with 7 boxes:
|
|
5
5
|
* - Left column (3 stacked): POSTURE, RESOURCES, ASSETS
|
|
6
6
|
* - Center (1): OPERATIONS
|
|
7
7
|
* - Right column (2 stacked): NETWORK, CAPABILITIES
|
|
8
8
|
* - Bottom bar (1): COMMAND LINE
|
|
9
|
+
*
|
|
10
|
+
* CRITICAL RULES (NEVER VIOLATE):
|
|
11
|
+
* 1. Use geometry.ts for all dimension queries
|
|
12
|
+
* 2. Total width MUST NOT exceed safeCols
|
|
13
|
+
* 3. Total height MUST NOT exceed safeRows
|
|
14
|
+
* 4. No floating point math - only integers
|
|
15
|
+
* 5. Right column width calculated as REMAINDER (prevents rounding errors)
|
|
16
|
+
* 6. All positions validated before return
|
|
17
|
+
* 7. All text must use fitText() to prevent overflow
|
|
9
18
|
*/
|
|
19
|
+
import type { Widgets } from 'neo-blessed';
|
|
10
20
|
export interface BoxRect {
|
|
11
21
|
top: number;
|
|
12
22
|
left: number;
|
|
@@ -27,10 +37,16 @@ export interface LayoutResult {
|
|
|
27
37
|
errorMessage?: string;
|
|
28
38
|
layout?: Phase1Layout;
|
|
29
39
|
}
|
|
30
|
-
export declare const MIN_WIDTH =
|
|
31
|
-
export declare const MIN_HEIGHT =
|
|
40
|
+
export declare const MIN_WIDTH = 80;
|
|
41
|
+
export declare const MIN_HEIGHT = 24;
|
|
32
42
|
/**
|
|
33
|
-
* Compute Phase 1 layout
|
|
43
|
+
* Compute Phase 1 layout - FINAL BULLETPROOF IMPLEMENTATION
|
|
44
|
+
*
|
|
45
|
+
* This function GUARANTEES:
|
|
46
|
+
* - Never exceeds terminal dimensions
|
|
47
|
+
* - Works on ANY terminal size >= MIN_WIDTH x MIN_HEIGHT
|
|
48
|
+
* - Integer math only (no rounding errors)
|
|
49
|
+
* - Uses geometry.ts as single source of truth
|
|
34
50
|
*/
|
|
35
|
-
export declare function computePhase1Layout(width: number, height: number): LayoutResult;
|
|
51
|
+
export declare function computePhase1Layout(width: number, height: number, screen?: Widgets.Screen): LayoutResult;
|
|
36
52
|
//# sourceMappingURL=phase1Layout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phase1Layout.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/ui/layout/phase1Layout.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"phase1Layout.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/ui/layout/phase1Layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAGD,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAC;AAM7B;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,YAAY,CAwJxG"}
|