mirror of https://github.com/razor-ai/soup.git
3 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
21a2bf8e8c |
feat(governance,energy): v0.71.3 — annex PDF, audit auto-log, energy hook, can v3, airgap receipt
Closes #180 #181 #182 #183 #184 #188. - #180 EnergyTracker (codecarbon offline) + `soup train --track-energy`; [carbon] extra - #181 PDF Annex XI/XII (reportlab) + paths.atomic_write_bytes; [pdf] extra - #182 Soup Can manifest v3 + attestations field + `can pack --attest` - #183 per-command audit-log auto-instrumentation (--no-audit-log / SOUP_NO_AUDIT_LOG) - #184 auto-populate Annex top_domains from the training JSONL - #188 embed repro-receipt into `soup airgap-bundle` New [pdf]+[carbon] extras (reportlab also in [dev]). +83 tests (12259 -> 12342), 79.10% coverage. Reviewed (security/code/python/tdd): security M1 raw-size gate on --attest before parse, python H1/H2 type hints, +22 negative tests. |
|
|
|
ff55e751ab |
fix(v0.33.0): review-wave findings (CRITICAL + HIGH + MEDIUM + LOW)
Addresses findings from 5-agent review wave (python-reviewer, code-reviewer, security-reviewer, tdd-guide, smoke-verification). CRITICAL: - cans/run.py _deploy_target ollama path: rglob *.gguf result is now realpath+commonpath checked against extract_dir before forwarding to `soup deploy ollama --gguf`. Prevents a crafted symlink in the can from making rglob point at an arbitrary on-disk path. HIGH: - cans/publish.py: removed dead update_repo_settings + bare-except tag block (was a no-op network round-trip). Tag attachment via README front-matter is documented as a v0.33.x docs follow-up. - registry/attach.py lookup_entry_by_output_dir: emits ResourceWarning when the 1000-row scan limit is hit (was a silent miss). - data/collators.py CrossDocCollator: stops mutating input dicts via pop() — uses get + dict comprehension. HF Dataset rows are cached and reused; mutation broke subsequent batches silently. Bare-except now logs at DEBUG level so production degradation is inspectable. - monitoring/callback.py _write_spike_recovery_hint: added is_under_cwd guard. args.output_dir came from raw HF TrainingArguments without separate path-containment check. - trainer/rewards.py MACOS_SANDBOX_PROFILE: narrowed (allow mach-lookup) to a 3-name allowlist (SecurityServer, notification_center, opendirectoryd.libinfo). Broad mach-lookup permitted DNS / NSURLSession via launchd, defeating (deny network*). - cans/run.py: PermissionError → ValueError so a caller wrapping in `except OSError` cannot silently swallow the consent gate. PermissionError is an OSError subclass. - commands/can.py run_cmd: assigns result=None up front + explicit None guard so a future _fail bypass cannot trigger NameError on result. - utils/v028_features.py: added type annotations on apply_v028_speed_memory (model: Any, tcfg: TrainingConfig via TYPE_CHECKING, console: Console) and warn_unsupported_features. - cans/run.py: confirm_callback now annotated Callable[[Manifest], bool] for IDE introspection. - tests/test_part_b.py reexec test: drops env-var contamination (RANK/WORLD_SIZE/LOCAL_RANK/ACCELERATE_*) before run, patches imported names on train module, and forces assertion that os.execvp was called — no more silent skip-on-bypass. - tests/test_part_d.py: added TestGenerateResponseSignature source-level guard that catches the lenient logits_processor mock silently passing. MEDIUM: - cans/run.py _run_subprocess: catches subprocess.TimeoutExpired and returns rc=124 (coreutils convention) so callers see a clean CanRunResult instead of an unhandled traceback after the 24h cap. - cans/run.py: temp dir created via mkdtemp is now cleaned up on extract_can failure (try/except + cleanup_extract_dir). - cans/run.py cleanup_extract_dir: switched startswith path check to os.path.commonpath (project-standard idiom; Windows-safe). - cans/schema.py DeployTarget._safe_relpath: normalises mixed separators before splitting on '/' so foo/..\bar can no longer bypass the .. check. - utils/lr_finder.py run_lr_sweep: removed redundant local `import math as _math` (math already at module level). LOW: - eval/gate.py _parse_judge_url: removed bare http:// catchall after scheme allowlist. Defence-in-depth for callers that bypass the Pydantic GateTask validator. - utils/auto_quant.py evaluate_candidate: latency mean now divides by *completed* prompts (excludes crashed). Crashed candidate no longer appears artificially fast. - utils/auto_quant.py Candidate.__post_init__: explicitly rejects bool in score / latency_ms (bool is a subclass of int, was sneaking past). - utils/mii.py: removed `noqa: F401` on Optional import (now actually used in type annotation since we restored it). Tests added (+7, total 3811→3818): - test_part_a_wave1: attach_artifact outside-cwd rejection. - test_part_a_wave2: PermissionError→ValueError migration in 2 tests. - test_part_c: CrossDocCollator mismatched doc_lengths fallback, does-not-mutate-input-dict regression guard. - test_part_d: source-level _generate_response signature guard. - test_part_e: should_recover at max_attempts, outside-cwd skip. Lint: clean. Full suite: 3818 passed in 156s. Findings deliberately not actioned (with rationale): - code-review M1 (mii Pydantic at import-time): forward-ref resolution requires module-level definitions for FastAPI; documented in mii.py. - code-review M4 (supports_v028_features vs validator divergence): the v0.33.0 schema validator was renamed to _validate_v028_speed_memory_supported_tasks and now imports supports_v028_features — they cannot drift. - python-review LOW (_deploy_target vllm silent no-op): documented in the docstring as advisory; logging requires a console arg the helper does not currently take. - security-review LOW 8/9 (TOCTOU window, CLONE_NEWPID): theoretical; documented in CLAUDE.md security section in the next commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|
|
|
8f2bc56334 |
feat(cans): soup can run + publish (v0.33.0 Part A wave 2)
Closes #34. Completes Part A — all of #32, #34, #35 now shipped. Schema bump: CAN_FORMAT_VERSION 1 -> 2 (additive). - SUPPORTED_CAN_FORMAT_VERSIONS = (1, 2): old cans still inspect/extract. - New DeployTarget Pydantic model with kind in {ollama, gguf, vllm}, name validation (no null bytes / newlines), path validation (relative-only, rejects '..' and absolute paths). - Manifest gains optional deploy_targets: list[DeployTarget] field. cans/run.py — orchestrator: - run_can(can_path, yes, deploy, extract_dir, capture_env_to, ...) validates path containment, requires --yes or explicit confirm_callback (security: auto-downloads data + auto-trains), extracts, optionally captures env, then invokes `soup train --config ... --yes` via subprocess so the trainer dispatch stays a single source of truth. - capture_env: best-effort pip freeze + python version + GPU detection, never blocks training on env-capture failure. - _deploy_target dispatches per-kind; ollama path runs `soup deploy ollama --gguf ... --name ...` if a *.gguf is present in the can. - cleanup_extract_dir: tmp-or-cwd-only safety guard around shutil.rmtree. cans/publish.py — HF Hub publish: - publish_can(can_path, repo_id, token, private, commit_message) validates can-path containment, repo_id via utils/hf.validate_repo_id, resolves token via utils/hf.resolve_token (env > cache files), uploads to repo_type='dataset' with commit-message first-line + 200-char cap (matches v0.29.0 push.py / data push policy). Tags as can-format-v1. CLI: soup_cli/commands/can.py - New `soup can run <path> [--yes] [--deploy] [--extract-dir] [--env-capture]` — confirmation panel mandatory without --yes. - New `soup can publish <path> --hf-hub <user/repo> [--private] [--message]`. Tests: +28 in tests/test_part_a_wave2.py covering schema bump (v1/v2/v3), DeployTarget validation (path traversal, null bytes, kind enum), capture_env (smoke + pip-failure tolerance), run_can (containment + confirmation gate + train-argv shape via mocked subprocess), publish_can (repo_id validation, token resolution, commit-message sanitization, HF upload via mocked HfApi), and CLI smoke (confirmation panel, missing file). One existing test_cans test relaxed (v1 == v1 -> v in {1,2}). Known follow-ups (not blocking release): - soup can run does NOT yet auto-fetch data_ref.kind=hf|url. Embedded config must reference a local data path. Filed mentally as v0.33.x follow-up. - registry_snapshot.json lineage export deferred — pack already embeds base_hash which is enough to query the source registry post-extract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |