@calmo/task-runner 3.8.3 → 4.0.4

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 (94) hide show
  1. package/.agent/workflows/openspec-apply.md +20 -0
  2. package/.agent/workflows/openspec-archive.md +24 -0
  3. package/.agent/workflows/openspec-proposal.md +25 -0
  4. package/.github/workflows/release-please.yml +46 -0
  5. package/.husky/commit-msg +0 -0
  6. package/.husky/pre-commit +0 -0
  7. package/.release-please-manifest.json +3 -0
  8. package/AGENTS.md +2 -4
  9. package/CHANGELOG.md +109 -0
  10. package/README.md +1 -1
  11. package/dist/TaskGraphValidator.js +2 -4
  12. package/dist/TaskGraphValidator.js.map +1 -1
  13. package/openspec/changes/adopt-release-pr/design.md +40 -0
  14. package/openspec/changes/adopt-release-pr/proposal.md +47 -0
  15. package/openspec/changes/adopt-release-pr/specs/release-pr/spec.md +34 -0
  16. package/openspec/changes/adopt-release-pr/tasks.md +14 -0
  17. package/openspec/changes/archive/2026-01-18-add-concurrency-control/specs/task-runner/spec.md +26 -0
  18. package/openspec/changes/archive/2026-01-18-add-external-task-cancellation/specs/task-runner/spec.md +63 -0
  19. package/openspec/changes/archive/2026-01-18-add-integration-tests/specs/task-runner/spec.md +22 -0
  20. package/openspec/changes/archive/2026-01-18-add-task-retry-policy/specs/task-runner/spec.md +40 -0
  21. package/openspec/changes/archive/2026-01-18-add-workflow-preview/specs/task-runner/spec.md +25 -0
  22. package/openspec/changes/archive/2026-01-18-refactor-core-architecture/specs/task-runner/spec.md +31 -0
  23. package/openspec/changes/feat-continue-on-error/proposal.md +20 -0
  24. package/openspec/changes/feat-continue-on-error/tasks.md +17 -0
  25. package/openspec/changes/feat-per-task-timeout/specs/task-runner/spec.md +34 -0
  26. package/openspec/changes/feat-task-metrics/specs/001-generic-task-runner/spec.md +13 -0
  27. package/openspec/specs/task-runner/spec.md +162 -0
  28. package/package.json +11 -20
  29. package/release-please-config.json +9 -0
  30. package/src/TaskGraphValidator.ts +2 -4
  31. package/.gemini/commands/speckit.analyze.toml +0 -188
  32. package/.gemini/commands/speckit.checklist.toml +0 -298
  33. package/.gemini/commands/speckit.clarify.toml +0 -185
  34. package/.gemini/commands/speckit.constitution.toml +0 -86
  35. package/.gemini/commands/speckit.implement.toml +0 -139
  36. package/.gemini/commands/speckit.plan.toml +0 -93
  37. package/.gemini/commands/speckit.specify.toml +0 -262
  38. package/.gemini/commands/speckit.tasks.toml +0 -141
  39. package/.gemini/commands/speckit.taskstoissues.toml +0 -34
  40. package/.github/workflows/release.yml +0 -46
  41. package/.releaserc.json +0 -27
  42. package/coverage/base.css +0 -224
  43. package/coverage/block-navigation.js +0 -87
  44. package/coverage/coverage-final.json +0 -15
  45. package/coverage/favicon.png +0 -0
  46. package/coverage/index.html +0 -146
  47. package/coverage/lcov-report/base.css +0 -224
  48. package/coverage/lcov-report/block-navigation.js +0 -87
  49. package/coverage/lcov-report/favicon.png +0 -0
  50. package/coverage/lcov-report/index.html +0 -146
  51. package/coverage/lcov-report/prettify.css +0 -1
  52. package/coverage/lcov-report/prettify.js +0 -2
  53. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  54. package/coverage/lcov-report/sorter.js +0 -210
  55. package/coverage/lcov-report/src/EventBus.ts.html +0 -379
  56. package/coverage/lcov-report/src/ExecutionConstants.ts.html +0 -121
  57. package/coverage/lcov-report/src/TaskGraphValidationError.ts.html +0 -130
  58. package/coverage/lcov-report/src/TaskGraphValidator.ts.html +0 -649
  59. package/coverage/lcov-report/src/TaskRunner.ts.html +0 -706
  60. package/coverage/lcov-report/src/TaskRunnerBuilder.ts.html +0 -337
  61. package/coverage/lcov-report/src/TaskRunnerExecutionConfig.ts.html +0 -154
  62. package/coverage/lcov-report/src/TaskStateManager.ts.html +0 -529
  63. package/coverage/lcov-report/src/WorkflowExecutor.ts.html +0 -712
  64. package/coverage/lcov-report/src/contracts/ErrorTypes.ts.html +0 -103
  65. package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +0 -217
  66. package/coverage/lcov-report/src/contracts/index.html +0 -131
  67. package/coverage/lcov-report/src/index.html +0 -236
  68. package/coverage/lcov-report/src/strategies/DryRunExecutionStrategy.ts.html +0 -178
  69. package/coverage/lcov-report/src/strategies/RetryingExecutionStrategy.ts.html +0 -373
  70. package/coverage/lcov-report/src/strategies/StandardExecutionStrategy.ts.html +0 -190
  71. package/coverage/lcov-report/src/strategies/index.html +0 -146
  72. package/coverage/lcov.info +0 -671
  73. package/coverage/prettify.css +0 -1
  74. package/coverage/prettify.js +0 -2
  75. package/coverage/sort-arrow-sprite.png +0 -0
  76. package/coverage/sorter.js +0 -210
  77. package/coverage/src/EventBus.ts.html +0 -379
  78. package/coverage/src/ExecutionConstants.ts.html +0 -121
  79. package/coverage/src/TaskGraphValidationError.ts.html +0 -130
  80. package/coverage/src/TaskGraphValidator.ts.html +0 -649
  81. package/coverage/src/TaskRunner.ts.html +0 -706
  82. package/coverage/src/TaskRunnerBuilder.ts.html +0 -337
  83. package/coverage/src/TaskRunnerExecutionConfig.ts.html +0 -154
  84. package/coverage/src/TaskStateManager.ts.html +0 -529
  85. package/coverage/src/WorkflowExecutor.ts.html +0 -712
  86. package/coverage/src/contracts/ErrorTypes.ts.html +0 -103
  87. package/coverage/src/contracts/RunnerEvents.ts.html +0 -217
  88. package/coverage/src/contracts/index.html +0 -131
  89. package/coverage/src/index.html +0 -236
  90. package/coverage/src/strategies/DryRunExecutionStrategy.ts.html +0 -178
  91. package/coverage/src/strategies/RetryingExecutionStrategy.ts.html +0 -373
  92. package/coverage/src/strategies/StandardExecutionStrategy.ts.html +0 -190
  93. package/coverage/src/strategies/index.html +0 -146
  94. package/test-report.xml +0 -299
