@vzn/vx 0.0.24 → 0.0.25
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "An open, extensible monorepo task runner.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
20
|
+
"@vzn/vx-linux-x64": "0.0.25",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.25",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.25",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.25"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/graph/task-graph.ts
CHANGED
|
@@ -30,6 +30,13 @@ export interface TaskNode {
|
|
|
30
30
|
config: TaskConfig
|
|
31
31
|
/** Ids of tasks that must complete before this one runs. */
|
|
32
32
|
deps: string[]
|
|
33
|
+
/**
|
|
34
|
+
* The members of `deps` that order the run and fold into no key:
|
|
35
|
+
* `--exclude-dependencies` dropped a task between this one and them
|
|
36
|
+
* (`excludeDependencies`). The dropped task's derived key already folds
|
|
37
|
+
* theirs, so folding them again would give a key no full run derives.
|
|
38
|
+
*/
|
|
39
|
+
orderOnly?: string[]
|
|
33
40
|
/**
|
|
34
41
|
* True for the tasks the user actually asked for (via cwd, `--all`,
|
|
35
42
|
* `--filter`, or `pkg#task`). False for deps pulled in by `dependsOn`
|
|
@@ -588,6 +595,27 @@ export function excludeDependencies(
|
|
|
588
595
|
if (lost.length === 0) continue
|
|
589
596
|
dropped.set(id, lost)
|
|
590
597
|
node.deps = node.deps.filter(stays)
|
|
598
|
+
// A scheduled task reached through a dropped one still runs first: in
|
|
599
|
+
// `test → gen → build` with `gen` excluded and `build` requested, the
|
|
600
|
+
// edge to `gen` went and nothing ordered `test` after `build`, so the
|
|
601
|
+
// two ran at once (item 1019). The walk reads unscheduled nodes only,
|
|
602
|
+
// whose deps this loop leaves as they are.
|
|
603
|
+
const order = new Set<string>()
|
|
604
|
+
const seen = new Set<string>()
|
|
605
|
+
const stack = [...lost]
|
|
606
|
+
while (stack.length > 0) {
|
|
607
|
+
const dep = stack.pop()!
|
|
608
|
+
if (seen.has(dep)) continue
|
|
609
|
+
seen.add(dep)
|
|
610
|
+
if (scheduled.has(dep)) {
|
|
611
|
+
if (!node.deps.includes(dep)) order.add(dep)
|
|
612
|
+
continue
|
|
613
|
+
}
|
|
614
|
+
stack.push(...nodes.get(dep)!.deps)
|
|
615
|
+
}
|
|
616
|
+
if (order.size === 0) continue
|
|
617
|
+
node.orderOnly = [...order].sort()
|
|
618
|
+
node.deps = [...node.deps, ...node.orderOnly].sort()
|
|
591
619
|
}
|
|
592
620
|
for (const id of keyOnly.keys()) nodes.delete(id)
|
|
593
621
|
return { keyOnly, dropped }
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import type { CacheLayer, GitFilesCache } from '../cache/index.js'
|
|
17
17
|
import { isGroupTask, type TaskNode, type TaskOutcome } from '../graph/index.js'
|
|
18
18
|
import { computeGroupHash, computeTaskHash, type HashCache } from './task-hash.js'
|
|
19
|
-
import { filterUpstreamHashes } from './upstream.js'
|
|
19
|
+
import { filterUpstreamHashes, keyedDeps } from './upstream.js'
|
|
20
20
|
|
|
21
21
|
export interface KeyExcludedArgs {
|
|
22
22
|
/** The scheduled graph, after `excludeDependencies`. */
|
|
@@ -41,7 +41,7 @@ export interface KeyExcludedArgs {
|
|
|
41
41
|
export async function keyExcludedDependencies(args: KeyExcludedArgs): Promise<void> {
|
|
42
42
|
const nodeOf = (id: string): TaskNode => args.nodes.get(id) ?? args.keyOnly.get(id)!
|
|
43
43
|
const fullDeps = (node: TaskNode): readonly string[] => [
|
|
44
|
-
...node
|
|
44
|
+
...keyedDeps(node),
|
|
45
45
|
...(args.dropped.get(node.id) ?? []),
|
|
46
46
|
]
|
|
47
47
|
// Each key's promise is made after its dependencies' promises, in a
|
|
@@ -17,7 +17,15 @@ import { UserError } from '../util/index.js'
|
|
|
17
17
|
* a key at one of them and not the others.
|
|
18
18
|
*/
|
|
19
19
|
export function keyUpstream(node: TaskNode, upstream: TaskOutcome[]): TaskOutcome[] {
|
|
20
|
-
|
|
20
|
+
const order = node.orderOnly
|
|
21
|
+
const keyed = order === undefined ? upstream : upstream.filter((o) => !order.includes(o.node.id))
|
|
22
|
+
return node.excludedUpstream === undefined ? keyed : [...keyed, ...node.excludedUpstream]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** `node.deps` less its ordering-only edges: the dependencies a key may fold. */
|
|
26
|
+
export function keyedDeps(node: TaskNode): readonly string[] {
|
|
27
|
+
const order = node.orderOnly
|
|
28
|
+
return order === undefined ? node.deps : node.deps.filter((d) => !order.includes(d))
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
/**
|