ctx v5.16.0
v5.16.0 — Tree-Shaking RC-2c: Phase E + F — Tripwires, Retirement-Vintage 2 mit Migration 152, Compose-Oberfläche, parent.mode-Gate
Minor-Release MIT Migration (Schema 151 → 152; 152 ist ein idempotentes DELETE ohne Schema-Änderung). 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; 5 Auflagen in 10 Wellen (drei Code-Funde vor der Landung behoben: Windows-Pfad in T06-7, FuncLit-Fail-open in T06-7b, retirierter Name im generierten Compose-Block in T05-5), 0 NICHT MERGEBAR. Die beabsichtigten Verhaltensänderungen sind unten vollständig benannt und gepinnt; der Rest ist byte-gleich belegt oder reines Gate-Set.
Verhaltensänderungen:
(1) T02-11 — parent.mode=required hat jetzt einen Mechanismus (E02-4 = A): ein viertes Tor in der Claim-Kette (handler/stage_gates.go parentRequiredReject) weist einen Schreibvorgang ohne Parent auf einem Typ mit parent.mode=required auf allen drei Schreib-Armen (REST /api/store, MCP-direct, MCP-staged) und im manage-update-Pfad mit 422 parent_required ab. Ist-Sweep vor dem Bau (context_block_types, alle Scopes): genau 1 Zeile _global|comment|builtin, 0 Nicht-Builtin-Typen ⇒ kein bestehender Tenant-Typ betroffen. Zusatzbefund: der Builtin-Typ comment war über /api/store claimbar (nicht write.internal_only) und erzeugte Blöcke ohne Parent — dieser Pfad ist jetzt geschlossen; Live-Sweep 05.09.: 0 comment-Blöcke in context_blocks. Der Issue-/Comment-Pfad (store.InsertCommentBlock) bleibt byte-identisch, store: comment requires a parent issue bleibt seine erste Refusal. Rollout-Hinweis + Sweep-SQL in docs/api.md.
(2) T05-8a + T05-8c — zwei Registry-Keys ohne Nachfolger fallen (Retirement-Vintage 2, E01-8 = A / E05-D1 = B): distill.local_only (der Distill-Aufruf ist fest LocalOnly=true — der Key hat ihn nie gesenkt) und root_map.label_budget (kein Leser, rootmap importiert kein llm). Tombstone statt Schweigen: ein gesetztes CTX_DISTILL_LOCAL_ONLY / CTX_ROOT_MAP_LABEL_BUDGET (≠ Scaffold-Wert "0") loggt beim Boot genau eine retired_env_v2-Zeile, eine context_settings-Zeile auf einem der Keys genau eine retired_settings_row_v2-WARN mit ausführbarem DELETE; GET /api/settings führt die Keys nicht mehr (Registry 231 → 229 Keys, per config.Keys() auf v5.15.0 und auf dem Tag-Stand gemessen). V1 (29 Namen, v5.0.0) bleibt byte-gleich getrennt.
(3) T05-10 — Migration 152 (152_retire_v2_settings.sql): ein idempotentes DELETE der context_settings-Zeilen auf genau diesen zwei Keys in allen Scopes, Audit-Rows per request_id = 'migration-152-retire-v2-settings', NOTICE nur bei > 0 gelöschten Zeilen; Set-Gleichheit ARRAY ↔ config.RetiredV2KeyNames() gepinnt. Live-Row-Sweep vor dem Deploy: 0 Zeilen (diese Instanz löscht nichts). Integrationstest (DB auf 151 gecappt): 6 V2-Zeilen über drei Scopes gelöscht, lebender Key bleibt, 6 Audit-Rows, zweiter Lauf 0, leere Menge 0; Manifest migration_max 152 / migration_count 40.
(4) T05-5 — docker-compose.yml deklariert jeden Registry-Env-Namen als ${NAME:-} und wiederholt keinen Registry-Default (E05-D5 = A): Block 105 → 227 Zuweisungen bei der Landung (217 Registry + 10 env-only; am Tag-Stand 226, weil T05-8c CTX_ROOT_MAP_LABEL_BUDGET wieder entfernt), 122 bisher unerreichbare Knöpfe erreichbar, 84 Default-Kopien fallen, die vier bewussten Abweichungen (CTX_RERANK_BLEND_WEIGHT=0.5, CTX_GRAPH_EXPAND_ENABLED=true, CTX_GRAPH_OVERVIEW_ENGINE=ctx, CTX_READ_SCOPES=private,shared) und die sechs CONTEXT_DB*/LISTEN_ADDR-Zeilen byte-gleich. Äquivalenz belegt: ein leerer Env-Wert ist für den Loader „nicht gesetzt" (config/load.go), kein strict-Key sieht ihn; DB-Overrides gewinnen vorher wie nachher. Sichtbare Folge: der Boot-Dump zeigt für die 84 Keys die Quelle default statt env, effektive Werte identisch. Gates TestComposeDeclaresEveryRegistryKey / TestComposeCopiesNoRegistryDefault; Generator + Vorlage im Plan-Korpus. DEPLOY: der Compose-Config-Hash ändert sich, up -d recreated den ctx-Container einmal.
Tripwires (Gate-Set, kein Produktverhalten; Phase E):
T02-7 — deadcode.sh + go/deadcode-allow.txt (heute genau 1 Zeile mit Grund: schemacontract.MarshalManifest, genmanifest-Blindstelle) blockierend in beiden Richtungen (neu tot / lebt wieder), unused im golangci-lint-Enable-Set (+0,3 s), nicht-blockierender dupl-Report; CI-Job lint + .hooks/pre-push; drei //nolint:unused-Zeilen mit Grund in overview/label.go (Leser in integration-getaggten Tests).
T02-13 — zweite Ratsche deadcode.sh testonly gegen go/deadcode-testonly-allow.txt: 183 Prod-Symbole, deren einzige Nutzer Tests sind, jede Zeile mit Grund (76 warten auf E01-2, 44 auf E01-1, 9 testdb, 2 K24, 2 E02-3, 49 Einzelgrund, 1 FUND llm.TemporalToEmbedPrefix); gemessene Grenze: deadcode meldet nur Funktionen/Methoden, test-only Vars/Konstanten/Typen fasst kein Werkzeug. Default-Modus byte-gleich; pre-push Gate 3 fährt beide Modi (≈ 12 s).
T06-7 — drei Zäune: Env-Namen-Budget über alle cmd/ctx-* (2. Aufruf des K10-Scanners, Muster parametrisiert; 9 Literale = 5 Registry + 4 begründet), depguard-Regel evalscore-tooling-only, Bench*-Naht (22 Shims, 25 Aufrufe alle in goldbench). Windows-Pfad-Falle (filepath.Dir auf slash-normiertem Pfad) vom Prüfer gefunden, vor der Landung behoben.
T06-7b — vierter Zaun: DB-direkte Werkzeuge öffnen READ ONLY (pgxdb.Read); 13 tool-only Pakete, 16 rohe Handle-Aufrufe, alle namentlich mit Grund, genau einer schreibend (distillreset/reset.go:278, Schreibvertrag E4-5); Fail-open bei Funktionsliteralen in Paket-Variablen vom Prüfer gefunden, vor der Landung geschlossen; Method-Value bleibt dokumentierte Grenze.
T02-12 — store.HashNOOPCheck (Dedup-Chokepoint dreier Schreibflächen) hat jetzt einen Integrationstest (5 Fälle über den Produktions-Schreibpfad, 7 Mutationen je genau ein Subtest rot); der letzte Placebo-Test fällt.
Batterie: go test -short -count=1 66 ok; go vet -tags=integration ok; golangci-lint 0 (frischer Cache glci-root-v5160, Existenz-Check vor dem Lauf); Integration -p 1 -count=1 ./... 67 ok / 0 FAIL / 0 Timeout (21:42–22:14Z, 32 min, detached; ctxcheckpoint 587,4 s PASS innerhalb des Laufs — kein Paket-Timeout, weil diesmal keine Parallel-Last lag); Pre-Push-Sweeps: Migrationen 1 (= 152), 13 Commits Author=Committer git@gottz.de, Live-Row-Sweep für Migration 152 = 0 Zeilen; test.sh, eval.sh, Deploy-Parität und die Nadeln (_migrations 152, Retired-V2-Log, Boot-Quellen env→default, settings list) laufen nach dem Deploy aus dem Tag-Worktree und stehen im Release-Log (LOOP.md).
Commits (root): T02-12 94231f9 · T02-11 c4a4c52 · T06-7 8df4ecf · T05-8a 2eae98e · T06-7b 5841d2a · T02-7 ba46c38 · T05-5 d30e5fa · T05-8c 14d0741 (+ T05-5-Nachzug 05e8b70) · T02-13 4295ec7 · T05-10 033b54a.
Installation
With Go:
go install github.com/GottZ/ctx/cmd/ctx@v5.16.0Binary download:
Download the binary for your platform, make it executable, move to PATH:
chmod +x ctx-*
sudo mv ctx-* /usr/local/bin/ctx