Deepline plays skill

Use for Deepline GTM work that searches, enriches, scores, collects signals, or automates a workflow: find companies or people, enrich a CSV, find emails or LinkedIn, compare providers, build a waterfall, create a webhook or cron, or write a Play.

by getaero-io·MIT license·★ 66 Stars on the repo·GitHub ↗

Use now

Inside this skill

SKILL.md · the author's own words
# Deepline Plays

## Quick Start

```bash
npm install -g deepline
deepline auth register --wait auto
deepline -h
```

## Build, run and inspect

### Plays and Tools

- **Tool:** one operation, such as looking up a profile or validating an email.
  Use direct tool calls for isolated spot checks.

Word-for-word excerpt, not a result. Read the full SKILL.md ↓

Files of Deepline plays

getaero-io/main1 file shown
SKILL.md
Show the full text312 lines

Deepline Plays

Quick Start

npm install -g deepline
deepline auth register --wait auto
deepline -h

Build, run and inspect

Plays and Tools
  • Tool: one operation, such as looking up a profile or validating an email. Use direct tool calls for isolated spot checks.
  • Play: TypeScript that expresses GTM work as code. Combine tools with custom logic—transformations, conditions and fallbacks—and process batches of data. Deepline handles provider rate limits and retries, persists progress and results, and supports recovery after failures.
  • For workflows or batches: use a supplied Play, reuse or adapt a suitable prebuilt, or author one when none fits. Don't process batches by looping direct tool calls in scripts or repeated agent calls.
Workflow
  • Discover/build: search and describe relevant Plays/tools; reuse a suitable prebuilt or adapt it. See authoring and the SDK reference.

  • Check/pilot: inspect input mappings and run deepline plays check <file> before local-source execution. Pilot costly or unproven work within the agreed budget. Run small supplied Plays once, without a duplicate pilot or redesign.

  • Run: plays run waits by default; --no-wait returns its ID immediately. Use runs tail <run-id> to follow an existing run and runs get <run-id> for status/results. After a disconnect, reconnect—don't relaunch.

  • Inspect/transform: overview first, then follow the suggested commands. Play datasets persist in database tables. Prefer read-only SQL for filtering, joining, flattening and aggregating stored data before downloading. Inspect actual column types and sample values first; don't assume a JSON structure. After a type error, inspect the data rather than guessing another query. Adapt the suggested SQL, preserving its table and run filter.

    Get the run ID, physical tables and suggested SQL in one call:

    deepline runs get <run-id> --json run.id,datasets.storage,actions
    

    Check deepline runs get --help before using field selection. Older CLIs offer only bare --json; use it without a field list, or update the CLI. Save a tool contract with deepline tools describe <tool-id> --json > contract.json; tools describe does not accept --out. In Windows PowerShell 5.1, use cmd /d /c "deepline tools describe <tool-id> --json > contract.json" to keep the file UTF-8; direct PowerShell redirection writes UTF-16.

    Use the returned schema/table for <returned-table> (for example, "storage"."contact_email_waterfall_email_rows"). Copy the run-membership predicate from the suggested SQL into <returned-run-filter> (for example, _run_id = '<run-id>'); storage alone doesn't supply it. Check additional status filters and sample limits before computing whole-run totals. Use the dataset's actual columns and JSON structure:

    -- Aggregate before downloading.
    SELECT domain, COUNT(*) AS contacts, COUNT(email) AS emails_found
    FROM <returned-table>
    WHERE <returned-run-filter>
    GROUP BY domain;
    

    These are read-only projections, not changes to stored rows.

  • Export: use the suggested export command for complete rows, CSV for delivery or --format json for nested evidence. The response is a file receipt—read the file. Use csv show <file> --summary for local CSV summaries.

  • CLI hygiene: use -h; run deepline preflight --json as a standalone command and wait before parallel Deepline work. No head/tail truncation of CLI responses; use field selection or summaries. Preserve complete responses, separate stderr from JSON, and check exit status (pipefail for pipelines).

  • Evidence: previews aren't complete results; completed runs can contain failures; nulls don't explain misses. Inspect affected rows, then use runs logs <run-id> --kind receipt.completed --payloads --json for saved tool results. Select an exact result by its returned eventId with --where. Logs reads don't execute tools. Investigate unresolved requested conditions and stop once supported. See debugging.

  • Save/scope: keep deliverables in a durable project directory, preserve source files and every supplied identity, including misses and failed rows. Planning/inspection authorizes no paid execution; returned actions don't authorize retries, provider changes, publishing or external writes. Monitor access/consent remains separate. A credit shortage doesn't block otherwise accessible retained results.

