@visulima/task-runner 1.0.0-alpha.4 → 1.0.0-alpha.5

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
@@ -1,3 +1,20 @@
1
+ ## @visulima/task-runner [1.0.0-alpha.5](https://github.com/visulima/visulima/compare/@visulima/task-runner@1.0.0-alpha.4...@visulima/task-runner@1.0.0-alpha.5) (2026-04-15)
2
+
3
+ ### Features
4
+
5
+ * Add comprehensive workspace configuration and command infrastructure ([#609](https://github.com/visulima/visulima/issues/609)) ([f4347bf](https://github.com/visulima/visulima/commit/f4347bfdcdd1b228cd9d842a927e446aaf23f035))
6
+ * **vis:** add cache command for task runner cache ([#607](https://github.com/visulima/visulima/issues/607)) ([6752769](https://github.com/visulima/visulima/commit/67527692562b3dd9c03bb6a67c084ff1e694a560))
7
+
8
+ ### Bug Fixes
9
+
10
+ * **tooling:** resolve eslint and formatting issues ([399d292](https://github.com/visulima/visulima/commit/399d29282be5b29bb26b4e5b24d45e2a6cdeeca3))
11
+
12
+
13
+ ### Dependencies
14
+
15
+ * **@visulima/humanizer:** upgraded to 3.0.0-alpha.10
16
+ * **@visulima/path:** upgraded to 3.0.0-alpha.9
17
+
1
18
  ## @visulima/task-runner [1.0.0-alpha.4](https://github.com/visulima/visulima/compare/@visulima/task-runner@1.0.0-alpha.3...@visulima/task-runner@1.0.0-alpha.4) (2026-04-08)
2
19
 
3
20
  ### Features
package/dist/cache.d.ts CHANGED
@@ -25,6 +25,13 @@ interface CacheOptions {
25
25
  /** The workspace root directory */
26
26
  workspaceRoot: string;
27
27
  }
28
+ /**
29
+ * Directory name (relative to `workspaceRoot`) where the task runner writes
30
+ * its cache by default. Exported so callers that manage the cache from the
31
+ * outside — e.g. a CLI `cache clean` command — can reach the same default
32
+ * without hard-coding the literal.
33
+ */
34
+ declare const DEFAULT_CACHE_DIRECTORY_NAME = ".task-runner-cache";
28
35
  /**
29
36
  * Parses a human-readable cache size string into bytes.
30
37
  * Delegates to @visulima/humanizer's parseBytes with base-2 (1024) multipliers.
@@ -100,4 +107,4 @@ declare class Cache {
100
107
  clear(): Promise<void>;
101
108
  }
102
109
  export type { CachedResult, CacheOptions };
103
- export { Cache, formatCacheSize, parseCacheSize };
110
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize };
@@ -40,5 +40,5 @@ interface CommandStdin {
40
40
  * @param options Input handler configuration
41
41
  * @returns cleanup function to call when done
42
42
  */
43
- export declare const createInputHandler: (commands: CommandStdin[], options?: InputHandlerOptions) => () => void;
43
+ export declare const createInputHandler: (commands: CommandStdin[], options?: InputHandlerOptions) => (() => void);
44
44
  export {};
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type { AffectedOptions, AffectedResult } from "./affected.d.ts";
2
2
  export { buildForwardDependencyMap, buildReverseDependencyMap, expandAffected, filterAffectedTasks, getAffectedProjects, getChangedFiles } from "./affected.d.ts";
3
3
  export type { CachedResult, CacheOptions } from "./cache.d.ts";
4
- export { Cache, formatCacheSize, parseCacheSize } from "./cache.d.ts";
4
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize } from "./cache.d.ts";
5
5
  export type { ParseCommandsOptions } from "./command-parser/index.d.ts";
6
6
  export { expandArguments, expandShortcut, expandWildcard, parseCommands, stripQuotes } from "./command-parser/index.d.ts";
7
7
  export { runConcurrently } from "./concurrent.d.ts";
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- export { buildForwardDependencyMap, buildReverseDependencyMap, expandAffected, filterAffectedTasks, getAffectedProjects, getChangedFiles } from './packem_shared/buildForwardDependencyMap-Cu08NWB1.js';
2
- export { Cache, formatCacheSize, parseCacheSize } from './packem_shared/Cache-C23LywYn.js';
1
+ export { buildForwardDependencyMap, buildReverseDependencyMap, expandAffected, filterAffectedTasks, getAffectedProjects, getChangedFiles } from './packem_shared/buildForwardDependencyMap-0BJFMMPv.js';
2
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize } from './packem_shared/Cache-iAjRMV2d.js';
3
3
  export { parseCommands } from './packem_shared/parseCommands-D-IgF8Zh.js';
4
- export { runConcurrently } from './packem_shared/runConcurrently-ATDwJNR6.js';
5
- export { runConcurrentFallback } from './packem_shared/runConcurrentFallback-3q46z4AS.js';
6
- export { defaultTaskRunner } from './packem_shared/defaultTaskRunner-X1MIynHu.js';
4
+ export { runConcurrently } from './packem_shared/runConcurrently-qrkWyzXW.js';
5
+ export { runConcurrentFallback } from './packem_shared/runConcurrentFallback-CGHz_f-Q.js';
6
+ export { defaultTaskRunner } from './packem_shared/defaultTaskRunner-BdFTifsh.js';
7
7
  export { detectScriptShell } from './packem_shared/detectScriptShell-CR-xXKA4.js';
8
8
  export { FileAccessTracker, generatePreloadScript } from './packem_shared/FileAccessTracker-CrtBAt5D.js';
9
9
  export { FingerprintManager } from './packem_shared/FingerprintManager-Cu-ta9ee.js';
@@ -13,7 +13,7 @@ export { IncrementalFileHasher } from './packem_shared/IncrementalFileHasher-Cm_
13
13
  export { CompositeLifeCycle, ConsoleLifeCycle, EmptyLifeCycle } from './packem_shared/CompositeLifeCycle-7AtYw1dv.js';
14
14
  export { LockfileHasher, extractPackageName, parseNpmLockfile, parsePnpmLockfile, parseYarnLockfile } from './packem_shared/extractPackageName-CbVNW-dr.js';
15
15
  export { isNativeAvailable, loadNativeBindings } from './packem_shared/isNativeAvailable-BpD28A6Z.js';
16
- export { enforceProjectConstraints } from './packem_shared/enforceProjectConstraints-_Ej0zHch.js';
16
+ export { enforceProjectConstraints } from './packem_shared/enforceProjectConstraints-C5Jp_C3u.js';
17
17
  export { RemoteCache } from './packem_shared/RemoteCache-BFceSe4a.js';
18
18
  export { generateRunSummary, writeRunSummary } from './packem_shared/generateRunSummary-qn-_jKwt.js';
19
19
  export { createTaskGraph, getTaskId, parseTaskId } from './packem_shared/createTaskGraph-CcsFaSrz.js';
@@ -21,7 +21,7 @@ export { findCycle, findCycles, getDependentTasks, getLeafTasks, getTransitiveDe
21
21
  export { InProcessTaskHasher, computeTaskHash } from './packem_shared/computeTaskHash-B2SVZqgp.js';
22
22
  export { TaskOrchestrator } from './packem_shared/TaskOrchestrator-lLn-PH1m.js';
23
23
  export { TaskScheduler, parsePartition } from './packem_shared/parsePartition-C4-P5RjK.js';
24
- export { TerminalBuffer } from './packem_shared/TerminalBuffer-D6zP2zLh.js';
24
+ export { TerminalBuffer } from './packem_shared/TerminalBuffer-CnPyFgPB.js';
25
25
  export { TrackedTaskExecutor } from './packem_shared/TrackedTaskExecutor-BGUKFE-7.js';
26
26
  export { c as collectFiles, a as createFailureResult, h as hashFile, b as hashStrings, r as readPackageDeps, d as resolveTaskCwd, s as sortObjectKeys, u as uniqueId } from './packem_shared/utils-zO0ZRgtf.js';
27
27
  export { createInputHandler } from './packem_shared/createInputHandler-DTfePcTG.js';
@@ -32,6 +32,7 @@ import { join, resolve, dirname } from '@visulima/path';
32
32
  import { u as uniqueId } from './utils-zO0ZRgtf.js';
33
33
 
34
34
  const DEFAULT_MAX_CACHE_AGE = 7 * 24 * 60 * 60 * 1e3;
35
+ const DEFAULT_CACHE_DIRECTORY_NAME = ".task-runner-cache";
35
36
  const removeEntry = async (entryPath) => {
36
37
  try {
37
38
  await rm(entryPath, { force: true, recursive: true });
@@ -72,7 +73,7 @@ class Cache {
72
73
  #indexWriteQueue = Promise.resolve();
73
74
  constructor(options) {
74
75
  this.#workspaceRoot = options.workspaceRoot;
75
- this.#cacheDirectory = options.cacheDirectory ?? join(options.workspaceRoot, ".task-runner-cache");
76
+ this.#cacheDirectory = options.cacheDirectory ?? join(options.workspaceRoot, DEFAULT_CACHE_DIRECTORY_NAME);
76
77
  this.#maxCacheAge = options.maxCacheAge ?? DEFAULT_MAX_CACHE_AGE;
77
78
  this.#maxCacheSize = options.maxCacheSize ? parseCacheSize(options.maxCacheSize) : void 0;
78
79
  }
@@ -294,4 +295,4 @@ class Cache {
294
295
  }
295
296
  }
296
297
 
297
- export { Cache, formatCacheSize, parseCacheSize };
298
+ export { Cache, DEFAULT_CACHE_DIRECTORY_NAME, formatCacheSize, parseCacheSize };
@@ -23,11 +23,7 @@ class TerminalBuffer {
23
23
  i = consumed;
24
24
  continue;
25
25
  }
26
- if (data[i + 1] === "(" || data[i + 1] === ")") {
27
- i += 3;
28
- } else {
29
- i += 2;
30
- }
26
+ i += data[i + 1] === "(" || data[i + 1] === ")" ? 3 : 2;
31
27
  continue;
32
28
  }
33
29
  if (ch === "\r") {
@@ -70,36 +66,42 @@ class TerminalBuffer {
70
66
  const cmd = data[j];
71
67
  const n = Number.parseInt(params, 10) || 1;
72
68
  switch (cmd) {
73
- case "A":
69
+ case "A": {
74
70
  this.#row = Math.max(0, this.#row - n);
75
71
  break;
76
- case "B":
72
+ }
73
+ case "B": {
77
74
  this.#row = Math.min(this.#lines.length - 1, this.#row + n);
78
75
  break;
79
- case "C":
76
+ }
77
+ case "C": {
80
78
  this.#col += n;
81
79
  break;
82
- case "D":
80
+ }
81
+ case "D": {
83
82
  this.#col = Math.max(0, this.#col - n);
84
83
  break;
85
- case "G":
86
- this.#col = Math.max(0, n - 1);
87
- break;
88
- case "H":
89
- // cursor position (row;col, 1-based)
90
- case "f": {
84
+ }
85
+ case "f":
86
+ case "H": {
91
87
  const parts = params.split(";");
92
88
  this.#row = Math.max(0, (Number.parseInt(parts[0] ?? "1", 10) || 1) - 1);
93
89
  this.#col = Math.max(0, (Number.parseInt(parts[1] ?? "1", 10) || 1) - 1);
94
90
  this.#ensureRow(this.#row);
95
91
  break;
96
92
  }
97
- case "J":
93
+ case "G": {
94
+ this.#col = Math.max(0, n - 1);
95
+ break;
96
+ }
97
+ case "J": {
98
98
  this.#eraseDisplay(Number.parseInt(params, 10) || 0);
99
99
  break;
100
- case "K":
100
+ }
101
+ case "K": {
101
102
  this.#eraseLine(Number.parseInt(params, 10) || 0);
102
103
  break;
104
+ }
103
105
  case "m": {
104
106
  const seq = `\x1B[${params}m`;
105
107
  this.#ensureRow(this.#row);
@@ -161,30 +163,44 @@ class TerminalBuffer {
161
163
  this.#lines[this.#row] = line.slice(0, strIndex) + seq + line.slice(strIndex);
162
164
  }
163
165
  #eraseDisplay(mode) {
164
- if (mode === 2) {
165
- this.#lines = [""];
166
- this.#row = 0;
167
- this.#col = 0;
168
- } else if (mode === 0) {
169
- this.#ensureRow(this.#row);
170
- this.#truncateLineAtCol(this.#row, this.#col);
171
- this.#lines.length = this.#row + 1;
172
- } else if (mode === 1) {
173
- for (let r = 0; r < this.#row; r++) {
174
- this.#lines[r] = "";
166
+ switch (mode) {
167
+ case 0: {
168
+ this.#ensureRow(this.#row);
169
+ this.#truncateLineAtCol(this.#row, this.#col);
170
+ this.#lines.length = this.#row + 1;
171
+ break;
172
+ }
173
+ case 1: {
174
+ for (let r = 0; r < this.#row; r++) {
175
+ this.#lines[r] = "";
176
+ }
177
+ this.#ensureRow(this.#row);
178
+ this.#fillLineToCol(this.#row, this.#col);
179
+ break;
180
+ }
181
+ case 2: {
182
+ this.#lines = [""];
183
+ this.#row = 0;
184
+ this.#col = 0;
185
+ break;
175
186
  }
176
- this.#ensureRow(this.#row);
177
- this.#fillLineToCol(this.#row, this.#col);
178
187
  }
179
188
  }
180
189
  #eraseLine(mode) {
181
190
  this.#ensureRow(this.#row);
182
- if (mode === 2) {
183
- this.#lines[this.#row] = "";
184
- } else if (mode === 0) {
185
- this.#truncateLineAtCol(this.#row, this.#col);
186
- } else if (mode === 1) {
187
- this.#fillLineToCol(this.#row, this.#col);
191
+ switch (mode) {
192
+ case 0: {
193
+ this.#truncateLineAtCol(this.#row, this.#col);
194
+ break;
195
+ }
196
+ case 1: {
197
+ this.#fillLineToCol(this.#row, this.#col);
198
+ break;
199
+ }
200
+ case 2: {
201
+ this.#lines[this.#row] = "";
202
+ break;
203
+ }
188
204
  }
189
205
  }
190
206
  /** Truncate a line at the given visual column. */
@@ -22,8 +22,10 @@ const {
22
22
  } = __cjs_getBuiltinModule("node:child_process");
23
23
 
24
24
  const validateGitRef = (ref) => {
25
- if (!/^[\w.\-/~^@{}]+$/.test(ref)) {
26
- throw new Error(`Invalid git ref: "${ref}". Only alphanumeric characters, dots, dashes, underscores, slashes, tildes, carets, and @ are allowed.`);
25
+ if (!/^[\w./~^@{}][\w.\-/~^@{}]*$/.test(ref)) {
26
+ throw new Error(
27
+ `Invalid git ref: "${ref}". Refs must start with an alphanumeric character or one of _ . / ~ ^ @ { } and may only contain letters, digits, dots, dashes, underscores, slashes, tildes, carets, @, and braces.`
28
+ );
27
29
  }
28
30
  };
29
31
  const findProjectForFile = (filePath, projects) => {
@@ -1,4 +1,4 @@
1
- import { Cache } from './Cache-C23LywYn.js';
1
+ import { Cache } from './Cache-iAjRMV2d.js';
2
2
  import { inferFrameworkEnvPatterns } from './detectFrameworks-CeFzKE6J.js';
3
3
  import { RemoteCache } from './RemoteCache-BFceSe4a.js';
4
4
  import { InProcessTaskHasher } from './computeTaskHash-B2SVZqgp.js';
@@ -1,10 +1,19 @@
1
+ const LAYER_ORDER = ["configuration", "library", "scaffolding", "tool", "automation", "application"];
2
+ const layerIndex = (layer) => {
3
+ if (!layer) {
4
+ return void 0;
5
+ }
6
+ const idx = LAYER_ORDER.indexOf(layer);
7
+ return idx === -1 ? void 0 : idx;
8
+ };
1
9
  const enforceProjectConstraints = (projectGraph, constraints) => {
2
10
  const violations = [];
3
- const { dependencyKindRules, tagRelationships, typeBoundaries } = constraints;
11
+ const { dependencyKindRules, enforceLayerRelationships, tagRelationships, typeBoundaries } = constraints;
4
12
  const hasTagRules = tagRelationships && Object.keys(tagRelationships).length > 0;
5
13
  const hasTypeBoundaries = typeBoundaries !== void 0;
6
14
  const hasKindRules = dependencyKindRules !== void 0;
7
- if (!hasTagRules && !hasTypeBoundaries && !hasKindRules) {
15
+ const hasLayerRules = enforceLayerRelationships === true;
16
+ if (!hasTagRules && !hasTypeBoundaries && !hasKindRules && !hasLayerRules) {
8
17
  return violations;
9
18
  }
10
19
  const enforceAppBoundary = typeBoundaries?.enforceApplicationBoundary !== false;
@@ -82,6 +91,18 @@ const enforceProjectConstraints = (projectGraph, constraints) => {
82
91
  }
83
92
  }
84
93
  }
94
+ if (hasLayerRules) {
95
+ const sourceLayer = layerIndex(sourceNode.data.layer);
96
+ const depLayer = layerIndex(depNode.data.layer);
97
+ if (sourceLayer !== void 0 && depLayer !== void 0 && depLayer > sourceLayer) {
98
+ violations.push({
99
+ dependencyProject: dep.target,
100
+ message: `Project "${projectName}" (layer: ${sourceNode.data.layer}) depends on "${dep.target}" (layer: ${depNode.data.layer}). A "${sourceNode.data.layer}" project may only depend on projects at the same or lower layer. Hierarchy: ${LAYER_ORDER.join(" < ")}.`,
101
+ rule: "layer-relationship",
102
+ sourceProject: projectName
103
+ });
104
+ }
105
+ }
85
106
  }
86
107
  }
87
108
  return violations;
@@ -104,7 +104,9 @@ const spawnCommand = (index, config, shellPath, onEvent, onComplete) => {
104
104
  }
105
105
  onEvent({
106
106
  index,
107
- kill: child.pid ? (signal) => killTree(child.pid, signal ?? "SIGTERM") : void 0,
107
+ kill: child.pid ? (signal) => {
108
+ killTree(child.pid, signal ?? "SIGTERM");
109
+ } : void 0,
108
110
  kind: "started",
109
111
  write: child.stdin ? (data) => child.stdin.write(data) : void 0
110
112
  });
@@ -223,17 +225,25 @@ const spawnCommandPty = (index, config, shellPath, onEvent, onComplete) => {
223
225
  cols: config.ptySize?.cols ?? 80,
224
226
  cwd: config.cwd ?? process.cwd(),
225
227
  env: Object.fromEntries(
226
- Object.entries({ ...process.env, ...config.env, FORCE_COLOR: process.env["FORCE_COLOR"] ?? "1", TERM: "xterm-256color" }).filter((entry) => entry[1] !== void 0)
228
+ Object.entries({ ...process.env, ...config.env, FORCE_COLOR: process.env["FORCE_COLOR"] ?? "1", TERM: "xterm-256color" }).filter(
229
+ (entry) => entry[1] !== void 0
230
+ )
227
231
  ),
228
232
  name: "xterm-256color",
229
233
  rows: config.ptySize?.rows ?? 24
230
234
  });
231
235
  onEvent({
232
236
  index,
233
- kill: (signal) => ptyInstance.kill(signal),
237
+ kill: (signal) => {
238
+ ptyInstance.kill(signal);
239
+ },
234
240
  kind: "started",
235
- resize: (cols, rows) => ptyInstance.resize(cols, rows),
236
- write: (data) => ptyInstance.write(data)
241
+ resize: (cols, rows) => {
242
+ ptyInstance.resize(cols, rows);
243
+ },
244
+ write: (data) => {
245
+ ptyInstance.write(data);
246
+ }
237
247
  });
238
248
  ptyInstance.onData((data) => {
239
249
  onEvent({ index, kind: "stdout", text: data });
@@ -326,7 +336,11 @@ const runConcurrentFallback = (commands, options) => new Promise((resolve) => {
326
336
  while (active.length < maxProcesses && pending.length > 0) {
327
337
  const cmdIndex = pending.shift();
328
338
  const config = commands[cmdIndex];
329
- const proc = config.stdin === "pty" ? spawnCommandPty(cmdIndex, config, options.shellPath, onEvent, (ce) => handleClose(cmdIndex, ce)) : spawnCommand(cmdIndex, config, options.shellPath, onEvent, (ce) => handleClose(cmdIndex, ce));
339
+ const proc = config.stdin === "pty" ? spawnCommandPty(cmdIndex, config, options.shellPath, onEvent, (ce) => {
340
+ handleClose(cmdIndex, ce);
341
+ }) : spawnCommand(cmdIndex, config, options.shellPath, onEvent, (ce) => {
342
+ handleClose(cmdIndex, ce);
343
+ });
330
344
  active.push(proc);
331
345
  }
332
346
  };
@@ -1,4 +1,4 @@
1
- import { runConcurrentFallback } from './runConcurrentFallback-3q46z4AS.js';
1
+ import { runConcurrentFallback } from './runConcurrentFallback-CGHz_f-Q.js';
2
2
  import { detectScriptShell } from './detectScriptShell-CR-xXKA4.js';
3
3
  import { logTimings } from './formatTimingTable-3qtCM552.js';
4
4
  import { withRestart } from './withRestart-BREjRJa4.js';
@@ -1,16 +1,9 @@
1
1
  import type { ConstraintsConfig, ConstraintViolation, ProjectGraph } from "./types.d.ts";
2
2
  /**
3
3
  * Enforces project dependency constraints on a project graph.
4
- * Returns an array of violations found. Does not throw — the caller
5
- * decides how to handle violations (fatal error, warning, etc.).
6
- *
7
- * Three constraint mechanisms:
8
- * 1. **Tag relationships**: If a project has a tag listed in `tagRelationships`,
9
- * its dependencies must have at least one of the required tags.
10
- * 2. **Type boundaries**: Controls which project types can depend on which.
11
- * By default, no project may depend on an "application" type project.
12
- * 3. **Dependency kind rules**: Controls rules based on whether the dependency
13
- * is a production dependency, devDependency, or peerDependency.
4
+ * @param projectGraph The workspace project graph to validate.
5
+ * @param constraints The constraint rules to enforce.
6
+ * @returns Array of violations found. Empty means all constraints pass.
14
7
  */
15
8
  declare const enforceProjectConstraints: (projectGraph: ProjectGraph, constraints: ConstraintsConfig) => ConstraintViolation[];
16
9
  export { enforceProjectConstraints };
package/dist/types.d.ts CHANGED
@@ -85,6 +85,15 @@ export type TaskResults = Map<string, TaskResult>;
85
85
  export interface ProjectConfiguration {
86
86
  /** Implicit dependencies on other projects */
87
87
  implicitDependencies?: string[];
88
+ /**
89
+ * Project layer in the dependency hierarchy. Used by
90
+ * `enforceLayerRelationships` to ensure projects only depend on
91
+ * projects at the same or lower layer.
92
+ *
93
+ * Hierarchy (lowest → highest):
94
+ * `configuration < library < scaffolding < tool < automation < application`
95
+ */
96
+ layer?: "application" | "automation" | "configuration" | "library" | "scaffolding" | "tool";
88
97
  /** The project type */
89
98
  projectType?: "library" | "application";
90
99
  /** The root directory of the project, relative to workspace root */
@@ -210,6 +219,16 @@ export interface DependencyKindRules {
210
219
  export interface ConstraintsConfig {
211
220
  /** Rules based on the dependency kind (static vs devDependency vs peerDependency) */
212
221
  dependencyKindRules?: DependencyKindRules;
222
+ /**
223
+ * When true, projects can only depend on projects at the same or
224
+ * lower layer in the hierarchy:
225
+ *
226
+ * configuration < library < scaffolding < tool < automation < application
227
+ *
228
+ * Projects without an explicit `layer` are unconstrained.
229
+ * @default false
230
+ */
231
+ enforceLayerRelationships?: boolean;
213
232
  /** Tag-based dependency rules */
214
233
  tagRelationships?: TagRelationships;
215
234
  /** Project-type-based dependency rules */
@@ -224,7 +243,7 @@ export interface ConstraintViolation {
224
243
  /** Human-readable description of the violation */
225
244
  message: string;
226
245
  /** The type of rule that was violated */
227
- rule: "dependency-kind" | "tag-relationship" | "type-boundary";
246
+ rule: "dependency-kind" | "layer-relationship" | "tag-relationship" | "type-boundary";
228
247
  /** The project that has the invalid dependency */
229
248
  sourceProject: string;
230
249
  }
@@ -462,12 +481,12 @@ export type ConcurrentCommandInput = string | {
462
481
  cwd?: string;
463
482
  env?: Record<string, string>;
464
483
  name?: string;
465
- stdin?: "inherit" | "null" | "pipe" | "pty";
466
484
  /** Initial PTY dimensions (only used when stdin is "pty"). */
467
485
  ptySize?: {
468
486
  cols: number;
469
487
  rows: number;
470
488
  };
489
+ stdin?: "inherit" | "null" | "pipe" | "pty";
471
490
  };
472
491
  /**
473
492
  * Configuration for a single command to run concurrently.
@@ -481,6 +500,14 @@ export interface ConcurrentCommandConfig {
481
500
  env?: Record<string, string>;
482
501
  /** Human-readable name for this command (used in prefixes/logs). */
483
502
  name?: string;
503
+ /**
504
+ * Initial PTY dimensions. Only used when stdin is "pty".
505
+ * Defaults to 80x24 if not specified.
506
+ */
507
+ ptySize?: {
508
+ cols: number;
509
+ rows: number;
510
+ };
484
511
  /** Whether to use shell execution (default: true). */
485
512
  shell?: boolean;
486
513
  /**
@@ -491,14 +518,6 @@ export interface ConcurrentCommandConfig {
491
518
  * - "pty": child runs inside a pseudo-terminal (isatty() returns true, enables interactive prompts)
492
519
  */
493
520
  stdin?: "inherit" | "null" | "pipe" | "pty";
494
- /**
495
- * Initial PTY dimensions. Only used when stdin is "pty".
496
- * Defaults to 80x24 if not specified.
497
- */
498
- ptySize?: {
499
- cols: number;
500
- rows: number;
501
- };
502
521
  }
503
522
  /**
504
523
  * Options controlling the concurrent runner behavior.
@@ -548,10 +567,10 @@ export interface ProcessEvent {
548
567
  exitCode?: number;
549
568
  /** Index of the command that produced this event. */
550
569
  index: number;
551
- /** Whether the process was killed (for close events). */
552
- killed?: boolean;
553
570
  /** Kill the child process/PTY. Only present on "started" events. */
554
571
  kill?: (signal?: string) => void;
572
+ /** Whether the process was killed (for close events). */
573
+ killed?: boolean;
555
574
  /** Event type: "stdout", "stderr", "close", "error", "started". */
556
575
  kind: "close" | "error" | "started" | "stderr" | "stdout";
557
576
  /** Error message (for error events). */