Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## 1.3.0-beta2 - 2026-08-04

Second beta of the Command Timeline release, fixing a failure-reporting
defect found while capturing the beta1 screenshots. Like beta1, this is
published as a GitHub prerelease; GitHub Latest and WinGet continue to
point at v1.2.0 until a stable 1.3.0.

### Fixed

- Command Timeline entries no longer report every command as Succeeded.
The PowerShell prompt wrapper ran `Get-Module` before reading `$?`, so
the finished mark always carried exit code 0. The wrapper now captures
`$?` as its first statement and passes it into the prompt function, so
failed cmdlets report exit code 1 and native commands report their real
exit codes. The shell integration suite now drives the installed prompt
wrapper end to end and locks in the first-prompt, success, cmdlet
failure, native failure, and recovery sequences.


## 1.3.0-beta1 - 2026-08-04

First beta of the Command Timeline release. The feature content is identical
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ notes, and checksums together.

A **beta** channel is also available for early access to the Command
Timeline:
[v1.3.0-beta1](https://github.com/HelloThisWorld/winTerm/releases/tag/v1.3.0-beta1)
[v1.3.0-beta2](https://github.com/HelloThisWorld/winTerm/releases/tag/v1.3.0-beta2)
is published as a GitHub prerelease with the same asset layout. Betas are for
testing; the stable release above stays the recommended download.

Expand All @@ -35,7 +35,7 @@ application downloads are:
- `winTerm-<version>-setup-x64.exe` — current-user or all-users installation;
- `winTerm-<version>-portable-x64.zip` — extract and run without installation.

The current source version is `1.3.0-beta1`;
The current source version is `1.3.0-beta2`;
the latest stable release is `1.2.0`. See the
[latest official Release](https://github.com/HelloThisWorld/winTerm/releases/latest)
for the complete published asset list and checksums.
Expand Down Expand Up @@ -104,8 +104,8 @@ Use PowerShell 7 and the Microsoft Terminal toolchain described in
.\scripts\winterm\build.ps1 -Configuration Release -Platform x64 -IncludeTests
.\scripts\winterm\test.ps1 -Suite Relevant -Configuration Release -Platform x64
.\scripts\winterm\build-unpackaged.ps1 -Configuration Release -Platform x64
.\scripts\winterm\build-installer.ps1 -Version 1.3.0-beta1 -Platform x64
.\scripts\winterm\build-portable.ps1 -Version 1.3.0-beta1 -Platform x64
.\scripts\winterm\build-installer.ps1 -Version 1.3.0-beta2 -Platform x64
.\scripts\winterm\build-portable.ps1 -Version 1.3.0-beta2 -Platform x64
```

The unpackaged generator uses an unsigned MSIX only as an upstream build
Expand Down
40 changes: 27 additions & 13 deletions docs/current-progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ Last updated: 2026-08-04

## Repository state

- Branch: `release/v1.3.0-beta1`
- Base branch: `main` at `c089caeb` (1.3.0-alpha4 release metadata, pull
request #37)
- Branch: `release/1.3.0-beta2`
- Base branch: `main` at `a6ec9a415` (prompt exit code fix, pull request
#39)
- Microsoft Terminal upstream revision:
`1cea42d433253d95c4487a3037db48197b5e72f4`
- Application version: `1.3.0-beta1`
- Package/file version: `1.3.0.4`
- PowerShell module version: `1.3.0` with prerelease suffix `beta1`
- Application version: `1.3.0-beta2`
- Package/file version: `1.3.0.5`
- PowerShell module version: `1.3.0` with prerelease suffix `beta2`
- Release channel: `beta`
- Release tag: `v1.3.0-beta1`
- Release tag: `v1.3.0-beta2`
- Current public Latest: `v1.2.0`, the stable Visual Progress release
- Supported target: Windows 11 x64

`v1.3.0-beta1` is the first beta of the Command Timeline release, with
feature content identical to `v1.3.0-alpha4`, which passed local field
testing. The release workflow marks any non-stable channel with
`--prerelease` and `--latest=false`, so `/releases/latest` keeps resolving to
v1.2.0. Unlike the alphas, the beta is listed on the winTerm website next to
the stable v1.2.0 download; it is still skipped by the WinGet workflow.
`v1.3.0-beta2` is the second beta of the Command Timeline release. It fixes
a beta1 defect found while producing the website screenshots: the PowerShell
prompt wrapper reset `$?` before reading it, so every Timeline entry reported
Succeeded and a failure mark could never appear. The release workflow marks
any non-stable channel with `--prerelease` and `--latest=false`, so
`/releases/latest` keeps resolving to v1.2.0. Like beta1, the beta is listed
on the winTerm website next to the stable v1.2.0 download; it is still
skipped by the WinGet workflow.

## Command Timeline status

Expand All @@ -49,6 +51,18 @@ prerelease suffix. The package version stays four-part numeric for MSIX and the
Win32 resource fields, and the PowerShell module version stays numeric with the
suffix carried in `PrivateData.PSData.Prerelease`.

## Beta1 findings

Producing the sanitized website screenshots against the published beta1
portable build surfaced one defect, fixed on `main` through pull request #39:

1. Every Command Timeline entry reported `✓ Succeeded`, including commands
that failed. The prompt wrapper executed `Get-Module` before the prompt
function read `$?`, so the finished mark always carried exit code 0. The
wrapper now captures `$?` first and passes it through, and the shell
integration suite drives the installed wrapper end to end (first prompt,
success, cmdlet failure, native exit code, recovery).

## Alpha3 field reports

Local testing of `v1.3.0-alpha3` surfaced three issues, all fixed on `main`
Expand Down
177 changes: 177 additions & 0 deletions docs/releases/1.3.0-beta2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# winTerm 1.3.0-beta2

**This is a beta prerelease.** The current stable release remains
[v1.2.0](https://github.com/HelloThisWorld/winTerm/releases/tag/v1.2.0), and
`/releases/latest` continues to point there. The beta is listed on the winTerm
website next to the stable download and is published as a GitHub prerelease;
it is not submitted to WinGet.

winTerm 1.3.0-beta2 is the second beta of the **Command Timeline** release.
It fixes one defect found in 1.3.0-beta1 and is otherwise identical to it.

## Fixed since 1.3.0-beta1

- **Failed commands are reported as failed again.** In beta1, every finished
command showed `✓ Succeeded`, including commands that clearly failed. The
PowerShell prompt wrapper executed `Get-Module` before it read `$?`, so the
shell always reported exit code 0. The wrapper now captures `$?` as its
first statement and hands it to the prompt function: a failed cmdlet
reports exit code 1, a native command reports its real exit code, and the
Timeline resolves entries to `✕ Failed` accordingly. The shell integration
test suite now drives the installed prompt wrapper exactly like the console
host and locks in the first-prompt, success, cmdlet-failure, native-failure,
and recovery sequences.

## What is new since v1.2.0: Command Timeline

The Command Timeline is a per-pane, in-memory list of the commands that pane
has run. Open it with `Ctrl+Tab`, or with the thin auto-hiding handle on the
left edge of the terminal; click the terminal, press `Escape`, or press
`Ctrl+Tab` again to close it.

- **Per-pane history.** Each pane keeps its own list, built from OSC 133
shell integration only. winTerm never guesses where a prompt or output
begins, and `cmd.exe` — which does not report command boundaries — shows
`Command timeline unavailable` rather than untrustworthy results.
- **Works out of the box.** A profile whose commandline is a bare
`powershell.exe` or `pwsh.exe` (optionally with `-NoLogo`/`-NoExit`)
automatically imports the packaged `winTerm.Shell` integration module at
startup. Any customized commandline launches unchanged; the per-profile
setting `"shellIntegration.autoInject": false` turns the rewrite off.
- **Load without executing.** `Enter` or a single click puts the selected
command on the input line and stops there. No carriage return is ever sent,
the Windows clipboard is never read, and input broadcast never forwards the
load to another pane.
- **Filtering.** Press `/` or `Tab` and type to narrow the list. Matching is
a plain, case-insensitive substring match over command text only — no
wildcards, no regular expressions, no fuzzy matching, and command output is
never searched.
- **Copy and jump.** Right-click an entry to copy the command, copy its
output, or scroll to where its output begins. Output is read from the
terminal buffer only at that moment and is never cached.
- **Trustworthy status.** A command shows ● Running while it executes and
resolves to ✓ Succeeded or ✕ Failed when the shell reports its exit code.
`Unknown` appears only when the shell genuinely did not report a result,
and explains itself on hover. Status is never conveyed by color alone.
- **Readable rows.** Hover any row for the full command text; the selection
moves without rebuilding rows, so the list stays steady under the arrow
keys.

## Keyboard

| Shortcut | Behavior |
| --- | --- |
| `Ctrl+Tab` | Toggle the Command Timeline for the focused pane |
| `Ctrl+T` | Next tab |
| `Ctrl+Shift+T` | Previous tab |
| `Ctrl+Alt+T` | Open new tab |

While the Timeline is open:

| Key | Behavior |
| --- | --- |
| `/` or `Tab` | Move focus to the filter box |
| `Up` / `Down` | Move the selection by one command |
| `Left` / `Right` | Select the first / last command on the current page |
| `Enter` | Load the selected command; never runs it |
| `Space` | Scroll the terminal to that command's output |
| `Ctrl+C` | Copy the selected command text |
| `Escape` | Clear the filter, or close the Timeline if the filter is empty |

Your own key bindings take precedence over every default above. Keys the
Timeline consumes are not sent to the shell, and filter text never reaches
the shell.

## Settings

```json
{
"commandTimeline.enabled": true,
"commandTimeline.historyLimit": 500
}
```

Per profile:

```json
{
"shellIntegration.autoInject": true
}
```

- **Show command timeline** defaults on. Turning it off hides the handle,
closes an open overlay, and stops `Ctrl+Tab` from opening it.
- **Commands remembered per pane** defaults to 500 and accepts 50 through
5000. An out-of-range value is clamped rather than failing the settings
load.

An existing settings file needs no migration.

## Changes accumulated through the prerelease series

- alpha2: auto-injected shell integration, the auto-hiding handle,
terminal-click light dismiss, and the recognition-engine fixes for stuck
progress bars.
- alpha3: correct FinalTerm mark emission (no stray characters, exact command
capture), no progress bar at an idle prompt, no phantom Timeline row, no
selection jitter, and silent degradation when antivirus blocks an optional
module component.
- alpha4: the antivirus write-then-execute false positive removed at its
source, ✓/✕ results restored through the Enter-keypress lifecycle
notification, and full-command tooltips.
- beta2: real exit codes restored to the finished mark, so failures resolve
to ✕ Failed instead of a false ✓ Succeeded.

## Privacy

- Command text lives only in memory, only in the pane that ran it, and only
while that pane is open. Nothing is written to disk; there is no command
history file or database.
- Command output is never cached, indexed, or searched.
- Filter text is never saved and never leaves the pane.
- No telemetry is written, and no command, output, path, or filter text is
logged.
- The clipboard is written only by an explicit copy action, and is never
read.

See the [privacy policy](https://github.com/HelloThisWorld/winTerm/blob/main/PRIVACY.md).

## Unchanged in this release

Workspace schema (2), docking model (1), shell protocol (1), theme schema
(1), update manifest schema (1), package identity, and signing policy are all
unchanged from v1.2.0. Visual Progress behavior is unchanged apart from the
recognition fixes above.

## Known limitations

- The Timeline requires OSC 133 shell integration; it stays unavailable under
`cmd.exe`.
- A multi-line command is refused when the shell has not enabled bracketed
paste, because unbracketed line breaks would be read as pressing Enter.
- Loading a command longer than 1024 characters asks for a confirming
`Enter`.
- Command history does not survive closing a pane, and is intentionally never
persisted.

## Installation

The Setup EXE supports current-user and all-users installation; the Portable
ZIP can be extracted to a writable directory and run without installation.
Installing the beta over v1.2.0 or an earlier prerelease is supported; the
file version is `1.3.0.5`. Package identity stays separate from Microsoft
Terminal, so it does not disturb an existing Windows Terminal installation.

Publisher: `helloThisWorld`. Tag: `v1.3.0-beta2`.

## Signing

The winTerm 1.3.0-beta2 Setup EXE is not Authenticode-signed. Windows may
display Unknown Publisher or a SmartScreen warning. Download only from the
official GitHub Release and verify the file against `SHA256SUMS.txt` before
running it.

## Policies

- [Code signing policy](https://github.com/HelloThisWorld/winTerm/blob/main/CODE_SIGNING_POLICY.md)
- [Privacy policy](https://github.com/HelloThisWorld/winTerm/blob/main/PRIVACY.md)
4 changes: 2 additions & 2 deletions scripts/winterm/package-shell-assets.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ foreach ($relativePath in $sourceAssets)

$version = Get-Content -LiteralPath (Join-Path $repositoryRoot 'shell\shared\version.json') -Raw | ConvertFrom-Json
if ($version.moduleVersion -ne '1.3.0' -or
$version.modulePrerelease -ne 'beta1' -or
$version.applicationVersion -ne '1.3.0-beta1' -or
$version.modulePrerelease -ne 'beta2' -or
$version.applicationVersion -ne '1.3.0-beta2' -or
$version.protocolVersion -ne 1)
{
throw 'The winTerm Shell asset version metadata is invalid.'
Expand Down
34 changes: 17 additions & 17 deletions scripts/winterm/test-visual-progress.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1378,12 +1378,12 @@ try

$version = $source.VersionMetadata | ConvertFrom-Json
$expectedVersionValues = [ordered]@{
applicationVersion = '1.3.0-beta1'
packageVersion = '1.3.0.4'
applicationVersion = '1.3.0-beta2'
packageVersion = '1.3.0.5'
moduleVersion = '1.3.0'
modulePrerelease = 'beta1'
modulePrerelease = 'beta2'
channel = 'beta'
tag = 'v1.3.0-beta1'
tag = 'v1.3.0-beta2'
workspaceSchemaVersion = 2
dockingModelVersion = 1
shellProtocolVersion = 1
Expand All @@ -1398,39 +1398,39 @@ try
}
}
$shellVersion = $source.ShellVersion | ConvertFrom-Json
if ($shellVersion.applicationVersion -ne '1.3.0-beta1' -or $shellVersion.moduleVersion -ne '1.3.0' -or $shellVersion.protocolVersion -ne 1)
if ($shellVersion.applicationVersion -ne '1.3.0-beta2' -or $shellVersion.moduleVersion -ne '1.3.0' -or $shellVersion.protocolVersion -ne 1)
{
throw 'Shell version metadata does not match winTerm release 1.3.0-beta1 with protocol version 1.'
throw 'Shell version metadata does not match winTerm release 1.3.0-beta2 with protocol version 1.'
}
foreach ($surface in @(
@{ Content = $source.ReleaseMetadata; Value = 'ApplicationVersion{ L"1.3.0-beta1" }'; Description = 'About release metadata' },
@{ Content = $source.PackageManifest; Value = 'Version="1.3.0.4"'; Description = 'MSIX package manifest' },
@{ Content = $source.HostResource; Value = 'FILEVERSION 1,3,0,4'; Description = 'Terminal host file version' },
@{ Content = $source.HostResource; Value = '"ProductVersion", "1.3.0-beta1\0"'; Description = 'Terminal host display version' },
@{ Content = $source.ShimResource; Value = 'FILEVERSION 1,3,0,4'; Description = 'Shim file version' },
@{ Content = $source.ShimResource; Value = '"ProductVersion", "1.3.0-beta1\0"'; Description = 'Shim display version' },
@{ Content = $source.ReleaseMetadata; Value = 'ApplicationVersion{ L"1.3.0-beta2" }'; Description = 'About release metadata' },
@{ Content = $source.PackageManifest; Value = 'Version="1.3.0.5"'; Description = 'MSIX package manifest' },
@{ Content = $source.HostResource; Value = 'FILEVERSION 1,3,0,5'; Description = 'Terminal host file version' },
@{ Content = $source.HostResource; Value = '"ProductVersion", "1.3.0-beta2\0"'; Description = 'Terminal host display version' },
@{ Content = $source.ShimResource; Value = 'FILEVERSION 1,3,0,5'; Description = 'Shim file version' },
@{ Content = $source.ShimResource; Value = '"ProductVersion", "1.3.0-beta2\0"'; Description = 'Shim display version' },
@{ Content = $source.CustomProps; Value = '<VersionMajor>1</VersionMajor>'; Description = 'Executable major version' },
@{ Content = $source.CustomProps; Value = '<VersionMinor>3</VersionMinor>'; Description = 'Executable minor version' },
@{ Content = $source.ShellModuleManifest; Value = "ModuleVersion = '1.3.0'"; Description = 'PowerShell module manifest' },
@{ Content = $source.ShellModule; Value = "`$script:WinTermModuleVersion = '1.3.0'"; Description = 'PowerShell module runtime' },
@{ Content = $source.PackageShellAssets; Value = "'shell\shared\version.json'"; Description = 'Canonical shell version metadata packaging' },
@{ Content = $source.WorkspaceSerializer; Value = '"1.3.0-beta1"'; Description = 'Workspace application-version fallback' }
@{ Content = $source.WorkspaceSerializer; Value = '"1.3.0-beta2"'; Description = 'Workspace application-version fallback' }
))
{
Assert-Contains $surface.Content $surface.Value $surface.Description
}
foreach ($required in @(
"applicationVersion -eq '1.3.0-beta1'",
"packageVersion -eq '1.3.0.4'",
"applicationVersion -eq '1.3.0-beta2'",
"packageVersion -eq '1.3.0.5'",
"moduleVersion -eq '1.3.0'",
"tag -eq 'v1.3.0-beta1'",
"tag -eq 'v1.3.0-beta2'",
"Workspace Schema version remains 2",
"Docking Model version remains 1",
"Shell Protocol version remains 1",
"Theme Schema remains at version 1"
))
{
Assert-Contains $source.VerifyVersion $required 'Authoritative v1.3.0-beta1 version validation surface'
Assert-Contains $source.VerifyVersion $required 'Authoritative v1.3.0-beta2 version validation surface'
}

$testBinary = Join-Path $root "bin\$Platform\$Configuration\UnitTests_SettingsModel\SettingsModel.Unit.Tests.dll"
Expand Down
2 changes: 1 addition & 1 deletion scripts/winterm/test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ function Test-ShellExperienceFoundations

$manifest = Import-PowerShellDataFile -LiteralPath $moduleManifest
if ($manifest.ModuleVersion -ne '1.3.0' -or
$manifest.PrivateData.PSData.Prerelease -ne 'beta1' -or
$manifest.PrivateData.PSData.Prerelease -ne 'beta2' -or
$manifest.PowerShellVersion -ne '5.1')
{
throw 'The winTerm PowerShell module manifest does not declare the supported version boundary.'
Expand Down
2 changes: 1 addition & 1 deletion scripts/winterm/verify-branding.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function Test-Manifest
Test-Requirement -Condition ($null -ne $identity -and $identity.Name -eq 'HelloThisWorld.winTerm') -Message "$Path uses package identity HelloThisWorld.winTerm"
Test-Requirement -Condition ($null -ne $identity -and $identity.Name -notmatch '^Microsoft\.') -Message "$Path does not use a Microsoft package name"
Test-Requirement -Condition ($null -ne $identity -and $identity.Publisher -ceq $ExpectedPublisher) -Message "$Path uses the expected non-Microsoft publisher"
Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.3.0.4') -Message "$Path uses package version 1.3.0.4"
Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.3.0.5') -Message "$Path uses package version 1.3.0.5"
Test-Requirement -Condition ($null -ne $properties -and $properties.DisplayName -eq 'winTerm') -Message "$Path package display name is winTerm"
Test-Requirement -Condition ($null -ne $application -and $application.Id -eq 'winTerm') -Message "$Path application ID is winTerm"
Test-Requirement -Condition ($null -ne $visualElements -and $visualElements.DisplayName -eq 'winTerm') -Message "$Path application display name is winTerm"
Expand Down
Loading