Read logs and events: use deepline runs logs --help for all known kinds and filter examples. A run ID alone reads text logs; omit it or add a search flag to search events. Use --kind for run/step outcomes and --payloads for available details or saved results. Follow next.logs to page with the same UTC window. These reads execute no providers. Read Run logs and events for more recipes and SDK fields.

Write searchable customer logs: use ctx.log('Lookup finished', { context: { companyId: 'acme_123', rows: 12 } }), then filter with --where '$.context.companyId == "acme_123"'. The runtime attaches the authenticated org, Run, Play and known attempt; do not copy those into context. Customer KV cannot override that identity. Context allows eight flat scalar fields and 2 KiB per line, with a 128 KiB context budget per run. Sampling and run text limits also apply. Fetch large outputs through receipt events and --payloads, rather than logging their bodies.

Typed provider activity events also expose safe provider and operation keys for equality filters. They identify the provider and tool operation recorded by the runtime; they do not index raw request/response bodies or promise one search event per provider call.

deepline runs logs --kind run.failed --json
deepline runs logs --kind step.failed --payloads --json
deepline runs logs --kind receipt.failed --payloads --json

Use the installed command's --help before an unfamiliar flag. Skills can refresh independently of the CLI binary; an unsupported flag is a grammar or version mismatch, not evidence that the cloud operation failed. Follow an update hint when compatibility identifies a newer command, then rerun preflight before using the refreshed instructions.

Before the first Deepline fanout in a task, run deepline preflight --json as one standalone command and wait for it to finish. Never submit preflight beside another Deepline command.

The experiment methodology below applies when designing or comparing new work, not to execution-only or existing-run inspection requests.

contract → compare → exploit → recover → export → price

Ordinary TypeScript, no DSL. A SearchProgram is one function that calls a tool, a fetch, a child Play, a connector, or a local artifact and returns a typed attempt. runSearchExperiment owns the pilot, ranked waterfall, holdout, gap-only retries, and cost/coverage report.

Deliverable

Part Contents
Result line rows in / accepted / marginal credits per accepted row / run id
CSV the user's exact headers, per-claim source, miss_reason on every null
Unresolved rows in the same file; a null carries an absence receipt
Route table initial and final waterfall, cost and completions per route
COST RECEIPT the block run-and-export-search-experiment.py prints, verbatim
Next actions dormant routes and what each would buy, at measured cost deltas
  • Marginal, never amortized. Total ÷ successes reported 1.51 credits/email for a route whose real marginal cost was 0.21.
  • Pass the printed block through. Do not recompute credits in prose.
  • A catalog ceiling stops the run; it is not spend. Label it. A 120-credit ceiling truncated recovery at ~12 credits actual, and two apparent logic regressions were budget artifacts.

Read one job page

Read the row that matches this job, and only that row. Each page is complete for its job: source geometry, route ladder, pilot sizing, stop conditions.

The job Page
Companies or people that are not rows yet jobs/finding.md
Columns to fill on rows you already have jobs/enriching.md
Claims that need attributable evidence jobs/researching.md
A trigger, review gate, or external side effect jobs/automating.md

Two lookups, consulted on a trigger rather than read up front: shared/authoring.md for Play syntax outside the scaffold, and references/debugging.md for a failed, empty, or misshapen run.

For every public definePlay/ctx.* type, binding, durable-cache rule, and runtime error, read references/sdk-reference.md. It is generated from the authoring contract and SDK source; do not duplicate that surface in this skill.

If your configuration forbids subagents, say so before starting serial work. Resolving that conflict silently cost one run ~30 minutes.

Topology

