Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when a change trains a model, reports a metric, or touches seeds, data or model versions, the lockfile, MLflow or DVC — what every run must log, seeding, environment pinning, data versioning and keeping tests off the shared tracking server
インストールする前に、エージェントに与えられる指示の中身を確認できます。
A metric nobody can reproduce is an anecdote. Reproducing a run needs five things: the code (git SHA), the data (a version or hash), the parameters, the environment (lockfile) and the seed. Log all five with every run, and make the training entrypoint a deterministic function of them.
Core principle: if two runs with the same five inputs can produce different models, the difference must be explainable (GPU non-determinism, thread scheduling) and bounded — never "randomness" from an unseeded call.
| Item | How |
|---|---|
| Code | git SHA and a dirty flag |
| Data | DVC hash from dvc.lock, a snapshot date plus query, or a content hash of the training frame |
| Parameters | the full resolved config, including defaults |
| Environment | hash of the lockfile (uv.lock, poetry.lock), Python version, key library versions |
| Seed | the one seed the run derived everything from |
| Metrics | mean and spread across folds, the baseline's score, the test score once (rule test-set-discipline) |
| Artifact | the fitted pipeline in a safe format (rule safe-model-serialization), with an input example |
def data_fingerprint(df: pd.DataFrame) -> str:
return hashlib.sha256(pd.util.hash_pandas_object(df, index=True).to_numpy().tobytes()).hexdigest()[:16]
def code_and_env() -> dict[str, str]:
sha = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True, text=True, check=True).stdout.strip()
dirty = bool(subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=True).stdout)
lock = hashlib.sha256(Path("uv.lock").read_bytes()).hexdigest()[:16]
return {"git_sha": sha, "git_dirty": str(dirty), "lock_sha": lock, "python": platform.python_version()}
with mlflow.start_run(run_name=f"churn-{cfg.seed}"):
mlflow.log_params(cfg.model_dump())
mlflow.set_tags({**code_and_env(), "data_fingerprint": data_fingerprint(train_df), "seed": str(cfg.seed)})
mlflow.log_input(mlflow.data.from_pandas(train_df, name="train", targets="churned"), context="training")
cv = cross_validate(pipe, X_train, y_train, cv=splitter, scoring="average_precision")
mlflow.log_metrics({
"cv_ap_mean": cv["test_score"].mean(),
"cv_ap_std": cv["test_score"].std(),
"baseline_ap": y_train.mean(),
})
pipe.fit(X_train, y_train)
info = mlflow.sklearn.log_model(
sk_model=pipe,
name="model",
input_example=X_train.head(5),
skops_trusted_types=REVIEWED_SKLEARN_TYPES,
)
LoggedModels: log_model(..., name=...) replaces the 2.x artifact_path= argument, and info.model_uri points at the logged model.champion, challenger) and load models:/churn@champion; registry stages are deprecated.REVIEWED_SKLEARN_TYPES names only the types you checked (a HistGradientBoosting* model needs its TreePredictor), never everything get_untrusted_types() reports. Older pins and Databricks use cloudpickle — load those only from the repository's own tracking server or registry (rule safe-model-serialization).@pytest.fixture(autouse=True)
def local_mlflow(tmp_path, monkeypatch):
monkeypatch.setenv("MLFLOW_TRACKING_URI", f"sqlite:///{tmp_path / 'mlflow.db'}")
A test asserts what the run logged (params, the metric keys, the data fingerprint tag) by reading it back from this local store. Your own end-to-end exercise of the pipeline logs to /tmp/tt-<task key>/ the same way.
# ❌ global, legacy, invisible
np.random.seed(42)
idx = np.random.permutation(n)
# ✅ one generator, passed down; integer seeds for estimators and splitters
rng = np.random.default_rng(cfg.seed)
idx = rng.permutation(n)
splitter = StratifiedKFold(n_splits=5, shuffle=True, random_state=cfg.seed)
model = HistGradientBoostingClassifier(random_state=cfg.seed)
random.seed(cfg.seed) too if any dependency uses it.seed=, plus deterministic=True and a fixed num_threads when bit-identical results matter. XGBoost: random_state=.uv sync --locked (or the repo's equivalent) builds it. Never pip install something ad hoc to get a run to work.stages:
features:
cmd: uv run python -m churn.pipelines.features --out data/features.parquet
deps:
- src/churn/features
- data/raw/events.parquet
outs:
- data/features.parquet
train:
cmd: uv run python -m churn.pipelines.train --features data/features.parquet --out models/
deps:
- src/churn/models
- data/features.parquet
params:
- train.seed
- train.learning_rate
outs:
- models/model.skops
metrics:
- reports/metrics.json:
cache: false
dvc repro re-runs only stages whose deps or params changed; dvc.lock records the hashes — commit it.dvc exp run -S train.learning_rate=0.05 and dvc exp show compare runs; dvc metrics diff compares against the default branch.dvc pull/dvc push need remote credentials. If the workspace has none, say so and run the stage on the fixture instead; never commit the data to git to work around it.Each stage writes its full output to a deterministic location for its inputs (features/date=2026-10-01/) and overwrites it on re-run; appending to a shared file makes a retry double the data (data-pipeline-orchestration).
random_state on the model but not on the splitter.np.random.seed or random.random() in library code.uv.lock changed in a diff with no dependency change in pyproject.toml.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。