@vzn/vx 0.0.0 → 0.0.12

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +332 -1
  3. package/launcher.mjs +84 -0
  4. package/package.json +44 -3
  5. package/src/bin.ts +25 -0
  6. package/src/cache/cache.ts +1832 -0
  7. package/src/cache/cas-backend.ts +97 -0
  8. package/src/cache/digest.ts +47 -0
  9. package/src/cache/index.ts +29 -0
  10. package/src/cache/inputs.ts +833 -0
  11. package/src/cache/layered-cache.ts +335 -0
  12. package/src/cache/remote-cache.ts +251 -0
  13. package/src/cache/tar.ts +343 -0
  14. package/src/cli/backend.ts +23 -0
  15. package/src/cli/cache.ts +101 -0
  16. package/src/cli/format.ts +15 -0
  17. package/src/cli/help.ts +123 -0
  18. package/src/cli/index.ts +85 -0
  19. package/src/cli/info.ts +83 -0
  20. package/src/cli/lock.ts +135 -0
  21. package/src/cli/mcp-rpc.ts +292 -0
  22. package/src/cli/mcp.ts +92 -0
  23. package/src/cli/migrate-nx.ts +450 -0
  24. package/src/cli/migrate-turbo.ts +364 -0
  25. package/src/cli/migrate.ts +219 -0
  26. package/src/cli/plan-format.ts +148 -0
  27. package/src/cli/run.ts +661 -0
  28. package/src/cli/show.ts +201 -0
  29. package/src/cli/upgrade.ts +103 -0
  30. package/src/cli/watch.ts +287 -0
  31. package/src/config.ts +421 -0
  32. package/src/exec/env.ts +74 -0
  33. package/src/exec/index.ts +13 -0
  34. package/src/exec/runner.ts +470 -0
  35. package/src/exec/sandbox-runtime.ts +578 -0
  36. package/src/graph/dependency-spec.ts +69 -0
  37. package/src/graph/index.ts +18 -0
  38. package/src/graph/scheduler.ts +482 -0
  39. package/src/graph/task-graph.ts +325 -0
  40. package/src/index.ts +197 -0
  41. package/src/orchestrator/colors.ts +63 -0
  42. package/src/orchestrator/devframe-surface.ts +74 -0
  43. package/src/orchestrator/events.ts +277 -0
  44. package/src/orchestrator/execute-task.ts +883 -0
  45. package/src/orchestrator/framed-output.ts +461 -0
  46. package/src/orchestrator/history.ts +148 -0
  47. package/src/orchestrator/index.ts +163 -0
  48. package/src/orchestrator/local-shortcircuit.ts +147 -0
  49. package/src/orchestrator/logger.ts +526 -0
  50. package/src/orchestrator/metrics.ts +1576 -0
  51. package/src/orchestrator/options.ts +176 -0
  52. package/src/orchestrator/plan.ts +129 -0
  53. package/src/orchestrator/plugin-host.ts +190 -0
  54. package/src/orchestrator/plugin.ts +283 -0
  55. package/src/orchestrator/predict.ts +106 -0
  56. package/src/orchestrator/prepare.ts +297 -0
  57. package/src/orchestrator/protocol.ts +142 -0
  58. package/src/orchestrator/remote-cache-setup.ts +60 -0
  59. package/src/orchestrator/remote-prefetch.ts +81 -0
  60. package/src/orchestrator/run-artifacts.ts +111 -0
  61. package/src/orchestrator/run-context.ts +205 -0
  62. package/src/orchestrator/run-report.ts +132 -0
  63. package/src/orchestrator/run-state.ts +145 -0
  64. package/src/orchestrator/run.ts +842 -0
  65. package/src/orchestrator/stable-keys.ts +177 -0
  66. package/src/orchestrator/status-line.ts +287 -0
  67. package/src/orchestrator/summary.ts +291 -0
  68. package/src/orchestrator/tally.ts +69 -0
  69. package/src/orchestrator/task-hash.ts +238 -0
  70. package/src/orchestrator/telemetry-host.ts +80 -0
  71. package/src/orchestrator/telemetry.ts +350 -0
  72. package/src/orchestrator/upstream.ts +93 -0
  73. package/src/orchestrator/verify.ts +141 -0
  74. package/src/orchestrator/wire-render.ts +92 -0
  75. package/src/orchestrator/wire.ts +212 -0
  76. package/src/util/errors.ts +11 -0
  77. package/src/util/hash.ts +25 -0
  78. package/src/util/index.ts +7 -0
  79. package/src/util/paths.ts +16 -0
  80. package/src/util/ulid.ts +15 -0
  81. package/src/version.ts +10 -0
  82. package/src/workspace/affected.ts +118 -0
  83. package/src/workspace/filter.ts +155 -0
  84. package/src/workspace/fingerprint.ts +41 -0
  85. package/src/workspace/index.ts +27 -0
  86. package/src/workspace/lockfile.ts +118 -0
  87. package/src/workspace/nested-dirs.ts +34 -0
  88. package/src/workspace/package-graph.ts +148 -0
  89. package/src/workspace/project-loader.ts +470 -0
  90. package/src/workspace/workspace.ts +176 -0