Write unit + decision + required facts + scale before touching tools. Requested fields stay required; demoting one to promote a run is not a pass. A null needs an absence receipt: materially different routes tried, typed outcomes retained.

One shape. Known rows: one experiment over the supplied rows. Open-world discovery: rows are query/page/geography/registry partitions, never remembered companies. Company → person: two sequential stages, not consensus; only companyExperiment.finalResults become contact rows. End-to-end: compare only when every program produces the same complete final row from the same seam.

Catalog

Use search commands without --json. Read the full default tools describe output before authoring; use JSON only when feeding a structured-data helper.

deepline search --type tools "<information role and controls>"
deepline tools grep "<substring>"   # ranked search has returned the same
                                           # irrelevant hits for three different queries
deepline tools list <returned-category> --json
deepline tools describe <tool-id>
# Optional: extract declared getters programmatically after reading the contract.
deepline tools describe <tool-id> --json | python3 <skill-root>/scripts/show-declared-getters.py
python3 <skill-root>/scripts/show-declared-getters.py "$WORKDIR/<tool-id>.json"   # saved contract

tools describe is the authoring contract and can disagree with runtime: a declared getter has been absent, and a tool documenting one scalar has returned a full list. Bind a named declared playExpression and sentinel-probe one row before scaling. toolResponse.rawV2 is for an exact source excerpt, debugging, or an undeclared field after that probe — never a cast into an invented Company[].

Cover source classes before provider names — index, SERP, primary document, registry, event feed, first-party data, aggregator, validator. Two vendors reaching the same terminal corpus are one evidence lineage.

Record each route's pricing basis: per call, per returned result, or unknown. A confirmed-uncharged miss justifies a broader challenge wave, not a narrower one.

Build and run

python3 <skill-root>/scripts/scaffold-search-experiment.py \
  ./deepline/data/<task-slug> --name <task-slug> --input-csv <rows.csv>

Read its printed next list: it carries the four seams, tools: [...], coherenceChecks, and the company→person handoff at the point you edit them. --input-csv also writes a stratified fixture.csv. Iterate route code against that; use the full cohort only for a scored run.

Give definePlay a short, readable displayName when its identifier is unclear; the UI uses it as the title and derives a name from the identifier when absent. Keep the separate top-level description short and concrete about the Play's purpose. Catalog categories are derived from the registered tools used by the Play; do not author category metadata on the Play itself.

deepline billing balance --json
python3 <skill-root>/scripts/run-and-export-search-experiment.py \
  ./deepline/data/<task-slug>/<task-slug>.play.ts --input '{}' --out ./results.csv
python3 <skill-root>/scripts/cost-receipt.py <run-id> --scorecard <scorecard>.csv  # already-run

run-and-export does the structural check, Play check, completed Play, run-bound export of both the results dataset and the route scorecard, then the COST RECEIPT. Its {ok: true, runId, output} is the completion receipt: before it the work is a probe, and a CSV written from remembered values hides which route won.

Receipt labels:

  • CUT CANDIDATE — spent credits, completed nothing. Cut it. One route at 3.95 credits/call, 200× a search, ran ten rounds for zero results because the scorecard reported no cost at all.
  • NEVER REACHED — never invoked, so its zero results are not a ceiling and not a source miss. maxFallbacks bounds the dependency-closed waterfall and defaults to 2; raise it (up to 4, scaled to pool size) or drop the route.
  • cached calls — reruns of the same inputs reuse tool receipts. Quote the marginal rate, not this run's total.

Quality gates precede economics; among valid results prefer fewer observed credits, then fewer calls. Never expose provider spend.

Reusing a route across jobs is an eval, not a score: freeze the contract, verifier, cases and ceiling, and stratify the case set (normal, sparse, likely-miss, collision-prone) rather than picking easy rows after seeing results. A concept is an information geometry, never a vendor.

Product friction feedback

Unless the user restricts external reporting, send one proactive deepline feedback send report per issue cluster when a Play is disproportionately slow, appears stuck through repeated status checks, or an ordinary result requires avoidable product steps. Continue the user's task after reporting; feedback is not the deliverable and does not authorize paid reproduction or session sharing.

