diff --git a/README.md b/README.md index 8647a32..2c1d55e 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/SPEC.md b/SPEC.md index 69b9d27..131399f 100644 --- a/SPEC.md +++ b/SPEC.md @@ -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) ``` diff --git a/installer/README.md b/installer/README.md index b5f809c..7e2b43e 100644 --- a/installer/README.md +++ b/installer/README.md @@ -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) ``` @@ -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-.exe` 7. Run `sign.ps1` against the output (`-Sign`) @@ -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 diff --git a/installer/build.ps1 b/installer/build.ps1 index ce4ec25..d4cc742 100644 --- a/installer/build.ps1 +++ b/installer/build.ps1 @@ -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 @@ -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). @@ -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)" diff --git a/installer/install.ps1 b/installer/install.ps1 index e241897..a59e72f 100644 --- a/installer/install.ps1 +++ b/installer/install.ps1 @@ -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 @@ -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." diff --git a/installer/installer.iss b/installer/installer.iss index 7399709..c38f730 100644 --- a/installer/installer.iss +++ b/installer/installer.iss @@ -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"""; \ StatusMsg: "Installing FastFlowLM runtime (~170 MB)..."; \ Check: NeedsFLM; \ Flags: waituntilterminated @@ -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; @@ -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; diff --git a/vendor/README.md b/vendor/README.md index 7ba064c..e6e17d8 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -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