| 1 | # Session Init Reference |
| 2 | |
| 3 | Procedures the coordinator runs at session start, in order. Each step is |
| 4 | self-contained, fails silent, and degrades to "show normal greeting." |
| 5 | |
| 6 | --- |
| 7 | |
| 8 | ## Step 1: Update Check |
| 9 | |
| 10 | Check whether a newer Squad version exists for the user's channel. Append to |
| 11 | the greeting if a newer version is found. Never block the session; every |
| 12 | failure path ends at "show normal greeting." |
| 13 | |
| 14 | ### 1.1 Kill Switch |
| 15 | |
| 16 | If the environment variable `SQUAD_NO_UPDATE_CHECK` is set to `1`, **skip |
| 17 | Step 1 entirely** and show the normal greeting. This is the same kill switch |
| 18 | as the upstream CLI banner — one opt-out disables both. |
| 19 | |
| 20 | ### 1.2 Channel Detection |
| 21 | |
| 22 | Read the stamped version from the `<!-- version: X -->` HTML comment at the |
| 23 | top of `squad.agent.md` (or from the `- **Version:** X` identity line as |
| 24 | fallback). Classify the channel: |
| 25 | |
| 26 | | Stamped version contains | Channel | |
| 27 | |--------------------------|-----------| |
| 28 | | `-insider` | `insider` | |
| 29 | | `-preview` | `preview` | |
| 30 | | (neither) | `latest` | |
| 31 | |
| 32 | Store the stamped version as `currentVersion` and the detected channel. |
| 33 | |
| 34 | ### 1.3 Hybrid Cache Strategy |
| 35 | |
| 36 | The strategy differs by channel to avoid redundant network calls for the |
| 37 | common (`latest`) case. |
| 38 | |
| 39 | #### For `latest` channel — read upstream OS-specific cache |
| 40 | |
| 41 | The upstream Squad CLI (`self-update.ts`) already fetches the latest version |
| 42 | on startup and writes it to an OS-specific path with a 24h TTL. Read that |
| 43 | cache instead of making a new npm call. |
| 44 | |
| 45 | **One-liner to read the upstream cache:** |
| 46 | ``` |
| 47 | node -e "const p=require('path'),o=require('os');const b=process.env.APPDATA||(process.platform==='darwin'?p.join(o.homedir(),'Library','Application Support'):p.join(o.homedir(),'.config'));const f=p.join(b,'squad-cli','update-check.json');try{const d=JSON.parse(require('fs').readFileSync(f,'utf8'));const age=Date.now()-d.checkedAt;if(age<86400000)console.log(JSON.stringify(d));else console.log('STALE')}catch{console.log('MISS')}" |
| 48 | ``` |
| 49 | |
| 50 | Output semantics: |
| 51 | - Valid JSON `{"latestVersion":"X.Y.Z","checkedAt":N}` → cache hit; use `latestVersion` |
| 52 | - `STALE` → cache expired (older than 24h); treat as no data |
| 53 | - `MISS` → cache missing or corrupt; treat as no data |
| 54 | |
| 55 | On `STALE` or `MISS`, show the normal greeting (no notice). Do **not** make an |
| 56 | independent npm call for `latest`-channel users — the upstream CLI will refresh |
| 57 | the cache on its next run. |
| 58 | |
| 59 | **OS-specific cache path for reference:** |
| 60 | - Windows: `%APPDATA%\squad-cli\update-check.json` |
| 61 | - Linux: `~/.config/squad-cli/update-check.json` |
| 62 | - macOS: `~/Library/Application Support/squad-cli/update-check.json` |
| 63 | |
| 64 | #### For `insider` / `preview` channels — own probe with repo-local cache |
| 65 | |
| 66 | The upstream cache only stores the `latest` dist-tag and is not useful for |
| 67 | pre-release channels. Use a separate probe. |
| 68 | |
| 69 | **Step A — Check repo-local cache:** |
| 70 | |
| 71 | Read `.squad/.cache/version-check.json`. If the file exists, is not older than |
| 72 | 24h, and `currentVersion` matches `stamped version`, use `channelVersion` from |
| 73 | it. Skip the npm probe. |
| 74 | |
| 75 | **Repo-local cache schema:** |
| 76 | ```json |
| 77 | { |
| 78 | "checkedAt": "2026-05-26T14:13:28.492Z", |
| 79 | "currentVersion": "0.9.6-insider.2", |
| 80 | "channel": "insider", |
| 81 | "channelVersion": "0.9.7-insider.1" |
| 82 | } |
| 83 | ``` |
| 84 | |
| 85 | **Step B — npm probe (on cache miss / stale / version mismatch):** |
| 86 | |
| 87 | ``` |
| 88 | npm view @bradygaster/squad-cli dist-tags --json |
| 89 | ``` |
| 90 | |
| 91 | - Timeout: **5 seconds.** If the command does not respond within 5 seconds, |
| 92 | abandon and show normal greeting. |
| 93 | - On success: extract `dist-tags[channel]` (e.g., `dist-tags["insider"]`). |
| 94 | Write `.squad/.cache/version-check.json` with the schema above. |
| 95 | Create `.squad/.cache/` if it does not exist. |
| 96 | - On any error (network failure, registry unreachable, parse error): show |
| 97 | normal greeting. |
| 98 | |
| 99 | ### 1.4 Comparison |
| 100 | |
| 101 | Compare `currentVersion` against the resolved `latestVersionForChannel` using |
| 102 | semver ordering (pre-release suffixes sort lower than their release counterpart, |
| 103 | e.g., `0.9.5-insider.1 < 0.9.5`). |
| 104 | |
| 105 | - `latestVersionForChannel > currentVersion` → update available |
| 106 | - Equal or older → no notice |
| 107 | |
| 108 | ### 1.5 Greeting Append |
| 109 | |
| 110 | When an update is available, append to the normal greeting (on the same line, |
| 111 | separated by ` · `): |
| 112 | |
| 113 | ``` |
| 114 | · 🆕 v{latestVersionForChannel} available — say "upgrade squad" |
| 115 | ``` |
| 116 | |
| 117 | Example complete greeting line: |
| 118 | ``` |
| 119 | Squad v0.9.4-insider.1 · 🆕 v0.9.7-insider.1 available — say "upgrade squad" |
| 120 | ``` |
| 121 | |
| 122 | Do not mention the update check, the cache, or the mechanism. Just the notice. |
| 123 | |
| 124 | ### 1.6 Upgrade Flow |
| 125 | |
| 126 | **Trigger phrases** (case-insensitive, match anywhere in user message): |
| 127 | - "upgrade squad" |
| 128 | - "update squad" |
| 129 | - "what's new" *(when a version notice has been shown in this session)* |
| 130 | - "install the update" |
| 131 | - "yes upgrade" |
| 132 | |
| 133 | **Flow:** |
| 134 | |
| 135 | 1. **Confirm** — ask the user to confirm before running the upgrade: |
| 136 | > "I'll run `squad upgrade` now. This overwrites `squad.agent.md` and |
| 137 | > casting files but preserves `config.json`, `team.md`, `decisions.md`, |
| 138 | > and all agent history. Ready?" |
| 139 | Wait for affirmative response before proceeding. |
| 140 | |
| 141 | 2. **Run upgrade:** |
| 142 | ``` |
| 143 | squad upgrade |
| 144 | ``` |
| 145 | Capture output. On failure (non-zero exit, error output), report the error |
| 146 | to the user and stop. |
| 147 | |
| 148 | 3. **What's-new digest** — after successful upgrade, fetch and summarize |
| 149 | release notes: |
| 150 | |
| 151 | ``` |
| 152 | gh api repos/bradygaster/squad/releases --jq '[.[] | select(.tag_name | test("^v"))]' |
| 153 | ``` |
| 154 | |
| 155 | - Extract 3–6 bullet points from releases between `oldVersion` and |
| 156 | `newVersion`, inclusive. |
| 157 | - Priority: `feat` entries first, then `fix`, then `docs`. |
| 158 | - Format: |
| 159 | ``` |
| 160 | 📋 What's new in v{newVersion}: |
| 161 | • {feat summary 1} |
| 162 | • {feat summary 2} |
| 163 | • {fix summary} |
| 164 | ``` |
| 165 | - **Fallback chain:** |
| 166 | - `gh` not authenticated → "See full release notes at: |
| 167 | https://github.com/bradygaster/squad/releases" |
| 168 | - No releases found → "No release notes found for this version range." |
| 169 | - Network failure → link to releases page |
| 170 | |
| 171 | 4. **Restart prompt** — after showing the digest, prompt the user: |
| 172 | > "`squad.agent.md` has been updated. For the new coordinator instructions |
| 173 | > to take effect, please start a new session (close and re-open this chat). |
| 174 | > Your team state and decisions are unchanged." |
| 175 | |
| 176 | ### 1.7 Failure Modes |
| 177 | |
| 178 | Every failure path ends at "show normal greeting." The update check never |
| 179 | interrupts or delays the session. |
| 180 | |
| 181 | | Failure | Behavior | |
| 182 | |---------|----------| |
| 183 | | `node` not on PATH | `MISS` → normal greeting | |
| 184 | | Upstream cache missing / corrupt | `MISS` → normal greeting | |
| 185 | | Upstream cache stale (`latest` channel) | Normal greeting (no npm call) | |
| 186 | | npm probe timeout (5s) | Normal greeting | |
| 187 | | npm probe network error | Normal greeting | |
| 188 | | npm probe parse error | Normal greeting | |
| 189 | | `.squad/.cache/` write error | Normal greeting (skip cache write) | |
| 190 | | `gh` not available / unauthenticated | Upgrade flow: link to releases page | |
| 191 | | `squad upgrade` exits non-zero | Report error, stop flow | |
| 192 | | Any unexpected exception | Log to `.squad/orchestration-log/`, normal greeting | |
| 193 | |
| 194 | --- |
| 195 | |
| 196 | ## (Future steps reserved) |
| 197 | |
| 198 | - Step 2: \<reserved\> — e.g., dependency drift check |
| 199 | - Step 3: \<reserved\> — e.g., repo policy / state-backend audit |