terraphim_grep 1.21.1

Intelligent hybrid grep with RLM fallback and KG curation
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
# Implementation Plan: terraphim_grep v1.20.0 Release

**Status**: Draft (awaiting approval)
**Research Doc**: `crates/terraphim_grep/RELEASE_RESEARCH.md`
**Author**: Alex (via disciplined-design skill)
**Date**: 2026-05-24
**Estimated Effort**: 1-2 days (excluding any unexpected cross-compile issues)

## Overview

### Summary

Ship terraphim_grep as part of a workspace 1.20.0 release. All standard distribution
channels live from day one: crates.io, GitHub Release, Gitea Release mirror, Homebrew,
Debian package, signed/notarised macOS, Windows binary. Tag `terraphim_grep-v1.20.0`.

### Approach

Sequenced into six gated stages, each with a clear pass/fail signal. The Vital Few from
research:
1. Unblock crates.io (now trivial -- fff-search 0.8.2 is on crates.io as of 2026-05-24)
2. Cross-platform binaries on all 7 standard targets via existing matrix
3. Signed + notarised macOS via existing self-hosted runners

### Scope

**In Scope:**
- Bump workspace 1.19.3 -> 1.20.0
- Bump `fff-search` from git pin to crates.io `0.8.2`, verify API compatibility (0.5.1 -> 0.8.2 is non-trivial)
- Extend `release-comprehensive.yml` to build/sign/package terraphim_grep for all 7 targets
- Extend `publish-crates.sh` to publish terraphim_grep in dependency order
- Author `Formula/terraphim-grep.rb` for the homebrew-terraphim tap
- Add `[[package]]` entry to `.release-plz.toml`
- Write `RELEASE_NOTES_v1.20.0.md` (rename of v1.19.3 file)
- Cross-compile spike on local + bigbox
- `workflow_dispatch test_run: true` dry-run
- Merge PR #1825 to main
- Tag `terraphim_grep-v1.20.0` from main HEAD
- Per-channel rollback procedures, exercised at least once via dry-run

**Out of Scope:**
- `terraphim_server`, `terraphim_agent`, `terraphim-cli` release content (they ride the
  workspace bump but their release notes are separate)
