Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) by argszero · Pull Request #664 · argszero/emrg · GitHub
Skip to content

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35) - #664

Merged
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework
Aug 11, 2026
Merged

emrg: GUI workspace panel P2 framework — resizable panel + tab bar + per-session tab state (rant 2026-08-11T12:20:35)#664
argszero merged 1 commit into
masterfrom
feature/gui-workspace-panel-p2-framework

Conversation

@argszero

Copy link
Copy Markdown
Owner

P2 slice 1 (framework) of the GUI workspace-panel rant (P1 data layer #661 merged).

P2.1 Panel structure

  • Tab bar: static Files / Artifacts tabs + opened-file tab strip (#result-tabbar, P3 viewer wires in)
  • #result-resizer absolutely positioned drag handle (out of the #app flex flow, R6-② — prevents WebContentsView bounds x offset); drag sets panel width, .dragging class suppresses the width transition (R1-①)
  • Collapse (⌘) keeps the 40px narrow bar (emrg: keep result-panel toggle visible when collapsed (rant 2026-08-10T14:11:18) #615) with width/collapse persisted separately (two localStorage keys) — expanding restores the dragged width, not the default

P2.2 Tab manager (per-session container mode, gap 5)

  • openFileTab/closeFileTab/activateTab — same-path dedupe, max 8 tabs (evicts oldest), closeable tabs, active highlight
  • openedTabsBySid / artifactsBySid state maps; switchSession(sid) shows each session's own tabs (wired into app.js switchSession/newSession); addToolResult(data, sid) classifies artifact records per event sid
  • Tool-output cards (WorkBuddy P1) intentionally retained under the Artifacts pane — removing them before P3.2's write/edit artifact registration exists would leave the panel empty across merge cycles

i18n: result.tabFiles/tabArtifacts/filesEmpty/resize zh/en.

Tests: +5 renderer smoke (tab render/switch, resizer drag + persistence + .dragging lifecycle, collapse/width separation, tab dedupe/cap-8/close, per-session isolation); harness extended with element dispatch(), window listener store, localStorage mock, new element IDs. GUI 188 → 193; pytest 694 ✓; doc guard 3/3 ✓ (README/README.cn/Agent).

Not in this slice (next): WebContentsView framework (P2.3, parallel with P3.4 HTML preview), file browser tree (P3.1), artifact list re-scope (P3.2), viewer tabs (P3.3).

…per-session tab state (rant 2026-08-11T12:20:35)

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

P2 framework slice of the workspace-panel rant: resizable panel (absolute resizer outside flex flow, .dragging transition suppression, width/collapse persisted separately), tab bar (Files/Artifacts static + opened-file tabs with dedupe/cap-8/close), per-session tab & artifact state (switchSession wiring), tool cards retained under Artifacts until P3.2 re-scopes registration. Verified: GUI 193/193 ✓ (incl. 5 new smoke tests), pytest 694 ✓, doc guard 3/3 ✓, import + --help ✓. CI test run green.

@pm25coder

Copy link
Copy Markdown
Collaborator

I tested PR #664 end-to-end on branch head 9cac295 (Windows) — the workspace panel P2 framework works well.

Verification results

  • uv run pytest tests/ → 639 passed, 55 skipped (694 total; unchanged from master, no Python changes — as expected)
  • cd emrg/gui && npm test193 tests, 192 pass, 0 fail, 1 cancelled. The 1 cancelled is the pre-existing P2 onRecovered timing flake in conn-manager.test.js:488 ("Promise resolution is still pending..."), which also cancels on master and passes in isolation — unrelated to this PR. All 5 new P2 framework tests pass.
  • node --check on all touched JS files: clean. Import + CLI checks: OK.
  • CI: gh pr checks 664 → test PASS (1m8s); PR MERGEABLE.
  • Doc counts in Agent.md / README.md / README.cn.md (193 = 43 daemon_client + 19 conn-manager + 22 app-commands + 72 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) match the actual test output; the doc-count guard is green.

Code review notes (non-blocking)

  1. Background-session artifact cards render into the active session's pane (cross-session DOM leak).addToolResult(data, sid) correctly stores into the per-sid artifactsBySid bucket, but renderCard(data) unconditionally renders into the shared #result-list DOM. So a tool_finished from a background session paints its card into the currently-active session's artifacts pane, and switchSession() does not re-render the pane from the per-session bucket. openFileTab/closeFileTab already gate DOM writes on (sid || null) === currentSid — applying the same gate to the card render (always store to the bucket, render only when the event sid is current) would make the per-session isolation claim consistent for artifacts too. P3.2 can then consume the per-sid arrays for real file registration.

  2. Two different caps for the same artifact list. DOM cards are still capped at MAX_ITEMS = 50 (P1 legacy) while the per-sid artifactsBySid buckets cap at 100. Worth aligning when P3.2 replaces the card rendering.

  3. Minor robustness nit (no change needed).#result-resizer's initial CSS right: 277px mirrors DEFAULT_WIDTH(280) − 3; it's always corrected by updateResizerPos() on init, so it only affects the initial paint — fine as-is.

Everything else looks clean: the absolutely-positioned resizer stays out of the #app flex flow (R6-②), .dragging correctly suppresses the width transition (R1-①), collapse/expand correctly keep panelWidth and collapsed persistence separate, and the tab-eviction math in the tests matches the implementation (open 3 → push 10 → first tab /tmp/f3.js).

Nice work — the framework lands cleanly and gives the P3 viewer a solid foundation to plug into.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle

Reviewed P2 framework (resizable panel + tab bar + per-session tab state) in a local worktree:

  • Tab bar (files/artifacts static tabs + open-file tabbar with dedup, 8-tab cap with oldest eviction, close button) + per-session state isolation (openedTabsBySid/artifactsBySid/activeTabBySid, switchSession wired into app.js session switch/new).
  • Resizer: absolute-positioned handle outside flex flow (avoids WebContentsView bounds x offset), .dragging suppresses width transition, width/collapsed separately persisted (localStorage), clamp 240px–45% vw.
  • Tool results now registered per-session (sid from event bridge), P1 cards retained in artifacts pane until P3.2.
  • Verification: renderer smoke 72/72 (incl. 5 new P2 tests: tab render/switch, resizer drag + persistence, collapse/expand width restore, file-tab dedup/cap/close, per-session isolation), app-commands 22/22, build-config 5/5, i18n 15/15. Doc counts consistent (GUI 187→193). (daemon-client/integration env-dependent tests need .venv — not affected by this renderer-only PR.)
    No issues found.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

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

✅ LGTM — cycle (3rd)

Re-verified against branch head 9cac295: resizable panel (absolute resizer, .dragging transition suppression, width/collapse separate persistence), tab bar + per-session tab/artifact state, addToolResult(data, sid) wiring. Local: GUI 193/193 ✓ pytest 694 ✓ doc guard 3/3 ✓. CI test run green (31461002024). Merge conditions met (3 consecutive ✅ from different cycles).

@argszero
argszero merged commit 4c71b25 into masterAug 11, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 11, 2026
…rk), #665 (P3 file browser + viewer), #666 (per-session artifact isolation) (#667)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-workspace-panel-p2-framework branch August 17, 2026 09:44
Sign up for freeto 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

@argszero@pm25coder