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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ Install these first on a new machine:
4. Install FastFlowLM from [fastflowlm.com](https://fastflowlm.com/) or directly with PowerShell:

```powershell
Invoke-WebRequest https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.exe -OutFile flm-setup.exe
Start-Process .\flm-setup.exe -Wait
Invoke-WebRequest https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.msi -OutFile flm-setup.msi
Start-Process msiexec.exe -ArgumentList '/i', 'flm-setup.msi', '/quiet', '/norestart' -Wait
```

5. Open a new terminal and verify FastFlowLM:
Expand Down
1 change: 1 addition & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,5 @@ B43|2026-07-29|`fresh_modules` teardown popped `notes` after test collection; la
B44|2026-08-13|pre-release review: V57's `call_tool` raise (the B42 fix) went ⊥ caught by `get_minutes`/`get_transcript`/`search_meetings`/`list_recent_meetings`; `run_batch`'s pagination loop, `meeting_overview`, and `process_meeting`'s `NoContentError` skip-path all broke on any Quill tool error: scheduled batch could silently no-op (status never updated), Overview widget 500'd instead of `reachable=False`, dead meetings retried forever instead of perma-skip|V62; catch `QuillToolError` in the 4 public read fns, restore module's documented fail-soft contract
B45|2026-08-13|pre-release review: `_ensure_note_schema`'s migration write ran outside `_NOTES_LOCK` ∴ could race a locked `note_update`/`note_organize` on the same file (dueling `uuid4()` note_id, last-writer-wins corruption); `_load_note_index`/`_find_note_path` silently dropped a note from every listing/lookup on migration-write failure (e.g. read-only file)|V61; lock + double-check inside `_ensure_note_schema`; index/lookup fall back to unmigrated read on failure instead of dropping the note
B46|2026-08-13|pre-release review: `trash_note` was the only note-mutating fn ⊥ taking a `revision` param ∴ "Move to Trash" could silently act on a note that changed since the editor loaded it, unlike update/organize/archive; also `_act_note_archive`/`_act_notes_board_save` used a bare `int()` revision parse (raw 500 on bad input) unlike `_act_note_update`/`_act_note_organize`'s guarded parse|V54; add revision param + conflict check to `trash_note` + daemon action + app.js call site; guard the two bare `int()` parses to match the others
B47|2026-08-13|`v2.5.0` tag build failed: upstream FastFlowLM/FastFlowLM → ROCm/FastFlowLM org move + v1.0.1 "Windows Installer Switch" replaced `flm-setup.exe` w/ `flm-setup.msi`; `build.ps1 -BundleFlm` 404'd on the old filename, blocking `release-installer.yml`|fetch/vendor/chain `flm-setup.msi` (build.ps1, install.ps1, installer.iss [Files]/[Run] → `msiexec /i ... /quiet /norestart`); docs updated. UNVERIFIED: `NeedsFLM`/`FlmUninstallCmd` match uninstall subkeys by NAME PREFIX `"flm version "`, which the old Inno .exe set — an MSI install registers under a product-code GUID instead, so detection/uninstall-chaining may silently no-op until validated on a real machine (needs T8 clean-VM test)
```
6 changes: 3 additions & 3 deletions installer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Sibling folders consumed by these scripts:
├── scripts/ ← Python + AHK source
├── setup/defaults/ ← seed config shipped read-only
├── vendor/ahk/ ← AutoHotkey v2 portable (downloaded)
├── vendor/flm/ ← flm-setup.exe (downloaded)
├── vendor/flm/ ← flm-setup.msi (downloaded)
├── dist/FastFlowPrompt/ ← PyInstaller output (build artifact)
└── out/ ← signed installer .exe (build artifact)
```
Expand Down Expand Up @@ -69,7 +69,7 @@ Steps the script runs:
1. Read `scripts\_version.py` → derive version (e.g. `2.1.0`)
2. Generate `file_version_info.txt` for the Win32 VERSIONINFO resource
3. Download `vendor\ahk\AutoHotkey64.exe` if missing (`-BundleAhk`)
4. Download `vendor\flm\flm-setup.exe` if missing (`-BundleFlm`)
4. Download `vendor\flm\flm-setup.msi` if missing (`-BundleFlm`)
5. Run `pyinstaller --clean --noconfirm fastflowprompt.spec` → `dist\FastFlowPrompt\`
6. Run `iscc installer.iss` → `out\Flowkey-Setup-<version>.exe`
7. Run `sign.ps1` against the output (`-Sign`)
Expand All @@ -83,7 +83,7 @@ Debug flags:

1. Installs the PyInstaller bundle, AHK runtime, and AHK source scripts to
`C:\Program Files\FastFlowPrompt\` (read-only).
2. Chain-installs FastFlowLM by running the vendored `flm-setup.exe` silently —
2. Chain-installs FastFlowLM by running the vendored `flm-setup.msi` silently —
only if FLM isn't already on the machine. Drops a marker so the uninstaller
knows whether to chain-remove FLM later.
3. (Optional task) Creates a per-machine HKLM `Run` entry so AHK starts on
Expand Down
12 changes: 8 additions & 4 deletions installer/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
1. Read version from scripts/_version.py
2. Generate file_version_info.txt for the VERSIONINFO resource
3a. (optional) Download AHK v2 portable into vendor/ahk/
3b. (optional) Download flm-setup.exe into vendor/flm/
3b. (optional) Download flm-setup.msi into vendor/flm/
4. Run PyInstaller against installer/fastflowprompt.spec
5. Run Inno Setup compiler on installer/installer.iss
6. (optional) Sign the resulting installer with sign.ps1
Expand All @@ -18,7 +18,7 @@
Download AutoHotkey v2 portable into vendor/ahk/ (skipped if present).

.PARAMETER BundleFlm
Download flm-setup.exe into vendor/flm/ (skipped if present).
Download flm-setup.msi into vendor/flm/ (skipped if present).

.PARAMETER SkipPyInstaller
Skip the PyInstaller step (debugging).
Expand Down Expand Up @@ -142,11 +142,15 @@ if ($BundleAhk) {
if ($BundleFlm) {
$vendorDir = Join-Path $releaseRoot "vendor\flm"
if (-not (Test-Path $vendorDir)) { New-Item -ItemType Directory -Path $vendorDir -Force | Out-Null }
$flmDst = Join-Path $vendorDir "flm-setup.exe"
# FastFlowLM moved from FastFlowLM/FastFlowLM to ROCm/FastFlowLM and, as of
# v1.0.1, switched its Windows asset from an Inno-Setup .exe to an .msi
# (release title: "Windows Installer Switch"). GitHub redirects the old
# org's "latest" URL to the new one, so the URL below still works.
$flmDst = Join-Path $vendorDir "flm-setup.msi"
if (Test-Path $flmDst) {
"FLM installer already present: $flmDst"
} else {
$flmUrl = "https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.exe"
$flmUrl = "https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.msi"
"Downloading FLM installer from $flmUrl ..."
Invoke-WebRequest -Uri $flmUrl -OutFile $flmDst -UseBasicParsing
"Got: $flmDst ($([math]::Round((Get-Item $flmDst).Length/1MB,1)) MB)"
Expand Down
18 changes: 11 additions & 7 deletions installer/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
3. AutoHotkey v2 stage ahk\AutoHotkey64.exe (copy bundled vendor copy,
else download ahk-v2.zip). Same path _autostart_command_line()
resolves, so the dashboard toggle and this agree.
4. FastFlowLM detect 'flm', else run flm-setup.exe silently (one UAC)
4. FastFlowLM detect 'flm', else run flm-setup.msi silently (one UAC)
5. autostart write HKCU Run value Flowkey (logon launch)
6. launch start grammarFix.ahk via AutoHotkey64.exe

Expand Down Expand Up @@ -214,17 +214,21 @@ if ($SkipFlm) {
} elseif (Test-Command "flm") {
Ok "flm already on PATH."
} else {
$flmSetup = Join-Path $releaseRoot "vendor\flm\flm-setup.exe"
# FastFlowLM moved from FastFlowLM/FastFlowLM to ROCm/FastFlowLM and, as of
# v1.0.1, switched its Windows asset from an Inno-Setup .exe to an .msi
# (release title: "Windows Installer Switch"). GitHub redirects the old
# org's "latest" URL to the new one, so the URL below still works.
$flmSetup = Join-Path $releaseRoot "vendor\flm\flm-setup.msi"
if (-not (Test-Path $flmSetup)) {
Info "Downloading FastFlowLM installer (large -- hundreds of MB)..."
$flmSetup = Join-Path $env:TEMP "ffp-flm-setup.exe"
Invoke-WebRequest -Uri "https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.exe" `
$flmSetup = Join-Path $env:TEMP "ffp-flm-setup.msi"
Invoke-WebRequest -Uri "https://github.com/FastFlowLM/FastFlowLM/releases/latest/download/flm-setup.msi" `
-OutFile $flmSetup -UseBasicParsing
}
Info "Installing FastFlowLM (a UAC prompt is expected; install is silent after you accept)..."
$flmArgs = "/VERYSILENT /SUPPRESSMSGBOXES /NOCANCEL /NORESTART /SP- /NOICONS " +
"/CLOSEAPPLICATIONS /FORCECLOSEAPPLICATIONS /LANG=english"
$proc = Start-Process -FilePath $flmSetup -ArgumentList $flmArgs -Verb RunAs -Wait -PassThru
$flmLog = Join-Path $env:TEMP "ffp-flm-install.log"
$flmArgs = "/i `"$flmSetup`" /quiet /norestart /l*v `"$flmLog`""
$proc = Start-Process -FilePath "msiexec.exe" -ArgumentList $flmArgs -Verb RunAs -Wait -PassThru
Update-SessionPath
if (Test-Command "flm") {
Ok "FastFlowLM installed."
Expand Down
24 changes: 19 additions & 5 deletions installer/installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,16 @@ Source: "setup\defaults\*"; DestDir: "{app}\setup\defaults"; \
Flags: ignoreversion recursesubdirs skipifsourcedoesntexist

; --- FLM chained installer (extracted to tmp, run during install, then deleted)
Source: "vendor\flm\flm-setup.exe"; DestDir: "{tmp}"; \
; FastFlowLM switched its Windows asset from an Inno-Setup .exe to an .msi as
; of v1.0.1 ("Windows Installer Switch") — chained via msiexec below instead
; of running it directly.
Source: "vendor\flm\flm-setup.msi"; DestDir: "{tmp}"; \
Flags: deleteafterinstall ignoreversion skipifsourcedoesntexist; Check: NeedsFLM

[Run]
; --- 1. Chain FLM install (skipped if FLM already on this machine) ------------
Filename: "{tmp}\flm-setup.exe"; \
Parameters: "/VERYSILENT /SUPPRESSMSGBOXES /NOCANCEL /NORESTART /SP- /NOICONS /CLOSEAPPLICATIONS /FORCECLOSEAPPLICATIONS /LANG=english /LOG=""{tmp}\flm-install.log"""; \
Filename: "msiexec.exe"; \
Parameters: "/i ""{tmp}\flm-setup.msi"" /quiet /norestart /l*v ""{tmp}\flm-install.log"""; \
Comment on lines +142 to +143

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Uninstall the MSI through its product-code registration

When Flowkey installs the new MSI on a clean machine, the later uninstall chain cannot find it: FlmUninstallCmd still searches only for the old Inno Setup subkey prefix flm version and reads QuietUninstallString, whereas an MSI is registered under its product-code key and may require msiexec /x. Consequently, even when .flm_installed_by_us exists, uninstalling Flowkey executes the fallback echo FLM not registered and leaves the bundled FastFlowLM runtime installed; update the lookup/uninstall command as part of this installer switch.

Useful? React with 👍 / 👎.

StatusMsg: "Installing FastFlowLM runtime (~170 MB)..."; \
Check: NeedsFLM; \
Flags: waituntilterminated
Expand Down Expand Up @@ -211,7 +214,15 @@ Type: dirifempty; Name: "{app}"
const
FLM_REG_PREFIX = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\flm version ';

{ True if no FLM uninstall key is found AND no flm.exe exists in PF\FastFlowLM. }
{ True if no FLM uninstall key is found AND no flm.exe exists in PF\FastFlowLM.

CAUTION (unverified as of the v1.0.1 exe->msi switch): this scans for an
uninstall SUBKEY NAME starting with 'flm version ' — how FastFlowLM's old
Inno-Setup .exe installer named its own entry. An MSI-based install
typically registers its uninstall key under a product-code GUID instead,
which this prefix match would never find, falling through to the
{commonpf}\FastFlowLM\flm.exe path check below. Needs validation on a real
machine with the new .msi installer (see SPEC.md B47 / T8 clean-VM test). }
function NeedsFLM(): Boolean;
var
Names: TArrayOfString;
Expand Down Expand Up @@ -242,7 +253,10 @@ begin
end;

{ Locate the FLM QuietUninstallString from the 32-bit Uninstall hive.
Returns a cmd-runnable string, or '' if FLM isn't registered. }
Returns a cmd-runnable string, or '' if FLM isn't registered.

Same 'flm version ' subkey-name assumption as NeedsFLM above, and the same
post-v1.0.1-msi caveat: unverified whether it still finds the entry. }
function FlmUninstallCmd(Param: String): String;
var
Names: TArrayOfString;
Expand Down
2 changes: 1 addition & 1 deletion vendor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ in source control — `installer/build.ps1` downloads them on demand.
```

The build script is idempotent — it skips a download if the file is already
present. Delete `vendor/ahk/AutoHotkey64.exe` or `vendor/flm/flm-setup.exe`
present. Delete `vendor/ahk/AutoHotkey64.exe` or `vendor/flm/flm-setup.msi`
to force a fresh pull (e.g. when picking up a new upstream version).

## Pinning
Expand Down