omk-protocol 0.98.5 → 0.99.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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.99.0] - 2026-09-13
6
+
7
+ ### Added
8
+
9
+ - `RunDagWriter` accepts optional `maxConcurrentTasks: 1 | 2`. Omitted concurrency stays omitted in parsed contracts, preserving legacy serialization and digests. The field describes an approved bound; it does not authorize or execute tasks by itself.
10
+
5
11
  ## [0.98.5] - 2026-09-12
6
12
 
7
13
  ### Added
package/README.md CHANGED
@@ -23,7 +23,8 @@ TaskSpec -> ExecutionAttempt -> Observation -> EvaluationResult -> RuntimeDecisi
23
23
  writer restart to an immutable input checkpoint. They grant no remote replay authority.
24
24
  - Bounded `linux-command-dag-v1`: `RunDagWriter`, `RunDagTask`, `orderRunDag()`,
25
25
  `runDagAncestors()`, `MAX_RUN_DAG_TASKS` and `MAX_RUN_TASK_ATTEMPTS`. Pure graph
26
- ordering/closure does not schedule or authorize a process.
26
+ ordering/closure does not schedule or authorize a process. `RunDagWriter` accepts
27
+ optional `maxConcurrentTasks: 1 | 2`; omitted fields stay omitted for legacy digest parity.
27
28
  - `RunTaskRetryCommand` / `parseRunTaskRetryCommand()` bind a failed/interrupted task
28
29
  selection to the original input and exact revision/generation. Empty selections
29
30
  request pending-only continuation, not permission to omit a failed dependency.
