docs: AGENTS.md + evidence-backed scaffold (state, trials, decisions, handoff)

- AGENTS.md operating rules incl. Gitea SSH port-2222 note + known_hosts incident
- CURRENT_STATE / TODO / CHANGELOG / TRIALS
- trials: endpoint-key pairing; config-merge safety matrix 14/14 (verify.sh + output)
- docs: DECISIONS (mcode 0.6.12 bundle facts, digest-pinned), FEATURE-MATRIX, PROJECT-HANDOFF
- handoffs: TEMPLATE + 2026-10-19 initial-install record
This commit is contained in:
aygea committed 2026-10-19 23:25:21 -07:00
1 parent 9ad073d4fc
commit fd8e8cbbd7
20 files changed
+619

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# scratch + local outputs (never durable evidence)
tmp/
*.log
# editor / OS noise
.DS_Store
*.swp
# never commit credentials or caches
credential.json
*.key
quota.json
+84
View File
@@ -0,0 +1,84 @@
# AGENTS.md — mcode-status
Aygea z.ai GLM usage segment for the MiniMax Code statusline. Three shipped files:
`zai-usage.sh` (the segment), `install.sh` (self-extracting installer with an embedded
copy), `README.md` (public-facing docs). No `src/` — root is the project.
## Starting or resuming work
1. Read `CURRENT_STATE.md`, then relevant `TODO.md` entries and the latest file in
`handoffs/`. Check `TRIALS.md` before repeating any investigation.
2. Inspect `git status` / `git log` before editing. The remote is
`git@git.itsaygea.com:admin/mcode-sl.git` (see SSH notes below).
3. Pick one bounded objective with explicit acceptance criteria; finish it before
starting another.
## Storage and isolation
- Scratch work goes in `tmp/` (git-ignored). Durable evidence goes in `trials/<topic>-<date>/`
or `evidence/`. OS temp dirs are not durable evidence.
- **Never commit secrets.** The z.ai key lives in SecretVault (`zai_api_key`) and is read
at runtime via `secretvault run`; `~/.secretvault/credential.json` never enters the repo.
- Host-specific paths (e.g. `/home/aygea/.minimax-code/releases/<ver>/...`) are recorded
in docs as facts about *this* machine, not portable assumptions.
## Evidence and confidence
Mark every technical claim in docs as `confirmed` (directly verified, scope stated),
`inferred` (supported interpretation), or `unknown` (untested). Record input paths,
SHA-256 digests, tool versions, and exact commands. Rule of thumb here:
- Anything read out of the mcode bundle is confirmed **for that release only**
(`0.6.12`, digests in `docs/DECISIONS.md`); re-verify after every mcode update.
- Anything not run on real hardware (e.g. macOS) stays `unknown`, however portable
the code looks.
- The safety matrix in `trials/config-merge-safety-2026-10-19/` is the regression gate
for `install.sh` — run it before committing installer changes.
## Trials
Uncertain approach or capability question → bounded trial under
`trials/<topic>-<YYYY-MM-DD>/` with question, scope, commands, expected vs observed,
verdict (`confirmed` / `rejected` / `inconclusive` / `blocked`), and a repeat guard.
Conventions + template: `trials/README.md`. Index: `TRIALS.md`. Preserve failed runs.
## Implementation and verification
- `install.sh` embeds a copy of `zai-usage.sh`. Checkout installs prefer the sibling
file; after editing `zai-usage.sh`, regenerate the embedded copy (command in README)
so `curl | bash` stays identical — the S5 check in the safety matrix enforces this.
- `bash -n` both scripts, then run the safety matrix, before committing.
- The statusline contract: always `exit 0`, print nothing when unknown, never block on
the network (refresh is a detached background job). Violating this freezes the TUI.
## Collaboration and Git
- Commit reviewed work at stage boundaries; push to `origin main` when the work is
verified (established policy for this repo). Report push failures plainly.
- Preserve others' uncommitted work; never reset/discard what you didn't write.
### SSH to Gitea (read before touching the remote)
`git.itsaygea.com` runs **Gitea in Docker with SSH on port 2222**. Port 22 on that
hostname is the *host machine's own sshd* — a different server with different host keys.
- `~/.ssh/config` carries the stanza that makes plain `git push` work:
`Host git.itsaygea.com` → `Port 2222`, `User git`, `IdentityFile ~/.ssh/id_ed25519`.
- Registered account key: **"Mewtwo Aygea"**,
`SHA256:Xc++/NLDGWbXqnzLWleNOhK8/NIgtSBN0xGxNx3gUfs` (= local `id_ed25519.pub`).
- Gitea host key (ED25519) accepted 2026-10-19:
`SHA256:VpdMjgEGpmRPyLhbOpYvrFNWNAxglINkKTgJo5T/sOQ`.
- **Incident record:** on 2026-10-19 a first probe hit port 22, produced a
"REMOTE HOST IDENTIFICATION HAS CHANGED" warning, and wrong (host) keys were briefly
appended to `~/.ssh/known_hosts` under this hostname. They were removed and replaced
with the real port-2222 keys. Repeat guard: any future host-key warning for
`git.itsaygea.com` must be checked against the fingerprint above **and** rescanned on
port 2222 (`ssh-keyscan -p 2222`) — never trust a key captured from port 22. If the
server was not reinstalled, treat it as an incident.
## Stage completion and handoff
At a meaningful boundary: run acceptance checks → update `CURRENT_STATE.md`, `TODO.md`,
`CHANGELOG.md`, `TRIALS.md` → write a handoff under `handoffs/` (template there) →
review the diff → commit → push → report handoff path, commit hash, push result, and
working-tree status separately. Not after every minor action.
+29
View File
@@ -0,0 +1,29 @@
# CHANGELOG
Reverse-chronological. Meaningful changes only; each entry points at evidence.
## 2026-10-19 — initial release: segment, installer, docs scaffold
- `zai-usage.sh` — statusline custom command: Aygea-palette `🔥 <pct>% · <clock>(<remaining>)`
segment; SecretVault-first auth (`secretvault run`, key never in argv) with
`~/.secretvault/credential.json` fallback; cache-shared with the Claude Aygea
statusline (`~/.cache/aygea-sl/quota.json`, schema `{pct, reset_iso, ts}`);
detached flock-guarded background refresh (no cron/systemd); always exit 0;
GNU/BSD date + flock/setsid fallbacks for macOS.
- `install.sh` — self-extracting installer (`curl | bash`): installs to
`~/.local/bin/mcode-zai-usage`, checks SecretVault presence (never prints the secret),
surgically merges the `tui:` section into `~/.minimax/config.yaml` (atomic
temp+fsync+rename, 0600, timestamped backup before change, duplicate-structure
refusal, byte-identical outside the tui block), primes the cache, `--uninstall` mode.
- Fixed during development: EXIT trap referencing function-local vars under `set -u`;
uninstall mode-name mismatch (`uninstall` vs `remove`); TOP regex never capturing the
key name (false "duplicate top-level keys" refusals); embedded-copy forward reference
(0-byte installs in piped mode); double-newline on re-embed.
- Config merge hardening per user request: atomicity + previous-entry checks + format
safety (see `docs/DECISIONS.md` D5, trial `config-merge-safety-2026-10-19`).
- Installed on this machine (backup `~/.minimax/config.yaml.bak.20261019-231642`),
cache primed `🔥 1%`; pushed to `git.itsaygea.com/admin/mcode-sl` (`main`).
- SSH: corrected Gitea-on-2222 setup; removed wrong port-22 host keys from
`~/.ssh/known_hosts` (details in `AGENTS.md` → "SSH to Gitea").
- Docs scaffold: AGENTS/CURRENT_STATE/TODO/CHANGELOG/TRIALS + `docs/`, `trials/`,
`handoffs/`, `tooling/`, `evidence/`.
+41
View File
@@ -0,0 +1,41 @@
# CURRENT_STATE
Updated: 2026-10-19
## Objective
Self-contained, secret-safe z.ai GLM 5h-usage segment for the MiniMax Code statusline,
installable on 1 macOS + 2 Ubuntu systems with one `curl | bash` line.
## Verified capabilities (this machine, mcode 0.6.12, Ubuntu-based PVE host)
- `confirmed` — Segment renders real quota data: `🔥 1% · 4:16a(4h59m)` right after
install (cache primed through SecretVault key against `https://api.z.ai`).
- `confirmed` — Config merge safety matrix 14/14
(`trials/config-merge-safety-2026-10-19/output.txt`): atomic write, 0600 on new files,
backup equals pre-merge original, duplicate-structure refusal, provider untouched,
piped-install embed identical, clean uninstall.
- `confirmed` — Vault key pairs with `api.z.ai` (200); old credential.json clientKey
pairs with the `vault.itsaygea.com` proxy (200); vault key against the proxy → 401.
(`trials/mcode-endpoint-key-pairing-2026-10-19/record.md`)
- `confirmed` — mcode statusline mechanics for 0.6.12: `tui.statusLine` + `tui.customStatusLine`
in `~/.minimax/config.yaml`; JSON on stdin; stdout becomes the `custom-command` item on
exit 0; `colorMode: ansi` passes ANSI through; intervalSeconds ≥10, timeoutMs 500–30000.
Evidence: bundle reads in `docs/DECISIONS.md` (release digests recorded).
- `confirmed` — Pushed to `git@git.itsaygea.com:admin/mcode-sl.git` (port 2222 SSH).
## Active work
None in flight. Last stage (initial install + push) completed 2026-10-19.
## Blockers
- Visual confirmation of the rendered segment in the live TUI requires the user to
restart MiniMax Code. Until then, ANSI/emoji rendering in the statusline is
`inferred` (config accepted by the parser; passthrough path verified in code, not on screen).
## Exact next action
User restarts the MiniMax Code TUI and confirms the segment renders (colors, emoji, no
misalignment). Then roll out to the two Ubuntu machines + macOS via the curl one-liner
and record results in `TODO.md` / `docs/FEATURE-MATRIX.md`.
+9
View File
@@ -76,6 +76,15 @@ Installer env overrides: `MCODE_SL_ITEMS` (item list), `MCODE_SL_INTERVAL`, `MCO
curl -fsSL https://git.itsaygea.com/admin/mcode-sl/raw/branch/main/install.sh | bash -s -- --uninstall curl -fsSL https://git.itsaygea.com/admin/mcode-sl/raw/branch/main/install.sh | bash -s -- --uninstall
``` ```
## Documentation
- `AGENTS.md` — operating instructions for humans + agents (incl. Gitea SSH notes)
- `CURRENT_STATE.md` — where the project stands and the exact next action
- `TODO.md` — prioritized work with acceptance criteria
- `CHANGELOG.md` / `TRIALS.md` — change log and experiment index
- `docs/` — decisions (ADR-style), feature matrix, handoff protocol
- `handoffs/` — stage continuation records; `tooling/` — verified toolchain
## Development ## Development
Requires `jq` + `curl`; `secretvault` optional (fallback: credential.json); `python3` for the config merge. Test locally: Requires `jq` + `curl`; `secretvault` optional (fallback: credential.json); `python3` for the config merge. Test locally:
+27
View File
@@ -0,0 +1,27 @@
# TODO
## Now
- [ ] **Visual TUI verification** — user restarts MiniMax Code; confirm the
`custom-command` segment renders with Aygea colors, emoji, and no width misalignment.
Acceptance: screenshot or user confirmation; move rendering from `inferred` to
`confirmed` in `docs/FEATURE-MATRIX.md`.
- [ ] **Ubuntu rollout ×2** — run the curl one-liner on both Ubuntu boxes; each needs the
`zai_api_key` SecretVault secret (or credential.json). Acceptance: `printf '{}' | mcode-zai-usage`
prints a segment on both; entry recorded in FEATURE-MATRIX.
## Next
- [ ] **macOS rollout** — same one-liner on the Mac. Script is written portable
(`date -r` fallback, no-`flock`/no-`setsid` degrade, `vm_stat` memory) but has never
run on macOS: treat as `unknown` until tested. Acceptance: install + segment on macOS.
- [ ] **mcode-update resilience check** — after the next mcode release, re-grep the new
bundle for `customStatusLine`/`statusLineItems` handling and re-check the clamps
documented in `docs/DECISIONS.md` D2; update digests there.
## Deferred
- Optional `AYGEA_SL_MEM` memory-segment polish on macOS (page-size assumptions in
`vm_stat` parsing are untested there).
- Consider a `--json` inspection mode for debugging cache state. Rejected for now:
scope creep against "little self-contained tool".
+10
View File
@@ -0,0 +1,10 @@
# TRIALS — index
Conventions and template: `trials/README.md`. Verdicts: `confirmed` / `rejected` /
`inconclusive` / `blocked`. Before repeating a rejected/inconclusive trial, cite it and
state what changed.
| Date | Trial | Verdict | Record |
|---|---|---|---|
| 2026-10-19 | Which endpoint accepts which z.ai key (vault key vs credential.json clientKey) | confirmed | `trials/mcode-endpoint-key-pairing-2026-10-19/record.md` |
| 2026-10-19 | install.sh config-merge safety matrix (atomicity, backup, refusal, embed, uninstall) | confirmed | `trials/config-merge-safety-2026-10-19/` (14/14, `output.txt`) |
+84
View File
@@ -0,0 +1,84 @@
# DECISIONS
Stable IDs; newest at the bottom. Each records context, choice, alternatives, consequences.
## D1 — Vault-first credentials, `api.zai` direct; credential.json fallback
- **Context:** the Aygea Claude statusline used `~/.secretvault/credential.json`
(`url` + `clientKey` → `vault.itsaygea.com` proxy). The user wants this repo public
and machines to need nothing but their existing SecretVault (`zai_api_key`).
- **Choice:** read `zai_api_key` via `secretvault run` (name from env, default
`zai_api_key`), hit `https://api.z.ai/api/monitor/usage/quota/limit`; fall back to
credential.json → `${url}/proxy/zai/...`. Key reaches curl via a 0600 header file
(`--header @file`), never argv.
- **Alternatives:** bake the proxy URL + require credential.json everywhere (rejected:
repo would document private infra as a requirement); store JSON {url,key} in the
vault (rejected: existing secret is a plain key).
- **Consequences:** one secret per machine is the only setup; trial
`mcode-endpoint-key-pairing-2026-10-19` pins the pairing. Proxy users still work.
## D2 — mcode statusline mechanics (verified facts, release-pinned)
Confirmed by reading the 0.6.12 bundle — re-verify after every mcode update.
Files (SHA-256): `chunks/launcher-AVQRYDKB.js` `2c4337e3…edfbe3`,
`chunks/chunk-X3PES5WL.js` `600c23d…09ee5` under
`~/.minimax-code/releases/0.6.12/lib/node_modules/@minimax-ai/code/`.
- Config source: `<dataDir>/config.yaml` → `tui.statusLine` (array) +
`tui.customStatusLine` (`Pv()` in launcher chunk).
- Valid statusLine items: `current-dir, session-title, git-branch, review-link,
plan-mode, approval-mode, model-with-reasoning, model, context-window, subagent,
token-quota, cache-read-ratio, context-remaining, context-meter, custom-command`.
- Custom command runner: only active when `custom-command` is in `statusLine` **and**
`build-mode` is not; command required (non-empty). Schema:
`display: inline|block`, `position: above|below`, `colorMode: plain|ansi`,
`intervalSeconds` (default 0 = off, clamp ≥10), `timeoutMs` (default 5000,
clamp 500–30000), block `maxLines` default 3 (clamp 1–5).
- Invocation: `{command}` parsed + spawned with `cwd = workspace_dir`, JSON on stdin
(`{protocol, event: startup|interval|session-change|workspace-change, session_id,
workspace_dir, model, session_title, tui_version}`), stdout capped ~8 KiB
(exact cap expression `Q1` not disambiguated: `8*1024` vs `8e3` — inferred).
stdout becomes the `custom-command` item **only on exit 0 without timeout**;
inline mode renders the first line; `colorMode: ansi` keeps escape codes when the
terminal color level > 0, strips otherwise.
- **Consequence:** our script must be silent-fail (`exit 0`, empty output when unknown)
and must not rely on stdin content.
## D3 — mcode is the scheduler; refresh decoupled in-process
- **Context:** the Claude statusline needed a systemd timer because Claude Code has no
interval hook. mcode's `customStatusLine.intervalSeconds` re-runs the command itself.
- **Choice:** no cron/systemd. On each call: fresh cache (≤150s) → print; stale → spawn
detached (`setsid`, fallback `& disown`) flock-guarded refresh (`--refresh-bg`) and
show the still-valid value (≤360s) or nothing.
- **Consequences:** zero extra services; segment self-heals; offline machines just hide
the segment after 6 min. Timer coexistence is harmless (same cache file).
## D4 — Shared cache with the Claude Aygea statusline
- **Choice:** keep schema `{pct, reset_iso, ts}` at `~/.cache/aygea-sl/quota.json`
exactly as the Claude refresher writes it (reset written as local ISO; epoch
conversions have GNU/BSD branches).
- **Consequence:** both ecosystems interop; any writer refreshes both. Constrained the
parser to ISO strings instead of the internally simpler `reset_ms`.
## D5 — Config merge safety rails
- **Context:** user requirement: atomic, previous-entry aware, must never break a config
holding API keys. Two early bugs (in-place write; backup taken after merge) proved the point.
- **Choice:** python3 stdlib line surgery limited to the `tui:` block; refuses multiple
`tui:` blocks or duplicate keys; validates result (structural + PyYAML when available);
writes temp + fsync + `os.replace`; preserves mode (0600 for new); timestamped backup
copied **before** first modification; byte-exact elsewhere (incl. trailing newline).
- **Alternatives:** PyYAML full round-trip (rejected: reformats/comments lost); yq
(rejected: extra dependency on every machine).
- **Consequences:** merge is monotonic and reviewable; `docs/FEATURE-MATRIX.md` gates
remaining platform risk.
## D6 — Public repo + Gitea over SSH port 2222
- **Choice:** repo `git.itsaygea.com/admin/mcode-sl` (`main`); remote via SSH; the
curl one-liner points at `…/raw/branch/main/install.sh`. No secrets in the repo by
design (D1).
- **Consequences:** see `AGENTS.md` → "SSH to Gitea" for the port-22 incident record,
accepted host-key fingerprint, and the repeat guard.
+20
View File
@@ -0,0 +1,20 @@
# FEATURE-MATRIX
Status: `confirmed` (verified within stated coverage) / `inferred` / `unknown`.
Evidence links point at trials, digests, or recorded commands.
| Capability | Status | Coverage / limits | Evidence |
|---|---|---|---|
| Quota fetch via SecretVault key → `api.z.ai` | confirmed | this machine; key `zai_api_key` | `trials/mcode-endpoint-key-pairing-2026-10-19/record.md` |
| Quota fetch via credential.json → `vault.itsaygea.com` proxy | confirmed | code path exercised in dev; falls back only | same record |
| Statusline segment output (value, clock, remaining, colors, thresholds) | confirmed | plain + 256 + truecolor modes exercised with mock caches | session commands, `CHANGELOG` 2026-10-19 |
| Stale/hidden behavior (≤150s fresh; ≤360s stale shown; >360s hidden) | confirmed | mock-cache tests, exit 0 always | session commands |
| mcode config schema + clamps (0.6.12) | confirmed | release-pinned; re-check on updates | `docs/DECISIONS.md` D2 |
| Config merge: atomic write, 0600, backup-before-change, refusal, byte-preservation, uninstall | confirmed | Linux host, 14/14 matrix | `trials/config-merge-safety-2026-10-19/` |
| Piped (`curl \| bash`) install with embedded copy | confirmed | embed byte-identical (S5) | same |
| Segment renders in live mcode TUI (ANSI + emoji) | **inferred** | passthrough verified in code; not yet seen on screen | D2; pending user restart |
| macOS end-to-end (install, date -r, no flock/setsid, `install -m`, vm_stat) | **unknown** | written portable, never run on macOS | TODO |
| Ubuntu rollout ×2 | **unknown** | not yet executed | TODO |
| secretvault CLI present + secret readable on other machines | **unknown** | assumed per user statement; verify at rollout | TODO |
| Background refresh survives mcode process-group kills | confirmed (by construction) | `setsid` detach; not adversarially tested | D3 rationale |
| mcode update resilience | **unknown** | bundle re-read required each release | D2 repeat guard |
+37
View File
@@ -0,0 +1,37 @@
# PROJECT-HANDOFF
How to resume work in this repo.
## Entry sequence
1. `CURRENT_STATE.md` — objective, what's confirmed, exact next action.
2. `TODO.md` — prioritized work with acceptance criteria.
3. Latest file in `handoffs/` — where the last stage stopped and why.
4. `TRIALS.md` — don't repeat what a verdict already settled.
5. `git status` + `git log` — see what's in flight.
## Authoritative records
- Decisions + verified mcode internals: `docs/DECISIONS.md` (D2 is release-pinned —
re-verify after mcode updates).
- Capability truth table: `docs/FEATURE-MATRIX.md` (update status as evidence lands).
- Regression gate for the installer: `trials/config-merge-safety-2026-10-19/verify.sh`
(must pass 14/14 before committing installer changes).
- Host-specific facts (Gitea SSH on 2222, key fingerprints): `AGENTS.md` → "SSH to Gitea".
## Handoff protocol
At a meaningful stage boundary write `handoffs/<date>-<topic>.md` from
`handoffs/TEMPLATE.md`: stopping point, verified results + evidence links, corrected
assumptions, blockers, exact next action with acceptance criteria, reproduction
commands, and git state (branch, commit, push result). Preserve prior handoffs; link
artifacts instead of duplicating logs.
## Environment assumptions (this project)
- Linux host `mewtwo` (Ubuntu-based, PVE); MiniMax Code 0.6.12 at
`~/.minimax-code/releases/0.6.12/`; data dir `~/.minimax/`.
- `secretvault` CLI at `~/.local/bin/secretvault`; secret `zai_api_key` (production).
- Remote: `git@git.itsaygea.com:admin/mcode-sl.git` — port 2222, see `AGENTS.md`.
Nothing above is portable to other machines without re-verification (see FEATURE-MATRIX).
+5
View File
@@ -0,0 +1,5 @@
# docs
- `PROJECT-HANDOFF.md` — how to resume work here; where authoritative records live.
- `DECISIONS.md` — indexed decisions (ADR-style) with evidence.
- `FEATURE-MATRIX.md` — capability × verification status; the honest state of the world.
+7
View File
@@ -0,0 +1,7 @@
# evidence
Shared evidence that does not belong to a single trial (captured command outputs,
environment snapshots, digest manifests). Trial-specific evidence stays inside its
`trials/<topic>-<date>/` directory.
Currently empty — evidence for the initial stage lives in the trial directories.
+75
View File
@@ -0,0 +1,75 @@
# Handoff: 2026-10-19 — initial release, install, push, docs scaffold
## Objective and stopping point
Build a self-contained z.ai GLM usage segment for the MiniMax Code statusline
(`zai-usage.sh` + self-extracting `install.sh`), install it on this machine, publish to
`git.itsaygea.com/admin/mcode-sl`, and scaffold the evidence-backed docs structure.
Stopped at the stage boundary: installed + pushed; TUI visual check and cross-machine
rollout deliberately left for next stages.
## Verified results and evidence
- `confirmed` — Safety matrix 14/14 on Linux: `trials/config-merge-safety-2026-10-19/output.txt`
(atomic write, 0600, backup == pre-merge original, duplicate-tui refusal untouched,
piped-install embed byte-identical, uninstall clean).
- `confirmed` — Key/endpoint pairing: `trials/mcode-endpoint-key-pairing-2026-10-19/record.md`
(vault key → api.z.ai 200; proxy 401; credential.json clientKey → proxy 200).
- `confirmed` — Live install on this machine: secret found, backup
`~/.minimax/config.yaml.bak.20261019-231642`, cache primed (`🔥 1% · 4:16a(4h59m)`),
provider/apiKey intact in `~/.minimax/config.yaml`.
- `confirmed` — Push: `main` → `git@git.itsaygea.com:admin/mcode-sl.git`; raw URL serves
a valid installer whose embedded copy matches the installed script.
- `inferred` — TUI rendering (colors/emoji): passthrough verified in bundle code
(`docs/DECISIONS.md` D2), not yet observed on screen.
- File digests at stage start: `zai-usage.sh` `ca2141a5…fa63c61`,
`install.sh` `a6c433da…4989a1`, `README.md` `d0e5bc42…576d5fb`.
## Corrected assumptions and limitations
- Assumed the user's Gitea answered SSH on 22 → actually Docker on **2222**; port 22 is
the host sshd. Wrong host keys were briefly written to `~/.ssh/known_hosts` and then
replaced (incident + repeat guard: `AGENTS.md` → "SSH to Gitea").
- `credential.json`'s clientKey is NOT the same credential as vault `zai_api_key`.
- macOS portability is designed-in but unproven (FEATURE-MATRIX `unknown`).
- mcode facts are pinned to 0.6.12 bundle digests; any update invalidates D2 until re-read.
## Unresolved questions and blockers
- Does the segment render correctly in the live TUI? (needs user restart)
- Do the other machines (2× Ubuntu, 1× macOS) have `secretvault` + `zai_api_key`?
- Does `zai_api_key` survive rotation without endpoint changes?
## Exact next action
User restarts MiniMax Code and confirms rendering; then run the curl one-liner on the
two Ubuntu boxes. Acceptance: segment visible with colors; matrix rerun green on each
Linux box; FEATURE-MATRIX rows updated from `unknown`.
## Reproduction
```bash
# installer (any machine)
curl -fsSL https://git.itsaygea.com/admin/mcode-sl/raw/branch/main/install.sh | bash
# segment preview / refresh
printf '{}' | ~/.local/bin/mcode-zai-usage
~/.local/bin/mcode-zai-usage --refresh
# regression gate
bash trials/config-merge-safety-2026-10-19/verify.sh
```
Requires: bash, jq, curl, python3; secretvault + `zai_api_key` for the primary path.
## Local artifacts
- `~/.minimax/config.yaml` — live config (backups `~/.minimax/config.yaml.bak.*`).
- `~/.cache/aygea-sl/quota.json` — quota cache (safe to delete; self-heals).
- `~/.secretvault/credential.json` — legacy proxy credential (never committed).
## Git state
- Branch: `main`
- Commit: see `git log --oneline -1` (docs-scaffold commit follows the `first commit`
`9ad073d`; final handoff commit reported in the stage summary, not here)
- Push: pushed to `git@git.itsaygea.com:admin/mcode-sl.git`
- Working tree: expected clean after the docs-scaffold commit
+39
View File
@@ -0,0 +1,39 @@
# Handoff: <date> — <topic>
## Objective and stopping point
<What the stage set out to do; where exactly it stopped.>
## Verified results and evidence
<Claims with status (`confirmed`/`inferred`/`unknown`), each linked to its evidence:
trial record, output file, digest, or command. No unevidenced claims.>
## Corrected assumptions and limitations
<What we believed at the start that turned out wrong; hard limits of the result.>
## Unresolved questions and blockers
<Open questions, with who/what is needed to resolve them.>
## Exact next action
<Single next step + acceptance criteria.>
## Reproduction
```bash
<exact commands, host requirements>
```
## Local artifacts
<Ignored/local files this work depends on and where to recover them.>
## Git state
- Branch: <branch>
- Commit: <hash — never self-referential; report the final handoff commit after it exists>
- Push: <pushed to <remote> / failed: <reason>>
- Working tree: <clean / modified files listed>
+18
View File
@@ -0,0 +1,18 @@
# tooling
Verified tools for this project (host `mewtwo`, 2026-10-19):
| Tool | Version/notes | Required for |
|---|---|---|
| bash | system | everything |
| jq | system | `zai-usage.sh` parsing |
| curl | system | quota fetch |
| python3 | stdlib; PyYAML present locally (optional, adds YAML validation) | `install.sh` merge |
| git | SSH remote | pushes |
| secretvault | `~/.local/bin/secretvault` CLI; MCP `create_secret` to provision | key resolution (fallback: credential.json) |
Setup on a new machine: `sudo`-install `jq curl python3` if missing, create the
`zai_api_key` SecretVault secret, then the one-liner from `README.md`.
macOS caveats (designed for, untested): no `flock`/`setsid` → script degrades to plain
background refresh; `date -r` fallback path; BSD `install` supports `-m 755`.
+11
View File
@@ -0,0 +1,11 @@
# trials
Bounded experiments. One directory per trial: `trials/<topic>-<YYYY-MM-DD>/` containing
`record.md` and, where possible, a re-runnable `verify.sh` plus its captured `output.txt`.
Required sections: question/hypothesis, scope + acceptance criteria, inputs (paths,
hashes, tool versions), procedure (exact commands), expected vs observed, evidence
paths, verdict (`confirmed` / `rejected` / `inconclusive` / `blocked`), and a repeat
guard (what would justify another attempt). Preserve failed runs.
Index lives in `TRIALS.md`. Routine edits and ordinary test runs do not need a trial.
@@ -0,0 +1,15 @@
PASS S1 fresh-install rc
PASS S1 created-tui message
PASS S1 new config mode 0600
PASS S1 no tmp leftovers
PASS S2 idempotent rerun
PASS S3 update rc
PASS S3 backup equals pre-merge original
PASS S3 provider intact + keys updated
PASS S4 duplicate-tui refused
PASS S4 file untouched on refusal
PASS S4 refusal reason reported
PASS S5 embedded copy identical
PASS S6 uninstall rc
PASS S6 keys removed, items kept
== 14 passed, 0 failed ==
@@ -0,0 +1,19 @@
# Trial: install.sh config-merge safety matrix
- **Date:** 2026-10-19
- **Question / hypothesis:** the `~/.minimax/config.yaml` surgery is atomic, idempotent,
backs up before change, refuses ambiguous input, keeps everything outside the `tui:`
block byte-identical, and works identically from a checkout or a piped install.
- **Scope / acceptance:** the 14 checks in `verify.sh` (S1–S6) all pass.
- **Inputs:** `install.sh` `a6c433da2cde4d92387c4de5845f6770ed71df55548499654e579869d84989a1`,
`zai-usage.sh` `ca2141a50b528072d7ca2a4842cd9d6c535fc036e2ff34f816fafc713fa63c61`.
- **Environment:** bash, GNU coreutils, python3 (PyYAML present → YAML validation active),
mktemp sandboxes with overridden `$HOME` (no live config touched).
- **Procedure:** `bash trials/config-merge-safety-2026-10-19/verify.sh`
- **Expected vs observed:** expected 14/14; observed 14/14 (`output.txt`).
First recorded run also caught two runner-script typos (`T1b`/`T2u` under `set -u`),
fixed before the clean run — both were test-harness bugs, not installer bugs.
- **Verdict:** confirmed (Linux, this host).
- **Repeat guard / limits:** rerun after any change to `install.sh` (required by
`AGENTS.md`), after mcode updates that change config.yaml's generated shape, and once
on macOS — pass/fail there is currently `unknown` (BSD stat/date/`install` differences).
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Trial: config-merge safety matrix for install.sh
#
# Re-runnable acceptance check for the ~/.minimax/config.yaml surgery:
# fresh create, idempotency, backup-before-change, byte preservation,
# duplicate-structure refusal, piped/embedded install, uninstall.
#
# Usage: bash verify.sh (from anywhere; uses mktemp sandboxes)
# Exit 0 when every check passes.
set -u
export LC_ALL=C
REPO="$(cd "$(dirname "$0")/../.." && pwd)"
pass=0; fail=0
ok(){ if [ "$2" = "0" ]; then pass=$((pass+1)); printf 'PASS %s\n' "$1"; else fail=$((fail+1)); printf 'FAIL %s\n' "$1"; fi; }
# S1 fresh install: creates tui block, 0600
T1=$(mktemp -d); HOME=$T1 bash "$REPO/install.sh" >"$T1.log" 2>&1; ok "S1 fresh-install rc" $?
grep -q created-tui "$T1.log"; ok "S1 created-tui message" $?
[ "$(stat -c '%a' "$T1/.minimax/config.yaml" 2>/dev/null)" = 600 ]; ok "S1 new config mode 0600" $?
ls "$T1"/.minimax/config.yaml.tmp.* >/dev/null 2>&1; [ $? -ne 0 ]; ok "S1 no tmp leftovers" $?
# S2 idempotent rerun
HOME=$T1 bash "$REPO/install.sh" >"$T1.b.log" 2>&1
grep -q already-configured "$T1.b.log"; ok "S2 idempotent rerun" $?
# S3 existing config: update in place, backup == pre-merge original
T2=$(mktemp -d); mkdir -p "$T2/.minimax"
printf 'logLevel: info\nprovider:\n x:\n apiKey: keepme\ntui:\n statusLine:\n - current-dir\n customStatusLine:\n command: /old/path\n intervalSeconds: 30\n' > "$T2/.minimax/config.yaml"
cp "$T2/.minimax/config.yaml" "$T2/orig.yaml"
HOME=$T2 bash "$REPO/install.sh" >"$T2.log" 2>&1; ok "S3 update rc" $?
cmp -s "$(ls -t "$T2"/.minimax/config.yaml.bak.* | head -1)" "$T2/orig.yaml"; ok "S3 backup equals pre-merge original" $?
grep -q "apiKey: keepme" "$T2/.minimax/config.yaml" && grep -q "colorMode: ansi" "$T2/.minimax/config.yaml"; ok "S3 provider intact + keys updated" $?
# S4 duplicate top-level tui blocks: refuse, file untouched
T3=$(mktemp -d); mkdir -p "$T3/.minimax"
printf 'a: 1\ntui:\n statusLine:\n - current-dir\nb: 2\ntui:\n statusLine:\n - model\nc: 3\n' > "$T3/.minimax/config.yaml"
cp "$T3/.minimax/config.yaml" "$T3/orig.yaml"
HOME=$T3 bash "$REPO/install.sh" >"$T3.log" 2>&1; [ $? -ne 0 ]; ok "S4 duplicate-tui refused" $?
cmp -s "$T3/.minimax/config.yaml" "$T3/orig.yaml"; ok "S4 file untouched on refusal" $?
grep -q merge-refused "$T3.log"; ok "S4 refusal reason reported" $?
# S5 piped/embedded install (only install.sh present) -> embedded == zai-usage.sh
T4=$(mktemp -d); cp "$REPO/install.sh" "$T4/"
HOME=$T4 bash "$T4/install.sh" >"$T4.log" 2>&1
cmp -s "$T4/.local/bin/mcode-zai-usage" "$REPO/zai-usage.sh"; ok "S5 embedded copy identical" $?
# S6 uninstall: removes keys, keeps other items
HOME=$T2 bash "$REPO/install.sh" --uninstall >"$T2.u.log" 2>&1; ok "S6 uninstall rc" $?
! grep -q customStatusLine "$T2/.minimax/config.yaml" && ! grep -q custom-command "$T2/.minimax/config.yaml" && grep -q "current-dir" "$T2/.minimax/config.yaml"; ok "S6 keys removed, items kept" $?
printf '== %s passed, %s failed ==\n' "$pass" "$fail"
rm -rf "$T1" "$T2" "$T3" "$T4"
[ "$fail" -eq 0 ]
@@ -0,0 +1,24 @@
# Trial: mcode endpoint / key pairing
- **Date:** 2026-10-19
- **Question / hypothesis:** the SecretVault secret `zai_api_key` (plain 48–49 char
string) is the direct z.ai API key, not the `vault.itsaygea.com` proxy clientKey;
therefore the statusline should default to `https://api.z.ai`.
- **Scope / acceptance:** three HTTP probes return codes consistent with exactly one
pairing per key; no key material printed.
- **Inputs / environment:** host `mewtwo` (Ubuntu, PVE), curl with `--max-time 8`,
key fetched via `secretvault run --secret zai_api_key -- bash -c 'printf %s "$zai_api_key"'`;
legacy key from `~/.secretvault/credential.json` (`.clientKey`, 51 chars).
- **Procedure:**
```bash
# codes only; -o /dev/null -w '%{http_code}'
vault-key @ https://vault.itsaygea.com/proxy/zai/api/monitor/usage/quota/limit
vault-key @ https://api.z.ai/api/monitor/usage/quota/limit
cred-key @ https://vault.itsaygea.com/proxy/zai/api/monitor/usage/quota/limit
```
- **Expected vs observed:** expected one 200; observed
`401 (vault@proxy) / 200 (vault@zai) / 200 (cred@proxy)`.
- **Verdict:** confirmed — vault key is the direct z.ai credential; proxy clientKey is
separate. `zai-usage.sh` implements vault→`api.z.ai` first, credential.json→proxy fallback.
- **Repeat guard:** revisit if the vault secret is rotated to a proxy clientKey, or if
`api.z.ai` starts rejecting it (401 after rotation).