Use judgment rather than a fixed threshold. Do not report normal provider work just because it is not instant. Report when the duration is surprising for the input size or prior comparable runs, progress stays uninformative, or the path needs avoidable discovery, conversion, ID extraction, retry, export, or manual workaround steps.

Include the goal and Play/run ID. For latency, include input size, observed duration, status transitions or polling count, and expected progress. For excess steps, include the actual path, avoidable detours, and expected direct path. Do not pass --requested for a proactive report. Omit --error-outcome when no error occurred; if an error did occur, use terminal only when it stopped the task and continued when work continued.

deepline feedback send "Goal: <goal>. Play/run: <play and run id>. Friction: <what was slow or indirect>. Observed: <duration, polling, or actual steps>. Expected: <reasonable duration, progress, or direct path>."

Subagents

One or two, only when several source geometries are plausible: same contract, one source lane each, returning a strategy card and ordinary TypeScript. The parent binds, runs, and judges. Verification fans out the same way — four defects found in four sequential rounds of eyeballing output fit in one pass over row batches.

1---
2name: deepline-plays
3description: 'Use for Deepline GTM work that searches, enriches, scores, collects signals, or automates a workflow: find companies or people, enrich a CSV, find emails or LinkedIn, compare providers, build a waterfall, create a webhook or cron, or write a Play. For live information work, run a small heterogeneous experiment, exploit the observed winner, and reopen misses. Skip pure copywriting and non-GTM research.'
4---
5 
6# Deepline Plays
7 
8## Quick Start
9 
10```bash
11npm install -g deepline
12deepline auth register --wait auto
13deepline -h
14```
15 
16## Build, run and inspect
17 
18### Plays and Tools
19 
20- **Tool:** one operation, such as looking up a profile or validating an email.
21 Use direct tool calls for isolated spot checks.
22- **Play:** TypeScript that expresses GTM work as code. Combine tools with custom
23 logic—transformations, conditions and fallbacks—and process batches of data.
24 Deepline handles provider rate limits and retries, persists progress and
25 results, and supports recovery after failures.
26- **For workflows or batches:** use a supplied Play, reuse or adapt a suitable
27 prebuilt, or author one when none fits. Don't process batches by looping direct
28 tool calls in scripts or repeated agent calls.
29 
30### Workflow
31 
32- **Discover/build:** search and describe relevant Plays/tools; reuse a suitable
33 prebuilt or adapt it.
34 See [authoring](shared/authoring.md) and the [SDK reference](references/sdk-reference.md).
35- **Check/pilot:** inspect input mappings and run `deepline plays check <file>`
36 before local-source execution. Pilot costly or unproven work within the agreed
37 budget. Run small supplied Plays once, without a duplicate pilot or redesign.
38- **Run:** `plays run` waits by default; `--no-wait` returns its ID immediately.
39 Use `runs tail <run-id>` to follow an existing run and `runs get <run-id>`
40 for status/results. After a disconnect, reconnect—don't relaunch.
41- **Inspect/transform:** overview first, then follow the suggested commands.
42 Play datasets persist in database tables. Prefer read-only SQL for filtering,
43 joining, flattening and aggregating stored data before downloading. Inspect
44 actual column types and sample values first; don't assume a JSON structure.
45 After a type error, inspect the data rather than guessing another query.
46 Adapt the suggested SQL, preserving its table and run filter.
47 
48 Get the run ID, physical tables and suggested SQL in one call:
49 
50 ```bash
51 deepline runs get <run-id> --json run.id,datasets.storage,actions
52 ```
53 
54 Check `deepline runs get --help` before using field selection. Older CLIs
55 offer only bare `--json`; use it without a field list, or update the CLI.
56 Save a tool contract with `deepline tools describe <tool-id> --json > contract.json`;
57 `tools describe` does not accept `--out`.
58 In Windows PowerShell 5.1, use
59 `cmd /d /c "deepline tools describe <tool-id> --json > contract.json"`
60 to keep the file UTF-8; direct PowerShell redirection writes UTF-16.
61 
62 Use the returned schema/table for `<returned-table>` (for example,
63 `"storage"."contact_email_waterfall_email_rows"`). Copy the run-membership
64 predicate from the suggested SQL into `<returned-run-filter>` (for example,
65 `_run_id = '<run-id>'`); storage alone doesn't supply it. Check additional
66 status filters and sample limits before computing whole-run totals.
67 Use the dataset's actual columns and JSON structure:
68 
69 ```sql
70 -- Aggregate before downloading.
71 SELECT domain, COUNT(*) AS contacts, COUNT(email) AS emails_found
72 FROM <returned-table>
73 WHERE <returned-run-filter>
74 GROUP BY domain;
75 ```
76 
77 These are read-only projections, not changes to stored rows.
78 
79- **Export:** use the suggested export command for complete rows, CSV for delivery
80 or `--format json` for nested evidence. The response is a file receipt—read
81 the file. Use `csv show <file> --summary` for local CSV summaries.
82- **CLI hygiene:** use `-h`; run `deepline preflight --json` as a standalone command
83 and wait before parallel Deepline work. No `head`/`tail` truncation of CLI responses;
84 use field selection or summaries. Preserve complete responses, separate
85 stderr from JSON, and check exit status (`pipefail` for pipelines).
86- **Evidence:** previews aren't complete results; completed runs can contain
87 failures; nulls don't explain misses. Inspect affected rows, then use
88 `runs logs <run-id> --kind receipt.completed --payloads --json` for saved
89 tool results. Select an exact result by its returned `eventId` with `--where`.
90 Logs reads don't execute tools. Investigate unresolved requested conditions
91 and stop once supported. See [debugging](references/debugging.md).
92- **Save/scope:** keep deliverables in a durable project directory, preserve
93 source files and every supplied identity, including misses and failed rows.
94 Planning/inspection authorizes no paid execution; returned actions don't
95 authorize retries, provider changes, publishing or external writes. Monitor
96 access/consent remains separate. A credit shortage doesn't block otherwise
97 accessible retained results.
98 
99**Read logs and events:** use `deepline runs logs --help` for all known kinds
100and filter examples. A run ID alone reads text logs; omit it or add a search
101flag to search events. Use `--kind` for run/step outcomes and `--payloads` for
102available details or saved results. Follow `next.logs` to page with the same
103UTC window. These reads execute no providers. Read
104[Run logs and events](references/run-events.md) for more recipes and SDK fields.
105 
106**Write searchable customer logs:** use `ctx.log('Lookup finished', { context:
107{ companyId: 'acme_123', rows: 12 } })`, then filter with
108`--where '$.context.companyId == "acme_123"'`. The runtime attaches the
109authenticated org, Run, Play and known attempt; do not copy those into context.
110Customer KV cannot override that identity. Context allows eight flat scalar
111fields and 2 KiB per line, with a 128 KiB context budget per run. Sampling and
112run text limits also apply. Fetch large outputs through receipt events and
113`--payloads`, rather than logging their bodies.
114 
115Typed provider activity events also expose safe `provider` and `operation` keys
116for equality filters. They identify the provider and tool operation recorded by
117the runtime; they do not index raw request/response bodies or promise one search
118event per provider call.
119 
120```bash
121deepline runs logs --kind run.failed --json
122deepline runs logs --kind step.failed --payloads --json
123deepline runs logs --kind receipt.failed --payloads --json
124```
125 
126Use the installed command's `--help` before an unfamiliar flag. Skills can
127refresh independently of the CLI binary; an unsupported flag is a grammar or
128version mismatch, not evidence that the cloud operation failed. Follow an
129update hint when compatibility identifies a newer command, then rerun preflight
130before using the refreshed instructions.
131 
132Before the first Deepline fanout in a task, run `deepline preflight --json` as
133one standalone command and wait for it to finish. Never submit preflight beside
134another Deepline command.
135 
136The experiment methodology below applies when designing or comparing new work,
137not to execution-only or existing-run inspection requests.
138 
139```text
140contract → compare → exploit → recover → export → price
141```
142 
143Ordinary TypeScript, no DSL. A `SearchProgram` is one function that calls a tool,
144a fetch, a child Play, a connector, or a local artifact and returns a typed
145attempt. `runSearchExperiment` owns the pilot, ranked waterfall, holdout,
146gap-only retries, and cost/coverage report.
147 
148## Deliverable
149 
150| Part | Contents |
151| ------------------- | ----------------------------------------------------------------------- |
152| **Result line** | rows in / accepted / marginal credits per accepted row / run id |
153| **CSV** | the user's exact headers, per-claim source, `miss_reason` on every null |
154| **Unresolved rows** | in the same file; a null carries an absence receipt |
155| **Route table** | initial and final waterfall, cost and completions per route |
156| **COST RECEIPT** | the block `run-and-export-search-experiment.py` prints, verbatim |
157| **Next actions** | dormant routes and what each would buy, at measured cost deltas |
158 
159- Marginal, never amortized. Total ÷ successes reported 1.51 credits/email for a
160 route whose real marginal cost was 0.21.
161- Pass the printed block through. Do not recompute credits in prose.
162- A catalog ceiling stops the run; it is not spend. Label it. A 120-credit
163 ceiling truncated recovery at ~12 credits actual, and two apparent logic
164 regressions were budget artifacts.
165 
166## Read one job page
167 
168Read the row that matches this job, and only that row. Each page is complete for
169its job: source geometry, route ladder, pilot sizing, stop conditions.
170 
171| The job | Page |
172| ----------------------------------------------- | --------------------- |
173| Companies or people that are not rows yet | `jobs/finding.md` |
174| Columns to fill on rows you already have | `jobs/enriching.md` |
175| Claims that need attributable evidence | `jobs/researching.md` |
176| A trigger, review gate, or external side effect | `jobs/automating.md` |
177 
178Two lookups, consulted on a trigger rather than read up front:
179`shared/authoring.md` for Play syntax outside the scaffold, and
180`references/debugging.md` for a failed, empty, or misshapen run.
181 
182For every public `definePlay`/`ctx.*` type, binding, durable-cache rule, and
183runtime error, read `references/sdk-reference.md`. It is generated from the
184authoring contract and SDK source; do not duplicate that surface in this skill.
185 
186**If your configuration forbids subagents, say so before starting serial work.**
187Resolving that conflict silently cost one run ~30 minutes.
188 
189## Topology
190 
191Write `unit + decision + required facts + scale` before touching tools.
192Requested fields stay required; demoting one to promote a run is not a pass. A
193null needs an absence receipt: materially different routes tried, typed outcomes
194retained.
195 
196One shape. **Known rows:** one experiment over the supplied rows. **Open-world
197discovery:** rows are query/page/geography/registry partitions, never remembered
198companies. **Company → person:** two sequential stages, not consensus; only
199`companyExperiment.finalResults` become contact rows. **End-to-end:** compare
200only when every program produces the same complete final row from the same seam.
201 
202## Catalog
203 
204Use search commands without `--json`. Read the full default `tools describe`
205output before authoring; use JSON only when feeding a structured-data helper.
206 
207```bash
208deepline search --type tools "<information role and controls>"
209deepline tools grep "<substring>" # ranked search has returned the same
210 # irrelevant hits for three different queries
211deepline tools list <returned-category> --json
212deepline tools describe <tool-id>
213# Optional: extract declared getters programmatically after reading the contract.
214deepline tools describe <tool-id> --json | python3 <skill-root>/scripts/show-declared-getters.py
215python3 <skill-root>/scripts/show-declared-getters.py "$WORKDIR/<tool-id>.json" # saved contract
216```
217 
218`tools describe` is the authoring contract and can disagree with runtime: a
219declared getter has been absent, and a tool documenting one scalar has returned a
220full list. Bind a named declared `playExpression` and sentinel-probe one row
221before scaling. `toolResponse.rawV2` is for an exact source excerpt, debugging, or
222an undeclared field after that probe — never a cast into an invented `Company[]`.
223 
224Cover source classes before provider names — index, SERP, primary document,
225registry, event feed, first-party data, aggregator, validator. Two vendors
226reaching the same terminal corpus are one evidence lineage.
227 
228Record each route's pricing basis: per call, per returned result, or unknown. A
229confirmed-uncharged miss justifies a broader challenge wave, not a narrower one.
230 
231## Build and run
232 
233```bash
234python3 <skill-root>/scripts/scaffold-search-experiment.py \
235 ./deepline/data/<task-slug> --name <task-slug> --input-csv <rows.csv>
236```
237 
238Read its printed `next` list: it carries the four seams, `tools: [...]`,
239`coherenceChecks`, and the company→person handoff at the point you edit them.
240`--input-csv` also writes a stratified `fixture.csv`. Iterate route code against
241that; use the full cohort only for a scored run.
242 
243Give `definePlay` a short, readable `displayName` when its identifier is unclear;
244the UI uses it as the title and derives a name from the identifier when absent.
245Keep the separate top-level `description` short and concrete about the Play's
246purpose. Catalog categories are derived from the registered tools used by the
247Play; do not author category metadata on the Play itself.
248 
249```bash
250deepline billing balance --json
251python3 <skill-root>/scripts/run-and-export-search-experiment.py \
252 ./deepline/data/<task-slug>/<task-slug>.play.ts --input '{}' --out ./results.csv
253python3 <skill-root>/scripts/cost-receipt.py <run-id> --scorecard <scorecard>.csv # already-run
254```
255 
256`run-and-export` does the structural check, Play check, completed Play, run-bound
257export of both the results dataset and the route scorecard, then the COST
258RECEIPT. Its `{ok: true, runId, output}` is the completion receipt: before it the
259work is a probe, and a CSV written from remembered values hides which route won.
260 
261Receipt labels:
262 
263- **CUT CANDIDATE** — spent credits, completed nothing. Cut it. One route at 3.95
264 credits/call, 200× a search, ran ten rounds for zero results because the
265 scorecard reported no cost at all.
266- **NEVER REACHED** — never invoked, so its zero results are not a ceiling and not
267 a source miss. `maxFallbacks` bounds the dependency-closed waterfall and
268 defaults to 2; raise it (up to 4, scaled to pool size) or drop the route.
269- **cached calls** — reruns of the same inputs reuse tool receipts. Quote the
270 marginal rate, not this run's total.
271 
272Quality gates precede economics; among valid results prefer fewer observed
273credits, then fewer calls. Never expose provider spend.
274 
275Reusing a route across jobs is an eval, not a score: freeze the contract,
276verifier, cases and ceiling, and stratify the case set (normal, sparse,
277likely-miss, collision-prone) rather than picking easy rows after seeing results.
278A concept is an information geometry, never a vendor.
279 
280## Product friction feedback
281 
282Unless the user restricts external reporting, send one proactive
283`deepline feedback send` report per issue cluster when a Play
284is disproportionately slow, appears stuck through repeated status checks, or an
285ordinary result requires avoidable product steps. Continue the user's task after
286reporting; feedback is not the deliverable and does not authorize paid
287reproduction or session sharing.
288 
289Use judgment rather than a fixed threshold. Do not report normal provider work
290just because it is not instant. Report when the duration is surprising for the
291input size or prior comparable runs, progress stays uninformative, or the path
292needs avoidable discovery, conversion, ID extraction, retry, export, or manual
293workaround steps.
294 
295Include the goal and Play/run ID. For latency, include input size, observed
296duration, status transitions or polling count, and expected progress. For excess
297steps, include the actual path, avoidable detours, and expected direct path. Do
298not pass `--requested` for a proactive report. Omit `--error-outcome` when no
299error occurred; if an error did occur, use `terminal` only when it stopped the
300task and `continued` when work continued.
301 
302```bash
303deepline feedback send "Goal: <goal>. Play/run: <play and run id>. Friction: <what was slow or indirect>. Observed: <duration, polling, or actual steps>. Expected: <reasonable duration, progress, or direct path>."
304```
305 
306## Subagents
307 
308One or two, only when several source geometries are plausible: same contract, one
309source lane each, returning a strategy card and ordinary TypeScript. The parent
310binds, runs, and judges. Verification fans out the same way — four defects found
311in four sequential rounds of eyeballing output fit in one pass over row batches.
312 

Discussion