/** * plan.ts — execution-plan.md の参照実装(doc-grade, COMMON)。 * * runPlan(plan, ops, exec): stage groups を逐次実行し、各 stage 内を bounded 並行で回し、 * 未生成 Port の Skip 伝播と Error Policy Kind(fail/retry/continue)を解釈して * 決定的な result tree(Φ 合流)を返す。**ノード実行は consumer コールバック `exec` に委譲**。 * * 実装状況ラベル(execution-plan.md §2/§3 冒頭): * - null-binding skip: graphddb 実装済み(データ駆動)。 * - continue policy 起因の skip / op-level retry Kind: 規範(additive/aspirational)。 * このキットは**規範(spec)挙動**を検証する(graphddb ミラーではない、runtime-boundary の指示)。 * * 決定性の要(execution-plan.md §4): * - mapWithConcurrency は入力順を保存(output[i] = worker(items[i]))。完了順非依存。 * - stage 間は逐次(後 stage が前 stage の result を読む)。 * - 各 worker は result tree の disjoint スロット(自ノードの port)に書く → Φ 合流は決定的。 * * 並列実行(bc#23、execution-plan.md §4.1): * - 同期 API(runPlan): 同期コールバックは JS では重畳できないため**逐次のまま** * (§4.1 の conforming fallback。結果は並列版と byte 一致)。 * - 非同期 API(runPlanAsync): exec が Promise を返す場合、stage 内メンバを * `plan.concurrency` を上限とした bounded 並列で**投機的に dispatch** し、 * 解釈(Skip/Policy/Failure)は **index 昇順の決定的 commit** で行う。 * 観測結果(result tree / executed / skipped / Failure code・message)は逐次実行と * 完全一致(determinism proof = 既存 conformance vectors が両経路で PASS すること)。 */ import type { Value } from "./expr-eval.js"; export interface ExecutionPlanSpec { groups: number[][]; concurrency: number; } /** Error Policy Kind の閉集合(値の SSoT)。型 {@link PolicyKind} はここから導出する。 */ export declare const POLICY_KINDS: readonly ["fail", "retry", "continue"]; export type PolicyKind = (typeof POLICY_KINDS)[number]; /** * Element Error Policy Kind の閉集合(値の SSoT・scp-error.md)。型 {@link ElementPolicyKind} は * ここから導出する。map ノード専用(要素ごとの Failure がある文脈でのみ意味を持つ)。 */ export declare const ELEMENT_POLICY_KINDS: readonly ["error", "skip"]; export type ElementPolicyKind = (typeof ELEMENT_POLICY_KINDS)[number]; /** 何が起きたか(閉集合・値の SSoT)。未知 kind は fail-closed(既定へ縮退しない)。 */ export declare const ERROR_KINDS: readonly ["typeMismatch", "missingField", "overflow"]; export type ErrorKind = (typeof ERROR_KINDS)[number]; /** * 構造化された回復可能ペイロード(scp-error.md)。**leaf が生成し**、runtime は運ぶだけ。 * kind 以外は省略可 — 省略は「該当なし」であって「不明ゆえ既定」ではない。 * * `expectedType` は PortableType の **Portable Type Notation**(`portableTypeNotation`)であって * 型オブジェクトではない。静的に宣言された型のレンダリングゆえ codegen はリテラルとして焼ける。 */ export interface ErrorDetail { kind: ErrorKind; /** 宣言元の model / component。 */ model?: string; /** 問題のフィールド / ポート。 */ field?: string; /** 宣言型(Portable Type Notation)。 */ expectedType?: string; /** 実際に観測された wire 型(producer 固有の語彙)。 */ actualWireType?: string; /** 問題の値(stringify 済み。型復元のために再パースされることは無い)。 */ rawValue?: string; /** 呼び出し文脈(その値を特定した item key 等)。 */ context?: Record; } /** * 未生成表現の種別の閉集合(値の SSoT・§2 末尾)。型 {@link RelationKind} はここから導出する。 * * **`connection` の 1 値のみ**: 未生成の既定表現は `null` で、注記の**不在**がそれを意味する。かつて在った * `"single"` は「未生成 = null」を明示的に綴り直すだけの既定値の重複で、5 言語の runtime も全 emitter も * absent と完全に同一に扱っていた(`unproducedValue` は `connection` だけを見る)。1 つの意味に 2 つの綴りが * あると IR が同じ意味で 2 通りになるので、綴りは 1 つに畳んである。 */ export declare const RELATION_KINDS: readonly ["connection"]; export type RelationKind = (typeof RELATION_KINDS)[number]; export interface OpSpec { /** 表示・デバッグ用 */ id: string; /** この op が依存する親 op の index({result.*} 供給元)。root は null。 */ parent: number | null; /** 親 result のどのフィールドを束縛キーに読むか(null/欠落なら null-binding skip)。 */ bindField?: string; /** この op の未生成表現の種別(single=null / connection=空 connection)。 */ relationKind?: RelationKind; /** Error Policy Kind(既定 fail)。 */ policy?: PolicyKind; } /** * consumer が供給するノード実行結果(mock)。 * * 失敗は `error`(人間向けテキスト)に加え、構造化された回復可能ペイロード `detail` を運べる * (scp-error.md「The Error Value」)。`detail` を生成するのは **leaf**(wire 境界で宣言型と生 wire * 値の両方を持つ唯一の当事者)で、runtime は運ぶだけ — 合成も推論もしない。 */ export type ExecOutcome = { ok: Value; } | { error: string; detail?: ErrorDetail; }; /** exec(op, boundValue) — boundValue は親 result[bindField](root は null)。 */ export type Exec = (op: OpSpec, boundValue: Value | undefined) => ExecOutcome; /** * 非同期 exec(runPlanAsync 用)。ExecOutcome を同期で返しても Promise で返してもよい。 * `plan.concurrency > 1` のとき、同一 stage 内のメンバに対して**並行に呼ばれ得る** * (=consumer 実装はその並行度までスレッド安全/再入安全であることを宣言したことになる。 * 並行呼び出しを許容しない consumer は `concurrency: 1` の plan を出荷する)。 */ export type AsyncExec = (op: OpSpec, boundValue: Value | undefined) => ExecOutcome | Promise; type OpState = { status: "ok"; value: Value; } | { status: "skipped"; } | { status: "failed"; error: string; detail?: ErrorDetail; }; export type PlanFailureCode = "OP_FAILED" | "UNKNOWN_POLICY" | "INVALID_PLAN"; export declare class PlanFailure extends Error { code: PlanFailureCode; /** leaf 由来の構造化ペイロード(scp-error.md「The Error Value」)。運搬のみ・合成しない。 */ detail?: ErrorDetail; constructor(code: PlanFailureCode, message: string, detail?: ErrorDetail); } export interface RunResult { /** 各 op の最終状態(Φ 合流結果。index 順)。 */ states: OpState[]; /** 実際に exec が呼ばれた op id 列(呼び出し順ではなく index 昇順で正規化)。 */ executed: string[]; /** skip された op id(index 昇順)。 */ skipped: string[]; } /** * 未生成 relation 値の SSoT(§2 末尾): 単一値 relation の未生成 = null / connection の未生成 = * {items:[],cursor:null}。この 1 定義が「connection → 空 connection、それ以外 → null」を決める唯一の * 地点。plan.ts(runPlan の skip tree)・behavior.ts(writeUnproduced の whole-node skip / applyInto の * per-element guard-skip)・primitives.ts(公開面)はすべてこれを読む(literal を写さない)。 */ export declare function unproducedValue(kind: RelationKind | undefined): Value; /** * runPlan — execution-plan.md の骨格。 * * @param plan groups/concurrency。null なら 1 op = 1 stage の逐次 fallback(§4)。 * @param ops operation 定義(index 順。ops[0] は root)。 * @param exec ノード実行 mock(consumer 委譲)。 */ export declare function runPlan(plan: ExecutionPlanSpec | null, ops: OpSpec[], exec: Exec): RunResult; /** * runPlanAsync — runPlan の非同期版(bc#23)。stage 内メンバを `plan.concurrency` を * 上限とした bounded 並列で dispatch する。 * * 決定的 commit プロトコル(execution-plan.md §4.1): * 1. preflight(index 昇順): policy 検証・Skip 判定・bindField 束縛を、確定済みの * 前 stage state から導出する(stage 内メンバは相互独立 — §1)。 * 2. dispatch(index 昇順・bounded): 実行対象メンバの exec を並行に発行する。 * 3. commit(index 昇順): outcome を宣言順に解釈する(Skip 記録 / Policy Kind / * Failure 伝播)。最初に fail する解釈が逐次実行と同一の Failure を投げる。 * * 逐次実行との観測等価: result tree / executed / skipped / Failure(code・message)は * runPlan と byte 一致。**相違は投機的 dispatch のみ**(あるメンバの解釈が Failure でも、 * 同 stage の後続メンバの exec は既に発行され得る。旧 graphddb の thread-overlap と同じ許容)。 * * 安全 fallback(結果は不変のまま逐次 dispatch に切り替える): * - `concurrency <= 1` / stage メンバが 1 個以下。 * - stage 内に親子依存があるとき(§1 違反 plan への防御 — 逐次実行の可視性semantics を保存)。 */ export declare function runPlanAsync(plan: ExecutionPlanSpec | null, ops: OpSpec[], exec: AsyncExec): Promise; /** * finalTree — states を index→port の result tree(Φ 合流の観測形)へ整形する。 * ok → 値 / skipped → 未生成表現(single=null / connection=空 connection)。 * conformance vector はこの tree を期待値と byte 比較する(canonicalJson 経由)。 */ export declare function finalTree(states: OpState[], ops: OpSpec[]): Record; export {}; //# sourceMappingURL=plan.d.ts.map