This meta skill owns selection and ordering, not child methodology.
Do not load smoke-test-ml-pipeline as a sibling of evaluate.
Human-facing prose
Details: setup-workspace references/human_facing_prose.md.
Design notes, JOURNAL text, and # comments describe this
experiment — not the skills framework, the CLI, or the command that
produced an output. Questions, replies, and the close narrative
use the same data-science language — not skill ids, G-* names,
or the wrapper CLI. Trailing locator tokens stay index strings.
<!-- results-embed: … --> is a site marker. Authoring hints
stay in this skill. style is ruff only.
Design note shell
python -m skore_skills scaffold --journal --stem <NN_short> writes
journal/<stem>.md. Do not recreate it from memory. Fill Question,
Motivation, Method, and Risks as science (what to learn, why now,
what changes, what could invalidate the result). Status lifecycle:
planned → approved → running → done | abandoned. Those
four content sections freeze after approval; only Status, generated
notebook viewers, and the Method <!-- results-embed: pipeline -->
embed change afterwards. Abandoned: one-line reason on State;
Headline result n/a — abandoned: <reason>. There is no "Success
criteria" section. Keep ## Notebooks with Evaluation then Audit.
Entry routing — deterministic
-
Run
python -m skore_skills status. Ifstatus.setup.pendingis non-empty andstatus.skills.setup-ml-projectis true, loadsetup-ml-projectand stop. Do not start this skill. When it returns, continue. Do not load it again on this turn. If that skill is not installed, name the pending pieces in one line and stop. Do not inventgit init, scaffold, orenv init. Ifstatus.setup.envorstatus.setup.workspaceisdeclined, stop in one line. A declinedgitoreditableis not asked again and does not block modeling. -
Framing is mandatory. If
status.modeling_decisionsis notlocked, loadframe-ml-problemonly ifstatus.skills.frame-ml-problemis true and stop. Do not invent the table, offer model choices, write a design note, or declare a pipeline. Missing skill → stop in one line. This includes an approved-stem resume: do not build until the table is locked. When the table islocked, runpython -m skore_skills frame show. Anything other thanproceedloadsframe-ml-problemand stops. Aproceedwhosetranslationis null has no splitter translation: say so and stop. Do not write model code. Do not present a choice list: no dummy predictor, standard baseline, EDA-driven proposal, Backlog row, or discussion. -
Resume beats menu. If the user names an experiment stem, or
status.policy.loop.stem/last_history_stemidentifies a current design, runpython -m skore_skills design consent --stem <stem>. Treat JSONactionas authoritative.proceed→ resume that stem directly; do not ask how to start again.ask→ Design approval below (render JSONcontextinline per § Gate context); do not write code.stop→ missing note: namescaffold --journal --stem(or abandoned: explain and do not implement). Do not infer approval from "build it". Missing shell: nosite build, no fill from memory. -
Otherwise run
python -m skore_skills model choices. Treat its JSON as authoritative.actionstop/modeling_decisions_unlocked— loadframe-ml-problemand stop. Do not offer a model menu.- If
choicesincludesbaselineand the user did not ask to discuss, propose a pipeline from the EDA, or pick a backlog item, do not AskUserQuestion. Take the locked-baseline contract below. On this turn, run that contract in order —python -m skore_skills status,python -m skore_skills model choices,python -m skore_skills scaffold --journal --stem <NN_short>, then fill the note — before any design-note prose or question. The only gate after the note is the three lines in the locked-baseline contract, not Yes / No. - An explicit discuss, EDA, or backlog request takes that
branch even when
baselineis present. Do not show the menu first. - Otherwise present exactly
choices[], in returned order, in one single-choice AskUserQuestion. Dropbaselinefrom that question: it is not a menu item.eda_proposal→ Propose a pipeline from the EDAbacklog→ Pick from the Backlogdiscuss→ Discuss the next step
Carry each choice's JSON
reasonas its description so the user reads why it is on offer. Choosing backlog asks which row, not whether to build it.
Do not add a disabled choice, infer availability yourself, or
reorder the list. In particular: no locked-baseline choice when
model_stems is non-empty; no EDA proposal unless
data_analysis is present; no Backlog option when backlog is
empty. Discussion is present only after the lock.
Gate context
Every approval question carries its own context. Before asking,
state in 2–4 lines what the answer authorizes, the facts it rests
on — echoed inline — and what each option does, in data-science
terms (Approve / Modify / Stop; dummy vs baseline). On the
locked-baseline branch, those lines name the baseline and its
note only, and the options are the three lines in that contract.
Do not name
skill ids or G-* tokens in the question. A file link is an
addition, never the context: "read journal/<stem>.md and
approve" is not an approval request.
On design consent ask, the JSON context holds those facts:
question, source, files_touched, change, and up to two
risks. Quote them in the message (question and planned change
first, then the risks the user may push back on). After the note
is populated, and before Approve / Modify / Stop, run
python -m skore_skills site build --if-stale when site policy
is true. In that same question, say the website has been
updated and paste the file:// line from that output
verbatim. Do not name the
design-note markdown or html/<stem>.html. An empty
field means the note does not state that fact: say
the note is not ready for approval and offer to populate it;
never fill it from memory. Do not site build an empty shell.
Choice contracts
An EDA proposal or a discussion first produces a user-confirmed
proposal and an approved design note. The proposal yes agrees
that idea. A locked baseline and a backlog row do not: the frame
table or the picked row is the decision. The note is approved
only by Design approval below. No branch writes model code before
that gate is proceed. Use the next available numeric stem; never
overwrite an existing note.
-
Locked baseline (
baseline). The note names the one comparison model the journal already locked. Adummytoken is aDummyClassifierorDummyRegressorinside the normal skrub DataOps declaration: it proves loading, fit/predict, and pytest smoke, and it is not expected to add predictive value. Any other token (logistic,seasonal_naive,group_mean,production) is that one comparison model. Do not upgrade it to another estimator. Do not AskUserQuestion before the note. The message lists these three commands, in order, before any design-note text. A workspace summary is not a substitute:python -m skore_skills status python -m skore_skills model choices python -m skore_skills scaffold --journal --stem <NN_short>Then fill Question, Motivation, Method, and Risks from the locked baseline, its note, and the comparison metric. Before the question, two to four lines name that baseline and its note. They do not say what Approve allows. The question is only these three lines:
- Approve — accept this note
- Modify — change this note
- Stop — leave this note unchanged
Nothing follows those lines. Do not mention discuss, an EDA proposal, or the backlog unless the user already asked for one of those. Keep the normal post-smoke Evaluate (Recommended) / Modify / Stop gate for a later turn.
-
EDA proposal (
eda_proposal). Readdata_analysis/data_analysis.mdand the project goal. Cite the EDA findings that motivate one pipeline proposal. Do not invent findings or present multiple silent alternatives. Restate the proposal, then one single-choice AskUserQuestion: Yes / No. Do not also ask for a typed yes. "Maybe" is not Yes. No or Stop writes nothing. A later Yes (the tool answer, or an explicit yes on a later turn) is what authorizes the write. On Yes, write the note, then Design approval, before build. -
Backlog (
backlog). Loadmanage-ml-backlogonly ifstatus.skills.manage-ml-backlogis true. Else one-line skip; do not invent a Backlog. Pass thebacklogrows returned by the CLI. That skill asks for oneB<N>when the user has not named one, and asks only for shaping facts the row does not state. It does not ask Yes / No. When it returns the proposal, runscaffold --journal --stem <NN_short>and fill the note from that Item, Source, and the facts just given, then Design approval, before build. Do not add an estimator or a procedure neither the row nor those facts stated. Do not add a new Backlog idea in this branch. -
Discussion (
discuss). Have an open conversation about what to learn, why now, and what changes. Restate the agreed idea, then one single-choice AskUserQuestion: Yes / No. Do not also ask for a typed yes. "Maybe" is not Yes. No or Stop writes nothing. A later Yes (the tool answer, or an explicit yes on a later turn) is what authorizes the write. Only after that confirmation create/populate the design note, then Design approval. If no idea is agreed, return to the entry choices.
Before execution
This dispatcher labels the next kind of work but does not duplicate a child's detailed preview.
- For
discuss, proposal shaping, or literature-backed design work, emit 1–3 natural sentences saying this is LLM discussion/research over recorded project facts, with no model fit, smoke test, or CV. Name any scratch research note or design note that may be written and stop at confirmation. - For an approved implementation, say which child comes next and
the broad sequence: local pipeline preparation → small
real-data smoke fit/predict → optional full-dataset evaluation
→ review. Then let
build-ml-pipeline,smoke-test-ml-pipeline,evaluate-ml-pipeline, andreview-ml-experimenteach own the single detailed Before execution preview at its actual compute boundary. The dispatcher preview is those four phase names only, one short line each. Do not mention the Method viewer, a site rebuild, a row-count assertion, orskore.evaluate. Do not list their commands (status,frame show,design consent,smoke run) or a DataOps declaration in this preview. Do not nameloop notebooksornotebook convert. Notebooks stay off until a report exists. With no shell, that four-phase paragraph is the whole answer: do not name the post-smoke Evaluate / Modify / Stop question, an unfittedsite build, orpipeline.html.
Do not invent minute estimates at dispatcher level. Name a known duration only when explicit measured evidence is available; otherwise leave cost details to the child that knows data scope, folds, and selected views. Pending proposal/design approval may preview the sequence but never starts local work.
If the design-note shell is missing, this turn only names
python -m skore_skills scaffold --journal --stem <NN_short>
and stops, except on the locked-baseline branch and on a backlog
proposal that skill already returned. Those two run the command
and populate Question / Motivation / Method / Risks in this same
turn, then Design approval. Do not fill those sections from
memory when the command did not run this turn.
Design approval
One gate approves a populated note. Run
python -m skore_skills design consent --stem <stem>.
proceed → already approved; do not ask again. ask → render
the JSON context inline (§ Gate context), including the site
preview when policy.site, then AskUserQuestion (single
choice), in order: Approve / Modify / Stop. Do not
also ask in chat whether the note looks right.
- Approve → run
python -m skore_skills design approve --stem <stem>. Do not type the date. Re-rundesign consent; code starts only onproceed. - Modify → leave
Stateplanned, edit the note, and ask this gate again. - Stop → do not implement.
Approved-design implement loop
- Load
build-ml-pipelineonly ifstatus.skills.build-ml-pipelineis true; else one-line skip and stop — do not declare the pipeline from this meta. That skill loadssmoke-test-ml-pipelineafter the experiment file exists and runspython -m skore_skills smoke run --stem <stem>. JSONstopstays in build (modify the pipeline, re-runsmoke run). Do not tell the user to edit the smoke test's expected row count so it matches the sample.proceed: build reports the design, thenpython -m skore_skills evaluate consent --stem <stem>(Evaluate / Modify / Stop onask, with that JSONcontextrendered inline per § Gate context). Build also writes the unfitted Method viewer (scratch/results/<stem>/pipeline/whenDataOp.skb.reportacceptseval, otherwisepipeline.html) and, whenpolicy.siteis true andexport-ml-siteis installed, runssite build --if-staleafter that snapshot and before Evaluate so Method shows that report. Missing or skipped EDA does not defer it. The post-loop rebuild refreshes the same unevaluated report; it does not replace this one. Do not fillexperiments/<stem>.pyat this unfitted snapshot if it already containsskore.evaluate. That ban ends whenloop notebooksreturnsconvert. - Only if the user chose Evaluate and
smoke runisproceed: loadevaluate-ml-pipelineonly ifstatus.skills.evaluate-ml-pipelineis true. It reuses the DataOpcvand writesskore.evaluatein the experiment script. Re-runstatusfirst, thenpython -m skore_skills evaluate consent --stem <stem>. Consent JSON is authoritative, not the user's wording alone. Missingevaluate-ml-pipeline→ one-line skip. Do not invent that skill's steps. - After a successful dispatched evaluate (locator returned): run
python -m skore_skills review consent --stem <stem>. Treat JSONactionas authoritative.stop— noscratch/results/<stem>/report.html. Do not review. Name that file. This is the evaluation snapshot, not the site launcherreport.html. Do not record-outcome.auditorproceed— loadreview-ml-experimentonly ifstatus.skills.review-ml-experimentis true. It returns the digest, G-AUDIT-FINDING, locator, and idea paths. Do not loadaudit-ml-pipelinefrom this dispatcher. Then § Close, in that order.- Missing skill → one-line skip and run § Close with
n/a — audit not run.
Do not duplicate child-skill methodology. Before new library
symbols are written, children use
python -m skore_skills api get <dotted>.... Several symbols
go in one call.
Stop conditions
- Pending setup (
status.setup.pendingnon-empty): loadsetup-ml-projectand do not start build. A declinedgitis not asked again. A declined env or workspace stops. - Generic model landing: do not hand-author the menu; run
python -m skore_skills model choices. - If
journal/NN_<short>.mdis missing, this turn only namespython -m skore_skills scaffold --journal --stem <NN_short>and stops, except the locked baseline and a returned backlog proposal. Those run that command and populate Question / Motivation / Method / Risks in the same turn, then Design approval. Do not fill the template from memory when the command did not run. Do notsite buildbefore the shell exists. - Require
design consentproceedbefore code. Do not treat "the user asked to build", or a chat yes on the drafted note, as approval. - Do not open an approval gate whose only context is a file path;
render the
contextfacts inline (§ Gate context). - Preserve identical stems across design, experiment, smoke, audit.
- Do not replace skrub DataOps with bare sklearn Pipeline.
- Do not persist a result as done while
smoke runisstop. - Do not load evaluate (or write
skore.evaluate) before the post-smoke HITL answer is Evaluate (evaluate consentask), exceptproceedfor a stem that already has a persisted report, or whilesmoke runisstop. - Do not load
smoke-test-ml-pipelinefrom this dispatcher. - Do not duplicate child-skill methodology in this dispatcher.
- If
status.data_analysisismissing, continue with facts the user stated; do not invent an exploratory data analysis report. - Literature-backed feature-engineering or learner-family
questions: load
build-ml-pipelineonly ifstatus.skills.build-ml-pipelineis true (it loadsresearch-ml-practiceonly ifstatus.skills.research-ml-practiceis true). Else one-line skip. Do not distill research here; do not invent papers from memory.
Close
Reached only after review returns, a missing review skill, or
red smoke. The four-phase preview does not enter here, and
neither does review consent stop. Run the steps in
this order. Do not reorder them. loop notebooks continues only
on skip. record is the loop artifacts action, not this
gate. Red smoke skips steps 3 and 4: do not mark the
experiment done. This dispatcher owns the user-facing close.
Children return locator / digest / finding and do not preview it.
python -m skore_skills loop notebooks --stem <stem>. Treat JSONactionas authoritative. Do not record-outcome,site build, orgit end-turnwhileactionisconvert.- On
convert, runpython -m skore_skills notebook fill <source>for everyexperiments/oraudit/entry, with--htmlwhenhtmlis true. Do notnotebook convertthose files. Fill does notput. Re-run the matchingmaterialize.pyfirst only when that human call changed since the run that wrote the current artifacts. Filling onlyaudit/<stem>.pydoes not finish the close. Re-run step 1 untilactionisskip. Missing jupytext / nbformat / nbconvert → one-line skip namingadd-python-package; do not fail the turn.skip/not_evaluatedmeans the report is missing: do not fill an unfitted script. Whenactionisconvert, the unfitted-snapshot ban does not apply, including whenexperiments/<stem>.pyalready containsskore.evaluate. - record-outcome, only once step 1 is
skip. Loadmanage-ml-backlogonly ifstatus.skills.manage-ml-backlogis true, in record-outcome mode, handing it the locator evaluate already returned, plus the optional headline and G-AUDIT-FINDING (n/a — audit not runwhen skipped). Else one-line skip; do not write History from this meta. It writes thejournal/JOURNAL.mdHistory row and design-note Status block plus## Results, then returns. It does not triage idea files. Never markdonewhilesmoke runisstop. Missing headline becomesn/a, never an invented metric. site buildonly whenpolicy.siteis true andexport-ml-siteis installed:python -m skore_skills site build --if-stale, so the Method DataOp report and Results replace the construct-time snapshot. Skip in one line otherwise. Site build embedsaudit/<stem>.nb.htmlunder## Notebooks; do not add<!-- results-embed: audit -->. Ifsite builderrors withmkdocs-material is required, loadadd-python-packageformkdocs-material(agent) and build once more. Do notpixi add/uv add. Name a build error; do not fail the turn.- User-facing close. 2–6 sentences of the result, grounded in
the audit digest when present (Checks + Metrics), else the
user's headline /
report.txt. Do not invent a metric. Whenpolicy.siteis true and the build ran, say the website has been updated and paste thefile://line from that output verbatim. Do not namehtml/<stem>.htmlorjournal/<stem>.md. When the site was not built, do not claim it was updated and do not name the markdown. Then G-REPORT-LOCATOR (the locator evaluate passed up, orn/a — backend did not expose a locator) first among tokens, then G-AUDIT-FINDING. Index strings, not the narrative. python -m skore_skills git end-turn --stage implement. If JSONactionisinvoke, loadpersist-ml-gitonly ifstatus.skills.persist-ml-gitis true and stop; that skill returns to triage. If persist is missing, name the pendingstagedpaths and stop. Otherwise loadtriage-ml-taskonly ifstatus.skills.triage-ml-taskis true; else stop. Do not rungit commitin this skill.