diff --git a/docs/runbooks/daily-first-user-walk.md b/docs/runbooks/daily-first-user-walk.md deleted file mode 100644 index aa2cad37e5..0000000000 --- a/docs/runbooks/daily-first-user-walk.md +++ /dev/null @@ -1,20 +0,0 @@ -# Daily first-user walk - -A fresh account walks the new-user path on prod: signup, the first agent (hosted or bring your own), an invite, and Settings. Record each verdict, with 390 and 1440 screenshots, in the launch pod. - -## Name every walk account `xcjsam-` - -Growth excludes the `xcjsam-` prefix from outside-user counts. A walk account under any other name is counted as a real signup and pollutes the launch funnel. - -- Sign up with an email whose local part is `xcjsam` plus a `+tag`. The handle comes from the local part with the `+tag` removed (`backend/services/derivedUsername.ts`), and because `xcjsam` is taken the server adds a short suffix, so the account becomes `xcjsam-<4 chars>`. -- Check the handle in Settings before walking. If it doesn't start with `xcjsam-`, delete the account (below) and sign up again. -- Put the handle in the walk record so Growth can confirm the exclusion. - -## Clean up in the same turn - -1. Stop any listener the walk started, and delete its local token file. -2. Uninstall every agent the walk installed, using the walk account's own session. -3. Delete the account: Settings → Delete account, type `DELETE`, and give the password if asked (`DELETE /api/users/me`, browser session only). -4. Note in the walk record that all three are done. - -A walk account that outlives its walk becomes a stale row in every count after it. diff --git a/docs/runbooks/skill-source-sync-tcc.md b/docs/runbooks/skill-source-sync-tcc.md deleted file mode 100644 index 3ee9544a00..0000000000 --- a/docs/runbooks/skill-source-sync-tcc.md +++ /dev/null @@ -1,97 +0,0 @@ -# Background LaunchAgents can't read `~/Documents` (macOS TCC) - -**Trap:** a macOS background LaunchAgent (`me.commonly.*`) cannot read **file -contents** under `~/Documents`, even as the owning user. The denial surfaces as -`fatal: Unable to read current working directory: Interrupted system call` -(EINTR) — which reads like a transient glitch, not a permission wall — so a job -that reads a repo there fails **silently** and keeps serving stale data. - -Earned 2026-10-28: `me.commonly.skill-source-sync` had been skipping every -shared skill-source checkout (all under `~/Documents/workspace`) as -`"on '', not main"` and serving the fleet skills **18 commits stale**, because -`git rev-parse` couldn't read the repo and returned empty. - -## Why it happens - -`~/Documents` (like `~/Desktop` and `~/Downloads`) is TCC-protected -("Files & Folders"). A process that touches it must either hold the grant or be -able to prompt the user for it. A **background LaunchAgent has no GUI session**, -so the consent prompt can't be shown and the read is denied. Interactive -Terminal / operator sessions already carry the grant, so **the same command -works by hand and fails under launchd** — the confusing part. - -The denial is on **reading contents**, not metadata: - -| operation under the agent | result | -|---|---| -| `/bin/pwd` | ✅ returns the cwd | -| `ls -lad ~/Documents` and `…//.git` | ✅ stat/list allowed | -| `cat …//.git/HEAD` | ❌ `Interrupted system call` | -| anything under `~/.commonly`, `/tmp`, `/opt` | ✅ fine | - -It is **not** a cwd bug: a shell `cd "$HOME"` and a plist `WorkingDirectory` -both leave it failing (both tried and ruled out). `getcwd()` itself works -(`/bin/pwd` succeeds); it's the file read under `~/Documents` that's blocked. - -## Diagnose it - -From the agent's context (reproduce under launchd, not your shell): - -```sh -launchctl kickstart -k gui/$(id -u)/me.commonly. -# then, decisively — a background agent will fail the second line: -/bin/pwd # succeeds -cat ~/Documents/workspace//.git/HEAD # "Interrupted system call" => TCC-blocked -cat ~/.commonly/ # succeeds => confirms it's Documents-specific -``` - -If `cat` under `~/Documents` fails with EINTR while a non-Documents read -succeeds, it's this. `ls` succeeding is **not** evidence of access — it only -stats; you must read file *contents* to see the wall. - -## Known-affected jobs (audit 2026-10-28) - -- `me.commonly.skill-source-sync` — **was** fully silent; now logs a loud - `BLOCKED … SKILLS ARE STALE` line and names this runbook. -- `me.commonly.sre-gate-drift` — reads `~/Documents/workspace/commonly`; - degraded, but self-alerts after 3 failed fetches (its message blames the - network, not TCC). -- One job is **not** affected: it resolves its repo under - `~/.commonly/repos/` (the reference pattern) and only falls back to - `~/Documents` as a last resort it never reaches. **This is the pattern to - copy.** - -Every other `me.commonly.*` job's launchd script is clean (no `~/Documents` -reads). A seat whose runtime workspace were set under `~/Documents` would hit -the same wall; none are. - -## Fix - -**Preferred — relocate (no security setting, no GUI):** keep the script and the -repo it reads under `~/.commonly/repos/` (not TCC-protected), and resolve the -repo path from the cwd's git top-level rather than hardcoding `~/Documents`, the -way a job that resolves its repo under `~/.commonly/repos/` does (the -reference pattern): - -```sh -if [ -n "$MY_REPO" ]; then REPO="$MY_REPO" -elif top=$(git rev-parse --show-toplevel 2>/dev/null) \ - && git -C "$top" remote get-url origin 2>/dev/null | grep -q ''; then - REPO="$top" -else REPO="$HOME/.commonly/repos/"; fi -``` - -Consumers that load from the old path (skill symlinks, operator sessions) move -with it — one coordinated change. - -**Not preferred — grant access:** granting Full Disk Access (or a -Files-and-Folders → Documents grant) to the agent is a System Settings action -(**operator's hands, GUI**) and widening it host-wide to `/bin/zsh` is the wrong -default. Don't reach for this unless relocation is impossible. - -## Stopgap - -Until a degraded job is relocated, run its logic from an **operator session** -(which holds the Documents grant) at each checkpoint — e.g. -`zsh ~/.commonly/bin/skill-source-sync.sh`. The launchd copy keeps logging -`BLOCKED` so the degradation stays visible. diff --git a/docs/runbooks/staging-environment.md b/docs/runbooks/staging-environment.md index dac411bc00..a5693ba7f9 100644 --- a/docs/runbooks/staging-environment.md +++ b/docs/runbooks/staging-environment.md @@ -35,7 +35,7 @@ render references **47** keys across three ExternalSecrets — **41 staging-pref - **Deliberately NOT shared — the prod GitHub PAT.** `commonly-github-pat` has write power over prod repos, and staging auto-deploys every merge (the reckless lane), so `githubPat.enabled: false` in values-staging omits the `GITHUB_PAT` - ref from the staging render entirely (Cofounder's ruling — the same principle + ref from the staging render entirely (the same principle that keeps atlasAdmin off staging). The backend reads GITHUB_PAT lazily and degrades (GitHub routes report not-configured) rather than crashing. Staging agents that ever need git get a separate fine-grained PAT on a throwaway repo, diff --git a/k8s/helm/commonly/templates/configmaps/litellm-config.yaml b/k8s/helm/commonly/templates/configmaps/litellm-config.yaml index 0739d438e3..e8f8ca3b51 100644 --- a/k8s/helm/commonly/templates/configmaps/litellm-config.yaml +++ b/k8s/helm/commonly/templates/configmaps/litellm-config.yaml @@ -47,9 +47,9 @@ data: # V4.1 for compatibility. The group name carries the build so a key # scoped to it says what it buys; re-check the changelog before trusting # the name after DeepSeek's next Flash update. Used by the dsh writer - # seats (D50), through their own budget-capped virtual key. + # seats, through their own budget-capped virtual key. # - # Budget (Sam, D50: the DeepSeek writers are budget-capped). Two caps: + # Budget (the DeepSeek writers are budget-capped). Two caps: # 1. This deployment: $200 per month across EVERY caller of the group. # Over it, LiteLLM answers 429 "crossed budget" and does not reroute # (there is no fallback for this group). Spend for this cap is @@ -59,8 +59,8 @@ data: # 2. The writers' virtual key: models=[deepseek-flash-1017], # max_budget 200, budget_duration 30d. Stored in LiteLLM's Postgres, # so it survives restarts and is the auditable record - # (/key/info). Minted after this ships; the file lives 0600 on the - # fleet host, never in the repo. + # (/key/info). Minted after this ships; the key lives 0600 with + # its operator, never in the repo. - model_name: deepseek-flash-1017 litellm_params: model: deepseek/deepseek-flash @@ -113,7 +113,7 @@ data: # all fallback chains below. If the model is reinstated, restore it as a # paired entry alongside nemotron above. - # --- D111 (2026-10-27): GPT/Codex access revoked. Every chatgpt/* alias below is + # --- 2026-10-27: GPT/Codex access revoked. Every chatgpt/* alias below is # repointed to the deepseek/deepseek-v4-flash backend so callers keep their # model_name but get DeepSeek. The ChatGPT OAuth path (chatgpt/responses/*, the # codex-auth-rotator sidecar, auth.json) is dormant until GPT access returns; @@ -194,7 +194,7 @@ data: model: openai/gpt-image-1 api_key: os.environ/OPENAI_API_KEY - # Direct Anthropic routes removed under D76. Claude on hosted runtimes + # Direct Anthropic routes removed. Claude on hosted runtimes # awaits OpenRouter routing; BYO Claude Code remains independent. router_settings: @@ -203,7 +203,7 @@ data: # (writes /chatgpt-auth/rotate-now → sidecar polls and swaps auth.json). routing_strategy: least-busy enable_pre_call_checks: true - # Fallback chain. Under D111 (2026-10-27) the gpt-5.4*/openai-codex/* Codex + # Fallback chain. Since 2026-10-27 the gpt-5.4*/openai-codex/* Codex # entries that used to fall through to nemotron here were removed — those # aliases now point straight at deepseek-v4-flash, and nemotron is dead (the # gateway it served is parked; OpenRouter keys expired 2026-10-25). The only @@ -221,7 +221,7 @@ data: # callers" alert fires (docs/runbooks/alerting.md#litellm-failing). There is # no nemotron or Codex tier behind it any more. fallbacks: - # D111 (2026-10-27): gpt-5.4*/openai-codex/*/codex-cli gpt->nemotron fallbacks + # 2026-10-27: gpt-5.4*/openai-codex/*/codex-cli gpt->nemotron fallbacks # removed — those aliases now point straight at deepseek-v4-flash (primary), and # nemotron itself is dead (OpenRouter keys expired 2026-10-25). # Dead routes fall back to deepseek-v4-flash (2026-10-15). Probing every @@ -243,7 +243,7 @@ data: - {"nvidia/nemotron-3-super-120b-a12b:free": ["deepseek-v4-flash"]} # One retry on rate-limit with a deliberate 1s delay. This retry is a global # router setting and still applies to every deployment. The Codex auth.json - # rotation it was originally written for is dormant post-D111 (no chatgpt/* + # rotation it was originally written for is dormant since 2026-10-27 (no chatgpt/* # route consumes the rotator now); for the repointed aliases a 429 simply # retries the same deepseek-v4-flash deployment after 1s, then fails fast. # diff --git a/k8s/helm/commonly/values-dev.yaml b/k8s/helm/commonly/values-dev.yaml index e02b9ca501..92aa993591 100644 --- a/k8s/helm/commonly/values-dev.yaml +++ b/k8s/helm/commonly/values-dev.yaml @@ -8,7 +8,7 @@ global: errorTracking: enabled: true -# commonly-dev-e2b-api-key has one enabled version (Cofounder, 2026-10-15). +# commonly-dev-e2b-api-key has one enabled version (2026-10-15). # Tools stay opt-in per install, so this offers code runs to nobody until an # agent declares commonly_run_code. hostedSandbox: @@ -220,7 +220,7 @@ externalSecrets: agents: clawdbot: - # PARKED 2026-08-20 (Sam) — the moltbot tier is retiring in favour of + # PARKED 2026-08-20 — the moltbot tier is retiring in favour of # pi/OpenCode wrapper adapters (ADR-021/ADR-023, #1050). Its credential # stack had been dead since 2026-07-02 — both cluster codex tokens expired, # OpenRouter 401 "User not found" — and nobody noticed for seven weeks, @@ -289,7 +289,7 @@ agents: adapter: codex storage: 1Gi tokenSecret: cloud-codex-cody-token - # Parked 2026-08-12 (Sam: the working fleet is the Sharpen pod). + # Parked 2026-08-12. # Identity, PVC, and token secret stay; flip to 1 to revive. replicas: 0 @@ -439,20 +439,18 @@ hostedMcp: hiddenEntries: # Client secrets exist, but Workspace MCP enrollment is still off. - google-calendar - # Not walked end to end on staging before the 10-23 deploy (Cofounder plan B: unwalked ships hidden). + # Not walked end to end on staging before the 10-23 deploy; unwalked entries ship hidden. # Remove each line once its staging walk passes. - atlassian - sentry - # Added by #2429 (deploy 4). Hidden until each is walked end to end (Cofounder 10-23). + # Added by #2429. Hidden until each is walked end to end. - notion - gitlab - supabase # The 10-27 prod walk failed before Airtable's consent screen ("invalid client_id # or mismatched redirect_uri"). Hidden until TASK-318 lands and a walk passes. - airtable - # Mongo User _id(s) permitted to walk each hidden hosted-MCP entry (#2649, TASK-485). - # lily-shen is the designated walk user (keeps the walk off Sam's account, Cofounder 10-24). - # Sentry and Atlassian stay hidden for every other account (Atlassian added for its walk, D153). + # Mongo User _id(s) permitted to walk each hidden hosted-MCP entry (#2649). hiddenEntryUserAllowlist: atlassian: - "6a47891ee025ce2e0ca1d30b" diff --git a/k8s/helm/commonly/values-staging.yaml b/k8s/helm/commonly/values-staging.yaml index c95b9ead99..bf86061483 100644 --- a/k8s/helm/commonly/values-staging.yaml +++ b/k8s/helm/commonly/values-staging.yaml @@ -49,7 +49,7 @@ email: # No prod GitHub PAT on staging. The shared commonly-github-pat has write power over # prod repos, and staging auto-deploys every merge (the reckless lane), so the -# api-keys render must not reference it (Cofounder's ruling, same principle as +# api-keys render must not reference it (the same principle as # keeping atlasAdmin off staging). The backend uses GitHub App installation tokens # and does not read this key. If staging agents ever need git, that is a # separate fine-grained PAT on a throwaway repo, post-11/1.