@devflow-tools/workflow-engine 0.16.21 → 0.16.23

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 (55) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/types.d.ts +37 -0
  6. package/dist/types.d.ts.map +1 -1
  7. package/dist/workers/context-session.d.ts +52 -0
  8. package/dist/workers/context-session.d.ts.map +1 -0
  9. package/dist/workers/context-session.js +70 -0
  10. package/dist/workers/context-session.js.map +1 -0
  11. package/dist/workers/file-ownership.d.ts +13 -0
  12. package/dist/workers/file-ownership.d.ts.map +1 -0
  13. package/dist/workers/file-ownership.js +87 -0
  14. package/dist/workers/file-ownership.js.map +1 -0
  15. package/dist/workers/git-worktree.d.ts +33 -0
  16. package/dist/workers/git-worktree.d.ts.map +1 -0
  17. package/dist/workers/git-worktree.js +121 -0
  18. package/dist/workers/git-worktree.js.map +1 -0
  19. package/dist/workers/handoff.d.ts +11 -0
  20. package/dist/workers/handoff.d.ts.map +1 -0
  21. package/dist/workers/handoff.js +64 -0
  22. package/dist/workers/handoff.js.map +1 -0
  23. package/dist/workers/host-launcher.d.ts +21 -0
  24. package/dist/workers/host-launcher.d.ts.map +1 -0
  25. package/dist/workers/host-launcher.js +99 -0
  26. package/dist/workers/host-launcher.js.map +1 -0
  27. package/dist/workers/index.d.ts +11 -0
  28. package/dist/workers/index.d.ts.map +1 -0
  29. package/dist/workers/index.js +11 -0
  30. package/dist/workers/index.js.map +1 -0
  31. package/dist/workers/merge-queue.d.ts +55 -0
  32. package/dist/workers/merge-queue.d.ts.map +1 -0
  33. package/dist/workers/merge-queue.js +76 -0
  34. package/dist/workers/merge-queue.js.map +1 -0
  35. package/dist/workers/paths.d.ts +8 -0
  36. package/dist/workers/paths.d.ts.map +1 -0
  37. package/dist/workers/paths.js +49 -0
  38. package/dist/workers/paths.js.map +1 -0
  39. package/dist/workers/scheduler.d.ts +19 -0
  40. package/dist/workers/scheduler.d.ts.map +1 -0
  41. package/dist/workers/scheduler.js +37 -0
  42. package/dist/workers/scheduler.js.map +1 -0
  43. package/dist/workers/types.d.ts +78 -0
  44. package/dist/workers/types.d.ts.map +1 -0
  45. package/dist/workers/types.js +2 -0
  46. package/dist/workers/types.js.map +1 -0
  47. package/dist/workers/verifier.d.ts +66 -0
  48. package/dist/workers/verifier.d.ts.map +1 -0
  49. package/dist/workers/verifier.js +123 -0
  50. package/dist/workers/verifier.js.map +1 -0
  51. package/dist/workflow-engine.d.ts +2 -0
  52. package/dist/workflow-engine.d.ts.map +1 -1
  53. package/dist/workflow-engine.js +92 -1
  54. package/dist/workflow-engine.js.map +1 -1
  55. package/package.json +4 -4
