@inflexa-ai/harness 0.46.0 → 0.47.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/README.md +1 -1
- package/dist/agents/conversation-agent.d.ts +3 -8
- package/dist/agents/conversation-agent.js +24 -4
- package/dist/agents/report-session-agent.d.ts +11 -14
- package/dist/agents/report-session-agent.js +30 -17
- package/dist/agents/sandbox/shared.d.ts +18 -13
- package/dist/agents/sandbox/shared.js +42 -27
- package/dist/agents/sandbox/types.d.ts +1 -1
- package/dist/agents/sandbox-catalog.d.ts +2 -0
- package/dist/agents/sandbox-catalog.js +30 -1
- package/dist/app/chat-turn-workflow.js +5 -6
- package/dist/app/synthesize-run.d.ts +10 -6
- package/dist/app/synthesize-run.js +4 -2
- package/dist/contracts/analogy-report.d.ts +46 -2
- package/dist/contracts/analogy-report.js +31 -25
- package/dist/contracts/chat-parts.d.ts +3 -14
- package/dist/contracts/report-reference.d.ts +2 -1
- package/dist/contracts/report-reference.js +2 -1
- package/dist/contracts/schemas/chat-parts.d.ts +0 -27
- package/dist/contracts/schemas/chat-parts.js +1 -3
- package/dist/execution/run-canceler.d.ts +2 -0
- package/dist/execution/run-canceler.js +9 -0
- package/dist/execution/run-synthesis.d.ts +36 -8
- package/dist/execution/run-synthesis.js +114 -32
- package/dist/index.d.ts +2 -5
- package/dist/index.js +3 -6
- package/dist/input-scan/enrich.d.ts +5 -10
- package/dist/input-scan/enrich.js +12 -8
- package/dist/lib/hooks.d.ts +9 -0
- package/dist/lib/hooks.js +6 -1
- package/dist/lib/markdown-pdf.d.ts +27 -0
- package/dist/lib/markdown-pdf.js +236 -0
- package/dist/lib/metrics.d.ts +31 -0
- package/dist/lib/metrics.js +64 -0
- package/dist/lib/pdf-text.d.ts +23 -0
- package/dist/lib/pdf-text.js +34 -0
- package/dist/lib/regulatory-corpus/fetch-fda-guidance.js +3 -5
- package/dist/lib/regulatory-corpus/fetch-ich.js +3 -5
- package/dist/loop/run-loop.d.ts +5 -0
- package/dist/loop/run-loop.js +30 -2
- package/dist/loop/sub-agent.js +5 -6
- package/dist/loop/tool-name-repair.d.ts +11 -0
- package/dist/loop/tool-name-repair.js +23 -0
- package/dist/loop/turn-credentials.d.ts +5 -0
- package/dist/loop/turn-credentials.js +17 -0
- package/dist/loop/types.d.ts +14 -0
- package/dist/memory/card-builders.d.ts +1 -1
- package/dist/prompts/SOUL.d.ts +6 -6
- package/dist/prompts/SOUL.js +22 -121
- package/dist/prompts/analogical-reasoner.d.ts +1 -1
- package/dist/prompts/analogical-reasoner.js +35 -101
- package/dist/prompts/briefing.d.ts +20 -11
- package/dist/prompts/briefing.js +36 -19
- package/dist/prompts/conversation.d.ts +1 -1
- package/dist/prompts/conversation.js +103 -383
- package/dist/prompts/planner.d.ts +1 -5
- package/dist/prompts/planner.js +45 -128
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +26 -57
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +3 -3
- package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/cheminformatics-agent.js +12 -47
- package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
- package/dist/prompts/sandbox/chromatin-agent.js +4 -5
- package/dist/prompts/sandbox/data-profiler.js +11 -34
- package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
- package/dist/prompts/sandbox/dna-methylation-agent.js +3 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
- package/dist/prompts/sandbox/drug-repurposing-agent.js +23 -73
- package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
- package/dist/prompts/sandbox/enrichment-agent.js +3 -1
- package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
- package/dist/prompts/sandbox/genomic-variant-agent.js +3 -4
- package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/immune-profiling-agent.js +5 -4
- package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/metabolomics-agent.js +3 -1
- package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
- package/dist/prompts/sandbox/microbiome-agent.js +3 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multi-omics-integration-agent.js +3 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
- package/dist/prompts/sandbox/multimodal-sc-agent.js +3 -1
- package/dist/prompts/sandbox/network-agent.d.ts +1 -1
- package/dist/prompts/sandbox/network-agent.js +3 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.d.ts +1 -1
- package/dist/prompts/sandbox/pkpd-clinical-response-agent.js +4 -7
- package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/proteomics-agent.js +3 -1
- package/dist/prompts/sandbox/scientific-executor.d.ts +1 -1
- package/dist/prompts/sandbox/scientific-executor.js +0 -12
- package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
- package/dist/prompts/sandbox/single-cell-agent.js +3 -1
- package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
- package/dist/prompts/sandbox/spatial-omics-agent.js +3 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
- package/dist/prompts/sandbox/statistical-modeling-agent.js +4 -4
- package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
- package/dist/prompts/sandbox/translational-safety-agent.js +10 -29
- package/dist/prompts/sandbox-standards.d.ts +15 -18
- package/dist/prompts/sandbox-standards.js +96 -305
- package/dist/prompts/synthesis-agent.d.ts +1 -1
- package/dist/prompts/synthesis-agent.js +24 -90
- package/dist/provenance/collector.d.ts +2 -5
- package/dist/provenance/collector.js +2 -5
- package/dist/provenance/seam.d.ts +36 -1
- package/dist/provenance/workspace-reads.d.ts +36 -0
- package/dist/provenance/workspace-reads.js +33 -0
- package/dist/providers/request-headers.js +12 -3
- package/dist/report-model/production-resolver.d.ts +22 -52
- package/dist/report-model/production-resolver.js +43 -112
- package/dist/report-render/chart-export.d.ts +9 -0
- package/dist/report-render/chart-export.js +1 -1
- package/dist/report-render/views/chart-view.d.ts +1 -0
- package/dist/report-render/views/chart-view.js +1 -0
- package/dist/report-render/views/lineage.d.ts +1 -0
- package/dist/report-render/views/page-view.d.ts +1 -0
- package/dist/report-render/views/page-view.js +1 -0
- package/dist/report-render/views/prose.d.ts +1 -0
- package/dist/report-render/views/prose.js +1 -0
- package/dist/report-render/views/references-view.d.ts +1 -0
- package/dist/report-render/views/values.d.ts +1 -0
- package/dist/report-render/views/values.js +1 -0
- package/dist/runtime/assemble.d.ts +20 -9
- package/dist/runtime/assemble.js +47 -38
- package/dist/sandbox/client.d.ts +5 -3
- package/dist/sandbox/create-sandbox.d.ts +7 -12
- package/dist/sandbox/create-sandbox.js +15 -37
- package/dist/sandbox/docker-client.d.ts +1 -3
- package/dist/sandbox/docker-client.js +3 -5
- package/dist/sandbox/exec-outcome.d.ts +11 -11
- package/dist/sandbox/exec-outcome.js +22 -22
- package/dist/sandbox/exec.d.ts +5 -0
- package/dist/sandbox/exec.js +9 -1
- package/dist/sandbox/identity.d.ts +4 -16
- package/dist/sandbox/identity.js +5 -21
- package/dist/sandbox/k8s-client.d.ts +0 -1
- package/dist/sandbox/k8s-client.js +8 -13
- package/dist/sandbox/lease-names.d.ts +6 -0
- package/dist/sandbox/lease-names.js +12 -0
- package/dist/sandbox/leases.d.ts +105 -0
- package/dist/sandbox/leases.js +519 -0
- package/dist/sandbox/liveness.d.ts +5 -2
- package/dist/sandbox/mount-plan.d.ts +10 -1
- package/dist/sandbox/mount-plan.js +7 -1
- package/dist/sandbox/reconciler.d.ts +58 -0
- package/dist/sandbox/reconciler.js +153 -0
- package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
- package/dist/sandbox/types.d.ts +25 -18
- package/dist/sandbox/types.js +10 -4
- package/dist/schemas/plan-schemas.d.ts +0 -21
- package/dist/schemas/plan-schemas.js +2 -3
- package/dist/schemas/run-synthesis.d.ts +2 -2
- package/dist/schemas/run-synthesis.js +3 -3
- package/dist/schemas/validate-plan.d.ts +1 -14
- package/dist/schemas/validate-plan.js +5 -24
- package/dist/schemas/workflow-state.d.ts +3 -32
- package/dist/schemas/workflow-state.js +4 -13
- package/dist/state/index.d.ts +0 -1
- package/dist/state/index.js +0 -1
- package/dist/state/migrations/20261030120000_lease_the_sandboxes.d.ts +7 -0
- package/dist/state/migrations/20261030120000_lease_the_sandboxes.js +34 -0
- package/dist/state/migrations/20261030120100_drop_the_report_derivations.d.ts +5 -0
- package/dist/state/migrations/20261030120100_drop_the_report_derivations.js +9 -0
- package/dist/state/migrations/20261030120200_keep_the_report_derivations.d.ts +6 -0
- package/dist/state/migrations/20261030120200_keep_the_report_derivations.js +10 -0
- package/dist/state/migrations/index.js +6 -0
- package/dist/state/purge-analysis.d.ts +4 -2
- package/dist/state/purge-analysis.js +22 -11
- package/dist/state/sandbox-leases.d.ts +81 -0
- package/dist/state/sandbox-leases.js +247 -0
- package/dist/state/schema.d.ts +1 -13
- package/dist/state/schema.js +1 -6
- package/dist/state/step-executions.d.ts +0 -2
- package/dist/state/step-executions.js +1 -4
- package/dist/tasks/data-profile.d.ts +40 -2
- package/dist/tasks/data-profile.js +89 -87
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +6 -1
- package/dist/tools/ad-hoc-router.d.ts +1 -6
- package/dist/tools/ad-hoc-router.js +5 -48
- package/dist/tools/bio/comptox.js +1 -1
- package/dist/tools/bio/drug-gene-interactions.js +1 -1
- package/dist/tools/bio/gene-disease-evidence.js +1 -1
- package/dist/tools/bio/keys.d.ts +1 -1
- package/dist/tools/bio/pubmed.js +31 -0
- package/dist/tools/bio/search-gene.js +17 -0
- package/dist/tools/bio/search-geo-datasets.js +13 -0
- package/dist/tools/bio/search-regulatory-approvals.js +1 -1
- package/dist/tools/define-tool.d.ts +25 -2
- package/dist/tools/define-tool.js +11 -1
- package/dist/tools/display/show-user.js +1 -1
- package/dist/tools/execute-analysis.d.ts +1 -3
- package/dist/tools/execute-analysis.js +5 -33
- package/dist/tools/report-session/index.d.ts +0 -1
- package/dist/tools/report-session/index.js +0 -1
- package/dist/tools/report-session/script-tools.d.ts +30 -0
- package/dist/tools/report-session/script-tools.js +177 -0
- package/dist/tools/research/generate-analogy-report.d.ts +16 -9
- package/dist/tools/research/generate-analogy-report.js +111 -49
- package/dist/tools/research/generate-plan.d.ts +102 -7
- package/dist/tools/research/generate-plan.js +74 -43
- package/dist/tools/research/index.d.ts +4 -3
- package/dist/tools/research/index.js +4 -3
- package/dist/tools/research/inspect-run.d.ts +0 -1
- package/dist/tools/research/inspect-run.js +5 -10
- package/dist/tools/research/search-arxiv.js +15 -0
- package/dist/tools/research/search-github-repos.js +13 -0
- package/dist/tools/research/search-semantic-scholar.js +16 -0
- package/dist/tools/research/synthesis-lookups.d.ts +21 -0
- package/dist/tools/research/synthesis-lookups.js +29 -0
- package/dist/tools/research/web-fetch.d.ts +1 -1
- package/dist/tools/research/web-fetch.js +14 -12
- package/dist/tools/sandbox/lease-tools.d.ts +32 -0
- package/dist/tools/sandbox/lease-tools.js +60 -0
- package/dist/tools/script/codemode-worker.d.ts +5 -0
- package/dist/tools/script/codemode-worker.js +5 -0
- package/dist/tools/script/file-tools.d.ts +100 -0
- package/dist/tools/script/file-tools.js +377 -0
- package/dist/tools/script/metrics.d.ts +21 -0
- package/dist/tools/script/metrics.js +38 -0
- package/dist/tools/script/quickjs.wasm +0 -0
- package/dist/tools/script/run-script.d.ts +76 -0
- package/dist/tools/script/run-script.js +326 -0
- package/dist/tools/script/scratch.d.ts +81 -0
- package/dist/tools/script/scratch.js +142 -0
- package/dist/tools/start-report-session.js +1 -1
- package/dist/tools/workspace/edit-file.js +2 -1
- package/dist/tools/workspace/execute-command.d.ts +9 -13
- package/dist/tools/workspace/execute-command.js +23 -19
- package/dist/tools/workspace/file-stat.js +1 -1
- package/dist/tools/workspace/grep.d.ts +5 -2
- package/dist/tools/workspace/grep.js +19 -10
- package/dist/tools/workspace/mutator.d.ts +48 -4
- package/dist/tools/workspace/mutator.js +43 -12
- package/dist/tools/workspace/read-file.d.ts +5 -2
- package/dist/tools/workspace/read-file.js +15 -11
- package/dist/tools/workspace/read-surface.d.ts +17 -0
- package/dist/tools/workspace/read-surface.js +17 -0
- package/dist/tools/workspace/result-bounds.d.ts +1 -0
- package/dist/tools/workspace/run-exec.d.ts +12 -13
- package/dist/tools/workspace/run-exec.js +13 -13
- package/dist/tools/workspace/scan-inputs.d.ts +2 -5
- package/dist/tools/workspace/scan-inputs.js +2 -3
- package/dist/tools/workspace/show-file.js +1 -1
- package/dist/tools/workspace/show-plan.js +4 -3
- package/dist/tools/workspace/write-file.js +2 -1
- package/dist/workflows/execute-analysis-scheduler.d.ts +0 -26
- package/dist/workflows/execute-analysis-scheduler.js +12 -32
- package/dist/workflows/execute-analysis.d.ts +17 -35
- package/dist/workflows/execute-analysis.js +13 -107
- package/dist/workflows/pause.js +29 -22
- package/dist/workflows/sandbox-step.d.ts +16 -31
- package/dist/workflows/sandbox-step.js +36 -71
- package/dist/workflows/test/sql-writes.d.ts +0 -1
- package/dist/workflows/test/sql-writes.js +0 -2
- package/dist/workspace/filesystem.d.ts +2 -2
- package/dist/workspace/filesystem.js +10 -5
- package/dist/workspace/paths.d.ts +19 -1
- package/dist/workspace/paths.js +22 -1
- package/package.json +6 -3
- package/dist/prompts/literature-reviewer.d.ts +0 -1
- package/dist/prompts/literature-reviewer.js +0 -114
- package/dist/sandbox/reaper.d.ts +0 -81
- package/dist/sandbox/reaper.js +0 -161
- package/dist/sandbox/step-sandbox.d.ts +0 -47
- package/dist/sandbox/step-sandbox.js +0 -53
- package/dist/state/active-sandboxes.d.ts +0 -33
- package/dist/state/active-sandboxes.js +0 -65
- package/dist/tasks/extract-values-script.d.ts +0 -64
- package/dist/tasks/extract-values-script.js +0 -180
- package/dist/tasks/extract-values.d.ts +0 -77
- package/dist/tasks/extract-values.js +0 -146
- package/dist/tools/report-session/derive-table.d.ts +0 -164
- package/dist/tools/report-session/derive-table.js +0 -419
- package/dist/tools/research/literature-reviewer.d.ts +0 -42
- package/dist/tools/research/literature-reviewer.js +0 -107
- package/dist/workflows/metrics.d.ts +0 -23
- package/dist/workflows/metrics.js +0 -38
package/dist/prompts/briefing.js
CHANGED
|
@@ -24,8 +24,10 @@
|
|
|
24
24
|
import { DATA_PROFILE_ORIENTATION_MAX_CHARS, buildDataProfileOrientation } from "../app/data-profile-orientation.js";
|
|
25
25
|
import { WORKING_MEMORY_LIMITS } from "../memory/working-memory.js";
|
|
26
26
|
// ── Bounds ────────────────────────────────────────────────────────────
|
|
27
|
-
/** Completed dependencies rendered as upstream blocks; the tail is
|
|
27
|
+
/** Completed dependencies rendered as upstream blocks; the tail is listed by its paths. */
|
|
28
28
|
export const MAX_UPSTREAM_DEPS = 5;
|
|
29
|
+
/** Completed dependencies past the blocks, listed one line each by their paths; the tail is counted. */
|
|
30
|
+
export const MAX_LISTED_UPSTREAM_DEPS = 20;
|
|
29
31
|
/** Characters of each dependency's summary carried in the seed — the gist, not the document. */
|
|
30
32
|
export const UPSTREAM_SUMMARY_MAX_CHARS = 500;
|
|
31
33
|
/** Artifact paths listed per dependency; the rest are reachable from its output directory. */
|
|
@@ -53,9 +55,7 @@ export const STEP_TASK_FIELDS = [
|
|
|
53
55
|
* threaded separately through the workflow input, execution knobs, and result
|
|
54
56
|
* fields populated after the step runs. `depends_on` is not rendered here
|
|
55
57
|
* because the dependencies appear as {@link renderUpstream} blocks — with their
|
|
56
|
-
* results — rather than as bare ids.
|
|
57
|
-
* {@link renderResources} section, because the budget is an execution bound,
|
|
58
|
-
* not a task instruction.
|
|
58
|
+
* results — rather than as bare ids.
|
|
59
59
|
*/
|
|
60
60
|
export const STEP_NON_TASK_FIELDS = [
|
|
61
61
|
"id",
|
|
@@ -63,9 +63,7 @@ export const STEP_NON_TASK_FIELDS = [
|
|
|
63
63
|
"step_type",
|
|
64
64
|
"depends_on",
|
|
65
65
|
"status",
|
|
66
|
-
"resources",
|
|
67
66
|
"agent",
|
|
68
|
-
"timeout",
|
|
69
67
|
"maxSteps",
|
|
70
68
|
"summary",
|
|
71
69
|
"artifactIds",
|
|
@@ -165,10 +163,7 @@ function renderGrounding(grounding, contract) {
|
|
|
165
163
|
return lines.join("\n");
|
|
166
164
|
}
|
|
167
165
|
// ── (1b) Analysis memory ──────────────────────────────────────────────
|
|
168
|
-
/**
|
|
169
|
-
* The heading of the analysis-memory section. The orient core of the sandbox
|
|
170
|
-
* prompt names this same text, thus a test pins the two together.
|
|
171
|
-
*/
|
|
166
|
+
/** The heading of the analysis-memory section. */
|
|
172
167
|
export const ANALYSIS_MEMORY_HEADING = "Analysis memory (read only)";
|
|
173
168
|
/** A memory with no goal and no constraints — the section renders nothing. */
|
|
174
169
|
export function emptyStepMemory() {
|
|
@@ -205,6 +200,22 @@ export function renderMemory(memory) {
|
|
|
205
200
|
}
|
|
206
201
|
return section(ANALYSIS_MEMORY_HEADING, parts.join("\n\n"));
|
|
207
202
|
}
|
|
203
|
+
/** The most characters of the request that a seed carries. A request above it keeps its head. */
|
|
204
|
+
export const REQUEST_CHARS = 8000;
|
|
205
|
+
/**
|
|
206
|
+
* The request of the analysis, as the planner received it. A step agent never sees the conversation, thus
|
|
207
|
+
* this is its one source for what the user asked in the words of the user: a file name, a field, an allowed
|
|
208
|
+
* value, or the shape of an entry of a deliverable that the plan only names.
|
|
209
|
+
*/
|
|
210
|
+
export function renderRequest(request) {
|
|
211
|
+
const text = clamp((request ?? "").trim(), REQUEST_CHARS);
|
|
212
|
+
if (text.length === 0)
|
|
213
|
+
return "";
|
|
214
|
+
return section("The request of the analysis", "This step is one part of the plan that answers this request. Do the task of this step. " +
|
|
215
|
+
"When this step writes a deliverable that the request describes, the deliverable keeps the file name, the fields, and the values of the request. " +
|
|
216
|
+
"It goes to `output/` of your working directory, with the other results of the step, whatever directory the request names.\n\n" +
|
|
217
|
+
text);
|
|
218
|
+
}
|
|
208
219
|
/** A value as the render request carries it: JSON, thus `"apeglm"` and `10` cannot be confused. */
|
|
209
220
|
function slotValue(value) {
|
|
210
221
|
return JSON.stringify(value);
|
|
@@ -274,7 +285,7 @@ export function renderTemplateContract(brief) {
|
|
|
274
285
|
blocks.push(`Inputs the script reads:\n${bullets(brief.inputs.map((input) => `${input.name}: \`${input.path}\`${input.description ? ` — ${input.description}` : ""}`))}`);
|
|
275
286
|
}
|
|
276
287
|
if (brief.bound.length > 0) {
|
|
277
|
-
blocks.push(`Bound by the plan
|
|
288
|
+
blocks.push(`Bound by the plan:\n${bullets(brief.bound.map((setting) => `\`${setting.name}\` = ${slotValue(setting.value)} (${setting.source})`))}`);
|
|
278
289
|
}
|
|
279
290
|
if (brief.unbound_settings.length > 0) {
|
|
280
291
|
blocks.push(`Unbound settings (the plan states them, and no bound slot carries them):\n${bullets(brief.unbound_settings)}`);
|
|
@@ -290,7 +301,7 @@ export function renderWorkspace(frame) {
|
|
|
290
301
|
return "";
|
|
291
302
|
const analysisRoot = analysisRootOf(frame);
|
|
292
303
|
return section("Workspace", bullets([
|
|
293
|
-
`Working directory (writable, your cwd): \`${frame.workingDir}
|
|
304
|
+
`Working directory (writable, your cwd): \`${frame.workingDir}\``,
|
|
294
305
|
`Analysis root (read-only): \`${analysisRoot}\` — inputs at \`${analysisRoot}/data/inputs/\`, prior runs at \`${analysisRoot}/runs/\`.`,
|
|
295
306
|
]));
|
|
296
307
|
}
|
|
@@ -301,7 +312,8 @@ export function renderWorkspace(frame) {
|
|
|
301
312
|
* `os.cpu_count()` report the quota, thus the fork count is right by default.
|
|
302
313
|
* The thread pools default to one thread (see `sandbox/thread-env.ts`), and
|
|
303
314
|
* only the agent knows when a step is thread-parallel. Thus the briefing names
|
|
304
|
-
* the budget and the rule
|
|
315
|
+
* the budget and the rule with its number. The thread defaults and the way to
|
|
316
|
+
* raise a pool are in the system prompt, because they are the same for each step.
|
|
305
317
|
*/
|
|
306
318
|
export function renderResources(resources) {
|
|
307
319
|
if (!resources)
|
|
@@ -309,8 +321,6 @@ export function renderResources(resources) {
|
|
|
309
321
|
const cores = Math.max(1, Math.floor(resources.cpu));
|
|
310
322
|
const items = [
|
|
311
323
|
`CPU: ${resources.cpu} ${resources.cpu === 1 ? "core" : "cores"} (hard quota). Memory: ${resources.memoryGb} GB (hard limit — exceeding it kills the process).`,
|
|
312
|
-
`Core-count calls (\`parallel::detectCores()\`, \`os.cpu_count()\`) report this quota — worker counts sized from them are already right, nothing to raise.`,
|
|
313
|
-
`BLAS/OpenMP thread pools default to **1 thread** (\`OMP_NUM_THREADS\` etc.). For a thread-parallel single-process step, raise them per command via \`execute_command\`'s \`env\`, up to ${cores}.`,
|
|
314
324
|
`The one rule: workers × threads-per-worker must stay ≤ ${cores}. A mix is fine while the product holds.`,
|
|
315
325
|
];
|
|
316
326
|
if (resources.gpu)
|
|
@@ -336,9 +346,16 @@ export function renderUpstream(handoffs) {
|
|
|
336
346
|
return "";
|
|
337
347
|
const shown = handoffs.slice(0, MAX_UPSTREAM_DEPS);
|
|
338
348
|
const blocks = shown.map(renderHandoff);
|
|
339
|
-
const
|
|
340
|
-
if (
|
|
341
|
-
blocks.push(`
|
|
349
|
+
const listed = handoffs.slice(MAX_UPSTREAM_DEPS, MAX_UPSTREAM_DEPS + MAX_LISTED_UPSTREAM_DEPS);
|
|
350
|
+
if (listed.length > 0) {
|
|
351
|
+
blocks.push(`More completed dependencies:\n${bullets(listed.map((h) => `\`${h.stepId}\` (${h.agentId}): summary \`${h.summaryPath}\`, outputs \`${h.outputDir}\``))}`);
|
|
352
|
+
}
|
|
353
|
+
// The run is still running while this step runs, and a run-level lookup gives
|
|
354
|
+
// step paths only for a finished run. Thus the tail is found on disk: each
|
|
355
|
+
// step directory of the run is a sibling of the working directory.
|
|
356
|
+
const counted = handoffs.length - shown.length - listed.length;
|
|
357
|
+
if (counted > 0) {
|
|
358
|
+
blocks.push(`(+${counted} more completed ${counted === 1 ? "dependency" : "dependencies"}, not listed. The directory of each step of this run is beside your working directory, and it holds the summary of that step at \`output/summary.md\`.)`);
|
|
342
359
|
}
|
|
343
360
|
return section("Upstream results (these already ran — build on them, do not redo them)", blocks.join("\n\n"));
|
|
344
361
|
}
|
|
@@ -367,10 +384,10 @@ function renderHandoff(handoff) {
|
|
|
367
384
|
export function composeStepBriefing(briefing) {
|
|
368
385
|
return [
|
|
369
386
|
renderTask(briefing.step, briefing),
|
|
387
|
+
renderRequest(briefing.request),
|
|
370
388
|
renderTemplateContract(briefing.template),
|
|
371
389
|
renderMemory(briefing.memory),
|
|
372
390
|
renderWorkspace(briefing.workspace),
|
|
373
|
-
renderResources(briefing.step.resources),
|
|
374
391
|
renderOrientation(briefing.profile, briefing.workspace.analysisId),
|
|
375
392
|
renderUpstream(briefing.upstream),
|
|
376
393
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const conversationPrompt = "# Conversation Agent\n\nYou are the user-facing companion for a bioinformatics analysis platform.\nYou help researchers explore their data, plan and execute analyses, interpret\nresults, and generate testable hypotheses. You handle everything\nconversational \u2014 from simple lookups to multi-step scientific exploration.\n\n## Your Role\n\n1. **Answer directly** \u2014 data questions, bio-lookups, file exploration,\n general bioinformatics questions. Use your tools.\n2. **Plan and execute analyses** \u2014 orient in the workspace, generate plans\n via `generate_plan`, present plans via `show_plan`, execute via\n `execute_analysis`. For an explicitly requested targeted computation, use\n `execute_analysis` in ad hoc mode without generating a plan.\n3. **Interpret results** \u2014 after runs complete, read summaries and artifacts,\n synthesize findings, grade evidence, flag novelty.\n4. **Explore hypotheses** \u2014 investigate data, cross-reference with biology,\n generate testable hypotheses, refine through discussion.\n\n## Context Continuity\n\nYou are one agent handling the full conversation. Your tool call results\npersist across turns. If you searched the workspace, read a file, or\ngenerated a plan \u2014 those results are still in your context. Do not\nrepeat searches or re-orient when the information is already available\nfrom a prior turn.\n\nRe-orient only when:\n- Starting a conversation with no prior workspace exploration\n- The user asks about something not covered by prior searches\n- A new workflow run has completed since your last search\n\n## Data Discovery \u2014 Search First\n\nRoute by what you are asking for:\n\n1. **What the dataset IS** \u2192 `inspect_data_profile`. Do not re-derive these\n facts by reading the raw inputs.\n2. **Which files exist** \u2192 `workspace_search`, then `list_files`.\n3. **What is inside a file** \u2192 `read_file` on a path a search returned.\n\nDo not tell the user you cannot access their files \u2014 you can.\n\nWhen the user points to data by name or location that is not yet an input of\nthis analysis, adding it as an input may be available to you as a host tool.\nIf so: list the candidates, confirm with the user, and add them so they get\nprofiled. Never tell the user to copy files into a folder to make them\nvisible \u2014 reach for the input tool if you have one, or say plainly that the\ndata must be added as an input and let the host handle how.\n\n## Analysis Planning\n\nWhen the user wants to run an analysis:\n\n1. **Orient** \u2014 `inspect_data_profile` for the data context (organism, design,\n per-file types), `workspace_search` for prior run outputs, `inspect_run` for\n run history.\n2. **Generate the plan** \u2014 call `generate_plan` with the research question,\n any prior run results, and the user's constraints. The dataset's own facts\n (organism, domain, experimental design, condition names, quality concerns,\n per-file types and dimensions) are read server-side from the persisted data\n profile and handed to the planner directly \u2014 do not summarize or re-type\n them into the call. Use `analystNotes` only for facts the user told you\n that the profile cannot know (e.g. \"samples 3 and 7 were re-sequenced\").\n The tool returns a `planId` along with the plan on success.\n3. **Handle the response**:\n - **plan_complete** \u2192 present the plan via `show_plan({ planId })`\n using the `planId` from the tool return, and explain the analytical\n narrative in text. Ask for approval.\n - **clarification_needed** \u2192 relay the question to the user.\n - **error** \u2192 explain the issue and suggest alternatives.\n4. **Iterate** \u2014 if the user wants changes, call `generate_plan` again,\n passing the prior `planId` as `parentPlanId` and the user's feedback\n as `userConstraints`. This produces a new `planId` linked to the\n previous one.\n5. **Execute** \u2014 on approval, call\n `execute_analysis({ mode: \"plan\", planId })` with the\n approved `planId`. The tool resolves the plan server-side and starts\n the workflow. A record in the thread that says that the person approved a\n plan means that the run of that plan started, thus the plan needs no\n `execute_analysis` call.\n6. **Plan stale / invalid?** If `execute_analysis` fails because the plan is\n not found, is malformed, or fails validation, or `show_plan` returns\n `shown: false` with `reason: \"plan_not_found\"`, the `planId` is no longer\n valid. Regenerate via `generate_plan` and present the new plan for\n approval, because a retry of the same `planId` fails the same way.\n\nThe workflow runs autonomously \u2014 you do not monitor or evaluate it. A launch\nresult with `status: \"in_progress\"` means exactly that; do not infer\ncompletion from the tool call returning.\n\n## Ad Hoc Analysis\n\nWhen the user explicitly asks you to run, compute, test, compare, or otherwise\nexecute one targeted computation, call\n`execute_analysis({ mode: \"adhoc\", request })` with their exact request. Their\nexplicit computational instruction is consent: do not generate or present a\nsynthetic plan and do not ask for a second approval. The tool automatically\nselects the sandbox specialist and resources; never add or invent an agent id.\n\nIf computation is only your suggestion \u2014 the user asked a conceptual question\nand did not ask you to execute anything \u2014 ask for consent before calling the\ntool. Ad hoc runs are asynchronous, writable, durable analysis runs. Retrieve\ntheir results later with `inspect_run`. If the user explicitly asks you to\nwait or check whether a run finishes, you may make one bounded\n`inspect_run({ runId, waitForTerminalSeconds })` call in that turn (maximum\n30 seconds). If it returns `inspectionState: \"in_progress\"` at the cutoff,\nstop polling and tell the user it is still running. Never loop on\n`inspect_run`; otherwise inspect on a later turn.\n\n## Interpreting Results\n\nAfter a run completes, the workflow automatically produces two types of output:\n- **A step summary**, one for each step \u2014 computational findings, method\n choices, quality assessment. Pure facts, no literature.\n- **A run synthesis**, one for the run \u2014 the integrated interpretation:\n conclusions, selective key findings, biological themes, limitations, and\n literature references. A run produces one only when it had summaries to\n integrate and it hit no blocker.\n\nTo interpret results:\n\n1. **Check whether the run produced a synthesis** \u2014 `inspect_run({ runId })`\n reports the `synthesisStatus` of the run, and it gives a `synthesisPath`\n only when that status is `produced`. The synthesis is your primary source\n when it exists. When it was skipped or failed, read the step summaries and\n integrate the findings yourself.\n2. **Read the synthesis** \u2014 when present, it has conclusions (the \"so what\"),\n selective key findings graded by novelty, biological themes, and\n explicit limitations with key references.\n3. **Read step summaries for detail** \u2014 when the synthesis references a finding,\n read the summary of that step for the full evidence basis\n (metrics, methods, quality assessment).\n4. **Dig deeper on specific findings** \u2014 for follow-up questions, use your\n bio-lookup tools directly to investigate beyond what the synthesis\n already covers.\n\nGroup findings by biological theme (e.g., immune response, metabolic\nchanges) rather than by analysis step. Clearly separate well-supported\nfindings from speculative interpretations. Every conclusion must reference\nspecific quantitative results from the step summaries.\n\n## Translational Assessment\n\nWhen interpreting results that have translational implications (therapeutic\ntargets, biomarkers, patient stratification, safety signals):\n\n1. **Check translationalRelevance** \u2014 if the synthesis includes\n translationalRelevance on findings, present the stage and actionType\n to the user. Group findings by translational category (targets,\n biomarkers, safety) rather than by analysis step.\n\n2. **Ground targets in existing therapeutics** \u2014 for findings flagged as\n therapeutic-target or mechanism-of-action, check whether approved drugs\n or clinical-stage compounds already exist for the target, and present\n the competitive landscape.\n\n3. **Distinguish predictive from prognostic** \u2014 when presenting biomarker\n findings, always clarify: a predictive biomarker says \"this patient\n will respond to treatment X\" (requires treatment x marker interaction);\n a prognostic biomarker says \"this patient has better/worse outcome\n regardless of treatment.\" Conflating these is a common error.\n\n4. **Flag translational gaps** \u2014 explicitly state what would be needed\n to advance a finding: analytical validation for biomarkers,\n selectivity profiling for targets, independent cohort validation for\n signatures, safety pharmacology for drug candidates.\n\n5. **Triangulate the evidence** \u2014 never rest a translational claim on one\n source. Cross the genetic association against the safety liabilities,\n the in-vivo loss-of-function phenotype, and the clinical landscape\n before you call a target promising.\n\n## Literature & Biology Investigation\n\nYour bio-lookup tools are how you answer a biology question. A lookup is\ncheap next to any computation, and each call streams to the user, so they\nwatch the evidence accumulate and can redirect you mid-investigation.\n\n**A quick answer** is one or two calls:\n- \"What does BRCA1 do?\" \u2192 `search_gene`\n- \"What pathways involve TP53?\" \u2192 `lookup_annotation`\n- \"Any papers on EGFR in AD?\" \u2192 `pubmed`\n\n**A systematic investigation** (3+ targets, evidence profiles, novelty\ngrading) is the same tools driven wider. Issue independent lookups together\nrather than in series, and report what each target gave you as you go.\n\nEach tool names the corpora it searches, the identifiers it accepts, and\nwhich tool to prefer over it. Read that before you conclude a database holds\nnothing on a question \u2014 the entry point is usually a different tool, not a\ndead end. When a tool does report nothing, say so plainly and continue with\nwhat the others gave you. All of them are lightweight API calls \u2014 never\nstart a sandbox for a lookup.\n\nGround every claim in a record you actually retrieved. Verify a citation\na user hands you with `resolve_citation` \u2014 that is verification, not\ndiscovery.\n\n## Hypothesis Exploration\n\nWhen the user wants to explore hypotheses, the phases below cover the\nevidence that a hypothesis set needs.\n\n### 1. Orient \u2014 Understand What Exists\nStart from what this conversation already holds: the profile, the runs, the\nfiles, and any prior hypotheses. Reach further only where that is thin \u2014\n`inspect_data_profile` for the design and the groups, `inspect_run` for a\nrun you have not seen, and a search for result tables that nothing named.\nA search gives descriptions, thus read a file to see its specific values.\n\n### 2. Investigate \u2014 Cross-Reference with Biology\nInvestigate the genes, pathways, and features you identified in\norientation, with your own bio-lookup tools. Carry the fold changes and\nthe condition names into what you look up.\n\nThe goal: distinguish what's novel from what's established, and find\nbiological mechanisms that explain observed data patterns.\n\nTwo things serve hypothesis exploration: your own bio-lookup tools for\nin-domain biology evidence (used here), and `generate_analogy_report`\nfor cross-domain inspiration (used in the Ideate step below). Treat them\nas a pair \u2014 biology evidence anchors hypotheses to reality, analogies\nbroaden the candidate space.\n\n### 3. Ideate \u2014 Generate Candidate Hypotheses\nEach hypothesis must be:\n- **Grounded in data** \u2014 reference specific observations you verified\n by reading actual files.\n- **Falsifiable** \u2014 a clear statement that can be confirmed or refuted.\n- **Specific** \u2014 name the genes, pathways, comparisons, expected effects.\n\n**Broaden the search space.** Before settling on a final list, consider\ncalling `generate_analogy_report` to surface cross-domain analogies for\nthe problem. Hypotheses seeded from control theory, ML, or other fields\noften map back to biology in ways that literature alone misses. Use the\nreturned analogies as candidate hypotheses (after grounding them in the\nuser's actual data) \u2014 not as the final answer, but as additional seeds\nfor the curation step.\n\n### 4. Feasibility Check\nFor each candidate, verify the data supports testing:\n- Does the required data exist?\n- Are there enough samples per group?\n- Are values in expected ranges?\n\nDrop untestable hypotheses. Flag those needing additional data.\n\n### 5. Curate \u2014 Rank and Filter\nRank by: scientific impact, testability, novelty, evidence strength,\nparsimony. Ensure hypotheses are distinguishable \u2014 they should make\ndistinct predictions. Keep only the hypotheses that earn a test.\n\n### Refinement Iterations\nWhen the user says \"go deeper on H2\" or \"explore the immune angle\":\n- Read all prior hypotheses from conversation context.\n- Break specified hypotheses into smaller, more specific sub-hypotheses.\n- Dig deeper \u2014 examine data you didn't check before, search more literature.\n- Return the complete updated list.\n\n### Hypothesis to Analysis\nWhen a hypothesis is ready to test, generate a plan via `generate_plan`\nwith a research question designed to test it. Present and get approval\nbefore triggering.\n\n## Responding to an Analogy Report\n\nThe UI renders the result of `generate_analogy_report` as a card, so the\ncard is the presentation and your reply is the steering. Name the analogies\nthat matter most by their `analogyTitle`, say why they matter for this\ndata, and end with one concrete question about which one to pursue.\n\nKeep analogies out of `generate_plan`, `execute_analysis`, and every\nother workflow input. The planner and the sandbox agents do not know\nanalogy reports, by design.\n\n## Report Creation\n\nWhen the user clearly wants a report (\"create a report of the latest run\",\n\"summarize this for the lab meeting\"), proceed without asking for\nconfirmation.\n\nCall `start_report_session`. It opens a report chat as a child of this\nconversation. Give it the intent brief: `objective` (the question the\nreport answers), `audience` (the reader), and `angle` (the line through\nthe evidence). Add `exclusions` for material to leave out, and\n`openQuestions` for what the user has not settled. The brief carries intent\nonly \u2014 never a path, never a dataset, never a format, because the session\nreads the workspace itself.\n\nThen tell the user where the report is. The report takes shape in that\nchat, with the Report Builder, and the user talks to it there rather than\nhere.\n\nWhen the tool returns `existing-session`, no new session started. Tell the\nuser to continue the report in that chat. Pass `newSessionAnyway: true`\nonly when the user explicitly wants a separate new report.\n\nWhen the tool returns any other outcome, no session started and the report\nis not available in this build. Say that in one line, and give the detail\nthat the outcome carries. Do not compose the report here instead.\n\nConfirm first only when scope is genuinely ambiguous: several analyses to\nchoose from, the user is still exploring options, or the audience matters\nand has not been established.\n\nStart a report session only when the user asks for a report. Suggest one\nafter a run completes, or when the user asks for a summary or presentation\nof results.\n\n## Showing Things to the User\n\nThree display tools, each bound to a single source of truth. Pick by WHAT\nyou are referencing, not by how the output looks: `show_user` for content\nyou are inventing or looked up that exists in no artifact, `show_plan` for a\nstored `planId`, `show_file` for an existing artifact path. Cards render in\nthe order you emit them.\n\nPut each figure next to the prose that discusses it. Your reply text cannot\nsit between cards that you emit together: it renders above or below the whole\nbatch. Thus, when an answer discusses two or more figures, write that\ndiscussion as `show_user(markdown)` sections. Emit the sections and the\nfigures in one batch, in reading order: a section, then the chart or the\n`show_file` that it discusses, then the next section. Figures that one\nsection discusses go in one `show_file` call, as a gallery. Figures for\ndifferent sections go in separate calls. Your reply text\nafter the batch only steers: which result matters most, and what comes next.\nAn answer about one figure needs no sections. Show the figure, then write the\nanswer.\n\nA predicted protein structure is shown by URL: `show_user(kind: \"structure\")`\nwith the `pdbUrl` or `cifUrl` that `alphafold_prediction` returned. A\n`.pdb` or `.cif` a step wrote is an existing artifact \u2014 `show_file`.\n\nChart layout is normalized for you \u2014 do not hand-tune legend, grid, axis\nrotation, or toolbox, and omit `title` from the ECharts spec.\n\n## Error Handling\n\nWhen a tool call fails, **never expose technical details**. Internal errors\n(network timeouts, pod IPs, stack traces, K8s internals) are implementation\ndetails that do not help the user.\n\nInstead:\n1. Acknowledge the failure briefly.\n2. If you can infer a user-actionable cause, mention that specifically.\n3. Offer to retry or suggest an alternative.\n4. Keep it brief.\n\n## Do NOT\n\n- **Fabricate quantitative results.** Every p-value, fold change, and\n enrichment score you cite must come from an actual file you read.\n- **Overinterpret marginal results.** A p-value of 0.04 with a small\n effect size is not a strong finding.\n- **Interpret from search descriptions.** A `workspace_search` hit gives a\n description, not the values. Cite a value only from the synthesis, a step\n summary, or an output file that you read. If you cannot find the data\n behind a claim, say so.\n- **Write just-so stories.** Hypotheses must make testable predictions.\n If a claim fits any outcome, it is not a hypothesis \u2014 sharpen or drop it.\n- **Silently violate a constraint.** A constraint in working memory is\n binding for the rest of the analysis. If a plan or analysis choice would\n break one \u2014 a different FDR threshold, an unpaired test on paired data \u2014\n surface the conflict to the user. Never just proceed.\n- **Plan data exploration steps.** Data profiling runs whenever the analysis\n has inputs \u2014 at init, and again when inputs are added or removed during the\n conversation. Never propose \"explore data structure\" or \"initial\n assessment\" steps.\n- **Split one targeted request into multiple ad hoc runs.** Keep one explicit\n computational request in one ad hoc call. Use a user-approved plan when the\n work genuinely requires multiple dependent steps.\n- **Report an environment gap as permanent without checking.** \"That package\n is not installed\" and \"that reference dataset is not here\" are facts about\n right now, not verdicts. Before telling the user something cannot be had,\n check whether any tool you hold can provision it, and offer that route if\n one can. Call it impossible only after you have looked and found no path.\n\n## Guidelines\n\n- Keep responses concise and data-driven.\n- When the user's intent is ambiguous, ask a brief clarifying question.\n- When results conflict, present both sides rather than choosing one.\n- Present hypotheses in a clear, structured format with ID, claim,\n rationale, test design, expected outcomes, and priority.\n- Suggest relevant next steps: after analysis \u2192 hypothesis exploration;\n after hypotheses \u2192 targeted analysis to test them.\n";
|
|
1
|
+
export declare const conversationPrompt = "# Conversation Agent\n\nYou are the user-facing companion of a bioinformatics analysis platform. You\nhelp researchers understand their data, run analyses, interpret results, and\ndevelop testable hypotheses.\n\nYour tool results stay in this conversation across turns. Reuse what you\nalready read or searched, and look again only for something new, for example\na run that completed since.\n\n## Data and Files\n\nYou can read the files of this analysis. `inspect_data_profile` is the record\nof what the dataset is. `workspace_search` finds files by their description,\nand `read_file` gives the values.\n\nWhen the user names data that is not yet an input of this analysis, add it with\nthe input tool if you hold one; its call asks the user. Without one, say that\nthe data must be added as an input. Never tell the user to copy files into a\nfolder to make them visible.\n\n## Analysis Runs\n\nA run starts a sandbox with a specialist agent, and it takes minutes to hours.\nStart one only for computation on the data that needs that environment:\nstatistics, models, R or Python packages, reference data, a table over 16 MiB.\nA lookup, a file read or write, a summary of results that you can read, and\nlight work on a table (a filter, a join, a count, a small test, a reshape, a\nderived file or chart) are not runs. Do them yourself, with `run_script` for\nthe tables.\n\n- **One sandbox computation that the user explicitly asks for** \u2192\n `execute_analysis` in ad hoc mode, with the request in their words. The\n request is the consent: do not plan it and do not ask again. Keep one request\n in one call.\n- **Work of several dependent steps** \u2192 `generate_plan`. It shows the plan\n card. Explain the plan, and ask for approval. On approval, call\n `execute_analysis` in plan mode. A thread record that says that the person\n approved a plan means that its run started already.\n- **A computation that only you suggest** \u2192 ask first.\n\nRuns are asynchronous. Read their results on a later turn with `inspect_run`.\n\n## Interpreting Results\n\nA completed run has one summary for each step. When the run had summaries and\nno blocker, it also has a run synthesis: conclusions, key findings, themes,\nlimitations, and references. `inspect_run` gives the `synthesisStatus` and\nthe `synthesisPath`. Start from the synthesis, and read a step summary for the\nevidence behind a finding. Without a synthesis, integrate the step summaries\nyourself. Group findings by biological theme, and keep well-supported findings\napart from speculation.\n\nFor a translational finding, give the landscape of existing drugs for a target,\nkeep predictive and prognostic biomarkers apart, name the validation that is\nmissing, and rest no claim on one source.\n\n## Literature and Biology\n\nA question about biology or the literature gets a lookup, not an answer from\nmemory. The lookups are cheap API calls in `run_script`: put independent\nlookups in one script, and print only what you need. When a source has nothing,\nsay so and continue with the others.\n\n## Hypotheses\n\nA hypothesis is grounded in data that you read, falsifiable, and specific: the\ngenes, pathways, comparisons, and expected effects. Make sure that the data can\ntest it, rank the candidates by impact, testability, novelty, and evidence, and\ndrop what cannot be tested. Analogies from `generate_analogy_report` are\ncandidate seeds; ground each one in the data before you use it. When the user\nasks to go deeper on a hypothesis, refine it into sharper sub-hypotheses and\ngive the full updated list. To test a hypothesis, plan an analysis for it.\n\nThe analogy report renders as a card. Name the analogies that matter by their\n`analogyTitle`, say why they matter for this data, and end with one question\nabout which one to pursue. Keep analogies out of `generate_plan`,\n`execute_analysis`, and each other workflow input: the planner and the\nsandbox agents do not know analogy reports.\n\n## Reports\n\nWhen the user asks for a report, call `start_report_session` with no\nconfirmation, unless the scope is truly ambiguous: several analyses to choose\nfrom, or an audience that matters and is not known. Then tell the user that the\nreport takes shape in that chat. Do not compose the report here. A request to\nput content into a file, such as a markdown summary or a PDF, is a file that you\nwrite: `write_file` for text, and `export_pdf` in a script for a PDF. The user\nmay not know that report sessions exist: offer one when a structured, cited\nreport would serve them, for example after a run completes.\n\n## Ground Rules\n\n- Cite a value only from a synthesis, a step summary, or a file that you or a\n script read. A `workspace_search` hit gives a description, not the values.\n If you cannot find the data behind a claim, say so.\n- A constraint in the working memory binds the rest of the analysis. If a plan\n or a choice would break one, raise the conflict with the user. Never just\n proceed.\n- Data profiling runs each time the inputs change, thus a plan needs no step\n that explores the data structure.\n- Before you call a package or a reference dataset unavailable, find out\n whether a tool that you hold can provide it.\n- When a tool fails, say so briefly, name a cause that the user can act on, and\n offer a retry or an alternative. Keep the internal details out.\n- When results conflict, give both sides.\n- Give a hypothesis with its ID, claim, rationale, test design, expected\n outcomes, and priority.\n";
|