Merge remote-tracking branch 'origin/master' into feat/wake-idle-owner-on-task-completion

This commit is contained in:
Yichen Jiang
2026-08-11 19:38:49 +08:00
247 changed files with 4899 additions and 1023 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/attachment.md
attachment.md: bfc1a54107c75b442f6b5b61fb705852ab4213db
attachment.zh.md: 4da600390ea111e9b2f640c51ab786ca0505db6e
attachment.md: ff7f14ceae8d4f8055d5cfd4367373729dc5ecbc
attachment.zh.md: d7a9527788588d5504fdeffd8ae7849b0f8b1378

View File

@@ -104,9 +104,11 @@ abstract saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef>
/**
* Read one image and verify that bytes still match the recorded reference.
* @param ref - durable reference from the session log.
* @param signal - optional cancellation for backend read and verification work.
* @returns the verified bytes and canonical reference.
* @throws the signal reason when aborted, or a storage error when verification fails.
*/
abstract readImage(ref: ImageAttachmentRef): Promise<StoredImageAttachment>
abstract readImage(ref: ImageAttachmentRef, signal?: AbortSignal): Promise<StoredImageAttachment>
```
Source: [`packages/attachment/attachment/src/index.ts:29`](../../packages/attachment/attachment/src/index.ts)

View File

@@ -104,9 +104,11 @@ abstract saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef>
/**
* Read one image and verify that bytes still match the recorded reference.
* @param ref - durable reference from the session log.
* @param signal - optional cancellation for backend read and verification work.
* @returns the verified bytes and canonical reference.
* @throws the signal reason when aborted, or a storage error when verification fails.
*/
abstract readImage(ref: ImageAttachmentRef): Promise<StoredImageAttachment>
abstract readImage(ref: ImageAttachmentRef, signal?: AbortSignal): Promise<StoredImageAttachment>
```
Source: [`packages/attachment/attachment/src/index.ts:29`](../../packages/attachment/attachment/src/index.ts)

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/persistence.md
persistence.md: 792d50c52ecb2255dee429098d2ef00744479292
persistence.zh.md: 6e1f29ee6dfc12193e7e5e4e79b4bfc5f751410f
persistence.md: fde8348d64a200eda5133abf66deedee6be09857
persistence.zh.md: 7a334501ee7fcbefda9d1381dfe41a79679d33b3

View File

@@ -124,7 +124,7 @@ Replay/fork is therefore `ctx.sessions.create(id, { seed: seedEvents })`; resumi
## `SessionRawArtifact` — verbatim stored artifact text
A backend's own artifact text for one session, byte-identical to what it durably wrote (decoded from its physical encoding). `readRaw` returns it without reconstructing from parsed events, so backend-specific serialization (chunk packing, key order, line breaks) survives; backends without a per-session artifact, such as SQLite, inherit the `undefined` default.
A backend's own artifact text for one session, byte-identical to what it durably wrote (decoded from its physical encoding). `readRaw` returns it without reconstructing from parsed events, so backend-specific serialization (chunk packing, key order, line breaks) survives. Consumers first test `supportsRawArtifacts`: `false` means the backend does not provide this capability (for example SQLite), while `readRaw(...) === undefined` means a supported backend has no materialized artifact for that session.
```ts type-equiv
/** A backend's own raw artifact text for one session, verbatim. */
@@ -262,13 +262,15 @@ abstract locate(meta: SessionHeader): SessionLocation | undefined
* bytes the backend wrote (decoded from its physical encoding, e.g. a
* decompressed JSONL). The returned `content` is the raw text, not a
* reconstruction from parsed events, so it preserves backend-specific
* serialization (chunk packing, key order, line breaks). Backends without a
* per-session artifact (SQLite) inherit the `undefined` default.
* serialization (chunk packing, key order, line breaks). Callers first test
* {@link supportsRawArtifacts}; `undefined` then means only that the requested
* session has no materialized artifact.
* @param _id - the persisted session to read (unused by the default: no
* per-session artifact).
* @param signal - optional cancellation for backend read work.
* @returns the raw artifact plus its parsed header, or `undefined` when the
* session is absent or the backend owns no per-session artifact.
* session is absent.
* @throws when this backend does not expose per-session raw artifacts.
*/
readRaw(_id: SessionId, signal?: AbortSignal): Promise<SessionRawArtifact | undefined>

View File

@@ -124,7 +124,7 @@ interface CreateSessionOptions {
## `SessionRawArtifact`——逐字存储工件文本
后端为单个会话自持的工件文本,与其持久化写入的字节逐字一致(按物理编码解码)。`readRaw` 返回它而不从解析后事件重建因此后端特定的序列化chunk 打包、键序、换行)得以保留;没有每会话工件的后端(如 SQLite继承 `undefined` 默认
后端为单个会话自持的工件文本,与其持久化写入的字节逐字一致(按物理编码解码)。`readRaw` 返回它而不从解析后事件重建因此后端特定的序列化chunk 打包、键序、换行)得以保留。Consumer 须先检查 `supportsRawArtifacts``false` 表示后端不提供此能力(如 SQLite,而 `readRaw(...) === undefined` 表示受支持的后端没有该会话的已实体化工件
```ts type-equiv
/** A backend's own raw artifact text for one session, verbatim. */
@@ -262,13 +262,15 @@ abstract locate(meta: SessionHeader): SessionLocation | undefined
* bytes the backend wrote (decoded from its physical encoding, e.g. a
* decompressed JSONL). The returned `content` is the raw text, not a
* reconstruction from parsed events, so it preserves backend-specific
* serialization (chunk packing, key order, line breaks). Backends without a
* per-session artifact (SQLite) inherit the `undefined` default.
* serialization (chunk packing, key order, line breaks). Callers first test
* {@link supportsRawArtifacts}; `undefined` then means only that the requested
* session has no materialized artifact.
* @param _id - the persisted session to read (unused by the default: no
* per-session artifact).
* @param signal - optional cancellation for backend read work.
* @returns the raw artifact plus its parsed header, or `undefined` when the
* session is absent or the backend owns no per-session artifact.
* session is absent.
* @throws when this backend does not expose per-session raw artifacts.
*/
readRaw(_id: SessionId, signal?: AbortSignal): Promise<SessionRawArtifact | undefined>

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/workflow.md
workflow.md: f0321cf258810197ac57780a916d059a5cdca0d8
workflow.zh.md: e1c23142e8bea3f3bf28d103cb7c37b40b0efbd7
workflow.md: b7f29526d4a1e6664ecc6cd54670d2c608947bee
workflow.zh.md: b714f9ce0ce68808a44b3824cfe2cac7c2d04b6e