@@ -0,0 +1,163 @@
1
+ // Module contract for `orchestrator`. Cross-module imports must come
2
+ // through here (enforced by tests/module-boundaries.test.ts).
3
+
4
+ export { run, planRun } from './run.js'
5
+ export { prepareRun, type PreparedRun } from './prepare.js'
6
+ export { computeTaskHash, createHashCache, type HashCache } from './task-hash.js'
7
+ export type { RunOptions, RunSummary } from './options.js'
8
+ // Re-surface the cache policy contract (defined in the cache module) so
9
+ // embedders constructing RunOptions.cache and the package façade can
10
+ // reach it without importing the cache module directly.
11
+ export { type CachePolicy, FULL_CACHE_POLICY, parseCachePolicy } from '../cache/index.js'
12
+ export { defaultLogger, resolveOutputView } from './logger.js'
13
+ export type { Logger, OutputView } from './logger.js'
14
+ export type { RunPlan, PlannedTask, CacheStatus } from './plan.js'
15
+ export {
16
+ createEventBus,
17
+ wireForwarder,
18
+ toWireEvent,
19
+ projectNode,
20
+ projectOutcome,
21
+ } from './events.js'
22
+ export type {
23
+ EventBus,
24
+ RunEvent,
25
+ RunEventSubscriber,
26
+ WireEvent,
27
+ TaskView,
28
+ OutcomeView,
29
+ } from './events.js'
30
+ export { createVxSurface } from './devframe-surface.js'
31
+ export { createWireRenderer } from './wire-render.js'
32
+ export { optionsToRequest, requestToOptions } from './protocol.js'
33
+ export type { ClientMessage, RunBackend, RunRequest, RunResult, ServerMessage } from './protocol.js'
34
+ export { formatRunReportMarkdown } from './run-report.js'
35
+ export {
36
+ clientMessageToEnvelope,
37
+ decodeEnvelope,
38
+ encodeForNDJSON,
39
+ encodeForSSE,
40
+ encodeForWS,
41
+ ENVELOPE_ERRORS,
42
+ envelopeToClientMessage,
43
+ envelopeToServerMessage,
44
+ isEnvelope,
45
+ isNotification,
46
+ isRequest,
47
+ makeError,
48
+ makeNotification,
49
+ makeRequest,
50
+ makeResponse,
51
+ serverMessageToEnvelope,
52
+ WIRE_CHANNELS,
53
+ WIRE_PROTOCOL_VERSION,
54
+ } from './wire.js'
55
+ export type {
56
+ Envelope,
57
+ ErrorResponse,
58
+ Notification,
59
+ Request as WireRequest,
60
+ Response as WireResponse,
61
+ WireChannel,
62
+ } from './wire.js'
63
+ export {
64
+ EmptyHistoryProvider,
65
+ type HistoryProvider,
66
+ type HistoryTable,
67
+ LocalHistoryProvider,
68
+ type TaskHistory,
69
+ } from './history.js'
70
+ export { computePredictedPriorities } from './predict.js'
71
+ export {
72
+ installPlugins,
73
+ type BackendContext,
74
+ type CacheContext,
75
+ type EventSink,
76
+ type EventSinkContext,
77
+ type InstallPluginsArgs,
78
+ type Plugin,
79
+ type PluginContext,
80
+ type PluginHookHandlers,
81
+ type PluginHookName,
82
+ type PluginSetupContext,
83
+ type VxPlugin,
84
+ } from './plugin.js'
85
+ export { resolveBackend, resolveCache, subscribeEventSinks } from './plugin-host.js'
86
+ export { subscribeTelemetry, type TelemetryHandle } from './telemetry-host.js'
87
+ export { createTelemetrySource, deriveCacheSource, TELEMETRY_SCHEMA_VERSION } from './telemetry.js'
88
+ export type {
89
+ CacheSource,
90
+ RunContextRecord,
91
+ RunSummaryRecord,
92
+ TaskTelemetry,
93
+ TelemetryContext,
94
+ TelemetryRecord,
95
+ TelemetrySink,
96
+ TelemetrySource,
97
+ } from './telemetry.js'
98
+ export { deriveStableKeys } from './stable-keys.js'
99
+ export type { DeriveStableKeysArgs, StableKey } from './stable-keys.js'
100
+ export { captureGitContext, captureWorkspaceIdentity, resolveCacheScope } from './run-context.js'
101
+ export type { GitContext, WorkspaceIdentity } from './run-context.js'
102
+ export {
103
+ cacheKeyDiff,
104
+ compareRuns,
105
+ explainCacheKey as explainCacheKeyQuery,
106
+ getBottlenecks,
107
+ getCacheBreakdown,
108
+ getCacheSavings,
109
+ getCacheStatsSql,
110
+ getFlakiestTasks,
111
+ getHistory,
112
+ getHitRateSplit,
113
+ getInvocation,
114
+ getParallelismHistory,
115
+ getPrunableEntries,
116
+ getRecentFailures,
117
+ getRun,
118
+ getRunHeatmap,
119
+ getRunTrends,
120
+ getStorageGrowth,
121
+ getTaskDetail,
122
+ getTopTimeBurners,
123
+ listCacheEntries,
124
+ listInvocations,
125
+ listProjects,
126
+ listRuns,
127
+ whyDidThisRerun as whyDidThisRerunQuery,
128
+ } from './metrics.js'
129
+ export type {
130
+ BottleneckRow,
131
+ CacheEntryRow,
132
+ CacheKeyDiff,
133
+ CacheKeyExplanation,
134
+ CacheProjectRow,
135
+ CacheSavings,
136
+ CacheStatsResult,
137
+ CompareRuns,
138
+ CompareTaskRow,
139
+ CompareTaskSide,
140
+ FailureRow,
141
+ FlakyTask,
142
+ GetHistoryArgs,
143
+ HeatmapCell,
144
+ HitRateSplit,
145
+ InputDiffEntry,
146
+ InvocationDetail,
147
+ InvocationRow,
148
+ ListCacheEntriesArgs,
149
+ ListInvocationsArgs,
150
+ ListRunsArgs,
151
+ ParallelismPoint,
152
+ PrunableEntry,
153
+ ProjectRollup,
154
+ RunDetail,
155
+ RunSummaryRow,
156
+ StoragePoint,
157
+ TaskDetail,
158
+ TaskHistoryRow,
159
+ TopTaskRow,
160
+ TrendBucket,
161
+ TrendPoint,
162
+ WhyDidThisRerun,
163
+ } from './metrics.js'
@@ -0,0 +1,147 @@
1
+ // Local cache short-circuit (default-on) — the classify phase. The
2
+ // owner's scheduling policy: "prioritize running cache MISSES; only if
3
+ // required, or if there are free workers, add cache restores." So a
4
+ // confirmed stable-key LOCAL cache HIT should not have to wait for its
5
+ // dependencies to finish RUNNING — its bytes are derivable now and its
6
+ // restore needs none of its deps' output — but it must NOT preempt a
7
+ // real cache MISS for a worker slot.
8
+ //
9
+ // This module owns the UP-FRONT CLASSIFY: for every STABLE-key,
10
+ // cacheable, local-read task it derives the key (reusing the run's
11
+ // hashCache memo) and probes `cache.get` ONCE, building a `preProbed`
12
+ // map that covers stable HITS and stable MISSES alike. The scheduler
13
+ // (two-tier) and execute-task (probe reuse) consume it:
14
+ //
15
+ // - hit → RESTORE-TIER: scheduler makes it ready immediately (LOW
16
+ // priority), execute reuses the probed entry → restoreHit
17
+ // (no second cache.get).
18
+ // - miss → EXEC-TIER (stable): scheduler runs it dep-gated at normal
19
+ // priority; execute skips the first cache.get (it's a known
20
+ // miss) and goes to the run path.
21
+ // - unstable / not-probed → EXEC-TIER: execute probes lazily, exactly
22
+ // as today (a codegen-consumer's key isn't computable until
23
+ // its upstream runs — see dependsOnSiblingOutputs).
24
+ //
25
+ // Because EVERY task still runs through execute(), the logger emits the
26
+ // same taskStart + stdout replay + taskComplete it always did — the
27
+ // focused live frame is preserved with zero special-casing — and the
28
+ // up-front probes are just the probes execute() would have done,
29
+ // hoisted (no double work — the warm path stays free).
30
+ //
31
+ // SCOPE / safety:
32
+ // - Only STABLE-key, cacheable, local-read tasks are classified. A
33
+ // stable miss stays in the normal (dep-gated) schedule; an unstable
34
+ // task is never probed here.
35
+ // - If ANY task in the graph declares `cache.outputs.workspaceFiles`,
36
+ // no task is restore-tiered (the boundary-ignoring escape hatch
37
+ // could let a task write where a restore touches — a blanket
38
+ // conservative exclusion). Those tasks still get an exec-tier probe
39
+ // reuse entry so there's no double work.
40
+
41
+ import type { CacheEntry, CacheLayer, GitFilesCache } from '../cache/index.js'
42
+ import type { TaskNode } from '../graph/index.js'
43
+ import { deriveStableKeys } from './stable-keys.js'
44
+ import type { HashCache } from './task-hash.js'
45
+
46
+ export interface ShortCircuitArgs {
47
+ nodes: Map<string, TaskNode>
48
+ cache: CacheLayer
49
+ workspaceRoot: string
50
+ workspaceFingerprint: string
51
+ forwardArgs?: readonly string[] | undefined
52
+ nestedDirsByProject: Map<string, string[]>
53
+ gitFilesCache: GitFilesCache
54
+ hashCache: HashCache
55
+ /** Cap on concurrent probes — the run's concurrency. */
56
+ concurrency: number
57
+ }
58
+
59
+ /** Per-task result of the up-front probe. `hit` null = a confirmed
60
+ * stable miss (skips the lazy probe in execute, goes to the run path).
61
+ * `hash` is the up-front-derived stable key (reused so a restore-tier
62
+ * task that runs before its deps doesn't recompute against an
63
+ * incomplete upstream). */
64
+ export interface ProbedEntry {
65
+ hash: string
66
+ hit: CacheEntry | null
67
+ }
68
+
69
+ export interface ShortCircuit {
70
+ /**
71
+ * Every stable, cacheable, local-read task → its up-front probe.
72
+ * Threaded into executeCachedTask so it reuses the probe (no second
73
+ * cache.get). Covers hits AND stable misses.
74
+ */
75
+ preProbed: Map<string, ProbedEntry>
76
+ /**
77
+ * Task ids that are confirmed stable LOCAL hits — the restore-tier.
78
+ * The scheduler makes these ready immediately (dep-independent) and
79
+ * LOW priority (backfill only). A subset of `preProbed` keys (those
80
+ * with a non-null hit, minus the workspace-outputs exclusion).
81
+ */
82
+ restoreTier: Set<string>
83
+ }
84
+
85
+ const EMPTY: ShortCircuit = { preProbed: new Map(), restoreTier: new Set() }
86
+
87
+ /**
88
+ * Classify the graph's stable tasks: derive keys + probe local ONCE,
89
+ * returning the `preProbed` map (probe reuse) and the `restoreTier` set
90
+ * (confirmed hits the scheduler may run ahead of their deps).
91
+ *
92
+ * Never throws — any error in derivation / probing degrades to "no
93
+ * short-circuit" (an empty result), so every task falls back to the
94
+ * normal lazy-probe schedule, identical to today.
95
+ */
96
+ export async function startLocalShortCircuit(args: ShortCircuitArgs): Promise<ShortCircuit> {
97
+ let stableKeys
98
+ try {
99
+ stableKeys = await deriveStableKeys(args)
100
+ } catch {
101
+ return EMPTY
102
+ }
103
+ const candidates = stableKeys.filter(({ node }) => node.config.cache !== undefined)
104
+ if (candidates.length === 0) return EMPTY
105
+
106
+ // Belt-and-suspenders for the boundary-ignoring escape hatch: a
107
+ // root-anchored output can land anywhere, so if ANY task declares
108
+ // workspace outputs a task could in principle write where a
109
+ // restore-tier task restores. Disable the RESTORE tier graph-wide —
110
+ // workspace outputs are rare bad-practice. (Probe reuse still applies,
111
+ // so there's no double work; those tasks just stay dep-gated.)
112
+ let anyWorkspaceOutputs = false
113
+ for (const node of args.nodes.values()) {
114
+ if ((node.config.cache?.outputs.workspaceFiles?.length ?? 0) > 0) {
115
+ anyWorkspaceOutputs = true
116
+ break
117
+ }
118
+ }
119
+
120
+ const preProbed = new Map<string, ProbedEntry>()
121
+ const restoreTier = new Set<string>()
122
+
123
+ // Bounded pool over the stable candidates: probe local ONCE each. A
124
+ // confirmed hit becomes restore-tier (unless workspace outputs disable
125
+ // it); a miss stays exec-tier with a known-miss reuse entry. The pool
126
+ // keeps the up-front pass from being a serial pre-phase on a wide warm
127
+ // graph — the probes parallelize at the run's concurrency.
128
+ let next = 0
129
+ const workers = Math.max(1, Math.min(args.concurrency, candidates.length))
130
+ const pump = async (): Promise<void> => {
131
+ while (next < candidates.length) {
132
+ const { hash, node } = candidates[next++]!
133
+ try {
134
+ const command = node.config.exec?.command ?? ''
135
+ const hit = await args.cache.get(hash, { taskId: node.id, command })
136
+ preProbed.set(node.id, { hash, hit })
137
+ if (hit !== null && !anyWorkspaceOutputs) restoreTier.add(node.id)
138
+ } catch {
139
+ // Leave this task out of preProbed → it probes lazily in
140
+ // execute(), exactly as today.
141
+ }
142
+ }
143
+ }
144
+ await Promise.all(Array.from({ length: workers }, () => pump()))
145
+
146
+ return { preProbed, restoreTier }
147
+ }