Ben Villalobos
90d · built 2026-08-09
90-day totals
- Commits
- 45
- Grow
- 8.8
- Maintenance
- 7.5
- Fixes
- 1.8
- Total ETV
- 18.1
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
↑+5.6 %
vs 18 prior
↑+3.6 pp
recent vs prior
↑+18.0 pp
recent vs prior
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 5.4ETVAutomations: Management UI (create/edit dialog, list widget, ChatInputPart integration) (#323914) * feat(automations): add management UI — list widget, create/edit dialog, modal polish Adds the complete automations management interface: - AutomationsListWidget: WorkbenchList-based view with run status, dynamic row heights - Create/Edit dialog: ChatInputPart-hosted prompt editor with ghost text - WorkspacePicker integration for folder selection - Isolation mode dropdown (Worktree/Folder via ActionListWidget) - Static 'Copilot CLI' harness chip (future picker placeholder) - Schedule configuration (Manual/Hourly/Daily/Weekly with time/day pickers) - Permission level and model selection via ChatInputPart toolbar - CSS styling matching form field backgrounds to prompt editor - PlaceholderTextContribution registered on ChatInputPart editor - List widget tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(automations): polish isolation chip and fix its default label Add a hover highlight and remove the redundant chevron so the isolation chip matches the new-session picker. Fix the chip showing 'Folder' for an unset isolation mode: the label now derives from !== 'workspace', so an undefined mode reads as 'Worktree' to match the picker, provider, and run defaults (previously it lied and the session ran as a worktree). * fix(automations): replace unknown fontWeight-medium with semiBold The stylelint rule flags --vscode-agents-fontWeight-medium as unknown. Only regular and semiBold are registered in vscode-known-variables.json. Use semiBold for form labels — visually equivalent for this context. * fix(automations): address review findings — CCR patterns, test gaps, bug fixes - Remove 33 em dashes from comments - Compress 5 over-length JSDoc blocks to 1-2 sentences - Fix semicolons-as-conjunctions in comments - Track rAF via MutableDisposable (use-after-dispose fix) - Switch runNow to CancellationToken.None (phantom CTS removal) - Restore defensive typeof guard in getCategoryLabel - Re-add ILabelService for URI display in remote contexts - Add tests: openEditDialog error, openCreateDialog, runNow failure, resetLanguageModelToDefault - Add race-safety comment in createSessionTypeBinder * refactor(automations): replace querySelector toolbar injection with menu-driven actions Migrate the harness chip and isolation group from DOM surgery (querySelector on ChatInputPart internals) to the structured MenuId + actionViewItemProvider pattern used by the New Session Page. - Register OpenAutomationsHarnessChipAction on MenuId.ChatInputSecondary - Register OpenAutomationsIsolationGroupAction on MenuId.ChatInputSecondary - Gate both with ChatContextKeys.inAutomationsDialog context key - Add secondaryToolbarActionViewItemProvider to IChatInputPartOptions - Route custom items in ChatInputPart secondary toolbar provider - Remove querySelector and eslint-disable-next-line comments * fix(automations): honor storeSelection in setChatMode2, handle hidden saved modes - setChatMode2 now gates _syncInputStateToModel behind storeSelection, preventing unintended persistence of transient mode changes. - automationDialog detects when a saved mode is hidden by the hideCustomChatModes filter and falls back to default instead of setting up an infinite retry watcher. * feat(automations): restore accessibility help provider and fix a11y issues * Signing commit * fix: correct indentation in dialog.ts focus-out handler * Signing commit --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 4c959fa6 · 2026-07-02
- 2.3ETVfeat(automations): add foundation — types, storage, scheduler, leader election (#323745) * feat(automations): add foundation — types, storage service, scheduler, leader election Introduces the Automations subsystem core: - IAutomation types and IAutomationSchedule (interval-based: manual/hourly/daily/weekly) - DST-safe computeNextRunAt scheduling logic - IAutomationService with persistent JSON ledger (StorageScope.APPLICATION) - Optimistic concurrency via revision counter for cross-window safety - Leader election to ensure single scheduler instance across windows - AutomationScheduler: periodic tick loop checking due automations - Feature gate: chat.automations.enabled setting mirrored to context key - Unit tests for scheduling logic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address Copilot Code Review feedback on PR 1 - Add _unsupportedSchema guard to recordRunStart and updateRun - Localize CRASH_RECOVERY_REASON string via nls.localize() - Move imports above registerSingleton call in contribution file - Fix test comment referencing wrong helper name (buildLocalDate -> localDate) * fix: address CCR round 2 — schema guards, telemetry cleanup, scope fix - Add _unsupportedSchema guard to markStaleRunsFailed and advanceNextRunAt - Replace boolean telemetry flags with actual enum values (permissionLevel, isolationMode) - Remove hasProviderId, hasSessionTypeId, hasModelId, hasMode, hasPermissionLevel flags - Add scope: ConfigurationScope.MACHINE to runTimeoutMinutes setting * fix: gate scheduler construction on chat.automations.enabled AutomationSchedulerCore (and its leader election heartbeat/storage writes) are now only constructed when the feature setting is enabled. Uses MutableDisposable for clean teardown on runtime toggle. Addresses CCR feedback: avoid 30s heartbeat timer + storage writes when the feature is disabled. * fix: isolate per-automation errors in dispatch loop Wrap advanceNextRunAt + runOneWithTimeout in try/catch so a failure in one automation does not abort dispatch of remaining due automations. * fix: register automations path in i18n resources Adds vs/sessions/contrib/automations to the translation resources so nls.localize calls pass the eslint translation-remind rule. * fix: validate enum fields at write boundary and harden persist() - Normalize permissionLevel/isolationMode in createAutomation and mergeAutomation: reject unknown values to keep persisted data and GDPR-classified telemetry low-cardinality. - Wrap persist() storage read and write in try/catch so storage failures degrade gracefully instead of breaking the scheduler. * fix: scheduler to Eventually phase, simplify persist(), document serial dispatch - Move scheduler registration from AfterRestored to Eventually — background concern that doesn't need to block workbench restore. - Remove re-read-before-write in persist() — refreshFromStorage via onDidChangeValue already handles cross-window sync. Eliminates redundant JSON.parse on every mutation and the misleading optimistic concurrency check that overwrote anyway. - Document that _pendingRuns serializes dispatch intentionally. * style: remove em dashes and obscure acronyms from comments Replace all em dashes with periods or semicolons. Remove TOCTOU acronym. Replace multiplication sign with plain x. * Signing commit --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 041ae8b0 · 2026-06-30
- 2.2ETVautomations: new management view (#328471) * feat(automations): automations custom view with cards UI and run history Implements the Automations page as an AbstractCustomView using the new custom view grid infrastructure. Registers via ICustomViewService and renders the cards widget (automation cards + run history with scroll). Adds ManageAutomations and MarkAllAutomationRunsRead actions. * feat(automations): sessions list sidebar shortcut with status indicator Adds an Automations shortcut section to the sessions list sidebar. Clicking it opens the automations custom view via ICustomViewService. Shows a blue dot status indicator for active/unread automation runs. * fix: automations UX polish — layout shift, focus outlines, icon color - Use visibility instead of display for toolbar show/hide to prevent blue dot layout shift on hover - Suppress focus outline on shortcut rows (focused/selected states) - Preserve bright icon/label color when shortcut is active * feat: migrate New Automation button to header, fix cards rendering and polish - Move 'New Automation' from inline widget header to custom view header action bar via Action2 + CustomViewAutomations MenuId - Register PrimaryButtonActionViewItem via IActionViewItemService so the button renders as primary (blue) instead of secondary - Fix cards not rendering: remove stale newButtonElement references that crashed renderCards silently - Add openCreateDialog back for empty state create button - Remove inner DomScrollableElement (outer custom view handles scroll) - Remove widget tabIndex and suppress .custom-view-content focus outline - Fix mark-read race: store read ID before opening session - Use pixel spinner grid animation for running/pending history status - Remove small: true from button for better sizing Apply the same pattern: override the content element to full width via CSS, and let the widget self-center with max-width and margin: 0 auto. * Remove redundant automation edit action * Derive automations shortcut active state * fix: improve automation card keyboard accessibility - Change card role from 'button' to 'group' since it contains nested interactive elements (buttons inside a button is invalid ARIA) - Add Enter/Space keyboard handler on the card to open edit dialog - Add role='toolbar' and aria-label to the actions container - Improve card aria-label to include schedule info for screen readers The action buttons were already keyboard-reachable (tabindex=0) and visible on :focus-within, but the card itself lacked keyboard activation and had an invalid ARIA role. * refactor: split AutomationsCardsWidget into section classes Extract two internal classes from the 480-line monolith: - AutomationCardsSection: card grid, empty state, card interactions, edit/create/delete dialogs - AutomationHistorySection: history list, date grouping, run cards, read state management The widget becomes a thin composition layer that creates both sections, wires up observables, and handles layout. Shared helpers (formatSchedule, groupRunsByDate, runStatusIcon) are promoted to module-level functions. All classes remain in the same file, following the sessionsList.ts convention of keeping related renderers together. * perf: split autorun so cards and history re-render independently Previously one autorun subscribed to automations, runs, and readStateVersion, causing both sections to fully rebuild when any observable fired. Now cards only re-render when automations change, and history only re-renders when runs, automations, or read state change. * Revert "perf: split autorun so cards and history re-render independently" * automations: unify unread run status * automations: refine view focus * automations: remove focus overridegithub.com-microsoft-vscode · 9bc8e151 · 2026-08-01
- 1.5ETVAutomations view polish (#328883) * Hide the 'New Automation' button when there are no automations * Fix caps * Fix context key setting for btn * Always show custom view header divider Previously the bottom border on the custom view header band was transparent by default and only became visible when the user scrolled down (via the .scrolled class toggled in customViewNode.ts). This meant the divider between the header and content was invisible at the top scroll position. Change the border color to always be visible so the header is consistently separated from the content regardless of scroll position. * Move automation dialog CSS to dedicated file and fix button padding The automation dialog CSS was still living in aiCustomizationManagement.css after the automations list widget was removed in #328654. Move it to a dedicated automationDialog.css file next to the dialog service and add the import there. Also fix padding issues where Create/Cancel buttons and the close button were too close to the dialog border (padding: 0 was inherited from the base dialog override): - dialog-toolbar-row (close button): 4px/6px → 8px/10px from top/right - dialog-buttons-row: add 8px top, 10px side, 10px bottom padding * Fix pointer cursor on automation dialog form labels Schedule, Time, Day of week, and Prompt labels were rendered as <label> elements without 'for' attributes. Chromium applies cursor: pointer to <label> elements regardless of author CSS, making them look like links. Change them to <span> elements since they are purely visual section headers with no programmatic association to their controls. * Fix extra spacing around automation dialog prompt input chat.css sets padding: 4px 0 on .interactive-input-part, designed for the full chat panel. In the compact dialog this adds visible dead space above the rounded input container (below the Prompt label) and below the secondary toolbar. Zero out both ends. Also reduce the 6px bottom padding inside .chat-input-container (between the picker chips and the container border) to 2px. * Truncate long automation card titles with ellipsis word-break: break-word on the card name container caused the Disabled badge to word-wrap when titles were long. Replace with ellipsis truncation on the title text so the badge always stays on one line. * Use editorWidget.border token for automation card outlines widget.border is transparent in many themes, making cards invisible. Switch to editorWidget.border which has concrete defaults across light and dark themes, and add a contrastBorder override for HC themes. * Fix ellipsis truncation on automation card titles and add context key test The title span needs flex: 1 1 0; min-width: 0 to actually shrink as a flex item — without it the min-width: auto default prevents ellipsis from engaging on long unbroken strings. Also add test coverage for the AutomationsHasItemsContext global context key fix: verifies the key transitions false → true → false as the automations observable changes through empty/non-empty/empty states. Export AutomationsCustomViewContribution to enable direct instantiation in the test. * Always show header divider for automations view Stamp data-view-id on the custom view node element so individual views can override the scroll-driven divider behavior via CSS. Use this to always show the header bottom border in the automations view, while keeping the scroll-driven behavior intact for any other custom views.github.com-microsoft-vscode · 106a3a45 · 2026-08-04
- 0.8ETVEnforce workspace trust for unattended agent sessions (#327670) * sessions: enforce trust for unattended sends Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · b6b514a5 · 2026-07-27
- 0.8ETVValidate workspace trust before selecting an automation workspace (#327724) * automations: validate workspace trust before selection Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · d3b057c5 · 2026-07-27
- 0.7ETVAutomations: Wire into customizations UI (#324167) Connects the Automations feature to existing VS Code surfaces: - AI Customizations sidebar entry gated on ChatAutomationsEnabledContext - Overview tile with automation count badge - Deep-link: sidebar click navigates directly to Automations tab - Feature gate when-clauses on all entry points - Allow a way to set model without persisting globallygithub.com-microsoft-vscode · 3379a344 · 2026-07-05
- 0.7ETVAutomations PR 2 (Runner) (#323810) * feat(automations): add session runner — dispatches automation runs via sessions layer Implements AutomationRunner: - Creates sessions with configured prompt, mode, model, and permission level - Dispatches via createAndSendNewChatRequest (background session) - Tracks run lifecycle: recordRunStart/updateRun on IAutomationService - Error notification on run failure - Cancellation handling for mid-flight stops - Sessions titled with automation name via renameChat Supporting changes: - ICreateNewSessionOptions: added modelId, modeId, permissionLevel, isolationMode, branch - ISessionsProvider: added optional setMode/setPermissionLevel/setIsolationMode/setBranch - ISendRequestOptions: added optional source field - createAndSendNewChatRequest now returns ISession | undefined - Implementation applies createOptions to provider before sending Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(automations): title the session before the agent host launches Thread an optional title through ISendRequestOptions and apply it in _sendFirstChat before sending, falling back to the query's first line. The automation runner passes the automation name, so launch-time prompts (e.g. worktree file transfer) show the automation name instead of the prompt text. The post-send renameChat still sets the committed CLI title. * Signing commit --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 126f9a2a · 2026-07-01
- 0.6ETVAdd a dedicated Automation session draft (#329278) * Add a dedicated Automation session draft Keep the Automation dialog draft isolated from New Chat and synchronize it with workspace, provider, session type, and workspace-less target changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · b3f7c8c6 · 2026-08-05
- 0.5ETVAdd deletion actions to automation run history (#329068) * Add deletion actions to automation run history * Address automation history deletion review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 68f210a0 · 2026-08-05
- 0.4ETVUnify isolation checkbox into shared BranchPicker (#326414) * Add isolation mode checkbox to shared branch picker * Migrate isolation plumbing into copilot branch picker adapter Largely a migration from the standalone IsolationPicker ahead of its deletion. The copilot adapter now drives the isolation checkbox added to the shared BranchPicker, connecting session state (config gating, git repo detection, context key, telemetry) to the new checkbox slot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove standalone isolation picker action and registration The branch picker now renders the isolation checkbox internally, so the separate isolationPicker action, view-item factory, and import are no longer needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move IsolationMode type into copilotChatSessionsProvider The type was defined in isolationPicker.ts which is being deleted. Relocated next to the STORAGE_KEY_ISOLATION_MODE constant where all isolation-mode session logic lives. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace automation dialog isolation chip with shared checkbox The chip-and-dropdown isolation UI is replaced by the same checkbox the shared BranchPicker now renders, unifying the isolation control across copilotChatSessions and automations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove automation isolation chip CSS (replaced by checkbox) The chip element no longer exists — its styles are dead code. Branch- slot styles and the divider box-shadow between slots are preserved. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update tests for unified isolation checkbox Fold isolation picker checkbox tests into the copilot branchPicker test. Rewrite automation dialog tests to assert checkbox state instead of the removed chip/dropdown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Delete standalone IsolationPicker and its test/CSS Fully replaced by the isolation checkbox in the shared BranchPicker. The IsolationMode type now lives in copilotChatSessionsProvider.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * 'Worktree' -> 'New Worktree' * Fix isolation checkbox stacking below branch trigger When isolation is configured, wrap both slots in a flex-row container so the checkbox and branch trigger sit side by side. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove super.render() from automation isolation group view item BaseActionViewItem.render() registers a MOUSE_DOWN listener that adds an .active class to the container, which triggers the workbench toolbar rule that highlights all .action-label descendants. Since the container now holds two action-labels (the isolation checkbox and the branch trigger), clicking either one highlighted both. The copilot PickerActionViewItem already skips super.render() for the same reason. The automation dialog called it but immediately wiped the DOM with clearNode — the only lasting side effect was the unwanted .active listener. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Prevent text selection on double-click in branch picker group Removing super.render() dropped the MOUSE_DOWN preventDefault that was suppressing native text selection. Add user-select: none to the wrapper instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Re-add markTarget for onboarding spotlight on isolation slot The onboarding tours reference 'sessions.newSession.isolation' and need a DOM element registered as the target. Wire markOnboardingTarget through the IBranchPickerIsolationOptions.markTarget option. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix test selector to target branch trigger, not isolation checkbox Use 'a.action-label' to disambiguate the branch trigger (an <a>) from the isolation checkbox row (a <div>), matching codebase convention. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Keep disabled isolation checkbox focusable for keyboard users Checkbox.disable() sets tabIndex=-1, making it unreachable via keyboard. Override to tabIndex=0 so users can tab to it and discover the disabled reason via the tooltip. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix wrapper layout: restore widget-owned group, fix divider + min-width - Restore span.sessions-chat-branch-picker-group as the layout owner (inline-flex + min-width:0) instead of inline styles on the caller. - Fix automation divider: drop direct-child selector so box-shadow matches through the wrapper. - Add min-width:0 so labels can ellipsize in narrow toolbars. - Revert PickerActionViewItem inline styles (not its responsibility). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * signing commit * Restore imports needed by new AutomationWorkspacePicker class PR #326315 added a workspace picker class that uses Codicon, renderIcon, ActionListItemKind, and IActionListItem. These imports were removed in our earlier commit because the isolation group class no longer needed them, but the new class does.github.com-microsoft-vscode · b2c7a9a2 · 2026-07-19
- 0.3ETVAdd session provider picker to automations dialog (#325223) * Stop defaulting to copilot * Render the SessionTypePicker * Automations: Wire in the sessiontypepicker * Remove session type binder in favor of session type picker * Permission label updates when selecting a new session type * Use MobileSessionTypePicker for phone-layout bottom sheet support The automation dialog was using the desktop-only SessionTypePicker directly. The rest of the codebase uses MobileSessionTypePicker which renders a bottom sheet on phone layouts and falls back to the desktop action-widget popup otherwise. Swap to the mobile-aware subclass so the automation picker behaves consistently on all viewports. * Allow clearing provider and session type * Prevent automations session type pick to change new session store * Keep picker in sync when late providers advertise session types * signing commitgithub.com-microsoft-vscode · e8a3eada · 2026-07-10
- 0.3ETVSessionTypePicker: Add optional folder source support (#325211) Updates SessionTypePicker to allow consumers to use setFolderSource to discover session types (Copilot, Claude, etc.) via folder source rather than explicitly requiring an existing session. Required for the Automations dialog to display session types, because the automation dialog does not create a session itself.github.com-microsoft-vscode · db58c891 · 2026-07-10
- 0.2ETVDialogs: Preserve arrow keys in editable controls (#328788) * Dialogs: Preserve arrow keys in editable controls Prevent dialog focus navigation from consuming horizontal arrow keys in embedded text inputs. Fixes #328732. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9f5a1f06-c4b5-43f2-bff2-9d3a41f3d611 * Cover contenteditable in dialog arrow-key guard Addresses PR review: include isContentEditable so the guard also protects contenteditable surfaces rendered via renderBody, and extend the test.1github.com-microsoft-vscode · e078027d · 2026-08-03
- 0.2ETVAutomations: polish dialog controls (#328288) * Add showChevron option to session type picker, hide in automations dialog * UX nits * Polish automation dialog focus behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 33375fda · 2026-07-30
- 0.1ETVAutomations: Make cards fully clickable (#328659) * Automations: Make cards fully clickable Open the edit dialog from card clicks and taps while preserving the Run and Delete actions. * Automations: Strengthen card interaction tests Model Gesture dispatch to both action and card targets, and verify that action taps run without opening Edit while card taps do open Edit. m>github.com-microsoft-vscode · 2ea7d8ae · 2026-08-03
- 0.1ETVSanity tests: stop constructing a second ConversationFeature (#316732)github.com-microsoft-vscode · 8f3318d0 · 2026-05-18
- 0.1ETVSupport embedding NewChatInputWidget in alternate surfaces (#329113) * Support embedding new chat input widget Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 04e08bc7 · 2026-08-05
- 0.1ETVFix automations card keyboard accessibility (#329053) * Fix automations card keyboard accessibility Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com><223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 1470017f · 2026-08-04
- 0.1ETVAutomations: Bring workspace picker under the chat input (#325397) * Debt: Remove workspacePickerInput from chatInputPart * Remove dead renderTrigger code * Cleanup: Consolidate into a single pickeractionviewitem class * signing commitgithub.com-microsoft-vscode · fbf54ced · 2026-07-11