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:
1 parent
9ad073d4fc
commit
fd8e8cbbd7
20 files changed
+619
No files matched your search
+12
@@ -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
|
||||||
@@ -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.
|
||||||
@@ -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/`.
|
||||||
@@ -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`.
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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".
|
||||||
@@ -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`) |
|
||||||
@@ -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.
|
||||||
@@ -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 |
|
||||||
@@ -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).
|
||||||
@@ -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.
|
||||||
@@ -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.
|
||||||
@@ -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
|
||||||
@@ -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>
|
||||||
@@ -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`.
|
||||||
@@ -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
@@ -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).
|
||||||
Reference in new issue
Block a user