sdd-mcp-server 5.3.0 → 5.5.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.
Files changed (117) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +85 -13
  3. package/agents/security-auditor.md +2 -2
  4. package/dist/__tests__/helpers/message-clarity.d.ts +15 -0
  5. package/dist/__tests__/helpers/message-clarity.js +26 -0
  6. package/dist/__tests__/helpers/message-clarity.js.map +1 -0
  7. package/dist/__tests__/helpers/message-extractor.d.ts +22 -0
  8. package/dist/__tests__/helpers/message-extractor.js +135 -0
  9. package/dist/__tests__/helpers/message-extractor.js.map +1 -0
  10. package/dist/__tests__/unit/jev/helpers.d.ts +84 -0
  11. package/dist/__tests__/unit/jev/helpers.js +188 -0
  12. package/dist/__tests__/unit/jev/helpers.js.map +1 -0
  13. package/dist/adapters/cli/SDDToolAdapter.d.ts +5 -1
  14. package/dist/adapters/cli/SDDToolAdapter.js +22 -3
  15. package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
  16. package/dist/application/services/JevAdvisoryService.d.ts +53 -0
  17. package/dist/application/services/JevAdvisoryService.js +310 -0
  18. package/dist/application/services/JevAdvisoryService.js.map +1 -0
  19. package/dist/application/services/JevBaseRef.d.ts +21 -0
  20. package/dist/application/services/JevBaseRef.js +46 -0
  21. package/dist/application/services/JevBaseRef.js.map +1 -0
  22. package/dist/application/services/JevChangeManifest.d.ts +33 -0
  23. package/dist/application/services/JevChangeManifest.js +208 -0
  24. package/dist/application/services/JevChangeManifest.js.map +1 -0
  25. package/dist/application/services/JevCheckTypes.d.ts +74 -0
  26. package/dist/application/services/JevCheckTypes.js +2 -0
  27. package/dist/application/services/JevCheckTypes.js.map +1 -0
  28. package/dist/application/services/JevCodeExcerpts.d.ts +23 -0
  29. package/dist/application/services/JevCodeExcerpts.js +102 -0
  30. package/dist/application/services/JevCodeExcerpts.js.map +1 -0
  31. package/dist/application/services/JevCommitLookup.d.ts +17 -0
  32. package/dist/application/services/JevCommitLookup.js +72 -0
  33. package/dist/application/services/JevCommitLookup.js.map +1 -0
  34. package/dist/application/services/JevExchange.d.ts +48 -0
  35. package/dist/application/services/JevExchange.js +119 -0
  36. package/dist/application/services/JevExchange.js.map +1 -0
  37. package/dist/application/services/JevQuestionCatalog.d.ts +28 -0
  38. package/dist/application/services/JevQuestionCatalog.js +194 -0
  39. package/dist/application/services/JevQuestionCatalog.js.map +1 -0
  40. package/dist/application/services/JevRedaction.d.ts +12 -0
  41. package/dist/application/services/JevRedaction.js +56 -0
  42. package/dist/application/services/JevRedaction.js.map +1 -0
  43. package/dist/application/services/JevReport.d.ts +41 -0
  44. package/dist/application/services/JevReport.js +101 -0
  45. package/dist/application/services/JevReport.js.map +1 -0
  46. package/dist/application/services/JevResponseValidator.d.ts +34 -0
  47. package/dist/application/services/JevResponseValidator.js +98 -0
  48. package/dist/application/services/JevResponseValidator.js.map +1 -0
  49. package/dist/application/services/JevResults.d.ts +3 -0
  50. package/dist/application/services/JevResults.js +7 -0
  51. package/dist/application/services/JevResults.js.map +1 -0
  52. package/dist/application/services/JevReviewCheck.d.ts +20 -0
  53. package/dist/application/services/JevReviewCheck.js +120 -0
  54. package/dist/application/services/JevReviewCheck.js.map +1 -0
  55. package/dist/application/services/JevSettings.d.ts +18 -0
  56. package/dist/application/services/JevSettings.js +72 -0
  57. package/dist/application/services/JevSettings.js.map +1 -0
  58. package/dist/application/services/JevSidecarStore.d.ts +68 -0
  59. package/dist/application/services/JevSidecarStore.js +201 -0
  60. package/dist/application/services/JevSidecarStore.js.map +1 -0
  61. package/dist/application/services/JevSpecState.d.ts +38 -0
  62. package/dist/application/services/JevSpecState.js +109 -0
  63. package/dist/application/services/JevSpecState.js.map +1 -0
  64. package/dist/application/services/JevTestcaseState.d.ts +22 -0
  65. package/dist/application/services/JevTestcaseState.js +85 -0
  66. package/dist/application/services/JevTestcaseState.js.map +1 -0
  67. package/dist/application/services/RedEvidenceClassifier.d.ts +10 -0
  68. package/dist/application/services/RedEvidenceClassifier.js +32 -0
  69. package/dist/application/services/RedEvidenceClassifier.js.map +1 -0
  70. package/dist/application/services/WorkflowEngineService.d.ts +28 -0
  71. package/dist/application/services/WorkflowEngineService.js +111 -63
  72. package/dist/application/services/WorkflowEngineService.js.map +1 -1
  73. package/dist/application/services/WorkflowValidationService.d.ts +16 -0
  74. package/dist/application/services/WorkflowValidationService.js +39 -34
  75. package/dist/application/services/WorkflowValidationService.js.map +1 -1
  76. package/dist/cli/install-skills.js +0 -0
  77. package/dist/cli/install-target.d.ts +8 -6
  78. package/dist/cli/install-target.js +11 -3
  79. package/dist/cli/install-target.js.map +1 -1
  80. package/dist/cli/tool-support/root-guidance.js +1 -0
  81. package/dist/cli/tool-support/root-guidance.js.map +1 -1
  82. package/dist/cli/tool-support/target-installer.d.ts +1 -0
  83. package/dist/cli/tool-support/target-installer.js +9 -5
  84. package/dist/cli/tool-support/target-installer.js.map +1 -1
  85. package/dist/domain/ports.d.ts +34 -0
  86. package/dist/domain/ports.js +11 -1
  87. package/dist/domain/ports.js.map +1 -1
  88. package/dist/infrastructure/adapters/FetchJevHttpAdapter.d.ts +4 -0
  89. package/dist/infrastructure/adapters/FetchJevHttpAdapter.js +73 -0
  90. package/dist/infrastructure/adapters/FetchJevHttpAdapter.js.map +1 -0
  91. package/dist/infrastructure/adapters/NodeGitAdapter.d.ts +5 -0
  92. package/dist/infrastructure/adapters/NodeGitAdapter.js +31 -0
  93. package/dist/infrastructure/adapters/NodeGitAdapter.js.map +1 -0
  94. package/dist/infrastructure/di/container.js +10 -0
  95. package/dist/infrastructure/di/container.js.map +1 -1
  96. package/dist/infrastructure/di/types.d.ts +4 -0
  97. package/dist/infrastructure/di/types.js +4 -0
  98. package/dist/infrastructure/di/types.js.map +1 -1
  99. package/dist/infrastructure/mcp/sddToolDefinitions.d.ts +1 -1
  100. package/dist/infrastructure/mcp/sddToolDefinitions.js +72 -1
  101. package/dist/infrastructure/mcp/sddToolDefinitions.js.map +1 -1
  102. package/dist/shared/version.d.ts +1 -1
  103. package/dist/shared/version.js +1 -1
  104. package/package.json +1 -1
  105. package/skills/output-clarity-ladder/SKILL.md +43 -0
  106. package/skills/output-clarity-ladder/references/ja.md +30 -0
  107. package/skills/output-clarity-ladder/references/zh-TW.md +30 -0
  108. package/skills/sdd-commit/SKILL.md +4 -3
  109. package/skills/sdd-design/SKILL.md +1 -1
  110. package/skills/sdd-implement/SKILL.md +4 -4
  111. package/skills/sdd-requirements/SKILL.md +6 -6
  112. package/skills/sdd-review/SKILL.md +3 -2
  113. package/skills/sdd-security-check/SKILL.md +3 -2
  114. package/skills/sdd-tasks/REFERENCE.md +4 -0
  115. package/skills/sdd-tasks/SKILL.md +8 -6
  116. package/templates/CLAUDE.md +1 -1
  117. package/templates/codex-AGENTS.md +1 -1
