Skip to content
Back to skills

Ds

ASecurity

ALWAYS use for ANY substantive empirical task whose output is a dataset, table, figure or number - \"analyze this data\", \"build the panel\", \"merge these datasets\", \"run the regression\", \"profile this dataset\", \"clean this file up for analysis\", \"make me a summary table\", \"pull the data and check X\", \"replicate this paper's table 2\", \"build the ETL pipeline\", \"/ds\". Use proactively even when the user asks casually and never says \"analysis\". NEGATIVE ROUTING: grading empi...

  • 22 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 19, 2026
datapythongobashsqlawsdebugginggitdocumentation

Works with

  • claude code

Security analysis

A100/100

Pro scans all 14 files and shows the line behind each finding

Scanned October 5, 2026

npx -y skills add edwinhu/workflows --skill ds --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ds?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ds
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/edwinhu-workflows/badge)](https://www.skillsdirectory.com/skills/edwinhu-workflows)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ds
description: "ALWAYS use for ANY substantive empirical task whose output is a dataset, table, figure or number - \"analyze this data\", \"build the panel\", \"merge these datasets\", \"run the regression\", \"profile this dataset\", \"clean this file up for analysis\", \"make me a summary table\", \"pull the data and check X\", \"replicate this paper's table 2\", \"build the ETL pipeline\", \"/ds\". Use proactively even when the user asks casually and never says \"analysis\". NEGATIVE ROUTING: grading empirical work that already exists is the ds-reviewer agent; writing the results up as prose is writing-econ; spreadsheet file mechanics - reading, writing or reformatting an .xlsx - is xlsx, while building, merging or modelling the dataset inside it is ds; a one-line lookup against a file already in hand is answered inline, since this skill runs a full clarify/plan/dispatch/human-review lifecycle."
argument-hint: 'the dataset, analysis, or data pipeline to build'
allowed-tools: [Bash, Read, Edit, Write, Grep, Glob, AskUserQuestion, EnterPlanMode, ExitPlanMode, Agent, Monitor]
---

# ds — a data project, run through `work` with a computed data-quality gate

**What this skill carries** — grep `references/` for any subject the names below miss:
!`d=${CLAUDE_SKILL_DIR}; command -v skill-toc >/dev/null 2>&1 && exec skill-toc "$d"; s=$HOME/.claude/skills/plugin-utils/bin/skill-toc; [ -x "$s" ] && exec "$s" "$d"; echo "(skill-toc unavailable: references and scripts are NOT listed here — install the plugin-utils plugin, or start a new session so its bin/ reaches PATH)"`

**DS constraints in force** — every rule scoped to this workflow, discovered from the corpus so a new one needs no edit here; read the ones your task touches:
!`c=${CLAUDE_PLUGIN_ROOT}/scripts/load-constraints; [ -x "$c" ] && exec "$c" ds; echo "(constraint index unavailable: NO DS rule is listed here — the four named below are not the whole set)"`

The lifecycle is [`work`](${CLAUDE_PLUGIN_ROOT}/skills/work/SKILL.md). Read it and follow it.
This file is a **delta**: it supplies the domain — the CLARIFY axes, the plan grammar, the lens,
the mechanical checks, the refs, the authority text. It ships no `workflow.js` and restates none of
`work`'s mechanics.

What makes a run `ds` rather than plain `work` is one thing: **every declared data output is verified
by a computed runner, not by the agent that produced it.** `scripts/ds-dq.py` reads the approved
plan's `## Data Outputs` table and opens each artifact itself; `work`'s JS reads its exit code.

## Write surface

Main chat clarifies, plans and dispatches. It does not do the analysis, and it never writes a `.py`,
`.ipynb`, `.R`, `.sas`, `.sql` or `.qmd` file — not by Write/Edit, and not by Bash (`python3 -c`,
`pixi run python`, inline pandas/numpy). Analysis runs in a dispatched agent. `work`'s dispatch is
already structural and its judges are pinned to `Explore`, so this line is a rule on you, not a hook;
reach for the workflow first rather than after a refusal.

## Phase 1 — CLARIFY

`work`'s Phase 1, on these axes.

<EXTREMELY-IMPORTANT>
**ASK BEFORE YOU LOOK; PLAN ONLY FROM EVIDENCE YOU ACTUALLY GATHERED. This is not negotiable.**

Loading a dataset or proposing a method before the user has stated the outcome anchors the work to
whatever data happens to be nearby. Skipping a necessary profile replaces evidence with a convenient
guess. Neither shortcut is helpful: it creates an analysis that is fast to start and expensive to
correct.
</EXTREMELY-IMPORTANT>

| Axis | Establish with the user |
|---|---|
| Outcome | Question, audience, decision the analysis informs, and deliverables |
| Universe | Unit of observation, entity inclusion rule, sample period, and authoritative source when sources disagree |
| Sources | Available data, access/location, expected refresh/vintage, and known restrictions |
| Constraints | Replication target, required methods, deadline, compute/cost limits, and reproducibility needs |
| Evidence | What makes each planned output credible: a check, an inspectable exhibit, a source comparison, or user judgment |

Ask in one `AskUserQuestion` call when answers are independent. Ask cascading questions separately:
a source choice that determines available variables must be answered before variable questions.

Three facts decide these axes, and each prevents a defect that is expensive to find later:

- A sample period and an entity universe are **research choices**, not properties inferred from the
  first query result. A rate at the wrong grain is a different statistic with a familiar label.
- The universe predicate belongs where scope is decided. Applying it to a lookup or a denominator
  can turn available values into nulls; a 43.7% null-denominator incident came from exactly that
  duplicate filtering mistake.
- A criterion that **cannot name evidence** is a wish. The explicit `TBD (<phase>)` convention is
  legitimate only when profiling is the scheduled evidence-producing phase; never invent coverage.

`work`'s remaining axes are taken as `work` states them, with two domain bindings: `work` axis 4
(observable success criteria) is answered with the DQ runner over the plan's `## Data Outputs` plus
the target project's own test and lint commands **when the project has them**, and those strings
become `mechanicalChecks` verbatim; `work` axis 5 (review surface) is answered by the plan's
`## Review Surfaces` section. The `ds-dq` entry is never conditional. The `tests` and `lint` entries
are **omitted entirely when the project has no such command** — `work`'s probe runs a `cmd` verbatim,
so an unsubstituted `<the project's lint command>` placeholder blocks the gate on a placeholder
instead of on data quality.

Then gather planning evidence — **a read-only profile, never implementation**. For each source that
materially affects the plan, collect or dispatch a profile covering: location/access, approximate
shape, columns/types, date coverage, and likely row grain/key; nulls, duplicates, type drift,
category/distribution anomalies, and likely join risks; raw size and whether source-side filtering,
caching, partitioning, or server-side computation is needed; and a small representative sample only
when access and project policy permit it. Use direct read-only inspection for one small local source;
for independent sources, dispatch read-only profilers in parallel and consolidate. Do not make a
profiling agent implement a pipeline, mutate project files, or spawn further agents. Do not pull a
full source merely to estimate it. If an answer depends on implementation, state it as a planned
evidence task rather than pretending the profile established it.

Four discovery rules run in this same planning step, each governed by its own constraint file:

- **Large sources.** If a source may be large (roughly 50M rows, 500 MB to ship, or described as
  bulk/large/uncertain), read
  `${CLAUDE_PLUGIN_ROOT}/rules/ds-pull-sizing-decision.md` and follow it. The
  profile must compare filtered raw and candidate aggregate/server-side paths before planning commits
  to one. Do not pull a full source merely to estimate it.
- **External-skill discovery.** When the plan will use another skill or data provider, discover its
  relevant references and examples before choosing an approach: read
  `${CLAUDE_PLUGIN_ROOT}/rules/ds-external-skill-decision.md` and follow it.
  Record the resulting ADOPT, PATCH, or GREENFIELD decision in the plan itself.
- **Master datasets.** For multi-output work that shares a sample, read
  `${CLAUDE_PLUGIN_ROOT}/rules/ds-master-datasets.md`. Plan the minimal
  canonical analysis dataset(s), their grain and keys, and which planned outputs consume each one.
- **Parameter transparency.** For analytic filters or tunable thresholds, read
  `${CLAUDE_PLUGIN_ROOT}/rules/ds-parameter-transparency.md`; name one
  configuration location, rationale, and treatment of convenience choices in the plan.

## Phase 2 — PLAN

`work`'s Phase 2. The plan opens with frontmatter `workflow: ds` — required, so a context clear at
approval resumes here and not in `work`.

Five domain requirements on the plan:

- **The source/access strategy and the profile-derived risks.** The plan states how each source is
  reached, and the data-quality and scale risks the read-only profile actually surfaced. A risk found
  at CLARIFY that reaches no plan section is a risk nothing acts on.
- **Reproducibility decisions**, appropriate to the work: source vintages, seeds, environments and
  config. `R1` (fresh re-run reproducibility) is judged by the review lens's data-quality item, so a
  plan recording none of these leaves `R1` with nothing to judge against.
- **A `## Data Outputs` table**, in exactly this grammar, because `scripts/ds-dq.py` parses it and an
  output absent from it is one nothing will check:

  ```markdown
  ## Data Outputs

  | Path | Grain | Key Columns | Required Window |
  |---|---|---|---|
  | data/processed/panel.parquet | one row per firm-fiscal-year | pk: gvkey, fyear; event: gvkey, datadate | datadate: 2005-01-01..2025-12-31 |
  | data/processed/industry_xwalk.csv | one row per SIC code | sic | n/a |
  ```

  - **Path** — the produced artifact, relative to the project root. `.parquet`, `.csv`, or `.tsv`;
    one row per artifact the plan promises to produce.
  - **Grain** — the declared row grain, in words. This is the claim `DQ3` verifies rather than
    assumes.
  - **Key Columns** — the declared primary key `DQ3a` tests for uniqueness. Write `a, b` for a bare
    primary key, or `pk: a, b; event: c, d` to also declare the coarser business/event key `DQ3c`
    needs to catch amendments and restatements. Without an `event:` clause `DQ3c` reports `N/A`, and
    the runner says why.
  - **Required Window** — the sample period `COV` checks, as `[column: ]YYYY-MM-DD..YYYY-MM-DD`.
    Write `n/a` for an unwindowed output; `COV` then reports `N/A` with that as its reason. Naming
    the column is optional only when exactly one date column exists; an ambiguous window is a `FAIL`,
    not a pass.

- **A `## Review Surfaces` section** naming the concrete tables, figures, notebook exports,
  diagnostics, or decisions the user will inspect during human review.
- **`refs` on every task row and on the lens** — required, may be empty. `work`'s spine does not validate it;
  `wc-probe` P7 refuses an absent key in THIS file, so a live run assembled from an approved plan is
  unchecked. Write `refs: []` to state "no domain rules" rather than omitting the key.
- **Batch extraction strategy.** A task whose work is per-document LLM coding or extraction is a task that LAUNCHES a `gemini-batch` job on pre-cut excerpts (with a 1-request synchronous test first). It is never an agent reading the documents.

## Phase 3 — GOAL

`work`'s Phase 3 unchanged.

## Phase 4 — the work call

The args go in the plan's `<!-- work:dispatch -->` arming block, and the dispatch is **`work`'s own
`work-dispatch.sh`** — never a hand-written runner line. That script owns the TIER 1 plan-lint
gate, which refuses to dispatch on a `major`/`critical` plan finding and fails CLOSED on a verdict it
cannot count; hand-rolling the invocation silently drops it. `work` owns the wait, the result handling
and the return shape too, and `work-result.sh` reads the verdict. This run's `projectDir` is the
session repo, so `work`'s own run directory is already inside it and no `--run-dir` override applies.
There is no built-in `Workflow` call — the guard at
`~/.claude/hooks/main-thread-guard.sh` denies that tool outright.

```bash
bash ${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-dispatch.sh   # armed plan; or pass one
bash ${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/work-dispatch.sh --provider codex   # "run this through codex"
```

**Forward the provider.** A provider named in this skill's `$ARGUMENTS`, however it is spelled —
`--provider codex`, `--dispatch codex`, "run this on gpt" — is `--provider codex` on the line
above. `--provider` is the only spelling the scripts take, and both reject the others by name.
Omitting it silently runs the user's codex request on claude.

```js
{
  projectDir,
  goal: "<one sentence>",

  // The plan's table verbatim. Every task carries refs, empty or not. The four constraint
  // aggregates are UNCONDITIONAL — every implementation task carries all four, alongside
  // whichever vendored references that task's own work needs.
  tasks: [
    { id: "T1",
      name: "<data pull or pipeline task>",
      work: "<what to build>",
      writablePaths: ["<narrow>"],
      acceptance: "<the criterion the verifier checks>",
      refs: ["${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-conventions.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-analysis-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-engineering-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/references/etl-enforcement.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/references/sql-patterns.md"] },

    { id: "T2",
      name: "<task whose acceptance is evidentiary>",
      work: "<what to build>",
      writablePaths: ["<narrow>"],
      acceptance: "<the criterion the verifier checks>",
      refs: ["${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-conventions.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-analysis-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-engineering-constraints.md",
             "${CLAUDE_PLUGIN_ROOT}/skills/ds/references/verification-patterns.md"] },
  ],

  // The DS gate: the runner reads the approved plan's ## Data Outputs and opens each artifact
  // itself. ds-dq is never conditional. tests and lint are the TARGET project's own commands,
  // collected at CLARIFY, and are included ONLY when the project has them — a probe runs cmd
  // verbatim, so an unsubstituted placeholder blocks the gate on a placeholder. Omit the entry.
  // ONE entry point. These were three entries until 2026-09-15; a list of N independent
  // commands loses one silently. The project's own test and lint commands are ARGUMENTS
  // because this skill cannot know them — omit a flag and that leg reports "not declared",
  // which is visible, where a dropped entry is not.
  mechanicalChecks: [
    { name: "ds",
      cmd: "bash ${CLAUDE_PLUGIN_ROOT}/skills/ds/scripts/check.sh --plan <planPath> --project-dir <projectDir> [--test-cmd \"<the project's test command>\"] [--lint-cmd \"<the project's lint command>\"]" },
  ],
  // work-checks.sh runs it as a command (no agent); Jev scores the wired DS rules (A1, A4, DEN, DQ4, DQ6, E7, M1, R1, UNI; DQ1 waits in constraints/jev/uncalibrated/ and ds-dq.py decides it); a rule with p >= 0.85 lands in rulesThatFailed and blocks, lower ones reach the lens as a ranked checklist.
  ruleChecks: { name: "jev-rules", cmd: "bun ${CLAUDE_PLUGIN_ROOT}/skills/work/scripts/rule-check.ts --project-dir <projectDir> --plan <planPath>" },

  // One lens after verification and mechanical checks; its checklist covers all five dimensions.
  //
  // It does NOT pin Explore. Explore is a built-in agent with a PREDEFINED prompt that no preloaded
  // skill reaches, and it skips the CLAUDE.md hierarchy — so a constraint-indexed judgement
  // dispatched there is graded from memory of constraint ids it was never given. ds-reviewer's body
  // is a file this repo controls, and it is read-only by tools allowlist AND by
  // tests/agent-contract.test.mjs — the same structural property Explore is pinned for, in an agent
  // whose prompt can be told what it is grading. The four aggregates are not vendored into any
  // skill: they reach the lens as refs, from their one canonical home.
  lens: {
    agentType: "ds-reviewer",
    refs: ["${CLAUDE_PLUGIN_ROOT}/skills/ds/references/ds-checks.md",
           "${CLAUDE_PLUGIN_ROOT}/skills/ds/references/verification-patterns.md",
           "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-constraints.md",
           "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-common-conventions.md",
           "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-analysis-constraints.md",
           "${CLAUDE_PLUGIN_ROOT}/skills/ds/rules/ds-engineering-constraints.md"],
    prompt: "Judge the datasets, tables and figures in the working tree against the approved plan and the goal. Read every file in refs in full before judging the items that name one. CHECKLIST, every item in scope on every run: (1) CRITERIA vs ARTIFACTS — for each success criterion in the plan and goal, is there an artifact in the tree that satisfies it? Missing or partial satisfaction is a finding, CRITICAL where the deliverable cannot stand without it. (2) SCOPE fidelity — did the changes stay inside the plan's task table and writable paths? Out-of-scope edits, unrequested features and silently skipped plan items are findings, CRITICAL where an edit landed outside every declared writable path. (3) DATA-QUALITY JUDGEMENT, against ds-checks.md. A1, A4, DEN, DQ4, DQ6, E7, M1, R1 and UNI are the jev-rules verdicts in the digest: do not re-grade them, except to rule on a verdict the digest ranks below the block line. A rule in rulesThatFailed is not re-judged either: diagnose it and route it like a mechanical failure. Jev does not score DQ1 or DEL; ds-dq.py decides DQ1. DEL (coverage improved because the base shrank) is yours and MODEL-EVALUATED: report it with the evidence you actually read, never as PASS, which presents a judgement as a computation, and a coverage improvement not attributable to the base shrinking is a finding. Two judgements reach past the wired rule texts and stay yours, stated as broader than any verdict in the digest: whether the sources the outputs combine admit the same entities, which one shared filter predicate does not establish, and whether the vintages, environment and config the plan records would let a fresh re-run reproduce the result, which seeded draws alone do not. Plan criterion compliance is item (1). A judgement you cannot support with evidence you actually read is a finding, never a pass. (4) METHODOLOGY, against verification-patterns.md: a statistic computed at a grain other than the one the plan declared, a universe predicate applied where scope was not meant to be decided, a claim whose evidence is read from code rather than observed from a run, and an output the plan promised that nothing checks. (5) DS-CONSTRAINTS — grade the implemented code and outputs against the indexed constraints in the four aggregates, C1-C6, V1-V9, A1-A6, E1-E7. Grade only the constraints the task actually touches; an engineering constraint applied to a pure analysis task is a wrong finding that costs a round. Report every constraint finding with the file, the line and the quoted code, naming the constraint id, and list every id you considered including those you judged satisfied. NEVER report a constraint judgement as a computation — it is MODEL-EVALUATED. Severity across the whole checklist: `major` at minimum, `critical` where the defect invalidates the output's stated grain, universe or inference, never `minor`, which would leave the gate passing over a real universe defect. MODE — RED (a task was flagged or a mechanical check failed): diagnose EVERY failure in the digest and route it, naming cause and fix, to the task id whose writablePaths own the file, or to 'plan' when no task can own the fix. MODE — GREEN (everything passed): make one open-ended pass over the whole checklist and report each finding with an ownerTask. In both modes, rule every carried finding open or closed against evidence you actually read; silence leaves it open.",
  },

  authorityExtra: [
    "THE DS CONSTRAINT CORPUS IS ONE COMMAND AWAY. Run `${CLAUDE_PLUGIN_ROOT}/scripts/load-constraints ds` for the index — every rule scoped to this workflow, with an openable path — then read the ones your task touches. Do not work from a paraphrase of them in a brief: a paraphrase is a lossy copy of a corpus that moves.",
    "IRON LAW OF DS PLANNING — ask before you look; plan only from evidence you actually gathered.",
    "IRON LAW OF DS VERIFICATION — no check result without the runner's own output. A mechanical check reported from reading the code, or an N/A justified by a reason the model composed, is the model certifying its own enumeration. Every mechanical result is a line ${CLAUDE_PLUGIN_ROOT}/skills/ds/scripts/ds-dq.py emitted, quoted as emitted.",
    "Never report M1, UNI, DEN, DEL or R1 as PASS. The runner lists them as MODEL-EVALUATED; Jev scores M1, UNI, DEN and R1, and DEL is a judgement reported with the evidence read.",
    "DQ4 and DQ6 are `always N/A` from the runner, and `always N/A` is not a third kind of pass — the runner emits a line for them only because ENUM requires one, and an N/A never sets its non-zero exit. Jev's DQ4 and DQ6 verdicts score them against the input → transform → output count chain and the before/after shape. Never read their N/A as `the runner checked this`.",
    "An artifact absent from the plan's ## Data Outputs table is one nothing will check and cannot be claimed as verified. Do not verify an output the table never declared.",
    "The analysis is done by dispatched agents. Main chat writes no .py, .ipynb, .R, .sas, .sql or .qmd file, by any tool.",
    "Standing DS doer authority — every implementation task follows the indexed constraints in the four aggregates under ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/: ds-common-constraints.md (C1-C6), ds-common-conventions.md (V1-V9 — assumption-over-evidence, deferred verification, statistical validity, P-hacking prevention, sample-selection documentation), ds-analysis-constraints.md (A1-A6 — robustness checks, standard-error specification, visualization integrity, table-figure pairing, chart typography, chart colour) and ds-engineering-constraints.md (E1-E7 — determinism and seeds, schema contracts, join audits with row counts and match rates, idempotency, loud error handling, native document input, network politeness), each indexing the self-contained files under ${CLAUDE_PLUGIN_ROOT}/constraints/. All four are named in every implementation task's refs, and refs are contractual reads, not a reading list: read all four in full before writing code. ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/ds-checks.md stays a separate load.",
    "Rules: ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/ds-checks.md defines all thirteen checks; ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/etl-enforcement.md governs pipelines; ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/sql-patterns.md governs data pulls; ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/verification-patterns.md governs evidence; ${CLAUDE_PLUGIN_ROOT}/skills/ds/references/competing-hypothesis.md governs debugging.",
  ].join("\n"),

  implementerAgentType: "ds",   // the doer's own prompt replaces Claude Code's software-engineering one, which frames a dataset as a codebase
  verifierAgentType: "Explore",
}
```

`implementerAgentType` names `ds` because the default agent carries Claude Code's
software-engineering system prompt, and the deliverable here is a dataset, a table and a figure a
human reads — not a codebase. An agent is justified only by a custom prompt, hooks or preloaded
skills; `ds` earns it on the first alone — the constraint aggregates reach it as task `refs`, not as
a preloaded skill.

`verifierAgentType` pins `Explore` because it has no Edit and no Write: a judge that structurally
cannot modify the tree beats a prompt asking it not to. The lens buys the same property a different
way — `ds-reviewer` is read-only by tools allowlist — because Explore's prompt is predefined and no
preloaded skill or CLAUDE.md reaches it; the lens carries the four aggregates in its own `refs`.

Add `${CLAUDE_PLUGIN_ROOT}/skills/ds/references/competing-hypothesis.md` to a task's `refs` when
that task is a diagnosis rather than a build. `authorityExtra` names it; `refs` is what makes an
implementer read it in full.

The runner's own contract suite lives at
`${CLAUDE_PLUGIN_ROOT}/skills/ds/scripts/ds_dq_test.py`; add it as a `mechanicalChecks` entry on
any run that touches the runner.

## Phase 5 — HUMAN REVIEW

`work`'s Phase 5 unchanged, over the plan's `## Review Surfaces`. A clean technical verification is
evidence for that conversation, not human acceptance.

## Red flags

| Situation | Wrong move | Right move |
|---|---|---|
| Sizing a source | pull the whole thing to see how big it is | the transfer is the failure you are meant to prevent — profile filtered counts and aggregate candidates read-only |
| Profiling a source | treat a head sample as the profile | nulls, grain failures and type drift live outside the head — profile shape, tail/coverage, keys and quality signals |
| Naming a produced artifact | name it in prose | a runner given prose cannot open it, key it, or window it — add its row to `## Data Outputs` before approval |
| The DQ result | let the implementer report it | the doer cannot see the assumption it made in both places — the runner is a `mechanicalCheck` and the JS reads its exit code |
| `M1`/`UNI`/`DEN`/`DEL`/`R1` | report them as `PASS` | that presents a judgement as a computation — Jev's verdicts decide M1, UNI, DEN and R1; DEL is `MODEL-EVALUATED` with the evidence read |
| `DQ4`/`DQ6` reported `N/A` | read the `N/A` as the runner having checked them | `always N/A` is not a third kind of pass — the runner computes neither and an `N/A` never sets its non-zero exit; Jev's DQ4 and DQ6 verdicts decide them |
| Per-document LLM coding or extraction | fan out agents to read each document | launch a `gemini-batch` job on pre-cut excerpts (with a 1-request synchronous test first) |
| A judgement that depends on the constraint index | dispatch a built-in agent (`Explore`, `Plan`, `general-purpose`) | their prompts are predefined, no preloaded skill reaches them and they skip the CLAUDE.md hierarchy, so the constraints are graded from memory — dispatch a custom agent whose body you control, like `ds-reviewer` |
| Handing a doer the constraint aggregates | name the four paths in the task prompt's prose, or copy the aggregates into a skill | prose is discretionary and a copy is a second source of truth `tests/constraints-no-duplication.test.ts` fails on — put the four canonical paths in the task's `refs`, which `work` defines as reads the doer owes in full |
| Project state | write a `SPEC.md`, `STATE.md` or `LEARNINGS.md` | competing state makes progress ambiguous — the approved plan is the authority and `work` hashes it |
| Something `work` does not obviously do | write a `ds/workflow.js` | ask which `work` parameter is missing — `mechanicalChecks` is what makes the DQ runner the gate |

Files in this skill

  • SKILL.md26.8 KB
  • references/competing-hypothesis.md2.3 KB
  • references/ds-checks.md15.5 KB
  • references/etl-enforcement.md13.2 KB
  • references/sql-patterns.md11.3 KB
  • references/verification-patterns.md2.9 KB
  • rules/ds-analysis-constraints.md2.3 KB
  • rules/ds-common-constraints.md2.1 KB
  • rules/ds-common-conventions.md1.9 KB
  • rules/ds-engineering-constraints.md2.7 KB
  • scripts/check.sh1.7 KB
  • scripts/ds-dq.py24.1 KB
  • scripts/ds_dq_test.py12.8 KB
  • scripts/ds_schema.py2.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…