Skip to content

ctx v5.15.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 18:22
· 79 commits to root since this release
v5.15.0
890e4d4

v5.15.0 — Tree-Shaking RC-2b: Phase D, zweiter Teil — CLI-Exit-Vertrag, /api/recent, Grants auf REST, Prompt-Provenienz

Minor-Release ohne Migration (Schema bleibt bei 151). Zehn Wellen des Tree-Shaking-Runs (Board v3; Entscheide K25–K39 in DECISIONS.md), jede mit Fable-Prüf-Agent (voller Diff-Read, Rot→Grün nachgefahren, Negativ-Proben, Integrations-Suiten) und eigenhändigen Gates auf root gelandet; 8 Auflagen in 10 Wellen, 0 NICHT MERGEBAR. Die beabsichtigten Verhaltensänderungen sind unten vollständig benannt und gepinnt; der Rest ist byte-gleich belegt.

K25-ANNOTATION — Exit-Code-Wechsel der CLI (T03-13, E03-6 = A, E03-10 = B; bewusst als Minor geschnitten, V1 = D):
(1) 24 Kommandopfade wechseln bei einer success:false-Antwort von Exit 0 auf Exit 1: stats, categories, get, delete, list-meta, digest, save, search, query --json, manage, dream / dream stats / review / enable / disable / throttle, mcp / mcp list, mcp delete, keys / keys list, keys delete und alle drei block-grant-Verben. Gedruckt wird zuerst, der Prüfer entscheidet danach — stdout bleibt byte-gleich (ctx stats | jq behält seine Bytes), der Servergrund geht auf stderr. Ein Prüfer (internal/cli/envelope.go) statt drei; die Fixture internal/cli/envelope_test.go listet alle 108 registrierten Kommandopfade mit alter und neuer Exit-Klasse und führt 100 davon gegen einen success:false-Server aus.
(2) ctx api druckt bei success:false jetzt den Antwort-Body auf stdout (gemessen 0 → 50 B), Exit-Code unverändert 1 — docs/cli.md beschrieb das seit jeher, der Code tat es nicht.
(3) ctx manage ≡ ctx api: beide laufen durch runRawRequest — derselbe Request, dieselbe Ausgabe, derselbe Exit-Vertrag; die Schreibweise ctx manage stats bleibt.
(4) Nur zwei Kommandos ändern ihre stdout-Bytes: keys list und mcp list drucken auf ein 403 nicht mehr „No API keys provisioned." / „No MCP clients registered." (eine falsche Aussage über eine abgelehnte Anfrage), der Servergrund steht auf stderr. Ein leerer oder nicht-JSON-Body endet auf typisierten Kommandos jetzt fail-closed mit Exit 1 (noenv 20 / notjson 17 Pfade); sieben Ad-hoc-stderr-Präfixe („error: ", „failed: ", „query failed: ") fallen zugunsten des Servergrunds. Rahmenlose Auth-Antworten ({"error":"unauthorized"} ohne success-Feld) behalten Error: unauthorized byte-gleich (Prüfer-Fund, eingearbeitet).
(5) Unverändert, mit Absicht: ctx health (GET /health trägt keinen Rahmen), die still degradierenden Hook-Oberflächen brief / persist / statusline / ingest (Exit 0), ctx contract mit eigener Skala 0/1/2/3, und die Roh-Durchreichen api/manage bei Bodies OHNE success-Feld (nacktes Array, durchgereichtes /health ⇒ Exit 0).
Die Änderung ist server-unabhängig (der Draht bewegt sich nicht). Rollout je Host: ctx version vor und nach dem Hop, Grep-Vorlage für Konsumenten des alten Exit 0, Rollback = Re-Download des Vor-Assets — docs/operations.md §„CLI rollout: the envelope exit-code contract (v5.15.0)", Tabelle in docs/cli.md §„Exit codes: one contract for every command".

Weitere Verhaltensänderungen:
(6) T03-8b — POST /api/recent ist neu (K26 / E03-11 = B): die REST-Tür auf dieselbe Store-Abfrage wie das MCP-Tool recent (store.RecentBlocks mit Klemme, Scope-Wache, Grant-OR), Alias-Union types_exclude ∪ block_roles_exclude, Grants des Tenants, Rate-Limit-Bucket wie /api/search; Envelope {success, count, filters, results} in /api/search-Form minus sensitivity, ohne limit-Echo. Parität MCP-Menge == REST-Menge über 9 Filter-Varianten gepinnt (recent_parity_integration_test.go).
(7) T03-9 + T04-20 — /api/search löst jetzt Block-Grants auf (E03-1 = A): vorher reiste ein literales nil, ein dem Tenant gegranteter Block war per MCP sichtbar und per REST nicht. Die Grant-Menge eines Tenants bekommt eine Schranke je Request (maxGrantedBlockIDs = 1024, Gültigkeitsgrenze der Strategie A, kein Registry-Key): darüber wird der Lesevorgang LAUT abgelehnt (REST 500 + eine Prosa, MCP errResult) statt still auf scope-only gekürzt. MCP-search akzeptiert block_roles_exclude additiv (E03-3 = A) statt ihn wortlos zu verwerfen; die REST-Decke 50 bleibt REST-only (K28 / E03-2 = B). Byte-Shape 15 REST- + 12 MCP-Varianten: Diff leer.
(8) T04-21 — jede context_llm_log-Zeile trägt metadata.prompt_id + prompt_version (14 Prompt-Identitäten in internal/prompts, ein Stempel-Helfer llmlog.StampPrompt an drei Orten; embed-Wire- und K9-Rejection-Zeilen bewusst ohne Stempel). Kein Byte eines Prompt-Körpers ändert sich, keine Migration, keine Spalte, kein Config-Key. Nadel nach Deploy: metadata ? 'prompt_id' auf context_llm_log.
(9) T03-8 — MCP-recent liest durch store.RecentBlocks statt per Inline-SQL; ein Row-Scan-Fehler bricht jetzt ab (fail-closed) statt die Zeile still zu überspringen; NOT is_archived steht außerhalb der Scope/Grant-OR (ein gegranteter archivierter Block leckt nicht, gepinnt). Grants werden vor der Store-Wache aufgelöst (A-4).
(10) T03-11 — /api/manage: 89 Actions in EINER Tabelle mit Routing und Tier je Zeile (statt 18 case-Arme + 15 Dispatcher + 211-zeiliger Resolver); die Tier-Enum beginnt bei tierUnset, eine Zeile ohne Tier antwortet 500 + slog.Error (nie 403, kein Tier-Orakel); elf Actions, die den Tier bisher per Default erreichten, stehen explizit auf tierOpen (Verhalten unverändert). Byte-Shape 306 Zellen identisch. docs/api.md dokumentiert die sieben Roh-Durchreichen-Actions (E03-9 = B).
(11) T03-2 — POST /api/store läuft durch runStageWriteGates, dieselbe Tor-Kette wie MCP-direct und MCP-staged (achter Probe-Arm im Gatechain-Test). Einzige Änderung: der Internal-Ausgang des Rate-Limit-Tors loggt „stage gates: rate limit check error" statt „store: …" (Attribute unverändert). Textinventar 13 Ablehnungen + 6 Erfolgs-Envelopes byte-gleich.

Wave-0 (byte-gleich belegt):
T03-10 — internal/handler/issues_core.go: EINE Schreiblogik für REST, manage und MCP der Issue-Familie (Registry-Wache, WorkflowInitial + ValidateTransition, Tx-Klammer, Store-Aufruf); Byte-Shape 50 Zellen: diff leer; Drossel/Zugriffs-Buchung bleiben REST-only (E03-5 = B); Rename resolveWriteScope → resolveProjectWriteScope; neuer Entry-Transition-Wächter für CREATE (Lücke der Bestandssuite).
T03-12 — internal/cli: renderOrJSON ersetzt 38 TTY-Verzweigungen, simpleCmd 11 Kommando-Rümpfe, newHTTPClient/NewClientWithTimeout 3 von 4 http.Client-Konstruktionen; 119 Läufe × pipe/pty, 357 md5-Paare über stdout/stderr/exit gleich, 129 Requests byte-gleich, 115 --help-Seiten md5-gleich; Invariante „kein X-Context-Key an api.github.com" gepinnt.

Batterie: go test -short 65 ok (57 inhaltsadressiert gecacht, 8 frisch); go vet -tags=integration ok; golangci-lint 0 (frischer Cache glci-root-v5150); Integration -p 1 ./... 65 ok / 1 Paket-Timeout ctxcheckpoint (17:26–17:58Z, 32 min; das Paket lief isoliert auf demselben Stand 568,6 s PASS unter der 10-min-Grenze — vorbestehende Klasse wie v5.13.5 593 s / v5.13.6 586 s, RC-2b berührt 0 Dateien in distillsource); test.sh, eval.sh, Deploy-Parität und die Nadeln (prompt_id, cost_usd) laufen nach dem Deploy aus dem Tag-Worktree und stehen im Release-Log (LOOP.md).

Commits (root): T03-8 5cde8b5 · T03-2 b940ed5 · T03-12 ad7b44c · T03-10 7b30b9e · T04-20 f2f8e5e · T04-21 c1ce91e · T03-8b 777e24f · T03-11 5baefd5 · T03-13 f44c6ed · T03-9 890e4d4.

Installation

With Go:

go install github.com/GottZ/ctx/cmd/ctx@v5.15.0

Binary download:
Download the binary for your platform, make it executable, move to PATH:

chmod +x ctx-*
sudo mv ctx-* /usr/local/bin/ctx