- Docker image for terraphim_grep specifically
- New features (the v1.20.0 release is the existing PR #1825 work, nothing more)

**Avoid At All Cost** (5/25 elimination list):
- Refactoring fff-search adoption to feature-gate per-platform (over-engineering;
  if it builds for one target it should build for all)
- Introducing a new versioning scheme (CalVer vs SemVer) -- stick with workspace SemVer
- Publishing additional terraphim crates we hadn't planned to (scope creep)
- Adding ARM Windows or BSD targets (out of matrix scope)
- Writing custom release-note generation (release-plz already does it)
- Auto-tweet integration (manual is fine for a single release)
- Adding new linters/checks to the release pipeline (zero changes to CI logic outside what's strictly required)

## Open Question Resolution

| Question | Answer | Source |
|---|---|---|
| Versioning | Workspace-aligned (bump workspace 1.19.3 -> 1.20.0) | User decision 2026-05-24 |
| Tag | `terraphim_grep-v1.20.0` (component-prefixed, workspace-aligned number) | User decision; note: the AskUserQuestion option labelled "terraphim_grep-v0.1.0" was a pattern example, not literal -- confirm interpretation |
| fff-search publish | **Already done** -- 0.8.2 stable on crates.io as of 2026-05-24 | crates.io API check |
| Release notes scope | Crate-focused | User decision 2026-05-24 |

## Architecture

### Release Pipeline Sequence

```
+---------------------+    +------------------------+    +--------------------+
| Stage 1: Prereqs    |    | Stage 2: Workflow      |    | Stage 3: Local     |
| - fff-search bump   |--> | extensions             |--> | cross-compile      |
| - API compat fix    |    | - matrix + Debian +    |    | - verify 7 targets |
| - Workspace 1.20.0  |    |   Homebrew + crates.io |    |   build clean      |
+---------------------+    +------------------------+    +--------------------+
                                                                  |
                                                                  v
+---------------------+    +------------------------+    +--------------------+
| Stage 6: Post-      |<-- | Stage 5: Tag + execute |<-- | Stage 4: Dry-run   |
| release verify      |    | - merge PR #1825       |    | workflow_dispatch  |
| - Each channel      |    | - push tag from main   |    | with test_run=true |
| - Update marketing  |    |                        |    |                    |
+---------------------+    +------------------------+    +--------------------+
```

### Key Design Decisions

| Decision | Rationale | Alternatives Rejected |
|---|---|---|
| Workspace 1.20.0 minor bump (not patch or major) | New feature (KG boost) but backward-compatible APIs | Patch (1.19.4) misrepresents the change; major (2.0.0) overstates it |
| Tag `terraphim_grep-v1.20.0` | Component-prefixed convention matches server/agent/desktop precedent; tag number matches workspace version for verify-versions step | Standalone `v1.20.0` would treat it as a workspace release with no clear grep emphasis; would also conflict if a separate workspace tag is pushed |
| Bump fff-search to crates.io 0.8.2 | The blocker is gone -- it's published. 0.5.1 git -> 0.8.2 crates.io may break our usage; that's a Stage 1 risk to surface early | Stay on git: blocks crates.io publish, holds whole release hostage |
| All 7 standard targets, not just the verified darwin-arm64 | Full coverage policy (memory `feedback_release_scope_full_coverage.md`); existing matrix already builds 7 for server/agent/cli; consistency matters | Subset: redo work at v1.20.1 with "now with Windows"; wastes infra investment |
| Crate-focused release notes (`RELEASE_NOTES_v1.20.0.md` under the crate dir) | Tag is component-scoped; notes scope matches tag scope | Workspace-context notes: dilutes the grep story with unrelated workspace changes |
| Merge-then-tag (PR #1825 lands on main first) | Tag points to merge commit, not feature branch; safer for verify-versions step which reads workspace state | Tag the feature branch: stale tag if branch gets squash-merged or rebased |

### Eliminated Options (Essentialism)

| Option Rejected | Why Rejected | Risk of Including |
|---|---|---|
| Auto-generate `Formula/terraphim-grep.rb` from a template | Single formula, manual authoring is faster than building generation | Maintenance burden of a generator for one formula |
| Custom signing certificate for terraphim_grep | Reuse the existing Developer ID Application certificate from 1Password | Duplicate Apple developer account work for no benefit |
| Add terraphim_grep to the auto-update mechanism | terraphim_grep is invoked per-command, not a long-running service | Stale-update bugs we'd inherit |
| Multi-architecture Docker image | Out of scope per research | Image bloat, multi-stage build complexity |
| Pre-release / RC tag (`terraphim_grep-v1.20.0-rc.1`) | Pipeline doesn't differentiate prerelease behaviour beyond GitHub release flag; existing release-comprehensive workflow handles `rc` in tag name correctly | Extra ceremony for a release with already-verified L3 e2e |
| Manual sha256 generation per platform | The CI workflow generates checksums for tarballs/zips already | Drift between local and CI checksums |
| Posting follow-up X thread automatically | Marketing is one human decision per channel, not automated | Premature automation |

### Simplicity Check

**What if this could be easy?** The simplest path is:
1. Two-line Cargo.toml edits (workspace version + fff-search version)
2. Six-line workflow edit (add terraphim_grep-v* trigger, add to BINARIES verify, add three cargo build lines, add to Debian packaging, add to release notes body)
3. Six-line publish-crates.sh edit (add terraphim_grep to ordered list)
4. One new Homebrew formula file
5. Three-line release-plz.toml addition
6. One file rename + content update for release notes
7. Tag + push

If any of these turn into more than that, surface the complication rather than absorb it
silently.

**Senior Engineer Test**: Would a senior call this overcomplicated? The framework is
clear: reuse existing infrastructure. The only place complexity could leak in is the
fff-search 0.5.1 -> 0.8.2 API change, which Stage 1 verifies before anything else.

**Nothing Speculative Checklist**:
- [x] No features the user didn't request (release-only PR)
- [x] No abstractions "in case we need them later" (no new release-mgmt code)
- [x] No flexibility "just in case" (specific channels, specific targets)
- [x] No error handling for scenarios that cannot occur
- [x] No premature optimization

## File Changes

### New Files

| File | Purpose |
|---|---|
| `crates/terraphim_grep/RELEASE_NOTES_v1.20.0.md` | Crate-focused release notes (renamed from existing `RELEASE_NOTES_v1.19.3.md`) |
| `crates/terraphim_grep/RELEASE_RESEARCH.md` | Already exists (Phase 1 output) |
| `crates/terraphim_grep/RELEASE_DESIGN.md` | This file (Phase 2 output) |
| `Formula/terraphim-grep.rb` (in `terraphim/homebrew-terraphim` tap, separate repo) | Homebrew formula |

### Modified Files

| File | Changes |
|---|---|
| `Cargo.toml` (workspace) | Bump `version` 1.19.3 -> 1.20.0 |
| `crates/terraphim_grep/Cargo.toml` | Change `fff-search` from git source to `version = "0.8.2"`; remove the `branch = "feat/external-scorer"` reference. The crate version stays `version.workspace = true` (so it inherits 1.20.0). |
| `crates/terraphim_grep/src/hybrid_searcher.rs` | Possible API adjustments if `fff_search::{FilePicker, FilePickerOptions, FFFMode, GrepMode, GrepSearchOptions, ContentCacheBudget, grep_search, parse_grep_query}` signatures changed between 0.5.1 and 0.8.2. Investigation in Step 1.2. |
| `.github/workflows/release-comprehensive.yml` | (1) Add `terraphim_grep-v*` to the on.push.tags list. (2) Add `terraphim_grep` to the BINARIES array in `verify-versions`. (3) Add `cargo build --release --target ... -p terraphim_grep --bin terraphim-grep --features "code-search openrouter"` after the existing `terraphim-cli` build. (4) Add `terraphim-grep` to the binary-list in the artifact-preparation steps for Unix and Windows. (5) Add `terraphim-grep` to the Debian packaging job. (6) Update the GitHub release `body:` to mention `terraphim-grep-*` binaries. |
| `scripts/publish-crates.sh` | Add `terraphim_grep` to the `CRATES=()` array at the correct dependency-ordered position (after `terraphim_service` since grep depends on it transitively via the `llm` feature). |
| `.release-plz.toml` | Add a `[[package]] name = "terraphim_grep"` block with `changelog_path` set to the per-crate CHANGELOG if we choose to have one, or omitted to use the workspace CHANGELOG. |
| `crates/terraphim_grep/RELEASE_NOTES_v1.19.3.md` | Rename to `RELEASE_NOTES_v1.20.0.md`. Update version references, SHA-256s after CI build, link to PR #1825 merge commit. |

### Deleted Files

| File | Reason |
|---|---|
| (none) | The v1.19.3 release notes file gets renamed, not deleted |

## Tagged Asset Surface

What the GitHub release page will contain after the tag fires:

| Asset | Origin |
|---|---|
| `terraphim-grep-x86_64-unknown-linux-gnu.tar.gz` + `.sha256` | matrix |
| `terraphim-grep-x86_64-unknown-linux-musl.tar.gz` + `.sha256` | matrix (cross) |
| `terraphim-grep-aarch64-unknown-linux-musl.tar.gz` + `.sha256` | matrix (cross) |
| `terraphim-grep-armv7-unknown-linux-musleabihf.tar.gz` + `.sha256` | matrix (cross) |
| `terraphim-grep-x86_64-apple-darwin.tar.gz` + `.sha256` | self-hosted macOS X64 (signed + notarised) |
| `terraphim-grep-aarch64-apple-darwin.tar.gz` + `.sha256` | self-hosted macOS ARM64 (signed + notarised) |
| `terraphim-grep-universal-apple-darwin.tar.gz` + `.sha256` | lipo of the two darwin builds |
| `terraphim-grep-x86_64-pc-windows-msvc.zip` + `.sha256` | windows-latest |
| `terraphim-grep_1.20.0_amd64.deb` | Debian job |
| `terraphim-grep_1.20.0_arm64.deb` | Debian job |
| Source tarball | GitHub automatic |

Plus on the Homebrew tap:
- `Formula/terraphim-grep.rb` referencing the universal macOS binary

## API Design

No new public APIs in this release. The release surface is the *artefact set*, not the
crate's library API.

## Test Strategy

### Pre-tag Verification

| Verification | Tool/Command | Pass Criterion |
|---|---|---|
| fff-search 0.8.2 API compat | `cargo build -p terraphim_grep --features code-search` | No errors; existing 21 lib tests pass |
| Cross-compile linux-musl x86_64 | `cargo build --release --target x86_64-unknown-linux-musl -p terraphim_grep --features "code-search openrouter"` (via `cross`) | Binary produced |
| Cross-compile linux-musl aarch64 | same, target swapped | Binary produced |
| Cross-compile windows-msvc | `cross build --target x86_64-pc-windows-msvc ...` or windows runner test_run | Binary produced |
| Workflow dry-run | `gh workflow run release-comprehensive.yml -f test_run=true` | All matrix jobs pass; no GitHub release created |
| Publish dry-run | `cargo publish -p terraphim_grep --dry-run --features code-search` | Returns "Verifying" success not "all dependencies must have a version" |

### Post-tag Verification

| Verification | Tool/Command | Pass Criterion |
|---|---|---|
| Tag triggered workflow | `gh run list --workflow=release-comprehensive.yml --limit 1` | Workflow run started with the tag's SHA |
| All matrix jobs green | `gh run view <run-id>` | All `build-binaries` jobs `success` |
| Release page populated | `gh release view terraphim_grep-v1.20.0` | All expected assets listed |
| crates.io listing | `cargo search terraphim_grep` | Version 1.20.0 returned |
| Homebrew formula | `brew install terraphim/terraphim/terraphim-grep` on a clean Mac | Installs without error; `terraphim-grep --version` reports `1.20.0` |
| Debian install | `dpkg -i terraphim-grep_1.20.0_amd64.deb` on Ubuntu | Installs without error |
| End-to-end smoke per platform | Run the same `parse_grep_query` fixture command used in earlier L3 verification | Returns chunks; sufficiency=SearchOnly without LLM, RlmSynthesis with OPENROUTER_API_KEY set |

## Implementation Steps

### Stage 1: Prerequisites (estimated 2-4 hours)

**Step 1.1: Bump fff-search dependency**
- Files: `crates/terraphim_grep/Cargo.toml`
- Change: `fff-search = { git = "...", branch = "feat/external-scorer", optional = true }` to `fff-search = { version = "0.8.2", optional = true }`
- Test: `cargo build -p terraphim_grep --features code-search 2>&1`
- Expected outcome: either clean build (best case) or compile errors that indicate API drift between 0.5.1 and 0.8.2

**Step 1.2: Fix any 0.5.1 -> 0.8.2 API drift**
- Files: `crates/terraphim_grep/src/hybrid_searcher.rs` (the only file using `fff_search::*`)
- Approach: read the 0.8.2 docs on crates.io; update the eight imported symbols (`FilePicker, FilePickerOptions, FFFMode, GrepMode, GrepSearchOptions, ContentCacheBudget, grep_search, parse_grep_query`) to their new shapes
- Test: `cargo test -p terraphim_grep --features code-search` -- 24 unit + 3 router tests pass
- Bench: `cargo bench -p terraphim_grep --bench hybrid_search -- --test` -- all four groups still pass smoke
- If fff-search 0.8.2 has dropped or renamed any of those APIs, surface as a Step 1.2 blocker

**Step 1.3: Workspace version bump**
- Files: `Cargo.toml` (workspace `[workspace.package]` section)
- Change: `version = "1.19.3"` -> `version = "1.20.0"`
- Test: `cargo metadata --no-deps --format-version=1 | jq '.packages[] | select(.name == "terraphim_grep") | .version'` returns `1.20.0`
- Side effect: every workspace crate now reports 1.20.0; this is expected for a workspace-aligned bump

**Step 1.4: Verify publishability via dry-run**
- Command: `cargo publish -p terraphim_grep --dry-run --features code-search`
- Expected: success message ending with "Packaging" and "Verifying" but no upload

### Stage 2: Workflow Extensions (estimated 3-5 hours)

**Step 2.1: Add tag trigger**
- File: `.github/workflows/release-comprehensive.yml` (line 4-7, the `on.push.tags` list)
- Change: add `- 'terraphim_grep-v*'` after the existing patterns
- Test: cannot test until Stage 4 dry-run

**Step 2.2: Extend verify-versions BINARIES list**
- File: `.github/workflows/release-comprehensive.yml` (around line 76)
- Change: `BINARIES=("terraphim_server" "terraphim_agent" "terraphim-cli" "terraphim_grep")`
- Test: dry-run validates against workspace version

**Step 2.3: Add cargo build steps for all 7 targets**
- File: `.github/workflows/release-comprehensive.yml` (after the `terraphim-cli` build step, around line 226)
- Change: add (one per relevant build context)
  ```yaml
  - name: Build grep binary
    if: matrix.target != 'armv7-unknown-linux-musleabihf'  # skip armv7 to mirror current cli scope
    run: |
      cargo build --release \
        --target ${{ matrix.target }} \
        -p terraphim_grep \
        --bin terraphim-grep \
        --features "code-search openrouter"
  ```
- Test: dry-run produces binaries in expected paths

**Step 2.4: Add to artefact prep**
- File: `.github/workflows/release-comprehensive.yml` (the Unix prep step around line 266, Windows around line 290)
- Change: copy `target/${{ matrix.target }}/release/terraphim-grep[.exe]` into the artefact staging dir alongside the other three binaries
- Test: dry-run produces tarballs/zips containing the binary

**Step 2.5: Add to Debian packaging**
- File: `.github/workflows/release-comprehensive.yml` (the `build-debian-packages` job)
- Change: emit a `terraphim-grep_${VERSION}_${ARCH}.deb` alongside the existing server/agent packages. Uses `cargo-deb` (already in the workflow). Requires adding a `[package.metadata.deb]` block to `crates/terraphim_grep/Cargo.toml` with maintainer / depends fields modelled on `crates/terraphim_server/Cargo.toml`.
- Test: dry-run produces .deb file

**Step 2.6: Update GitHub release body**
- File: `.github/workflows/release-comprehensive.yml` (lines 663-700 area)
- Change: add a "### Grep Binaries" section mentioning `terraphim-grep-*` and pointing to `crates/terraphim_grep/RELEASE_NOTES_v1.20.0.md` for crate-focused details
- Test: dry-run produces expected release body text

### Stage 3: Publish & Tap Plumbing (estimated 2 hours)

**Step 3.1: Add to publish-crates.sh**
- File: `scripts/publish-crates.sh` (the `CRATES=()` array around line 50)
- Change: append `"terraphim_grep"` after the last entry. Ordering note: grep depends on terraphim_service, terraphim_router, terraphim_rolegraph, terraphim_automata, terraphim_types, terraphim_config -- all of which appear earlier in the list. Safe to append.
- Test: `./scripts/publish-crates.sh -v 1.20.0 -c terraphim_grep --dry-run`

**Step 3.2: Add to .release-plz.toml**
- File: `.release-plz.toml`
- Change: add
  ```toml
  [[package]]
  name = "terraphim_grep"
  publish = true
  semver_check = true
  ```
- Test: `release-plz update --dry-run` (if release-plz is locally available)

**Step 3.3: Author Homebrew formula**
- File: `Formula/terraphim-grep.rb` in the separate `terraphim/homebrew-terraphim` repo (not this workspace)
- Template (verify the SHA-256 placeholders are filled after Stage 5):
  ```ruby
  class TerraphimGrep < Formula
    desc "Intelligent hybrid grep with knowledge-graph boosting and LLM fallback"
    homepage "https://github.com/terraphim/terraphim-ai"
    version "1.20.0"
    license "MIT"

    on_macos do
      url "https://github.com/terraphim/terraphim-ai/releases/download/terraphim_grep-v1.20.0/terraphim-grep-universal-apple-darwin.tar.gz"
      sha256 "TBD_AFTER_CI_BUILD"
    end

    on_linux do
      if Hardware::CPU.intel?
        url "https://github.com/terraphim/terraphim-ai/releases/download/terraphim_grep-v1.20.0/terraphim-grep-x86_64-unknown-linux-musl.tar.gz"
        sha256 "TBD_AFTER_CI_BUILD"
      elsif Hardware::CPU.arm?
        url "https://github.com/terraphim/terraphim-ai/releases/download/terraphim_grep-v1.20.0/terraphim-grep-aarch64-unknown-linux-musl.tar.gz"
        sha256 "TBD_AFTER_CI_BUILD"
      end
    end

    def install
      bin.install "terraphim-grep"
    end

    test do
      system "#{bin}/terraphim-grep", "--version"
    end
  end
  ```
- Test: `brew install --build-from-source ./Formula/terraphim-grep.rb` locally on a Mac after Stage 5 lands SHA-256s
- Commit and push to the tap repo only after the GitHub release is live and SHA-256s are known. The existing release workflow has an "Update Homebrew tap" step (line 762 area) -- update that step to also handle the terraphim-grep formula by templating SHA-256s in.

### Stage 4: Cross-compile Spike (estimated 2 hours)

**Step 4.1: Local cross-compile via `cross`**
- Commands (run on darwin-arm64 dev box):
  ```bash
  cargo install cross --git https://github.com/cross-rs/cross  # if not present
  cross build --release --target x86_64-unknown-linux-musl -p terraphim_grep --features "code-search openrouter"
  cross build --release --target aarch64-unknown-linux-musl -p terraphim_grep --features "code-search openrouter"
  cross build --release --target armv7-unknown-linux-musleabihf -p terraphim_grep --features "code-search openrouter"
  ```
- Test: all three produce binaries; `file target/<target>/release/terraphim-grep` confirms architecture
- Risk: `git2` (transitively via fff-search?) may need `vendored-openssl` or similar feature for musl. If it fails, surface as a Stage 4 blocker.

**Step 4.2: Windows verification**
- Cannot cross-compile to Windows MSVC from Mac without significant setup. Instead: do this verification via the Stage 5 dry-run (windows-latest runner).
- If the Stage 5 dry-run fails on Windows, treat as a Stage 4 blocker -- do not proceed to the real tag.

**Step 4.3: macOS aarch64 (native)**
- Command: `cargo build --release -p terraphim_grep --features "code-search openrouter"` (we have already done this; it works)
- Test: already done -- verified in commit `fb261af30`

### Stage 5: Workflow Dry-Run (estimated 1-2 hours plus CI wait time)

**Step 5.1: Trigger workflow_dispatch**
- Command: `gh workflow run release-comprehensive.yml -f test_run=true --ref task/1743-terraphim-grep` (run from feature branch BEFORE merging, so we can iterate)
- Test: workflow run starts; all matrix jobs reach completion; no GitHub release is created (test_run=true blocks that)

**Step 5.2: Address any matrix failures**
- Most likely failure mode: Windows MSVC build of fff-search if git2 TLS isn't configured
- Mitigation: if fff-search needs platform-specific features for Windows, add them to terraphim_grep's Cargo.toml via target-specific dep configuration:
  ```toml
  [target.'cfg(windows)'.dependencies]
  fff-search = { version = "0.8.2", optional = true, features = ["vendored-openssl"] }
  ```

**Step 5.3: Verify artefact shapes**
- Download artefacts from the dry-run via `gh run download <run-id>`
- Confirm: every expected tarball/zip exists, contains the binary, runs `--version`

### Stage 6: Merge + Tag (estimated 30 minutes)

**Step 6.1: Merge PR #1825**
- Command: `gtr merge-pull --owner terraphim --repo terraphim-ai --index 1825` (or via Gitea web UI)
- Test: `git fetch origin main && git log origin/main --oneline -5` shows the merged commits

**Step 6.2: Pull main**
- Commands: `git checkout main && git pull origin main`

**Step 6.3: Tag from main HEAD**
- Commands:
  ```bash
  git tag -a terraphim_grep-v1.20.0 -m "terraphim_grep v1.20.0: hybrid search with KG boost and LLM fallback"
  git push origin terraphim_grep-v1.20.0
  ```
- Test: `gh run list --workflow=release-comprehensive.yml --limit 1` shows the tag-triggered run starting

**Step 6.4: Monitor the release run**
- Command: `gh run watch <run-id>` (or `tea` equivalent)
- Test: all jobs green; GitHub release page populated; crates.io publish step succeeded

### Stage 7: Post-Release (estimated 1 hour)

**Step 7.1: Capture SHA-256s and update Homebrew formula**
- Download each release asset; compute sha256; update `Formula/terraphim-grep.rb` in the tap repo with real values
- The workflow's existing "Update Homebrew tap" step should do this automatically -- verify it actually wrote the new formula. If manual, PR the formula to the tap repo.

**Step 7.2: Update release notes with final SHA-256s**
- File: `crates/terraphim_grep/RELEASE_NOTES_v1.20.0.md`
- Edit: replace placeholder SHA-256s with actual values from CI artefacts
- Commit on main as a documentation patch

**Step 7.3: Verify each channel from a clean machine**
- crates.io: `cargo install terraphim_grep --version 1.20.0 --features code-search` on a machine that hasn't seen this repo
- Homebrew: `brew install terraphim/terraphim/terraphim-grep` on a clean Mac
- Debian: `wget terraphim-grep_1.20.0_amd64.deb && sudo dpkg -i ...` on a clean Ubuntu VM (or bigbox)
- GitHub Release: download the darwin-arm64 tarball, extract, run `--version`
- Each smoke: run the parse_grep_query fixture command from earlier verification

**Step 7.4: Post-release marketing**
- Single follow-up tweet under the existing thread pointing to the GitHub release URL
- No new thread, no Reddit follow-up (the original drafts are still ready in `docs/src/blog/reddit-grep-announcement.md` -- post when ready, independently)
- Update the long-form blog post (`docs/blog/terraphim-grep-hybrid-search-with-llm-fallback.md`) with the "How to install" section pointing at the release URL

## Rollback Plan

For each channel, the rollback recipe + when to use it:

| Channel | Rollback Command | When to Use | Reversibility |
|---|---|---|---|
| crates.io | `cargo yank --vers 1.20.0 terraphim_grep` | Critical bug, security issue | Hard -- yank does not delete; everyone keeps their resolved versions, but new downloads are blocked |
| GitHub Release | `gh release delete terraphim_grep-v1.20.0 --yes` (keeps tag) or `gh release delete terraphim_grep-v1.20.0 --yes --cleanup-tag` (also deletes tag) | Mistake before downloads happen; quick recall | Soft -- can re-publish |
| Gitea Release | `tea release delete terraphim_grep-v1.20.0 --repo terraphim/terraphim-ai` | Same as GitHub | Soft |
| Homebrew tap | `cd homebrew-terraphim && git revert <commit-that-added-formula> && git push origin main` | Bad binary, broken formula | Soft -- users on the tap get the revert on next `brew update` |
| Debian | Supersede with `terraphim_grep_1.20.1_*.deb` carrying the fix; users get it on next `apt upgrade`. No way to "unpublish" a .deb already downloaded. | Bad binary | Forward-only; no real "remove" |
| Tag itself | `git push origin :refs/tags/terraphim_grep-v1.20.0` (delete) -- **only acceptable within the first hour and only if no users have cloned** | Catastrophic CI mistake | Hard -- destroys provenance |

**General principles**:
- Prefer a patch release (`1.20.1`) over a rollback. The release pipeline is fast enough that a fix-forward is usually cheaper than the support load of a partial rollback.
- Never force-push tags. The release workflow records SHA mappings; force-push breaks them.
- Each rollback step in the table above should be exercised at least once in dry-run mode (i.e., for crates.io, do a `cargo publish --dry-run` of 1.20.1 with the proposed fix; for Homebrew, do the revert locally without pushing).

## Migration (if applicable)

No database changes. No data migration. The "migration" is users moving from
"build-from-source" to one of the published channels -- documented in release notes.

## Dependencies

### New Dependencies

| Crate | Version | Justification |
|---|---|---|
| `fff-search` | bumped from git 0.5.1 to crates.io 0.8.2 | Unblocks crates.io publish |

### Dependency Updates

| Crate | From | To | Reason |
|---|---|---|---|
| `fff-search` | git (0.5.1) | crates.io 0.8.2 | Unblocks crates.io publish for terraphim_grep |

Side effect: `cargo update` will resolve the new fff-search across the lockfile. Verify
no other crate in the workspace breaks (look at `cargo tree -i fff-search`).

## Performance Considerations

Release artefacts are static binaries; runtime performance is unchanged from PR #1825
(which already has benchmarks for hybrid search and KG boost overhead). No release-
specific benchmarks needed.

Build performance: cross-compilation via `cross` adds ~5-10 min per non-native target.
The existing matrix runs them in parallel, so total wall-clock for the release run is
dominated by the slowest job (typically macOS sign+notarise at ~15-20 min).

## Software Release Definition (SRD)

Not applicable -- this is an internal release without formal SRD requirements.

## Open Items (Resolved 2026-05-24)

| Item | Resolution |
|---|---|
| Tag number | `terraphim_grep-v1.20.0` -- workspace-aligned in both crate version and tag |
| `[package.metadata.deb]` block | Copy from `crates/terraphim_server/Cargo.toml` defaults, adjust description and binary name |
| Docker image for terraphim_grep | **Out of scope** -- terraphim_grep is a CLI invoked per-command, not a service |
| Workspace `v1.20.0` tag in addition to `terraphim_grep-v1.20.0` | **In scope** -- full workspace release as part of this work. Requires full workspace testing before tagging. |
| verify-versions for component-prefixed tag | Verified via Stage 5 dry-run |

## Expanded Scope: Full Workspace Release

Because v1.20.0 ships as both a workspace tag (`v1.20.0`) AND a component tag
(`terraphim_grep-v1.20.0`), the full workspace must be production-ready, not just grep.
This adds:

**Stage 0 (new): Full workspace test gate**
- `cargo test --workspace --features "code-search openrouter"` -- all crates pass
- `cargo build --workspace --release` -- entire workspace compiles
- `cargo clippy --workspace --tests --benches -- -D warnings` -- zero warnings
- `cargo fmt --all -- --check` -- clean
- Each binary (`terraphim_server`, `terraphim-agent`, `terraphim-cli`, `terraphim-grep`)
  runs `--version` and reports `1.20.0`
- Existing live integration tests (`-- --ignored`) pass at least for terraphim_service +
  terraphim_grep that have OpenRouter dependencies
- **Gate criterion**: cannot proceed to Stage 1 if any workspace test or build fails.
  If a non-grep crate has a real defect at 1.20.0, that's a separate PR before tagging.

**Stage 5 (expanded): Dry-run must succeed for ALL binaries**
- The existing `test_run=true` dispatch builds server + agent + cli; with my edits it
  also builds grep. All four binaries must pass for the run to be acceptable.

**Stage 7 (expanded): Post-release verification per binary**
- Smoke `--version` against each of the 4 published binaries on each of the platforms
  they ship for. Mostly automatable via a small shell script.

## Risk Register

| Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|
| fff-search 0.5.1 -> 0.8.2 API drift requires substantive code changes | High | Medium | Stage 1.2 catches early; if drift is large, can revert the bump and ship without crates.io | Alex |
| Cross-compile fails on linux-musl or windows due to fff-search deps | Medium | Medium | Stage 4 spike catches before Stage 5; mitigation is target-specific features in Cargo.toml | Alex |
| Workflow edit breaks server/agent releases | Low | High | Stage 5 dry-run on the feature branch verifies; the edits are additive (new BINARIES entry, new build steps) not destructive | Alex |
| Homebrew tap formula has a typo that breaks `brew install` | Medium | Low | Stage 7.3 verification from a clean Mac catches it; fix-forward is 5 minutes | Alex |
| Marketing audience tries to install before the release lands | Medium | Low | Stage 6 (tag + workflow) takes ~30 min from merge; communicate ETA | Alex |
| 1Password Apple credentials expire or break | Low | High | Existing server/agent releases use the same credentials; if broken, blocks all macOS-signed releases; would surface as Stage 5 failure | (out of band) |

## Approval

- [ ] Technical review complete
- [ ] Test strategy approved
- [ ] Risk register acknowledged
- [ ] Tag number resolved (1.20.0 vs 0.1.0)
- [ ] Open items addressed or explicitly deferred
- [ ] Human approval received

## Next Steps After Approval

1. Phase 2.5 (disciplined-specification) -- optional; this design is detailed enough that
   specification interview would mostly be confirmation rather than discovery
2. Phase 3 (disciplined-implementation) -- execute Stages 1-7 in order
3. Phase 4 (disciplined-verification) -- verify each channel from a clean machine
4. Phase 5 (disciplined-validation) -- check the release meets the success criteria from
   the research doc (install time <60s, cross-platform, reproducible, rollback documented)