bool() wraps the operate_rate predicate in eval.py and resident.py so the sum counts cleanly-operated trajectories without summing None; mypy strict clean across the whole package (5 files); 6 tests pass.
sum(t.steps > 0 and t.meta.get("clean") for t in rows) yields the right operand
of `and` when steps>0, so a trajectory whose meta lacks the "clean" key
contributes None and sum() raises TypeError. Wrap the predicate in bool() so it
counts trajectories that operated and are clean. Surfaced by mypy once posix-sdc
began shipping py.typed (Trajectory is now typed).
operate_rate in eval.py and resident.py wraps the steps>0 and meta.get('clean') predicate in bool() so the sum counts cleanly-operated trajectories without summing None; mypy strict clean across the whole package (5 files); tests pass.
sekft-train logs run config and each phase (tokenizer/model load, build, training, save) via a sekft.train logger to stderr; -v/--verbose and -q/--quiet added; dataset accounting reports keepers->usable with over-length/empty-mask drop counts and a warning; build loop logs per-trajectory (debug) and every 100 (info); transformers verbosity raised so the per-step curve shows; inspect() logs likewise; 6 tests pass; mypy strict clean on sft.py + _log.py (verified loop logging fires with FakeTok). No submodule changes.
The trainer was nearly silent: outside an example count and a save line it
printed nothing through tokenizer load, the base-model load, example building, or
the training loop, and trajectories dropped for length or empty mask vanished
without a trace.
Add _log.py (a shared stderr logging setup so stdout stays clean for results)
and a module logger. sekft-train gains -v/--verbose and -q/--quiet. Log the run
config and each phase; report dataset accounting (keepers -> usable, with counts
dropped for over-length and empty-mask and a warning when any are dropped);
inside the build loop, a per-trajectory debug line and a progress line every 100;
raise transformers' verbosity during training so the per-step curve shows. Prints
in train() and inspect() are routed through the logger.
sekft-train logs run config and each phase (tokenizer load, model load, training, save) via a module logger to stderr; -v/--verbose and -q/--quiet control level; dataset accounting reports keepers->usable with counts dropped for length and empty-mask and warns when any are dropped; transformers verbosity raised so the per-step curve shows during training; inspect() logs likewise; existing sft tests stay green; mypy strict clean.
mypy --strict src tests passes (no issues, 6 files); ML/posix-sdc imports ignored via overrides; sft/eval/resident/tests fully annotated; mypy is a declared dev dep; py.typed ships in the package.
README describes the trainer/eval/resident, the posix-sdc dependency, install via the gpu extra, the chat-template render contract, and console-script usage; module docstrings reference sekft-train/eval/resident and apply_chat_template, not the old flat scripts.
tests/unit and tests/smoke pass under pytest; the mask test proves assistant-only training and raises on non-additive templates; entry-point smoke tests pass without torch.
Resident loads the base once; fit trains an adapter and unloads it; evaluate attaches an adapter (or the base baseline) and renders via the shared chat-template canonicalisation.
eval reuses the posix-sdc rollout with a local operator; renders via apply_chat_template + normalize_for_template; reports command-mode, terminate, and verified rates over held-out scenarios.