@inflexa-ai/harness 0.42.2 → 0.43.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 +2 -2
- package/dist/agents/sandbox/shared.d.ts +1 -6
- package/dist/agents/sandbox/shared.js +0 -15
- package/dist/app/chat-turn.js +13 -1
- package/dist/config/environment-stores.d.ts +4 -2
- package/dist/contracts/chat-events.d.ts +9 -1
- package/dist/contracts/chat-frame.d.ts +3 -3
- package/dist/contracts/chat-frame.js +8 -3
- package/dist/contracts/chat-parts.d.ts +4 -1
- package/dist/contracts/data-profile.d.ts +4 -6
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/report-blocks.d.ts +1364 -75
- package/dist/contracts/report-blocks.js +221 -29
- package/dist/contracts/report-reference.js +1 -1
- package/dist/contracts/schemas/chat-events.d.ts +13 -0
- package/dist/contracts/schemas/chat-events.js +5 -0
- package/dist/contracts/schemas/chat-parts.d.ts +2 -2
- package/dist/contracts/schemas/index.d.ts +1 -1
- package/dist/contracts/schemas/index.js +1 -1
- package/dist/execution/input-signature.d.ts +7 -13
- package/dist/execution/input-signature.js +0 -0
- package/dist/execution/run-canceler.d.ts +3 -2
- package/dist/execution/run-canceler.js +3 -2
- package/dist/execution/run-event-stream.d.ts +16 -2
- package/dist/execution/run-event-stream.js +54 -3
- package/dist/index.d.ts +1 -8
- package/dist/index.js +5 -16
- package/dist/input-scan/enrich.d.ts +0 -2
- package/dist/input-scan/enrich.js +0 -1
- package/dist/lib/metrics.js +6 -7
- package/dist/lib/otel-spans.d.ts +4 -9
- package/dist/lib/otel-spans.js +3 -8
- package/dist/loop/run-agent.d.ts +4 -2
- package/dist/loop/run-agent.js +38 -23
- package/dist/memory/thread-history.d.ts +1 -1
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +17 -0
- package/dist/provenance/exec-frame.d.ts +1 -1
- package/dist/report-model/authoring-grammar.d.ts +416 -17
- package/dist/report-model/authoring-grammar.js +25 -4
- package/dist/report-model/block-walk.d.ts +20 -4
- package/dist/report-model/block-walk.js +64 -7
- package/dist/report-model/draft-finish.d.ts +6 -2
- package/dist/report-model/draft-finish.js +6 -1
- package/dist/report-model/production-resolver.d.ts +8 -0
- package/dist/report-model/production-resolver.js +1 -1
- package/dist/report-model/validate.d.ts +20 -10
- package/dist/report-model/validate.js +29 -13
- package/dist/report-render/chart-export.d.ts +52 -0
- package/dist/report-render/chart-export.js +192 -0
- package/dist/report-render/chart-presets.d.ts +46 -47
- package/dist/report-render/chart-presets.js +31 -101
- package/dist/report-render/chart-renderers.d.ts +163 -0
- package/dist/report-render/chart-renderers.js +1055 -0
- package/dist/report-render/chart-toolbox.d.ts +124 -0
- package/dist/report-render/chart-toolbox.js +595 -0
- package/dist/report-render/chart.d.ts +60 -27
- package/dist/report-render/chart.js +2323 -524
- package/dist/report-render/design.d.ts +476 -16
- package/dist/report-render/design.js +390 -56
- package/dist/report-render/figures/common.d.ts +321 -0
- package/dist/report-render/figures/common.js +759 -0
- package/dist/report-render/figures/dendrogram.d.ts +36 -0
- package/dist/report-render/figures/dendrogram.js +130 -0
- package/dist/report-render/figures/dense.d.ts +111 -0
- package/dist/report-render/figures/dense.js +204 -0
- package/dist/report-render/figures/dotplot.d.ts +28 -0
- package/dist/report-render/figures/dotplot.js +234 -0
- package/dist/report-render/figures/embedding.d.ts +43 -0
- package/dist/report-render/figures/embedding.js +360 -0
- package/dist/report-render/figures/equal-units.d.ts +101 -0
- package/dist/report-render/figures/equal-units.js +215 -0
- package/dist/report-render/figures/forest.d.ts +20 -0
- package/dist/report-render/figures/forest.js +398 -0
- package/dist/report-render/figures/gsea.d.ts +30 -0
- package/dist/report-render/figures/gsea.js +391 -0
- package/dist/report-render/figures/heatmap.d.ts +40 -0
- package/dist/report-render/figures/heatmap.js +395 -0
- package/dist/report-render/figures/index.d.ts +135 -0
- package/dist/report-render/figures/index.js +100 -0
- package/dist/report-render/figures/km.d.ts +16 -0
- package/dist/report-render/figures/km.js +406 -0
- package/dist/report-render/figures/label-room.d.ts +130 -0
- package/dist/report-render/figures/label-room.js +341 -0
- package/dist/report-render/figures/locuszoom.d.ts +50 -0
- package/dist/report-render/figures/locuszoom.js +675 -0
- package/dist/report-render/figures/lollipop.d.ts +16 -0
- package/dist/report-render/figures/lollipop.js +247 -0
- package/dist/report-render/figures/ma.d.ts +20 -0
- package/dist/report-render/figures/ma.js +114 -0
- package/dist/report-render/figures/manhattan.d.ts +60 -0
- package/dist/report-render/figures/manhattan.js +343 -0
- package/dist/report-render/figures/oncoprint.d.ts +41 -0
- package/dist/report-render/figures/oncoprint.js +420 -0
- package/dist/report-render/figures/pca.d.ts +37 -0
- package/dist/report-render/figures/pca.js +241 -0
- package/dist/report-render/figures/qq.d.ts +30 -0
- package/dist/report-render/figures/qq.js +182 -0
- package/dist/report-render/figures/roc.d.ts +17 -0
- package/dist/report-render/figures/roc.js +116 -0
- package/dist/report-render/figures/sankey.d.ts +48 -0
- package/dist/report-render/figures/sankey.js +353 -0
- package/dist/report-render/figures/upset.d.ts +60 -0
- package/dist/report-render/figures/upset.js +316 -0
- package/dist/report-render/figures/volcano.d.ts +25 -0
- package/dist/report-render/figures/volcano.js +166 -0
- package/dist/report-render/hybrid-svg.d.ts +75 -0
- package/dist/report-render/hybrid-svg.js +504 -0
- package/dist/report-render/number-format.d.ts +19 -0
- package/dist/report-render/number-format.js +25 -1
- package/dist/report-render/page.d.ts +41 -4
- package/dist/report-render/page.js +247 -12
- package/dist/report-render/render.d.ts +13 -4
- package/dist/report-render/render.js +37 -6
- package/dist/report-render/types.d.ts +23 -2
- package/dist/report-render/value-bridge.d.ts +38 -3
- package/dist/report-render/value-bridge.js +137 -6
- package/dist/report-render/views/chart-view.d.ts +42 -6
- package/dist/report-render/views/chart-view.js +70 -9
- package/dist/report-render/views/page-view.js +9 -10
- package/dist/runtime/assemble.js +2 -2
- package/dist/sandbox/client.d.ts +23 -32
- package/dist/sandbox/client.js +3 -11
- package/dist/sandbox/create-sandbox.d.ts +9 -24
- package/dist/sandbox/create-sandbox.js +15 -30
- package/dist/sandbox/docker-client.d.ts +12 -22
- package/dist/sandbox/docker-client.js +29 -43
- package/dist/sandbox/exec.d.ts +58 -0
- package/dist/sandbox/exec.js +197 -0
- package/dist/sandbox/identity.d.ts +5 -5
- package/dist/sandbox/identity.js +7 -10
- package/dist/sandbox/k8s-client.d.ts +4 -10
- package/dist/sandbox/k8s-client.js +5 -12
- package/dist/sandbox/liveness.d.ts +5 -12
- package/dist/sandbox/liveness.js +5 -12
- package/dist/sandbox/notification-sweep.d.ts +4 -7
- package/dist/sandbox/notification-sweep.js +4 -7
- package/dist/sandbox/reaper.d.ts +3 -3
- package/dist/sandbox/reaper.js +3 -3
- package/dist/sandbox/sandbox-error.d.ts +10 -11
- package/dist/sandbox/sandbox-error.js +10 -11
- package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
- package/dist/sandbox/sandbox-step-translate.js +1 -1
- package/dist/sandbox/types.d.ts +31 -99
- package/dist/sandbox/types.js +17 -84
- package/dist/state/active-sandboxes.d.ts +7 -32
- package/dist/state/active-sandboxes.js +11 -46
- package/dist/state/index.d.ts +1 -2
- package/dist/state/index.js +1 -1
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.d.ts +7 -0
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.js +12 -0
- package/dist/state/migrations/index.js +2 -0
- package/dist/state/schema.d.ts +1 -5
- package/dist/state/schema.js +1 -6
- package/dist/state/step-executions.js +1 -2
- package/dist/tasks/data-profile.js +7 -20
- package/dist/tasks/derive-table-exec.d.ts +4 -14
- package/dist/tasks/derive-table-exec.js +9 -24
- package/dist/tasks/extract-values.d.ts +2 -2
- package/dist/tasks/extract-values.js +4 -7
- package/dist/tools/define-tool.d.ts +56 -13
- package/dist/tools/define-tool.js +28 -1
- package/dist/tools/execute-analysis.js +3 -3
- package/dist/tools/report-session/derive-table.d.ts +8 -9
- package/dist/tools/report-session/derive-table.js +3 -4
- package/dist/tools/report-session/preview-report.js +4 -49
- package/dist/tools/sandbox/list-available-packages.d.ts +1 -1
- package/dist/tools/sandbox/list-available-packages.js +5 -4
- package/dist/tools/workspace/edit-file.d.ts +5 -4
- package/dist/tools/workspace/edit-file.js +10 -13
- package/dist/tools/workspace/execute-command.d.ts +27 -42
- package/dist/tools/workspace/execute-command.js +42 -38
- package/dist/tools/workspace/index.d.ts +5 -6
- package/dist/tools/workspace/index.js +5 -6
- package/dist/tools/workspace/mutator.d.ts +43 -8
- package/dist/tools/workspace/mutator.js +45 -34
- package/dist/tools/workspace/run-exec.d.ts +3 -12
- package/dist/tools/workspace/run-exec.js +7 -24
- package/dist/tools/workspace/scan-inputs.d.ts +0 -3
- package/dist/tools/workspace/scan-inputs.js +0 -1
- package/dist/tools/workspace/write-file.d.ts +12 -3
- package/dist/tools/workspace/write-file.js +17 -13
- package/dist/workflows/sandbox-step.d.ts +7 -11
- package/dist/workflows/sandbox-step.js +24 -27
- package/package.json +3 -1
- package/dist/sandbox/await-exec.d.ts +0 -143
- package/dist/sandbox/await-exec.js +0 -417
- package/dist/sandbox/deliver-exec-event.d.ts +0 -25
- package/dist/sandbox/deliver-exec-event.js +0 -29
- package/dist/sandbox/digest.d.ts +0 -14
- package/dist/sandbox/digest.js +0 -17
- package/dist/sandbox/exec-id.d.ts +0 -12
- package/dist/sandbox/exec-id.js +0 -20
- package/dist/sandbox/hmac.d.ts +0 -62
- package/dist/sandbox/hmac.js +0 -72
- package/dist/sandbox/submit-exec.d.ts +0 -38
- package/dist/sandbox/submit-exec.js +0 -80
- package/dist/sandbox/watchdog.d.ts +0 -71
- package/dist/sandbox/watchdog.js +0 -161
|
@@ -34,6 +34,7 @@ import { DBOS } from "@dbos-inc/dbos-sdk";
|
|
|
34
34
|
import { sleep } from "../lib/async-utils.js";
|
|
35
35
|
import { createNoopLogger } from "../lib/console-logger.js";
|
|
36
36
|
import { describeDbError } from "../lib/db-result.js";
|
|
37
|
+
import { queryRun } from "../state/runs.js";
|
|
37
38
|
import { queryStepsByRun } from "../state/step-executions.js";
|
|
38
39
|
import { foldRunEventParts, parseRunEventPart } from "./run-event-parts.js";
|
|
39
40
|
/** Durable stream key every run producer writes its parts under. */
|
|
@@ -51,6 +52,14 @@ const RUN_EVENT_STREAM_KEY = "events";
|
|
|
51
52
|
* still read from its beginning.
|
|
52
53
|
*/
|
|
53
54
|
const CHILD_DISCOVERY_INTERVAL_MS = 1_000;
|
|
55
|
+
/**
|
|
56
|
+
* The reads of the run row for a run whose parent stream ended with no terminal
|
|
57
|
+
* part. The canceler writes `canceled` to the row after the engine cancel, thus
|
|
58
|
+
* the stream can end before the row changes, and the later reads wait out that
|
|
59
|
+
* window.
|
|
60
|
+
*/
|
|
61
|
+
const CANCELED_ROW_READ_ATTEMPTS = 4;
|
|
62
|
+
const CANCELED_ROW_READ_INTERVAL_MS = 500;
|
|
54
63
|
/**
|
|
55
64
|
* Build the DBOS-backed realization of {@link RunEventStream}.
|
|
56
65
|
*
|
|
@@ -63,6 +72,8 @@ const CHILD_DISCOVERY_INTERVAL_MS = 1_000;
|
|
|
63
72
|
*/
|
|
64
73
|
export function createRunEventStream(deps) {
|
|
65
74
|
const baseLogger = (deps.logger ?? createNoopLogger()).named("run-event-stream");
|
|
75
|
+
const readRunStatus = deps.readRunStatus ?? ((runId) => queryRun(deps.pool, runId).map((row) => row?.status ?? null));
|
|
76
|
+
const waitForRowRead = deps.sleep ?? sleep;
|
|
66
77
|
return {
|
|
67
78
|
async subscribe({ runId, onPart, signal }) {
|
|
68
79
|
const logger = baseLogger.with({ runId });
|
|
@@ -97,9 +108,8 @@ export function createRunEventStream(deps) {
|
|
|
97
108
|
// survivors in place, so a single stream's write order survives it.
|
|
98
109
|
const pending = [];
|
|
99
110
|
let delivering = false;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return;
|
|
111
|
+
let delivered = Promise.resolve();
|
|
112
|
+
const drain = async () => {
|
|
103
113
|
delivering = true;
|
|
104
114
|
try {
|
|
105
115
|
while (pending.length > 0 && !signal.aborted) {
|
|
@@ -120,6 +130,14 @@ export function createRunEventStream(deps) {
|
|
|
120
130
|
delivering = false;
|
|
121
131
|
}
|
|
122
132
|
};
|
|
133
|
+
// The returned promise settles when the queue is empty, thus a caller
|
|
134
|
+
// that awaits it knows that the handler took each part enqueued so far.
|
|
135
|
+
const deliver = () => {
|
|
136
|
+
if (!delivering)
|
|
137
|
+
delivered = drain();
|
|
138
|
+
return delivered;
|
|
139
|
+
};
|
|
140
|
+
let sawTerminal = false;
|
|
123
141
|
const readWorkflowStream = async (workflowId) => {
|
|
124
142
|
const streamLogger = logger.with({ workflowId });
|
|
125
143
|
const generator = DBOS.readStream(workflowId, RUN_EVENT_STREAM_KEY);
|
|
@@ -137,6 +155,8 @@ export function createRunEventStream(deps) {
|
|
|
137
155
|
streamLogger.debug("dropped a stream value outside the chat-part contract");
|
|
138
156
|
continue;
|
|
139
157
|
}
|
|
158
|
+
if (part.type === "data-run-completed" || part.type === "data-run-failed")
|
|
159
|
+
sawTerminal = true;
|
|
140
160
|
pending.push(part);
|
|
141
161
|
void deliver();
|
|
142
162
|
}
|
|
@@ -190,10 +210,41 @@ export function createRunEventStream(deps) {
|
|
|
190
210
|
await Promise.race([sleep(CHILD_DISCOVERY_INTERVAL_MS), aborted, parentRead]);
|
|
191
211
|
}
|
|
192
212
|
})();
|
|
213
|
+
const canceledTerminalPart = async () => {
|
|
214
|
+
for (let attempt = 1; attempt <= CANCELED_ROW_READ_ATTEMPTS; attempt++) {
|
|
215
|
+
const read = await readRunStatus(runId);
|
|
216
|
+
if (read.isErr()) {
|
|
217
|
+
logger.warn("run row read failed", { err: describeDbError(read.error) });
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const status = read.value;
|
|
221
|
+
if (status === "canceled")
|
|
222
|
+
return { type: "data-run-failed", runId, error: "Run canceled", reason: "canceled" };
|
|
223
|
+
// The launch writes the row before the workflow starts, thus
|
|
224
|
+
// no row means that the id is not an analysis run.
|
|
225
|
+
if (status === null)
|
|
226
|
+
return null;
|
|
227
|
+
// Only an active row can still become `canceled`.
|
|
228
|
+
if (status !== "running" && status !== "suspended_insufficient_funds")
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
if (attempt < CANCELED_ROW_READ_ATTEMPTS)
|
|
232
|
+
await Promise.race([waitForRowRead(CANCELED_ROW_READ_INTERVAL_MS), aborted]);
|
|
233
|
+
if (signal.aborted)
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
237
|
+
};
|
|
193
238
|
const settled = (async () => {
|
|
194
239
|
await discovery;
|
|
195
240
|
await parentRead;
|
|
196
241
|
await Promise.all(childReads);
|
|
242
|
+
if (!sawTerminal && !signal.aborted) {
|
|
243
|
+
const terminal = await canceledTerminalPart();
|
|
244
|
+
if (terminal !== null)
|
|
245
|
+
pending.push(terminal);
|
|
246
|
+
}
|
|
247
|
+
await deliver();
|
|
197
248
|
})().catch((err) => {
|
|
198
249
|
// Defensive: every stream read and every discovery pass contains its
|
|
199
250
|
// own failure, so arriving here is a defect in this seam rather than
|
package/dist/index.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ export type { ConversationDisplayRecorder, ConversationDisplayRecorderOptions }
|
|
|
94
94
|
export { envelopeDisplayMessages, parseStoredDisplayEnvelope } from "./memory/conversation-display-storage.js";
|
|
95
95
|
export type { ConversationDisplayMetadata, ConversationUIData, ConversationUIMessage, StoredDisplayEnvelope } from "./memory/conversation-display-storage.js";
|
|
96
96
|
export { storedMessagesToChat } from "./memory/conversation-display-replay.js";
|
|
97
|
-
export type { ChatEvent, ChatFrame, ChatPartFrame, TextDeltaEvent, ToolStartedEvent, ToolFinishedEvent, ToolOutcome, ToolCallOutcome, ToolCallDetail, FinishEvent, ChatErrorEvent, } from "./contracts/chat-events.js";
|
|
97
|
+
export type { ChatEvent, ChatFrame, ChatPartFrame, TextDeltaEvent, IterationEvent, ToolStartedEvent, ToolFinishedEvent, ToolOutcome, ToolCallOutcome, ToolCallDetail, FinishEvent, ChatErrorEvent, } from "./contracts/chat-events.js";
|
|
98
98
|
export { toChatFrame, applyChatFrame, checkChatPart } from "./contracts/chat-frame.js";
|
|
99
99
|
export type { TextPart, ToolCallPart, MessagePart, ChatMessage } from "./contracts/message.js";
|
|
100
100
|
export type { TurnTerminal, ApplyFrameResult, ChatPartCheck } from "./contracts/chat-frame.js";
|
|
@@ -160,10 +160,6 @@ export { MachineBudgetSchema, ResourceLimitsSchema, ResourcePolicySchema, Resour
|
|
|
160
160
|
export type { MachineBudget, ResourceLimits, ResourcePolicy, ResourceSpec } from "./config/resource-limits.js";
|
|
161
161
|
export { createWorkspaceFilesystem } from "./workspace/filesystem.js";
|
|
162
162
|
export type { WorkspaceFilesystem, WorkspaceFilesystemDeps } from "./workspace/filesystem.js";
|
|
163
|
-
export { workflowIdFromExec } from "./sandbox/exec-id.js";
|
|
164
|
-
export { deliverExecEvent, execEventTopic } from "./sandbox/deliver-exec-event.js";
|
|
165
|
-
export { ExecEventMessageSchema } from "./sandbox/types.js";
|
|
166
|
-
export type { ExecEventMessage, DoneMarker } from "./sandbox/types.js";
|
|
167
163
|
export { registerExecuteAnalysis } from "./workflows/execute-analysis.js";
|
|
168
164
|
export type { ExecuteAnalysisDeps, ExecuteAnalysisInput, ExecuteAnalysisResult, RunObservation, RunStepObservation, StepRuntimeStatus, } from "./workflows/execute-analysis.js";
|
|
169
165
|
export { registerSandboxStep } from "./workflows/sandbox-step.js";
|
|
@@ -190,7 +186,6 @@ export { REFERENCE_DATA_CATALOG, REFERENCE_DATA_CATALOG_VERSION, ReferenceArtifa
|
|
|
190
186
|
export type { ReferenceArtifact, ReferenceDataCatalog, ReferenceDataset, ReferenceInstallPlan, ReferenceInstallPlanDataset } from "./reference-data/catalog.js";
|
|
191
187
|
export { REFERENCE_INSTALL_RECEIPT_VERSION, ReferenceInstallReceiptSchema, parseReferenceInstallReceipt } from "./reference-data/receipt.js";
|
|
192
188
|
export type { ReferenceInstallReceipt, ReferenceReceiptArtifact } from "./reference-data/receipt.js";
|
|
193
|
-
export { queryActiveSandboxes } from "./state/active-sandboxes.js";
|
|
194
189
|
export { runStepDir } from "./workspace/paths.js";
|
|
195
190
|
export { reportSessionDir } from "./workspace/paths.js";
|
|
196
191
|
export type { LogFields, LogLevel, Logger } from "./lib/logger.js";
|
|
@@ -198,7 +193,5 @@ export { defaultErrorFields } from "./lib/logger.js";
|
|
|
198
193
|
export { createConsoleLogger, createNoopLogger } from "./lib/console-logger.js";
|
|
199
194
|
export { registerSandboxReaper } from "./sandbox/reaper.js";
|
|
200
195
|
export type { RegisterReaperDeps } from "./sandbox/reaper.js";
|
|
201
|
-
export { registerWatchdog } from "./sandbox/watchdog.js";
|
|
202
|
-
export type { WatchdogDeps } from "./sandbox/watchdog.js";
|
|
203
196
|
export { registerNotificationSweep } from "./sandbox/notification-sweep.js";
|
|
204
197
|
export type { RegisterNotificationSweepDeps } from "./sandbox/notification-sweep.js";
|
package/dist/index.js
CHANGED
|
@@ -162,9 +162,8 @@ export { PART_REGISTRY, isTransient, isReconciling, isSidebarPart } from "./cont
|
|
|
162
162
|
export { parseStructureUrl, alphafoldEntryUrl, alphafoldPredictionUrl } from "./contracts/structure-source.js";
|
|
163
163
|
// Embedder runtime surface — what a same-process host needs to run durable
|
|
164
164
|
// workflows itself: the DBOS lifecycle, per-workflow registration + triggers,
|
|
165
|
-
// the staged-input manifest contract, the sandbox/workspace factories over
|
|
166
|
-
// workspace tree
|
|
167
|
-
// ingress is the embedder's to host; see the sandbox-server callback protocol).
|
|
165
|
+
// the staged-input manifest contract, and the sandbox/workspace factories over
|
|
166
|
+
// its workspace tree.
|
|
168
167
|
// DBOS lifecycle. `sweepEphemeralWorkflows` is a pre-launch upgrade migration:
|
|
169
168
|
// older releases could leave PENDING `ephemeral:*` rows that recovery would
|
|
170
169
|
// otherwise re-dispatch. No current workflow creates that prefix.
|
|
@@ -179,7 +178,7 @@ export { isDraining } from "./runtime/lifecycle.js";
|
|
|
179
178
|
// `dbos.workflow_status` rows must classify them against the SDK's status set,
|
|
180
179
|
// but must never depend on `@dbos-inc/dbos-sdk` directly — the SDK is
|
|
181
180
|
// module-singleton state, so a host's own copy is a different, un-launched
|
|
182
|
-
// instance
|
|
181
|
+
// instance. The barrel forwards the
|
|
183
182
|
// status const + its union so the classification vocabulary comes from the one
|
|
184
183
|
// launched SDK, not a drifting hand-kept string literal on the embedder side.
|
|
185
184
|
export { StatusString } from "@dbos-inc/dbos-sdk";
|
|
@@ -250,12 +249,6 @@ export { FARM_LOCK_FILE, FarmLockSchema, readFarmLock, readFarmLockFile } from "
|
|
|
250
249
|
export { IMAGE_PACKAGES_FILE } from "./sandbox/image-packages.js";
|
|
251
250
|
export { MachineBudgetSchema, ResourceLimitsSchema, ResourcePolicySchema, ResourceSpecSchema, parseResourcePolicy } from "./config/resource-limits.js";
|
|
252
251
|
export { createWorkspaceFilesystem } from "./workspace/filesystem.js";
|
|
253
|
-
// Exec-callback ingress building blocks. Delivery goes through
|
|
254
|
-
// `deliverExecEvent` — never a host-side `DBOS.send`: the SDK is
|
|
255
|
-
// module-singleton state, and a host's own copy would be un-launched.
|
|
256
|
-
export { workflowIdFromExec } from "./sandbox/exec-id.js";
|
|
257
|
-
export { deliverExecEvent, execEventTopic } from "./sandbox/deliver-exec-event.js";
|
|
258
|
-
export { ExecEventMessageSchema } from "./sandbox/types.js";
|
|
259
252
|
// Run engine — the analysis + sandbox-step durable workflows an embedder
|
|
260
253
|
// registers itself (in child-before-parent assemble-order: the parent's deps
|
|
261
254
|
// close over the registered child callable). `assembleCoreRuntime` also wires
|
|
@@ -296,8 +289,6 @@ export { queryStepsByRun } from "./state/step-executions.js";
|
|
|
296
289
|
// transfer/storage behavior but never choose a different source.
|
|
297
290
|
export { REFERENCE_DATA_CATALOG, REFERENCE_DATA_CATALOG_VERSION, ReferenceArtifactPathSchema, ReferenceArtifactSchema, ReferenceDataCatalogSchema, ReferenceDatasetSchema, ReferenceSha256Schema, UnknownReferenceDatasetError, referenceArtifactKey, resolveReferenceInstallPlan, } from "./reference-data/catalog.js";
|
|
298
291
|
export { REFERENCE_INSTALL_RECEIPT_VERSION, ReferenceInstallReceiptSchema, parseReferenceInstallReceipt } from "./reference-data/receipt.js";
|
|
299
|
-
// Backs `WatchdogDeps.queryActiveSandboxes` when the embedder wires the watchdog.
|
|
300
|
-
export { queryActiveSandboxes } from "./state/active-sandboxes.js";
|
|
301
292
|
// Workspace-tree path convention — the root-relative step directory each
|
|
302
293
|
// sandbox step confines its artifact writes to (join onto the resolved root).
|
|
303
294
|
export { runStepDir } from "./workspace/paths.js";
|
|
@@ -311,9 +302,7 @@ export { reportSessionDir } from "./workspace/paths.js";
|
|
|
311
302
|
export { defaultErrorFields } from "./lib/logger.js";
|
|
312
303
|
export { createConsoleLogger, createNoopLogger } from "./lib/console-logger.js";
|
|
313
304
|
// Sandbox-hygiene scheduled workflows. Reaper reclaims a dead host's orphaned
|
|
314
|
-
// containers;
|
|
315
|
-
//
|
|
316
|
-
// notifications. Each is a `@DBOS.scheduled` no-op on an idle system.
|
|
305
|
+
// containers; the sweep prunes stale notifications. Each is a
|
|
306
|
+
// `@DBOS.scheduled` no-op on an idle system.
|
|
317
307
|
export { registerSandboxReaper } from "./sandbox/reaper.js";
|
|
318
|
-
export { registerWatchdog } from "./sandbox/watchdog.js";
|
|
319
308
|
export { registerNotificationSweep } from "./sandbox/notification-sweep.js";
|
|
@@ -50,7 +50,6 @@ export interface ReadHeadersArgs {
|
|
|
50
50
|
readonly sandbox?: SandboxRef;
|
|
51
51
|
/** Absolute in-sandbox path of the analysis root (`/{analysisId}`). */
|
|
52
52
|
readonly mountRoot: string;
|
|
53
|
-
readonly execId: string;
|
|
54
53
|
readonly deadlineMs: number;
|
|
55
54
|
readonly emit: EmitFn;
|
|
56
55
|
}
|
|
@@ -63,7 +62,6 @@ export interface EnrichShapesArgs {
|
|
|
63
62
|
readonly sandbox?: SandboxRef;
|
|
64
63
|
/** Absolute in-sandbox path of the analysis root (`/{analysisId}`). */
|
|
65
64
|
readonly mountRoot: string;
|
|
66
|
-
readonly execId: string;
|
|
67
65
|
readonly deadlineMs: number;
|
|
68
66
|
readonly emit: EmitFn;
|
|
69
67
|
}
|
|
@@ -122,7 +122,6 @@ async function decodeContainers(args, machine, containers) {
|
|
|
122
122
|
const result = await runSandboxExec({
|
|
123
123
|
sandboxClient: machine.sandboxClient,
|
|
124
124
|
sandbox: machine.sandbox,
|
|
125
|
-
execId: args.execId,
|
|
126
125
|
command: ["python3", "-c", source, ...byAbsolute.keys()],
|
|
127
126
|
timeoutSeconds: ENRICH_TIMEOUT_SECONDS,
|
|
128
127
|
deadlineMs: args.deadlineMs,
|
package/dist/lib/metrics.js
CHANGED
|
@@ -184,13 +184,12 @@ export function elapsedSinceIso(startedAt, nowMs = Date.now()) {
|
|
|
184
184
|
* Exec ids already counted, so a replay counts one exec one time.
|
|
185
185
|
*
|
|
186
186
|
* The run and step counters sit inside the DBOS step that persists the same
|
|
187
|
-
* outcome, and DBOS never runs a cached step body a second time.
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* memory of the first count and can count that exec again.
|
|
187
|
+
* outcome, and DBOS never runs a cached step body a second time. The exec
|
|
188
|
+
* record sits inside the step of its exec too, but a step that did not finish
|
|
189
|
+
* runs its body again on recovery. An exec id is `{workflowId}:{functionId}`
|
|
190
|
+
* and it is stable across that second run, thus it is the key that makes the
|
|
191
|
+
* record idempotent. The set is process-local: a recovery in a fresh process
|
|
192
|
+
* holds no memory of the first count and can count that exec again.
|
|
194
193
|
*/
|
|
195
194
|
const countedExecs = new Set();
|
|
196
195
|
/**
|
package/dist/lib/otel-spans.d.ts
CHANGED
|
@@ -54,12 +54,8 @@ export declare function untracedWorkflow(name: string): void;
|
|
|
54
54
|
export declare function createHarnessSampler(): Sampler;
|
|
55
55
|
/** The plan step id a `compose-step-seed` step carries. */
|
|
56
56
|
export declare const ATTR_INFLEXA_STEP_ID = "inflexa.step_id";
|
|
57
|
-
/** The
|
|
58
|
-
export declare const ATTR_INFLEXA_TOOL_USE_ID = "inflexa.tool_use_id";
|
|
59
|
-
/** The exec id (`${workflowId}:${stepId}:${fnId}`) of a sandbox exec step. */
|
|
57
|
+
/** The exec id (`${workflowId}:${functionId}`) of a sandbox exec step. */
|
|
60
58
|
export declare const ATTR_INFLEXA_EXEC_ID = "inflexa.exec_id";
|
|
61
|
-
/** The 1-based attempt counter of a sandbox poll, pull, or liveness-probe step. */
|
|
62
|
-
export declare const ATTR_INFLEXA_ATTEMPT = "inflexa.attempt";
|
|
63
59
|
/**
|
|
64
60
|
* Rename the DBOS span of the step that is running to `name` and put its id
|
|
65
61
|
* in `attributes`. Call it as the first statement of a step body whose DBOS
|
|
@@ -75,12 +71,11 @@ export declare function stableSpan(dbosName: string, name: string, attributes: A
|
|
|
75
71
|
/**
|
|
76
72
|
* Send a request to sandbox-server with the active trace context in its
|
|
77
73
|
* headers and with tracing suppressed, so the host's HTTP instrumentation
|
|
78
|
-
* writes no client span. Sandbox-server records no spans and
|
|
79
|
-
*
|
|
80
|
-
* show the host calling itself; the step span around the call already covers it.
|
|
74
|
+
* writes no client span. Sandbox-server records no spans, and the step span
|
|
75
|
+
* around the call already covers it.
|
|
81
76
|
*/
|
|
82
77
|
export declare function untracedFetch(fetchImpl: typeof fetch, url: string, init: RequestInit & {
|
|
83
|
-
headers
|
|
78
|
+
headers?: Record<string, string>;
|
|
84
79
|
}): Promise<Response>;
|
|
85
80
|
/**
|
|
86
81
|
* Decides whether the span that `startSpan` is about to start passes through.
|
package/dist/lib/otel-spans.js
CHANGED
|
@@ -78,12 +78,8 @@ export function createHarnessSampler() {
|
|
|
78
78
|
}
|
|
79
79
|
/** The plan step id a `compose-step-seed` step carries. */
|
|
80
80
|
export const ATTR_INFLEXA_STEP_ID = "inflexa.step_id";
|
|
81
|
-
/** The
|
|
82
|
-
export const ATTR_INFLEXA_TOOL_USE_ID = "inflexa.tool_use_id";
|
|
83
|
-
/** The exec id (`${workflowId}:${stepId}:${fnId}`) of a sandbox exec step. */
|
|
81
|
+
/** The exec id (`${workflowId}:${functionId}`) of a sandbox exec step. */
|
|
84
82
|
export const ATTR_INFLEXA_EXEC_ID = "inflexa.exec_id";
|
|
85
|
-
/** The 1-based attempt counter of a sandbox poll, pull, or liveness-probe step. */
|
|
86
|
-
export const ATTR_INFLEXA_ATTEMPT = "inflexa.attempt";
|
|
87
83
|
/**
|
|
88
84
|
* Rename the DBOS span of the step that is running to `name` and put its id
|
|
89
85
|
* in `attributes`. Call it as the first statement of a step body whose DBOS
|
|
@@ -108,9 +104,8 @@ export function stableSpan(dbosName, name, attributes) {
|
|
|
108
104
|
/**
|
|
109
105
|
* Send a request to sandbox-server with the active trace context in its
|
|
110
106
|
* headers and with tracing suppressed, so the host's HTTP instrumentation
|
|
111
|
-
* writes no client span. Sandbox-server records no spans and
|
|
112
|
-
*
|
|
113
|
-
* show the host calling itself; the step span around the call already covers it.
|
|
107
|
+
* writes no client span. Sandbox-server records no spans, and the step span
|
|
108
|
+
* around the call already covers it.
|
|
114
109
|
*/
|
|
115
110
|
export function untracedFetch(fetchImpl, url, init) {
|
|
116
111
|
const active = context.active();
|
package/dist/loop/run-agent.d.ts
CHANGED
|
@@ -153,8 +153,10 @@ export interface RunAgentOptions {
|
|
|
153
153
|
* sub-agent-running tool from its `ctx.invocationId`. It is what separates
|
|
154
154
|
* two dispatches of the *same* sub-agent in one round — they share the run
|
|
155
155
|
* frame, the call path, and every loop-local step name — in the usage
|
|
156
|
-
* record key.
|
|
157
|
-
*
|
|
156
|
+
* record key. The data profile gives the workflow id of its attempt,
|
|
157
|
+
* because each profile runs under the same constant frame. Absent for any
|
|
158
|
+
* other loop that is not nested inside a tool dispatch (a chat turn's
|
|
159
|
+
* root, a workflow step body, a background task).
|
|
158
160
|
*/
|
|
159
161
|
readonly invocationId?: string;
|
|
160
162
|
}
|
package/dist/loop/run-agent.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createNoopUsageRecorder } from "../billing/noop-usage-recorder.js";
|
|
|
4
4
|
import { stripNulCharacters } from "../input-sanitization.js";
|
|
5
5
|
import { createNoopLogger } from "../lib/console-logger.js";
|
|
6
6
|
import { deliverNotice } from "../lib/hooks.js";
|
|
7
|
-
import {
|
|
7
|
+
import { passThroughSpan } from "../lib/otel-spans.js";
|
|
8
8
|
import { ResultError, unwrapOrThrow } from "../lib/result.js";
|
|
9
9
|
import { describeZodIssueShapes } from "../lib/zod-issue-shape.js";
|
|
10
10
|
import { hintForZodIssue, repairToolInput } from "../lib/zod-issues.js";
|
|
@@ -17,7 +17,7 @@ import { COMPACTION_MAX_REQUESTS } from "./compaction.js";
|
|
|
17
17
|
import { continueAgent } from "./continue-agent.js";
|
|
18
18
|
import { resultStep } from "./run-step.js";
|
|
19
19
|
import { AskRejectedError, UnavailableAsk } from "../tools/approval/contract.js";
|
|
20
|
-
import { isToolError, readToolResultImages } from "../tools/define-tool.js";
|
|
20
|
+
import { isToolError, readToolCallRecord, readToolResultImages, } from "../tools/define-tool.js";
|
|
21
21
|
import { labelToolFailure, labelToolValidationFailure, recordToolException, traceAgentRun, traceToolCall } from "./genai-spans.js";
|
|
22
22
|
import { addChatUsage, countChatTokens, hasReportedUsage, recordAgentRun } from "./metrics.js";
|
|
23
23
|
import { computeDetail, computeResultDetail } from "./tool-detail.js";
|
|
@@ -142,18 +142,11 @@ export function openLoop(agent, initial, session, opts, metricAgentId) {
|
|
|
142
142
|
// turn total. Descendants receive the root's object and mutate it in place.
|
|
143
143
|
const turnUsage = opts.turnUsage ?? {};
|
|
144
144
|
const turnRoot = isTurnRoot(opts);
|
|
145
|
-
const toolCtx = (tu
|
|
145
|
+
const toolCtx = (tu) => ({
|
|
146
146
|
invocationId: tu.toolCallId,
|
|
147
147
|
session,
|
|
148
148
|
signal,
|
|
149
149
|
emit,
|
|
150
|
-
runStep: (name, fn) => {
|
|
151
|
-
const stepName = `${names.tool(tu.toolName, tu.toolCallId)}:${name}`;
|
|
152
|
-
return runStep(stepName, () => {
|
|
153
|
-
stableSpan(stepName, `tool:${tu.toolName}:${name}`, { [ATTR_INFLEXA_TOOL_USE_ID]: tu.toolCallId });
|
|
154
|
-
return fn();
|
|
155
|
-
});
|
|
156
|
-
},
|
|
157
150
|
ask,
|
|
158
151
|
turnUsage,
|
|
159
152
|
});
|
|
@@ -317,7 +310,7 @@ export function openLoop(agent, initial, session, opts, metricAgentId) {
|
|
|
317
310
|
*/
|
|
318
311
|
const dispatchRound = (calls, mask, names) => {
|
|
319
312
|
const refusals = refusalsFor(calls, mask, opts.toolBudget, used);
|
|
320
|
-
return dispatchTools(calls, refusals, toolsById,
|
|
313
|
+
return dispatchTools(calls, refusals, toolsById, toolCtx, isFatalLoopError, callStep, names.tool, encoding, cut);
|
|
321
314
|
};
|
|
322
315
|
const stopOnResolved = async (index) => {
|
|
323
316
|
settleTranscript();
|
|
@@ -637,9 +630,10 @@ export function accountForChatCall(reply, call) {
|
|
|
637
630
|
* can never be read as one: agent ids are kebab-case identifiers, run ids are
|
|
638
631
|
* UUIDs or the profiler's `data-profile` literal, step ids are path-safe plan
|
|
639
632
|
* ids (`T1S1`, `synthesis`, `profile`), tool-call ids are provider-issued
|
|
640
|
-
* opaque tokens,
|
|
641
|
-
*
|
|
642
|
-
* `
|
|
633
|
+
* opaque tokens, a profile attempt's workflow id is
|
|
634
|
+
* `dataprofile:{analysisId}:{nonce}`, and the loop's step names are `llm-{n}`
|
|
635
|
+
* / `tool-{name}-{id}` with an optional continuation namespace (`salvage:`,
|
|
636
|
+
* `file-metadata:`, `step-summary:`) — none of them can contain `>`.
|
|
643
637
|
*/
|
|
644
638
|
const CALL_PATH_DELIMITER = ">";
|
|
645
639
|
/**
|
|
@@ -663,7 +657,9 @@ const CALL_PATH_DELIMITER = ">";
|
|
|
663
657
|
* - `invocationId` — the same sub-agent dispatched twice in one round has an
|
|
664
658
|
* identical call path, so only the dispatching tool-call id tells the two
|
|
665
659
|
* child loops apart. It is replay-stable by the harness-tools contract: a
|
|
666
|
-
* redelivered call carries the id it was issued under.
|
|
660
|
+
* redelivered call carries the id it was issued under. Each data profile
|
|
661
|
+
* runs under the same constant frame, thus the workflow id of its attempt
|
|
662
|
+
* takes this place, and a replay of the attempt keeps that id.
|
|
667
663
|
* - `stepName` — the loop's own deterministic name, reused rather than
|
|
668
664
|
* re-derived. Minting a second *naming* scheme here would create two things
|
|
669
665
|
* that must agree about what "the same call" is, and they would drift.
|
|
@@ -764,7 +760,8 @@ function appendDeferredImages(messages, results, deferredImages) {
|
|
|
764
760
|
deferredImages.length = 0;
|
|
765
761
|
}
|
|
766
762
|
/**
|
|
767
|
-
* Dispatch one round of tool calls,
|
|
763
|
+
* Dispatch one round of tool calls, measure the time of each call, and fold the
|
|
764
|
+
* call record of each call in call order.
|
|
768
765
|
*
|
|
769
766
|
* `refusals`, `results`, `durations` and `resultDetails` are positionally aligned
|
|
770
767
|
* with `toolUses`; `refusals[i]` is the refusal text, or `undefined` if the call runs.
|
|
@@ -792,14 +789,12 @@ async function dispatchTools(toolUses, refusals, toolsById, toolCtx, isFatalLoop
|
|
|
792
789
|
// denial, and a tool with no result hook each leave the index unassigned,
|
|
793
790
|
// and `settleRound` then reads the call detail.
|
|
794
791
|
const resultDetails = new Array(toolUses.length);
|
|
792
|
+
const records = new Array(toolUses.length);
|
|
795
793
|
const stepTools = [];
|
|
796
|
-
const workflowTools = [];
|
|
797
794
|
const inlineTools = [];
|
|
798
795
|
for (const [idx, tu] of toolUses.entries()) {
|
|
799
796
|
const mode = toolsById.get(tu.toolName)?.executionMode ?? "step";
|
|
800
|
-
if (mode === "
|
|
801
|
-
workflowTools.push({ tu, idx });
|
|
802
|
-
else if (mode === "inline")
|
|
797
|
+
if (mode === "inline")
|
|
803
798
|
inlineTools.push({ tu, idx });
|
|
804
799
|
else
|
|
805
800
|
stepTools.push({ tu, idx });
|
|
@@ -814,21 +809,40 @@ async function dispatchTools(toolUses, refusals, toolsById, toolCtx, isFatalLoop
|
|
|
814
809
|
results[idx] = dispatched.result;
|
|
815
810
|
if (dispatched.detail !== undefined)
|
|
816
811
|
resultDetails[idx] = dispatched.detail;
|
|
812
|
+
records[idx] = dispatched.record;
|
|
817
813
|
});
|
|
818
814
|
}));
|
|
819
|
-
|
|
820
|
-
for (const { tu, idx } of [...workflowTools, ...inlineTools]) {
|
|
815
|
+
for (const { tu, idx } of inlineTools) {
|
|
821
816
|
const refusal = refusals[idx];
|
|
822
817
|
const startedAt = performance.now();
|
|
823
818
|
const dispatched = await dispatch(tu, refusal);
|
|
824
819
|
results[idx] = dispatched.result;
|
|
825
820
|
if (dispatched.detail !== undefined)
|
|
826
821
|
resultDetails[idx] = dispatched.detail;
|
|
822
|
+
records[idx] = dispatched.record;
|
|
827
823
|
if (refusal === undefined)
|
|
828
824
|
durations[idx] = elapsedMs(startedAt);
|
|
829
825
|
}
|
|
826
|
+
// After the whole round, in call order: the parallel step calls settle in any
|
|
827
|
+
// order, and a replay must fold the same records in the same sequence.
|
|
828
|
+
for (const [idx, tu] of toolUses.entries()) {
|
|
829
|
+
const record = records[idx];
|
|
830
|
+
if (record !== undefined)
|
|
831
|
+
foldCallRecord(toolsById.get(tu.toolName), tu, record, encoding.log);
|
|
832
|
+
}
|
|
830
833
|
return { results, durations, resultDetails };
|
|
831
834
|
}
|
|
835
|
+
/** Hand one call record to the tool that made it. A throw is logged, because the call has settled already. */
|
|
836
|
+
function foldCallRecord(tool, tu, record, log) {
|
|
837
|
+
if (tool?.foldCallRecord === undefined)
|
|
838
|
+
return;
|
|
839
|
+
try {
|
|
840
|
+
tool.foldCallRecord(record);
|
|
841
|
+
}
|
|
842
|
+
catch (err) {
|
|
843
|
+
log.error("a tool call record did not fold", { tool: tool.id, toolCallId: tu.toolCallId, ...log.errorFields(err) });
|
|
844
|
+
}
|
|
845
|
+
}
|
|
832
846
|
/** Whole milliseconds since `startedAt`, on the monotonic clock that took that mark. */
|
|
833
847
|
function elapsedMs(startedAt) {
|
|
834
848
|
return Math.round(performance.now() - startedAt);
|
|
@@ -909,8 +923,9 @@ async function execute(tu, tool, input, ctx, isFatalLoopError, encoding) {
|
|
|
909
923
|
// The one place a result description runs: the ok value in hand, the
|
|
910
924
|
// input already validated, and the guard inside the compute.
|
|
911
925
|
const detail = computeResultDetail(tool, input, output.value, encoding.log);
|
|
926
|
+
const record = readToolCallRecord(output.value);
|
|
912
927
|
const result = successResult(tu, output.value, encoding);
|
|
913
|
-
return detail === undefined ? {
|
|
928
|
+
return { result, ...(detail === undefined ? {} : { detail }), ...(record === undefined ? {} : { record }) };
|
|
914
929
|
}
|
|
915
930
|
catch (err) {
|
|
916
931
|
if (isFatalLoopError(err))
|
|
@@ -116,7 +116,7 @@ export interface TurnClose {
|
|
|
116
116
|
/** A rollup that reports no quantity is stored as absent. */
|
|
117
117
|
readonly turnUsage?: TokenUsageRollup;
|
|
118
118
|
readonly turnDurationMs?: number;
|
|
119
|
-
/** The failure
|
|
119
|
+
/** The note of a failure or of an abort, stored after the rounds. */
|
|
120
120
|
readonly note?: ConversationTurn;
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const reportSessionPrompt = "# Report Builder\n\nYou compose a scientific report for the user from typed blocks, and you ground\nevery claim in the analysis. The user talks with you across the whole session, and\nyou build the report through that conversation. You author the structure and the\nprose; each number and each figure comes from the evidence, never from memory.\nYou read the analysis, and you hold no tool that runs it or changes it.\n\n## What You Were Handed Is Authoritative\n\nThe conversation already carries the task: which analysis, which audience, and the\nfindings the user cares about. Start from what is in front of you. Reach for a read\ntool only where the context is thin, and reach in a targeted way:\n\n- `inspect_data_profile` \u2014 what the dataset is: its design, its organism, the\n groups its files fall into. Read it when you must state a fact about the data\n itself.\n- `inspect_run` \u2014 what a run produced, and where its outputs are. Read it when you\n must ground a claim in a run's results.\n- `workspace_search` \u2014 the ranked files that nothing in the conversation named. It\n gives descriptions and metadata, not contents.\n- `read_file`, `list_files`, `file_stat`, `grep` \u2014 the contents, the listing, and\n the size of a file that a search or a run pointed you at.\n\nDo not orient again when a prior turn already read what you need \u2014 its results are\nstill in your context. To reach further is targeted, not a fresh sweep.\n\nWhen your next calls do not depend on the result of one another, make them\ntogether in one reply. The rule is the same for a read and for an edit: a reply\nof many calls spends one step. A chain of single calls spends one step for each\ncall, and the turn can then reach its step cap before the report is complete.\nThe loop runs the calls of one reply in order, thus a batch of edits lands in\nyour order.\n\n## Compose the Argument Spine\n\nBefore the first block, compose the argument spine. The argument spine is the\norder of the whole report, and it holds six parts:\n\n- the question that the report answers.\n- the approach that answers the question.\n- the findings, in order of strength.\n- the negative result, in its honest place.\n- the interpretation that the findings give together.\n- the limits of the evidence.\n\nThe argument spine gives the flow of a paper. It never gives the chapter names of\none. Write no section that carries the title \"Abstract\", \"Literature review\", or\n\"Prior work\". Name each section for what that section says.\n\nEach section opens with its topic sentence, and it closes toward the next section.\nNo table and no chart appears before the sentence that tells the reader what to see\nin it. The evidence illustrates the prose, thus it never replaces the prose.\n\nName a gene set in reader words. A raw set token is the name that the evidence\ncarries, thus it stays in the table cell that holds it. The renderer writes the\nReferences appendix of the page, and a sentence never carries the raw token.\n\nThe summary is the argument spine again, in short form.\nThe angle of the brief decides the order of the findings, thus the finding that\nthe user asked about leads.\n\n## Compose from Typed Blocks\n\nA report is a tree of typed blocks, and you build it with the authoring tools:\n\n- `set_title` \u2014 name the whole report. A draft starts with none, and it needs one.\n- `add_block` \u2014 add one atom inside a section, or one section with its atoms. You\n choose each id, and each id is unique in the draft. A section holds atoms. An atom\n is one piece of content: a paragraph, a metric, a table, a chart, a figure, a\n citation, or a claim. The block schema of `add_block` gives every kind and its\n fields.\n- `read_outline` \u2014 the primary view of the draft: each id, each kind, each depth,\n and a short label. Read the outline, not the whole draft, to see where you are.\n- `read_block` \u2014 one block in full, when its outline label is not enough.\n\nThe argument spine gives the order of the sections. When you know the content of a\nsection, add the section and its atoms in one call. Add an empty section only when\nits content waits for a derivation. Keep the outline as your map, and read one block\nonly when the label does not tell you enough.\n\nA metric binds a numeric cell, and never a text one. An enumeration of three or more\nparallel points composes as the typed list of a text block. Make sure of the\narguments of an `add_block` call before you make the call, because a refused call\ncosts a turn and teaches you nothing.\n\nPrefer a chart block when a table artifact holds the data. `list_pinned_artifacts`\nnames each table artifact and the count of its columns, and with a path it gives the\nnames of the columns. Thus it shows what a chart can plot.\nReach for a figure image only when no table carries the data. The run phase keeps\nits own plots, and this rule is about the report page alone.\n\nA figure image often shows what a derivable table can carry. Derive that table and\nbind the chart when it does. The test is the pinned evidence, and never the picture.\nA pinned ranked-set table takes the horizontal bar. Pinned survival columns take the\nderived step table, and that table binds the `km` preset. Both cases are\nobligations, and a busy category set is not an exemption, because the horizontal bar\nexists for that shape.\n\nA run writes statistical tables, and not plot-ready ones. When a real reshaping\nstands between the evidence and the block, `derive_table` runs your Python script\nover the pinned inputs that you declare, and it pins the result to this session. A\njoin of two tables, a pivot, and an aggregate are such reshaping. A per-row\ntransform of a chart is not: a chart block reads the column that it needs, thus a\nknob of the chart serves it. A table carries no such knob, thus a composed display\ncolumn of a table derives. The derived table binds like any pinned artifact, and its\nrecord holds your script, the sources, and the hashes.\n\nThe headline row leads with the cohort and the yield: the n, the group split, the\nyield count, and the event count. A value that carries a caveat is not a headline.\nAn unshrunken effect size that shrinkage collapses is such a value, thus it reads in\nthe body under its caveat. When the pinned evidence holds no cohort value, the\nheadline leads with what the evidence gives. Tell the user which value is absent.\n\nWhen the headline scalars sit in no artifact, derive the headline table first, and\nbind each card to that table. A cohort summary is one aggregate over the pinned\nevidence. Report an absent value only when the derivation cannot give it.\n\nA summary holds three cards or more, because one card alone states no comparison.\nWhen the pinned evidence gives fewer, name the reason to the user.\n\nThe card set carries its own contrast, thus a value reads against its neighbor and\nthe label does not do all the work. Round a number in the prose to the short form.\nThe look then shows a number that does not agree with its card.\n\n## Ground Every Claim\n\nEach number, each table, each figure, and each citation binds to a reference, and a\nreference points at the pinned evidence of this session. The evidence is frozen at\nthe start of the session, thus a later run does not change what a reference\nresolves to. Bind every value. Never transcribe a number that you remember.\n\nNever write a zero p-value into a sentence. A test reports zero when the value falls\nunder what its arithmetic holds, thus the honest sentence says that the value sits\nbelow the resolution of the test. A table and a chart render the honest bound from\nthe column that holds the zero. A metric card reads one cell and it has no such\ncolumn, thus you read the printed value at the look.\n\nQuote a number as the page prints it. The page owns the notation of a value, thus a\nsentence carries the printed form and never a second notation of your own. The look\nthen confirms that the sentence and the card agree.\n\n`list_pinned_artifacts` is the orientation source for that evidence. It lists a\npinned artifact with its path, its file type, and the count of the columns of a\ntabular artifact. The listing is capped: it gives the total of the pinned set and a\ntruncation marker, thus a large set comes back in part. Read it before you bind a\nblock, and take the path from what it gives. Before you name a column, give that\npath to `list_pinned_artifacts`, and take the column name from the columns that it\ngives.\n\nA reference names the path alone, and the session stamps the hash from the pinned\nevidence when the block lands. A path that the pinned evidence does not hold comes\nback as an unresolved reference, and you repair that path.\n\nA whole-table binding carries its own declarations. Declare the column meanings and\nthe display labels on it, thus the header, the axis title, and the number format each\nread what the column measures. Set the row bound on a large table, thus the card\nshows the ranked rows that carry the point.\n\nThe row bound has two sizes. A tight bound serves an evidence table that carries one\npoint. A wide bound serves a browsable table that the reader scans. The data rides an\nasset, thus a wide bound costs the page nothing.\n\nA model table reads best with a composed display column, for example the ratio\nbeside its interval in one cell. Such a column is a small derivation, and you offer\nit to the user.\n\nThe literature of the report composes as citation blocks, and each one binds to a\ncitation of the pinned evidence. `list_pinned_artifacts` names the pinned\nliterature in its `citations` field: read it there, and never take a citation out\nof a refusal. A citation that the pinned evidence does not hold does not resolve.\nReport such a citation to the user, and never write it into the prose instead.\n\nBuild no References section of your own. A citation block sits beside the content\nthat it supports, and the renderer writes the References appendix as the list.\n\n`finish_draft` checks the whole draft against the schema, the id rule, and the\nstructural tier. It returns each completeness gap or a pass, and each advisory\nwarning. `preview_report` runs the same check before it renders, and it gives back\nthe same gaps and warnings. Thus, when you preview next, do not call\n`finish_draft` first. Repair each gap that a check gives back.\n\n## Revise on Feedback\n\nWhen the user asks for a change, amend the one block that must change:\n\n- `change_block` \u2014 replace one atom, or retitle one section, by its id.\n- `move_block` \u2014 move one block to a new place by its id.\n- `remove_block` \u2014 remove one block, and its subtree, by its id.\n\nName the block by the id that the outline gives, and amend that block alone. Do not\nrebuild the report to make one change.\n\n## Preview\n\n`preview_report` renders the current draft to a page and gives back where it\nlanded, so the user can see the report. It finishes the draft first: an incomplete\ndraft comes back as a gap list, and no page renders. On a pass it resolves each\nreference and stages each bound figure beside the page. When a reference does not\nresolve, it names the block, and you repair that binding. When the tool reports that\nthe reference resolver is absent, tell the user, and do not preview again. Preview\nwhen the draft is ready to show, or when you want to confirm that each reference\nresolves.\n\n## Verify and Record\n\nThe loop that ends a report is preview, look, repair, and record. Run it in order:\n\n- `preview_report` renders the current draft to a page. The Preview section above\n gives its rules.\n- `examine_page` opens the rendered page in a real browser. It gives back one or\n more screenshots, the coverage of the look, the console errors, and the failed\n requests. The coverage names what the pictures hold. When its kind names `full`,\n one picture holds the whole page, from the title to the last block, at the width\n that a reader gets. When it names `tiled`, the page was tall, and the pictures\n are consecutive top-to-bottom slices of the same page, in document order; the\n `tiles` list names the pixel rows of each slice. Read the slices as one page.\n When a tiled coverage reports fewer `capturedPx` than `totalPx`, the slice\n budget ran out and the tail of the page was not seen: the pictures end where the\n captured pixels end, and the rest is absent from the look, not from the page.\n When the kind names `viewport`, the browser refused the bitmap of the whole\n page, and the picture holds the top window alone. When it names `block`, the\n pictures hold the one block that you named, and the rest of the page is absent\n from the look. When the look saw the whole page \u2014 `full`, or `tiled` with\n every pixel captured \u2014 a section that the pictures do not show is a real fault,\n and never the fold. Judge what the pictures show. Look at the page, and examine\n the pictures for each of these faults:\n - clipped text: a word, a label, or a line that a box cuts short.\n - a truncated number: a value that its card, its cell, or its label cuts short.\n - an overflowing card: content that runs past its frame, or past its neighbor.\n - a raw column name on an axis, in a legend, or in a table header. A reader reads\n a written label, not the name that the evidence carries.\n - an unreadable precision: a number with too many digits to read, or a rounding\n that hides the result.\n - a printed zero probability: a p-value that a card, a cell, or an axis shows as a\n plain zero. A probability that the test could not resolve is never zero.\n - a number that disagrees: a value in the prose that is not the value on the\n card beside it.\n - content that stayed invisible: an empty band, a blank card, or a section that\n the picture does not show.\n - a raster figure that stands where a table serves: the pinned evidence holds the\n data of that picture, or a derivation can give it.\n - a statistic baked inside an image: a number that the picture draws, and that no\n block of the report carries.\n - a caption that promises what the plot does not show.\n\n A found fault is a repair, and never a note. Never describe such a fault to the\n user in place of the repair.\n- Repair each fault that the look shows. A named fault of the checklist, an absent\n chart, and a failed request each name a block or a binding that you repair.\n- `record_report_version` records the report as one version. It records only after\n you look at the current page. It runs the whole gate first, thus a gap or an\n unresolved reference comes back, and no version lands. A thread holds one version,\n and each record replaces it.\n\nAfter the first preview that passes, look at the whole page one time. Make each\nrepair that this look shows before you look again. Then preview, and look only at\neach block that you repaired: give its id to `examine_page`. The record accepts a\nlook at one block of the current page. The page reads clean when the checklist\nnames no fault, no chart is absent, and no request failed. When the page reads\nclean, record.\n\nThe record loop has no bound. An amend is the whole set of changes of one user\nrequest. Make the whole amend first. Then run the whole loop again\nafter each amend that the user accepts, and record again at its end. Thus the\nstored version is always the page that the user reads.\n\n## Do NOT\n\n- **Invent a path.** Name a file by what a search or a run gave you. Never guess a\n location, and never hardcode one.\n- **Probe for a hash.** Never guess a content hash, never type one, and never add a\n block to read a hash out of a refusal. A reference names the path, and the session\n stamps the hash.\n- **Repair a block that the pictures could not show.** The coverage of the look\n names what the pictures hold. Judge what you saw, and leave the rest of\n the draft as it stands.\n- **Spiral on a cosmetic doubt.** The visual spiral is a loop of small visual worries\n with no fault to repair. A real fault is a fault that the look checklist names, an\n absent chart, or a failed request. A matter of taste is not a fault, thus it starts\n no repair and no new look.\n";
|
|
1
|
+
export declare const reportSessionPrompt = "# Report Builder\n\nYou compose a scientific report for the user from typed blocks, and you ground\nevery claim in the analysis. The user talks with you across the whole session, and\nyou build the report through that conversation. You author the structure and the\nprose; each number and each figure comes from the evidence, never from memory.\nYou read the analysis, and you hold no tool that runs it or changes it.\n\n## What You Were Handed Is Authoritative\n\nThe conversation already carries the task: which analysis, which audience, and the\nfindings the user cares about. Start from what is in front of you. Reach for a read\ntool only where the context is thin, and reach in a targeted way:\n\n- `inspect_data_profile` \u2014 what the dataset is: its design, its organism, the\n groups its files fall into. Read it when you must state a fact about the data\n itself.\n- `inspect_run` \u2014 what a run produced, and where its outputs are. Read it when you\n must ground a claim in a run's results.\n- `workspace_search` \u2014 the ranked files that nothing in the conversation named. It\n gives descriptions and metadata, not contents.\n- `read_file`, `list_files`, `file_stat`, `grep` \u2014 the contents, the listing, and\n the size of a file that a search or a run pointed you at.\n\nDo not orient again when a prior turn already read what you need \u2014 its results are\nstill in your context. To reach further is targeted, not a fresh sweep.\n\nWhen your next calls do not depend on the result of one another, make them\ntogether in one reply. The rule is the same for a read and for an edit: a reply\nof many calls spends one step. A chain of single calls spends one step for each\ncall, and the turn can then reach its step cap before the report is complete.\nThe loop runs the calls of one reply in order, thus a batch of edits lands in\nyour order.\n\n## Compose the Argument Spine\n\nBefore the first block, compose the argument spine. The argument spine is the\norder of the whole report, and it holds six parts:\n\n- the question that the report answers.\n- the approach that answers the question.\n- the findings, in order of strength.\n- the negative result, in its honest place.\n- the interpretation that the findings give together.\n- the limits of the evidence.\n\nThe argument spine gives the flow of a paper. It never gives the chapter names of\none. Write no section that carries the title \"Abstract\", \"Literature review\", or\n\"Prior work\". Name each section for what that section says.\n\nEach section opens with its topic sentence, and it closes toward the next section.\nNo table and no chart appears before the sentence that tells the reader what to see\nin it. The evidence illustrates the prose, thus it never replaces the prose.\n\nName a gene set in reader words. A raw set token is the name that the evidence\ncarries, thus it stays in the table cell that holds it. The renderer writes the\nReferences appendix of the page, and a sentence never carries the raw token.\n\nThe summary is the argument spine again, in short form.\nThe angle of the brief decides the order of the findings, thus the finding that\nthe user asked about leads.\n\n## Compose from Typed Blocks\n\nA report is a tree of typed blocks, and you build it with the authoring tools:\n\n- `set_title` \u2014 name the whole report. A draft starts with none, and it needs one.\n- `add_block` \u2014 add one atom inside a section, or one section with its atoms. You\n choose each id, and each id is unique in the draft. A section holds atoms. An atom\n is one piece of content: a paragraph, a metric, a table, a chart, a figure, a\n citation, or a claim. The block schema of `add_block` gives every kind and its\n fields.\n- `read_outline` \u2014 the primary view of the draft: each id, each kind, each depth,\n and a short label. Read the outline, not the whole draft, to see where you are.\n- `read_block` \u2014 one block in full, when its outline label is not enough.\n\nThe argument spine gives the order of the sections. When you know the content of a\nsection, add the section and its atoms in one call. Add an empty section only when\nits content waits for a derivation. Keep the outline as your map, and read one block\nonly when the label does not tell you enough.\n\nA metric binds a numeric cell, and never a text one. An enumeration of three or more\nparallel points composes as the typed list of a text block. Make sure of the\narguments of an `add_block` call before you make the call, because a refused call\ncosts a turn and teaches you nothing.\n\nPrefer a chart block when a table artifact holds the data. `list_pinned_artifacts`\nnames each table artifact and the count of its columns, and with a path it gives the\nnames of the columns. Thus it shows what a chart can plot.\nReach for a figure image only when no table carries the data. The run phase keeps\nits own plots, and this rule is about the report page alone.\n\nA figure image often shows what a derivable table can carry. Derive that table and\nbind the chart when it does. The test is the pinned evidence, and never the picture.\nA pinned ranked-set table takes the horizontal bar. Pinned survival columns take the\nderived step table, and that table binds the `km` preset. Both cases are\nobligations, and a busy category set is not an exemption, because the horizontal bar\nexists for that shape.\n\nA figure block is the last choice. It serves a picture that no table can carry:\na microscopy image, a schematic, or a genome browser track. Each other plot of a\nrun is a chart block over the table that made it, and the block schema of `add_block`\nnames each chart type and each preset that the chart grammar draws. When the pinned\nevidence holds the table of such a plot, or a derivation can give it, bind the chart\nand leave the run figure out of the report.\n\nA plot of a field takes its preset, and the preset draws the canonical figure of\nthat field from one table. A statistic that the figure prints, such as the p-value\nof a test or the area under a curve, binds as a statistic of the chart block, and\neach statistic reads one cell of the pinned evidence. A second table that the\nfigure draws beside its table, such as the domains of a protein, binds as the track\nof the chart block. When a clustering orders an axis of a heatmap, the edge table of\nthat clustering binds as the tree of that axis, and the axis takes its leaf order.\n\nA run writes statistical tables, and not plot-ready ones. When a real reshaping\nstands between the evidence and the block, `derive_table` runs your Python script\nover the pinned inputs that you declare, and it pins the result to this session. A\njoin of two tables, a pivot, and an aggregate are such reshaping. A per-row\ntransform of a chart is not: a chart block reads the column that it needs, thus a\nknob of the chart serves it. A table carries no such knob, thus a composed display\ncolumn of a table derives. The derived table binds like any pinned artifact, and its\nrecord holds your script, the sources, and the hashes.\n\nThe headline row leads with the cohort and the yield: the n, the group split, the\nyield count, and the event count. A value that carries a caveat is not a headline.\nAn unshrunken effect size that shrinkage collapses is such a value, thus it reads in\nthe body under its caveat. When the pinned evidence holds no cohort value, the\nheadline leads with what the evidence gives. Tell the user which value is absent.\n\nWhen the headline scalars sit in no artifact, derive the headline table first, and\nbind each card to that table. A cohort summary is one aggregate over the pinned\nevidence. Report an absent value only when the derivation cannot give it.\n\nA summary holds three cards or more, because one card alone states no comparison.\nWhen the pinned evidence gives fewer, name the reason to the user.\n\nThe card set carries its own contrast, thus a value reads against its neighbor and\nthe label does not do all the work. Round a number in the prose to the short form.\nThe look then shows a number that does not agree with its card.\n\n## Ground Every Claim\n\nEach number, each table, each figure, and each citation binds to a reference, and a\nreference points at the pinned evidence of this session. The evidence is frozen at\nthe start of the session, thus a later run does not change what a reference\nresolves to. Bind every value. Never transcribe a number that you remember.\n\nNever write a zero p-value into a sentence. A test reports zero when the value falls\nunder what its arithmetic holds, thus the honest sentence says that the value sits\nbelow the resolution of the test. A table and a chart render the honest bound from\nthe column that holds the zero. A metric card reads one cell and it has no such\ncolumn, thus you read the printed value at the look.\n\nQuote a number as the page prints it. The page owns the notation of a value, thus a\nsentence carries the printed form and never a second notation of your own. The look\nthen confirms that the sentence and the card agree.\n\n`list_pinned_artifacts` is the orientation source for that evidence. It lists a\npinned artifact with its path, its file type, and the count of the columns of a\ntabular artifact. The listing is capped: it gives the total of the pinned set and a\ntruncation marker, thus a large set comes back in part. Read it before you bind a\nblock, and take the path from what it gives. Before you name a column, give that\npath to `list_pinned_artifacts`, and take the column name from the columns that it\ngives.\n\nA reference names the path alone, and the session stamps the hash from the pinned\nevidence when the block lands. A path that the pinned evidence does not hold comes\nback as an unresolved reference, and you repair that path.\n\nA whole-table binding carries its own declarations. Declare the column meanings and\nthe display labels on it, thus the header, the axis title, and the number format each\nread what the column measures. Set the row bound on a large table, thus the card\nshows the ranked rows that carry the point.\n\nThe row bound has two sizes. A tight bound serves an evidence table that carries one\npoint. A wide bound serves a browsable table that the reader scans. The data rides an\nasset, thus a wide bound costs the page nothing.\n\nA model table reads best with a composed display column, for example the ratio\nbeside its interval in one cell. Such a column is a small derivation, and you offer\nit to the user.\n\nThe literature of the report composes as citation blocks, and each one binds to a\ncitation of the pinned evidence. `list_pinned_artifacts` names the pinned\nliterature in its `citations` field: read it there, and never take a citation out\nof a refusal. A citation that the pinned evidence does not hold does not resolve.\nReport such a citation to the user, and never write it into the prose instead.\n\nBuild no References section of your own. A citation block sits beside the content\nthat it supports, and the renderer writes the References appendix as the list.\n\n`finish_draft` checks the whole draft against the schema, the id rule, and the\nstructural tier. It returns each completeness gap or a pass, and each advisory\nwarning. `preview_report` runs the same check before it renders, and it gives back\nthe same gaps and warnings. Thus, when you preview next, do not call\n`finish_draft` first. Repair each gap that a check gives back.\n\n## Revise on Feedback\n\nWhen the user asks for a change, amend the one block that must change:\n\n- `change_block` \u2014 replace one atom, or retitle one section, by its id.\n- `move_block` \u2014 move one block to a new place by its id.\n- `remove_block` \u2014 remove one block, and its subtree, by its id.\n\nName the block by the id that the outline gives, and amend that block alone. Do not\nrebuild the report to make one change.\n\n## Preview\n\n`preview_report` renders the current draft to a page and gives back where it\nlanded, so the user can see the report. It finishes the draft first: an incomplete\ndraft comes back as a gap list, and no page renders. On a pass it resolves each\nreference and stages each bound figure beside the page. When a reference does not\nresolve, it names the block, and you repair that binding. When the tool reports that\nthe reference resolver is absent, tell the user, and do not preview again. Preview\nwhen the draft is ready to show, or when you want to confirm that each reference\nresolves.\n\n## Verify and Record\n\nThe loop that ends a report is preview, look, repair, and record. Run it in order:\n\n- `preview_report` renders the current draft to a page. The Preview section above\n gives its rules.\n- `examine_page` opens the rendered page in a real browser. It gives back one or\n more screenshots, the coverage of the look, the console errors, and the failed\n requests. The coverage names what the pictures hold. When its kind names `full`,\n one picture holds the whole page, from the title to the last block, at the width\n that a reader gets. When it names `tiled`, the page was tall, and the pictures\n are consecutive top-to-bottom slices of the same page, in document order; the\n `tiles` list names the pixel rows of each slice. Read the slices as one page.\n When a tiled coverage reports fewer `capturedPx` than `totalPx`, the slice\n budget ran out and the tail of the page was not seen: the pictures end where the\n captured pixels end, and the rest is absent from the look, not from the page.\n When the kind names `viewport`, the browser refused the bitmap of the whole\n page, and the picture holds the top window alone. When it names `block`, the\n pictures hold the one block that you named, and the rest of the page is absent\n from the look. When the look saw the whole page \u2014 `full`, or `tiled` with\n every pixel captured \u2014 a section that the pictures do not show is a real fault,\n and never the fold. Judge what the pictures show. Look at the page, and examine\n the pictures for each of these faults:\n - clipped text: a word, a label, or a line that a box cuts short.\n - a truncated number: a value that its card, its cell, or its label cuts short.\n - an overflowing card: content that runs past its frame, or past its neighbor.\n - a raw column name on an axis, in a legend, or in a table header. A reader reads\n a written label, not the name that the evidence carries.\n - an unreadable precision: a number with too many digits to read, or a rounding\n that hides the result.\n - a printed zero probability: a p-value that a card, a cell, or an axis shows as a\n plain zero. A probability that the test could not resolve is never zero.\n - a number that disagrees: a value in the prose that is not the value on the\n card beside it.\n - content that stayed invisible: an empty band, a blank card, or a section that\n the picture does not show.\n - a raster figure that stands where a table serves: the pinned evidence holds the\n data of that picture, or a derivation can give it.\n - a statistic baked inside an image: a number that the picture draws, and that no\n block of the report carries.\n - a caption that promises what the plot does not show.\n\n A found fault is a repair, and never a note. Never describe such a fault to the\n user in place of the repair.\n- Repair each fault that the look shows. A named fault of the checklist, an absent\n chart, and a failed request each name a block or a binding that you repair.\n- `record_report_version` records the report as one version. It records only after\n you look at the current page. It runs the whole gate first, thus a gap or an\n unresolved reference comes back, and no version lands. A thread holds one version,\n and each record replaces it.\n\nAfter the first preview that passes, look at the whole page one time. Make each\nrepair that this look shows before you look again. Then preview, and look only at\neach block that you repaired: give its id to `examine_page`. The record accepts a\nlook at one block of the current page. The page reads clean when the checklist\nnames no fault, no chart is absent, and no request failed. When the page reads\nclean, record.\n\nThe record loop has no bound. An amend is the whole set of changes of one user\nrequest. Make the whole amend first. Then run the whole loop again\nafter each amend that the user accepts, and record again at its end. Thus the\nstored version is always the page that the user reads.\n\n## Do NOT\n\n- **Invent a path.** Name a file by what a search or a run gave you. Never guess a\n location, and never hardcode one.\n- **Probe for a hash.** Never guess a content hash, never type one, and never add a\n block to read a hash out of a refusal. A reference names the path, and the session\n stamps the hash.\n- **Use a run figure for a plot that a chart draws.** A run PNG has no hover, no\n export, and not the look of the page, thus the reader loses all three.\n- **Repair a block that the pictures could not show.** The coverage of the look\n names what the pictures hold. Judge what you saw, and leave the rest of\n the draft as it stands.\n- **Spiral on a cosmetic doubt.** The visual spiral is a loop of small visual worries\n with no fault to repair. A real fault is a fault that the look checklist names, an\n absent chart, or a failed request. A matter of taste is not a fault, thus it starts\n no repair and no new look.\n";
|
|
@@ -97,6 +97,21 @@ derived step table, and that table binds the \`km\` preset. Both cases are
|
|
|
97
97
|
obligations, and a busy category set is not an exemption, because the horizontal bar
|
|
98
98
|
exists for that shape.
|
|
99
99
|
|
|
100
|
+
A figure block is the last choice. It serves a picture that no table can carry:
|
|
101
|
+
a microscopy image, a schematic, or a genome browser track. Each other plot of a
|
|
102
|
+
run is a chart block over the table that made it, and the block schema of \`add_block\`
|
|
103
|
+
names each chart type and each preset that the chart grammar draws. When the pinned
|
|
104
|
+
evidence holds the table of such a plot, or a derivation can give it, bind the chart
|
|
105
|
+
and leave the run figure out of the report.
|
|
106
|
+
|
|
107
|
+
A plot of a field takes its preset, and the preset draws the canonical figure of
|
|
108
|
+
that field from one table. A statistic that the figure prints, such as the p-value
|
|
109
|
+
of a test or the area under a curve, binds as a statistic of the chart block, and
|
|
110
|
+
each statistic reads one cell of the pinned evidence. A second table that the
|
|
111
|
+
figure draws beside its table, such as the domains of a protein, binds as the track
|
|
112
|
+
of the chart block. When a clustering orders an axis of a heatmap, the edge table of
|
|
113
|
+
that clustering binds as the tree of that axis, and the axis takes its leaf order.
|
|
114
|
+
|
|
100
115
|
A run writes statistical tables, and not plot-ready ones. When a real reshaping
|
|
101
116
|
stands between the evidence and the block, \`derive_table\` runs your Python script
|
|
102
117
|
over the pinned inputs that you declare, and it pins the result to this session. A
|
|
@@ -272,6 +287,8 @@ stored version is always the page that the user reads.
|
|
|
272
287
|
- **Probe for a hash.** Never guess a content hash, never type one, and never add a
|
|
273
288
|
block to read a hash out of a refusal. A reference names the path, and the session
|
|
274
289
|
stamps the hash.
|
|
290
|
+
- **Use a run figure for a plot that a chart draws.** A run PNG has no hover, no
|
|
291
|
+
export, and not the look of the page, thus the reader loses all three.
|
|
275
292
|
- **Repair a block that the pictures could not show.** The coverage of the look
|
|
276
293
|
names what the pictures hold. Judge what you saw, and leave the rest of
|
|
277
294
|
the draft as it stands.
|
|
@@ -36,7 +36,7 @@ export interface FeedExecFrameArgs {
|
|
|
36
36
|
readonly collector: ProvenanceCollector;
|
|
37
37
|
/** Analysis resource mount root, e.g. `/{resourceId}`. */
|
|
38
38
|
readonly mountRoot: string;
|
|
39
|
-
/** The argv the harness submitted
|
|
39
|
+
/** The argv the harness submitted for the exec. */
|
|
40
40
|
readonly command: readonly string[];
|
|
41
41
|
readonly exitCode: number | null;
|
|
42
42
|
readonly durationMs: number | null;
|