package/dist/run-dag.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface RunDagTask {
9
9
  export interface RunDagWriter {
10
10
  readonly kind: "command-dag";
11
11
  readonly tasks: readonly RunDagTask[];
12
+ readonly maxConcurrentTasks?: 1 | 2;
12
13
  }
13
14
  /** Deterministic FIFO Kahn ordering. This orders artifacts, not tool resource-conflict claims. */
14
15
  export declare function orderRunDag(tasks: readonly RunDagTask[]): readonly RunDagTask[];
@@ -1 +1 @@
1
- {"version":3,"file":"run-dag.d.ts","sourceRoot":"","sources":["../src/run-dag.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;CAClD;AACD,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACtC;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,UAAU,EAAE,CAiB/E;AAED,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAQnG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAoC3F","sourcesContent":["import { RunContractError, runArgv, runArray, runId, runObject, runRelativePath } from \"./run-parsing.ts\";\n\nexport const MAX_RUN_DAG_TASKS = 16;\nexport const MAX_RUN_TASK_ATTEMPTS = 2;\n\nexport interface RunDagTask {\n\treadonly id: string;\n\treadonly dependsOn: readonly string[];\n\treadonly writablePaths: readonly string[];\n\treadonly attempts: readonly (readonly string[])[];\n}\nexport interface RunDagWriter {\n\treadonly kind: \"command-dag\";\n\treadonly tasks: readonly RunDagTask[];\n}\n\n/** Deterministic FIFO Kahn ordering. This orders artifacts, not tool resource-conflict claims. */\nexport function orderRunDag(tasks: readonly RunDagTask[]): readonly RunDagTask[] {\n\tconst pending = new Map(tasks.map((task) => [task.id, task.dependsOn.length]));\n\tconst ready = tasks.filter((task) => task.dependsOn.length === 0);\n\tconst ordered: RunDagTask[] = [];\n\tfor (let index = 0; index < ready.length; index++) {\n\t\tconst next = ready[index];\n\t\tordered.push(next);\n\t\tfor (const task of tasks) {\n\t\t\tif (!task.dependsOn.includes(next.id)) continue;\n\t\t\tconst count = pending.get(task.id);\n\t\t\tif (count === undefined) throw new RunContractError(\"dependency\");\n\t\t\tpending.set(task.id, count - 1);\n\t\t\tif (count === 1) ready.push(task);\n\t\t}\n\t}\n\tif (ordered.length !== tasks.length) throw new RunContractError(\"cyclic dependency\");\n\treturn Object.freeze(ordered);\n}\n\n/** Every ancestor material is an input; unrelated successful branches are deliberately excluded. */\nexport function runDagAncestors(tasks: readonly RunDagTask[], taskId: string): readonly RunDagTask[] {\n\tif (!tasks.some((task) => task.id === taskId)) throw new RunContractError(\"taskId\");\n\tconst order = orderRunDag(tasks);\n\tconst included = new Set([taskId]);\n\tfor (const task of [...order].reverse()) {\n\t\tif (included.has(task.id)) for (const id of task.dependsOn) included.add(id);\n\t}\n\treturn Object.freeze(order.filter((task) => task.id !== taskId && included.has(task.id)));\n}\n\nexport function parseRunDagWriter(value: unknown, writable: readonly string[]): RunDagWriter {\n\tconst raw = runObject(value, [\"kind\", \"tasks\"]);\n\tif (raw.kind !== \"command-dag\") throw new RunContractError(\"writer.kind\");\n\tconst tasks = runArray(\n\t\traw.tasks,\n\t\t(value): RunDagTask => {\n\t\t\tconst task = runObject(value, [\"id\", \"dependsOn\", \"writablePaths\", \"attempts\"]);\n\t\t\tconst dependsOn =\n\t\t\t\tArray.isArray(task.dependsOn) && task.dependsOn.length === 0\n\t\t\t\t\t? Object.freeze([])\n\t\t\t\t\t: runArray(task.dependsOn, runId, MAX_RUN_DAG_TASKS);\n\t\t\tif (new Set(dependsOn).size !== dependsOn.length) throw new RunContractError(\"duplicate dependency\");\n\t\t\treturn Object.freeze({\n\t\t\t\tid: runId(task.id),\n\t\t\t\tdependsOn,\n\t\t\t\twritablePaths: runArray(task.writablePaths, runRelativePath, 128),\n\t\t\t\tattempts: runArray(task.attempts, runArgv, MAX_RUN_TASK_ATTEMPTS),\n\t\t\t});\n\t\t},\n\t\tMAX_RUN_DAG_TASKS,\n\t);\n\tconst ids = new Set(tasks.map((task) => task.id));\n\tif (ids.size !== tasks.length) throw new RunContractError(\"duplicate task\");\n\tconst scopes: string[] = [];\n\tfor (const task of tasks) {\n\t\tif (task.dependsOn.some((id) => id === task.id || !ids.has(id))) throw new RunContractError(\"dependency\");\n\t\tfor (const path of task.writablePaths) {\n\t\t\tif (!writable.some((scope) => path === scope || path.startsWith(`${scope}/`)))\n\t\t\t\tthrow new RunContractError(\"task scope\");\n\t\t\tif (scopes.some((scope) => path === scope || path.startsWith(`${scope}/`) || scope.startsWith(`${path}/`)))\n\t\t\t\tthrow new RunContractError(\"overlapping task scope\");\n\t\t\tscopes.push(path);\n\t\t}\n\t}\n\torderRunDag(tasks);\n\treturn Object.freeze({ kind: \"command-dag\", tasks });\n}\n"]}
1
+ {"version":3,"file":"run-dag.d.ts","sourceRoot":"","sources":["../src/run-dag.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;CAClD;AACD,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CACpC;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,UAAU,EAAE,CAiB/E;AAED,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAQnG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CA6C3F","sourcesContent":["import { RunContractError, runArgv, runArray, runId, runObject, runRelativePath } from \"./run-parsing.ts\";\n\nexport const MAX_RUN_DAG_TASKS = 16;\nexport const MAX_RUN_TASK_ATTEMPTS = 2;\n\nexport interface RunDagTask {\n\treadonly id: string;\n\treadonly dependsOn: readonly string[];\n\treadonly writablePaths: readonly string[];\n\treadonly attempts: readonly (readonly string[])[];\n}\nexport interface RunDagWriter {\n\treadonly kind: \"command-dag\";\n\treadonly tasks: readonly RunDagTask[];\n\treadonly maxConcurrentTasks?: 1 | 2;\n}\n\n/** Deterministic FIFO Kahn ordering. This orders artifacts, not tool resource-conflict claims. */\nexport function orderRunDag(tasks: readonly RunDagTask[]): readonly RunDagTask[] {\n\tconst pending = new Map(tasks.map((task) => [task.id, task.dependsOn.length]));\n\tconst ready = tasks.filter((task) => task.dependsOn.length === 0);\n\tconst ordered: RunDagTask[] = [];\n\tfor (let index = 0; index < ready.length; index++) {\n\t\tconst next = ready[index];\n\t\tordered.push(next);\n\t\tfor (const task of tasks) {\n\t\t\tif (!task.dependsOn.includes(next.id)) continue;\n\t\t\tconst count = pending.get(task.id);\n\t\t\tif (count === undefined) throw new RunContractError(\"dependency\");\n\t\t\tpending.set(task.id, count - 1);\n\t\t\tif (count === 1) ready.push(task);\n\t\t}\n\t}\n\tif (ordered.length !== tasks.length) throw new RunContractError(\"cyclic dependency\");\n\treturn Object.freeze(ordered);\n}\n\n/** Every ancestor material is an input; unrelated successful branches are deliberately excluded. */\nexport function runDagAncestors(tasks: readonly RunDagTask[], taskId: string): readonly RunDagTask[] {\n\tif (!tasks.some((task) => task.id === taskId)) throw new RunContractError(\"taskId\");\n\tconst order = orderRunDag(tasks);\n\tconst included = new Set([taskId]);\n\tfor (const task of [...order].reverse()) {\n\t\tif (included.has(task.id)) for (const id of task.dependsOn) included.add(id);\n\t}\n\treturn Object.freeze(order.filter((task) => task.id !== taskId && included.has(task.id)));\n}\n\nexport function parseRunDagWriter(value: unknown, writable: readonly string[]): RunDagWriter {\n\tconst hasConcurrency =\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\tObject.getOwnPropertyDescriptor(value, \"maxConcurrentTasks\") !== undefined;\n\tconst raw = runObject(value, hasConcurrency ? [\"kind\", \"tasks\", \"maxConcurrentTasks\"] : [\"kind\", \"tasks\"]);\n\tif (raw.kind !== \"command-dag\") throw new RunContractError(\"writer.kind\");\n\tconst tasks = runArray(\n\t\traw.tasks,\n\t\t(value): RunDagTask => {\n\t\t\tconst task = runObject(value, [\"id\", \"dependsOn\", \"writablePaths\", \"attempts\"]);\n\t\t\tconst dependsOn =\n\t\t\t\tArray.isArray(task.dependsOn) && task.dependsOn.length === 0\n\t\t\t\t\t? Object.freeze([])\n\t\t\t\t\t: runArray(task.dependsOn, runId, MAX_RUN_DAG_TASKS);\n\t\t\tif (new Set(dependsOn).size !== dependsOn.length) throw new RunContractError(\"duplicate dependency\");\n\t\t\treturn Object.freeze({\n\t\t\t\tid: runId(task.id),\n\t\t\t\tdependsOn,\n\t\t\t\twritablePaths: runArray(task.writablePaths, runRelativePath, 128),\n\t\t\t\tattempts: runArray(task.attempts, runArgv, MAX_RUN_TASK_ATTEMPTS),\n\t\t\t});\n\t\t},\n\t\tMAX_RUN_DAG_TASKS,\n\t);\n\tconst ids = new Set(tasks.map((task) => task.id));\n\tif (ids.size !== tasks.length) throw new RunContractError(\"duplicate task\");\n\tconst scopes: string[] = [];\n\tfor (const task of tasks) {\n\t\tif (task.dependsOn.some((id) => id === task.id || !ids.has(id))) throw new RunContractError(\"dependency\");\n\t\tfor (const path of task.writablePaths) {\n\t\t\tif (!writable.some((scope) => path === scope || path.startsWith(`${scope}/`)))\n\t\t\t\tthrow new RunContractError(\"task scope\");\n\t\t\tif (scopes.some((scope) => path === scope || path.startsWith(`${scope}/`) || scope.startsWith(`${path}/`)))\n\t\t\t\tthrow new RunContractError(\"overlapping task scope\");\n\t\t\tscopes.push(path);\n\t\t}\n\t}\n\torderRunDag(tasks);\n\tif (hasConcurrency) {\n\t\tconst maxConcurrentTasks = raw.maxConcurrentTasks;\n\t\tif (maxConcurrentTasks !== 1 && maxConcurrentTasks !== 2) throw new RunContractError(\"maxConcurrentTasks\");\n\t\treturn Object.freeze({ kind: \"command-dag\", tasks, maxConcurrentTasks });\n\t}\n\treturn Object.freeze({ kind: \"command-dag\", tasks });\n}\n"]}
package/dist/run-dag.js CHANGED
@@ -38,7 +38,10 @@ export function runDagAncestors(tasks, taskId) {
38
38
  return Object.freeze(order.filter((task) => task.id !== taskId && included.has(task.id)));
39
39
  }
40
40
  export function parseRunDagWriter(value, writable) {
41
- const raw = runObject(value, ["kind", "tasks"]);
41
+ const hasConcurrency = typeof value === "object" &&
42
+ value !== null &&
43
+ Object.getOwnPropertyDescriptor(value, "maxConcurrentTasks") !== undefined;
44
+ const raw = runObject(value, hasConcurrency ? ["kind", "tasks", "maxConcurrentTasks"] : ["kind", "tasks"]);
42
45
  if (raw.kind !== "command-dag")
43
46
  throw new RunContractError("writer.kind");
44
47
  const tasks = runArray(raw.tasks, (value) => {
@@ -71,6 +74,12 @@ export function parseRunDagWriter(value, writable) {
71
74
  }
72
75
  }
73
76
  orderRunDag(tasks);
77
+ if (hasConcurrency) {
78
+ const maxConcurrentTasks = raw.maxConcurrentTasks;
79
+ if (maxConcurrentTasks !== 1 && maxConcurrentTasks !== 2)
80
+ throw new RunContractError("maxConcurrentTasks");
81
+ return Object.freeze({ kind: "command-dag", tasks, maxConcurrentTasks });
82
+ }
74
83
  return Object.freeze({ kind: "command-dag", tasks });
75
84
  }
76
85
  //# sourceMappingURL=run-dag.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-dag.js","sourceRoot":"","sources":["../src/run-dag.ts"],"names":[],"mappings":"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","sourcesContent":["import { RunContractError, runArgv, runArray, runId, runObject, runRelativePath } from \"./run-parsing.ts\";\n\nexport const MAX_RUN_DAG_TASKS = 16;\nexport const MAX_RUN_TASK_ATTEMPTS = 2;\n\nexport interface RunDagTask {\n\treadonly id: string;\n\treadonly dependsOn: readonly string[];\n\treadonly writablePaths: readonly string[];\n\treadonly attempts: readonly (readonly string[])[];\n}\nexport interface RunDagWriter {\n\treadonly kind: \"command-dag\";\n\treadonly tasks: readonly RunDagTask[];\n}\n\n/** Deterministic FIFO Kahn ordering. This orders artifacts, not tool resource-conflict claims. */\nexport function orderRunDag(tasks: readonly RunDagTask[]): readonly RunDagTask[] {\n\tconst pending = new Map(tasks.map((task) => [task.id, task.dependsOn.length]));\n\tconst ready = tasks.filter((task) => task.dependsOn.length === 0);\n\tconst ordered: RunDagTask[] = [];\n\tfor (let index = 0; index < ready.length; index++) {\n\t\tconst next = ready[index];\n\t\tordered.push(next);\n\t\tfor (const task of tasks) {\n\t\t\tif (!task.dependsOn.includes(next.id)) continue;\n\t\t\tconst count = pending.get(task.id);\n\t\t\tif (count === undefined) throw new RunContractError(\"dependency\");\n\t\t\tpending.set(task.id, count - 1);\n\t\t\tif (count === 1) ready.push(task);\n\t\t}\n\t}\n\tif (ordered.length !== tasks.length) throw new RunContractError(\"cyclic dependency\");\n\treturn Object.freeze(ordered);\n}\n\n/** Every ancestor material is an input; unrelated successful branches are deliberately excluded. */\nexport function runDagAncestors(tasks: readonly RunDagTask[], taskId: string): readonly RunDagTask[] {\n\tif (!tasks.some((task) => task.id === taskId)) throw new RunContractError(\"taskId\");\n\tconst order = orderRunDag(tasks);\n\tconst included = new Set([taskId]);\n\tfor (const task of [...order].reverse()) {\n\t\tif (included.has(task.id)) for (const id of task.dependsOn) included.add(id);\n\t}\n\treturn Object.freeze(order.filter((task) => task.id !== taskId && included.has(task.id)));\n}\n\nexport function parseRunDagWriter(value: unknown, writable: readonly string[]): RunDagWriter {\n\tconst raw = runObject(value, [\"kind\", \"tasks\"]);\n\tif (raw.kind !== \"command-dag\") throw new RunContractError(\"writer.kind\");\n\tconst tasks = runArray(\n\t\traw.tasks,\n\t\t(value): RunDagTask => {\n\t\t\tconst task = runObject(value, [\"id\", \"dependsOn\", \"writablePaths\", \"attempts\"]);\n\t\t\tconst dependsOn =\n\t\t\t\tArray.isArray(task.dependsOn) && task.dependsOn.length === 0\n\t\t\t\t\t? Object.freeze([])\n\t\t\t\t\t: runArray(task.dependsOn, runId, MAX_RUN_DAG_TASKS);\n\t\t\tif (new Set(dependsOn).size !== dependsOn.length) throw new RunContractError(\"duplicate dependency\");\n\t\t\treturn Object.freeze({\n\t\t\t\tid: runId(task.id),\n\t\t\t\tdependsOn,\n\t\t\t\twritablePaths: runArray(task.writablePaths, runRelativePath, 128),\n\t\t\t\tattempts: runArray(task.attempts, runArgv, MAX_RUN_TASK_ATTEMPTS),\n\t\t\t});\n\t\t},\n\t\tMAX_RUN_DAG_TASKS,\n\t);\n\tconst ids = new Set(tasks.map((task) => task.id));\n\tif (ids.size !== tasks.length) throw new RunContractError(\"duplicate task\");\n\tconst scopes: string[] = [];\n\tfor (const task of tasks) {\n\t\tif (task.dependsOn.some((id) => id === task.id || !ids.has(id))) throw new RunContractError(\"dependency\");\n\t\tfor (const path of task.writablePaths) {\n\t\t\tif (!writable.some((scope) => path === scope || path.startsWith(`${scope}/`)))\n\t\t\t\tthrow new RunContractError(\"task scope\");\n\t\t\tif (scopes.some((scope) => path === scope || path.startsWith(`${scope}/`) || scope.startsWith(`${path}/`)))\n\t\t\t\tthrow new RunContractError(\"overlapping task scope\");\n\t\t\tscopes.push(path);\n\t\t}\n\t}\n\torderRunDag(tasks);\n\treturn Object.freeze({ kind: \"command-dag\", tasks });\n}\n"]}
1
+ {"version":3,"file":"run-dag.js","sourceRoot":"","sources":["../src/run-dag.ts"],"names":[],"mappings":"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","sourcesContent":["import { RunContractError, runArgv, runArray, runId, runObject, runRelativePath } from \"./run-parsing.ts\";\n\nexport const MAX_RUN_DAG_TASKS = 16;\nexport const MAX_RUN_TASK_ATTEMPTS = 2;\n\nexport interface RunDagTask {\n\treadonly id: string;\n\treadonly dependsOn: readonly string[];\n\treadonly writablePaths: readonly string[];\n\treadonly attempts: readonly (readonly string[])[];\n}\nexport interface RunDagWriter {\n\treadonly kind: \"command-dag\";\n\treadonly tasks: readonly RunDagTask[];\n\treadonly maxConcurrentTasks?: 1 | 2;\n}\n\n/** Deterministic FIFO Kahn ordering. This orders artifacts, not tool resource-conflict claims. */\nexport function orderRunDag(tasks: readonly RunDagTask[]): readonly RunDagTask[] {\n\tconst pending = new Map(tasks.map((task) => [task.id, task.dependsOn.length]));\n\tconst ready = tasks.filter((task) => task.dependsOn.length === 0);\n\tconst ordered: RunDagTask[] = [];\n\tfor (let index = 0; index < ready.length; index++) {\n\t\tconst next = ready[index];\n\t\tordered.push(next);\n\t\tfor (const task of tasks) {\n\t\t\tif (!task.dependsOn.includes(next.id)) continue;\n\t\t\tconst count = pending.get(task.id);\n\t\t\tif (count === undefined) throw new RunContractError(\"dependency\");\n\t\t\tpending.set(task.id, count - 1);\n\t\t\tif (count === 1) ready.push(task);\n\t\t}\n\t}\n\tif (ordered.length !== tasks.length) throw new RunContractError(\"cyclic dependency\");\n\treturn Object.freeze(ordered);\n}\n\n/** Every ancestor material is an input; unrelated successful branches are deliberately excluded. */\nexport function runDagAncestors(tasks: readonly RunDagTask[], taskId: string): readonly RunDagTask[] {\n\tif (!tasks.some((task) => task.id === taskId)) throw new RunContractError(\"taskId\");\n\tconst order = orderRunDag(tasks);\n\tconst included = new Set([taskId]);\n\tfor (const task of [...order].reverse()) {\n\t\tif (included.has(task.id)) for (const id of task.dependsOn) included.add(id);\n\t}\n\treturn Object.freeze(order.filter((task) => task.id !== taskId && included.has(task.id)));\n}\n\nexport function parseRunDagWriter(value: unknown, writable: readonly string[]): RunDagWriter {\n\tconst hasConcurrency =\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\tObject.getOwnPropertyDescriptor(value, \"maxConcurrentTasks\") !== undefined;\n\tconst raw = runObject(value, hasConcurrency ? [\"kind\", \"tasks\", \"maxConcurrentTasks\"] : [\"kind\", \"tasks\"]);\n\tif (raw.kind !== \"command-dag\") throw new RunContractError(\"writer.kind\");\n\tconst tasks = runArray(\n\t\traw.tasks,\n\t\t(value): RunDagTask => {\n\t\t\tconst task = runObject(value, [\"id\", \"dependsOn\", \"writablePaths\", \"attempts\"]);\n\t\t\tconst dependsOn =\n\t\t\t\tArray.isArray(task.dependsOn) && task.dependsOn.length === 0\n\t\t\t\t\t? Object.freeze([])\n\t\t\t\t\t: runArray(task.dependsOn, runId, MAX_RUN_DAG_TASKS);\n\t\t\tif (new Set(dependsOn).size !== dependsOn.length) throw new RunContractError(\"duplicate dependency\");\n\t\t\treturn Object.freeze({\n\t\t\t\tid: runId(task.id),\n\t\t\t\tdependsOn,\n\t\t\t\twritablePaths: runArray(task.writablePaths, runRelativePath, 128),\n\t\t\t\tattempts: runArray(task.attempts, runArgv, MAX_RUN_TASK_ATTEMPTS),\n\t\t\t});\n\t\t},\n\t\tMAX_RUN_DAG_TASKS,\n\t);\n\tconst ids = new Set(tasks.map((task) => task.id));\n\tif (ids.size !== tasks.length) throw new RunContractError(\"duplicate task\");\n\tconst scopes: string[] = [];\n\tfor (const task of tasks) {\n\t\tif (task.dependsOn.some((id) => id === task.id || !ids.has(id))) throw new RunContractError(\"dependency\");\n\t\tfor (const path of task.writablePaths) {\n\t\t\tif (!writable.some((scope) => path === scope || path.startsWith(`${scope}/`)))\n\t\t\t\tthrow new RunContractError(\"task scope\");\n\t\t\tif (scopes.some((scope) => path === scope || path.startsWith(`${scope}/`) || scope.startsWith(`${path}/`)))\n\t\t\t\tthrow new RunContractError(\"overlapping task scope\");\n\t\t\tscopes.push(path);\n\t\t}\n\t}\n\torderRunDag(tasks);\n\tif (hasConcurrency) {\n\t\tconst maxConcurrentTasks = raw.maxConcurrentTasks;\n\t\tif (maxConcurrentTasks !== 1 && maxConcurrentTasks !== 2) throw new RunContractError(\"maxConcurrentTasks\");\n\t\treturn Object.freeze({ kind: \"command-dag\", tasks, maxConcurrentTasks });\n\t}\n\treturn Object.freeze({ kind: \"command-dag\", tasks });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omk-protocol",
3
- "version": "0.98.5",
3
+ "version": "0.99.0",
4
4
  "description": "Canonical OMK Run Protocol contracts and pure semantic reducers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",