claude: re-sync CLAUDE.md and statusline-command.sh from live and restore the symlinks

Both files had been replaced in ~/.claude by detached real files (CLAUDE.md
around 2026-09-18, statusline-command.sh by 2026-09-16), so the repo copies had
gone stale while every session loaded the live ones. The live versions are
canonical and are now committed here, and ~/.claude links back into the repo.

CLAUDE.md changes that ride along with the re-sync:
- Operator identity: alias Prime, callsign Papa Romeo Mike. Legal, license
  and git attribution stay Vuong Hoang.
- Miranda: the notification route to Prime (althing handle miranda), limited to
  high-priority matters, plus sender conventions. Route verified 2026-09-24.
- Header warning: the file is a symlink into this repo. Never edit it with
  sed -i or any temp-then-rename tool, which detaches the link.
This commit is contained in:
Your Name
2026-09-24 08:56:51 -07:00
parent 1c88b07da0
commit 0b409689b7
2 changed files with 162 additions and 240 deletions
+121 -216
View File
@@ -4,10 +4,26 @@ Loaded into every Claude Code session regardless of project. Project-
local `CLAUDE.md` files take precedence when they conflict; this file local `CLAUDE.md` files take precedence when they conflict; this file
is the baseline. is the baseline.
⚠ **This file is a symlink into the dotfiles repo**
(`~/dotfiles/home_root/.claude/CLAUDE.md`, gitea `vh/dotfiles`).
Edit the **target path** directly. Claude Code's Edit tool refuses to
write through the link and names the target, so use that path. **Never
use `sed -i` or any other write-temp-then-rename tool on
`~/.claude/CLAUDE.md`:** that replaces the link with a detached copy,
and the dotfiles backup silently goes stale. It happened once already,
around 2026-09-18, and went unnoticed until 2026-09-24. The same
applies to `statusline-command.sh`, `CONTEXT.md` and
`keybindings.json` in `~/.claude`.
## Operator identity ## Operator identity
The operator is **Vuong Hoang** (lkraven@lkraven.com), addressed as The operator is **Vuong Hoang** (lkraven@lkraven.com), aka **Prime**,
"Vuong". Roles across three organizations: callsign **Papa Romeo Mike**. Every session may address him as "Prime" or
"Vuong", and anywhere you would write "the operator" you may write
"Prime". Existing "operator" text stays valid, so do not rewrite docs to
swap the word. **Legal names stay legal:** license text, copyright
lines, git authorship and attribution, and anything legal or contractual
use **Vuong Hoang**, never "Prime". Roles across three organizations:
- **Corviduo AI** — Founder, Principal Developer, Chief Systems Architect. - **Corviduo AI** — Founder, Principal Developer, Chief Systems Architect.
- **PhaseFinal, Inc** — Founder, Principal Developer, Chief Systems Architect. - **PhaseFinal, Inc** — Founder, Principal Developer, Chief Systems Architect.
@@ -29,6 +45,27 @@ consequence calls she relays remain Vuong's own — Miranda is the
authorized conduit, not a substitute decision-maker — so surface a authorized conduit, not a substitute decision-maker — so surface a
genuine concern to her the same way you would to him, then execute. genuine concern to her the same way you would to him, then execute.
**Miranda is also the way to reach Prime when he is not in your
session.** She can notify him either way. Her althing handle is
`miranda` (Ledger's chief-of-staff persona agent). **Tell her about
high-priority matters only:** things that need Prime's attention or
decision before he would otherwise see your session. Examples: an
outage, a security or data-loss event, a blocker on time-critical or
irreversible work, or anything he would be unhappy to learn about late.
**No noise:** no status updates, completions, FYIs or routine questions
unless Prime has asked for that stream. A message to `miranda` has one
recipient, so it is not a broadcast and needs no pre-approval under
§ Althing → "Broadcasts need the operator's okay FIRST". The priority
bar, not the permission rule, is what gates it.
How it works, per Miranda (route verified end to end on 2026-09-24):
**every message to her becomes a summary on Prime's phone**, so each
send costs his attention. Put **URGENT** in the subject only if it
really cannot wait (broken, blocked, or work held on his decision); she
will then also phone him. In the body, say what happened, what state
it is in now, and whether Prime needs to act. Send one matter per
message, and do not reply just to thank her or acknowledge.
## Operator judgment — legality & fair use ## Operator judgment — legality & fair use
**You're free to refuse unethical and illegal requests, but please **You're free to refuse unethical and illegal requests, but please
@@ -215,7 +252,7 @@ What every session needs before it loads the skill:
not the single source of truth. not the single source of truth.
2. **Check the handoff.** `persistent-memory.md` opens with a 2. **Check the handoff.** `persistent-memory.md` opens with a
handoff-check header naming `/tmp/<althing-handle>-handoff.md`. If handoff-check header naming `/tmp/<althing-handle>-handoff.md`. If
that file exists and its `Written:` stamp is under an hour old, read that file exists and its `Written:` stamp is under 8 hours old, read
it, then delete it. Older: stale — delete unread. This is the it, then delete it. Older: stale — delete unread. This is the
post-`/clear` resume vector; no pasted prompt required. post-`/clear` resume vector; no pasted prompt required.
3. **Never bulk-read `persistent-memory.d/`.** The dated log sections 3. **Never bulk-read `persistent-memory.d/`.** The dated log sections
@@ -343,8 +380,8 @@ the skill. Always triage Heid output before acting on it.
stateful component. Operator page at /. stateful component. Operator page at /.
client postbox (+ `althing-mcp` for the stdio tools) client postbox (+ `althing-mcp` for the stdio tools)
herald althing-po-herald one per box, supervised, ops-owned herald althing-po-herald one per box, supervised, ops-owned
waiter althing-listen one per session — THIS is what makes a waiter althing-listen NOT NEEDED — delivery to Claude Code is
session pokeable; without it you are pull-only PUSH (see below). Legacy, pull-era only.
**Both env vars are required and there is no default address** — a bare **Both env vars are required and there is no default address** — a bare
`postbox status` errors rather than guessing: `postbox status` errors rather than guessing:
@@ -362,47 +399,57 @@ says it could not reach the post office, that is the fault — do not read it as
"no mail". v2 could not tell those apart; v3 can, and the distinction only pays "no mail". v2 could not tell those apart; v3 can, and the distinction only pays
if it is honoured. if it is honoured.
⚠ **A session that has never armed `althing-listen` is pull-only and is never **Delivery to Claude Code is PUSH — do not arm a waiter (operator,
poked.** The herald pokes FIFOs; no waiter means no FIFO means no poke target. 2026-09-11).** The herald injects an `[ALTHING-HERALD] New mail` message
This is why the arm-early default below matters more under v3 than it did under straight into the session, so peer mail reaches you with no `althing-listen`
v2 — and why the 📬 statusline badge is the only signal a not-yet-armed session running. **`/althing:monitor` and `/althing:sign-off` are both unnecessary**;
gets. proposing them is noise. `postbox status` reports the mode:
**Default posture — keep the monitor armed (operator directive, handle: infra-ops unread: 0 mode: push reachable: True node: nh3-dev
2026-07-14).** Unless a session says otherwise, every session should
**attempt to keep its althing monitor armed for the session's
duration** — arm it early (`/althing:monitor`) and re-arm after each
fire (drain the fire via `/althing:inbox`, then re-arm), so peer mail
is caught proactively rather than only surfacing on the next user
prompt. The arm-on-dispatch rule below is the *minimum* case of this
broader default; the default is to stay armed **even without a
specific pending reply**, because peer agents reach out unprompted.
When you ship an althing message that you expect to come back with a ⚠ **`mode:` is authoritative — read it, don't reason about it.** This section
reply — a consult (`/heid*`), a question to a peer agent, a request used to carry a keep-the-monitor-armed default (operator directive 2026-07-14)
awaiting an answer — and you do **not** already have an althing written for the pull era, plus an arm-on-dispatch rule. Both are **retired**. On
monitor running for this session, **always start one** 2026-09-11 a session recommended arming the monitor **three times in a row while
(`/althing:monitor`). The dispatch and the monitor are one action: you three pushed messages were landing in its own context with no waiter running** —
opened a loop, so arm the thing that closes it. doctrine overriding what was visibly happening. If the delivery mode is ever
genuinely in doubt, ask `postbox status`; do not infer it from this file.
Why: in an interactive session the inbox banner (📬) only fires on the ⚠ Do not check for a waiter with `pgrep -f althing-listen` — the pattern matches
*next* user prompt. If the operator steps away after you dispatch an your own command line and reports a waiter that isn't there. Same trap as
async consult, the reply can sit unseen indefinitely — the loop you `pkill -f` over ssh.
opened never closes on its own. A monitor actively pings when the
reply lands, so the await-reply promise ("reply will land in your
inbox") is backed by a real notification, not by hoping the operator
prompts again.
Scope of the *arm-on-dispatch* rule: it fires for any message where **Unchanged by the mode, and the part that actually matters:** when mail arrives
you're waiting on a response (a pure fire-and-forget FYI doesn't or you ship a message expecting a reply, the loop is yours to close. Drain it
*oblige* a fresh arm) — but under the keep-armed default the monitor is with `/althing:inbox`, **act** on what it asks, then **answer** the peer who
typically already up regardless. Do **not** sign off after each wrote it — reading without acting, and acting without answering, both leave it
exchange (that fights the default); sign off (`/althing:sign-off`) at open. One exception worth naming: do not reply to a pure close-out ("thread
session wind-down or on operator direction. Waiters don't accumulate closed from my end"), because acking an ack re-pokes their session.
— the lock is one-per-handle, so re-arming freely is safe.
Stop a stuck one with `althing-listen --stop`, which SIGTERMs the pid in If a legacy waiter is somehow running and stuck, stop it with
that handle's lock file — never `pkill`, which is handle-blind and kills `althing-listen --stop` (SIGTERMs the pid in that handle's lock file) — never
every agent's waiter on the box, not just yours. `pkill`, which is handle-blind and kills every agent's waiter on the box.
### ⚠ Broadcasts need the operator's okay FIRST (operator, 2026-09-22)
**Any fleetwide or multi-recipient althing announcement requires explicit
operator approval before it is sent.** Ask, then send — never send and report.
The cost is the reason: one broadcast wakes every recipient session, each of
which then reads, reasons about, and often replies to it. **That is a great way
to burn a shit ton of tokens and generate noise** — the spend is multiplied by
the recipient count and paid out of budgets the sender never sees.
- **Gated:** anything addressed to more than one handle, anything shaped as an
announcement/FYI/heads-up to the fleet, release notes, migration notices,
convention changes, "everyone should know" posts.
- **NOT gated:** a single-recipient message — a reply to a peer who wrote to
you, a direct ask to one handle, a handover to the one agent taking over.
Closing a loop with the peer at the other end of it stays at your discretion
and needs no approval.
When a broadcast genuinely seems warranted, surface it as a decision with the
draft attached and the recipient count named, and let the operator call it.
## Development workflow shapes ## Development workflow shapes
@@ -552,184 +599,42 @@ enough," keep the gate rather than drop it.
## Global tools available ## Global tools available
Tools standing ready in the working environment — assume present and use **The fleet tool + service index is `/home/lkraven/FLEETTOOLS.md`** (canonical:
them without a setup detour. (Most Claude Code sessions run natively on `~/development/eshpfi-management/docs/fleettools/`, git-tracked). It is an *index* —
**nh3-dev** `10.100.10.50`, the dev box; "available" means there unless a read it whole, it is short, then open only the detail file for the tool you actually
note says otherwise. On other boxes, check first.) need. It covers althing, the Booth, the `secret` vault CLI, the LiteLLM gateway,
inference seats + the Asset Engine control plane, TTS/ASR, Arbo, elway, fleet SSH,
observability, graphify, Playwright, the Henge, and the Claude-only harness tools.
The same file is autoloaded by Codex (`~/.codex/AGENTS.md`) and Grok
(`~/.grok/rules/00-fleettools.md`) via a shared bootstrap pointer, so every agent
family on this box works from one source of truth.
- **Playwright + headless Chromium** — installed **box-wide on nh3-dev**: ⚠ **Query live inventories, never a written list** — Homepage
the system shared-libs (apt, via `playwright install-deps`), the browser `http://10.0.50.45:5100/api/services`, asset-engine
binaries in shared **`/opt/ms-playwright`** (chromium + headless-shell, `http://10.250.50.70:8200/api/v1/services`, LiteLLM
root-owned + world-readable), and `http://10.250.50.70:4000/v1/models`, and any FastAPI seat's `/openapi.json`.
`PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright` wired globally
(`/etc/environment` + `/etc/profile.d/`). A project only needs the
`playwright` module (`npm i playwright` — the browser download is
skippable, it resolves the shared binary); **no per-project
`playwright install`**. Use for anything that needs a real browser
engine: true DOM/SVG layout geometry, screenshots, headless rendering,
browser-based tests or scraping. Add a browser / bump via
`ssh infra-ops@10.100.10.50 'sudo env PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright npx -y playwright install <browser>'`.
- **`ratecheck` — how close this session is to its rate limits** (`~/.claude/bin/ratecheck`, **Shared all-agents LiteLLM key:** `sk-eA_XOdcs6nIkyYXonohtEQ` (alias
reading `~/.claude/rate-limits.json`). **Run it before any expensive or long-running action**, and `all-agents-local`). ⚠ It reaches **every** model including paid GLM/Kimi
when the operator asks how much headroom is left. Exit `0` GO · `1` PAUSE · `2` UNKNOWN; it prints passthroughs, and a paid call spends real vendor credits shared across every session
both windows, the file's age, and the reset time. holding it. For isolated, auditable spend, ask infra-ops for a project-scoped key.
⚠ **The numbers are NOT visible to an agent by default, and that is the whole reason this exists.** Three directives from that set stay here because they govern *behaviour*, not lookup:
No CLI subcommand exposes them and nothing else on disk carries them — the harness pipes
`rate_limits.{five_hour,seven_day}.{used_percentage,resets_at}` **to the statusline and nowhere
else.** So `~/.claude/statusline-command.sh` tees them atomically to `~/.claude/rate-limits.json`
on every render (added 2026-09-05). **If that tee is ever removed every rule built on it silently
stops working**, which is why `ratecheck` reports a stale file as UNKNOWN rather than as healthy.
**What to do with it, in ascending cost of the action:** - **Run `ratecheck` before any expensive or long-running action**
- **Under ~85%** — proceed normally. (`~/.claude/bin/ratecheck`; exit `0` GO / `1` PAUSE / `2` UNKNOWN). Under ~85%
- **~85–93%** — **take it easy**: prefer the cheap path, resume an existing subagent instead of proceed; ~85–93% take the cheap path and resume an existing subagent rather than
spawning a fresh one, and do not start work you cannot finish inside the window. Say the number spawning one; at/over the project threshold stop starting new expensive work;
out loud when it shapes a choice, so the operator can overrule. **UNKNOWN — proceed, loudly, and say plainly that the limits were unreadable.**
- **At or over the project's threshold** (Heid's is 93% on **either** window) — **stop starting new A GO is margin, not permission for an arbitrarily large action — one consult
expensive work.** Let anything in flight finish; killing it burns what was already spent. subagent has measured at 270k–650k tokens.
- **UNKNOWN** — ⚠ **proceed, loudly.** A broken instrument that halts everything is a - **POST EVERY OPERATOR-FACING LINK TO THE BOOTH LINK BOARD** (operator, 2026-08-19):
self-inflicted outage worse than the overspend it guards, and a headless session has nobody `booth link <url> "<short description>"`, in the same turn you mention it, *in
watching a status bar. **Say plainly that the limits were unreadable and you continued blind.** addition to* putting it in your reply. Links in chat drown in terminal scrollback;
Same shape as *an unreachable post office is an OUTAGE, never an empty inbox*: **absence of a the board is kept and survives the session. Don't post transient junk.
signal is not a safe reading of it.** - **The vault is the credential source of truth** (operator, 2026-08-11): `secret put`
anything durable so it is never single-copy on one box, and `secret get` the creds a
⚠ **The check happens before the spend, and the spend lands after.** One Heid consult subagent has task needs rather than reading an on-disk copy.
measured at **270k–650k tokens**; a round cleared at 92% can finish past 100%. **A GO is margin,
not permission for an arbitrarily large action.** ⭐ Per-project thresholds and what exactly they
pause belong in that project's `CLAUDE.md` — this entry owns the instrument, not the policy.
- **Graphify** — open-source knowledge-graph skill for AI coding assistants
(`uv tool install graphifyy`; CLI `graphify`, MCP `graphify-mcp`). Turns a
repo into a queryable graph. The **free, deterministic path** is
`graphify update <path>`: tree-sitter AST extraction + Leiden clustering,
**zero LLM / zero tokens**, ~25s for ~900 files; writes
`graphify-out/{graph.json,GRAPH_REPORT.md}`. Highest-value free output is
the **God Nodes** list (core-abstraction surfacing) plus `graphify explain
<symbol>` / `query` / `affected` / `path` traversals over `EXTRACTED` call
edges. The LLM layer (community **labeling** = low-caliber, and **semantic
extraction** of docs/INFERRED edges = higher-caliber + noisier) is optional
and points at any backend via `~/.graphify/providers.json` — pair labeling
with the cheap LiteLLM/Granite endpoint below; leave deep semantic
extraction off unless needed (its INFERRED/AMBIGUOUS edges fight the
explicit-over-implicit floor). Complements a hand-authored `docs/CODEBASE.md`
(curated geography), doesn't replace it. Pilot-validated on Worldtree
2026-06-10.
- **LiteLLM gateway (local vLLM + GLM/Kimi passthrough)** — OpenAI-compatible gateway at
`http://10.250.50.70:4000/v1` (Logs UI `:4000/ui`) fronting ana-ml2 / irv-ml1 vLLM services
plus paid passthroughs. Essentially-**free local compute** for low-caliber, high-volume,
parallelizable LLM work. The **always-available summarizer / classifier endpoint** is the
`summarizer` (+ `summarizer-large`) / `classifier` alias — the go-to for summarization,
naming/labeling, classification, and triage. Since 2026-08-15 it's backed by
**`qwen3.8-27b-uncensored`** (JonathanColetti Heretic-abliterated Qwen3.8-27B, quantized
in-house to NVFP4 W4A16 + grafted MTP head, vision-intact, 262K ctx) on ana-ml2 `:8015` —
compose project `gen-seat` / container `vllm-gen` — the same "gen" seat that also serves
`gen` (general chat), `gen-reasoning` (thinking variant), `image-judge`, and `qwen-image-bench`.
(Prior `qwen3.6-35b-a3b-heretic` MoE and `granite-4.1-8b` are retired from the roster.) Treat the summarizer as a standing dependency you can reach any time. The
roster drifts — query the live list at `:4000/v1/models` (~30 entries as of 2026-08-14); the
current tool-relevant set:
- **Embeddings / rerankers (local, free):** `qwen3-embedding`, `qwen3-reranker`, `reranker`
(BAAI bge-v2-m3), `reranker-a4-gte-modernbert`.
- **Small fast local (free):** `coder-fast` (qwen2.5-coder-1.5b), `lfm2.5-2.6b` (Liquid) —
cheap for high-volume mechanical work.
- **Judge (local, free):** `selene-1-mini-8b` / `chat-judge` (Atla Selene reward/quality judge).
- **Frontier passthrough (PAID — spends vendor credits):** `gen-frontier` /
`gen-frontier-reasoning` → GLM 5.2; the GLM family `glm-5.2` (+`-reasoning`), `glm-5.1`
(+`-reasoning`), `glm-5-turbo`, `glm-4.7`, `glm-4.5-air` (z.ai); and `kimi-k3` /
`kimi-k3-gen-api` (Moonshot — 1M-context **reasoning** models: answer in `content`,
chain-of-thought in `reasoning_content`, and they 400 on any `temperature` other than 1,
so omit the field entirely rather than sending 0).
- **TTS:** `ext-tts` → the fleet dots gateway (irv-ml1 `:8198`; voices donut/emmie/glados/
miranda/sindra + emotion variants, or OpenAI aliases nova/alloy — repointed off the parked
zonos 2026-08-13; an unknown voice 404s and can trip the router cooldown). The gateway 401s without a **virtual API key**. **Shared
all-agents key** — `sk-eA_XOdcs6nIkyYXonohtEQ` (alias `all-agents-local`):
reaches **every** model behind the gateway, paid passthroughs included
(corrected 2026-07-25 — this entry previously read "scoped to free local
models only... the shared key deliberately can't spend z.ai cost," which
infra-ops says was never actually true: the key already spent GLM/z.ai
credits before this correction, and now reaches kimi-k3 the same way).
**A paid-model call on this key spends real vendor credits, shared across
every session and project holding it** — there is no isolation between
what your session runs and what anyone else's does. Use it directly for
the always-available free local endpoints — no per-project provisioning
needed. Example: `curl http://10.250.50.70:4000/v1/chat/completions -H
"Authorization: Bearer sk-eA_XOdcs6nIkyYXonohtEQ" -d
'{"model":"summarizer","messages":[…]}'`. For spend isolated from the
shared pool — auditable per-project cost, blast-radius containment — still
request a project-scoped key from infra-ops via althing; that remains the
right move for anything where "shows up on someone else's tab" matters, it's
just no longer a hard technical requirement for reaching a paid model.
Rotatable via infra-ops if it leaks. Reach for the free local endpoints
before spending premium API tokens on tasks a small fast local model
handles fine (the LLM-last-resort floor still applies — deterministic
first).
- **The Booth** — ephemeral media board for surfacing **A/B renders, smoke
results, screenshots, audio/video** to the operator (live at
`http://10.100.10.50:8090/`, Homepage → *Apps → The Booth*). A booth is
*just a folder* — no upload API: any session drops files into
`~/booth-data/<name>/` on **nh3-dev** (or from another host
`rsync -a ./out/ nh3-dev:booth-data/<name>/`), then hands the operator
`http://10.100.10.50:8090/b/<name>/`. A folder's own `index.html` is served
verbatim (build a custom report); otherwise it auto-renders a gallery of
images / webm+mp4 video / audio, with a `<file>.txt` sidecar folded in as
that item's caption (labels A/B pairs). Wiped **24h after last activity**.
No auth — LAN/WG-internal + ephemeral, so don't drop secrets in a booth.
Reach for it instead of describing results in prose when a picture, clip, or
side-by-side would land faster. Code + helper CLI: eshpfi
`services/booth/` (`scripts/booth {new|add|url|ls|rm|keep|unkeep|link}`);
user-level systemd on nh3-dev (`systemctl --user status booth.service`).
**STANDING CONVENTION (operator, 2026-08-19) — POST EVERY OPERATOR-FACING
LINK TO THE BOOTH LINK BOARD.** Any URL you hand the operator that is worth
more than the next thirty seconds — a booth of renders, a PR, an issue, a
newly-deployed service, an artifact page, a dashboard — **also** goes on the
standing link board, in the same turn you mention it:
```bash
booth link <url> "<short description>" # on nh3-dev
ssh nh3-dev 'booth link <url> "<desc>"' # from anywhere else
```
Still put the link in your reply — this is *in addition to*, not instead of.
The reason is simple and the operator raised it directly: links in chat drown
in terminal scrollback and are gone. The board is a **kept** booth (a
`.forever` sentinel exempts it from the 24h sweep) rendered in its own lane at
the top of `http://10.100.10.50:8090/`, so it survives the session that
produced it. Entries carry provenance automatically (`ALTHING_HANDLE` or the
hostname, plus a timestamp), and the board is a plain markdown file the
operator prunes by hand — `booth unkeep links` or deleting the folder ends it.
Don't post noise: transient junk (a scratch path, a URL only meaningful for
the next two minutes) stays out. If you wouldn't expect him to click it a week
from now, it doesn't belong on the board. Any booth you want to outlive its
24h can be kept the same way (`booth keep <name>`), but keep that rare — the
ephemeral default is what makes the Booth cleanup-free.
- **`secret` — Vaultwarden credential store (per dev box)** — a CLI for stashing
and looking up secrets that shouldn't live in a git repo, backed by
**`vaultwarden.phasefinal.com`** (the `infra-ops` org, visible from the operator's
primary account). On nh3-dev the CLI is
`~/development/eshpfi-management/services/secrets-broker/secret` (bw-backed; auth
bootstraps from `~/.config/secrets-broker/bootstrap.env`, `0600`). Usage:
`secret put <name> (--file P | --stdin) [--folder C] [--field k=v]`,
`secret get <name> [--field F] [--file OUT]` (the only command that prints a
value), `secret list [--prefix P]`, `secret backfill [--dry-run]` (scans THIS
box's `~/development/*/{env.sh,.env}` + `~/.config` creds and upserts each).
Items are hostname-namespaced (`<host>/…`); small text → item note, small binary
→ base64 hidden field, >6000 B → a bw attachment. **STANDING DIRECTIVE (operator,
2026-08-11): the vault is the credential source of truth — store durable secrets
in it AND pull the creds you need FROM it.** Any token / API key / cert / env-secret
worth keeping — not ephemeral, doesn't belong in git — should be `secret put` into
the vault so it survives and is findable, never left single-copy on a box; and when
a task needs a credential (e.g. a gitea token to create a repo), **`secret get` it
from the vault** rather than reading an on-disk copy where practical. The one
exception is `bootstrap.env` itself (secrets-zero — it unlocks the vault, so it
can't live inside it; keep it `0600`). **Not a fleet service / no daemon** — each
new dev box duplicates this stack against its own local secrets (setup steps in
the service `README.md`). Details: auto-memory `reference_secrets_broker_cli`.
## DevOps delegation ## DevOps delegation
+41 -24
View File
@@ -1,6 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Claude Code statusline. Layout: # Claude Code statusline. Layout:
# [📬N] [🔔/🔕] | <proj> ⎇<branch> *<dirty> ↑<unpushed> | <model> | ctx:<pct> <toks> | $<session-cost> | 5h:% 7d:% # [📬N] [🔔/🔕/📵] | <proj> ⎇<branch> *<dirty> ↑<unpushed> | <model> | ctx:<pct> <toks> | $<session-cost> | 5h:% 7d:%
#
# 🔔 reachable — the post office will push to this session
# 🔕 pull-only — nothing will poke it; mail waits until it looks
# 📵 the post office could not be asked — an OUTAGE, not an empty inbox
# ctx% and rate-limit %s are threshold-colored: green <60, yellow 60-90, red >90. # ctx% and rate-limit %s are threshold-colored: green <60, yellow 60-90, red >90.
# All segments degrade gracefully (missing tool / non-git dir / no handle => segment omitted). # All segments degrade gracefully (missing tool / non-git dir / no handle => segment omitted).
input=$(cat) input=$(cat)
@@ -54,6 +58,21 @@ IFS=$'\x1f' read -r model used_pct input_tok five_pct week_pct cwd fast cost_usd
) )
[ -z "$model" ] && model="unknown" [ -z "$model" ] && model="unknown"
# --- persist the rate-limit window for agents (added 2026-09-05, operator directive) ---
# The percentages arrive here on stdin and nowhere else: no CLI subcommand exposes them and
# nothing else on disk carries them, so an agent that must throttle on them cannot see them.
# Written atomically (tmp + mv) so a reader never catches a half-written file. Empty fields
# are preserved as null rather than 0 -- a session with no rate_limits must read as UNKNOWN,
# never as "plenty left", which is the one way this file could cause the harm it prevents.
{
_rl_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"; _rl_tmp="$_rl_dir/rate-limits.json.$$"
printf '{"five_hour_pct":%s,"seven_day_pct":%s,"five_hour_resets_at":%s,"seven_day_resets_at":%s,"written_at":%s,"written_at_iso":"%s"}\n' \
"${five_pct:-null}" "${week_pct:-null}" "${five_reset:-null}" "${week_reset:-null}" \
"$(date +%s)" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$_rl_tmp" 2>/dev/null \
&& mv -f "$_rl_tmp" "$_rl_dir/rate-limits.json" 2>/dev/null
rm -f "$_rl_tmp" 2>/dev/null
} || true
# --- model (compact) + fast-mode flag --- # --- model (compact) + fast-mode flag ---
model="${model%% (*}" # "Opus 4.8 (1M context)" -> "Opus 4.8" model="${model%% (*}" # "Opus 4.8 (1M context)" -> "Opus 4.8"
[ "$fast" = "true" ] && model="⚡$model" [ "$fast" = "true" ] && model="⚡$model"
@@ -103,30 +122,28 @@ if [ -n "$cwd" ]; then
fi fi
fi fi
# --- althing: unread count (📬 N) + monitor-armed (🔔 armed / 🔕 not) --- # --- althing: unread count (📬 N) + reachability (🔔 push / 🔕 pull / 📵 outage) ---
# NOT implemented here any more. `althing-statusline` is the canonical segment,
# shipped as a console script by the althing package (3.4.0+).
#
# This block used to be one of THREE hand-maintained copies of the same twelve
# lines -- this file, althing's plugin/scripts/statusline.sh, and infra-ops'
# copy in eshpfi-management. An audit on 2026-09-02 found DIFFERENT defects in
# each and all three were fixed separately, by hand, on the same day. That is a
# drift surface with a countdown on it, and it is the same failure that left
# this very block dead for a month after the v3 cutover deleted the binary it
# gated on. A script, unlike a document, has somewhere to be installed: PATH.
#
# The payload goes in on STDIN -- the segment resolves the handle from the cwd
# it carries, and falls back to nothing rather than guessing.
#
# The outer `timeout` is deliberately LOOSER than the program's own 2s budget.
# If the outer one fired first we would get an empty segment, which reads as
# "not an althing directory" -- the outage conflation, reintroduced by the
# guard meant to prevent a hang.
althing=""; mon="" althing=""; mon=""
if command -v althing-cli >/dev/null 2>&1; then if command -v althing-statusline >/dev/null 2>&1; then
althing=$(althing-cli statusline 2>/dev/null </dev/null) althing=$(printf '%s' "$input" | timeout 5 althing-statusline 2>/dev/null)
# suppress the empty-inbox form (📪 0) — only surface actual unread mail (📬 N)
case "$althing" in *📪*) althing="" ;; esac
h="${ALTHING_HANDLE:-}"
# ALTHING_HANDLE isn't set in the statusline env — resolve the per-project handle from
# althing's session map (keyed by the cwd Claude Code passes on stdin), the same source
# `althing-cli use` writes. Without this the monitor bell (🔔/🔕) never renders.
[ -z "$h" ] && [ -n "$cwd" ] && h=$(jq -r --arg d "$cwd" '.[$d] // empty' "$HOME/.althing/session_handles.json" 2>/dev/null)
if [ -n "$h" ]; then
mon="🔕"
# Three independent arming mechanisms, one lock each — any live one means "armed":
# monitor-$h.lock <- `althing-cli monitor` (the CC-native exit-0-re-arm loop)
# wake-listener-$h.lock <- `althing-wake-listener` (herald inbound)
# light-monitor-$h.lock <- `althing-light-monitor` (standing watch)
# The kill -0 liveness gate below discards stale locks, so listing all three is safe.
for lk in "$HOME/.althing/monitor-$h.lock" "$HOME/.althing/wake-listener-$h.lock" "$HOME/.althing/light-monitor-$h.lock"; do
[ -f "$lk" ] || continue
pid=$(tr -dc '0-9' < "$lk" 2>/dev/null)
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then mon="🔔"; break; fi
done
fi
fi fi
# --- assemble --- # --- assemble ---