@@ -0,0 +1,25 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Dry Run Execution Strategy
4
+
5
+ The system SHALL provide a `DryRunExecutionStrategy` that implements `IExecutionStrategy`.
6
+
7
+ #### Scenario: Simulating execution
8
+
9
+ - **WHEN** `WorkflowExecutor` is configured with `DryRunExecutionStrategy`
10
+ - **AND** `execute` is called
11
+ - **THEN** it SHALL traverse the dependency graph respecting order
12
+ - **AND** it SHALL NOT execute the actual work of the `TaskStep`.
13
+ - **AND** it SHALL return `TaskResult`s with a status indicating successful simulation (e.g., `simulated` or `success`).
14
+
15
+ ### Requirement: Mermaid Visualization
16
+
17
+ The system SHALL provide a utility to generate a Mermaid.js graph from task steps.
18
+
19
+ #### Scenario: Generate Mermaid Graph
20
+
21
+ - **GIVEN** a list of `TaskStep`s with dependencies
22
+ - **WHEN** `generateMermaidGraph` is called
23
+ - **THEN** it SHALL return a valid Mermaid flowchart syntax string.
24
+ - **AND** dependencies SHALL be represented as arrows (`-->`).
25
+ - **AND** independent tasks SHALL appear as nodes.
@@ -0,0 +1,31 @@
1
+ ## MODIFIED Requirements
2
+
3
+ ### Requirement: TaskRunner Execution
4
+
5
+ The `TaskRunner` SHALL execute a sequence of `TaskStep`s based on their dependencies, processing inputs and producing outputs.
6
+
7
+ #### Scenario: Successful execution
8
+
9
+ - **WHEN** all `TaskStep`s complete successfully
10
+ - **THEN** the `TaskRunner` returns a successful workflow result.
11
+
12
+ #### Scenario: Execution with AbortSignal
13
+
14
+ - **WHEN** `TaskRunner.execute` is called with an `AbortSignal`
15
+ - **THEN** the `TaskRunner` monitors the `AbortSignal` for cancellation requests.
16
+
17
+ #### Scenario: Execution with Global Timeout
18
+
19
+ - **WHEN** `TaskRunner.execute` is called with a `timeout` option
20
+ - **THEN** the `TaskRunner` monitors the elapsed time for the workflow.
21
+
22
+ ## ADDED Requirements
23
+
24
+ ### Requirement: Modular Execution Architecture
25
+
26
+ The system SHALL support pluggable execution strategies and decoupled state management.
27
+
28
+ #### Scenario: Pluggable Strategy
29
+
30
+ - **WHEN** configured with a custom execution strategy
31
+ - **THEN** the `TaskRunner` SHALL delegate the execution logic to that strategy.
@@ -0,0 +1,20 @@
1
+ # Change: Continue On Error
2
+
3
+ ## Why
4
+
5
+ Currently, if a task fails, all tasks that depend on it are automatically skipped. This is a safe default, but it prevents users from defining "non-critical" tasks (e.g., "Cleanup Temp Files", "Send Optional Notification") that should not block the workflow if they fail. Users often want downstream tasks to continue executing even if a specific non-essential dependency fails.
6
+
7
+ ## What Changes
8
+
9
+ - Update `TaskStep` interface to include an optional `continueOnError: boolean` property (defaulting to `false`).
10
+ - Update `TaskStateManager` to be aware of task definitions.
11
+ - Update `TaskStateManager.processDependencies` logic:
12
+ - If a dependency failed but has `continueOnError: true`, treat it as "satisfied" for the purpose of unblocking dependents.
13
+ - The dependent task will execute as if the dependency succeeded.
14
+ - The failed task's result remains `status: "failure"`, preserving visibility of the error.
15
+
16
+ ## Impact
17
+
18
+ - Affected specs: `001-generic-task-runner`
19
+ - Affected code: `src/TaskStep.ts`, `src/TaskStateManager.ts`
20
+ - **Non-breaking change**: The default behavior remains (stop on error). Users must opt-in by setting the flag.
@@ -0,0 +1,17 @@
1
+ # Tasks: Continue On Error
2
+
3
+ - [ ] **Update TaskStep Interface**
4
+ - [ ] Add `continueOnError?: boolean` to `TaskStep<TContext>` in `src/TaskStep.ts`.
5
+ - [ ] Update documentation comments for the new property.
6
+
7
+ - [ ] **Update TaskStateManager**
8
+ - [ ] Modify `TaskStateManager` to store the full `TaskStep` definitions map (name -> step) during initialization (`initialize` method).
9
+ - [ ] Update `processDependencies` to check `continueOnError` property when a dependency is in "failure" state.
10
+ - [ ] If `continueOnError` is true, allow the dependent task to proceed (do not mark as skipped).
11
+
12
+ - [ ] **Tests**
13
+ - [ ] Create a new test file `tests/continueOnError.test.ts`.
14
+ - [ ] Test case: Task A fails (default) -> Task B is skipped. (Regression check)
15
+ - [ ] Test case: Task A fails (continueOnError: true) -> Task B runs.
16
+ - [ ] Test case: Task A fails (continueOnError: true) -> Task B runs -> Task C runs.
17
+ - [ ] Test case: Task A fails (continueOnError: true) -> Task B fails (continueOnError: false) -> Task C skipped.
@@ -0,0 +1,34 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Per-Task Timeout
4
+
5
+ The `TaskStep` interface SHALL support an optional `timeout` property, and the `StandardExecutionStrategy` SHALL enforce this timeout.
6
+
7
+ #### Scenario: Task completes within timeout
8
+
9
+ - **GIVEN** a task with `timeout: 100` (ms)
10
+ - **WHEN** the task execution takes 50ms
11
+ - **THEN** the task SHALL complete successfully.
12
+ - **AND** the timeout timer SHALL be cleared immediately.
13
+
14
+ #### Scenario: Task exceeds timeout
15
+
16
+ - **GIVEN** a task with `timeout: 100` (ms)
17
+ - **WHEN** the task execution attempts to run longer than 100ms
18
+ - **THEN** the task execution SHALL be aborted with an error indicating a timeout.
19
+ - **AND** the `TaskResult` status SHALL be 'failure' (or 'cancelled' if appropriate, but typically 'failure' due to timeout error).
20
+ - **AND** the `AbortSignal` passed to the task's `run` method SHALL be triggered.
21
+
22
+ #### Scenario: Global cancellation overrides task timeout
23
+
24
+ - **GIVEN** a task with `timeout: 5000` (ms)
25
+ - **WHEN** the workflow's global `AbortSignal` is triggered at 100ms
26
+ - **THEN** the task SHALL receive the abort signal immediately (at 100ms).
27
+ - **AND** the task SHALL NOT wait for the 5000ms timeout.
28
+ - **AND** the `TaskResult` status SHALL be 'cancelled'.
29
+
30
+ #### Scenario: Task without timeout
31
+
32
+ - **GIVEN** a task without a `timeout` property
33
+ - **WHEN** it executes
34
+ - **THEN** it SHALL NOT be subject to any local timeout constraints (only global workflow timeout).
@@ -0,0 +1,13 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: Task Execution Metrics
4
+
5
+ The system SHALL record timing metrics for each executed task, including start time, end time, and duration.
6
+
7
+ #### Scenario: Successful execution
8
+ - **WHEN** a task completes successfully
9
+ - **THEN** the task result contains the start timestamp, end timestamp, and duration in milliseconds
10
+
11
+ #### Scenario: Failed execution
12
+ - **WHEN** a task fails
13
+ - **THEN** the task result contains the start timestamp, end timestamp, and duration in milliseconds
@@ -0,0 +1,162 @@
1
+ # task-runner Specification
2
+
3
+ ## Purpose
4
+
5
+ TBD - created by archiving change add-external-task-cancellation. Update Purpose after archive.
6
+
7
+ ## Requirements
8
+
9
+ ### Requirement: TaskRunner Execution
10
+
11
+ The `TaskRunner` SHALL execute a sequence of `TaskStep`s based on their dependencies, processing inputs and producing outputs.
12
+
13
+ #### Scenario: Successful execution
14
+
15
+ - **WHEN** all `TaskStep`s complete successfully
16
+ - **THEN** the `TaskRunner` returns a successful workflow result.
17
+
18
+ #### Scenario: Execution with AbortSignal
19
+
20
+ - **WHEN** `TaskRunner.execute` is called with an `AbortSignal`
21
+ - **THEN** the `TaskRunner` monitors the `AbortSignal` for cancellation requests.
22
+
23
+ #### Scenario: Execution with Global Timeout
24
+
25
+ - **WHEN** `TaskRunner.execute` is called with a `timeout` option
26
+ - **THEN** the `TaskRunner` monitors the elapsed time for the workflow.
27
+
28
+ ### Requirement: External Workflow Cancellation
29
+
30
+ The `TaskRunner` SHALL allow external cancellation of an ongoing workflow.
31
+
32
+ #### Scenario: Workflow cancelled by AbortSignal
33
+
34
+ - **WHEN** an `AbortSignal` provided to `TaskRunner.execute` is triggered
35
+ - **THEN** the `TaskRunner` immediately attempts to stop execution of current and pending tasks.
36
+
37
+ #### Scenario: Workflow cancelled by Global Timeout
38
+
39
+ - **WHEN** the specified global `timeout` for `TaskRunner.execute` is reached
40
+ - **THEN** the `TaskRunner` immediately attempts to stop execution of current and pending tasks.
41
+
42
+ #### Scenario: Tasks marked as cancelled
43
+
44
+ - **WHEN** a workflow is cancelled (by `AbortSignal` or `timeout`)
45
+ - **THEN** all unexecuted `TaskStep`s SHALL be marked with a 'cancelled' status in the final result.
46
+
47
+ #### Scenario: Pre-aborted workflow
48
+
49
+ - **WHEN** `TaskRunner.execute` is called with an `AbortSignal` that is already aborted
50
+ - **THEN** the `TaskRunner` SHALL return immediately with all tasks marked as cancelled, without executing any steps.
51
+
52
+ #### Scenario: Graceful interruption of current task
53
+
54
+ - **WHEN** a workflow is cancelled and a `TaskStep` is currently executing
55
+ - **THEN** the `TaskStep` SHALL receive the cancellation signal (e.g., via `AbortSignal` context) to allow for graceful interruption.
56
+
57
+ ### Requirement: Cancellation Conflict Resolution
58
+
59
+ The `TaskRunner` SHALL handle scenarios where both `AbortSignal` and global `timeout` are provided.
60
+
61
+ #### Scenario: AbortSignal precedes Timeout
62
+
63
+ - **WHEN** both `AbortSignal` and `timeout` are provided, and `AbortSignal` is triggered first
64
+ - **THEN** the `TaskRunner` SHALL cancel the workflow based on the `AbortSignal`, ignoring the `timeout`.
65
+
66
+ #### Scenario: Timeout precedes AbortSignal
67
+
68
+ - **WHEN** both `AbortSignal` and `timeout` are provided, and `timeout` is reached first
69
+ - **THEN** the `TaskRunner` SHALL cancel the workflow based on the `timeout`, ignoring the `AbortSignal`.
70
+
71
+ ### Requirement: Integration Verification
72
+
73
+ The system's integrity SHALL be verified through comprehensive integration scenarios executed against the real runtime environment without mocks.
74
+
75
+ #### Scenario: Complex Graph Execution
76
+
77
+ - **WHEN** a complex task graph (diamonds, sequences, parallel branches) is executed
78
+ - **THEN** the system SHALL respect all dependency constraints and execution orders.
79
+ - **AND** the final state MUST reflect the cumulative side effects of all successful tasks.
80
+
81
+ #### Scenario: Failure Propagation
82
+
83
+ - **WHEN** a task fails in a complex graph
84
+ - **THEN** ONLY dependent tasks SHALL be skipped
85
+ - **AND** independent branches SHALL continue to execute to completion.
86
+
87
+ #### Scenario: Context Integrity
88
+
89
+ - **WHEN** multiple tasks mutate the shared context
90
+ - **THEN** state changes MUST be propagated correctly to downstream tasks.
91
+
92
+ ### Requirement: Modular Execution Architecture
93
+
94
+ The system SHALL support pluggable execution strategies and decoupled state management.
95
+
96
+ #### Scenario: Pluggable Strategy
97
+
98
+ - **WHEN** configured with a custom execution strategy
99
+ - **THEN** the `TaskRunner` SHALL delegate the execution logic to that strategy.
100
+
101
+ ### Requirement: Dry Run Execution Strategy
102
+
103
+ The system SHALL provide a `DryRunExecutionStrategy` that implements `IExecutionStrategy`.
104
+
105
+ #### Scenario: Simulating execution
106
+
107
+ - **WHEN** `WorkflowExecutor` is configured with `DryRunExecutionStrategy`
108
+ - **AND** `execute` is called
109
+ - **THEN** it SHALL traverse the dependency graph respecting order
110
+ - **AND** it SHALL NOT execute the actual work of the `TaskStep`.
111
+ - **AND** it SHALL return `TaskResult`s with a status indicating successful simulation (e.g., `simulated` or `success`).
112
+
113
+ ### Requirement: Mermaid Visualization
114
+
115
+ The system SHALL provide a utility to generate a Mermaid.js graph from task steps.
116
+
117
+ #### Scenario: Generate Mermaid Graph
118
+
119
+ - **GIVEN** a list of `TaskStep`s with dependencies
120
+ - **WHEN** `generateMermaidGraph` is called
121
+ - **THEN** it SHALL return a valid Mermaid flowchart syntax string.
122
+ - **AND** dependencies SHALL be represented as arrows (`-->`).
123
+ - **AND** independent tasks SHALL appear as nodes.
124
+
125
+ ### Requirement: Task Retry Configuration
126
+
127
+ The `TaskStep` interface SHALL support an optional `retry` property of type `TaskRetryConfig`.
128
+
129
+ #### Scenario: Retry Config Structure
130
+
131
+ - **GIVEN** a `TaskRetryConfig` object
132
+ - **THEN** it SHALL support:
133
+ - `attempts`: Number of retry attempts (default: 0).
134
+ - `delay`: Base delay in milliseconds (default: 0).
135
+ - `backoff`: Backoff strategy ('fixed' | 'exponential') (default: 'fixed').
136
+
137
+ ### Requirement: Retrying Execution Strategy
138
+
139
+ The system SHALL provide a `RetryingExecutionStrategy` that implements `IExecutionStrategy` and wraps another `IExecutionStrategy`.
140
+
141
+ #### Scenario: Successful execution
142
+
143
+ - **WHEN** the inner strategy returns a successful `TaskResult`
144
+ - **THEN** `RetryingExecutionStrategy` SHALL return that result immediately.
145
+
146
+ #### Scenario: Retry on failure
147
+
148
+ - **WHEN** the inner strategy throws or returns a failed `TaskResult`
149
+ - **AND** the task has `retry.attempts > 0`
150
+ - **THEN** it SHALL wait for the configured `delay`.
151
+ - **AND** it SHALL re-execute the task using the inner strategy.
152
+ - **AND** it SHALL decrement the remaining attempts.
153
+
154
+ #### Scenario: Max attempts reached
155
+
156
+ - **WHEN** the task fails and no attempts remain
157
+ - **THEN** it SHALL return the failed result (or throw).
158
+
159
+ #### Scenario: Exponential Backoff
160
+
161
+ - **WHEN** `retry.backoff` is 'exponential'
162
+ - **THEN** the delay SHALL increase for each attempt (e.g., `delay * 2^attempt`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@calmo/task-runner",
3
- "version": "3.8.3",
3
+ "version": "4.0.4",
4
4
  "description": "A lightweight, type-safe, and domain-agnostic task orchestration engine. It resolves a Directed Acyclic Graph (DAG) of steps, executes independent tasks in parallel, and manages a shared context across the pipeline.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,16 +15,6 @@
15
15
  }