@@ -0,0 +1,310 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { createHash } from 'node:crypto';
14
+ import path from 'node:path';
15
+ import { inject, injectable } from 'inversify';
16
+ import { TYPES } from '../../infrastructure/di/types.js';
17
+ import { isWellFormedBaseRef } from './JevBaseRef.js';
18
+ import { buildRangeManifest, buildReviewManifest } from './JevChangeManifest.js';
19
+ import { JevCommitLookup } from './JevCommitLookup.js';
20
+ import { JevExchange } from './JevExchange.js';
21
+ import { QUESTION_SET_VERSION } from './JevQuestionCatalog.js';
22
+ import { flagDesign, flagRed, flagRequirements, flagTestcases, renderJevLine } from './JevReport.js';
23
+ import { inputHash, JevReviewCheck } from './JevReviewCheck.js';
24
+ import { skippedResult, unavailableResult } from './JevResults.js';
25
+ import { classifyRedEvidence } from './RedEvidenceClassifier.js';
26
+ import { buildDesignExchange, buildRedExchange, buildRequirementsExchange } from './JevSpecState.js';
27
+ import { buildTestcaseExchange } from './JevTestcaseState.js';
28
+ import { JevSidecarStore } from './JevSidecarStore.js';
29
+ import { readProjectJevSetting, resolveJevSettings } from './JevSettings.js';
30
+ import { validateFeatureName } from './SpecPathResolver.js';
31
+ const FEATURE_REQUIRED = new Set(['requirements', 'design', 'testcases', 'red']);
32
+ const sha256 = (value) => createHash('sha256').update(value).digest('hex');
33
+ let JevAdvisoryService = class JevAdvisoryService {
34
+ http;
35
+ git;
36
+ engine;
37
+ fileSystem;
38
+ logger;
39
+ env;
40
+ store;
41
+ exchange;
42
+ review;
43
+ commit;
44
+ constructor(http, git, engine, fileSystem, logger, env) {
45
+ this.http = http;
46
+ this.git = git;
47
+ this.engine = engine;
48
+ this.fileSystem = fileSystem;
49
+ this.logger = logger;
50
+ this.env = env;
51
+ this.store = new JevSidecarStore(fileSystem, logger);
52
+ this.exchange = new JevExchange(http, this.store, logger);
53
+ this.review = new JevReviewCheck(this.exchange);
54
+ this.commit = new JevCommitLookup(fileSystem, git, this.store);
55
+ }
56
+ /** Never rejects: every failure becomes a result value. */
57
+ async check(request) {
58
+ try {
59
+ return await this.run(request);
60
+ }
61
+ catch (error) {
62
+ this.logger.warn('JEV check failed locally', { check: request.check, errorName: error instanceof Error ? error.name : 'Error' });
63
+ return skippedResult(request.check, 'not-ready');
64
+ }
65
+ }
66
+ async run(request) {
67
+ // Gates 1-2 return before any path resolution, lock, git call, or write.
68
+ const settings = await this.resolveSettings(request.projectRoot);
69
+ if (!settings.enabled) {
70
+ return request.check === 'commit' ? skippedResult('commit', 'disabled') : unavailableResult(request.check, 'disabled');
71
+ }
72
+ if (request.check === 'commit')
73
+ return this.commitLookup(request);
74
+ if (!settings.hasKey)
75
+ return unavailableResult(request.check, 'no-key');
76
+ if (!this.baseRefAcceptable(request))
77
+ return skippedResult(request.check, 'invalid-base-ref');
78
+ if (!(await this.featureInScope(request)))
79
+ return skippedResult(request.check, 'feature-not-found');
80
+ if ((request.check === 'security' || request.check === 'principles') && !settings.allowCode) {
81
+ return this.codeDisabled(request);
82
+ }
83
+ return this.dispatch(request, { projectRoot: request.projectRoot, featureName: request.featureName, settings });
84
+ }
85
+ dispatch(request, context) {
86
+ if (request.check === 'requirements' || request.check === 'design')
87
+ return this.specCheck(request, context);
88
+ if (request.check === 'testcases')
89
+ return this.testcasesCheck(request, context);
90
+ if (request.check === 'red')
91
+ return this.redCheck(request, context);
92
+ if (request.check === 'security' || request.check === 'principles')
93
+ return this.review.run(request, context, () => this.manifestFor(request));
94
+ return skippedResult(request.check, 'not-ready');
95
+ }
96
+ /** The commit lookup matches staged diffs only, so a base ref has no meaning there. */
97
+ commitLookup(request) {
98
+ return request.baseRef === undefined ? this.commit.run(request.projectRoot) : skippedResult('commit', 'invalid-base-ref');
99
+ }
100
+ /** No base ref is always fine; one is meaningful only for the code reviews, and only when well formed. */
101
+ baseRefAcceptable(request) {
102
+ if (request.baseRef === undefined)
103
+ return true;
104
+ return (request.check === 'security' || request.check === 'principles') && isWellFormedBaseRef(request.baseRef);
105
+ }
106
+ /** A snapshot of a phase that passed validation and still matches what was recorded; else undefined. */
107
+ async readySnapshot(request, phase) {
108
+ const snapshot = await this.engine.readAdvisorySnapshot({ projectRoot: request.projectRoot, featureName: request.featureName ?? '', phase });
109
+ const ready = snapshot.validationStatus === 'passed'
110
+ && snapshot.recordedSha256 !== undefined && snapshot.recordedSha256 === snapshot.observedSha256;
111
+ return ready ? snapshot : undefined;
112
+ }
113
+ /** A2: classify RED evidence locally; only ambiguous evidence is sent. Never affects record-red. */
114
+ async redCheck(request, context) {
115
+ const { taskNumber, testName, evidence } = request;
116
+ if (!taskNumber || !testName || !evidence || evidence.exitCode === 0)
117
+ return skippedResult('red', 'not-ready');
118
+ const snapshot = await this.engine.readAdvisorySnapshot({ projectRoot: request.projectRoot, featureName: request.featureName ?? '', phase: 'tasks' });
119
+ const task = snapshot.implementation?.tasks[taskNumber];
120
+ if (!task || task.status !== 'in-progress' || !task.tddRequired)
121
+ return skippedResult('red', 'not-ready');
122
+ const binding = {
123
+ questionSetVersion: QUESTION_SET_VERSION,
124
+ evidenceSha256: sha256(JSON.stringify([taskNumber, testName, evidence.command, evidence.summary])),
125
+ };
126
+ const local = classifyRedEvidence(evidence.command, evidence.summary);
127
+ if (local.classification !== 'ambiguous')
128
+ return this.localRed(request, context, binding, local);
129
+ const built = buildRedExchange(taskNumber, testName, evidence, task.acceptanceCriteria);
130
+ if (!built)
131
+ return skippedResult('red', 'not-ready');
132
+ const plan = {
133
+ check: 'red',
134
+ kind: 'red',
135
+ taskNumber,
136
+ binding,
137
+ state: built.state,
138
+ questions: built.questions,
139
+ omittedIds: built.omittedIds,
140
+ truncated: built.truncated,
141
+ redactions: built.redactions,
142
+ interpret: (answers) => {
143
+ const flagged = flagRed(answers).length > 0 ? [taskNumber] : [];
144
+ return { flagged, details: [{ id: taskNumber, flagged: flagged.length > 0 }], extras: { classification: 'ambiguous' } };
145
+ },
146
+ };
147
+ return this.exchange.run(plan, context);
148
+ }
149
+ /** A decisive local result costs nothing: no key use, no request. */
150
+ async localRed(request, context, binding, local) {
151
+ const taskNumber = request.taskNumber ?? '';
152
+ const sidecar = {
153
+ schema: 1,
154
+ kind: 'red',
155
+ createdAt: new Date().toISOString(),
156
+ binding,
157
+ status: 'answered',
158
+ source: 'local',
159
+ meta: { classification: local.classification, ...(local.matchedPattern && { matchedPattern: local.matchedPattern }) },
160
+ truncated: false,
161
+ omittedIds: [],
162
+ droppedFindingIds: [],
163
+ redactions: 0,
164
+ };
165
+ const written = await this.store.write(context.projectRoot, context.featureName, sidecar, taskNumber);
166
+ const flagged = local.classification === 'setup' ? [taskNumber] : [];
167
+ return {
168
+ check: 'red',
169
+ status: 'answered',
170
+ line: renderJevLine({ status: 'answered', flagged }),
171
+ flagged,
172
+ details: [{ id: taskNumber, flagged: flagged.length > 0, note: local.matchedPattern }],
173
+ persisted: written.persisted,
174
+ sidecar: written.path,
175
+ truncated: false,
176
+ redactions: 0,
177
+ classification: local.classification,
178
+ matchedPattern: local.matchedPattern,
179
+ };
180
+ }
181
+ /**
182
+ * A1: judge the planned test cases. The skill first calls without cases to learn whether JEV is active.
183
+ * With no TDD-required task, only the not-applicable reasons are judged, so no cases are needed.
184
+ */
185
+ async testcasesCheck(request, context) {
186
+ const cases = request.cases ?? [];
187
+ const snapshot = await this.readySnapshot(request, 'tasks');
188
+ const built = snapshot && buildTestcaseExchange(snapshot, cases);
189
+ if (!snapshot || !built)
190
+ return skippedResult('testcases', 'not-ready');
191
+ // Without a single case for an existing TDD-required task, every task would be judged on `cases: []`.
192
+ if (built.tddTaskCount > 0 && built.matchedCases === 0)
193
+ return skippedResult('testcases', 'cases-required');
194
+ const plan = {
195
+ check: 'testcases',
196
+ kind: 'testcases',
197
+ binding: {
198
+ questionSetVersion: QUESTION_SET_VERSION,
199
+ revision: snapshot.revision,
200
+ artifactSha256: snapshot.recordedSha256,
201
+ caseListSha256: built.caseListSha256,
202
+ },
203
+ state: built.state,
204
+ questions: built.questions,
205
+ omittedIds: built.omittedIds,
206
+ truncated: built.truncated,
207
+ redactions: built.redactions,
208
+ interpret: (answers) => {
209
+ const flagged = flagTestcases(answers, built.tasks);
210
+ const flaggedFirst = [...flagged, ...built.itemIds.filter((id) => !flagged.includes(id))];
211
+ return {
212
+ flagged,
213
+ details: flaggedFirst.map((id) => ({ id, flagged: flagged.includes(id) })),
214
+ extras: {
215
+ ...(built.unknownTasks.length > 0 && { unknownTasks: built.unknownTasks }),
216
+ ...(built.truncatedTasks.length > 0 && { truncatedTasks: built.truncatedTasks }),
217
+ },
218
+ };
219
+ },
220
+ };
221
+ return this.exchange.run(plan, context);
222
+ }
223
+ /** Requirements and design: one advisory check on a passed, unchanged artifact. */
224
+ async specCheck(request, context) {
225
+ const phase = request.check === 'design' ? 'design' : 'requirements';
226
+ const snapshot = await this.readySnapshot(request, phase);
227
+ const built = snapshot && (phase === 'design' ? buildDesignExchange(snapshot) : buildRequirementsExchange(snapshot));
228
+ if (!snapshot || !built)
229
+ return skippedResult(request.check, 'not-ready');
230
+ const plan = {
231
+ check: request.check,
232
+ kind: phase,
233
+ binding: { questionSetVersion: QUESTION_SET_VERSION, revision: snapshot.revision, artifactSha256: snapshot.recordedSha256 },
234
+ state: built.state,
235
+ questions: built.questions,
236
+ omittedIds: built.omittedIds,
237
+ truncated: built.truncated,
238
+ redactions: built.redactions,
239
+ interpret: (answers) => {
240
+ const flagged = phase === 'design'
241
+ ? flagDesign(answers, built.itemIds, built.secondaryIds)
242
+ : flagRequirements(answers, built.itemIds);
243
+ return { flagged, details: flagged.map((id) => ({ id, flagged: true })) };
244
+ },
245
+ };
246
+ return this.exchange.run(plan, context);
247
+ }
248
+ async resolveSettings(projectRoot) {
249
+ const envDecides = (this.env.SDD_JEV_ENABLED ?? '').trim() !== '';
250
+ const project = envDecides ? undefined : await readProjectJevSetting(projectRoot, this.fileSystem);
251
+ return resolveJevSettings(this.env, project);
252
+ }
253
+ /** Read-only existence check; never creates the feature directory (unlike the lock helper). */
254
+ async featureInScope(request) {
255
+ const { featureName } = request;
256
+ if (featureName === undefined)
257
+ return !FEATURE_REQUIRED.has(request.check);
258
+ try {
259
+ validateFeatureName(featureName);
260
+ }
261
+ catch {
262
+ return false;
263
+ }
264
+ return this.fileSystem.exists(path.join(path.resolve(request.projectRoot), '.spec', 'specs', featureName, 'spec.json'));
265
+ }
266
+ /** The change set to judge: the working tree alone, or the working tree against merge-base(baseRef, HEAD). */
267
+ manifestFor(request) {
268
+ return request.baseRef === undefined
269
+ ? buildReviewManifest(this.git, request.projectRoot)
270
+ : buildRangeManifest(this.git, request.projectRoot, request.baseRef);
271
+ }
272
+ /** Reported whatever the working tree holds (FR-14); a sidecar needs a manifest to bind to. */
273
+ async codeDisabled(request) {
274
+ const result = unavailableResult(request.check, 'code-disabled');
275
+ const manifest = await this.manifestFor(request);
276
+ if (manifest.status === 'invalid-base-ref')
277
+ return skippedResult(request.check, 'invalid-base-ref');
278
+ if (manifest.status !== 'ok')
279
+ return result;
280
+ const kind = request.check === 'principles' ? 'principles' : 'security';
281
+ const sidecar = {
282
+ schema: 1,
283
+ kind,
284
+ createdAt: new Date().toISOString(),
285
+ binding: { questionSetVersion: QUESTION_SET_VERSION, diffSha256: manifest.diffSha256, inputSha256: inputHash(request), ...manifest.range },
286
+ status: 'unavailable',
287
+ reason: 'code-disabled',
288
+ source: 'jev',
289
+ baseCommit: manifest.baseCommit,
290
+ truncated: false,
291
+ omittedIds: [],
292
+ droppedFindingIds: [],
293
+ redactions: 0,
294
+ };
295
+ const written = await this.store.write(request.projectRoot, request.featureName, sidecar);
296
+ return { ...result, persisted: written.persisted, sidecar: written.path };
297
+ }
298
+ };
299
+ JevAdvisoryService = __decorate([
300
+ injectable(),
301
+ __param(0, inject(TYPES.JevHttpPort)),
302
+ __param(1, inject(TYPES.GitPort)),
303
+ __param(2, inject(TYPES.WorkflowEngineService)),
304
+ __param(3, inject(TYPES.FileSystemPort)),
305
+ __param(4, inject(TYPES.LoggerPort)),
306
+ __param(5, inject(TYPES.JevEnvironment)),
307
+ __metadata("design:paramtypes", [Object, Object, Object, Object, Object, Object])
308
+ ], JevAdvisoryService);
309
+ export { JevAdvisoryService };
310
+ //# sourceMappingURL=JevAdvisoryService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JevAdvisoryService.js","sourceRoot":"","sources":["../../../src/application/services/JevAdvisoryService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { GitPort } from '../../domain/ports.js';
2
+ export declare const MAX_BASE_REF_LENGTH = 256;
3
+ /**
4
+ * Strict shape check for a caller-supplied base ref. It runs before any git command, so a value
5
+ * that could be read as an option (leading `-`) or that carries whitespace or control characters
6
+ * never reaches git.
7
+ */
8
+ export declare function isWellFormedBaseRef(value: string): boolean;
9
+ export type ResolvedRange = {
10
+ ok: true;
11
+ rangeBaseCommit: string;
12
+ headCommit: string;
13
+ } | {
14
+ ok: false;
15
+ };
16
+ /**
17
+ * Resolves a well-formed `baseRef` to the merge base with HEAD. The caller's ref appears in exactly
18
+ * one argument vector, after `--end-of-options`; every later command receives only object ids that
19
+ * git itself printed and that matched the object-id shape.
20
+ */
21
+ export declare function resolveRange(git: GitPort, root: string, baseRef: string): Promise<ResolvedRange>;
@@ -0,0 +1,46 @@
1
+ export const MAX_BASE_REF_LENGTH = 256;
2
+ const DEL = 0x7f;
3
+ const LAST_C0_CONTROL = 0x1f;
4
+ const hasControlCharacter = (value) => [...value].some((char) => {
5
+ const code = char.codePointAt(0) ?? 0;
6
+ return code <= LAST_C0_CONTROL || code === DEL;
7
+ });
8
+ /**
9
+ * Strict shape check for a caller-supplied base ref. It runs before any git command, so a value
10
+ * that could be read as an option (leading `-`) or that carries whitespace or control characters
11
+ * never reaches git.
12
+ */
13
+ export function isWellFormedBaseRef(value) {
14
+ return value.length > 0
15
+ && value.length <= MAX_BASE_REF_LENGTH
16
+ && !value.startsWith('-')
17
+ && !/\s/u.test(value)
18
+ && !hasControlCharacter(value);
19
+ }
20
+ /** SHA-1 or SHA-256 object id, as git prints it. */
21
+ const OBJECT_ID = /^[0-9a-f]{40}(?:[0-9a-f]{24})?$/;
22
+ const FAILED = { ok: false };
23
+ /** One read-only git command whose whole output must be a single object id. */
24
+ async function objectId(git, root, args) {
25
+ const result = await git.run(args, root);
26
+ if (!result.ok)
27
+ return undefined;
28
+ const id = result.stdout.toString('utf8').trim();
29
+ return OBJECT_ID.test(id) ? id : undefined;
30
+ }
31
+ /**
32
+ * Resolves a well-formed `baseRef` to the merge base with HEAD. The caller's ref appears in exactly
33
+ * one argument vector, after `--end-of-options`; every later command receives only object ids that
34
+ * git itself printed and that matched the object-id shape.
35
+ */
36
+ export async function resolveRange(git, root, baseRef) {
37
+ const base = await objectId(git, root, ['rev-parse', '--verify', '--quiet', '--end-of-options', `${baseRef}^{commit}`]);
38
+ if (!base)
39
+ return FAILED;
40
+ const head = await objectId(git, root, ['rev-parse', '--verify', '--quiet', 'HEAD']);
41
+ if (!head)
42
+ return FAILED;
43
+ const rangeBaseCommit = await objectId(git, root, ['merge-base', base, head]);
44
+ return rangeBaseCommit ? { ok: true, rangeBaseCommit, headCommit: head } : FAILED;
45
+ }
46
+ //# sourceMappingURL=JevBaseRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JevBaseRef.js","sourceRoot":"","sources":["../../../src/application/services/JevBaseRef.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,MAAM,GAAG,GAAG,IAAI,CAAC;AACjB,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAAW,EAAE,CACrD,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,IAAI,IAAI,eAAe,IAAI,IAAI,KAAK,GAAG,CAAC;AACjD,CAAC,CAAC,CAAC;AAEL;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC;WAClB,KAAK,CAAC,MAAM,IAAI,mBAAmB;WACnC,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;WACtB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;WAClB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAMD,oDAAoD;AACpD,MAAM,SAAS,GAAG,iCAAiC,CAAC;AACpD,MAAM,MAAM,GAAkB,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AAE5C,+EAA+E;AAC/E,KAAK,UAAU,QAAQ,CAAC,GAAY,EAAE,IAAY,EAAE,IAAuB;IACzE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY,EAAE,IAAY,EAAE,OAAe;IAC5E,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,kBAAkB,EAAE,GAAG,OAAO,WAAW,CAAC,CAAC,CAAC;IACxH,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IACzB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACrF,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IACzB,MAAM,eAAe,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9E,OAAO,eAAe,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACpF,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { GitPort } from '../../domain/ports.js';
2
+ export interface ManifestEntry {
3
+ path: string;
4
+ token: string;
5
+ }
6
+ export interface RangeIdentity {
7
+ rangeBaseCommit: string;
8
+ headCommit: string;
9
+ }
10
+ export type ChangeManifest = {
11
+ status: 'ok';
12
+ diffSha256: string;
13
+ baseCommit: string | null;
14
+ entries: ManifestEntry[];
15
+ range?: RangeIdentity;
16
+ } | {
17
+ status: 'empty';
18
+ } | {
19
+ status: 'unavailable';
20
+ };
21
+ export type RangeManifest = ChangeManifest | {
22
+ status: 'invalid-base-ref';
23
+ };
24
+ /** Working-tree changes plus untracked files; compares equal to a full stage of the same content. */
25
+ export declare function buildReviewManifest(git: GitPort, projectRoot: string): Promise<ChangeManifest>;
26
+ /** Staged changes only, hashed with the same definition as the review manifest. */
27
+ export declare function buildStagedManifest(git: GitPort, projectRoot: string): Promise<ChangeManifest>;
28
+ /**
29
+ * Everything that differs between merge-base(baseRef, HEAD) and the working tree: committed,
30
+ * staged, unstaged, and untracked changes, tokenized exactly like the review manifest. `baseRef`
31
+ * must already be well formed; an unresolvable one yields `invalid-base-ref`.
32
+ */
33
+ export declare function buildRangeManifest(git: GitPort, projectRoot: string, baseRef: string): Promise<RangeManifest>;
@@ -0,0 +1,208 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lstat, readlink } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { resolveRange } from './JevBaseRef.js';
5
+ const MAX_PATHS = 2000;
6
+ const HASH_CHUNK = 200;
7
+ const DELETED = 'deleted';
8
+ const UNAVAILABLE = { status: 'unavailable' };
9
+ /** JEV's own sidecars must not influence the hash that binds them. */
10
+ const SIDECAR_PATH = /^\.spec\/(?:reviews\/|specs\/[^/]+\/review\/)/;
11
+ const text = (stdout) => stdout.toString('utf8').split('\0').filter((part) => part.length > 0);
12
+ async function kindOf(root, file) {
13
+ try {
14
+ const info = await lstat(path.join(root, file));
15
+ if (info.isFile())
16
+ return 'file';
17
+ if (info.isSymbolicLink())
18
+ return 'symlink';
19
+ return info.isDirectory() ? 'directory' : 'other';
20
+ }
21
+ catch {
22
+ return 'deleted';
23
+ }
24
+ }
25
+ async function baseCommit(git, root) {
26
+ const result = await git.run(['rev-parse', '--verify', '--quiet', 'HEAD'], root);
27
+ return result.ok ? result.stdout.toString('utf8').trim() || null : null;
28
+ }
29
+ /** The 120000 blob `git add` stores for a symlink: the hash of its link text, not of its target. */
30
+ async function symlinkBlob(git, root, file) {
31
+ const target = await readlink(path.join(root, file), { encoding: 'buffer' });
32
+ const result = await git.run(['hash-object', '--no-filters', '--stdin'], root, target);
33
+ return result.ok ? result.stdout.toString('utf8').trim() || undefined : undefined;
34
+ }
35
+ /**
36
+ * The 160000 gitlink `git add` stores for a submodule or embedded repository: its HEAD commit.
37
+ * Undefined when the directory is not its own repository, has no commit, or its commit is
38
+ * unchanged from the one recorded in `recordedIn` (only its own working tree is dirty, which
39
+ * `git add` cannot stage).
40
+ */
41
+ async function gitlinkCommit(git, root, dir, recordedIn) {
42
+ try {
43
+ await lstat(path.join(root, dir, '.git'));
44
+ }
45
+ catch {
46
+ return undefined;
47
+ }
48
+ const head = await git.run(['rev-parse', '--verify', '--quiet', 'HEAD'], path.join(root, dir));
49
+ const commit = head.ok ? head.stdout.toString('utf8').trim() : '';
50
+ if (!commit)
51
+ return undefined;
52
+ const recorded = await git.run(['ls-tree', '-z', recordedIn, '--', dir], root);
53
+ const match = recorded.ok ? /^160000 commit ([0-9a-f]+)\t/.exec(recorded.stdout.toString('utf8')) : null;
54
+ return match?.[1] === commit ? undefined : commit;
55
+ }
56
+ /** Blob ids for regular working-tree files, exactly as `git add` would store them. */
57
+ async function workingTreeBlobs(git, root, files) {
58
+ const blobs = new Map();
59
+ for (let start = 0; start < files.length; start += HASH_CHUNK) {
60
+ const chunk = files.slice(start, start + HASH_CHUNK);
61
+ const result = await git.run(['hash-object', '--', ...chunk], root);
62
+ if (!result.ok)
63
+ return undefined;
64
+ const ids = result.stdout.toString('utf8').split('\n').filter((line) => line.length > 0);
65
+ if (ids.length !== chunk.length)
66
+ return undefined;
67
+ chunk.forEach((file, index) => blobs.set(file, ids[index]));
68
+ }
69
+ return blobs;
70
+ }
71
+ function finish(entries, base) {
72
+ const kept = entries.filter((entry) => !SIDECAR_PATH.test(entry.path)).sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
73
+ if (kept.length === 0)
74
+ return { status: 'empty' };
75
+ if (kept.length > MAX_PATHS)
76
+ return UNAVAILABLE;
77
+ const manifest = kept.map((entry) => `${entry.path}\0${entry.token}\n`).join('');
78
+ return { status: 'ok', diffSha256: createHash('sha256').update(manifest).digest('hex'), baseCommit: base, entries: kept };
79
+ }
80
+ /**
81
+ * One token per changed path, as `git add` would store it. `recordedIn` is the commit a nested
82
+ * repository's gitlink is compared with: HEAD for working-tree reviews, the merge base for ranges.
83
+ */
84
+ async function tokenEntries(git, root, paths, recordedIn) {
85
+ const present = [];
86
+ const entries = [];
87
+ for (const file of paths) {
88
+ const kind = await kindOf(root, file);
89
+ if (kind === 'file')
90
+ present.push(file);
91
+ else if (kind === 'deleted')
92
+ entries.push({ path: file, token: DELETED });
93
+ else if (kind === 'symlink') {
94
+ const blob = await symlinkBlob(git, root, file);
95
+ if (!blob)
96
+ return undefined;
97
+ entries.push({ path: file, token: blob });
98
+ }
99
+ else if (kind === 'directory') {
100
+ const commit = await gitlinkCommit(git, root, file, recordedIn);
101
+ if (commit)
102
+ entries.push({ path: file, token: commit });
103
+ }
104
+ // Other entry types (sockets, FIFOs) cannot be staged and are skipped.
105
+ }
106
+ const blobs = await workingTreeBlobs(git, root, present);
107
+ if (!blobs)
108
+ return undefined;
109
+ for (const [file, blob] of blobs)
110
+ entries.push({ path: file, token: blob });
111
+ return entries;
112
+ }
113
+ const STATUS_ARGS = ['-c', 'status.renames=false', 'status', '--porcelain=v1', '-z', '--untracked-files=all'];
114
+ // An untracked embedded repository is listed with a trailing slash; `git add` records it without one.
115
+ const statusPath = (record) => record.slice(3).replace(/\/$/, '');
116
+ async function reviewEntries(git, root) {
117
+ const status = await git.run(STATUS_ARGS, root);
118
+ if (!status.ok)
119
+ return undefined;
120
+ return tokenEntries(git, root, text(status.stdout).map(statusPath), 'HEAD');
121
+ }
122
+ /** Every path that differs between the merge base and the working tree, plus untracked files. */
123
+ async function rangeEntries(git, root, range) {
124
+ const diff = await git.run(['diff', '--name-status', '--no-renames', '--no-ext-diff', '-z', range.rangeBaseCommit, '--'], root);
125
+ const status = await git.run(STATUS_ARGS, root);
126
+ if (!diff.ok || !status.ok)
127
+ return undefined;
128
+ const paths = new Set(text(status.stdout).filter((record) => record.startsWith('?? ')).map(statusPath));
129
+ const removed = new Set();
130
+ const parts = text(diff.stdout);
131
+ for (let index = 0; index + 1 < parts.length; index += 2) {
132
+ const file = parts[index + 1];
133
+ // A path the commit tracked and the tree no longer holds is deleted, even if a directory now sits there.
134
+ if (parts[index] === 'D' && !paths.has(file))
135
+ removed.add(file);
136
+ else
137
+ paths.add(file);
138
+ }
139
+ const entries = await tokenEntries(git, root, [...paths], range.rangeBaseCommit);
140
+ return entries && [...[...removed].map((file) => ({ path: file, token: DELETED })), ...entries];
141
+ }
142
+ async function stagedEntries(git, root) {
143
+ const diff = await git.run(['diff', '--cached', '--name-status', '--no-renames', '-z'], root);
144
+ if (!diff.ok)
145
+ return undefined;
146
+ const parts = text(diff.stdout);
147
+ const entries = [];
148
+ const live = [];
149
+ for (let index = 0; index + 1 < parts.length; index += 2) {
150
+ const file = parts[index + 1];
151
+ if (parts[index] === 'D')
152
+ entries.push({ path: file, token: DELETED });
153
+ else
154
+ live.push(file);
155
+ }
156
+ if (live.length > 0) {
157
+ const listing = await git.run(['ls-files', '-s', '-z', '--', ...live], root);
158
+ if (!listing.ok)
159
+ return undefined;
160
+ for (const record of text(listing.stdout)) {
161
+ const match = /^\d+ ([0-9a-f]+) \d\t(.*)$/s.exec(record);
162
+ if (match)
163
+ entries.push({ path: match[2], token: match[1] });
164
+ }
165
+ }
166
+ return entries;
167
+ }
168
+ async function build(git, root, entriesOf) {
169
+ try {
170
+ const entries = await entriesOf(git, root);
171
+ if (!entries)
172
+ return UNAVAILABLE;
173
+ return finish(entries, await baseCommit(git, root));
174
+ }
175
+ catch {
176
+ return UNAVAILABLE;
177
+ }
178
+ }
179
+ /** Working-tree changes plus untracked files; compares equal to a full stage of the same content. */
180
+ export function buildReviewManifest(git, projectRoot) {
181
+ return build(git, projectRoot, reviewEntries);
182
+ }
183
+ /** Staged changes only, hashed with the same definition as the review manifest. */
184
+ export function buildStagedManifest(git, projectRoot) {
185
+ return build(git, projectRoot, stagedEntries);
186
+ }
187
+ /**
188
+ * Everything that differs between merge-base(baseRef, HEAD) and the working tree: committed,
189
+ * staged, unstaged, and untracked changes, tokenized exactly like the review manifest. `baseRef`
190
+ * must already be well formed; an unresolvable one yields `invalid-base-ref`.
191
+ */
192
+ export async function buildRangeManifest(git, projectRoot, baseRef) {
193
+ try {
194
+ const resolved = await resolveRange(git, projectRoot, baseRef);
195
+ if (!resolved.ok)
196
+ return { status: 'invalid-base-ref' };
197
+ const range = { rangeBaseCommit: resolved.rangeBaseCommit, headCommit: resolved.headCommit };
198
+ const entries = await rangeEntries(git, projectRoot, range);
199
+ if (!entries)
200
+ return UNAVAILABLE;
201
+ const manifest = finish(entries, range.headCommit);
202
+ return manifest.status === 'ok' ? { ...manifest, range } : manifest;
203
+ }
204
+ catch {
205
+ return UNAVAILABLE;
206
+ }
207
+ }
208
+ //# sourceMappingURL=JevChangeManifest.js.map