View File

@@ -6,7 +6,7 @@ The workflow seam lets an agent run a model-written orchestration SCRIPT that st
Service Definition: [dsh-workflow](../../packages/workflow/workflow) (`ctx.workflows` + the vocabulary below). The Service provider is [dsh-workflow-workerthread](../../packages/workflow/workflow-workerthread) (a `node:worker_threads` engine — one worker per run, the script's vm context inside it); the model-facing Consumer is [dsh-tool-workflow](../../packages/workflow/tool-workflow). The proposal and rationale: [the dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md).
Source: [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts)
Sources: browser-safe vocabulary in [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts), Host request and live-run handles in [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts).
## The start request
@@ -15,33 +15,23 @@ What a caller asks for when starting a run. The ordinary workflow tool builds th
```ts type-equiv
/**
* What a caller asks for when starting a workflow run. `meta` and `args` are
* plain JSON DATA by the seam contract (the tool builds both from the model's schema-validated call;
* the engine validates `meta` against its schema and rejects loud
* before anything runs) — an engine never evaluates script text to obtain
* them. `parent` is REQUIRED — every `agent()` the script spawns is
* attributed to it (cwd, lineage, depth flow through the subagent seam).
* plain JSON data by the seam contract. `parent` is required because every
* `agent()` spawned by the script is attributed to that live Agent.
*/
interface WorkflowStartRequest {
/** The plain-JS script body (top-level await allowed; ends with `return <json-value>`). */
script: string
/** The workflow's identity fields as plain JSON data, validated by the engine. */
/** The workflow's identity block, as plain JSON data (shape-validated by the engine). */
meta: WorkflowMeta
/** Optional input exposed verbatim to the script as the `args` global. */
args?: unknown
/**
* Optional engine-wide child-provider override for this run. The workflow
* script cannot observe or replace it; omission uses the engine's configured
* provider.
*/
/** Optional engine-wide child-provider override for this run. */
subagentProvider?: string
/**
* Optional per-run total-child ceiling. Implementations reject values above
* their deployment ceiling before publishing the run.
*/
/** Optional per-run total-child ceiling. */
maxTotalAgents?: number
/** The agent on whose behalf the run executes (parent of every child). */
parent: Agent
/** Cancels the run when aborted (the tool's `exec.signal`). */
/** Cancels the run when aborted. */
signal?: AbortSignal
}
```
@@ -76,7 +66,7 @@ The outcome of one run, resolved by `WorkflowRun.result`. `value` is the script'
```ts type-equiv
/**
* The outcome of one run, resolved by {@link WorkflowRun.result}. `value` is
* The outcome resolved by a live workflow run. `value` is
* the script's materialized return value (plain host-realm JSON data; `null`
* when the script returned `undefined`) — meaningful only for `completed`.
* A non-`completed` reason carries the failure in `error`; the consumer maps
@@ -106,19 +96,17 @@ The handle the consumer holds while a script executes. The consumer awaits `resu
```ts type-equiv
/**
* Holder-owned live workflow. `result` never rejects and settles within the
* engine's cancellation grace; failures resolve through `stopReason`. Consumers
* may cancel and must call idempotent `dispose()` on every path to await bounded
* script settlement and child quiescence.
* Holder-owned live workflow. `result` never rejects; consumers may cancel
* and must call idempotent `dispose()` to await script and child quiescence.
*/
interface WorkflowRun {
readonly id: WorkflowRunId
/** The validated meta block (available before the body runs). */
/** The validated meta block available before the script body runs. */
readonly meta: WorkflowMeta
readonly result: Promise<WorkflowResult>
/** Cancel the run: children abort, pending hooks reject, the script dies at its next await (or is force-settled at the grace). */
/** Cancel the run and its children. */
cancel(reason?: string): void
/** Cancel + bounded-grace settle; safe to call on every path (idempotent). */
/** Cancel if needed and await bounded settlement and cleanup. */
dispose(): Promise<void>
}
```
@@ -131,6 +119,14 @@ Hook misuse inside a script — bad arguments, unknown/deferred `agent()` option
The `workflow/*` events (`workflow/start`, `workflow/phase`, `workflow/log`, `workflow/agent-start`, `workflow/agent-end`, `workflow/end` — see the [events catalog](#cordis-surface)) are **observe-only** emits carrying DATA SNAPSHOTS: every payload starts with `WorkflowRunInfo` (id + meta), never the live `WorkflowRun`, so a subscriber cannot gain `cancel`/`dispose`, and `workflow/end` deliberately omits the result value (a listener observing outcomes must not receive a mutable alias of the caller's result). Every emit is per-listener contained — a throwing subscriber is logged, never propagated, and cannot starve the listeners registered after it — and every listener receives its own payload clone, so mutating it corrupts neither the engine nor other listeners; the containment mirrors `subagent/start`/`subagent/end`.
## Durable Chat records
The top-level `dsh-tool-workflow` consumer projects display facts into its calling parent Session without changing execution ownership. It writes `tool-workflow/run-start` after a run is accepted, pairs member start and end by `runId + seq`, and writes `tool-workflow/run-end` only after the result is known and disposal reaches quiescence. Nested transport calls write no record. The first append failure disables later writes for that run, so the log remains empty or a legal continuous prefix and the tool result is unchanged.
`dsh-tool-workflow/invariant` validates the same protocol before live commit and when a Session is loaded: one start per run, positive unique member sequences, paired member endings, no run ending with open members, and no updates after the run ending. A missing member ending or run ending at the log tail is valid interruption evidence rather than corruption.
`dsh-client-ui-workflow-run` folds the four events through the Conversation Node engine into one `workflow-run` Chat node anchored at the run-start sequence, after the original workflow tool node. Phase groups come only from actual member starts and preserve exact strings, including the distinction between an omitted phase and `''`. Closed Locations turn missing terminal facts into interrupted presentation. The [UI package README](../../packages/client/ui-workflow-run/README.md) owns disclosure, status, and same-parent local navigation behavior.
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
<a id="cordis-surface"></a>
@@ -155,7 +151,7 @@ Workflow Service Definition contract. Invalid requests throw before publication;
abstract start(request: WorkflowStartRequest): WorkflowRun
```
Source: [`packages/workflow/workflow/src/index.ts:159`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:157`](../../packages/workflow/workflow/src/index.ts)
<a id="workflow-events"></a>
@@ -181,7 +177,7 @@ One `agent()` call settled (clean result, child failure, or run cancellation). P
'workflow/agent-end'(info: WorkflowRunInfo, agent: WorkflowAgentEndInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:81`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:79`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowagent-start--emit"></a>
@@ -202,7 +198,7 @@ One `agent()` call established a published child run. Paired with Events['workfl
'workflow/agent-start'(info: WorkflowRunInfo, agent: WorkflowAgentInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:70`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:68`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowend--emit"></a>
@@ -223,7 +219,7 @@ A workflow run settled (any stop reason). Fired when WorkflowRun.result resolves
'workflow/end'(info: WorkflowRunInfo, result: WorkflowResultInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:91`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:89`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowlog--emit"></a>
@@ -241,7 +237,7 @@ The script emitted a narration line (a `log(message)` call).
'workflow/log'(info: WorkflowRunInfo, message: string): void
```
Source: [`packages/workflow/workflow/src/index.ts:60`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:58`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowphase--emit"></a>
@@ -260,7 +256,7 @@ The script entered a phase (a `phase(title)` call) — progress grouping for obs
'workflow/phase'(info: WorkflowRunInfo, title: string): void
```
Source: [`packages/workflow/workflow/src/index.ts:53`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:51`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowstart--emit"></a>
@@ -278,5 +274,5 @@ A workflow run started — the script's meta block validated, the body about to
'workflow/start'(info: WorkflowRunInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:45`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:43`](../../packages/workflow/workflow/src/index.ts)
<!-- END GENERATED cordis-surface -->

View File

@@ -6,7 +6,7 @@
Service Definition[dsh-workflow](../../packages/workflow/workflow)`ctx.workflows` + 下文词汇。Service provider 是 [dsh-workflow-workerthread](../../packages/workflow/workflow-workerthread)(一个 `node:worker_threads` 引擎——每个 run 一个 worker脚本的 vm 上下文位于其中);面向模型的 Consumer 是 [dsh-tool-workflow](../../packages/workflow/tool-workflow)。提案与设计理由见 [dynamic-workflows Agent Note](../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md)。
源码:[`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts)
源码:浏览器安全词汇位于 [`packages/workflow/workflow/src/types.ts`](../../packages/workflow/workflow/src/types.ts)Host 请求与活跃运行句柄位于 [`runtime-types.ts`](../../packages/workflow/workflow/src/runtime-types.ts)。
## 启动请求
@@ -15,33 +15,23 @@ Service Definition[dsh-workflow](../../packages/workflow/workflow)`ctx.wor
```ts type-equiv
/**
* What a caller asks for when starting a workflow run. `meta` and `args` are
* plain JSON DATA by the seam contract (the tool builds both from the model's schema-validated call;
* the engine validates `meta` against its schema and rejects loud
* before anything runs) — an engine never evaluates script text to obtain
* them. `parent` is REQUIRED — every `agent()` the script spawns is
* attributed to it (cwd, lineage, depth flow through the subagent seam).
* plain JSON data by the seam contract. `parent` is required because every
* `agent()` spawned by the script is attributed to that live Agent.
*/
interface WorkflowStartRequest {
/** The plain-JS script body (top-level await allowed; ends with `return <json-value>`). */
script: string
/** The workflow's identity fields as plain JSON data, validated by the engine. */
/** The workflow's identity block, as plain JSON data (shape-validated by the engine). */
meta: WorkflowMeta
/** Optional input exposed verbatim to the script as the `args` global. */
args?: unknown
/**
* Optional engine-wide child-provider override for this run. The workflow
* script cannot observe or replace it; omission uses the engine's configured
* provider.
*/
/** Optional engine-wide child-provider override for this run. */
subagentProvider?: string
/**
* Optional per-run total-child ceiling. Implementations reject values above
* their deployment ceiling before publishing the run.
*/
/** Optional per-run total-child ceiling. */
maxTotalAgents?: number
/** The agent on whose behalf the run executes (parent of every child). */
parent: Agent
/** Cancels the run when aborted (the tool's `exec.signal`). */
/** Cancels the run when aborted. */
signal?: AbortSignal
}
```
@@ -76,7 +66,7 @@ interface WorkflowMeta {
```ts type-equiv
/**
* The outcome of one run, resolved by {@link WorkflowRun.result}. `value` is
* The outcome resolved by a live workflow run. `value` is
* the script's materialized return value (plain host-realm JSON data; `null`
* when the script returned `undefined`) — meaningful only for `completed`.
* A non-`completed` reason carries the failure in `error`; the consumer maps
@@ -106,19 +96,17 @@ interface WorkflowResult {
```ts type-equiv
/**
* Holder-owned live workflow. `result` never rejects and settles within the
* engine's cancellation grace; failures resolve through `stopReason`. Consumers
* may cancel and must call idempotent `dispose()` on every path to await bounded
* script settlement and child quiescence.
* Holder-owned live workflow. `result` never rejects; consumers may cancel
* and must call idempotent `dispose()` to await script and child quiescence.
*/
interface WorkflowRun {
readonly id: WorkflowRunId
/** The validated meta block (available before the body runs). */
/** The validated meta block available before the script body runs. */
readonly meta: WorkflowMeta
readonly result: Promise<WorkflowResult>
/** Cancel the run: children abort, pending hooks reject, the script dies at its next await (or is force-settled at the grace). */
/** Cancel the run and its children. */
cancel(reason?: string): void
/** Cancel + bounded-grace settle; safe to call on every path (idempotent). */
/** Cancel if needed and await bounded settlement and cleanup. */
dispose(): Promise<void>
}
```
@@ -131,6 +119,14 @@ interface WorkflowRun {
`workflow/*` 事件(`workflow/start`、`workflow/phase`、`workflow/log`、`workflow/agent-start`、`workflow/agent-end`、`workflow/end`,见[事件目录](#cordis-surface))是**仅供观察**的 emit携带数据快照每个 payload 以 `WorkflowRunInfo`id + meta开头而非活跃的 `WorkflowRun`,因此订阅者无法获得 `cancel`/`dispose``workflow/end` 刻意省略 result value观察结果的监听器不得收到调用方 result 的可变别名)。每次 emit 对每个监听器隔离:抛出异常的订阅者被记录日志但不传播,不会饿死在它之后注册的监听器;每个监听器收到自己的 payload 克隆,因此修改它既不会损坏引擎也不会影响其他监听器。这种隔离方式与 `subagent/start`/`subagent/end` 一致。
## 持久 Chat 记录
顶层 `dsh-tool-workflow` 消费方把展示事实投影到调用它的父 Session同时不改变执行所有权。运行接受后写 `tool-workflow/run-start`,以 `runId + seq` 配对成员开始与结束,并且只在结果已取得且 dispose 完全停稳后写 `tool-workflow/run-end`。嵌套 transport 调用不写记录。第一次 append 失败会禁用本运行后续写入,因此日志保持为空或合法连续前缀,工具结果不变。
`dsh-tool-workflow/invariant` 会在实时提交前和 Session 加载时校验同一协议:每个运行只有一个 start成员序号为正且唯一成员 end 必须配对,仍有开放成员时不能结束运行,运行结束后不能继续更新。日志尾部缺少成员 end 或 run end 是有效的中断证据,不是损坏。
`dsh-client-ui-workflow-run` 通过 Conversation Node 引擎把四类事件折叠为一个 `workflow-run` Chat 节点,以 run-start 序号锚定在原工作流工具节点之后。阶段组只来自真正开始过的成员,并保留精确字符串,包括字段缺省与 `''` 的区别。Location 关闭时,缺失终点会显示为已中断。[界面包 README](../../packages/client/ui-workflow-run/README.md)负责定义 disclosure、状态与同父本地导航行为。
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
<a id="cordis-surface"></a>
@@ -155,7 +151,7 @@ Workflow Service Definition contract. Invalid requests throw before publication;
abstract start(request: WorkflowStartRequest): WorkflowRun
```
Source: [`packages/workflow/workflow/src/index.ts:159`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:157`](../../packages/workflow/workflow/src/index.ts)
<a id="workflow-events"></a>
@@ -181,7 +177,7 @@ One `agent()` call settled (clean result, child failure, or run cancellation). P
'workflow/agent-end'(info: WorkflowRunInfo, agent: WorkflowAgentEndInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:81`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:79`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowagent-start--emit"></a>
@@ -202,7 +198,7 @@ One `agent()` call established a published child run. Paired with Events['workfl
'workflow/agent-start'(info: WorkflowRunInfo, agent: WorkflowAgentInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:70`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:68`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowend--emit"></a>
@@ -223,7 +219,7 @@ A workflow run settled (any stop reason). Fired when WorkflowRun.result resolves
'workflow/end'(info: WorkflowRunInfo, result: WorkflowResultInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:91`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:89`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowlog--emit"></a>
@@ -241,7 +237,7 @@ The script emitted a narration line (a `log(message)` call).
'workflow/log'(info: WorkflowRunInfo, message: string): void
```
Source: [`packages/workflow/workflow/src/index.ts:60`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:58`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowphase--emit"></a>
@@ -260,7 +256,7 @@ The script entered a phase (a `phase(title)` call) — progress grouping for obs
'workflow/phase'(info: WorkflowRunInfo, title: string): void
```
Source: [`packages/workflow/workflow/src/index.ts:53`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:51`](../../packages/workflow/workflow/src/index.ts)
<a id="workflowstart--emit"></a>
@@ -278,5 +274,5 @@ A workflow run started — the script's meta block validated, the body about to
'workflow/start'(info: WorkflowRunInfo): void
```
Source: [`packages/workflow/workflow/src/index.ts:45`](../../packages/workflow/workflow/src/index.ts)
Source: [`packages/workflow/workflow/src/index.ts:43`](../../packages/workflow/workflow/src/index.ts)
<!-- END GENERATED cordis-surface -->