From 0034628b03105861ec130654ffaa2e4938e5948a Mon Sep 17 00:00:00 2001 From: Alpamys Date: Mon, 20 Apr 2026 22:05:47 +0500 Subject: [PATCH] docs: drop internal Part A/B/C/D/E labels from public docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Part A/B/C/D/E" is our internal decomposition (tracked in .claude/plan.md and referenced in commit messages + GitHub issues). It leaked into user-facing docs during v0.26.0 release prep. Users don't care about our internal breakdown — they care about features and versions. Cleanup: - README.md: "New in v0.26.0" bullets now describe features by name only, (vX.Y.Z) version tags retained where present - SECURITY.md: v0.26.0 hardening entries grouped by feature name, not Part - CONTRIBUTING.md: module tree annotations use (v0.26.0) not (v0.26.0 Part X) .claude/CLAUDE.md: added explicit rule under Release Checklist terminology stating that Part X labels are internal-only and must NOT appear in public docs. Prevents the same mistake next release. .claude/plan.md + commit messages continue to use Part X — that's the correct venue for internal dev decomposition. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/CLAUDE.md | 1 + CONTRIBUTING.md | 6 +++--- README.md | 10 +++++----- SECURITY.md | 10 +++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 45cba1e..3f128e0 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -440,6 +440,7 @@ soup version # Show version (--full for details) - **"Phase"** = a single version release (e.g. v0.26.0). NOT individual sub-Parts (A/B/C/D/E). - **"Part"** = a chunk of work within a phase (e.g. v0.26.0 Part A = Model Registry). Parts are an internal decomposition for TDD + review efficiency, not for separate releases. - **One release per phase.** All Parts ship together under a single tag. Bumping version before all Parts land is fine; tagging is ONE time per phase. +- **"Part A/B/C/D/E" is internal-only terminology** — it belongs in `.claude/plan.md`, `.claude/CLAUDE.md`, commit messages, and GitHub issues. It **must NOT** appear in user-facing docs: `README.md`, `SECURITY.md`, `CONTRIBUTING.md`, `examples/README.md`, release notes. Users care about features and versions, not our internal breakdown. In public docs, describe each feature by its user-facing name only (e.g. "Local Model Registry"), with an optional `(vX.Y.Z)` tag to show when it shipped. **Multi-part phases (A, B, C…):** implement part by part. Write tests FIRST (TDD), then implement to pass them. Run `ruff check soup_cli/ tests/` + `pytest tests/ -v --tb=short` after each part to catch issues early. Commits CAN be split per Part (for bisect clarity) but the release / tag / PyPI publish happens ONCE after all Parts pass the full checklist. Only proceed to the Release Checklist below after ALL parts pass lint + tests. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 18da3a3..704e263 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,9 +103,9 @@ soup_cli/ migrate/ - Config migration (LLaMA-Factory, Axolotl, Unsloth) recipes/ - Ready-made configs for popular models (43 recipes) autopilot/ - Zero-config decision engine (v0.25.0) - registry/ - Model Registry (hashing, store, diff) (v0.26.0 Part A) - cans/ - Shareable .can artifact format (v0.26.0 Part E) - data/traces/ - Trace-to-Preference harvester (v0.26.0 Part C) + registry/ - Model Registry (hashing, store, diff) (v0.26.0) + cans/ - Shareable .can artifact format (v0.26.0) + data/traces/ - Trace-to-Preference harvester (v0.26.0) utils/ - GPU, errors, MoE, GaLore, QAT, Unsloth, vLLM, SGLang, Liger, FlashAttn, FSDP, Ring Attention, long-context, quality, curriculum, freeze, dataset-registry, mlx, peft_builder, paths ui/ - Web UI (FastAPI + HTML/JS SPA) diff --git a/README.md b/README.md index 632f10b..d8f450d 100644 --- a/README.md +++ b/README.md @@ -40,11 +40,11 @@ soup train The flywheel: **Train -> Registry -> Deploy -> Observe -> Improve -> Train**. -- **Local Model Registry** (Part A) — `soup registry push/list/show/diff/search/promote/delete`: track every fine-tune with lineage, config, and eval baseline. `soup history ` renders the full DAG. Backing store: `~/.soup/registry.db`. -- **Eval-Gated Training** (Part B) — `training.eval_gate` (or `soup train --gate evals/gate.yaml`) runs a declarative suite at epoch boundaries and halts training on regression. `soup eval gate` for post-hoc verdicts. Baselines may be `registry://`, a file, or omitted. -- **Trace-to-Preference** (Part C) — `soup data from-traces` ingests LangChain / OpenAI / Soup-serve logs, builds DPO/KTO-ready preference pairs from thumbs, regenerations, or user edits. `soup data review` previews pairs before training. -- **Quant-Lobotomy Checker** (Part D) — `soup eval quant-check --before X --after Y --tasks t.jsonl` renders an OK / MINOR / MAJOR verdict per task so you never ship a quantization regression unknowingly. -- **Soup Cans** (Part E) — `.can` = tar.gz of manifest + config + data_ref. `soup can pack/inspect/verify/fork` makes recipes shareable + reproducible; safe tar extraction blocks symlink / path-traversal escape; 100 MB cap; format version locked to 1. +- **Local Model Registry** — `soup registry push/list/show/diff/search/promote/delete`: track every fine-tune with lineage, config, and eval baseline. `soup history ` renders the full DAG. Backing store: `~/.soup/registry.db`. +- **Eval-Gated Training** — `training.eval_gate` (or `soup train --gate evals/gate.yaml`) runs a declarative suite at epoch boundaries and halts training on regression. `soup eval gate` for post-hoc verdicts. Baselines may be `registry://`, a file, or omitted. +- **Trace-to-Preference** — `soup data from-traces` ingests LangChain / OpenAI / Soup-serve logs, builds DPO/KTO-ready preference pairs from thumbs, regenerations, or user edits. `soup data review` previews pairs before training. +- **Quant-Lobotomy Checker** — `soup eval quant-check --before X --after Y --tasks t.jsonl` renders an OK / MINOR / MAJOR verdict per task so you never ship a quantization regression unknowingly. +- **Soup Cans** — `.can` = tar.gz of manifest + config + data_ref. `soup can pack/inspect/verify/fork` makes recipes shareable + reproducible; safe tar extraction blocks symlink / path-traversal escape; 100 MB cap; format version locked to 1. - **Security-hardened**: name/tag validation; SQL LIKE-wildcard escaping; Windows-safe path containment via shared `os.path.realpath + commonpath`; SSRF allowlist on judge URLs; HTTPS-only `DataRef`; dunder-key / null-byte rejection in can-fork; cycle detection in lineage walks; structured-error-as-regression policy in eval gate. ### New in v0.25.0 — "Beyond the Wrapper" diff --git a/SECURITY.md b/SECURITY.md index 167ff39..24044ce 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -130,11 +130,11 @@ No known critical vulnerabilities in current releases. - **v0.24.1**: AWQ/GPTQ output path traversal validation moved before import check (previously unreachable when autoawq/auto-gptq not installed), Windows Unicode fix for Rich console output (replaced non-ASCII symbols with ASCII equivalents) - **v0.24.2**: Chat proxy SSRF protection (localhost-only HTTP, HTTPS for remote), chat proxy max_tokens capped at 16384 + temperature/top_p bounded, chat proxy Bearer token auth required, XSS prevention (HTML-escape before markdown render), runs compare max 5 runs, config from-form validates via load_config_from_string, SSE read endpoints no auth (GET) - **v0.25.0**: Tool-calling JSON-only parsing (no eval), RLVR math_verify regex-extracted numerics (no eval), code_exec 5s timeout + 512MB RLIMIT on POSIX + ephemeral cwd + socket patch + `python -I -S` + 10KB output cap, verifiable_domain Literal constraint, LoRA PEFT mutual exclusion (DoRA/VeRA/OLoRA), data augment path containment + caps, forgetting_detection bounds, checkpoint_intelligence bounds + symlink refusal, autopilot path containment (realpath + commonpath) + goal Literal + GPU/time budget bounds, MLX trainers no trust_remote_code -- **v0.26.0 Part A — Registry**: name/tag validation (alphanumeric + `_-.` only, null-byte rejected, name ≤128 / tag ≤64 chars), artifact path containment (default `enforce_cwd=True` via `os.path.realpath + commonpath`, stored path is realpath), SQL LIKE wildcard escaping (`%` and `_` escaped with `ESCAPE '\\'` in `search()` and prefix `resolve()`), DB 600 perms on POSIX, lineage indirect-cycle detection (BFS ancestor walk before insert), CLI Rich markup escaped everywhere, `resolve()` raises `AmbiguousRefError` on ambiguous prefix (no silent None) -- **v0.26.0 Part B — Eval Gate**: suite path via shared `utils/paths.is_under_cwd` containment, `regression_threshold` [0.0, 1.0], `every_n_epochs` [1, 100], `on_regression` Literal ("stop"/"warn"/"continue"), `GateTask.tasks`/`prompts` null-byte rejection, `judge_model` URL scheme allowlist (`ollama://`, `https://`, `http://localhost`/`http://127.0.0.1`) — SSRF hardening, callback fails-safe: structured errors treated as regressions under `on_regression="stop"` -- **v0.26.0 Part C — Trace-to-Preference**: input/output path containment via shared `is_under_cwd`, trace line cap 100,000, `--format`/`--signal` Literal validation, PII warning panel before every run, JSON-only parsing (no eval), malformed JSON lines skipped silently -- **v0.26.0 Part D — Quant-Lobotomy**: `--before`/`--after`/`--tasks` all containment-checked, `registry://` refs support optional `kinds` filter to avoid picking the wrong artifact, format Literal validated -- **v0.26.0 Part E — Soup Cans**: Manifest format version pinned to 1; name alphanumeric+`_-.`; author max 128 chars, no null bytes/newlines; created_at must parse via `datetime.fromisoformat`; description max 4096; DataRef URL HTTPS-only; hf_dataset regex-validated; tar extraction uses `filter="data"` on Python 3.12+, fallback only on `TypeError`/`AttributeError` (not `TarError`); manual symlink/hardlink rejection + `commonpath` check; 100 MB size cap on pack + fork; dunder-key (`__*__`) and null-byte rejection in fork modifications to prevent prototype pollution; inspect/read_config refuse paths outside cwd +- **v0.26.0 — Registry**: name/tag validation (alphanumeric + `_-.` only, null-byte rejected, name ≤128 / tag ≤64 chars), artifact path containment (default `enforce_cwd=True` via `os.path.realpath + commonpath`, stored path is realpath), SQL LIKE wildcard escaping (`%` and `_` escaped with `ESCAPE '\\'` in `search()` and prefix `resolve()`), DB 600 perms on POSIX, lineage indirect-cycle detection (BFS ancestor walk before insert), CLI Rich markup escaped everywhere, `resolve()` raises `AmbiguousRefError` on ambiguous prefix (no silent None) +- **v0.26.0 — Eval Gate**: suite path via shared `utils/paths.is_under_cwd` containment, `regression_threshold` [0.0, 1.0], `every_n_epochs` [1, 100], `on_regression` Literal ("stop"/"warn"/"continue"), `GateTask.tasks`/`prompts` null-byte rejection, `judge_model` URL scheme allowlist (`ollama://`, `https://`, `http://localhost`/`http://127.0.0.1`) — SSRF hardening, callback fails-safe: structured errors treated as regressions under `on_regression="stop"` +- **v0.26.0 — Trace-to-Preference**: input/output path containment via shared `is_under_cwd`, trace line cap 100,000, `--format`/`--signal` Literal validation, PII warning panel before every run, JSON-only parsing (no eval), malformed JSON lines skipped silently +- **v0.26.0 — Quant-Lobotomy**: `--before`/`--after`/`--tasks` all containment-checked, `registry://` refs support optional `kinds` filter to avoid picking the wrong artifact, format Literal validated +- **v0.26.0 — Soup Cans**: Manifest format version pinned to 1; name alphanumeric+`_-.`; author max 128 chars, no null bytes/newlines; created_at must parse via `datetime.fromisoformat`; description max 4096; DataRef URL HTTPS-only; hf_dataset regex-validated; tar extraction uses `filter="data"` on Python 3.12+, fallback only on `TypeError`/`AttributeError` (not `TarError`); manual symlink/hardlink rejection + `commonpath` check; 100 MB size cap on pack + fork; dunder-key (`__*__`) and null-byte rejection in fork modifications to prevent prototype pollution; inspect/read_config refuse paths outside cwd ## Security Scanning