@@ -0,0 +1,21 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { HostAdapter, HostWorkerLaunchProjection } from '@devflow-tools/sdk';
3
+ import type { WorkerCoordinationPaths, WorkerHandoff, WorkerLaunchRequest, WorkerTaskEnvelope } from './types.js';
4
+ export interface WorkerProcessResult {
5
+ exitCode: number | null;
6
+ signal: NodeJS.Signals | null;
7
+ timedOut: boolean;
8
+ cancelled: boolean;
9
+ handoff?: WorkerHandoff;
10
+ }
11
+ export declare function createWorkerArtifacts(paths: WorkerCoordinationPaths, envelope: WorkerTaskEnvelope): void;
12
+ export declare function projectWorkerLaunch(adapter: HostAdapter, request: WorkerLaunchRequest): HostWorkerLaunchProjection;
13
+ export declare function launchWorker(adapter: HostAdapter, request: WorkerLaunchRequest, paths: WorkerCoordinationPaths, options?: {
14
+ parentEnv?: NodeJS.ProcessEnv;
15
+ onHeartbeat?: () => void;
16
+ }): {
17
+ child: ChildProcess;
18
+ completion: Promise<WorkerProcessResult>;
19
+ cancel: () => void;
20
+ };
21
+ //# sourceMappingURL=host-launcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-launcher.d.ts","sourceRoot":"","sources":["../../src/workers/host-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAOpB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,kBAAkB,GAC3B,IAAI,CAQN;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,GAC3B,0BAA0B,CAgB5B;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,mBAAmB,EAC5B,KAAK,EAAE,uBAAuB,EAC9B,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACxE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CA4DvF"}
@@ -0,0 +1,99 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { closeSync, mkdirSync, openSync } from 'node:fs';
3
+ import { dirname } from 'node:path';
4
+ import { readWorkerHandoff, writeJsonAtomic, writeWorkerTask } from './handoff.js';
5
+ const ALLOWED_ENV_KEYS = new Set([
6
+ 'PATH', 'HOME', 'USER', 'SHELL', 'TMPDIR', 'LANG', 'LC_ALL',
7
+ 'CODEX_HOME', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY',
8
+ ]);
9
+ export function createWorkerArtifacts(paths, envelope) {
10
+ mkdirSync(paths.root, { recursive: true, mode: 0o700 });
11
+ writeWorkerTask(paths.taskFile, envelope);
12
+ writeJsonAtomic(paths.statusFile, {
13
+ workerId: envelope.workerId,
14
+ state: 'planned',
15
+ updatedAt: Date.now(),
16
+ });
17
+ }
18
+ export function projectWorkerLaunch(adapter, request) {
19
+ if (!adapter.workers) {
20
+ return {
21
+ status: 'unavailable', args: [], env: {}, detached: false,
22
+ completionFormat: 'handoff-file', reason: `Host ${adapter.id} does not support isolated workers.`,
23
+ };
24
+ }
25
+ const projection = adapter.workers.project(request);
26
+ if (projection.command?.includes('\0') || projection.args.some(arg => arg.includes('\0'))) {
27
+ throw new Error('WORKER_LAUNCH_INVALID_ARGUMENT');
28
+ }
29
+ return {
30
+ ...projection,
31
+ env: Object.fromEntries(Object.entries(projection.env)
32
+ .filter(([key, value]) => key.startsWith('DEVFLOW_') && typeof value === 'string')),
33
+ };
34
+ }
35
+ export function launchWorker(adapter, request, paths, options = {}) {
36
+ const projection = projectWorkerLaunch(adapter, request);
37
+ if (projection.status !== 'supported' || !projection.command) {
38
+ throw new Error(`WORKER_HOST_UNAVAILABLE:${projection.reason ?? adapter.id}`);
39
+ }
40
+ mkdirSync(dirname(paths.stdoutFile), { recursive: true });
41
+ const stdoutFd = openSync(paths.stdoutFile, 'a', 0o600);
42
+ const stderrFd = openSync(paths.stderrFile, 'a', 0o600);
43
+ const parentEnv = Object.fromEntries(Object.entries(options.parentEnv ?? process.env)
44
+ .filter(([key, value]) => ALLOWED_ENV_KEYS.has(key) && typeof value === 'string'));
45
+ const child = spawn(projection.command, projection.args, {
46
+ cwd: request.worktreePath,
47
+ shell: false,
48
+ detached: projection.detached,
49
+ stdio: ['ignore', stdoutFd, stderrFd],
50
+ env: { ...parentEnv, ...projection.env },
51
+ });
52
+ if (projection.detached)
53
+ child.unref();
54
+ closeSync(stdoutFd);
55
+ closeSync(stderrFd);
56
+ let timedOut = false;
57
+ let cancelled = false;
58
+ const terminate = () => {
59
+ if (child.exitCode !== null)
60
+ return;
61
+ child.kill('SIGTERM');
62
+ setTimeout(() => child.kill('SIGKILL'), 2_000).unref();
63
+ };
64
+ const timer = setTimeout(() => { timedOut = true; terminate(); }, request.timeoutMs);
65
+ timer.unref();
66
+ const heartbeat = setInterval(() => options.onHeartbeat?.(), 10_000);
67
+ heartbeat.unref();
68
+ const completion = new Promise((resolve, reject) => {
69
+ child.on('error', error => {
70
+ clearTimeout(timer);
71
+ clearInterval(heartbeat);
72
+ reject(error);
73
+ });
74
+ child.on('close', (exitCode, signal) => {
75
+ clearTimeout(timer);
76
+ clearInterval(heartbeat);
77
+ let handoff;
78
+ try {
79
+ handoff = readWorkerHandoff(paths.handoffFile, {
80
+ workerId: request.workerId,
81
+ runId: request.runId,
82
+ stepId: request.stepId,
83
+ contextReceipt: request.contextReceipt,
84
+ worktreePath: request.worktreePath,
85
+ });
86
+ }
87
+ catch {
88
+ // Process exit is only a report event; missing handoff is handled by verification.
89
+ }
90
+ resolve({ exitCode, signal, timedOut, cancelled, handoff });
91
+ });
92
+ });
93
+ return {
94
+ child,
95
+ completion,
96
+ cancel: () => { cancelled = true; terminate(); },
97
+ };
98
+ }
99
+ //# sourceMappingURL=host-launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-launcher.js","sourceRoot":"","sources":["../../src/workers/host-launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export * from './types.js';
2
+ export * from './paths.js';
3
+ export * from './git-worktree.js';
4
+ export * from './handoff.js';
5
+ export * from './host-launcher.js';
6
+ export * from './file-ownership.js';
7
+ export * from './scheduler.js';
8
+ export * from './context-session.js';
9
+ export * from './verifier.js';
10
+ export * from './merge-queue.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export * from './types.js';
2
+ export * from './paths.js';
3
+ export * from './git-worktree.js';
4
+ export * from './handoff.js';
5
+ export * from './host-launcher.js';
6
+ export * from './file-ownership.js';
7
+ export * from './scheduler.js';
8
+ export * from './context-session.js';
9
+ export * from './verifier.js';
10
+ export * from './merge-queue.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,55 @@
1
+ import type { WorkerVerificationResult } from './verifier.js';
2
+ export interface MergeQueueRecord {
3
+ mergeId: string;
4
+ workerId: string;
5
+ projectRoot: string;
6
+ state: 'waiting' | 'ready' | 'conflict' | 'merged' | 'rejected';
7
+ parentRevision: string;
8
+ candidateRevision: string;
9
+ graderReceipts: string[];
10
+ simulationHash?: string;
11
+ }
12
+ export interface MergeQueueStore {
13
+ enqueueWorkflowMerge(input: {
14
+ workerId: string;
15
+ projectRoot: string;
16
+ baseRevision: string;
17
+ parentRevision: string;
18
+ candidateRevision: string;
19
+ graderReceipts: string[];
20
+ simulationHash?: string;
21
+ }): MergeQueueRecord | Promise<MergeQueueRecord>;
22
+ transitionWorkflowMerge(projectRoot: string, mergeId: string, target: MergeQueueRecord['state'], update?: {
23
+ parentRevision?: string;
24
+ simulationHash?: string;
25
+ mergeCommit?: string;
26
+ reason?: string;
27
+ }): MergeQueueRecord | Promise<MergeQueueRecord>;
28
+ }
29
+ export declare class SerializedWorkerMergeQueue {
30
+ private readonly store;
31
+ private readonly lifecycle;
32
+ constructor(store: MergeQueueStore, lifecycle?: {
33
+ onMerged?: (input: {
34
+ workerId: string;
35
+ mergeCommit: string;
36
+ }) => void | Promise<void>;
37
+ scheduleCleanup?: (input: {
38
+ workerId: string;
39
+ mergeCommit: string;
40
+ }) => void | Promise<void>;
41
+ });
42
+ enqueueAndMerge(input: {
43
+ workerId: string;
44
+ projectRoot: string;
45
+ baseRevision: string;
46
+ verification: WorkerVerificationResult;
47
+ message: string;
48
+ }): Promise<{
49
+ state: 'merged' | 'conflict';
50
+ mergeCommit?: string;
51
+ reason?: string;
52
+ }>;
53
+ private serialize;
54
+ }
55
+ //# sourceMappingURL=merge-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-queue.d.ts","sourceRoot":"","sources":["../../src/workers/merge-queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,oBAAoB,CAAC,KAAK,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjD,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,EACjC,MAAM,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACnG,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjD;AAID,qBAAa,0BAA0B;IAEnC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,eAAe,EACtB,SAAS,GAAE;QAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACtF,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACzF;IAGF,eAAe,CAAC,KAAK,EAAE;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,wBAAwB,CAAC;QACvC,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,QAAQ,GAAG,UAAU,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;YAiDtE,SAAS;CAYxB"}
@@ -0,0 +1,76 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { gitRevision, runGit, simulateMerge } from './git-worktree.js';
3
+ const projectQueues = new Map();
4
+ export class SerializedWorkerMergeQueue {
5
+ store;
6
+ lifecycle;
7
+ constructor(store, lifecycle = {}) {
8
+ this.store = store;
9
+ this.lifecycle = lifecycle;
10
+ }
11
+ async enqueueAndMerge(input) {
12
+ if (!input.verification.passed || !input.verification.finalRevision || !input.verification.simulationHash) {
13
+ throw new Error('WORKER_MERGE_REQUIRES_VERIFIED_EVIDENCE');
14
+ }
15
+ const record = await this.store.enqueueWorkflowMerge({
16
+ workerId: input.workerId,
17
+ projectRoot: input.projectRoot,
18
+ baseRevision: input.baseRevision,
19
+ parentRevision: input.verification.parentRevision,
20
+ candidateRevision: input.verification.finalRevision,
21
+ graderReceipts: input.verification.graderReceipts,
22
+ simulationHash: input.verification.simulationHash,
23
+ });
24
+ return this.serialize(input.projectRoot, async () => {
25
+ const currentParent = await gitRevision(input.projectRoot, 'HEAD');
26
+ if (currentParent !== record.parentRevision) {
27
+ await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', {
28
+ parentRevision: currentParent, reason: 'parent_advanced_after_simulation',
29
+ });
30
+ return { state: 'conflict', reason: 'parent_advanced_after_simulation' };
31
+ }
32
+ const simulation = await simulateMerge(input.projectRoot, currentParent, record.candidateRevision);
33
+ const currentHash = createHash('sha256').update(JSON.stringify({
34
+ parent: currentParent, candidate: record.candidateRevision, exitCode: simulation.exitCode,
35
+ stdout: simulation.stdout, stderr: simulation.stderr,
36
+ })).digest('hex');
37
+ if (simulation.exitCode !== 0 || currentHash !== record.simulationHash) {
38
+ await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', {
39
+ simulationHash: currentHash, reason: 'merge_simulation_changed',
40
+ });
41
+ return { state: 'conflict', reason: 'merge_simulation_changed' };
42
+ }
43
+ await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'ready');
44
+ const merged = await runGit(input.projectRoot, [
45
+ 'merge', '--no-ff', '--no-edit', '-m', input.message.slice(0, 500), record.candidateRevision,
46
+ ], { timeoutMs: 120_000, maxOutputBytes: 1_000_000 });
47
+ if (merged.exitCode !== 0) {
48
+ await runGit(input.projectRoot, ['merge', '--abort']);
49
+ await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'conflict', { reason: 'merge_command_conflict' });
50
+ return { state: 'conflict', reason: 'merge_command_conflict' };
51
+ }
52
+ const mergeCommit = await gitRevision(input.projectRoot, 'HEAD');
53
+ await this.store.transitionWorkflowMerge(input.projectRoot, record.mergeId, 'merged', { mergeCommit });
54
+ await this.lifecycle.onMerged?.({ workerId: input.workerId, mergeCommit });
55
+ await this.lifecycle.scheduleCleanup?.({ workerId: input.workerId, mergeCommit });
56
+ return { state: 'merged', mergeCommit };
57
+ });
58
+ }
59
+ async serialize(projectRoot, operation) {
60
+ const prior = projectQueues.get(projectRoot) ?? Promise.resolve();
61
+ let release;
62
+ const current = new Promise(resolve => { release = resolve; });
63
+ const queued = prior.then(() => current);
64
+ projectQueues.set(projectRoot, queued);
65
+ await prior.catch(() => undefined);
66
+ try {
67
+ return await operation();
68
+ }
69
+ finally {
70
+ release();
71
+ if (projectQueues.get(projectRoot) === queued)
72
+ projectQueues.delete(projectRoot);
73
+ }
74
+ }
75
+ }
76
+ //# sourceMappingURL=merge-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-queue.js","sourceRoot":"","sources":["../../src/workers/merge-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function sanitizeWorkerSlug(value: string, fallback?: string): string;
2
+ export declare function projectWorktreeHash(repositoryRoot: string): string;
3
+ export declare function workerBranch(runId: string, stepId: string): string;
4
+ export declare function workerWorktreePath(repositoryRoot: string, runId: string, stepId: string, home?: string): string;
5
+ export declare function workerCoordinationRoot(workerId: string, home?: string): string;
6
+ export declare function isPathInside(parent: string, candidate: string): boolean;
7
+ export declare function assertSafeWorkerPath(repositoryRoot: string, candidate: string, home?: string): string;
8
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/workers/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,MAAM,CAM7E;AAED,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,SAAY,GACf,MAAM,CAGR;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAY,GAAG,MAAM,CAEjF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGvE;AAED,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,SAAY,GACf,MAAM,CAkBR"}
@@ -0,0 +1,49 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { homedir } from 'node:os';
3
+ import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
4
+ import { existsSync, realpathSync } from 'node:fs';
5
+ export function sanitizeWorkerSlug(value, fallback = 'worker') {
6
+ const slug = value.trim().toLowerCase()
7
+ .replace(/[^a-z0-9._-]+/g, '-')
8
+ .replace(/^[._-]+|[._-]+$/g, '')
9
+ .slice(0, 64);
10
+ return slug || fallback;
11
+ }
12
+ export function projectWorktreeHash(repositoryRoot) {
13
+ return createHash('sha256').update(resolve(repositoryRoot)).digest('hex').slice(0, 16);
14
+ }
15
+ export function workerBranch(runId, stepId) {
16
+ return `devflow/${sanitizeWorkerSlug(runId, 'run')}/${sanitizeWorkerSlug(stepId, 'step')}`;
17
+ }
18
+ export function workerWorktreePath(repositoryRoot, runId, stepId, home = homedir()) {
19
+ const name = `${sanitizeWorkerSlug(runId, 'run')}-${sanitizeWorkerSlug(stepId, 'step')}`;
20
+ return join(home, '.devflow', 'worktrees', projectWorktreeHash(repositoryRoot), name);
21
+ }
22
+ export function workerCoordinationRoot(workerId, home = homedir()) {
23
+ return join(home, '.devflow', 'workers', sanitizeWorkerSlug(workerId));
24
+ }
25
+ export function isPathInside(parent, candidate) {
26
+ const rel = relative(resolve(parent), resolve(candidate));
27
+ return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel));
28
+ }
29
+ export function assertSafeWorkerPath(repositoryRoot, candidate, home = homedir()) {
30
+ const expectedRoot = resolve(home, '.devflow', 'worktrees', projectWorktreeHash(repositoryRoot));
31
+ const resolvedCandidate = resolve(candidate);
32
+ if (!isPathInside(expectedRoot, resolvedCandidate) || resolvedCandidate === expectedRoot) {
33
+ throw new Error(`WORKTREE_PATH_OUTSIDE_MANAGED_ROOT:${candidate}`);
34
+ }
35
+ if (isPathInside(repositoryRoot, resolvedCandidate)) {
36
+ throw new Error(`WORKTREE_PATH_INSIDE_SOURCE:${candidate}`);
37
+ }
38
+ const parent = resolve(resolvedCandidate, '..');
39
+ if (existsSync(parent)) {
40
+ const realParent = realpathSync(parent);
41
+ if (!isPathInside(expectedRoot, realParent)) {
42
+ throw new Error(`WORKTREE_PATH_SYMLINK_ESCAPE:${candidate}`);
43
+ }
44
+ }
45
+ if (!basename(resolvedCandidate).trim())
46
+ throw new Error('WORKTREE_PATH_EMPTY_NAME');
47
+ return resolvedCandidate;
48
+ }
49
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/workers/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { StepInstruction, WorkflowStepDef } from '@devflow-tools/sdk';
2
+ import { type FileOwnership } from './file-ownership.js';
3
+ export interface ScheduledWorkerStep<T> {
4
+ step: T;
5
+ ownership: FileOwnership;
6
+ eligible: boolean;
7
+ reason?: string;
8
+ }
9
+ export interface WorkerSchedule<T> {
10
+ batches: Array<Array<ScheduledWorkerStep<T>>>;
11
+ maxConcurrency: number;
12
+ recursiveRequestRejected: boolean;
13
+ }
14
+ export declare function resolveWorkerConcurrency(env?: NodeJS.ProcessEnv): number;
15
+ export declare function scheduleWorkerSteps<T extends WorkflowStepDef | StepInstruction>(steps: T[], inputs?: Map<string, Record<string, unknown>>, options?: {
16
+ maxConcurrency?: number;
17
+ recursiveRequest?: boolean;
18
+ }): WorkerSchedule<T>;
19
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/workers/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAA2C,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElG,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;IACR,SAAS,EAAE,aAAa,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAIrF;AAED,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,GAAG,eAAe,EAC7E,KAAK,EAAE,CAAC,EAAE,EACV,MAAM,GAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa,EACxD,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GACpE,cAAc,CAAC,CAAC,CAAC,CA0BnB"}
@@ -0,0 +1,37 @@
1
+ import { ownershipOverlaps, predictFileOwnership } from './file-ownership.js';
2
+ export function resolveWorkerConcurrency(env = process.env) {
3
+ const requested = Number(env.DEVFLOW_WORKER_CONCURRENCY ?? 3);
4
+ if (!Number.isFinite(requested))
5
+ return 3;
6
+ return Math.max(1, Math.min(3, Math.floor(requested)));
7
+ }
8
+ export function scheduleWorkerSteps(steps, inputs = new Map(), options = {}) {
9
+ const maxConcurrency = Math.max(1, Math.min(3, options.maxConcurrency ?? resolveWorkerConcurrency()));
10
+ if (options.recursiveRequest) {
11
+ return { batches: [], maxConcurrency, recursiveRequestRejected: true };
12
+ }
13
+ const scheduled = steps.map(step => {
14
+ const ownership = predictFileOwnership(step, inputs.get(step.id) ?? {});
15
+ return {
16
+ step,
17
+ ownership,
18
+ eligible: ownership.risk === 'low',
19
+ ...(ownership.risk === 'high' ? { reason: ownership.reasons.join(',') } : {}),
20
+ };
21
+ });
22
+ const batches = [];
23
+ for (const candidate of scheduled) {
24
+ if (!candidate.eligible) {
25
+ batches.push([candidate]);
26
+ continue;
27
+ }
28
+ const batch = batches.find(current => current.length < maxConcurrency
29
+ && current.every(existing => existing.eligible && !ownershipOverlaps(existing.ownership, candidate.ownership)));
30
+ if (batch)
31
+ batch.push(candidate);
32
+ else
33
+ batches.push([candidate]);
34
+ }
35
+ return { batches, maxConcurrency, recursiveRequestRejected: false };
36
+ }
37
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/workers/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAsB,MAAM,qBAAqB,CAAC;AAelG,MAAM,UAAU,wBAAwB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,0BAA0B,IAAI,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAU,EACV,SAA+C,IAAI,GAAG,EAAE,EACxD,UAAmE,EAAE;IAErE,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,wBAAwB,EAAE,CAAC,CAAC,CAAC;IACtG,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACjC,MAAM,SAAS,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,OAAO;YACL,IAAI;YACJ,SAAS;YACT,QAAQ,EAAE,SAAS,CAAC,IAAI,KAAK,KAAK;YAClC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7C,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAyC,EAAE,CAAC;IACzD,KAAK,MAAM,SAAS,IAAI,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,cAAc;eAChE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAClH,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,KAAK,EAAE,CAAC;AACtE,CAAC"}
@@ -0,0 +1,78 @@
1
+ export type WorkerHost = 'claude-code' | 'codex' | 'custom';
2
+ export interface WorkerLaunchRequest {
3
+ workerId: string;
4
+ runId: string;
5
+ stepId: string;
6
+ host: WorkerHost;
7
+ worktreePath: string;
8
+ taskFile: string;
9
+ handoffFile: string;
10
+ statusFile: string;
11
+ sessionId: string;
12
+ executionId: string;
13
+ contextReceipt: string;
14
+ timeoutMs: number;
15
+ }
16
+ export interface WorkerTaskEnvelope {
17
+ workerId: string;
18
+ runId: string;
19
+ stepId: string;
20
+ projectRoot: string;
21
+ worktreePath: string;
22
+ baseRevision: string;
23
+ contextReceipt: string;
24
+ retrievalSessionId?: string;
25
+ allowedFiles: string[];
26
+ requiredTools: string[];
27
+ task: Record<string, unknown>;
28
+ verification: {
29
+ commands: Array<{
30
+ command: string;
31
+ args: string[];
32
+ }>;
33
+ graders: string[];
34
+ };
35
+ constraints: {
36
+ recursiveWorkers: false;
37
+ maxContextCycles: number;
38
+ };
39
+ }
40
+ export interface WorkerHandoff {
41
+ workerId: string;
42
+ runId: string;
43
+ stepId: string;
44
+ baseRevision: string;
45
+ finalRevision: string;
46
+ changedFiles: string[];
47
+ contextReceipt: string;
48
+ toolReceipts: string[];
49
+ reportReceipts: string[];
50
+ verificationIntent: string[];
51
+ summary: string;
52
+ hostStatus: 'completed' | 'failed' | 'cancelled' | 'timed_out';
53
+ }
54
+ export interface WorkerCoordinationPaths {
55
+ root: string;
56
+ taskFile: string;
57
+ handoffFile: string;
58
+ statusFile: string;
59
+ stdoutFile: string;
60
+ stderrFile: string;
61
+ }
62
+ export interface GitCommandResult {
63
+ command: string;
64
+ args: string[];
65
+ cwd: string;
66
+ exitCode: number;
67
+ stdout: string;
68
+ stderr: string;
69
+ timedOut: boolean;
70
+ truncated: boolean;
71
+ }
72
+ export interface WorktreeDescriptor {
73
+ repositoryRoot: string;
74
+ worktreePath: string;
75
+ branch: string;
76
+ baseRevision: string;
77
+ }
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workers/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,YAAY,EAAE;QACZ,QAAQ,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAC;QACrD,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,WAAW,EAAE;QACX,gBAAgB,EAAE,KAAK,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;CAChE;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/workers/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ import type { WorkerHandoff } from './types.js';
2
+ export interface WorkerGraderResult {
3
+ graderId: string;
4
+ kind: 'deterministic' | 'model' | 'human';
5
+ status: 'passed' | 'failed' | 'unavailable';
6
+ receipt: string;
7
+ reason?: string;
8
+ }
9
+ export interface WorkerGraderSummary {
10
+ status: 'passed' | 'failed' | 'unavailable';
11
+ results: WorkerGraderResult[];
12
+ blockingFailures: string[];
13
+ unavailableBlocking: string[];
14
+ }
15
+ export interface WorkerGraderRunner {
16
+ run(context: {
17
+ taskKind: string;
18
+ projectRoot: string;
19
+ evidence: Record<string, unknown>;
20
+ }, graderIds?: string[]): Promise<WorkerGraderSummary>;
21
+ }
22
+ export interface WorkerVerificationInput {
23
+ workerId: string;
24
+ projectRoot: string;
25
+ worktreePath: string;
26
+ baseRevision: string;
27
+ parentRevision: string;
28
+ contextReceipt: string;
29
+ allowedFiles: string[];
30
+ handoff: WorkerHandoff;
31
+ hostAction: {
32
+ state: string;
33
+ evidenceHash?: string;
34
+ report: Record<string, unknown>;
35
+ };
36
+ graderRunner?: WorkerGraderRunner;
37
+ graderIds?: string[];
38
+ verificationCommands?: Array<{
39
+ command: string;
40
+ args: string[];
41
+ timeoutMs?: number;
42
+ }>;
43
+ }
44
+ export interface WorkerVerificationResult {
45
+ passed: boolean;
46
+ state: 'merge_ready' | 'hold' | 'failed';
47
+ reason?: string;
48
+ finalRevision?: string;
49
+ changedFiles: string[];
50
+ graderReceipts: string[];
51
+ simulationHash?: string;
52
+ parentRevision: string;
53
+ }
54
+ export declare function verifyWorkerOutput(input: WorkerVerificationInput): Promise<WorkerVerificationResult>;
55
+ export declare function runVerificationCommands(cwd: string, commands: Array<{
56
+ command: string;
57
+ args: string[];
58
+ timeoutMs?: number;
59
+ }>): Promise<Array<{
60
+ command: string;
61
+ args: string[];
62
+ exitCode: number;
63
+ timedOut: boolean;
64
+ outputHash: string;
65
+ }>>;
66
+ //# sourceMappingURL=verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/workers/verifier.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,GAAG,OAAO,GAAG,OAAO,CAAC;IAC1C,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC5C,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,OAAO,EAAE;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACtF,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvF;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA2D1G;AAED,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACvE,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAoC9G"}