@cleocode/core 2026.3.45 → 2026.3.46
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/dist/bootstrap.d.ts.map +1 -1
- package/dist/index.js +1475 -372
- package/dist/index.js.map +4 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/injection.d.ts +1 -1
- package/dist/injection.d.ts.map +1 -1
- package/dist/routing/capability-matrix.d.ts +6 -4
- package/dist/routing/capability-matrix.d.ts.map +1 -1
- package/dist/scaffold.d.ts +16 -9
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/skills/agents/install.d.ts.map +1 -1
- package/dist/skills/routing-table.d.ts +17 -16
- package/dist/skills/routing-table.d.ts.map +1 -1
- package/dist/skills/skill-paths.d.ts.map +1 -1
- package/dist/system/health.d.ts.map +1 -1
- package/dist/ui/index.d.ts +0 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/package.json +9 -4
- package/schemas/adr-frontmatter.schema.json +72 -0
- package/schemas/agent-configs.schema.json +120 -0
- package/schemas/agent-registry.json +243 -0
- package/schemas/agent-registry.schema.json +132 -0
- package/schemas/archive/research-manifest.schema.json +257 -0
- package/schemas/archive.schema.json +450 -0
- package/schemas/brain-decision.schema.json +69 -0
- package/schemas/brain-learning.schema.json +57 -0
- package/schemas/brain-pattern.schema.json +72 -0
- package/schemas/config.schema.json +2606 -0
- package/schemas/context-state.schema.json +137 -0
- package/schemas/contribution.schema.json +722 -0
- package/schemas/critical-path.schema.json +246 -0
- package/schemas/deps-cache.schema.json +97 -0
- package/schemas/doctor-output.schema.json +283 -0
- package/schemas/error.schema.json +161 -0
- package/schemas/export-package.schema.json +375 -0
- package/schemas/global-config.schema.json +219 -0
- package/schemas/grade.schema.json +49 -0
- package/schemas/log.schema.json +250 -0
- package/schemas/metrics.schema.json +328 -0
- package/schemas/migrations.schema.json +150 -0
- package/schemas/nexus-registry.schema.json +90 -0
- package/schemas/operation-constitution.schema.json +438 -0
- package/schemas/output.schema.json +164 -0
- package/schemas/project-context.schema.json +164 -0
- package/schemas/project-info.schema.json +180 -0
- package/schemas/projects-registry.schema.json +107 -0
- package/schemas/protocol-frontmatter.schema.json +72 -0
- package/schemas/rcasd-consensus-report.schema.json +10 -0
- package/schemas/rcasd-evidence.schema.json +42 -0
- package/schemas/rcasd-gate-result.schema.json +46 -0
- package/schemas/rcasd-hitl-resolution.schema.json +10 -0
- package/schemas/rcasd-index.schema.json +10 -0
- package/schemas/rcasd-manifest.schema.json +10 -0
- package/schemas/rcasd-research-output.schema.json +10 -0
- package/schemas/rcasd-spec-frontmatter.schema.json +10 -0
- package/schemas/rcasd-stage-transition.schema.json +38 -0
- package/schemas/releases.schema.json +267 -0
- package/schemas/skills-manifest.schema.json +91 -0
- package/schemas/skillsmp.schema.json +208 -0
- package/schemas/spec-index.schema.json +196 -0
- package/schemas/system-flow-atlas.schema.json +125 -0
- package/src/__tests__/injection-chain.test.ts +11 -10
- package/src/__tests__/injection-mvi-tiers.test.ts +4 -2
- package/src/agents/__tests__/capacity.test.d.ts +7 -0
- package/src/agents/__tests__/capacity.test.d.ts.map +1 -0
- package/src/agents/__tests__/capacity.test.js +173 -0
- package/src/agents/__tests__/capacity.test.js.map +1 -0
- package/src/agents/__tests__/registry.test.d.ts +8 -0
- package/src/agents/__tests__/registry.test.d.ts.map +1 -0
- package/src/agents/__tests__/registry.test.js +348 -0
- package/src/agents/__tests__/registry.test.js.map +1 -0
- package/src/agents/__tests__/retry.test.d.ts +7 -0
- package/src/agents/__tests__/retry.test.d.ts.map +1 -0
- package/src/agents/__tests__/retry.test.js +225 -0
- package/src/agents/__tests__/retry.test.js.map +1 -0
- package/src/bootstrap.ts +3 -1
- package/src/init.ts +63 -18
- package/src/injection.ts +11 -5
- package/src/intelligence/__tests__/impact.test.d.ts +15 -0
- package/src/intelligence/__tests__/impact.test.d.ts.map +1 -0
- package/src/intelligence/__tests__/impact.test.js +384 -0
- package/src/intelligence/__tests__/impact.test.js.map +1 -0
- package/src/intelligence/__tests__/patterns.test.d.ts +8 -0
- package/src/intelligence/__tests__/patterns.test.d.ts.map +1 -0
- package/src/intelligence/__tests__/patterns.test.js +370 -0
- package/src/intelligence/__tests__/patterns.test.js.map +1 -0
- package/src/intelligence/__tests__/prediction.test.d.ts +8 -0
- package/src/intelligence/__tests__/prediction.test.d.ts.map +1 -0
- package/src/intelligence/__tests__/prediction.test.js +314 -0
- package/src/intelligence/__tests__/prediction.test.js.map +1 -0
- package/src/nexus/__tests__/nexus-e2e.test.d.ts +12 -0
- package/src/nexus/__tests__/nexus-e2e.test.d.ts.map +1 -0
- package/src/nexus/__tests__/nexus-e2e.test.js +1220 -0
- package/src/nexus/__tests__/nexus-e2e.test.js.map +1 -0
- package/src/nexus/__tests__/transfer.test.d.ts +8 -0
- package/src/nexus/__tests__/transfer.test.d.ts.map +1 -0
- package/src/nexus/__tests__/transfer.test.js +372 -0
- package/src/nexus/__tests__/transfer.test.js.map +1 -0
- package/src/nexus/__tests__/transfer.test.ts +1 -1
- package/src/routing/capability-matrix.ts +1435 -205
- package/src/scaffold.ts +18 -11
- package/src/skills/__tests__/routing-table.test.ts +53 -33
- package/src/skills/agents/install.ts +9 -1
- package/src/skills/routing-table.ts +39 -253
- package/src/skills/skill-paths.ts +3 -2
- package/src/store/__tests__/project-detect.test.ts +1 -1
- package/src/system/health.ts +18 -7
- package/src/ui/index.ts +0 -6
- package/src/validation/operation-gate-validators.ts +2 -2
- package/templates/CLEO-INJECTION.md +120 -0
- package/templates/README.md +29 -0
- package/templates/agent-registry.json +305 -0
- package/templates/cleo-gitignore +74 -0
- package/templates/config.template.json +187 -0
- package/templates/git-hooks/commit-msg +149 -0
- package/templates/git-hooks/pre-commit +40 -0
- package/templates/git-hooks/pre-push +79 -0
- package/templates/github/ISSUE_TEMPLATE/bug_report.yml +143 -0
- package/templates/github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/github/ISSUE_TEMPLATE/feature_request.yml +125 -0
- package/templates/github/ISSUE_TEMPLATE/help_question.yml +99 -0
- package/templates/global-config.template.json +56 -0
- package/templates/hooks/precompact-safestop.sh +89 -0
- package/templates/issue-templates/bug_report.yml +143 -0
- package/templates/issue-templates/config.yml +8 -0
- package/templates/issue-templates/feature_request.yml +125 -0
- package/templates/issue-templates/help_question.yml +99 -0
- package/templates/skillsmp.json.example +28 -0
- package/templates/skillsmp.json.example.md +214 -0
- package/dist/ui/injection-legacy.d.ts +0 -26
- package/dist/ui/injection-legacy.d.ts.map +0 -1
- package/src/ui/__tests__/injection-registry.test.d.ts +0 -11
- package/src/ui/__tests__/injection-registry.test.d.ts.map +0 -1
- package/src/ui/__tests__/injection-registry.test.js +0 -46
- package/src/ui/__tests__/injection-registry.test.js.map +0 -1
- package/src/ui/__tests__/injection-registry.test.ts +0 -57
- package/src/ui/injection-legacy.ts +0 -44
package/src/bootstrap.ts
CHANGED
|
@@ -141,7 +141,9 @@ async function injectAgentsHub(ctx: BootstrapContext): Promise<void> {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
// Direct call — CAAMP 1.8.0 handles idempotency
|
|
145
|
+
const expectedContent = '@~/.cleo/templates/CLEO-INJECTION.md';
|
|
146
|
+
const action = await inject(globalAgentsMd, expectedContent);
|
|
145
147
|
ctx.created.push(`~/.agents/AGENTS.md (${action})`);
|
|
146
148
|
} else {
|
|
147
149
|
ctx.created.push('~/.agents/AGENTS.md (would create/update CAAMP block)');
|
package/src/init.ts
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
36
36
|
import { copyFile, lstat, mkdir, readFile, symlink, unlink, writeFile } from 'node:fs/promises';
|
|
37
|
+
import { platform } from 'node:os';
|
|
37
38
|
import { basename, dirname, join } from 'node:path';
|
|
38
39
|
import { ExitCode } from '@cleocode/contracts';
|
|
39
40
|
import { CleoError } from './errors.js';
|
|
@@ -83,6 +84,15 @@ export interface InitResult {
|
|
|
83
84
|
updateDocsOnly?: boolean;
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Symlink type for directory symlinks.
|
|
91
|
+
* On Windows, use 'junction' (no admin privileges required).
|
|
92
|
+
* On Unix, use 'dir'.
|
|
93
|
+
*/
|
|
94
|
+
const DIR_SYMLINK_TYPE: 'junction' | 'dir' = platform() === 'win32' ? 'junction' : 'dir';
|
|
95
|
+
|
|
86
96
|
// ── Init-specific operations ─────────────────────────────────────────
|
|
87
97
|
|
|
88
98
|
/**
|
|
@@ -90,10 +100,30 @@ export interface InitResult {
|
|
|
90
100
|
* @task T4685
|
|
91
101
|
*/
|
|
92
102
|
export async function initAgentDefinition(created: string[], warnings: string[]): Promise<void> {
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
// Resolve agents package via require.resolve, then workspace/bundled fallback
|
|
104
|
+
let agentSourceDir: string | null = null;
|
|
105
|
+
try {
|
|
106
|
+
const { createRequire } = await import('node:module');
|
|
107
|
+
const req = createRequire(import.meta.url);
|
|
108
|
+
const agentsPkgMain = req.resolve('@cleocode/agents/package.json');
|
|
109
|
+
const agentsPkgRoot = dirname(agentsPkgMain);
|
|
110
|
+
const candidate = join(agentsPkgRoot, 'cleo-subagent');
|
|
111
|
+
if (existsSync(candidate)) {
|
|
112
|
+
agentSourceDir = candidate;
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// Not resolvable via require.resolve — fall through to bundled path
|
|
116
|
+
}
|
|
95
117
|
|
|
96
|
-
if (!
|
|
118
|
+
if (!agentSourceDir) {
|
|
119
|
+
const packageRoot = getPackageRoot();
|
|
120
|
+
const bundled = join(packageRoot, 'agents', 'cleo-subagent');
|
|
121
|
+
if (existsSync(bundled)) {
|
|
122
|
+
agentSourceDir = bundled;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!agentSourceDir) {
|
|
97
127
|
warnings.push('agents/cleo-subagent/ not found in package, skipping agent definition install');
|
|
98
128
|
return;
|
|
99
129
|
}
|
|
@@ -114,7 +144,7 @@ export async function initAgentDefinition(created: string[], warnings: string[])
|
|
|
114
144
|
}
|
|
115
145
|
|
|
116
146
|
// Create symlink from ~/.agents/agents/cleo-subagent -> package agents/cleo-subagent/
|
|
117
|
-
await symlink(agentSourceDir, globalAgentsDir,
|
|
147
|
+
await symlink(agentSourceDir, globalAgentsDir, DIR_SYMLINK_TYPE);
|
|
118
148
|
created.push('agent: cleo-subagent (symlinked)');
|
|
119
149
|
} catch (_err) {
|
|
120
150
|
// If symlink fails (e.g., permissions), try copying
|
|
@@ -201,23 +231,38 @@ export async function initCoreSkills(created: string[], warnings: string[]): Pro
|
|
|
201
231
|
return;
|
|
202
232
|
}
|
|
203
233
|
|
|
204
|
-
// Find skills package
|
|
234
|
+
// Find skills package via require.resolve, then workspace path, then node_modules fallback
|
|
205
235
|
const packageRoot = getPackageRoot();
|
|
206
236
|
let ctSkillsRoot: string | null = null;
|
|
207
237
|
try {
|
|
208
|
-
//
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (existsSync(join(ctSkillsPath, 'skills.json'))) {
|
|
216
|
-
ctSkillsRoot = ctSkillsPath;
|
|
217
|
-
}
|
|
238
|
+
// Primary: resolve via Node module resolution (@cleocode/skills)
|
|
239
|
+
const { createRequire } = await import('node:module');
|
|
240
|
+
const req = createRequire(import.meta.url);
|
|
241
|
+
const skillsPkgMain = req.resolve('@cleocode/skills/package.json');
|
|
242
|
+
const skillsPkgRoot = dirname(skillsPkgMain);
|
|
243
|
+
if (existsSync(join(skillsPkgRoot, 'skills.json'))) {
|
|
244
|
+
ctSkillsRoot = skillsPkgRoot;
|
|
218
245
|
}
|
|
219
246
|
} catch {
|
|
220
|
-
//
|
|
247
|
+
// Not resolvable via require.resolve — try workspace and node_modules fallbacks
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (!ctSkillsRoot) {
|
|
251
|
+
try {
|
|
252
|
+
// Workspace monorepo fallback (packages/skills/)
|
|
253
|
+
const bundledPath = join(packageRoot, 'packages', 'skills');
|
|
254
|
+
if (existsSync(join(bundledPath, 'skills.json'))) {
|
|
255
|
+
ctSkillsRoot = bundledPath;
|
|
256
|
+
} else {
|
|
257
|
+
// node_modules fallback
|
|
258
|
+
const ctSkillsPath = join(packageRoot, 'node_modules', '@cleocode', 'skills');
|
|
259
|
+
if (existsSync(join(ctSkillsPath, 'skills.json'))) {
|
|
260
|
+
ctSkillsRoot = ctSkillsPath;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
} catch {
|
|
264
|
+
// not found
|
|
265
|
+
}
|
|
221
266
|
}
|
|
222
267
|
|
|
223
268
|
if (!ctSkillsRoot) {
|
|
@@ -651,8 +696,8 @@ export async function initProject(opts: InitOptions = {}): Promise<InitResult> {
|
|
|
651
696
|
// T4685: Agent definition (cleo-subagent)
|
|
652
697
|
await initAgentDefinition(created, warnings);
|
|
653
698
|
|
|
654
|
-
//
|
|
655
|
-
|
|
699
|
+
// Note: Core skills installation is global-only (bootstrapGlobalCleo / installSkillsGlobally).
|
|
700
|
+
// Skills are NOT installed during project-level init — they are installed once globally.
|
|
656
701
|
|
|
657
702
|
// T4684: NEXUS registration (reconcile-based handshake, T5368)
|
|
658
703
|
await initNexusRegistration(projRoot, created, warnings);
|
package/src/injection.ts
CHANGED
|
@@ -78,7 +78,7 @@ async function removeStaleAgentInjection(projectRoot: string): Promise<boolean>
|
|
|
78
78
|
*
|
|
79
79
|
* Target architecture:
|
|
80
80
|
* CLAUDE.md/GEMINI.md -> @AGENTS.md (via injectAll)
|
|
81
|
-
* AGENTS.md -> @~/.
|
|
81
|
+
* AGENTS.md -> @~/.agents/AGENTS.md + @.cleo/project-context.json + @.cleo/memory-bridge.md
|
|
82
82
|
*
|
|
83
83
|
* @task T4682
|
|
84
84
|
*/
|
|
@@ -125,8 +125,9 @@ export async function ensureInjection(projectRoot: string): Promise<ScaffoldResu
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// Step 2: Inject CLEO protocol content into AGENTS.md itself
|
|
128
|
+
// Project AGENTS.md references the global hub, which loads CLEO-INJECTION.md
|
|
128
129
|
const agentsMdPath = join(projectRoot, 'AGENTS.md');
|
|
129
|
-
const agentsMdLines = ['@~/.
|
|
130
|
+
const agentsMdLines = ['@~/.agents/AGENTS.md'];
|
|
130
131
|
|
|
131
132
|
const projectContextPath = join(projectRoot, '.cleo', 'project-context.json');
|
|
132
133
|
if (existsSync(projectContextPath)) {
|
|
@@ -146,7 +147,10 @@ export async function ensureInjection(projectRoot: string): Promise<ScaffoldResu
|
|
|
146
147
|
agentsMdLines.push(contributorBlock);
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
const
|
|
150
|
+
const agentsMdContent = agentsMdLines.join('\n');
|
|
151
|
+
|
|
152
|
+
// Direct call — CAAMP 1.8.0 handles idempotency
|
|
153
|
+
const agentsAction = await inject(agentsMdPath, agentsMdContent);
|
|
150
154
|
actions.push(`AGENTS.md CLEO content (${agentsAction})`);
|
|
151
155
|
|
|
152
156
|
// Step 3: Install CLEO-INJECTION.md to global templates dir
|
|
@@ -161,12 +165,14 @@ export async function ensureInjection(projectRoot: string): Promise<ScaffoldResu
|
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
// Step 4: Create global ~/.agents/AGENTS.md hub
|
|
168
|
+
// Step 4: Create global ~/.agents/AGENTS.md hub (idempotent)
|
|
165
169
|
try {
|
|
166
170
|
const globalAgentsDir = getAgentsHome();
|
|
167
171
|
const globalAgentsMd = join(globalAgentsDir, 'AGENTS.md');
|
|
172
|
+
const globalHubContent = '@~/.cleo/templates/CLEO-INJECTION.md';
|
|
168
173
|
await mkdir(globalAgentsDir, { recursive: true });
|
|
169
|
-
|
|
174
|
+
// Direct call — CAAMP 1.8.0 handles idempotency
|
|
175
|
+
await inject(globalAgentsMd, globalHubContent);
|
|
170
176
|
} catch {
|
|
171
177
|
// Best-effort — don't fail if global hub creation fails
|
|
172
178
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for impact analysis module.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - Simple dependency chains (A->B->C)
|
|
6
|
+
* - Complex graphs (diamond dependencies)
|
|
7
|
+
* - Each change type (cancel, block, complete, reprioritize)
|
|
8
|
+
* - Blast radius calculation
|
|
9
|
+
* - Critical path detection
|
|
10
|
+
* - Edge cases (orphan tasks, circular refs, no deps)
|
|
11
|
+
*
|
|
12
|
+
* @module intelligence
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=impact.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.test.d.ts","sourceRoot":"","sources":["impact.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for impact analysis module.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - Simple dependency chains (A->B->C)
|
|
6
|
+
* - Complex graphs (diamond dependencies)
|
|
7
|
+
* - Each change type (cancel, block, complete, reprioritize)
|
|
8
|
+
* - Blast radius calculation
|
|
9
|
+
* - Critical path detection
|
|
10
|
+
* - Edge cases (orphan tasks, circular refs, no deps)
|
|
11
|
+
*
|
|
12
|
+
* @module intelligence
|
|
13
|
+
*/
|
|
14
|
+
import { describe, expect, it } from 'vitest';
|
|
15
|
+
import { analyzeChangeImpact, analyzeTaskImpact, calculateBlastRadius } from '../impact.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Test Helpers
|
|
18
|
+
// ============================================================================
|
|
19
|
+
function makeTask(overrides) {
|
|
20
|
+
return {
|
|
21
|
+
title: `Task ${overrides.id}`,
|
|
22
|
+
description: `Description for ${overrides.id}`,
|
|
23
|
+
status: 'pending',
|
|
24
|
+
priority: 'medium',
|
|
25
|
+
createdAt: new Date().toISOString(),
|
|
26
|
+
...overrides,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a mock DataAccessor that returns the given tasks.
|
|
31
|
+
*/
|
|
32
|
+
function mockAccessor(tasks) {
|
|
33
|
+
return {
|
|
34
|
+
queryTasks: async () => ({ tasks, total: tasks.length }),
|
|
35
|
+
loadSingleTask: async (id) => tasks.find((t) => t.id === id) ?? null,
|
|
36
|
+
taskExists: async (id) => tasks.some((t) => t.id === id),
|
|
37
|
+
upsertSingleTask: async () => { },
|
|
38
|
+
deleteSingleTask: async () => true,
|
|
39
|
+
close: async () => { },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// analyzeTaskImpact
|
|
44
|
+
// ============================================================================
|
|
45
|
+
describe('analyzeTaskImpact', () => {
|
|
46
|
+
it('returns empty assessment for non-existent task', async () => {
|
|
47
|
+
const acc = mockAccessor([]);
|
|
48
|
+
const result = await analyzeTaskImpact('T999', acc);
|
|
49
|
+
expect(result.taskId).toBe('T999');
|
|
50
|
+
expect(result.directDependents).toEqual([]);
|
|
51
|
+
expect(result.transitiveDependents).toEqual([]);
|
|
52
|
+
expect(result.blockedWorkCount).toBe(0);
|
|
53
|
+
expect(result.isOnCriticalPath).toBe(false);
|
|
54
|
+
expect(result.blastRadius.severity).toBe('isolated');
|
|
55
|
+
});
|
|
56
|
+
it('analyzes simple linear chain A->B->C', async () => {
|
|
57
|
+
const tasks = [
|
|
58
|
+
makeTask({ id: 'T001' }),
|
|
59
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
60
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
61
|
+
];
|
|
62
|
+
const acc = mockAccessor(tasks);
|
|
63
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
64
|
+
expect(result.taskId).toBe('T001');
|
|
65
|
+
expect(result.directDependents).toEqual(['T002']);
|
|
66
|
+
expect(result.transitiveDependents.sort()).toEqual(['T002', 'T003']);
|
|
67
|
+
expect(result.blockedWorkCount).toBe(2);
|
|
68
|
+
});
|
|
69
|
+
it('analyzes diamond dependency graph', async () => {
|
|
70
|
+
// T001 -> T002 -> T004
|
|
71
|
+
// T001 -> T003 -> T004
|
|
72
|
+
const tasks = [
|
|
73
|
+
makeTask({ id: 'T001' }),
|
|
74
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
75
|
+
makeTask({ id: 'T003', depends: ['T001'] }),
|
|
76
|
+
makeTask({ id: 'T004', depends: ['T002', 'T003'] }),
|
|
77
|
+
];
|
|
78
|
+
const acc = mockAccessor(tasks);
|
|
79
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
80
|
+
expect(result.directDependents.sort()).toEqual(['T002', 'T003']);
|
|
81
|
+
expect(result.transitiveDependents.sort()).toEqual(['T002', 'T003', 'T004']);
|
|
82
|
+
expect(result.blockedWorkCount).toBe(3);
|
|
83
|
+
});
|
|
84
|
+
it('excludes completed tasks from blocked work count', async () => {
|
|
85
|
+
const tasks = [
|
|
86
|
+
makeTask({ id: 'T001' }),
|
|
87
|
+
makeTask({ id: 'T002', depends: ['T001'], status: 'done' }),
|
|
88
|
+
makeTask({ id: 'T003', depends: ['T001'] }),
|
|
89
|
+
];
|
|
90
|
+
const acc = mockAccessor(tasks);
|
|
91
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
92
|
+
expect(result.directDependents.sort()).toEqual(['T002', 'T003']);
|
|
93
|
+
expect(result.blockedWorkCount).toBe(1); // T002 is done, only T003 counts
|
|
94
|
+
});
|
|
95
|
+
it('detects task on critical path', async () => {
|
|
96
|
+
const tasks = [
|
|
97
|
+
makeTask({ id: 'T001' }),
|
|
98
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
99
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
100
|
+
makeTask({ id: 'T004' }), // isolated, not on critical path
|
|
101
|
+
];
|
|
102
|
+
const acc = mockAccessor(tasks);
|
|
103
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
104
|
+
expect(result.isOnCriticalPath).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
it('detects task NOT on critical path', async () => {
|
|
107
|
+
// T001 -> T002 -> T003 (critical path, length 3)
|
|
108
|
+
// T004 (independent, shorter)
|
|
109
|
+
const tasks = [
|
|
110
|
+
makeTask({ id: 'T001' }),
|
|
111
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
112
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
113
|
+
makeTask({ id: 'T004' }),
|
|
114
|
+
];
|
|
115
|
+
const acc = mockAccessor(tasks);
|
|
116
|
+
const result = await analyzeTaskImpact('T004', acc);
|
|
117
|
+
expect(result.isOnCriticalPath).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
it('finds affected pipelines via parent chain', async () => {
|
|
120
|
+
const tasks = [
|
|
121
|
+
makeTask({ id: 'T001', type: 'epic' }),
|
|
122
|
+
makeTask({ id: 'T002', parentId: 'T001', type: 'task' }),
|
|
123
|
+
makeTask({ id: 'T003', parentId: 'T001', type: 'task', depends: ['T002'] }),
|
|
124
|
+
];
|
|
125
|
+
const acc = mockAccessor(tasks);
|
|
126
|
+
const result = await analyzeTaskImpact('T002', acc);
|
|
127
|
+
expect(result.affectedPipelines).toContain('T001');
|
|
128
|
+
});
|
|
129
|
+
it('handles orphan task with no dependents', async () => {
|
|
130
|
+
const tasks = [makeTask({ id: 'T001' }), makeTask({ id: 'T002' })];
|
|
131
|
+
const acc = mockAccessor(tasks);
|
|
132
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
133
|
+
expect(result.directDependents).toEqual([]);
|
|
134
|
+
expect(result.transitiveDependents).toEqual([]);
|
|
135
|
+
expect(result.blockedWorkCount).toBe(0);
|
|
136
|
+
expect(result.blastRadius.severity).toBe('isolated');
|
|
137
|
+
});
|
|
138
|
+
it('handles circular dependency gracefully', async () => {
|
|
139
|
+
const tasks = [
|
|
140
|
+
makeTask({ id: 'T001', depends: ['T002'] }),
|
|
141
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
142
|
+
];
|
|
143
|
+
const acc = mockAccessor(tasks);
|
|
144
|
+
// Should not throw, BFS handles cycles via visited set
|
|
145
|
+
const result = await analyzeTaskImpact('T001', acc);
|
|
146
|
+
expect(result.directDependents).toContain('T002');
|
|
147
|
+
expect(result.transitiveDependents).toContain('T002');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// analyzeChangeImpact
|
|
152
|
+
// ============================================================================
|
|
153
|
+
describe('analyzeChangeImpact', () => {
|
|
154
|
+
it('returns empty for non-existent task', async () => {
|
|
155
|
+
const acc = mockAccessor([]);
|
|
156
|
+
const result = await analyzeChangeImpact('T999', 'cancel', acc);
|
|
157
|
+
expect(result.affectedTasks).toEqual([]);
|
|
158
|
+
expect(result.cascadeDepth).toBe(0);
|
|
159
|
+
expect(result.recommendation).toContain('not found');
|
|
160
|
+
});
|
|
161
|
+
describe('cancel', () => {
|
|
162
|
+
it('identifies orphaned dependents when sole dependency cancelled', async () => {
|
|
163
|
+
const tasks = [
|
|
164
|
+
makeTask({ id: 'T001' }),
|
|
165
|
+
makeTask({ id: 'T002', depends: ['T001'], status: 'blocked' }),
|
|
166
|
+
];
|
|
167
|
+
const acc = mockAccessor(tasks);
|
|
168
|
+
const result = await analyzeChangeImpact('T001', 'cancel', acc);
|
|
169
|
+
expect(result.affectedTasks).toHaveLength(1);
|
|
170
|
+
expect(result.affectedTasks[0].id).toBe('T002');
|
|
171
|
+
expect(result.affectedTasks[0].newStatus).toBe('pending');
|
|
172
|
+
expect(result.affectedTasks[0].reason).toContain('orphaned');
|
|
173
|
+
});
|
|
174
|
+
it('identifies tasks with remaining dependencies', async () => {
|
|
175
|
+
const tasks = [
|
|
176
|
+
makeTask({ id: 'T001' }),
|
|
177
|
+
makeTask({ id: 'T003' }),
|
|
178
|
+
makeTask({ id: 'T002', depends: ['T001', 'T003'] }),
|
|
179
|
+
];
|
|
180
|
+
const acc = mockAccessor(tasks);
|
|
181
|
+
const result = await analyzeChangeImpact('T001', 'cancel', acc);
|
|
182
|
+
expect(result.affectedTasks).toHaveLength(1);
|
|
183
|
+
expect(result.affectedTasks[0].reason).toContain('other dependencies remain');
|
|
184
|
+
});
|
|
185
|
+
it('skips already-completed dependents', async () => {
|
|
186
|
+
const tasks = [
|
|
187
|
+
makeTask({ id: 'T001' }),
|
|
188
|
+
makeTask({ id: 'T002', depends: ['T001'], status: 'done' }),
|
|
189
|
+
];
|
|
190
|
+
const acc = mockAccessor(tasks);
|
|
191
|
+
const result = await analyzeChangeImpact('T001', 'cancel', acc);
|
|
192
|
+
expect(result.affectedTasks).toEqual([]);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
describe('block', () => {
|
|
196
|
+
it('cascade-blocks all downstream tasks', async () => {
|
|
197
|
+
const tasks = [
|
|
198
|
+
makeTask({ id: 'T001' }),
|
|
199
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
200
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
201
|
+
];
|
|
202
|
+
const acc = mockAccessor(tasks);
|
|
203
|
+
const result = await analyzeChangeImpact('T001', 'block', acc);
|
|
204
|
+
expect(result.affectedTasks).toHaveLength(2);
|
|
205
|
+
expect(result.affectedTasks.every((t) => t.newStatus === 'blocked')).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
it('includes direct dependency reason', async () => {
|
|
208
|
+
const tasks = [makeTask({ id: 'T001' }), makeTask({ id: 'T002', depends: ['T001'] })];
|
|
209
|
+
const acc = mockAccessor(tasks);
|
|
210
|
+
const result = await analyzeChangeImpact('T001', 'block', acc);
|
|
211
|
+
expect(result.affectedTasks[0].reason).toContain('Direct dependency blocked');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
describe('complete', () => {
|
|
215
|
+
it('unblocks tasks whose last dependency is completed', async () => {
|
|
216
|
+
const tasks = [
|
|
217
|
+
makeTask({ id: 'T001' }),
|
|
218
|
+
makeTask({ id: 'T002', depends: ['T001'], status: 'blocked' }),
|
|
219
|
+
];
|
|
220
|
+
const acc = mockAccessor(tasks);
|
|
221
|
+
const result = await analyzeChangeImpact('T001', 'complete', acc);
|
|
222
|
+
expect(result.affectedTasks).toHaveLength(1);
|
|
223
|
+
expect(result.affectedTasks[0].id).toBe('T002');
|
|
224
|
+
expect(result.affectedTasks[0].newStatus).toBe('pending');
|
|
225
|
+
expect(result.affectedTasks[0].reason).toContain('unblocked');
|
|
226
|
+
});
|
|
227
|
+
it('reports partially unblocked tasks with remaining deps', async () => {
|
|
228
|
+
const tasks = [
|
|
229
|
+
makeTask({ id: 'T001' }),
|
|
230
|
+
makeTask({ id: 'T003' }),
|
|
231
|
+
makeTask({ id: 'T002', depends: ['T001', 'T003'], status: 'blocked' }),
|
|
232
|
+
];
|
|
233
|
+
const acc = mockAccessor(tasks);
|
|
234
|
+
const result = await analyzeChangeImpact('T001', 'complete', acc);
|
|
235
|
+
expect(result.affectedTasks).toHaveLength(1);
|
|
236
|
+
expect(result.affectedTasks[0].reason).toContain('1 other dependency');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
describe('reprioritize', () => {
|
|
240
|
+
it('flags downstream tasks for reordering', async () => {
|
|
241
|
+
const tasks = [
|
|
242
|
+
makeTask({ id: 'T001' }),
|
|
243
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
244
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
245
|
+
];
|
|
246
|
+
const acc = mockAccessor(tasks);
|
|
247
|
+
const result = await analyzeChangeImpact('T001', 'reprioritize', acc);
|
|
248
|
+
expect(result.affectedTasks).toHaveLength(2);
|
|
249
|
+
expect(result.affectedTasks.every((t) => t.reason.includes('reprioritized'))).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
it('computes cascade depth correctly', async () => {
|
|
253
|
+
const tasks = [
|
|
254
|
+
makeTask({ id: 'T001' }),
|
|
255
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
256
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
257
|
+
makeTask({ id: 'T004', depends: ['T003'] }),
|
|
258
|
+
];
|
|
259
|
+
const acc = mockAccessor(tasks);
|
|
260
|
+
const result = await analyzeChangeImpact('T001', 'block', acc);
|
|
261
|
+
expect(result.cascadeDepth).toBe(3);
|
|
262
|
+
});
|
|
263
|
+
it('generates recommendation text', async () => {
|
|
264
|
+
const tasks = [makeTask({ id: 'T001' }), makeTask({ id: 'T002', depends: ['T001'] })];
|
|
265
|
+
const acc = mockAccessor(tasks);
|
|
266
|
+
const result = await analyzeChangeImpact('T001', 'block', acc);
|
|
267
|
+
expect(result.recommendation).toContain('blocking');
|
|
268
|
+
expect(result.recommendation).toContain('T001');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
// ============================================================================
|
|
272
|
+
// calculateBlastRadius
|
|
273
|
+
// ============================================================================
|
|
274
|
+
describe('calculateBlastRadius', () => {
|
|
275
|
+
it('returns isolated for non-existent task', async () => {
|
|
276
|
+
const acc = mockAccessor([]);
|
|
277
|
+
const result = await calculateBlastRadius('T999', acc);
|
|
278
|
+
expect(result.directCount).toBe(0);
|
|
279
|
+
expect(result.transitiveCount).toBe(0);
|
|
280
|
+
expect(result.severity).toBe('isolated');
|
|
281
|
+
});
|
|
282
|
+
it('computes correct counts for linear chain', async () => {
|
|
283
|
+
const tasks = [
|
|
284
|
+
makeTask({ id: 'T001' }),
|
|
285
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
286
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
287
|
+
];
|
|
288
|
+
const acc = mockAccessor(tasks);
|
|
289
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
290
|
+
expect(result.directCount).toBe(1);
|
|
291
|
+
expect(result.transitiveCount).toBe(2);
|
|
292
|
+
});
|
|
293
|
+
it('computes correct counts for diamond dependency', async () => {
|
|
294
|
+
const tasks = [
|
|
295
|
+
makeTask({ id: 'T001' }),
|
|
296
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
297
|
+
makeTask({ id: 'T003', depends: ['T001'] }),
|
|
298
|
+
makeTask({ id: 'T004', depends: ['T002', 'T003'] }),
|
|
299
|
+
];
|
|
300
|
+
const acc = mockAccessor(tasks);
|
|
301
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
302
|
+
expect(result.directCount).toBe(2);
|
|
303
|
+
expect(result.transitiveCount).toBe(3);
|
|
304
|
+
});
|
|
305
|
+
it('counts affected epics', async () => {
|
|
306
|
+
const tasks = [
|
|
307
|
+
makeTask({ id: 'T001', type: 'epic' }),
|
|
308
|
+
makeTask({ id: 'T002', parentId: 'T001', type: 'task' }),
|
|
309
|
+
makeTask({ id: 'T003', parentId: 'T001', type: 'task', depends: ['T002'] }),
|
|
310
|
+
];
|
|
311
|
+
const acc = mockAccessor(tasks);
|
|
312
|
+
const result = await calculateBlastRadius('T002', acc);
|
|
313
|
+
expect(result.epicCount).toBeGreaterThanOrEqual(1);
|
|
314
|
+
});
|
|
315
|
+
it('calculates project percentage', async () => {
|
|
316
|
+
// 3 out of 10 tasks affected = 30%
|
|
317
|
+
const tasks = [];
|
|
318
|
+
for (let i = 1; i <= 10; i++) {
|
|
319
|
+
tasks.push(makeTask({
|
|
320
|
+
id: `T${String(i).padStart(3, '0')}`,
|
|
321
|
+
depends: i > 1 && i <= 4 ? [`T${String(i - 1).padStart(3, '0')}`] : undefined,
|
|
322
|
+
}));
|
|
323
|
+
}
|
|
324
|
+
const acc = mockAccessor(tasks);
|
|
325
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
326
|
+
// T001 -> T002 -> T003 -> T004 (transitive: T002, T003, T004 = 3 tasks)
|
|
327
|
+
expect(result.transitiveCount).toBe(3);
|
|
328
|
+
expect(result.projectPercentage).toBe(30);
|
|
329
|
+
});
|
|
330
|
+
it('classifies severity as isolated for 0%', async () => {
|
|
331
|
+
const tasks = [makeTask({ id: 'T001' }), makeTask({ id: 'T002' })];
|
|
332
|
+
const acc = mockAccessor(tasks);
|
|
333
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
334
|
+
expect(result.severity).toBe('isolated');
|
|
335
|
+
});
|
|
336
|
+
it('classifies severity as moderate for 2-10%', async () => {
|
|
337
|
+
// 1 out of 20 = 5%
|
|
338
|
+
const tasks = [];
|
|
339
|
+
for (let i = 1; i <= 20; i++) {
|
|
340
|
+
tasks.push(makeTask({ id: `T${String(i).padStart(3, '0')}` }));
|
|
341
|
+
}
|
|
342
|
+
// Make T002 depend on T001
|
|
343
|
+
tasks[1] = makeTask({ id: 'T002', depends: ['T001'] });
|
|
344
|
+
const acc = mockAccessor(tasks);
|
|
345
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
346
|
+
expect(result.severity).toBe('moderate');
|
|
347
|
+
});
|
|
348
|
+
it('classifies severity as critical for >30%', async () => {
|
|
349
|
+
// Chain of 4 out of 5 tasks = 60%
|
|
350
|
+
const tasks = [
|
|
351
|
+
makeTask({ id: 'T001' }),
|
|
352
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
353
|
+
makeTask({ id: 'T003', depends: ['T002'] }),
|
|
354
|
+
makeTask({ id: 'T004', depends: ['T003'] }),
|
|
355
|
+
makeTask({ id: 'T005' }),
|
|
356
|
+
];
|
|
357
|
+
const acc = mockAccessor(tasks);
|
|
358
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
359
|
+
expect(result.severity).toBe('critical');
|
|
360
|
+
});
|
|
361
|
+
it('handles orphan task with no dependents', async () => {
|
|
362
|
+
const tasks = [makeTask({ id: 'T001' }), makeTask({ id: 'T002' }), makeTask({ id: 'T003' })];
|
|
363
|
+
const acc = mockAccessor(tasks);
|
|
364
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
365
|
+
expect(result.directCount).toBe(0);
|
|
366
|
+
expect(result.transitiveCount).toBe(0);
|
|
367
|
+
expect(result.severity).toBe('isolated');
|
|
368
|
+
});
|
|
369
|
+
it('handles circular dependency without infinite loop', async () => {
|
|
370
|
+
const tasks = [
|
|
371
|
+
makeTask({ id: 'T001', depends: ['T002'] }),
|
|
372
|
+
makeTask({ id: 'T002', depends: ['T001'] }),
|
|
373
|
+
];
|
|
374
|
+
const acc = mockAccessor(tasks);
|
|
375
|
+
// Should complete without hanging.
|
|
376
|
+
// In a cycle, both tasks appear in the transitive closure
|
|
377
|
+
// because BFS from T001 finds T002 (direct dep), then from T002
|
|
378
|
+
// finds T001 (since T001 depends on T002), yielding 2.
|
|
379
|
+
const result = await calculateBlastRadius('T001', acc);
|
|
380
|
+
expect(result.directCount).toBe(1);
|
|
381
|
+
expect(result.transitiveCount).toBe(2);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
//# sourceMappingURL=impact.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.test.js","sourceRoot":"","sources":["impact.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Pattern Extraction module.
|
|
3
|
+
*
|
|
4
|
+
* Tests pattern extraction from history, pattern matching against tasks,
|
|
5
|
+
* pattern storage, and stat updates. All external dependencies are mocked.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=patterns.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.test.d.ts","sourceRoot":"","sources":["patterns.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|