Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
5d1afc1
Add solution skeleton: projects, central package management, and root…
ImanEstiri Oct 24, 2026
6f509eb
Add core enums for AgentScript commands, statuses, and agent events
ImanEstiri Oct 24, 2026
c3ca610
Add AgentScript v1 parser, validator, and format guard with tests
ImanEstiri Oct 24, 2026
6cda371
Add workspace execution layer: git service, guards, executors, and ba…
ImanEstiri Oct 24, 2026
fb7832f
Add phase 3 tests and harden sandbox, slug builder, and policy
ImanEstiri Oct 24, 2026
62b9b59
.
ImanEstiri Oct 24, 2026
30c9dfa
Add snapshot service (bat runner, filter, chunking) and result formatter
ImanEstiri Oct 25, 2026
1653457
Add chat provider layer: Playwright driver, selectors catalog, reply …
ImanEstiri Oct 25, 2026
6d2e79f
Add agent loop, session store, configuration, and system prompt
ImanEstiri Oct 25, 2026
39c5ee2
Add the keyless CLI: commands, Spectre UI implementation, and tool pa…
ImanEstiri Oct 25, 2026
0938497
Add documentation and finish the final checklist review
ImanEstiri Oct 25, 2026
534b921
Make the workspace path the first input instead of assuming the curre…
ImanEstiri Oct 25, 2026
1f4b411
Fix CLI crash: never run prompts under a live display; make turns non…
ImanEstiri Oct 25, 2026
ecacb42
Fix reply-identity bug: never return the previous assistant reply
ImanEstiri Oct 25, 2026
2cf1aff
.
ImanEstiri Oct 26, 2026
ef24294
Handle line endings: workspace CRLF files survive model LF text
ImanEstiri Oct 26, 2026
2564b58
Make approval behavior consistent and safer
ImanEstiri Oct 26, 2026
9067199
Harden CLI console handling and make failures diagnosable
ImanEstiri Oct 26, 2026
65a4dce
Harden send-button and toggle selectors against the real DOM sample
ImanEstiri Oct 26, 2026
964022b
Add /workspace and /help slash commands to the interactive session
ImanEstiri Oct 26, 2026
af2528b
Fix send-logic risks: no duplicate sends, no duplicate attachments
ImanEstiri Oct 26, 2026
7f2a681
Add keyless doctor: live selector check without changing the chat
ImanEstiri Oct 26, 2026
a2f5278
Make IChatPage async with cancellation and improve failure diagnostics
ImanEstiri Oct 27, 2026
c7956b9
Sanitize doctor captures: mask all personal text and identifying attr…
ImanEstiri Oct 27, 2026
20fe134
Treat file-input listing as 'selected', not 'uploaded': wait for send…
ImanEstiri Oct 27, 2026
f4473ca
Remove remaining sync-over-async; enforce with a source-scan test
ImanEstiri Oct 27, 2026
a2bfb6b
Redesign browser connection: dedicated profile, probe/launch/attach, …
ImanEstiri Oct 27, 2026
e7ff40e
Git workflow UX: numbered menus, auto init, no-origin push skip
ImanEstiri Oct 27, 2026
ade53d3
Reply reading via the message Copy button (ReplySource) with DOM fall…
ImanEstiri Oct 27, 2026
0e8cee8
Docs written once: README + docs/* rewrite, consistency tests, DOCS-T…
ImanEstiri Oct 27, 2026
2b97c70
Fix phantom cancel; native C# snapshot analyzer replaces the workspac…
ImanEstiri Oct 27, 2026
d905f5d
Fix paperclip click (OS file dialog) and Enter-only send retry
ImanEstiri Oct 27, 2026
376d55d
docs: send-button selector row and Enter-only retry note
ImanEstiri Oct 27, 2026
40de88e
Remove DOCS-TODO (follow-up fixes documented)
ImanEstiri Oct 27, 2026
3e0ec18
Clean up dead exception filters and a nullable warning from the captu…
ImanEstiri Oct 27, 2026
13566ec
First message = AgentScript rules alone; visible reply trail; hidden …
ImanEstiri Oct 27, 2026
881d907
Prompt lessons from the live run; keep the chat open across turns; au…
ImanEstiri Oct 27, 2026
fe7efca
Workspace capabilities, no-git mode, change tracking, dirty-menu rules
ImanEstiri Oct 27, 2026
134aa88
Command risk classifier and failure-reason model (Task 2 part 1)
ImanEstiri Oct 28, 2026
b8ff945
Command execution model: risk classifier wiring, failure modes, @@nex…
ImanEstiri Oct 28, 2026
36fd7d1
Format reliability: lenient one-line payloads, per-message reminder, …
ImanEstiri Oct 28, 2026
a18ebf7
Browser window behavior: never un-minimize during normal operation
ImanEstiri Oct 28, 2026
35ce80e
Reply panel policy: raw reply shown only when invalid or with -v; com…
ImanEstiri Oct 28, 2026
d2cbb1b
Chat lifecycle: MaxTurnsPerChat, auto new chat, ChatLimitNotice selector
ImanEstiri Oct 28, 2026
c61a718
Task 7: docs written once — README + docs/* + CLI README + consistenc…
ImanEstiri Oct 28, 2026
5431e25
Fix window un-minimize: remove focus from normal operation; add ITimi…
ImanEstiri Oct 28, 2026
c4c87cb
Turn summary with changed files; reply panel policy (invalid-only or -v)
ImanEstiri Oct 28, 2026
44f816c
Docs: browser window config, no-git mode, chat lifecycle; DOCS-TODO r…
ImanEstiri Oct 28, 2026
5da4d26
Add /newchat slash command; chat lifecycle; classifier 108 tests
ImanEstiri Oct 28, 2026
69bc184
Fix dry-run sending to chat: guard request-send with if (!dryRun)
ImanEstiri Oct 28, 2026
513ab2c
Enforce strict batch failure precedence inside the command loop
ImanEstiri Oct 28, 2026
cead72d
Report a missing program as KA_COMMAND_NOT_FOUND, not KA_INTERNAL
ImanEstiri Oct 28, 2026
9a2e998
Validate control directives on parse-valid replies too
ImanEstiri Oct 28, 2026
193bb88
Fix MaxTurnsPerChat ordering, TurnsInChat counting, AgentChangedPaths…
ImanEstiri Oct 28, 2026
f2ce27c
Reset the copy-capture buffer before each capture attempt
ImanEstiri Oct 28, 2026
abc9d2f
Report the send button as disabled when aria-disabled is set
ImanEstiri Oct 28, 2026
6f14f6d
List @@movefile and @@next in the system prompt and format correction
ImanEstiri Oct 28, 2026
5e13a08
Include only known extensions in the code dump
ImanEstiri Oct 28, 2026
b1834b8
Populate AgentTurnResult.ChangeSet so the CLI can show changed files
ImanEstiri Oct 28, 2026
3e86195
Compare the dirty-menu skip against freshly read porcelain
ImanEstiri Oct 28, 2026
58eee01
Log reply-received once and show TurnFinished once per turn
ImanEstiri Oct 28, 2026
243cae6
Correct the raw-reply comment: no -v path exists
ImanEstiri Oct 28, 2026
017a92a
Time every chat phase and add a --timing flag
ImanEstiri Oct 28, 2026
8c26e63
Add approval counts and diff stat to the turn summary
ImanEstiri Oct 28, 2026
94f4669
Set the DeepThink and Search toggles on the first message of a new chat
ImanEstiri Oct 28, 2026
8020069
Apply Browser.WindowMode when auto-launching Chrome
ImanEstiri Oct 28, 2026
b140eab
Honor Snapshot.RefreshAfterEachBatch between batches
ImanEstiri Oct 28, 2026
b88918a
Produce a ChangedFiles attachment in TreeAndChanged mode
ImanEstiri Oct 28, 2026
fa503ce
Detect and recover from chat length exhaustion
ImanEstiri Oct 28, 2026
85473d0
Prove /newchat's clear leads to a new chat on the next turn
ImanEstiri Oct 28, 2026
6a5cc32
Treat shell machinery and Unix paths as Risky in the risk classifier
ImanEstiri Oct 28, 2026
488748b
Split policy segments with quote awareness
ImanEstiri Oct 28, 2026
b665c42
Reject ADS, UNC and device paths in the path sandbox
ImanEstiri Oct 28, 2026
1b6d201
Refuse link escapes in backup and undo
ImanEstiri Oct 28, 2026
86afdcc
Prove file contents are data, never AgentScript commands
ImanEstiri Oct 28, 2026
9e27027
Validate movefile paths in the format guard
ImanEstiri Oct 28, 2026
9114374
Confirm file moves in Ask mode and show the diff
ImanEstiri Oct 28, 2026
35a33fb
Make keyless undo reverse newfile and movefile
ImanEstiri Oct 28, 2026
680592e
Parallel selector waits, instant checks, positive-first login probe
ImanEstiri Oct 29, 2026
e08d828
Fake-page round-trip tests for the wait fixes
ImanEstiri Oct 29, 2026
b932e04
Graceful Ctrl+C in the interactive session
ImanEstiri Oct 29, 2026
ef63a99
Consistent step renderer for progress output
ImanEstiri Oct 29, 2026
753ec0d
Document the responsiveness, control and timing behavior
ImanEstiri Oct 29, 2026
81ad797
Pin the per-phase session timings through the fake page
ImanEstiri Oct 29, 2026
29ea43a
Parallel-wait the remaining sequential selector waits
ImanEstiri Oct 29, 2026
bb4b9d4
Visibility-aware combined wait: a hidden first match cannot mask a la…
ImanEstiri Oct 29, 2026
7d1674f
Time the tab-open phase of the browser connection
ImanEstiri Oct 29, 2026
b84317e
Round-trip tests prove absent fallback lists cost one wait
ImanEstiri Oct 29, 2026
4117f69
Docs must match the real KeylessOptions defaults, verified by test
ImanEstiri Oct 29, 2026
2255729
Never send secrets to the chat through snapshot attachments
ImanEstiri Oct 29, 2026
e5783f2
Stop when the debugging port answers but CDP attach fails
ImanEstiri Oct 29, 2026
c38a18e
A turn that stops early exits with code 2
ImanEstiri Oct 29, 2026
3f20dd6
Corrupt session.json and failing log writes never crash a turn
ImanEstiri Oct 29, 2026
f02cece
Commands after @@done are skipped, not executed
ImanEstiri Oct 29, 2026
9911c2a
Redact secrets from command output in the turn log
ImanEstiri Oct 29, 2026
ed484e5
Use the catalog selectors for the input editability check
ImanEstiri Oct 29, 2026
403ee45
Defect sweep: 4 confirmed fixes, 2 invariants, 2 already covered
ImanEstiri Oct 29, 2026
f0e8bce
The application version comes from one place: Directory.Build.props
ImanEstiri Oct 29, 2026
0a2cee4
Make publish.ps1 safe: SkipPush without a key, exact package name
ImanEstiri Oct 29, 2026
859599f
Document the queued-fix behaviors (DOCS-TODO applied and deleted)
ImanEstiri Oct 29, 2026
ee5ac77
Copy-capture click loop: one combined wait, not 3s per fallback
ImanEstiri Oct 29, 2026
9bcbf3b
Four small verified fixes
ImanEstiri Oct 29, 2026
c3fea23
ConfirmSendAsync rework: richer signals, safer retries, attempt diagn…
ImanEstiri Oct 30, 2026
3922ea3
Run command lines through the platform shell
ImanEstiri Oct 30, 2026
d97b55a
New command @@mkdir <path>
ImanEstiri Oct 30, 2026
96a284b
Timing accuracy: user-wait split, concurrent cached env probe, number…
ImanEstiri Oct 30, 2026
2a23612
Copy attempt facts: timed phase, skip/reject reasons, doctor candidat…
ImanEstiri Oct 31, 2026
f513212
WPF UI Phase 1: skeleton and solution wiring
ImanEstiri Oct 31, 2026
5bcebfd
WPF UI Phase 2: theme dictionaries (Midnight & Champagne)
ImanEstiri Oct 31, 2026
3745eb5
WPF UI Phase 3: shell, chrome and backdrop
ImanEstiri Oct 31, 2026
b81cf2e
Add WPF Phase 4: MVVM infrastructure, navigation, dispatcher, setting…
ImanEstiri Oct 31, 2026
bed0b0d
Add WPF Phase 5: dialog host, WpfUserInterface, feed and busy infrast…
ImanEstiri Oct 31, 2026
5077efd
Add WPF Phase 6: agent page, activity feed, composer, AgentRunner int…
ImanEstiri Oct 31, 2026
ad2f434
Add WPF Phase 7: diff viewer with LCS line diff, collapsible cards, t…
ImanEstiri Oct 31, 2026
13cc602
Add WPF Phase 8: workspace page, recents, folder picker, workspace he…
ImanEstiri Oct 31, 2026
17f6a05
Add WPF Phase 9: doctor, undo, chrome, settings, and about pages
ImanEstiri Oct 31, 2026
406d415
Add WPF Phase 10: polish, shortcuts, RTL detection, window persistenc…
ImanEstiri Oct 31, 2026
e7896fc
Add WPF Phase 11: publish-wpf.ps1 with Playwright output verification
ImanEstiri Oct 31, 2026
b48de06
Add WPF Phase 12: docs/wpf-ui.md, README WPF section, documented-toke…
ImanEstiri Oct 31, 2026
adf599e
Fix WPF startup crash: animation storyboards must precede the styles …
ImanEstiri Oct 31, 2026
16291a8
Fix startup StackOverflowException: resolve theme-internal resource r…
ImanEstiri Oct 31, 2026
9eb33db
Fix WPF startup XamlParseException: suffix Color keys, guard against …
ImanEstiri Oct 31, 2026
9ed9532
Reject payload markers chained with @@ commands on one line; harden t…
ImanEstiri Oct 31, 2026
c2e5d35
Composer reset, offline detection, and failed-attachment handling for…
ImanEstiri Nov 1, 2026
be09f5e
Environment probing with fail-fast tool_missing, per-session Tools li…
ImanEstiri Nov 1, 2026
df62109
Agent.Pace (Step/Balanced/Batch): per-response command limits, pace r…
ImanEstiri Nov 1, 2026
676a362
Hardening: KA_CANCELLED on the dirty-tree cancel path, IEnvironmentTo…
ImanEstiri Nov 1, 2026
f66f552
WPF polish: spacing, control heights, focus rings, empty states, tool…
ImanEstiri Nov 1, 2026
7eb461f
Tidy DOCS-TODO after the polish round
ImanEstiri Nov 1, 2026
958ce5e
Documentation written from the final code; DOCS-TODO applied and remo…
ImanEstiri Nov 1, 2026
c117f03
Composer suspect safety net: reload on next send after failed attachm…
ImanEstiri Nov 1, 2026
6150d18
P0-P5: copy-button path, parser repair, lenient shapes, stall fixes, …
ImanEstiri Nov 1, 2026
619ff3a
Fix schema migration, prompt contradiction, Playwright timeouts, copy…
ImanEstiri Nov 1, 2026
6131306
Fix turn slowness (30s selector probes, copy waits) and minimize pers…
ImanEstiri Nov 2, 2026
65fd5ca
Keep minimized-Chrome streams complete: occlusion flags + truncation …
ImanEstiri Nov 2, 2026
acc2870
Chrome stays minimized for the whole turn: silent truncation polling
ImanEstiri Nov 3, 2026
20a98f0
Chrome window show/hide (keyless show|hide) + login shows the window
ImanEstiri Nov 3, 2026
54fc53e
Offscreen everywhere: WindowMode default, hide instead of minimize, H…
ImanEstiri Nov 3, 2026
2a199c1
Offscreen is occluded too: TinyCorner default, tiny-corner hide, chro…
ImanEstiri Nov 3, 2026
17854bc
TinyCorner sits in the WORK AREA, not behind the taskbar
ImanEstiri Nov 3, 2026
b808a43
One shared window mover: verified CDP moves, Win32 both directions, h…
ImanEstiri Nov 3, 2026
8ca7885
Known-stale-default upgrades: old default literals never override new…
ImanEstiri Nov 3, 2026
b4fcff7
selectors.json versioning: stale catalogs merge up, old copy-button s…
ImanEstiri Nov 3, 2026
ef17692
Truncation budget is wall-clock time, with real poll spacing
ImanEstiri Nov 3, 2026
cf3b5fb
Per-Monitor-V2 DPI awareness + launch-geometry diagnostics
ImanEstiri Nov 4, 2026
29b0e71
WPF: explicit PerMonitorV2 app.manifest (ApplicationHighDpiMode embed…
ImanEstiri Nov 4, 2026
7b48c31
Close Chrome: graceful CDP close + tree-kill fallback, WPF button, Ap…
ImanEstiri Nov 4, 2026
8c89547
Snapshot size budget: TreeAndChanged default, total ceiling, per-file…
ImanEstiri Nov 4, 2026
23f1543
NuGet publishing: icons, packaging metadata, publish scripts, per-pro…
ImanEstiri Nov 5, 2026
6f4040b
Publish readiness: real ICO, WPF IsPackable=false, version-bump dry-run
ImanEstiri Nov 5, 2026
ef579c1
slnx - refactoring folder struc
ImanEstiri Nov 5, 2026
5e12ef2
Merge origin/main into feature/keyless-agent
ImanEstiri Nov 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions DOCS-TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# DOCS-TODO

- P0 copy-button path: MessageCopyButton selectors replaced (aria-label/title "copy" with the case-insensitive `i` flag, `.ds-message` scoping) plus a GetByRole accessibility fallback (direct + after hover) in ClickNewestCopyControlAsync; WaitForMessageCopyButtonAsync logs the tried selectors and the `keyless doctor --capture` hint when nothing matches — selectors are UNVERIFIED until run against the live chat; verify with `keyless doctor --capture` (MessageCopyButton must be MATCHED) and confirm the next turn log shows Source "Copy".
- P1 parser repair: RepairKnownCorruptions splits close-marker+@@-command and @@end+@@-command chains onto separate lines (fixpoint, up to 3 passes); the legacy ParseBadMarker rejection test in AgentScriptParserTests was replaced by the repaired-outcome test — no docs change needed, but the AgentScript spec's format-error list should mention the auto-repair.
- P2 lenient shapes: "@@say hello" (argument becomes MSG), one outer code fence stripped from CONTENT, say-only replies no longer rejected (KA_PARSE_SAY_ONLY is now unused by the validator but stays documented in the catalog) — document the accepted one-line shapes in docs/agentscript-spec.md.
- P4 stalls: defaults ReplyTimeoutSeconds 180, SendConfirmSeconds 8, UploadWaitSeconds 15 (docs/configuration.md updated); generation waits in ResetComposerAsync/WaitForGenerationAsync capped at 10 s; IsSendEnabledAsync skips the paperclip button in one round trip; StopIndicator selectors replaced (div:has(textarea) scoping — UNVERIFIED until live chat).
- P5 minimize: no URL in the Chrome launch arguments (Chrome 136+ ignores --start-minimized with a URL); MinimizeWindowAsync falls back to Win32 ShowWindow through the launched process id — document the two-step minimize in docs/browser-automation.md.
- A1 selector-probe timeouts: EvaluateAsync hard-capped at 1.5 s; IsSendEnabledAsync skips absent selectors via an instant CountAsync (no element resolution, no EvaluateAsync) while keeping the paperclip skip and the null=undetectable contract; SetInputFiles 5 s, accessibility-hover 2 s, page.SetDefaultTimeout(5000) on every connection path as the safety net; IsSendEnabledAsync/ResetComposerAsync log a warning above 2 s (with the slowest selector index). The 60/120/180 s send/upload multiples should be gone — UNVERIFIED until a live run's --timing table shows no phase at or above 30 s.
- A2 copy-button cost: first copy wait capped at 3 s; a per-session circuit breaker (_copyButtonBroken) skips the whole copy path after the first miss (origin 'copy disabled after the first miss this session'), reset naturally by a new session/run or a doctor --capture re-check; Browser.ReplySource=Dom still short-circuits with zero waits. Copy behavior UNVERIFIED until run against the live chat (the selector may still not match — the circuit breaker only caps the cost).
- B minimize persistence: Target.createTarget now sends background=true (Chrome activated the new tab and restored the minimized window); the minimize runs IMMEDIATELY after OpenChatTabAsync (when WindowMode=Minimized and MinimizeAfterLogin) and again after login; CDP verifies via Browser.getWindowBounds read-back with a normal->minimized recovery, up to 3 attempts; the Win32 fallback was made real (ChromeWindowMinimizer: EnumWindows over Chrome_WidgetWin_1 windows owned by our chrome.exe processes — the launched PID's descendant tree or the --user-data-dir/--remote-debugging-port command-line match — then ShowWindow(SW_MINIMIZE)). FocusTabAsync/BringToFront stays login-only. UNVERIFIED until run on the live chat (window must minimize within a few seconds and STAY minimized during sends).
- Truncated replies under minimize: Chrome launch gains --disable-features=CalculateNativeWinOcclusion,IntensiveWakeUpThrottling (Windows 11 throttles minimized windows at the feature level even with the classic flags), --disable-ipc-flooding-protection, --disable-hang-monitor — the window still minimizes, the renderer keeps streaming. WaitForReplyAsync rejects an AgentScript reply without a trailing @@eof (keeps polling silently, no correction message), logs 'Truncated reply detected (attempt N)' + a 'reply-truncated' turn event (FocusTriggered:false) per detection, and fails with KA_REPLY_TRUNCATED at the 20th detection with a hint to enable Browser.AutoFocusOnTruncation or WindowMode:Offscreen — only when AutoFocusOnTruncation=true does the window focus ONCE at the fifth detection (opt-in; default path never un-minimizes, Chrome stays minimized for the whole turn; the CLI confirmation prompt rings a terminal bell instead of raising a window). UNVERIFIED until a live run: fresh-workspace turn must end with Reply ending '@@eof', no 'Block newfile opened on line 1 is never closed' correction, and a manual mid-turn minimize must still produce a complete reply.
- Chrome window show/hide: IChromeWindowController (ChromeWindowController.cs) moves the window by pure CDP setWindowBounds (show: normal @100,100 1280x900 + Target.activateTarget; hide: normal @-32000,-32000; optional --peek returns offscreen after N seconds) — 'keyless show/hide <workspace>', a Show Chrome button on the doctor page, and 'keyless chrome' now show the window after connecting. The login flow shows the window instead of BringToFront (FocusTabAsync remains only as the IChatPage contract, unused by the provider). UNVERIFIED until live: show/hide during a running turn must not disturb send-attempt timing, and the Offscreen login flow must be visible.
- True-minimize root cause (turn-16): WindowMode default was still 'Minimized' and the MinimizeAfterLogin path sent CDP windowState:'minimized', which Chrome throttles regardless of startup position — the stream then truncated 20x. Now: WindowMode default 'Offscreen'; 'Minimized' is backward-compatible and ALSO means offscreen (launch flags --window-position=-32000,-32000 --window-size=1280,900); HideWindowAsync (renamed from MinimizeWindowAsync) moves the window offscreen with windowState:'normal' and verifies via getWindowBounds read-back (left/top -32000), and the Win32 fallback uses SW_HIDE instead of SW_MINIMIZE. Doctor page has Start/Show/Hide Chrome buttons. UNVERIFIED until live: zero reply-truncated on a full turn, taskbar click produces nothing while offscreen, show at (100,100) 1280x900 not fullscreen.
- Offscreen STILL throttles (turn-17: 20 truncations with the occlusion flag present; turn-18: visible window OK, hidden -> truncating again): Chrome treats fully offscreen positions as occluded regardless of --disable-features=CalculateNativeWinOcclusion. Fix: WindowMode default 'TinyCorner' (80x80 square, bottom-right of the REAL primary screen bounds via GetSystemMetrics, never hardcoded); new modes TinyCorner/EdgePeek (10x10 sliver, may still be throttled); every hide path (MinimizeWindowAsync successor, keyless hide, peek return) now moves to the same tiny corner instead of -32000; the launch command line is logged and emitted as a 'chrome-launched' turn event; 'keyless diagnostics chrome' prints the running Chrome's command line (Get-CimInstance) with a flag verdict. UNVERIFIED until live: TinyCorner/EdgePeek truncation counts (expected zero / near-zero), the visible 80x80 square during a turn, and whether EdgePeek's 10x10 passes Chrome's occlusion heuristic.
- selectors.json versioning: CatalogVersion 2 in the embedded default + MergeAsync in SelectorsCatalog - a workspace file with an older/missing version is backed up (selectors.json.v<N>.bak) and merged: keys whose value matches ANY version ever shipped (ShippedValues table generated from git history; MessageCopyButton/StopIndicator/SendButton/DeepThinkToggle/SearchToggle/MessageItems) are refreshed to the current embedded values, genuine customizations and workspace-only keys survive, missing keys added; keyless selectors refresh <workspace> forces the merge; the copy-button miss warning points at it. UNVERIFIED until live: a real turn in an OLD workspace must show reply-source Source: Copy (the circuit breaker resets per session).
- Truncation budget is WALL-CLOCK now: the old fixed 20-attempt count burned out in ~2-4s (detections ran back-to-back with no poll delay) while a stream that resumed after ~8s was still killed. New Browser.TruncationBudgetSeconds (default 20): the wait fails with KA_REPLY_TRUNCATED only when the time since the FIRST truncation detection exceeds it; detections are spaced by the normal poll delay (no busy-loop); the reply-truncated event carries ElapsedSeconds; AutoFocusOnTruncation fires at 25% of the budget instead of attempt 5. UNVERIFIED until live: an 8-10s slow stream must now complete instead of failing, and ElapsedSeconds must grow in step with real time in turn-N.jsonl.
- DPI + launch-geometry diagnostics: a live chrome-launched log showed the RAW screen size (1840,1000 on 1920x1080) despite the SPI_GETWORKAREA fix - the process was not DPI-aware, so the screen APIs returned OS-virtualized values at non-100% scale. The CLI now embeds an app.manifest with dpiAwareness=PerMonitorV2 (ApplicationManifest in the csproj; verified embedded in the exe) and the WPF csproj sets ApplicationHighDpiMode=PerMonitorV2. Chrome launches now log raw screen vs work area side by side (plus RawScreenSize/WorkAreaSize fields in the chrome-launched turn event), and after the launch attach the connector locates the real HWND (FindOurChromeWindows, polled up to 3s), GetWindowRects it, logs actual-vs-requested (8px tolerance, MISMATCH warning on drift, chrome-window-bounds turn event). UNVERIFIED until live on the test machine: Raw/WorkArea differ by the taskbar height, --window-position uses work-area coordinates, actual GetWindowRect matches within pixels, and the 80x80 square is visibly on the desktop - note the machine resolution + scale factor first.
- Chrome CLOSE path: IChromeWindowController.CloseAsync (options, allowAttached=false) - graceful CDP Browser.close (whole browser, profile flushed), the debug port polled ~3s to confirm, then a tree-kill fallback (Process.Kill(entireProcessTree)) of every chrome.exe whose command line carries OUR profile dir; a Chrome matched only by our port (user-launched, no profile) is REFUSED unless allowAttached - same ownership rule as AttachedToRunningChrome. Ownership matches RUNNING command lines (ChromeWindowMover.GetChromeProcessInfos), so it works after an app restart without a session PID. WPF: Close Chrome button (4th command, cross-disabling) + App.OnExit always-on safety net (4s bounded, distinct from CloseChromeOnExit which still only gates per-turn session disposal). UNVERIFIED until live: start-via-app -> normal app exit leaves no chrome.exe for the profile; Close Chrome button then Start Chrome relaunches cleanly; a manually-attached Chrome is untouched in both cases.
- Snapshot size budget: Snapshot.Mode defaults to TreeAndChanged (Full still supported); a new total ceiling MaxTotalAttachmentChars (400k chars) caps EVERYTHING attached to one turn - when exceeded the tree stays complete, the dump keeps only request-referenced files, and everything else becomes per-folder omission notes + a snapshot-budget-exceeded turn event (original total, ceiling, omitted count/chars). TreeAndChanged no-baseline/empty-diff falls through the SAME budget path (first turn is never an unlimited full dump). ExcludeFilePatterns (*.min.js/*.min.css/lock files/designer/migration snapshots) drop generated files from the attached dump; MaxDumpedFileChars (50k) replaces oversized files with heading + placeholder. Change-stash: the TreeAndChanged diff is computed at refresh time BEFORE the baseline is overwritten (the old code diffed against a just-captured baseline, so changed-files.txt could never list real changes). UNVERIFIED until live: a real first turn on a large workspace stays under the ceiling with referenced files present, and the second turn shows the changed-files diff.
53 changes: 25 additions & 28 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
<Project>

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>All</AnalysisMode>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<InvariantGlobalization>false</InvariantGlobalization>
<NuGetAudit>false</NuGetAudit>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<!-- CA1031: boundary methods intentionally convert any exception into an Outcome failure.
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>All</AnalysisMode>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<InvariantGlobalization>false</InvariantGlobalization>
<NuGetAudit>false</NuGetAudit>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<!-- CA1031: boundary methods intentionally convert any exception into an Outcome failure.
CA1040: IService is a deliberate marker interface (DepLens convention).
CA1303: the CLI is not a localized application.
CA1307/CA1308: StringComparison overload suggestions on char comparisons are noise here.
CA1822: stateless runners stay instance methods for injection symmetry.
S3267: "simplify loop" suggestions fight legitimate async loops with early returns.
CA1707, S1135, CA1861: style choices mirrored from the reference repository. -->
<NoWarn>$(NoWarn);CA1873;CA2007;CA1031;CA1040;CA1303;CA1307;CA1308;CA1822;S3267;CA1707;S1135;CA1861;CA1056;CA1054;CA2000;CA5394;S1075;S2245</NoWarn>
</PropertyGroup>
<ItemGroup Condition="'$(MSBuildProjectExtension)' != '.dcproj' and '$(MSBuildProjectName)' != 'ImanSoftware.KeylessAgent.Tests'">
<PackageReference Include="SonarAnalyzer.CSharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<NoWarn>$(NoWarn);CA1873;CA2007;CA1031;CA1040;CA1303;CA1307;CA1308;CA1822;S3267;CA1707;S1135;CA1861;CA1056;CA1054;CA2000;CA5394;S1075;S2245</NoWarn>
</PropertyGroup>
<ItemGroup Condition="'$(MSBuildProjectExtension)' != '.dcproj' and '$(MSBuildProjectName)' != 'ImanSoftware.KeylessAgent.Tests'">
<PackageReference Include="SonarAnalyzer.CSharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<!-- The single source of the application version: Program.cs reads it from the
assembly and publish.ps1 bumps it here. -->
Expand All @@ -45,6 +43,5 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<RepositoryUrl>https://github.com/ImanEstiri/KeylessAgent</RepositoryUrl>
<PackageReadmeFile Condition="Exists('README.md')">README.md</PackageReadmeFile>

</PropertyGroup>
</Project>
</Project>
21 changes: 16 additions & 5 deletions KeylessAgent.slnx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
<Solution>
<Project Path="src\Core\ImanSoftware.KeylessAgent.Abstractions\ImanSoftware.KeylessAgent.Abstractions.csproj" />
<Project Path="src\Core\ImanSoftware.KeylessAgent.Core\ImanSoftware.KeylessAgent.Core.csproj" />
<Project Path="src\UI\ImanSoftware.KeylessAgent.Cli\ImanSoftware.KeylessAgent.Cli.csproj" />
<Project Path="src\Playground\ImanSoftware.KeylessAgent.Playground\ImanSoftware.KeylessAgent.Playground.csproj" />
<Project Path="src\tests\ImanSoftware.KeylessAgent.Tests\ImanSoftware.KeylessAgent.Tests.csproj" />
<Folder Name="/src/" />
<Folder Name="/src/Core/">
<Project Path="src\Core\ImanSoftware.KeylessAgent.Abstractions\ImanSoftware.KeylessAgent.Abstractions.csproj" />
<Project Path="src\Core\ImanSoftware.KeylessAgent.Core\ImanSoftware.KeylessAgent.Core.csproj" />
</Folder>
<Folder Name="/src/Playground/">
<Project Path="src\Playground\ImanSoftware.KeylessAgent.Playground\ImanSoftware.KeylessAgent.Playground.csproj" />
</Folder>
<Folder Name="/src/tests/">
<Project Path="src/tests/ImanSoftware.KeylessAgent.Wpf.Tests/ImanSoftware.KeylessAgent.Wpf.Tests.csproj" />
<Project Path="src\tests\ImanSoftware.KeylessAgent.Tests\ImanSoftware.KeylessAgent.Tests.csproj" />
</Folder>
<Folder Name="/src/UI/">
<Project Path="src/UI/ImanSoftware.KeylessAgent.Wpf/ImanSoftware.KeylessAgent.Wpf.csproj" />
<Project Path="src\UI\ImanSoftware.KeylessAgent.Cli\ImanSoftware.KeylessAgent.Cli.csproj" />
</Folder>
</Solution>
Loading
Loading