@inflexa-ai/harness 0.24.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/sandbox/__fixtures__/deps.js +6 -0
- package/dist/agents/sandbox/data-profiler.js +5 -4
- package/dist/agents/sandbox/shared.js +11 -0
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/app/data-profile-orientation.js +30 -1
- package/dist/contracts/data-profile.d.ts +166 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/execution/input-signature.d.ts +33 -0
- package/dist/execution/input-signature.js +0 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +10 -3
- package/dist/input-scan/coverage.d.ts +22 -0
- package/dist/input-scan/coverage.js +85 -0
- package/dist/input-scan/enrich.d.ts +41 -0
- package/dist/input-scan/enrich.js +227 -0
- package/dist/input-scan/formats.d.ts +41 -0
- package/dist/input-scan/formats.js +279 -0
- package/dist/input-scan/index.d.ts +12 -0
- package/dist/input-scan/index.js +11 -0
- package/dist/input-scan/scan.d.ts +50 -0
- package/dist/input-scan/scan.js +182 -0
- package/dist/input-scan/shapes.d.ts +46 -0
- package/dist/input-scan/shapes.js +0 -0
- package/dist/input-scan/types.d.ts +172 -0
- package/dist/input-scan/types.js +12 -0
- package/dist/lib/page-capture.d.ts +44 -15
- package/dist/lib/page-capture.js +78 -19
- package/dist/loop/run-agent.js +36 -19
- package/dist/memory/card-builders.d.ts +4 -6
- package/dist/memory/card-builders.js +4 -6
- package/dist/memory/conversation-display-replay.d.ts +7 -6
- package/dist/memory/conversation-display-replay.js +7 -6
- package/dist/memory/conversation-display-storage.d.ts +2 -10
- package/dist/memory/conversation-display-storage.js +79 -32
- package/dist/memory/thread-history.d.ts +31 -20
- package/dist/memory/thread-history.js +45 -45
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +22 -13
- package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
- package/dist/prompts/sandbox/data-profiler.js +159 -275
- package/dist/provenance/exec-frame.js +9 -3
- package/dist/runtime/boot.d.ts +7 -8
- package/dist/runtime/boot.js +7 -19
- package/dist/sandbox/client.d.ts +7 -0
- package/dist/sandbox/create-sandbox.js +1 -0
- package/dist/sandbox/docker-client.d.ts +1 -0
- package/dist/sandbox/docker-client.js +20 -15
- package/dist/sandbox/k8s-client.d.ts +6 -5
- package/dist/sandbox/k8s-client.js +55 -39
- package/dist/sandbox/reaper.d.ts +24 -13
- package/dist/sandbox/reaper.js +47 -14
- package/dist/sandbox/types.d.ts +6 -5
- package/dist/schemas/data-profile-schemas.d.ts +62 -0
- package/dist/schemas/data-profile-schemas.js +68 -2
- package/dist/state/data-profile.d.ts +7 -88
- package/dist/state/index.d.ts +1 -1
- package/dist/tasks/data-profile-activity.d.ts +8 -0
- package/dist/tasks/data-profile-activity.js +1 -0
- package/dist/tasks/data-profile-index.d.ts +45 -0
- package/dist/tasks/data-profile-index.js +134 -0
- package/dist/tasks/data-profile.d.ts +8 -23
- package/dist/tasks/data-profile.js +150 -117
- package/dist/tools/define-tool.d.ts +19 -8
- package/dist/tools/define-tool.js +28 -12
- package/dist/tools/report-session/examine-page.d.ts +22 -13
- package/dist/tools/report-session/examine-page.js +15 -10
- package/dist/tools/report-session/index.d.ts +1 -1
- package/dist/tools/research/generate-plan.js +3 -8
- package/dist/tools/research/inspect-data-profile.d.ts +30 -4
- package/dist/tools/research/inspect-data-profile.js +75 -20
- package/dist/tools/workspace/scan-inputs.d.ts +38 -0
- package/dist/tools/workspace/scan-inputs.js +61 -0
- package/dist/tools/workspace/workspace-search.d.ts +1 -1
- package/dist/tools/workspace/workspace-search.js +12 -9
- package/dist/workspace/filesystem.d.ts +27 -0
- package/dist/workspace/filesystem.js +27 -0
- package/package.json +1 -1
- package/dist/app/data-profile-policy.d.ts +0 -36
- package/dist/app/data-profile-policy.js +0 -37
- package/dist/memory/content-to-cortex.d.ts +0 -75
- package/dist/memory/content-to-cortex.js +0 -201
- package/dist/memory/conversation-display-backfill.d.ts +0 -23
- package/dist/memory/conversation-display-backfill.js +0 -91
- package/dist/memory/reconstruct-cards.d.ts +0 -27
- package/dist/memory/reconstruct-cards.js +0 -57
|
@@ -1,297 +1,181 @@
|
|
|
1
1
|
export const dataProfilerPrompt = `# Data Profiler Agent
|
|
2
2
|
|
|
3
|
-
You
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
You produce this dataset's **orientation record**: what the data IS, so that planning
|
|
4
|
+
can proceed. You do NOT perform quality control — that belongs to the analysis steps,
|
|
5
|
+
which run on the data with a question in hand.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
The rule that decides whether a check earns its place: it answers *what is this*, not
|
|
8
|
+
*is this good*. Whether a matrix holds raw or normalised counts is identity, and you
|
|
9
|
+
keep it. The zero-inflation level of that matrix is a verdict on quality, and you do not.
|
|
10
|
+
|
|
11
|
+
Your outputs guide automated analysis planning, so be explicit about what the data CAN
|
|
12
|
+
and CANNOT support.
|
|
13
|
+
|
|
14
|
+
## Orientation: the input scan
|
|
15
|
+
|
|
16
|
+
Your briefing carries a deterministic scan of the input tree, produced before your first
|
|
17
|
+
turn. It reports the tree's formats, the SHAPES its filenames form — sets of files whose
|
|
18
|
+
names differ only at marked positions — the distinct values each varying position takes,
|
|
19
|
+
how those positions co-occur, value overlap between shapes, and the files that share
|
|
20
|
+
structure with nothing else.
|
|
21
|
+
|
|
22
|
+
Read it first. It is the orientation pass, so listing the tree yourself only rediscovers
|
|
23
|
+
what you were handed.
|
|
24
|
+
|
|
25
|
+
The scan reports observations. It does not decide what the dataset is made of — that is
|
|
26
|
+
your judgement, and the next section is where you make it.
|
|
27
|
+
|
|
28
|
+
For exploration beyond the manifest:
|
|
29
|
+
|
|
30
|
+
- \`scan_inputs\` with a path re-scans a subtree, when you want to look at one directory
|
|
31
|
+
more closely or check a grouping you are unsure about.
|
|
32
|
+
- \`list_files\` with \`path: "data/inputs"\` lists the tree — \`path\` is its only
|
|
33
|
+
parameter, so recurse by calling it again on a subdirectory it returned.
|
|
9
34
|
|
|
10
35
|
Data files (count matrices, expression tables, large CSVs, genomic files) must be
|
|
11
|
-
processed programmatically. Do not \`read_file\` data files — they will exceed
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
re-derivation of work already done. To see the tree beyond the briefing's list,
|
|
25
|
-
call \`list_files\` with \`path: "data/inputs"\` — \`path\` is its only parameter.
|
|
26
|
-
To go deeper, call it again on a subdirectory it returned.
|
|
27
|
-
|
|
28
|
-
## Stage 1: Orient — Subject, Source, Design
|
|
29
|
-
|
|
30
|
-
BEFORE running format-specific profiling on individual data files, look
|
|
31
|
-
across ALL inputs to identify the experimental subject, the data source,
|
|
32
|
-
and the high-level design. Without these, downstream planning cannot
|
|
33
|
-
choose the right tools (per-organism gene mappings, species-appropriate
|
|
34
|
-
references, design-appropriate statistics).
|
|
36
|
+
processed programmatically. Do not \`read_file\` data files — they will exceed your
|
|
37
|
+
context window. Preview structure with \`head\`/\`wc -l\` via \`execute_command\`, or write
|
|
38
|
+
a Python script. R is available if a method has no adequate Python equivalent, but
|
|
39
|
+
default to Python.
|
|
40
|
+
|
|
41
|
+
Small metadata or config files are fine to \`read_file\` directly. Paper PDFs, READMEs,
|
|
42
|
+
and Word documents need a parser — \`pypdf\` and \`python-docx\` are available.
|
|
43
|
+
|
|
44
|
+
## Stage 1: Identity — subject, source, design
|
|
45
|
+
|
|
46
|
+
Identify the experimental subject, the data source, and the high-level design. Without
|
|
47
|
+
these, downstream planning cannot choose the right tools (per-organism gene mappings,
|
|
48
|
+
species-appropriate references, design-appropriate statistics).
|
|
35
49
|
|
|
36
50
|
What to identify:
|
|
37
51
|
|
|
38
|
-
1. **Organism + NCBI taxon ID** — REQUIRED for every dataset. Fill the
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
Where to look (in this order):
|
|
52
|
+
1. **Organism + NCBI taxon ID** — REQUIRED for every dataset. Fill the \`organism\`
|
|
53
|
+
field with \`{scientificName, taxonId, source, confidence}\`. Use \`null\` ONLY when
|
|
54
|
+
no input identifies the organism; never guess from gene-symbol patterns alone (HGNC
|
|
55
|
+
symbols are widely shared with orthologs and do NOT prove human).
|
|
56
|
+
2. **Tissue / cell type / condition** — when applicable. Fill the matching fields.
|
|
57
|
+
3. **Public accessions** — GEO (\`GSE\`/\`GSM\`), SRA (\`SRP\`/\`SRR\`/\`SRX\`),
|
|
58
|
+
BioProject (\`PRJNA\`/\`PRJEB\`/\`PRJDB\`), ArrayExpress (\`E-MTAB-xxxx\`), dbGaP
|
|
59
|
+
(\`phs\`), EGA (\`EGAS\`/\`EGAD\`). Collect into \`accessions\`.
|
|
60
|
+
4. **High-level experimental design** — case/control, dose-response, time-course,
|
|
61
|
+
paired/longitudinal, group sizes. Goes into \`experimentalDesign\`.
|
|
62
|
+
|
|
63
|
+
The scan's detected axes and their cardinalities are design evidence: 1171 × 3 × 2 across
|
|
64
|
+
three varying positions is a longitudinal design with replicates, stated in the filenames.
|
|
65
|
+
Read them before you conclude the design is undocumented.
|
|
66
|
+
|
|
67
|
+
Where else to look (in this order):
|
|
54
68
|
|
|
55
69
|
- **Sample-sheet / metadata files** (\`metadata.csv\`, \`samplesheet.tsv\`,
|
|
56
|
-
\`*_meta.csv\`) — \`read_file\` for small (<1 MB) tabular files. Look for
|
|
57
|
-
|
|
58
|
-
\`
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **Filenames and folder structure** — accession prefixes
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
staged here, not that your data is that species, and an empty store
|
|
72
|
-
is a normal state that proves nothing either way.
|
|
70
|
+
\`*_meta.csv\`) — \`read_file\` for small (<1 MB) tabular files. Look for columns named
|
|
71
|
+
\`organism\`, \`taxon\`, \`taxon_id\`, \`species\`, \`tissue\`, \`cell_type\`,
|
|
72
|
+
\`condition\`, \`disease\`, \`arm\`, \`treatment\`, \`timepoint\`. The first few data
|
|
73
|
+
rows usually answer the subject question outright.
|
|
74
|
+
- **Document inputs** — paper PDFs, READMEs, methods documents. The abstract and methods
|
|
75
|
+
section of a paper typically state organism, tissue, and design in one paragraph.
|
|
76
|
+
Parse PDFs with \`pypdf\` (\`from pypdf import PdfReader\`) and Word documents with
|
|
77
|
+
\`python-docx\` (\`from docx import Document\`); read READMEs, Markdown, and plain text
|
|
78
|
+
with \`read_file\`.
|
|
79
|
+
- **Filenames and folder structure** — accession prefixes (\`GSE...\`, \`SRR...\`,
|
|
80
|
+
\`PRJNA...\`), organism shorthand (\`human_\`, \`hg38\`, \`mm10\`, \`macaque_\`, \`cyno_\`).
|
|
81
|
+
- **Reference store** — \`list_available_refs\` labels catalogued files with the organism
|
|
82
|
+
they describe. Query it for a candidate organism as corroboration only: a hit means
|
|
83
|
+
reference data for that species is staged here, not that your data is that species, and
|
|
84
|
+
an empty store is a normal state that proves nothing either way.
|
|
73
85
|
|
|
74
86
|
How to record what you find:
|
|
75
87
|
|
|
76
|
-
- Set \`source\` honestly to the most-direct evidence
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
- Quality score distribution (FASTQ: per-base and per-read)
|
|
140
|
-
- N-base / ambiguous base content
|
|
141
|
-
|
|
142
|
-
### Annotations (\`.gff\`, \`.gtf\`, \`.bed\`)
|
|
143
|
-
- Feature type distribution and counts
|
|
144
|
-
- Chromosome/contig coverage
|
|
145
|
-
- Gene model statistics (exons per gene, transcript isoforms)
|
|
146
|
-
- Attribute completeness
|
|
147
|
-
|
|
148
|
-
### Chemical Structure Data (\`.sdf\`, \`.mol\`, CSV/TSV with SMILES)
|
|
149
|
-
For SDF/MOL files:
|
|
150
|
-
- Molecule count and property fields present in the data block
|
|
151
|
-
- 3D coordinate presence (2D vs 3D structures)
|
|
152
|
-
- Structure validity: parse with RDKit \`Chem.MolFromMolFile()\` or
|
|
153
|
-
\`Chem.SDMolSupplier()\`, report percentage of valid molecules
|
|
154
|
-
- Molecular weight distribution (median, min, max)
|
|
155
|
-
- Heavy atom count range
|
|
156
|
-
|
|
157
|
-
For CSV/TSV with SMILES columns:
|
|
158
|
-
- **Detection by name**: column named \`smiles\`, \`canonical_smiles\`, \`SMILES\`,
|
|
159
|
-
\`Canonical_SMILES\`, \`mol\`, \`structure\`, or \`compound_smiles\`
|
|
160
|
-
- **Detection by content**: if no named column found, check string columns
|
|
161
|
-
where >80% of non-empty values parse as valid molecules via
|
|
162
|
-
\`Chem.MolFromSmiles()\`. Flag confidence as heuristic-based.
|
|
163
|
-
- SMILES validity rate (percentage that parse successfully)
|
|
164
|
-
|
|
165
|
-
Activity data detection:
|
|
166
|
-
- Columns matching activity patterns: \`IC50\`, \`EC50\`, \`Ki\`, \`Kd\`, \`pIC50\`,
|
|
167
|
-
\`% inhibition\`, \`standard_value\`, \`standard_type\`
|
|
168
|
-
- Report activity type(s) and value range (min, max, median in nM)
|
|
169
|
-
|
|
170
|
-
Chemical profiling metrics to report in the file's \`metrics\` map. Every
|
|
171
|
-
value there must be a flat scalar (string, number, or boolean) — the schema
|
|
172
|
-
rejects arrays and nested objects, so record a range as two scalar keys, not
|
|
173
|
-
as a pair:
|
|
174
|
-
- \`molecule_count\`, \`valid_smiles_pct\`, \`mw_median\`, \`mw_min\`, \`mw_max\`
|
|
175
|
-
- \`has_activity_data\`, \`activity_type\`, \`activity_min_nM\`, \`activity_max_nM\`
|
|
176
|
-
- \`scaffold_count\` (Murcko generic scaffolds via RDKit)
|
|
177
|
-
- \`pains_hit_pct\` (PAINS filter hit rate via RDKit FilterCatalog)
|
|
178
|
-
|
|
179
|
-
Set \`domain: "cheminformatics"\` when molecular structures are the primary
|
|
180
|
-
data type. Subtypes: \`"compound-screening"\`, \`"structure-activity"\`,
|
|
181
|
-
\`"compound-library"\`, \`"molecular-properties"\`.
|
|
182
|
-
|
|
183
|
-
### Clinical Trial Data (SDTM/ADaM/General Clinical)
|
|
184
|
-
|
|
185
|
-
Clinical trial datasets often follow CDISC standards. Detect and profile:
|
|
186
|
-
|
|
187
|
-
**SDTM domain detection** — check column names for standard domain prefixes:
|
|
188
|
-
- DM (Demographics): STUDYID, USUBJID, AGE, SEX, RACE, ARM, ACTARM
|
|
189
|
-
- LB (Laboratory): LBTESTCD, LBORRES, LBORNRLO, LBORNRHI, LBSTRESU
|
|
190
|
-
- AE (Adverse Events): AETERM, AESEV, AESER, AEREL, AESTDTC, AEENDTC
|
|
191
|
-
- VS (Vital Signs): VSTESTCD, VSORRES, VSORRESU
|
|
192
|
-
- EC/EX (Exposure): ECDOSE, ECROUTE, ECFREQ, ECDOSFRM
|
|
193
|
-
- RS (Response): RSEVAL, RSCAT (RECIST), RSORRES
|
|
194
|
-
- PC (Pharmacoconcentrations): PCTEST, PCORRES, PCSTRESU, PCTPTNUM
|
|
195
|
-
|
|
196
|
-
**ADaM detection** — check for analysis-ready indicators:
|
|
197
|
-
- ADSL: one-row-per-subject (SUBJID, TRT01P, TRT01A, SAFFL, ITTFL)
|
|
198
|
-
- ADAE: one-row-per-AE with analysis flags
|
|
199
|
-
- ADLB: one-row-per-lab-assessment with AVAL, BASE, CHG
|
|
200
|
-
- ADTTE: time-to-event (AVAL=time, CNSR=censoring, PARAMCD=event)
|
|
201
|
-
- ADRS: tumor response (PARAMCD=OVRLRESP, AVALC=CR/PR/SD/PD)
|
|
202
|
-
|
|
203
|
-
**General clinical (non-CDISC):**
|
|
204
|
-
- Patient ID columns (check for consistent IDs across files)
|
|
205
|
-
- Treatment arm columns (randomization groups)
|
|
206
|
-
- Timepoint/visit structure (baseline, on-treatment, follow-up)
|
|
207
|
-
- Response classifications (if present)
|
|
208
|
-
- Censoring indicators (for survival/time-to-event data)
|
|
209
|
-
|
|
210
|
-
**Profile metrics for clinical data:**
|
|
211
|
-
- Subject count per treatment arm
|
|
212
|
-
- Visit completeness (% subjects with data at each visit)
|
|
213
|
-
- Missing data rate per variable
|
|
214
|
-
- Date range (first enrollment to last follow-up)
|
|
215
|
-
- Adverse event severity distribution (if AE data)
|
|
216
|
-
- Lab value ranges vs normal reference ranges (if LB data)
|
|
217
|
-
- Response rate per arm (if response data)
|
|
218
|
-
|
|
219
|
-
**Quality flags:**
|
|
220
|
-
- Non-standard variable names when CDISC structure is otherwise present
|
|
221
|
-
- Missing randomization/treatment arm information
|
|
222
|
-
- Inconsistent subject IDs across data files
|
|
223
|
-
- Missing baseline values for change-from-baseline analyses
|
|
224
|
-
- Censoring indicator present but not documented
|
|
225
|
-
|
|
226
|
-
### General Tabular Data
|
|
227
|
-
- Row and column counts, data types per column
|
|
228
|
-
- Missing value patterns and frequency
|
|
229
|
-
- Outlier detection for numeric columns
|
|
230
|
-
- Duplicate row detection
|
|
231
|
-
- Encoding issues (mixed types in columns, non-UTF8 characters)
|
|
232
|
-
|
|
233
|
-
### Document Inputs (\`.pdf\`, \`.docx\`, \`README\`, \`.md\`, \`.txt\`)
|
|
234
|
-
|
|
235
|
-
Documents commonly accompany datasets — published papers describing the
|
|
236
|
-
experiment, README files explaining the file layout, or methods
|
|
237
|
-
documents. They are PRIMARY sources for the Stage 1 orient pass and must
|
|
238
|
-
not be skipped.
|
|
239
|
-
|
|
240
|
-
- **PDFs**: parse with \`pypdf\` (\`from pypdf import PdfReader\`).
|
|
241
|
-
Extract text, then search for organism / species / taxon mentions,
|
|
242
|
-
accession patterns, and the methods/experimental-design paragraph.
|
|
243
|
-
Long papers — read the abstract and methods section, not the entire
|
|
244
|
-
body.
|
|
245
|
-
- **Word documents**: \`python-docx\` (\`from docx import Document\`).
|
|
246
|
-
- **READMEs / Markdown / plain text**: \`read_file\` directly.
|
|
247
|
-
- For each document, register it in \`files\` with
|
|
248
|
-
\`dataType: "document"\` and a one-sentence \`description\` of what
|
|
249
|
-
context it provides. Do NOT report row/col counts for documents.
|
|
250
|
-
|
|
251
|
-
## Quality Signals to Always Report
|
|
252
|
-
|
|
253
|
-
Regardless of format, flag these when present:
|
|
254
|
-
- **Batch structure** — are there batch labels? Do samples cluster by batch
|
|
255
|
-
in PCA rather than by biological condition?
|
|
256
|
-
- **Sample imbalance** — uneven group sizes that limit statistical power
|
|
257
|
-
- **Missing or malformed metadata** — sample annotations that are absent,
|
|
258
|
-
incomplete, or inconsistent with the data matrix
|
|
259
|
-
- **Unexpected zeros or NAs** — patterns suggesting technical dropout vs.
|
|
260
|
-
true biological absence
|
|
261
|
-
- **Normalization state** — is the data raw counts, normalized, or log-
|
|
262
|
-
transformed? Misidentifying this derails every downstream step.
|
|
263
|
-
|
|
264
|
-
## Single-Cell Extended Profiling
|
|
265
|
-
|
|
266
|
-
- For snRNA-seq data: also profile ribosomal gene fraction (pct_ribo), intronic read content, and ambient RNA contamination metrics.
|
|
267
|
-
|
|
268
|
-
## Scripting Standards
|
|
269
|
-
|
|
270
|
-
- Set random seeds for reproducibility in any sampling or statistical operations.
|
|
88
|
+
- Set \`source\` honestly to the most-direct evidence (\`user-context\` > \`metadata\` >
|
|
89
|
+
\`document\` > \`filename\` > \`inferred\`). \`user-context\` ranks highest because an
|
|
90
|
+
explicit user statement is direct evidence, not inference.
|
|
91
|
+
- Set \`confidence\`: \`high\` for an explicit user statement, an organism column, or a
|
|
92
|
+
paper statement; \`medium\` for filename or accession-prefix signals; \`low\` for
|
|
93
|
+
inference from data content alone.
|
|
94
|
+
- If sources DISAGREE (paper says human, metadata column says mouse), pick the
|
|
95
|
+
most-trusted source, set \`confidence\` to \`low\`, and add the conflict to
|
|
96
|
+
\`qualityAssessment.concerns\`. Do not silently pick one.
|
|
97
|
+
|
|
98
|
+
## Stage 2: Grouping — the kinds this dataset is made of
|
|
99
|
+
|
|
100
|
+
Decide what the dataset is MADE OF and submit it as \`kinds\`. A kind is a repeating set
|
|
101
|
+
of files that are the same sort of thing: "per-patient variant calls", "the reference
|
|
102
|
+
transcriptome", "the sample sheet". A singleton is a kind of count 1 — there is no
|
|
103
|
+
threshold to reason about.
|
|
104
|
+
|
|
105
|
+
Your kinds need NOT match the scan's shapes:
|
|
106
|
+
|
|
107
|
+
- One shape may be **two kinds** — a position taking the values \`tumor\` and \`normal\`
|
|
108
|
+
is mechanically one shape, and analytically two arms. Split it when the values say so.
|
|
109
|
+
- Several shapes may be **one kind** — files serving the same analytical role under two
|
|
110
|
+
naming conventions are one kind.
|
|
111
|
+
- You may declare an axis the scan never saw, if a metadata sheet states it.
|
|
112
|
+
|
|
113
|
+
For each kind, state what ONE MEMBER represents (\`memberRepresents\`) as well as what
|
|
114
|
+
the set contains (\`description\`). These are different: "1171 VCF files" is the shape you
|
|
115
|
+
were handed; "one patient's somatic variant calls" is the decision only you can make.
|
|
116
|
+
|
|
117
|
+
Give each kind a \`pathPattern\` that actually matches its members. Coverage is computed by
|
|
118
|
+
matching your patterns against the scanned tree, so a pattern matching nothing records
|
|
119
|
+
the kind as covering nothing.
|
|
120
|
+
|
|
121
|
+
Label the \`axes\` — what varies across members. The scan reports that a position varies
|
|
122
|
+
and which values it takes; whether that is a subject, a timepoint, a treatment arm, or a
|
|
123
|
+
chromosome shard is not derivable from the values, and is yours to name.
|
|
124
|
+
|
|
125
|
+
Where a kind's description depends on content the scan did not capture, inspect **ONE**
|
|
126
|
+
example file of that kind — not one per member. A set whose names already match does not
|
|
127
|
+
become better understood by reading its 1171st member.
|
|
128
|
+
|
|
129
|
+
## Stage 3: Notable singletons
|
|
130
|
+
|
|
131
|
+
\`files\` is for the inputs that deserve individual prose — the metadata sheet, the
|
|
132
|
+
README, the paper, an outlier that fits no kind. Describe those well, because there are
|
|
133
|
+
few of them.
|
|
134
|
+
|
|
135
|
+
It is NOT a list of the dataset's files. The workspace filesystem is the authoritative
|
|
136
|
+
file list, and \`list_files\`, \`grep\`, and semantic search all read the live tree.
|
|
137
|
+
|
|
138
|
+
## Stage 4: Dataset-level concerns
|
|
139
|
+
|
|
140
|
+
Record dataset-wide findings in \`qualityAssessment\`, in the sense of "what a planner
|
|
141
|
+
must know before designing an analysis":
|
|
142
|
+
|
|
143
|
+
- **Completeness from the scan** — 1171 variant files against 1168 indexes names three
|
|
144
|
+
subjects missing a file. That costs a count, and it changes the plan.
|
|
145
|
+
- **Batch structure** — are there batch labels in the filenames or the metadata?
|
|
146
|
+
- **Sample imbalance** — uneven group sizes that limit statistical power.
|
|
147
|
+
- **Missing or malformed metadata** — annotations absent, incomplete, or inconsistent
|
|
148
|
+
with the data.
|
|
149
|
+
- **Normalization state** — raw counts, normalized, or log-transformed. Misidentifying
|
|
150
|
+
this derails every downstream step; it is identity, not quality.
|
|
271
151
|
|
|
272
152
|
## Submitting Results
|
|
273
153
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
the expected schema; if validation fails you will see the errors and can
|
|
278
|
-
fix and re-submit.
|
|
154
|
+
Call \`submit_profile\` exactly once, after the work above is done. This is the ONLY way
|
|
155
|
+
to deliver results — do not return JSON in your message text. The tool validates against
|
|
156
|
+
the schema; if validation fails you will see the errors and can fix and re-submit.
|
|
279
157
|
|
|
280
|
-
|
|
281
|
-
|
|
158
|
+
The schema caps \`kinds\` and \`files\`. If you hit a cap, you are enumerating members
|
|
159
|
+
where you should be grouping them.
|
|
282
160
|
|
|
283
161
|
## Do NOT
|
|
284
162
|
|
|
163
|
+
- Profile file by file. The scan already enumerated the tree; your job is to say what it
|
|
164
|
+
IS, and one programmatic pass per input file is what this design exists to remove.
|
|
165
|
+
- Enumerate a kind's members in your output — no member lists, no per-file records for
|
|
166
|
+
files that belong to a kind.
|
|
167
|
+
- Decode a file in full. Read a header, a first record, a page — a bounded prefix.
|
|
168
|
+
- Compute per-file statistical quality measures. Specifically NOT: transition/transversion
|
|
169
|
+
ratios, allele-frequency spectra, replicate correlation, principal-component outlier
|
|
170
|
+
detection, coverage depth, mapping rate, duplicate rate, insert-size distribution, or GC
|
|
171
|
+
bias. These require decoding files in full, no consumer of the profile reads them, and
|
|
172
|
+
they answer *is this good* rather than *what is this*.
|
|
173
|
+
- \`read_file\` a data file. Preview it programmatically instead.
|
|
174
|
+
- Guess the organism. If no input identifies it, set \`organism: null\` and explain in
|
|
175
|
+
\`analysisSummary\`. Inferring "human" from gene symbols alone is wrong — orthologs
|
|
176
|
+
share symbols across species.
|
|
177
|
+
- Skip document inputs (PDFs, READMEs, DOCX). They carry the subject and design context
|
|
178
|
+
and are a primary source for Stage 1.
|
|
285
179
|
- Use \`print()\` for status messages — use the \`logging\` module.
|
|
286
|
-
-
|
|
287
|
-
- Skip Stage 1 orientation. Even if every input looks like a data file,
|
|
288
|
-
check filenames, headers, and any embedded metadata for organism /
|
|
289
|
-
accession signals.
|
|
290
|
-
- Guess the organism. If no input identifies it, set \`organism: null\`
|
|
291
|
-
and explain in \`analysisSummary\`. Inferring "human" from gene symbols
|
|
292
|
-
alone is wrong — orthologs share symbols across species.
|
|
293
|
-
- Skip document inputs (PDFs, READMEs, DOCX). They carry the subject and
|
|
294
|
-
design context and are the primary source for Stage 1.
|
|
295
|
-
- Return profiling results as JSON in your message text. Always use the
|
|
296
|
-
\`submit_profile\` tool.
|
|
180
|
+
- Return profiling results as JSON in your message text. Always use \`submit_profile\`.
|
|
297
181
|
`;
|
|
@@ -46,13 +46,19 @@ export function feedExecFrame(args) {
|
|
|
46
46
|
const cmdArgs = command.slice(1);
|
|
47
47
|
const code = exitCode ?? -1;
|
|
48
48
|
const duration = durationMs ?? 0;
|
|
49
|
+
// Resolved once so the read loop logs unconditionally instead of threading
|
|
50
|
+
// `?.` through every diagnostic.
|
|
51
|
+
const logger = (args.logger ?? createNoopLogger()).named("exec-frame");
|
|
49
52
|
if (!provenance || provenance.disabled) {
|
|
53
|
+
// The sandbox failed to start its tracker, so this command's file
|
|
54
|
+
// operations were never captured. The record below is empty rather than
|
|
55
|
+
// complete, and downstream nothing distinguishes the two — say so here or
|
|
56
|
+
// the gap ships looking like a command that touched no files.
|
|
57
|
+
if (provenance?.disabled)
|
|
58
|
+
logger.warn("sandbox reported provenance disabled — no file operations captured for this command", { command: cmd });
|
|
50
59
|
collector.recordCommandExecution(cmd, [...cmdArgs], code, duration, [], undefined, []);
|
|
51
60
|
return;
|
|
52
61
|
}
|
|
53
|
-
// Resolved once so the read loop logs unconditionally instead of threading
|
|
54
|
-
// `?.` through every diagnostic.
|
|
55
|
-
const logger = (args.logger ?? createNoopLogger()).named("exec-frame");
|
|
56
62
|
const commandReads = [];
|
|
57
63
|
for (const read of provenance.reads) {
|
|
58
64
|
const rel = stripMountPrefix(mountRoot, read.path);
|
package/dist/runtime/boot.d.ts
CHANGED
|
@@ -20,17 +20,16 @@
|
|
|
20
20
|
* misconfigured pool fails loudly at boot, not under load.
|
|
21
21
|
* 5. `assembleCoreRuntime(core)` — registers the durable-workflow cohort and
|
|
22
22
|
* builds the conversation agent (register-before-launch invariant).
|
|
23
|
-
* 6. `
|
|
24
|
-
* display envelope and freezes one for each legacy turn that has none, so
|
|
25
|
-
* the runtime read path never meets a row without a display projection.
|
|
26
|
-
* Runs AFTER assembly because migrating a legacy call's one-line detail
|
|
27
|
-
* needs the assembled conversation roster, embedder-contributed tools
|
|
28
|
-
* included; assembly starts no traffic, so this is still before any read.
|
|
29
|
-
* 7. `beforeLaunch()` — embedder hook for host-specific pre-launch work that
|
|
23
|
+
* 6. `beforeLaunch()` — embedder hook for host-specific pre-launch work that
|
|
30
24
|
* must attach before DBOS launch re-emits events (scheduled sweeps, an
|
|
31
25
|
* legacy-workflow reap, an agent-switch install). Runs after registration
|
|
32
26
|
* so it may close over the registered callables.
|
|
33
|
-
*
|
|
27
|
+
* 7. `launchDbos(...)` — the last registration-dependent step.
|
|
28
|
+
*
|
|
29
|
+
* No step reads or rewrites stored conversation display. A boot that validated
|
|
30
|
+
* every `messages` row is what let a single retired part key fail startup for a
|
|
31
|
+
* whole deployment; the read tolerates such a row by itself now
|
|
32
|
+
* (`parseStoredDisplayEnvelope`), which is where a per-row concern belongs.
|
|
34
33
|
*
|
|
35
34
|
* Boot-step errors PROPAGATE (the embedder's composition root catches them and
|
|
36
35
|
* releases whatever it acquired). Only `shutdown` swallows per-step failures —
|
package/dist/runtime/boot.js
CHANGED
|
@@ -20,27 +20,24 @@
|
|
|
20
20
|
* misconfigured pool fails loudly at boot, not under load.
|
|
21
21
|
* 5. `assembleCoreRuntime(core)` — registers the durable-workflow cohort and
|
|
22
22
|
* builds the conversation agent (register-before-launch invariant).
|
|
23
|
-
* 6. `
|
|
24
|
-
* display envelope and freezes one for each legacy turn that has none, so
|
|
25
|
-
* the runtime read path never meets a row without a display projection.
|
|
26
|
-
* Runs AFTER assembly because migrating a legacy call's one-line detail
|
|
27
|
-
* needs the assembled conversation roster, embedder-contributed tools
|
|
28
|
-
* included; assembly starts no traffic, so this is still before any read.
|
|
29
|
-
* 7. `beforeLaunch()` — embedder hook for host-specific pre-launch work that
|
|
23
|
+
* 6. `beforeLaunch()` — embedder hook for host-specific pre-launch work that
|
|
30
24
|
* must attach before DBOS launch re-emits events (scheduled sweeps, an
|
|
31
25
|
* legacy-workflow reap, an agent-switch install). Runs after registration
|
|
32
26
|
* so it may close over the registered callables.
|
|
33
|
-
*
|
|
27
|
+
* 7. `launchDbos(...)` — the last registration-dependent step.
|
|
28
|
+
*
|
|
29
|
+
* No step reads or rewrites stored conversation display. A boot that validated
|
|
30
|
+
* every `messages` row is what let a single retired part key fail startup for a
|
|
31
|
+
* whole deployment; the read tolerates such a row by itself now
|
|
32
|
+
* (`parseStoredDisplayEnvelope`), which is where a per-row concern belongs.
|
|
34
33
|
*
|
|
35
34
|
* Boot-step errors PROPAGATE (the embedder's composition root catches them and
|
|
36
35
|
* releases whatever it acquired). Only `shutdown` swallows per-step failures —
|
|
37
36
|
* once shutdown starts, exiting takes precedence (see `runShutdownSequence`).
|
|
38
37
|
*/
|
|
39
|
-
import { unwrapOrThrow } from "../lib/result.js";
|
|
40
38
|
import { SANDBOX_AGENT_META } from "../agents/sandbox/index.js";
|
|
41
39
|
import { validateAgentSkills } from "../agents/sandbox/validate-skills.js";
|
|
42
40
|
import { initCortexState } from "../state/init.js";
|
|
43
|
-
import { backfillConversationDisplayEnvelopes } from "../memory/conversation-display-backfill.js";
|
|
44
41
|
import { assembleCoreRuntime } from "./assemble.js";
|
|
45
42
|
import { assertConnectionBudget } from "./connection-budget.js";
|
|
46
43
|
import { launchDbos, shutdownDbos } from "./dbos.js";
|
|
@@ -57,15 +54,6 @@ export async function bootHarness(deps) {
|
|
|
57
54
|
await initCortexState(pool);
|
|
58
55
|
await assertConnectionBudget({ pool, logger, config: deps.connectionBudget });
|
|
59
56
|
const runtime = assembleCoreRuntime(core);
|
|
60
|
-
// Assembly registers `conversation` unconditionally, so this resolution can
|
|
61
|
-
// never refuse; `unwrapOrThrow` turns the impossible error branch into a
|
|
62
|
-
// boot-propagating throw rather than threading a Result through the boot
|
|
63
|
-
// sequence, whose steps already fail by propagation.
|
|
64
|
-
const conversationAgent = unwrapOrThrow(runtime.agents.forThread("conversation"));
|
|
65
|
-
await backfillConversationDisplayEnvelopes({
|
|
66
|
-
pool,
|
|
67
|
-
tools: conversationAgent.tools,
|
|
68
|
-
});
|
|
69
57
|
await deps.beforeLaunch?.();
|
|
70
58
|
await launchDbos({ config: deps.dbos, logger });
|
|
71
59
|
logger.named("boot").info("harness booted", { executorId: deps.dbos.executorId });
|
package/dist/sandbox/client.d.ts
CHANGED
|
@@ -68,6 +68,13 @@ export interface SandboxClient {
|
|
|
68
68
|
* dead sandboxes would race the synthetic-complete path.
|
|
69
69
|
*/
|
|
70
70
|
isAlive(ref: SandboxRef): Promise<SandboxLiveness>;
|
|
71
|
+
/**
|
|
72
|
+
* Liveness by id alone — the reaper path (see the harness-sandbox-exec spec),
|
|
73
|
+
* which holds a `sandboxId` from the cluster sweep but no full `SandboxRef`.
|
|
74
|
+
* Same semantics and the same throwing contract as {@link SandboxClient.isAlive},
|
|
75
|
+
* which delegates to it.
|
|
76
|
+
*/
|
|
77
|
+
isAliveById(sandboxId: string): Promise<SandboxLiveness>;
|
|
71
78
|
/**
|
|
72
79
|
* DBOS step (`sandbox.teardown`). Deletes the K8s Job / removes the
|
|
73
80
|
* Docker container, clears the active-sandbox registry. Idempotent —
|
|
@@ -149,6 +149,7 @@ export function createSandboxClient(config) {
|
|
|
149
149
|
submitExec: async (ref, body) => submitExec(ref, body, config.submitDeps),
|
|
150
150
|
awaitExec: (ref, execId, emit, deadline) => awaitExec(ref, execId, emit, deadline, composeAwaitOptions(config.awaitOptions, transport, isAlive)),
|
|
151
151
|
isAlive,
|
|
152
|
+
isAliveById: async (sandboxId) => unwrapOrThrow(await ops.isAliveById(sandboxId)),
|
|
152
153
|
teardown,
|
|
153
154
|
teardownById: async (sandboxId) => unwrapOrThrow(await ops.teardownById(sandboxId)),
|
|
154
155
|
listManagedSandboxes: async () => unwrapOrThrow(await ops.listManagedSandboxes()),
|
|
@@ -91,5 +91,6 @@ export declare function createDockerSandboxOps(config: DockerClientConfig): {
|
|
|
91
91
|
teardown(ref: SandboxRef): ResultAsync<void, SandboxError>;
|
|
92
92
|
teardownById(sandboxId: string): ResultAsync<void, SandboxError>;
|
|
93
93
|
isAlive(ref: SandboxRef): ResultAsync<SandboxLiveness, SandboxError>;
|
|
94
|
+
isAliveById(sandboxId: string): ResultAsync<SandboxLiveness, SandboxError>;
|
|
94
95
|
listManagedSandboxes(): ResultAsync<ManagedSandbox[], SandboxError>;
|
|
95
96
|
};
|