16
16
  },
17
17
  "type": "module",
18
- "scripts": {
19
- "build": "tsc",
20
- "test": "tsc --noEmit -p tsconfig.test.json && vitest run --coverage",
21
- "lint": "eslint .",
22
- "lint:fix": "eslint . --fix",
23
- "all": "pnpm run build && pnpm run test && pnpm run lint",
24
- "format": "prettier --write .",
25
- "prepare": "husky",
26
- "commit": "git add . &&git-cz"
27
- },
28
18
  "config": {
29
19
  "commitizen": {
30
20
  "path": "git-cz"
@@ -44,17 +34,10 @@
44
34
  ],
45
35
  "author": "",
46
36
  "license": "ISC",
47
- "packageManager": "pnpm@10.28.0",
48
37
  "devDependencies": {
49
38
  "@commitlint/cli": "^20.3.1",
50
39
  "@commitlint/config-conventional": "^20.3.1",
51
40
  "@eslint/js": "^9.39.2",
52
- "@semantic-release/changelog": "^6.0.3",
53
- "@semantic-release/commit-analyzer": "^13.0.1",
54
- "@semantic-release/git": "^10.0.1",
55
- "@semantic-release/github": "^12.0.2",
56
- "@semantic-release/npm": "^13.1.3",
57
- "@semantic-release/release-notes-generator": "^14.1.0",
58
41
  "@types/node": "^25.0.9",
59
42
  "@vitest/coverage-v8": "4.0.17",
60
43
  "eslint": "^9.39.2",
@@ -62,9 +45,17 @@
62
45
  "git-cz": "^4.9.0",
63
46
  "husky": "^9.1.7",
64
47
  "prettier": "^3.8.0",
65
- "semantic-release": "^25.0.2",
66
48
  "typescript": "^5.9.3",
67
49
  "typescript-eslint": "^8.53.0",
68
50
  "vitest": "^4.0.17"
51
+ },
52
+ "scripts": {
53
+ "build": "tsc",
54
+ "test": "tsc --noEmit -p tsconfig.test.json && vitest run --coverage",
55
+ "lint": "eslint .",
56
+ "lint:fix": "eslint . --fix",
57
+ "all": "pnpm run build && pnpm run test && pnpm run lint",
58
+ "format": "prettier --write .",
59
+ "commit": "git add . &&git-cz"
69
60
  }
70
- }
61
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "packages": {
3
+ ".": {
4
+ "release-type": "node",
5
+ "package-name": "@calmo/task-runner"
6
+ }
7
+ },
8
+ "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
9
+ }
@@ -145,8 +145,7 @@ export class TaskGraphValidator implements ITaskGraphValidator {
145
145
  stack.push({
146
146
  taskId: startTaskId,
147
147
  index: 0,
148
- /* v8 ignore next */
149
- dependencies: adjacencyList.get(startTaskId) ?? [],
148
+ dependencies: adjacencyList.get(startTaskId)!,
150
149
  });
151
150
 
152
151
  while (stack.length > 0) {
@@ -171,8 +170,7 @@ export class TaskGraphValidator implements ITaskGraphValidator {
171
170
  stack.push({
172
171
  taskId: dependenceId,
173
172
  index: 0,
174
- /* v8 ignore next */
175
- dependencies: adjacencyList.get(dependenceId) ?? [],
173
+ dependencies: adjacencyList.get(dependenceId)!,
176
174
  });
177
175
  }
178
176
  } else {
@@ -1,188 +0,0 @@
1
- description = "Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation."
2
-
3
- prompt = """
4
- ---
5
- description: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation.
6
- ---
7
-
8
- ## User Input
9
-
10
- ```text
11
- $ARGUMENTS
12
- ```
13
-
14
- You **MUST** consider the user input before proceeding (if not empty).
15
-
16
- ## Goal
17
-
18
- Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/speckit.tasks` has successfully produced a complete `tasks.md`.
19
-
20
- ## Operating Constraints
21
-
22
- **STRICTLY READ-ONLY**: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).
23
-
24
- **Constitution Authority**: The project constitution (`.specify/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/speckit.analyze`.
25
-
26
- ## Execution Steps
27
-
28
- ### 1. Initialize Analysis Context
29
-
30
- Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths:
31
-
32
- - SPEC = FEATURE_DIR/spec.md
33
- - PLAN = FEATURE_DIR/plan.md
34
- - TASKS = FEATURE_DIR/tasks.md
35
-
36
- Abort with an error message if any required file is missing (instruct the user to run missing prerequisite command).
37
- For single quotes in args like "I'm Groot", use escape syntax: e.g 'I'\\''m Groot' (or double-quote if possible: "I'm Groot").
38
-
39
- ### 2. Load Artifacts (Progressive Disclosure)
40
-
41
- Load only the minimal necessary context from each artifact:
42
-
43
- **From spec.md:**
44
-
45
- - Overview/Context
46
- - Functional Requirements
47
- - Non-Functional Requirements
48
- - User Stories
49
- - Edge Cases (if present)
50
-
51
- **From plan.md:**
52
-
53
- - Architecture/stack choices
54
- - Data Model references
55
- - Phases
56
- - Technical constraints
57
-
58
- **From tasks.md:**
59
-
60
- - Task IDs
61
- - Descriptions
62
- - Phase grouping
63
- - Parallel markers [P]
64
- - Referenced file paths
65
-
66
- **From constitution:**
67
-
68
- - Load `.specify/memory/constitution.md` for principle validation
69
-
70
- ### 3. Build Semantic Models
71
-
72
- Create internal representations (do not include raw artifacts in output):
73
-
74
- - **Requirements inventory**: Each functional + non-functional requirement with a stable key (derive slug based on imperative phrase; e.g., "User can upload file" → `user-can-upload-file`)
75
- - **User story/action inventory**: Discrete user actions with acceptance criteria
76
- - **Task coverage mapping**: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases)
77
- - **Constitution rule set**: Extract principle names and MUST/SHOULD normative statements
78
-
79
- ### 4. Detection Passes (Token-Efficient Analysis)
80
-
81
- Focus on high-signal findings. Limit to 50 findings total; aggregate remainder in overflow summary.
82
-
83
- #### A. Duplication Detection
84
-
85
- - Identify near-duplicate requirements
86
- - Mark lower-quality phrasing for consolidation
87
-
88
- #### B. Ambiguity Detection
89
-
90
- - Flag vague adjectives (fast, scalable, secure, intuitive, robust) lacking measurable criteria
91
- - Flag unresolved placeholders (TODO, TKTK, ???, `<placeholder>`, etc.)
92
-
93
- #### C. Underspecification
94
-
95
- - Requirements with verbs but missing object or measurable outcome
96
- - User stories missing acceptance criteria alignment
97
- - Tasks referencing files or components not defined in spec/plan
98
-
99
- #### D. Constitution Alignment
100
-
101
- - Any requirement or plan element conflicting with a MUST principle
102
- - Missing mandated sections or quality gates from constitution
103
-
104
- #### E. Coverage Gaps
105
-
106
- - Requirements with zero associated tasks
107
- - Tasks with no mapped requirement/story
108
- - Non-functional requirements not reflected in tasks (e.g., performance, security)
109
-
110
- #### F. Inconsistency
111
-
112
- - Terminology drift (same concept named differently across files)
113
- - Data entities referenced in plan but absent in spec (or vice versa)
114
- - Task ordering contradictions (e.g., integration tasks before foundational setup tasks without dependency note)
115
- - Conflicting requirements (e.g., one requires Next.js while other specifies Vue)
116
-
117
- ### 5. Severity Assignment
118
-
119
- Use this heuristic to prioritize findings:
120
-
121
- - **CRITICAL**: Violates constitution MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality
122
- - **HIGH**: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion
123
- - **MEDIUM**: Terminology drift, missing non-functional task coverage, underspecified edge case
124
- - **LOW**: Style/wording improvements, minor redundancy not affecting execution order
125
-
126
- ### 6. Produce Compact Analysis Report
127
-
128
- Output a Markdown report (no file writes) with the following structure:
129
-
130
- ## Specification Analysis Report
131
-
132
- | ID | Category | Severity | Location(s) | Summary | Recommendation |
133
- |----|----------|----------|-------------|---------|----------------|
134
- | A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version |
135
-
136
- (Add one row per finding; generate stable IDs prefixed by category initial.)
137
-
138
- **Coverage Summary Table:**
139
-
140
- | Requirement Key | Has Task? | Task IDs | Notes |
141
- |-----------------|-----------|----------|-------|
142
-
143
- **Constitution Alignment Issues:** (if any)
144
-
145
- **Unmapped Tasks:** (if any)
146
-
147
- **Metrics:**
148
-
149
- - Total Requirements
150
- - Total Tasks
151
- - Coverage % (requirements with >=1 task)
152
- - Ambiguity Count
153
- - Duplication Count
154
- - Critical Issues Count
155
-
156
- ### 7. Provide Next Actions
157
-
158
- At end of report, output a concise Next Actions block:
159
-
160
- - If CRITICAL issues exist: Recommend resolving before `/speckit.implement`
161
- - If only LOW/MEDIUM: User may proceed, but provide improvement suggestions
162
- - Provide explicit command suggestions: e.g., "Run /speckit.specify with refinement", "Run /speckit.plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'"
163
-
164
- ### 8. Offer Remediation
165
-
166
- Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.)
167
-
168
- ## Operating Principles
169
-
170
- ### Context Efficiency
171
-
172
- - **Minimal high-signal tokens**: Focus on actionable findings, not exhaustive documentation
173
- - **Progressive disclosure**: Load artifacts incrementally; don't dump all content into analysis
174
- - **Token-efficient output**: Limit findings table to 50 rows; summarize overflow
175
- - **Deterministic results**: Rerunning without changes should produce consistent IDs and counts
176
-
177
- ### Analysis Guidelines
178
-
179
- - **NEVER modify files** (this is read-only analysis)
180
- - **NEVER hallucinate missing sections** (if absent, report them accurately)
181
- - **Prioritize constitution violations** (these are always CRITICAL)
182
- - **Use examples over exhaustive rules** (cite specific instances, not generic patterns)
183
- - **Report zero issues gracefully** (emit success report with coverage statistics)
184
-
185
- ## Context
186
-
187
- {{args}}
188
- """