prjct-cli 1.12.0 → 1.14.0
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 +89 -0
- package/core/__tests__/agentic/analysis-injection.test.ts +377 -0
- package/core/__tests__/domain/velocity.test.ts +623 -0
- package/core/agentic/anti-hallucination.ts +23 -1
- package/core/agentic/orchestrator-executor.ts +59 -3
- package/core/agentic/prompt-builder.ts +53 -1
- package/core/commands/command-data.ts +17 -0
- package/core/commands/commands.ts +12 -0
- package/core/commands/register.ts +6 -0
- package/core/commands/velocity.ts +149 -0
- package/core/domain/velocity.ts +470 -0
- package/core/index.ts +1 -0
- package/core/schemas/index.ts +2 -0
- package/core/schemas/velocity.ts +103 -0
- package/core/storage/index.ts +2 -1
- package/core/storage/velocity-storage.ts +149 -0
- package/core/types/agentic.ts +33 -0
- package/core/types/index.ts +2 -0
- package/dist/bin/prjct.mjs +1103 -362
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.14.0] - 2026-02-09
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- add sprint-based velocity calculation with trend detection (PRJ-296) (#156)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [1.14.0] - 2026-02-09
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
- **Velocity Dashboard**: New `prjct velocity` command with sprint-by-sprint breakdown, trend detection, and estimation accuracy (PRJ-296)
|
|
14
|
+
- **Estimation Patterns**: Automatic detection of over/under estimation patterns by task category
|
|
15
|
+
- **Completion Projections**: Given remaining backlog points, projects estimated sprints and completion date
|
|
16
|
+
- **Velocity Context Injection**: Historical velocity data automatically injected into LLM task prompts for better estimation
|
|
17
|
+
|
|
18
|
+
### Implementation Details
|
|
19
|
+
|
|
20
|
+
**PRJ-296 — Sprint-Based Velocity Calculation**
|
|
21
|
+
New velocity subsystem that aggregates completed task data (from outcomes.jsonl) into sprint periods, calculates rolling velocity metrics, detects trends, and identifies estimation patterns.
|
|
22
|
+
|
|
23
|
+
Key changes:
|
|
24
|
+
- `core/schemas/velocity.ts` — Zod schemas: SprintVelocity, VelocityMetrics, VelocityConfig, EstimationPattern, CompletionProjection
|
|
25
|
+
- `core/domain/velocity.ts` — Velocity engine: sprint bucketing, linear regression trend detection, accuracy tracking, pattern detection, duration parsing, LLM context formatting
|
|
26
|
+
- `core/storage/velocity-storage.ts` — Write-through storage extending StorageManager with markdown generation
|
|
27
|
+
- `core/commands/velocity.ts` — Dashboard command with chalk-formatted output + registration
|
|
28
|
+
- `core/types/agentic.ts` — Extended `OrchestratorContext` with `velocityContext` field
|
|
29
|
+
- `core/agentic/orchestrator-executor.ts` — Loads velocity context in parallel via `Promise.all`
|
|
30
|
+
- `core/agentic/prompt-builder.ts` — Injects velocity into Section 6 (task context)
|
|
31
|
+
- `core/__tests__/domain/velocity.test.ts` — 35 new tests
|
|
32
|
+
|
|
33
|
+
### Learnings
|
|
34
|
+
- Derive story points from estimated duration via Fibonacci mapping when outcomes lack explicit point data
|
|
35
|
+
- Linear regression slope normalized by average velocity works well for trend detection (>10% = improving, <-10% = declining)
|
|
36
|
+
- Parallel loading pattern in orchestrator-executor (`Promise.all`) ensures zero-latency context enrichment
|
|
37
|
+
|
|
38
|
+
### Test Plan
|
|
39
|
+
|
|
40
|
+
#### For QA
|
|
41
|
+
1. Run `prjct velocity` on a project with outcomes data — verify sprint-by-sprint breakdown with points, tasks, accuracy
|
|
42
|
+
2. Run `prjct velocity` with no outcomes — verify graceful "No velocity data yet" message
|
|
43
|
+
3. Run `prjct velocity 89` — verify completion projection (sprints remaining + date)
|
|
44
|
+
4. Run `bun test core/__tests__/domain/velocity.test.ts` — 35 tests pass
|
|
45
|
+
5. Run `bun test` — all 805 tests pass
|
|
46
|
+
|
|
47
|
+
#### For Users
|
|
48
|
+
- **What changed:** New `prjct velocity` command shows sprint velocity, estimation accuracy trends, and completion projections. Velocity data is automatically injected into task prompts for better LLM estimation.
|
|
49
|
+
- **How to use:** Run `prjct velocity` after completing tasks with estimates. Add backlog points: `prjct velocity 89`
|
|
50
|
+
- **Breaking changes:** None
|
|
51
|
+
|
|
52
|
+
## [1.13.0] - 2026-02-09
|
|
53
|
+
|
|
54
|
+
### Features
|
|
55
|
+
|
|
56
|
+
- inject sealed analysis into task prompt context (PRJ-260) (#155)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## [1.13.0] - 2026-02-09
|
|
60
|
+
|
|
61
|
+
### Features
|
|
62
|
+
- **Analysis Injection**: Sealed analysis (languages, frameworks, patterns, anti-patterns) now automatically injected into LLM prompt context (PRJ-260)
|
|
63
|
+
- **Enriched Ground Truth**: Prompt section 3 renders full analysis data — languages, frameworks, package manager, source/test dirs, code patterns, and anti-patterns
|
|
64
|
+
- **Enhanced Anti-Hallucination**: AVAILABLE tech list enriched with analysis data (case-insensitive dedup), package manager constraint added
|
|
65
|
+
|
|
66
|
+
### Implementation Details
|
|
67
|
+
|
|
68
|
+
**PRJ-260 — Inject Sync Analysis into Task Context**
|
|
69
|
+
Connected the analysis pipeline (from PRJ-263) to the prompt assembly pipeline (from PRJ-301). `analysisStorage.getActive()` returns sealed analysis (or draft fallback), loaded in parallel with real codebase context for zero latency impact.
|
|
70
|
+
|
|
71
|
+
Key changes:
|
|
72
|
+
- `core/types/agentic.ts` — New `SealedAnalysisContext` interface, extended `OrchestratorContext` with `sealedAnalysis` field
|
|
73
|
+
- `core/agentic/orchestrator-executor.ts` — Added `loadSealedAnalysis()`, loads in parallel with `gatherRealContext()`
|
|
74
|
+
- `core/agentic/prompt-builder.ts` — Section 3 (ground truth) renders analysis data, Section 5 passes analysis to anti-hallucination
|
|
75
|
+
- `core/agentic/anti-hallucination.ts` — Extended `ProjectGroundTruth` with `analysisLanguages`, `analysisFrameworks`, `analysisPackageManager`
|
|
76
|
+
- `core/__tests__/agentic/analysis-injection.test.ts` — 14 new tests
|
|
77
|
+
|
|
78
|
+
### Test Plan
|
|
79
|
+
|
|
80
|
+
#### For QA
|
|
81
|
+
1. Run `prjct sync` on a project with sealed analysis — verify prompt contains Languages, Frameworks, Patterns sections
|
|
82
|
+
2. Run `prjct sync` on a project WITHOUT sealed analysis — verify no crash, fallback rules still present
|
|
83
|
+
3. Check anti-hallucination block — verify AVAILABLE list includes analysis languages/frameworks (deduped)
|
|
84
|
+
4. Run `bun test core/__tests__/agentic/analysis-injection.test.ts` — 14 tests pass
|
|
85
|
+
5. Run `bun test` — all 770 tests pass
|
|
86
|
+
|
|
87
|
+
#### For Users
|
|
88
|
+
- **What changed:** AI prompts now include your project's detected languages, frameworks, code patterns, and anti-patterns from sealed analysis
|
|
89
|
+
- **How to use:** Run `prjct sync` then `prjct seal` — improvements are automatic in subsequent task prompts
|
|
90
|
+
- **Breaking changes:** None
|
|
91
|
+
|
|
3
92
|
## [1.12.0] - 2026-02-09
|
|
4
93
|
|
|
5
94
|
### Features
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analysis Injection Tests (PRJ-260)
|
|
3
|
+
*
|
|
4
|
+
* Tests for injecting sealed analysis data into task context:
|
|
5
|
+
* - Prompt builder renders analysis in ground_truth section
|
|
6
|
+
* - Anti-hallucination block enriched with analysis data
|
|
7
|
+
* - Graceful degradation when no analysis available
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { beforeEach, describe, expect, it } from 'bun:test'
|
|
11
|
+
import {
|
|
12
|
+
buildAntiHallucinationBlock,
|
|
13
|
+
type ProjectGroundTruth,
|
|
14
|
+
} from '../../agentic/anti-hallucination'
|
|
15
|
+
import promptBuilder from '../../agentic/prompt-builder'
|
|
16
|
+
import type { OrchestratorContext, SealedAnalysisContext } from '../../types'
|
|
17
|
+
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Test Fixtures
|
|
20
|
+
// =============================================================================
|
|
21
|
+
|
|
22
|
+
const mockSealedAnalysis: SealedAnalysisContext = {
|
|
23
|
+
languages: ['TypeScript', 'JavaScript'],
|
|
24
|
+
frameworks: ['Hono', 'Zod'],
|
|
25
|
+
packageManager: 'bun',
|
|
26
|
+
sourceDir: 'core/',
|
|
27
|
+
testDir: 'core/__tests__/',
|
|
28
|
+
fileCount: 295,
|
|
29
|
+
patterns: [
|
|
30
|
+
{
|
|
31
|
+
name: 'StorageManager pattern',
|
|
32
|
+
description: 'All storage uses StorageManager base class with read/write/update',
|
|
33
|
+
location: 'core/storage/',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'Zod schemas',
|
|
37
|
+
description: 'Runtime validation with Zod for all data structures',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
antiPatterns: [
|
|
41
|
+
{
|
|
42
|
+
issue: 'Direct fs.writeFile without StorageManager',
|
|
43
|
+
file: 'core/storage/legacy.ts',
|
|
44
|
+
suggestion: 'Use StorageManager.write() instead',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
status: 'sealed',
|
|
48
|
+
commitHash: 'abc123def456',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function makeOrchestratorContext(
|
|
52
|
+
sealedAnalysis: SealedAnalysisContext | null = mockSealedAnalysis
|
|
53
|
+
): OrchestratorContext {
|
|
54
|
+
return {
|
|
55
|
+
detectedDomains: ['backend', 'testing'],
|
|
56
|
+
primaryDomain: 'backend',
|
|
57
|
+
agents: [],
|
|
58
|
+
skills: [],
|
|
59
|
+
requiresFragmentation: false,
|
|
60
|
+
subtasks: null,
|
|
61
|
+
project: {
|
|
62
|
+
id: 'test-project',
|
|
63
|
+
ecosystem: 'TypeScript',
|
|
64
|
+
conventions: ['Hono', 'Zod'],
|
|
65
|
+
},
|
|
66
|
+
sealedAnalysis,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// Prompt Builder — Ground Truth Section
|
|
72
|
+
// =============================================================================
|
|
73
|
+
|
|
74
|
+
describe('Analysis Injection in Prompt Builder (PRJ-260)', () => {
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
promptBuilder.resetContext()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should render sealed analysis in ground truth section', async () => {
|
|
80
|
+
const template = {
|
|
81
|
+
frontmatter: { description: 'Test task' },
|
|
82
|
+
content: '## Instructions\nDo the work',
|
|
83
|
+
}
|
|
84
|
+
const context = { projectPath: '/test/project', files: ['a.ts'] }
|
|
85
|
+
const orcCtx = makeOrchestratorContext()
|
|
86
|
+
|
|
87
|
+
const prompt = await promptBuilder.build(
|
|
88
|
+
template,
|
|
89
|
+
context,
|
|
90
|
+
{},
|
|
91
|
+
null,
|
|
92
|
+
null,
|
|
93
|
+
null,
|
|
94
|
+
null,
|
|
95
|
+
null,
|
|
96
|
+
orcCtx
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// Should contain analysis data
|
|
100
|
+
expect(prompt).toContain('Languages**: TypeScript, JavaScript')
|
|
101
|
+
expect(prompt).toContain('Frameworks**: Hono, Zod')
|
|
102
|
+
expect(prompt).toContain('Package Manager**: bun')
|
|
103
|
+
expect(prompt).toContain('Source Dir**: core/')
|
|
104
|
+
expect(prompt).toContain('Test Dir**: core/__tests__/')
|
|
105
|
+
expect(prompt).toContain('Files Analyzed**: 295')
|
|
106
|
+
expect(prompt).toContain('Analysis Status**: sealed')
|
|
107
|
+
expect(prompt).toContain('abc123de') // truncated commit hash
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('should render code patterns from sealed analysis', async () => {
|
|
111
|
+
const template = {
|
|
112
|
+
frontmatter: { description: 'Test' },
|
|
113
|
+
content: '## Do',
|
|
114
|
+
}
|
|
115
|
+
const context = { projectPath: '/test', files: [] }
|
|
116
|
+
const orcCtx = makeOrchestratorContext()
|
|
117
|
+
|
|
118
|
+
const prompt = await promptBuilder.build(
|
|
119
|
+
template,
|
|
120
|
+
context,
|
|
121
|
+
{},
|
|
122
|
+
null,
|
|
123
|
+
null,
|
|
124
|
+
null,
|
|
125
|
+
null,
|
|
126
|
+
null,
|
|
127
|
+
orcCtx
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
expect(prompt).toContain('Code Patterns (Follow These)')
|
|
131
|
+
expect(prompt).toContain('StorageManager pattern')
|
|
132
|
+
expect(prompt).toContain('All storage uses StorageManager base class')
|
|
133
|
+
expect(prompt).toContain('core/storage/')
|
|
134
|
+
expect(prompt).toContain('Zod schemas')
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('should render anti-patterns from sealed analysis', async () => {
|
|
138
|
+
const template = {
|
|
139
|
+
frontmatter: { description: 'Test' },
|
|
140
|
+
content: '## Do',
|
|
141
|
+
}
|
|
142
|
+
const context = { projectPath: '/test', files: [] }
|
|
143
|
+
const orcCtx = makeOrchestratorContext()
|
|
144
|
+
|
|
145
|
+
const prompt = await promptBuilder.build(
|
|
146
|
+
template,
|
|
147
|
+
context,
|
|
148
|
+
{},
|
|
149
|
+
null,
|
|
150
|
+
null,
|
|
151
|
+
null,
|
|
152
|
+
null,
|
|
153
|
+
null,
|
|
154
|
+
orcCtx
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
expect(prompt).toContain('Anti-Patterns (Avoid These)')
|
|
158
|
+
expect(prompt).toContain('Direct fs.writeFile without StorageManager')
|
|
159
|
+
expect(prompt).toContain('core/storage/legacy.ts')
|
|
160
|
+
expect(prompt).toContain('Use StorageManager.write() instead')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('should gracefully handle null sealed analysis', async () => {
|
|
164
|
+
const template = {
|
|
165
|
+
frontmatter: { description: 'Test' },
|
|
166
|
+
content: '## Do',
|
|
167
|
+
}
|
|
168
|
+
const context = { projectPath: '/test', files: [] }
|
|
169
|
+
const orcCtx = makeOrchestratorContext(null)
|
|
170
|
+
|
|
171
|
+
const prompt = await promptBuilder.build(
|
|
172
|
+
template,
|
|
173
|
+
context,
|
|
174
|
+
{},
|
|
175
|
+
null,
|
|
176
|
+
null,
|
|
177
|
+
null,
|
|
178
|
+
null,
|
|
179
|
+
null,
|
|
180
|
+
orcCtx
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
// Should still have basic project analysis
|
|
184
|
+
expect(prompt).toContain('PROJECT ANALYSIS')
|
|
185
|
+
expect(prompt).toContain('Ecosystem**: TypeScript')
|
|
186
|
+
// Should NOT have analysis-specific fields
|
|
187
|
+
expect(prompt).not.toContain('Languages**:')
|
|
188
|
+
expect(prompt).not.toContain('Code Patterns (Follow These)')
|
|
189
|
+
expect(prompt).not.toContain('Anti-Patterns (Avoid These)')
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('should handle empty patterns and anti-patterns', async () => {
|
|
193
|
+
const template = {
|
|
194
|
+
frontmatter: { description: 'Test' },
|
|
195
|
+
content: '## Do',
|
|
196
|
+
}
|
|
197
|
+
const context = { projectPath: '/test', files: [] }
|
|
198
|
+
const emptyAnalysis: SealedAnalysisContext = {
|
|
199
|
+
...mockSealedAnalysis,
|
|
200
|
+
patterns: [],
|
|
201
|
+
antiPatterns: [],
|
|
202
|
+
}
|
|
203
|
+
const orcCtx = makeOrchestratorContext(emptyAnalysis)
|
|
204
|
+
|
|
205
|
+
const prompt = await promptBuilder.build(
|
|
206
|
+
template,
|
|
207
|
+
context,
|
|
208
|
+
{},
|
|
209
|
+
null,
|
|
210
|
+
null,
|
|
211
|
+
null,
|
|
212
|
+
null,
|
|
213
|
+
null,
|
|
214
|
+
orcCtx
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
expect(prompt).toContain('Languages**: TypeScript, JavaScript')
|
|
218
|
+
expect(prompt).not.toContain('Code Patterns (Follow These)')
|
|
219
|
+
expect(prompt).not.toContain('Anti-Patterns (Avoid These)')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('should handle no orchestrator context at all', async () => {
|
|
223
|
+
const template = {
|
|
224
|
+
frontmatter: { description: 'Test' },
|
|
225
|
+
content: '## Do',
|
|
226
|
+
}
|
|
227
|
+
const context = { projectPath: '/test', files: [] }
|
|
228
|
+
|
|
229
|
+
const prompt = await promptBuilder.build(
|
|
230
|
+
template,
|
|
231
|
+
context,
|
|
232
|
+
{},
|
|
233
|
+
null,
|
|
234
|
+
null,
|
|
235
|
+
null,
|
|
236
|
+
null,
|
|
237
|
+
null,
|
|
238
|
+
null
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
// Should not crash, should have fallback rules
|
|
242
|
+
expect(prompt).toContain('CONSTRAINTS')
|
|
243
|
+
expect(prompt).not.toContain('PROJECT ANALYSIS')
|
|
244
|
+
})
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// Anti-Hallucination Block — Analysis Enrichment
|
|
249
|
+
// =============================================================================
|
|
250
|
+
|
|
251
|
+
describe('Anti-Hallucination Block with Analysis (PRJ-260)', () => {
|
|
252
|
+
it('should include analysis languages in AVAILABLE list', () => {
|
|
253
|
+
const truth: ProjectGroundTruth = {
|
|
254
|
+
projectPath: '/test',
|
|
255
|
+
language: 'TypeScript',
|
|
256
|
+
techStack: ['Hono'],
|
|
257
|
+
analysisLanguages: ['TypeScript', 'JavaScript', 'Shell'],
|
|
258
|
+
analysisFrameworks: ['Hono', 'Vitest'],
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const block = buildAntiHallucinationBlock(truth)
|
|
262
|
+
|
|
263
|
+
expect(block).toContain('AVAILABLE in this project:')
|
|
264
|
+
// TypeScript and Hono should not be duplicated
|
|
265
|
+
expect(block).toContain('JavaScript')
|
|
266
|
+
expect(block).toContain('Shell')
|
|
267
|
+
expect(block).toContain('Vitest')
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should deduplicate analysis data with existing tech stack (case-insensitive)', () => {
|
|
271
|
+
const truth: ProjectGroundTruth = {
|
|
272
|
+
projectPath: '/test',
|
|
273
|
+
language: 'TypeScript',
|
|
274
|
+
framework: 'Hono',
|
|
275
|
+
techStack: ['Zod'],
|
|
276
|
+
analysisLanguages: ['typescript'], // lowercase duplicate
|
|
277
|
+
analysisFrameworks: ['hono', 'Zod'], // lowercase duplicates
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const block = buildAntiHallucinationBlock(truth)
|
|
281
|
+
|
|
282
|
+
// Count occurrences — each should appear exactly once
|
|
283
|
+
const typescriptMatches = block.match(/typescript/gi)
|
|
284
|
+
expect(typescriptMatches?.length).toBe(1)
|
|
285
|
+
|
|
286
|
+
const honoMatches = block.match(/hono/gi)
|
|
287
|
+
expect(honoMatches?.length).toBe(1)
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('should show package manager from analysis', () => {
|
|
291
|
+
const truth: ProjectGroundTruth = {
|
|
292
|
+
projectPath: '/test',
|
|
293
|
+
analysisPackageManager: 'bun',
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const block = buildAntiHallucinationBlock(truth)
|
|
297
|
+
|
|
298
|
+
expect(block).toContain('PACKAGE MANAGER: bun')
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
it('should work without any analysis data', () => {
|
|
302
|
+
const truth: ProjectGroundTruth = {
|
|
303
|
+
projectPath: '/test',
|
|
304
|
+
language: 'Python',
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const block = buildAntiHallucinationBlock(truth)
|
|
308
|
+
|
|
309
|
+
expect(block).toContain('AVAILABLE in this project: Python')
|
|
310
|
+
expect(block).not.toContain('PACKAGE MANAGER:')
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
it('should handle empty analysis arrays gracefully', () => {
|
|
314
|
+
const truth: ProjectGroundTruth = {
|
|
315
|
+
projectPath: '/test',
|
|
316
|
+
analysisLanguages: [],
|
|
317
|
+
analysisFrameworks: [],
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const block = buildAntiHallucinationBlock(truth)
|
|
321
|
+
|
|
322
|
+
// Should not contain AVAILABLE line (no tech to show)
|
|
323
|
+
expect(block).not.toContain('AVAILABLE in this project:')
|
|
324
|
+
expect(block).toContain('CONSTRAINTS')
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
// =============================================================================
|
|
329
|
+
// SealedAnalysisContext Type
|
|
330
|
+
// =============================================================================
|
|
331
|
+
|
|
332
|
+
describe('SealedAnalysisContext type (PRJ-260)', () => {
|
|
333
|
+
it('should accept valid sealed analysis data', () => {
|
|
334
|
+
const analysis: SealedAnalysisContext = {
|
|
335
|
+
languages: ['TypeScript'],
|
|
336
|
+
frameworks: ['Hono'],
|
|
337
|
+
fileCount: 100,
|
|
338
|
+
patterns: [{ name: 'test', description: 'test pattern' }],
|
|
339
|
+
antiPatterns: [{ issue: 'test', file: 'test.ts', suggestion: 'fix it' }],
|
|
340
|
+
status: 'sealed',
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
expect(analysis.languages).toEqual(['TypeScript'])
|
|
344
|
+
expect(analysis.status).toBe('sealed')
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
it('should accept draft status', () => {
|
|
348
|
+
const analysis: SealedAnalysisContext = {
|
|
349
|
+
languages: [],
|
|
350
|
+
frameworks: [],
|
|
351
|
+
fileCount: 0,
|
|
352
|
+
patterns: [],
|
|
353
|
+
antiPatterns: [],
|
|
354
|
+
status: 'draft',
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
expect(analysis.status).toBe('draft')
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('should accept optional fields', () => {
|
|
361
|
+
const analysis: SealedAnalysisContext = {
|
|
362
|
+
languages: ['Python'],
|
|
363
|
+
frameworks: [],
|
|
364
|
+
fileCount: 50,
|
|
365
|
+
patterns: [],
|
|
366
|
+
antiPatterns: [],
|
|
367
|
+
status: 'sealed',
|
|
368
|
+
packageManager: 'pip',
|
|
369
|
+
sourceDir: 'src/',
|
|
370
|
+
testDir: 'tests/',
|
|
371
|
+
commitHash: 'abc123',
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
expect(analysis.packageManager).toBe('pip')
|
|
375
|
+
expect(analysis.commitHash).toBe('abc123')
|
|
376
|
+
})
|
|
377
|
+
})
|