taskflow-core 0.2.6 → 0.2.8

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.
Files changed (42) hide show
  1. package/README.md +39 -5
  2. package/dist/analytics.d.ts +30 -0
  3. package/dist/analytics.d.ts.map +1 -0
  4. package/dist/analytics.js +127 -0
  5. package/dist/analytics.js.map +1 -0
  6. package/dist/build-info.json +2 -2
  7. package/dist/exec/step-kinds.d.ts +1 -1
  8. package/dist/exec/step-kinds.d.ts.map +1 -1
  9. package/dist/exec/step-kinds.js +26 -14
  10. package/dist/exec/step-kinds.js.map +1 -1
  11. package/dist/hooks.d.ts +73 -0
  12. package/dist/hooks.d.ts.map +1 -0
  13. package/dist/hooks.js +296 -0
  14. package/dist/hooks.js.map +1 -0
  15. package/dist/index.d.ts +4 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +4 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/preflight.d.ts +69 -0
  20. package/dist/preflight.d.ts.map +1 -0
  21. package/dist/preflight.js +389 -0
  22. package/dist/preflight.js.map +1 -0
  23. package/dist/runtime/phases/approval-wait.d.ts +33 -0
  24. package/dist/runtime/phases/approval-wait.d.ts.map +1 -0
  25. package/dist/runtime/phases/approval-wait.js +95 -0
  26. package/dist/runtime/phases/approval-wait.js.map +1 -0
  27. package/dist/runtime/phases/approval.d.ts +1 -1
  28. package/dist/runtime/phases/approval.d.ts.map +1 -1
  29. package/dist/runtime/phases/approval.js +10 -6
  30. package/dist/runtime/phases/approval.js.map +1 -1
  31. package/dist/runtime.d.ts.map +1 -1
  32. package/dist/runtime.js +40 -11
  33. package/dist/runtime.js.map +1 -1
  34. package/dist/savings.d.ts +36 -0
  35. package/dist/savings.d.ts.map +1 -0
  36. package/dist/savings.js +76 -0
  37. package/dist/savings.js.map +1 -0
  38. package/dist/schema.d.ts +31 -0
  39. package/dist/schema.d.ts.map +1 -1
  40. package/dist/schema.js +123 -0
  41. package/dist/schema.js.map +1 -1
  42. package/package.json +1 -1
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Incremental / recompute savings summary — one-line numbers users can see.
3
+ *
4
+ * Pure formatters over RecomputeReport and run phase states. No I/O.
5
+ */
6
+ import type { PhaseState, RunState } from "./store.ts";
7
+ /** Minimal recompute-shaped input (avoids circular import with runtime). */
8
+ export interface SavingsRecomputeInput {
9
+ readonly dryRun?: boolean;
10
+ readonly seeds?: readonly string[];
11
+ readonly rerun: readonly string[];
12
+ readonly reused: readonly string[];
13
+ readonly cutoff: readonly string[];
14
+ }
15
+ export interface PhaseCountSummary {
16
+ total: number;
17
+ completed: number;
18
+ failed: number;
19
+ skipped: number;
20
+ /** Phases with cacheHit set (cross-run or run-only). */
21
+ cached: number;
22
+ running: number;
23
+ other: number;
24
+ }
25
+ /** Count phase outcomes from a run state map (status / cache hits). */
26
+ export declare function countPhaseOutcomes(phases: Record<string, PhaseState> | undefined): PhaseCountSummary;
27
+ /**
28
+ * One-line savings for recompute reports.
29
+ * Example: `reused 5 · rerun 2 · cutoff 1 · saved ~71% phases`
30
+ */
31
+ export declare function formatSavingsLine(r: SavingsRecomputeInput): string;
32
+ /** One-line run cache summary when any phase was a cache hit. */
33
+ export declare function formatRunCacheLine(state: Pick<RunState, "phases">): string | undefined;
34
+ /** Prefix block for recompute human output. */
35
+ export declare function formatRecomputeSavingsHeader(r: SavingsRecomputeInput): string;
36
+ //# sourceMappingURL=savings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"savings.d.ts","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEvD,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,SAAS,GAAG,iBAAiB,CAiCpG;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAclE;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,GAAG,SAAS,CAKtF;AAED,+CAA+C;AAC/C,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAI7E"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Incremental / recompute savings summary — one-line numbers users can see.
3
+ *
4
+ * Pure formatters over RecomputeReport and run phase states. No I/O.
5
+ */
6
+ /** Count phase outcomes from a run state map (status / cache hits). */
7
+ export function countPhaseOutcomes(phases) {
8
+ const out = {
9
+ total: 0,
10
+ completed: 0,
11
+ failed: 0,
12
+ skipped: 0,
13
+ cached: 0,
14
+ running: 0,
15
+ other: 0,
16
+ };
17
+ if (!phases)
18
+ return out;
19
+ for (const ps of Object.values(phases)) {
20
+ out.total++;
21
+ if (ps.cacheHit)
22
+ out.cached++;
23
+ switch (ps.status) {
24
+ case "done":
25
+ out.completed++;
26
+ break;
27
+ case "failed":
28
+ out.failed++;
29
+ break;
30
+ case "skipped":
31
+ out.skipped++;
32
+ break;
33
+ case "running":
34
+ case "pending":
35
+ out.running++;
36
+ break;
37
+ default:
38
+ out.other++;
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+ /**
44
+ * One-line savings for recompute reports.
45
+ * Example: `reused 5 · rerun 2 · cutoff 1 · saved ~71% phases`
46
+ */
47
+ export function formatSavingsLine(r) {
48
+ const reused = r.reused.length;
49
+ const rerun = r.rerun.length;
50
+ const cutoff = r.cutoff.length;
51
+ const total = reused + rerun + cutoff;
52
+ const saved = reused + cutoff;
53
+ const pct = total > 0 ? Math.round((saved / total) * 100) : 0;
54
+ const parts = [
55
+ `reused ${reused}`,
56
+ `rerun ${rerun}`,
57
+ ...(r.dryRun ? [] : [`cutoff ${cutoff}`]),
58
+ total > 0 ? `saved ~${pct}% phases` : "saved —",
59
+ ];
60
+ return parts.join(" · ");
61
+ }
62
+ /** One-line run cache summary when any phase was a cache hit. */
63
+ export function formatRunCacheLine(state) {
64
+ const c = countPhaseOutcomes(state.phases);
65
+ if (c.cached === 0)
66
+ return undefined;
67
+ const pct = c.total > 0 ? Math.round((c.cached / c.total) * 100) : 0;
68
+ return `cache hits ${c.cached}/${c.total} (~${pct}%) · completed ${c.completed} · failed ${c.failed} · skipped ${c.skipped}`;
69
+ }
70
+ /** Prefix block for recompute human output. */
71
+ export function formatRecomputeSavingsHeader(r) {
72
+ const mode = r.dryRun ? "DRY RUN" : "applied";
73
+ const seeds = r.seeds?.length ? r.seeds.join(", ") : "—";
74
+ return `Savings (${mode}, seed: ${seeds}): ${formatSavingsLine(r)}`;
75
+ }
76
+ //# sourceMappingURL=savings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"savings.js","sourceRoot":"","sources":["../src/savings.ts"],"names":[],"mappings":"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"}
package/dist/schema.d.ts CHANGED
@@ -122,6 +122,8 @@ declare const PhaseSchema: Type.TObject<{
122
122
  * Overrides the flow-level `idleTimeout`. Absent → flow-level or host default.
123
123
  */
124
124
  idleTimeout: Type.TOptional<Type.TNumber>;
125
+ timeoutMs: Type.TOptional<Type.TNumber>;
126
+ onExpire: Type.TOptional<Type.TUnsafe<"approve" | "fail" | "reject">>;
125
127
  until: Type.TOptional<Type.TString>;
126
128
  maxIterations: Type.TOptional<Type.TNumber>;
127
129
  convergence: Type.TOptional<Type.TBoolean>;
@@ -249,6 +251,33 @@ export declare const TaskflowSchema: Type.TObject<{
249
251
  * flow can never hang forever. A per-phase `idleTimeout` overrides this.
250
252
  */
251
253
  idleTimeout: Type.TOptional<Type.TNumber>;
254
+ /**
255
+ * Fire-and-forget terminal notifications. Payload is summary-only
256
+ * (`taskflow.hook.v1`) — never transcripts. Hook failure does not change run status.
257
+ */
258
+ hooks: Type.TOptional<Type.TObject<{
259
+ onComplete: Type.TOptional<Type.TArray<Type.TObject<{
260
+ type: Type.TUnsafe<"command" | "file" | "webhook">;
261
+ url: Type.TOptional<Type.TString>;
262
+ timeoutMs: Type.TOptional<Type.TNumber>;
263
+ path: Type.TOptional<Type.TString>;
264
+ run: Type.TOptional<Type.TArray<Type.TString>>;
265
+ }>>>;
266
+ onFail: Type.TOptional<Type.TArray<Type.TObject<{
267
+ type: Type.TUnsafe<"command" | "file" | "webhook">;
268
+ url: Type.TOptional<Type.TString>;
269
+ timeoutMs: Type.TOptional<Type.TNumber>;
270
+ path: Type.TOptional<Type.TString>;
271
+ run: Type.TOptional<Type.TArray<Type.TString>>;
272
+ }>>>;
273
+ onBlocked: Type.TOptional<Type.TArray<Type.TObject<{
274
+ type: Type.TUnsafe<"command" | "file" | "webhook">;
275
+ url: Type.TOptional<Type.TString>;
276
+ timeoutMs: Type.TOptional<Type.TNumber>;
277
+ path: Type.TOptional<Type.TString>;
278
+ run: Type.TOptional<Type.TArray<Type.TString>>;
279
+ }>>>;
280
+ }>>;
252
281
  phases: Type.TArray<Type.TObject<{
253
282
  id: Type.TString;
254
283
  type: Type.TOptional<Type.TUnsafe<"agent" | "approval" | "expand" | "flow" | "gate" | "loop" | "map" | "parallel" | "race" | "reduce" | "script" | "tournament">>;
@@ -302,6 +331,8 @@ export declare const TaskflowSchema: Type.TObject<{
302
331
  * Overrides the flow-level `idleTimeout`. Absent → flow-level or host default.
303
332
  */
304
333
  idleTimeout: Type.TOptional<Type.TNumber>;
334
+ timeoutMs: Type.TOptional<Type.TNumber>;
335
+ onExpire: Type.TOptional<Type.TUnsafe<"approve" | "fail" | "reject">>;
305
336
  until: Type.TOptional<Type.TString>;
306
337
  maxIterations: Type.TOptional<Type.TNumber>;
307
338
  convergence: Type.TOptional<Type.TBoolean>;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js CHANGED
@@ -184,6 +184,14 @@ const PhaseSchema = Type.Object({
184
184
  idleTimeout: Type.Optional(Type.Number({
185
185
  description: "[agent-running] Idle watchdog in ms (>= 1000, or 0 to disable). 0 requires a finite wall 'timeout' >= 1000. Overrides the flow-level idleTimeout.",
186
186
  })),
187
+ // approval — HITL wait bound (distinct from agent wall `timeout`)
188
+ timeoutMs: Type.Optional(Type.Number({
189
+ description: "[approval] Max wait for a human decision in ms (>= 1000). On expiry, apply onExpire. Omit for infinite wait (current default).",
190
+ })),
191
+ onExpire: Type.Optional(StringEnum(["reject", "fail", "approve"], {
192
+ description: "[approval] Decision when timeoutMs elapses. Default 'reject'. 'approve' auto-continues without review (footgun — use deliberately).",
193
+ default: "reject",
194
+ })),
187
195
  // loop-until-done
188
196
  until: Type.Optional(Type.String({
189
197
  description: "[loop] Stop condition evaluated after each iteration. The iteration's output is exposed as {steps.<thisId>.output}/.json. Supports the same operators as `when`. The loop stops when this is truthy, on convergence, or at maxIterations. A parse error stops the loop (fail-safe).",
@@ -308,6 +316,16 @@ const ArgSpecSchema = Type.Union([
308
316
  BooleanArgSpecSchema,
309
317
  EnumArgSpecSchema,
310
318
  ]);
319
+ /** Flow-level hook action (webhook | file | command). Validated further in validateTaskflow. */
320
+ const HookActionSchema = Type.Object({
321
+ type: StringEnum(["webhook", "file", "command"]),
322
+ url: Type.Optional(Type.String({ description: "[webhook] Destination URL (https, or http://127.0.0.1|localhost)" })),
323
+ timeoutMs: Type.Optional(Type.Number({ description: "[webhook] Request timeout ms (default 5000)" })),
324
+ path: Type.Optional(Type.String({ description: "[file] Project-relative path for JSON payload" })),
325
+ run: Type.Optional(Type.Array(Type.String(), {
326
+ description: "[command] argv only (no shell string). Receives TASKFLOW_HOOK_* env vars.",
327
+ })),
328
+ }, { additionalProperties: false });
311
329
  export const TaskflowSchema = Type.Object({
312
330
  name: Type.String({ minLength: 1, description: "Workflow name (becomes /tf:<name> command when saved)" }),
313
331
  description: Type.Optional(Type.String()),
@@ -336,6 +354,15 @@ export const TaskflowSchema = Type.Object({
336
354
  idleTimeout: Type.Optional(Type.Number({
337
355
  description: "Flow-level idle watchdog in ms (>= 1000, or 0 to disable). Per-phase idleTimeout overrides. 0 requires every agent-running phase to declare a finite wall 'timeout' >= 1000.",
338
356
  })),
357
+ /**
358
+ * Fire-and-forget terminal notifications. Payload is summary-only
359
+ * (`taskflow.hook.v1`) — never transcripts. Hook failure does not change run status.
360
+ */
361
+ hooks: Type.Optional(Type.Object({
362
+ onComplete: Type.Optional(Type.Array(HookActionSchema, { maxItems: 5 })),
363
+ onFail: Type.Optional(Type.Array(HookActionSchema, { maxItems: 5 })),
364
+ onBlocked: Type.Optional(Type.Array(HookActionSchema, { maxItems: 5 })),
365
+ }, { additionalProperties: false, description: "Terminal-run hooks (complete / fail / blocked)" })),
339
366
  phases: Type.Array(PhaseSchema, { minItems: 1, description: "Ordered phase definitions (DAG via dependsOn)" }),
340
367
  }, { additionalProperties: false });
341
368
  /** True when `def` is a shorthand spec (no `phases`, but a task/tasks/chain field). */
@@ -520,6 +547,76 @@ function typedArgValueErrors(name, spec, value, source) {
520
547
  }
521
548
  return [];
522
549
  }
550
+ /** Inline hook validation (kept in schema to avoid schema↔hooks import cycles). */
551
+ function validateFlowHooksInline(hooks) {
552
+ if (hooks === undefined)
553
+ return [];
554
+ if (!hooks || typeof hooks !== "object" || Array.isArray(hooks))
555
+ return ["hooks must be an object"];
556
+ const h = hooks;
557
+ const errors = [];
558
+ const max = 5;
559
+ for (const event of ["onComplete", "onFail", "onBlocked"]) {
560
+ if (h[event] === undefined)
561
+ continue;
562
+ if (!Array.isArray(h[event])) {
563
+ errors.push(`hooks.${event} must be an array`);
564
+ continue;
565
+ }
566
+ if (h[event].length > max)
567
+ errors.push(`hooks.${event} allows at most ${max} actions`);
568
+ h[event].forEach((action, index) => {
569
+ if (!action || typeof action !== "object" || Array.isArray(action)) {
570
+ errors.push(`hooks.${event}[${index}] must be an object`);
571
+ return;
572
+ }
573
+ const a = action;
574
+ if (a.type === "webhook") {
575
+ if (typeof a.url !== "string" || !a.url.trim()) {
576
+ errors.push(`hooks.${event}[${index}].url is required`);
577
+ return;
578
+ }
579
+ try {
580
+ const u = new URL(a.url.trim());
581
+ const host = u.hostname.toLowerCase();
582
+ const okHttpLocal = u.protocol === "http:" &&
583
+ (host === "127.0.0.1" || host === "localhost" || host === "[::1]" || host === "::1");
584
+ if (u.protocol !== "https:" && !okHttpLocal) {
585
+ errors.push(`hooks.${event}[${index}]: URL must be https or http://127.0.0.1|localhost`);
586
+ }
587
+ }
588
+ catch {
589
+ errors.push(`hooks.${event}[${index}]: invalid URL`);
590
+ }
591
+ if (a.timeoutMs !== undefined &&
592
+ (typeof a.timeoutMs !== "number" || a.timeoutMs < 100 || a.timeoutMs > 60_000)) {
593
+ errors.push(`hooks.${event}[${index}].timeoutMs must be 100–60000`);
594
+ }
595
+ }
596
+ else if (a.type === "file") {
597
+ if (typeof a.path !== "string" || !a.path.trim()) {
598
+ errors.push(`hooks.${event}[${index}].path is required`);
599
+ }
600
+ else if (path.isAbsolute(a.path) || a.path.split(/[/\\]/).includes("..")) {
601
+ errors.push(`hooks.${event}[${index}].path must be project-relative without '..'`);
602
+ }
603
+ }
604
+ else if (a.type === "command") {
605
+ if (!Array.isArray(a.run) || a.run.length === 0 || !a.run.every((x) => typeof x === "string")) {
606
+ errors.push(`hooks.${event}[${index}].run must be a non-empty string array (no shell string)`);
607
+ }
608
+ }
609
+ else {
610
+ errors.push(`hooks.${event}[${index}].type must be webhook|file|command`);
611
+ }
612
+ });
613
+ }
614
+ for (const k of Object.keys(h)) {
615
+ if (!["onComplete", "onFail", "onBlocked"].includes(k))
616
+ errors.push(`hooks: unknown key '${k}'`);
617
+ }
618
+ return errors;
619
+ }
523
620
  /** Validate resolved invocation values independently of full flow structure.
524
621
  * Runtime calls this at the Core boundary so direct, resume, and detached
525
622
  * execution cannot bypass adapter-level typed-arg checks. */
@@ -605,6 +702,10 @@ export function validateTaskflow(def, opts = {}) {
605
702
  warnings.push(`Invocation argument '${name}' is undeclared`);
606
703
  }
607
704
  }
705
+ // Flow-level hooks (summary-only terminal notifications).
706
+ if (flow.hooks !== undefined) {
707
+ errors.push(...validateFlowHooksInline(flow.hooks));
708
+ }
608
709
  // Flow-level idleTimeout: positive must be >= 1000; 0 is allowed (disables the
609
710
  // watchdog) but every agent-running phase must then declare a finite wall
610
711
  // `timeout` so the run can never hang forever (critical invariant #5).
@@ -869,6 +970,28 @@ export function validateTaskflow(def, opts = {}) {
869
970
  errors.push(`Phase '${p.id}' (${type}): 'reflexion' is only valid for loop phases`);
870
971
  }
871
972
  }
973
+ // Approval wait bound (timeoutMs / onExpire) — approval-only.
974
+ if (p.timeoutMs !== undefined) {
975
+ const t = p.timeoutMs;
976
+ if (type !== "approval") {
977
+ errors.push(`Phase '${p.id}' (${type}): 'timeoutMs' is only valid for approval phases (use 'timeout' for agent wall caps)`);
978
+ }
979
+ else if (typeof t !== "number" || !Number.isFinite(t) || t < 1000) {
980
+ errors.push(`Phase '${p.id}' (approval): 'timeoutMs' must be a number >= 1000 ms`);
981
+ }
982
+ }
983
+ if (p.onExpire !== undefined) {
984
+ const o = p.onExpire;
985
+ if (type !== "approval") {
986
+ errors.push(`Phase '${p.id}' (${type}): 'onExpire' is only valid for approval phases`);
987
+ }
988
+ else if (o !== "reject" && o !== "fail" && o !== "approve") {
989
+ errors.push(`Phase '${p.id}' (approval): 'onExpire' must be reject|fail|approve`);
990
+ }
991
+ else if (p.timeoutMs === undefined) {
992
+ warnings.push(`Phase '${p.id}' (approval): 'onExpire' without 'timeoutMs' has no effect`);
993
+ }
994
+ }
872
995
  // Other loop-only fields on non-loop phases are silently ignored by the
873
996
  // runtime — warn so the author learns the field does nothing (a warning,
874
997
  // not an error, to avoid breaking pre-existing flows that carry them).