scene-capability-engine 3.6.64 → 3.6.67

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 (125) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +17 -6
  3. package/README.zh.md +18 -6
  4. package/bin/scene-capability-engine.js +4 -0
  5. package/docs/README.md +2 -2
  6. package/docs/command-reference.md +385 -8
  7. package/docs/document-governance.md +3 -2
  8. package/docs/integration-modes.md +62 -478
  9. package/docs/integration-philosophy.md +56 -263
  10. package/docs/magicball-cli-invocation-examples.md +1 -0
  11. package/docs/magicball-project-portfolio-contract.md +125 -4
  12. package/docs/project-management/README.md +14 -0
  13. package/docs/project-management/assurance/backup.md +3 -0
  14. package/docs/project-management/assurance/config.md +3 -0
  15. package/docs/project-management/assurance/evidence/README.md +3 -0
  16. package/docs/project-management/assurance/incidents/README.md +3 -0
  17. package/docs/project-management/assurance/logs.md +3 -0
  18. package/docs/project-management/assurance/overview.md +3 -0
  19. package/docs/project-management/assurance/recovery/README.md +3 -0
  20. package/docs/project-management/assurance/resource.md +3 -0
  21. package/docs/project-management/assurance/runbooks/README.md +3 -0
  22. package/docs/project-management/delivery/acceptance/README.md +3 -0
  23. package/docs/project-management/delivery/acceptance/evidence/README.md +3 -0
  24. package/docs/project-management/delivery/acceptance/exceptions/README.md +3 -0
  25. package/docs/project-management/delivery/acceptance/reports/README.md +3 -0
  26. package/docs/project-management/delivery/documents/changes.md +3 -0
  27. package/docs/project-management/delivery/documents/issues.md +3 -0
  28. package/docs/project-management/delivery/documents/overview.md +3 -0
  29. package/docs/project-management/delivery/documents/planning.md +3 -0
  30. package/docs/project-management/delivery/documents/requirements.md +3 -0
  31. package/docs/project-management/delivery/documents/tracking.md +3 -0
  32. package/docs/project-management/delivery/handoffs/README.md +3 -0
  33. package/docs/project-management/delivery/handoffs/evidence/README.md +3 -0
  34. package/docs/project-management/delivery/handoffs/records/README.md +3 -0
  35. package/docs/project-management/delivery/overview.md +10 -0
  36. package/docs/project-management/delivery/releases/README.md +3 -0
  37. package/docs/project-management/delivery/releases/baselines/README.md +3 -0
  38. package/docs/project-management/delivery/releases/evidence/README.md +3 -0
  39. package/docs/project-management/delivery/tables/changes.md +3 -0
  40. package/docs/project-management/delivery/tables/issues.md +3 -0
  41. package/docs/project-management/delivery/tables/planning.md +3 -0
  42. package/docs/project-management/delivery/tables/requirements.md +3 -0
  43. package/docs/project-management/delivery/tables/tracking.md +3 -0
  44. package/docs/project-management/environment/agent-discovery.md +3 -0
  45. package/docs/project-management/environment/development.md +3 -0
  46. package/docs/project-management/environment/overview.md +10 -0
  47. package/docs/project-management/environment/testing.md +3 -0
  48. package/docs/project-management/environment/version-alignment.md +3 -0
  49. package/docs/quick-start-with-ai-tools.md +68 -308
  50. package/docs/releases/README.md +3 -0
  51. package/docs/releases/v3.6.65.md +25 -0
  52. package/docs/releases/v3.6.66.md +23 -0
  53. package/docs/releases/v3.6.67.md +23 -0
  54. package/docs/steering-governance.md +64 -2
  55. package/docs/zh/README.md +2 -2
  56. package/docs/zh/releases/README.md +3 -0
  57. package/docs/zh/releases/v3.6.65.md +25 -0
  58. package/docs/zh/releases/v3.6.66.md +23 -0
  59. package/docs/zh/releases/v3.6.67.md +23 -0
  60. package/lib/commands/adopt.js +24 -0
  61. package/lib/commands/native.js +158 -0
  62. package/lib/commands/project.js +96 -0
  63. package/lib/commands/semantic.js +1459 -0
  64. package/lib/commands/session.js +74 -3
  65. package/lib/commands/spec-bootstrap.js +10 -1
  66. package/lib/commands/spec-gate.js +10 -1
  67. package/lib/commands/spec-pipeline.js +10 -1
  68. package/lib/commands/studio.js +405 -30
  69. package/lib/commands/task.js +141 -7
  70. package/lib/governance/supreme-principles.js +530 -0
  71. package/lib/problem/problem-evaluator.js +4 -0
  72. package/lib/project/candidate-inspection-service.js +24 -1
  73. package/lib/project/portfolio-projection-service.js +315 -5
  74. package/lib/project/project-channel-output.js +94 -0
  75. package/lib/project/project-channel-projection.js +181 -0
  76. package/lib/project/root-onboarding-service.js +107 -7
  77. package/lib/project/semantic-shared-source-projection.js +150 -0
  78. package/lib/project/supervision-action-model.js +277 -0
  79. package/lib/project/supervision-projection-service.js +305 -5
  80. package/lib/project/target-resolution-service.js +70 -5
  81. package/lib/project/visibility-policy.js +93 -0
  82. package/lib/runtime/multi-spec-scene-session.js +8 -1
  83. package/lib/runtime/project-channel-context-store.js +387 -0
  84. package/lib/runtime/project-channel-context.js +406 -0
  85. package/lib/runtime/scene-session-binding.js +46 -0
  86. package/lib/runtime/session-store.js +186 -0
  87. package/lib/runtime/steering-contract.js +7 -1
  88. package/lib/semantic/archive-report.js +283 -0
  89. package/lib/semantic/archive-routing.js +67 -0
  90. package/lib/semantic/backflow-report.js +245 -0
  91. package/lib/semantic/capability-contract.js +30 -0
  92. package/lib/semantic/delta-export.js +145 -0
  93. package/lib/semantic/interaction-observer.js +254 -0
  94. package/lib/semantic/kernel-loader.js +881 -0
  95. package/lib/semantic/native-runtime.js +359 -0
  96. package/lib/semantic/progress-ledger.js +433 -0
  97. package/lib/semantic/replay-evaluator.js +382 -0
  98. package/lib/semantic/shared-publication.js +592 -0
  99. package/lib/semantic/shared-source-config.js +183 -0
  100. package/lib/semantic/shared-source-connect.js +139 -0
  101. package/lib/semantic/shared-source-discovery.js +98 -0
  102. package/lib/semantic/shared-sync-export.js +413 -0
  103. package/lib/semantic/shared-sync-intake.js +592 -0
  104. package/lib/semantic/shared-sync-merge.js +547 -0
  105. package/lib/semantic/shared-sync-release.js +463 -0
  106. package/lib/semantic/supreme-intent-report.js +300 -0
  107. package/lib/state/sce-state-store.js +1360 -0
  108. package/lib/steering/context-sync-manager.js +276 -25
  109. package/lib/studio/spec-intake-governor.js +39 -3
  110. package/lib/studio/task-envelope.js +35 -2
  111. package/lib/workspace/takeover-baseline.js +342 -83
  112. package/package.json +7 -2
  113. package/scripts/agent-governance-baseline-audit.js +395 -0
  114. package/scripts/clarification-first-audit.js +9 -9
  115. package/scripts/deprecated-entry-audit.js +240 -0
  116. package/scripts/release-doc-version-audit.js +24 -0
  117. package/scripts/release-posture-report.js +262 -0
  118. package/template/.sce/README.md +62 -228
  119. package/template/.sce/config/semantic-shared-sources.json +5 -0
  120. package/template/.sce/config/supreme-principles-policy.json +105 -0
  121. package/template/.sce/config/takeover-baseline.json +7 -0
  122. package/template/.sce/steering/CORE_PRINCIPLES.md +23 -63
  123. package/template/.sce/steering/CURRENT_CONTEXT.md +4 -0
  124. package/template/.sce/steering/RULES_GUIDE.md +17 -9
  125. package/template/README.md +32 -96
@@ -0,0 +1,463 @@
1
+ const path = require('path');
2
+ const http = require('http');
3
+ const https = require('https');
4
+ const fs = require('fs-extra');
5
+ const {
6
+ SEMANTIC_SHARED_SYNC_BUNDLE_API_VERSION,
7
+ SEMANTIC_SHARED_SYNC_INDEX_API_VERSION,
8
+ SEMANTIC_SHARED_SYNC_SHARD_API_VERSION
9
+ } = require('./shared-sync-export');
10
+
11
+ const SEMANTIC_SHARED_SYNC_RELEASE_RECEIPT_API_VERSION = 'sce.semantic.shared-sync.release-receipt/v0.1';
12
+ const SEMANTIC_SHARED_SOURCE_DESCRIPTOR_API_VERSION = 'sce.semantic.shared-source-descriptor/v0.1';
13
+
14
+ function normalizeString(value) {
15
+ if (typeof value !== 'string') {
16
+ return '';
17
+ }
18
+ return value.trim();
19
+ }
20
+
21
+ function normalizeInteger(value, fallback = 0) {
22
+ const parsed = Number.parseInt(`${value}`, 10);
23
+ if (!Number.isFinite(parsed) || parsed <= 0) {
24
+ return fallback;
25
+ }
26
+ return parsed;
27
+ }
28
+
29
+ function normalizeBoolean(value, fallback = false) {
30
+ if (typeof value === 'boolean') {
31
+ return value;
32
+ }
33
+ const normalized = normalizeString(`${value || ''}`).toLowerCase();
34
+ if (!normalized) {
35
+ return fallback;
36
+ }
37
+ if (['1', 'true', 'yes', 'y', 'on'].includes(normalized)) {
38
+ return true;
39
+ }
40
+ if (['0', 'false', 'no', 'n', 'off'].includes(normalized)) {
41
+ return false;
42
+ }
43
+ return fallback;
44
+ }
45
+
46
+ function isObject(value) {
47
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
48
+ }
49
+
50
+ function isHttpSource(source = '') {
51
+ return /^https?:\/\//i.test(normalizeString(source));
52
+ }
53
+
54
+ function inferSourceRootFromSource(source = '') {
55
+ const normalized = normalizeString(source);
56
+ if (!normalized) {
57
+ return '';
58
+ }
59
+ if (isHttpSource(normalized)) {
60
+ const sceMarkerIndex = normalized.indexOf('/.sce/');
61
+ if (sceMarkerIndex > 0) {
62
+ return normalized.slice(0, sceMarkerIndex);
63
+ }
64
+ return normalizeString(normalized.replace(/\/[^/]*$/, ''));
65
+ }
66
+ const normalizedPath = path.resolve(normalized);
67
+ const marker = `${path.sep}.sce${path.sep}`;
68
+ const markerIndex = normalizedPath.indexOf(marker);
69
+ if (markerIndex > -1) {
70
+ return normalizedPath.slice(0, markerIndex);
71
+ }
72
+ return path.dirname(normalizedPath);
73
+ }
74
+
75
+ function toProjectRelative(projectPath, targetPath) {
76
+ return path.relative(projectPath, targetPath).replace(/\\/g, '/');
77
+ }
78
+
79
+ function resolveDefaultSemanticSharedPublishedBaseDir(specId = '') {
80
+ const normalizedSpecId = normalizeString(specId);
81
+ if (!normalizedSpecId) {
82
+ return '';
83
+ }
84
+ return `.sce/specs/${normalizedSpecId}/registry/semantic-shared/published`;
85
+ }
86
+
87
+ function resolveDefaultSemanticSharedPublishedBundleOutFile(specId = '') {
88
+ const baseDir = resolveDefaultSemanticSharedPublishedBaseDir(specId);
89
+ return baseDir ? `${baseDir}/latest.bundle.json` : '';
90
+ }
91
+
92
+ function resolveDefaultSemanticSharedPublishedIndexOutFile(specId = '') {
93
+ const baseDir = resolveDefaultSemanticSharedPublishedBaseDir(specId);
94
+ return baseDir ? `${baseDir}/latest.index.json` : '';
95
+ }
96
+
97
+ function resolveDefaultSemanticSharedPublishedReceiptOutFile(specId = '') {
98
+ const baseDir = resolveDefaultSemanticSharedPublishedBaseDir(specId);
99
+ return baseDir ? `${baseDir}/latest.receipt.json` : '';
100
+ }
101
+
102
+ function resolveDefaultSemanticSharedPublishedSourceDescriptorOutFile(specId = '') {
103
+ const baseDir = resolveDefaultSemanticSharedPublishedBaseDir(specId);
104
+ return baseDir ? `${baseDir}/source-descriptor.json` : '';
105
+ }
106
+
107
+ function resolveDefaultSemanticSharedPublishedShardOutFile(specId = '', targetLibrary = '') {
108
+ const baseDir = resolveDefaultSemanticSharedPublishedBaseDir(specId);
109
+ const normalizedLibrary = normalizeString(targetLibrary);
110
+ return baseDir && normalizedLibrary
111
+ ? `${baseDir}/shards/${normalizedLibrary}.json`
112
+ : '';
113
+ }
114
+
115
+ function fetchJsonFromHttp(source, timeoutMs = 15000) {
116
+ const normalized = normalizeString(source);
117
+ if (!normalized) {
118
+ return Promise.reject(new Error('shared release source is required'));
119
+ }
120
+ const client = normalized.startsWith('https://') ? https : http;
121
+ return new Promise((resolve, reject) => {
122
+ const request = client.get(normalized, {
123
+ timeout: timeoutMs,
124
+ headers: {
125
+ Accept: 'application/json'
126
+ }
127
+ }, (response) => {
128
+ const chunks = [];
129
+ response.on('data', (chunk) => chunks.push(chunk));
130
+ response.on('end', () => {
131
+ const body = Buffer.concat(chunks).toString('utf8');
132
+ if (response.statusCode < 200 || response.statusCode >= 300) {
133
+ reject(new Error(`shared release source responded ${response.statusCode}`));
134
+ return;
135
+ }
136
+ try {
137
+ resolve(JSON.parse(body));
138
+ } catch (error) {
139
+ reject(new Error(`shared release source returned invalid JSON: ${error.message}`));
140
+ }
141
+ });
142
+ });
143
+ request.on('timeout', () => {
144
+ request.destroy(new Error('shared release source request timed out'));
145
+ });
146
+ request.on('error', reject);
147
+ });
148
+ }
149
+
150
+ async function loadJsonSource(projectPath, source, fileSystem = fs) {
151
+ const normalized = normalizeString(source);
152
+ if (!normalized) {
153
+ throw new Error('shared release source is required');
154
+ }
155
+ if (isHttpSource(normalized)) {
156
+ return fetchJsonFromHttp(normalized);
157
+ }
158
+ const absolutePath = path.isAbsolute(normalized)
159
+ ? normalized
160
+ : path.resolve(projectPath, normalized);
161
+ if (!await fileSystem.pathExists(absolutePath)) {
162
+ throw new Error(`shared release source file not found: ${source}`);
163
+ }
164
+ return fileSystem.readJson(absolutePath);
165
+ }
166
+
167
+ function resolveCandidateShardSource(projectPath, bundleSource, shardFile) {
168
+ const normalizedShardFile = normalizeString(shardFile);
169
+ if (!normalizedShardFile) {
170
+ return '';
171
+ }
172
+ if (isHttpSource(normalizedShardFile) || path.isAbsolute(normalizedShardFile)) {
173
+ return normalizedShardFile;
174
+ }
175
+ if (/^\.sce[\\/]/i.test(normalizedShardFile)) {
176
+ const sourceRoot = inferSourceRootFromSource(path.isAbsolute(bundleSource) ? bundleSource : path.resolve(projectPath, bundleSource));
177
+ if (isHttpSource(sourceRoot)) {
178
+ return `${sourceRoot.replace(/\/+$/, '')}/${normalizedShardFile.replace(/^\/+/, '')}`;
179
+ }
180
+ if (sourceRoot) {
181
+ return path.resolve(sourceRoot, normalizedShardFile);
182
+ }
183
+ return path.resolve(projectPath, normalizedShardFile);
184
+ }
185
+ if (isHttpSource(bundleSource)) {
186
+ return new URL(normalizedShardFile, bundleSource).toString();
187
+ }
188
+ const bundleDir = path.dirname(path.isAbsolute(bundleSource) ? bundleSource : path.resolve(projectPath, bundleSource));
189
+ return path.resolve(bundleDir, normalizedShardFile);
190
+ }
191
+
192
+ function assessApprovedCentralEntryGate(entry = {}) {
193
+ const publication = isObject(entry.publication) ? entry.publication : {};
194
+ const publishState = normalizeString(publication.publish_state);
195
+ const blockedReason = normalizeString(publication.blocked_reason);
196
+ const blockedGate = isObject(publication.blocked_gate) ? publication.blocked_gate : null;
197
+ const reasons = [];
198
+
199
+ if (publishState && publishState !== 'published-shared') {
200
+ reasons.push({
201
+ reason: 'entry-not-shared-ready',
202
+ publish_state: publishState
203
+ });
204
+ }
205
+ if (blockedReason) {
206
+ reasons.push({
207
+ reason: 'entry-has-blocked-reason',
208
+ blocked_reason: blockedReason
209
+ });
210
+ }
211
+ if (blockedGate) {
212
+ reasons.push({
213
+ reason: 'entry-has-blocked-gate',
214
+ blocked_gate: blockedGate
215
+ });
216
+ }
217
+
218
+ return {
219
+ allowed: reasons.length === 0,
220
+ reasons
221
+ };
222
+ }
223
+
224
+ async function publishSemanticSharedRegistry(options = {}, dependencies = {}) {
225
+ const projectPath = dependencies.projectPath || process.cwd();
226
+ const fileSystem = dependencies.fileSystem || fs;
227
+ const specId = normalizeString(options.spec);
228
+ const inputFile = normalizeString(options.inputFile || options.input_file)
229
+ || (specId ? `.sce/specs/${specId}/registry/semantic-shared/latest.bundle.json` : '');
230
+ if (!inputFile) {
231
+ throw new Error('candidate bundle source is required (use --input-file or provide --spec)');
232
+ }
233
+
234
+ const candidateBundle = await loadJsonSource(projectPath, inputFile, fileSystem);
235
+ if (!isObject(candidateBundle) || normalizeString(candidateBundle.api_version) !== SEMANTIC_SHARED_SYNC_BUNDLE_API_VERSION) {
236
+ throw new Error(`invalid semantic shared candidate bundle: ${inputFile}`);
237
+ }
238
+
239
+ const minSources = normalizeInteger(options.minSources || options.min_sources, 1);
240
+ const minEntries = normalizeInteger(options.minEntries || options.min_entries, 1);
241
+ const requireZeroBlocked = normalizeBoolean(options.requireZeroBlocked ?? options.require_zero_blocked, true);
242
+ const generatedAt = new Date().toISOString();
243
+ const blocked = [];
244
+
245
+ const totals = isObject(candidateBundle.totals) ? candidateBundle.totals : {};
246
+ const sourceReports = Array.isArray(candidateBundle.sources) ? candidateBundle.sources : [];
247
+ const libraries = Array.isArray(candidateBundle.libraries) ? candidateBundle.libraries : [];
248
+
249
+ if (sourceReports.length < minSources) {
250
+ blocked.push({
251
+ reason: 'insufficient-sources',
252
+ required_sources: minSources,
253
+ actual_sources: sourceReports.length
254
+ });
255
+ }
256
+ if (normalizeInteger(totals.merged_entries, 0) < minEntries) {
257
+ blocked.push({
258
+ reason: 'insufficient-merged-entries',
259
+ required_entries: minEntries,
260
+ actual_entries: normalizeInteger(totals.merged_entries, 0)
261
+ });
262
+ }
263
+ if (requireZeroBlocked && normalizeInteger(totals.blocked, 0) > 0) {
264
+ blocked.push({
265
+ reason: 'candidate-has-blocked-entries',
266
+ blocked_entries: normalizeInteger(totals.blocked, 0)
267
+ });
268
+ }
269
+
270
+ const publishedLibraries = [];
271
+ const publishedIndexShards = {};
272
+ for (const library of libraries) {
273
+ const targetLibrary = normalizeString(library && library.target_library);
274
+ const publishedShardFile = resolveDefaultSemanticSharedPublishedShardOutFile(specId, targetLibrary);
275
+ const candidateShardSource = resolveCandidateShardSource(projectPath, inputFile, normalizeString(library && library.shard_file));
276
+ let shardPayload = {
277
+ api_version: SEMANTIC_SHARED_SYNC_SHARD_API_VERSION,
278
+ generated_at: generatedAt,
279
+ target_library: targetLibrary,
280
+ total_entries: 0,
281
+ entries: []
282
+ };
283
+ if (candidateShardSource) {
284
+ const loadedShard = await loadJsonSource(projectPath, candidateShardSource, fileSystem);
285
+ if (isObject(loadedShard) && normalizeString(loadedShard.api_version) === SEMANTIC_SHARED_SYNC_SHARD_API_VERSION) {
286
+ const shardEntries = Array.isArray(loadedShard.entries) ? loadedShard.entries : [];
287
+ const shardBlockedEntries = [];
288
+ for (const entry of shardEntries) {
289
+ const gate = assessApprovedCentralEntryGate(entry);
290
+ if (!gate.allowed) {
291
+ shardBlockedEntries.push({
292
+ capability_id: normalizeString(entry && entry.capability_id) || null,
293
+ lesson_id: normalizeString(entry && entry.lesson_id) || null,
294
+ target_library: targetLibrary || normalizeString(entry && entry.target_library) || null,
295
+ reason: 'entry-failed-approved-central-gate',
296
+ gate
297
+ });
298
+ }
299
+ }
300
+ if (shardBlockedEntries.length > 0) {
301
+ blocked.push(...shardBlockedEntries);
302
+ }
303
+ shardPayload = {
304
+ ...loadedShard,
305
+ generated_at: generatedAt,
306
+ publication: {
307
+ publish_state: blocked.length === 0 ? 'approved-central' : 'publish-blocked',
308
+ source_bundle: inputFile
309
+ }
310
+ };
311
+ }
312
+ }
313
+ if (publishedShardFile) {
314
+ const absoluteShardPath = path.join(projectPath, publishedShardFile);
315
+ await fileSystem.ensureDir(path.dirname(absoluteShardPath));
316
+ await fileSystem.writeJson(absoluteShardPath, shardPayload, { spaces: 2 });
317
+ }
318
+ publishedLibraries.push({
319
+ target_library: targetLibrary,
320
+ shard_file: publishedShardFile || null,
321
+ entry_count: normalizeInteger(shardPayload.total_entries, 0),
322
+ latest_published_at: normalizeString(library && library.latest_published_at) || null
323
+ });
324
+ publishedIndexShards[targetLibrary] = {
325
+ shard_file: publishedShardFile || null,
326
+ entry_count: normalizeInteger(shardPayload.total_entries, 0),
327
+ latest_published_at: normalizeString(library && library.latest_published_at) || null
328
+ };
329
+ }
330
+
331
+ const success = blocked.length === 0;
332
+ const bundlePayload = {
333
+ api_version: SEMANTIC_SHARED_SYNC_BUNDLE_API_VERSION,
334
+ mode: 'semantic-publish-shared-registry',
335
+ success,
336
+ generated_at: generatedAt,
337
+ spec_id: specId || normalizeString(candidateBundle.spec_id) || null,
338
+ mirror_root: normalizeString(candidateBundle.mirror_root) || '.sce/knowledge/semantic-shared',
339
+ governance: {
340
+ release_state: success ? 'approved-central' : 'publish-blocked',
341
+ candidate_bundle: normalizeString(inputFile),
342
+ min_sources: minSources,
343
+ min_entries: minEntries,
344
+ require_zero_blocked: requireZeroBlocked
345
+ },
346
+ totals: {
347
+ sources: sourceReports.length,
348
+ merged_entries: normalizeInteger(totals.merged_entries, 0),
349
+ superseded: normalizeInteger(totals.superseded, 0),
350
+ blocked: blocked.length
351
+ },
352
+ sources: sourceReports,
353
+ libraries: publishedLibraries,
354
+ blocked
355
+ };
356
+
357
+ const bundleOutFile = normalizeString(options.outFile || options.out_file)
358
+ || resolveDefaultSemanticSharedPublishedBundleOutFile(specId);
359
+ const indexOutFile = normalizeString(options.indexFile || options.index_file)
360
+ || resolveDefaultSemanticSharedPublishedIndexOutFile(specId);
361
+ const receiptOutFile = normalizeString(options.receiptFile || options.receipt_file)
362
+ || resolveDefaultSemanticSharedPublishedReceiptOutFile(specId);
363
+ const sourceDescriptorOutFile = normalizeString(options.sourceDescriptorFile || options.source_descriptor_file)
364
+ || resolveDefaultSemanticSharedPublishedSourceDescriptorOutFile(specId);
365
+ const sourceName = normalizeString(options.sourceName || options.source_name) || 'central';
366
+ const publicBundle = normalizeString(options.publicBundle || options.public_bundle);
367
+ const publicRoot = normalizeString(options.publicRoot || options.public_root);
368
+
369
+ const indexPayload = {
370
+ api_version: SEMANTIC_SHARED_SYNC_INDEX_API_VERSION,
371
+ generated_at: generatedAt,
372
+ spec_id: specId || normalizeString(candidateBundle.spec_id) || null,
373
+ bundle_file: bundleOutFile || null,
374
+ shard_count: publishedLibraries.length,
375
+ shards: publishedIndexShards
376
+ };
377
+
378
+ const receiptPayload = {
379
+ api_version: SEMANTIC_SHARED_SYNC_RELEASE_RECEIPT_API_VERSION,
380
+ mode: 'semantic-publish-shared-registry',
381
+ success,
382
+ generated_at: generatedAt,
383
+ spec_id: specId || normalizeString(candidateBundle.spec_id) || null,
384
+ candidate_bundle: normalizeString(inputFile),
385
+ governance: bundlePayload.governance,
386
+ totals: bundlePayload.totals,
387
+ libraries: publishedLibraries,
388
+ blocked
389
+ };
390
+
391
+ let absoluteBundlePath = '';
392
+ if (bundleOutFile) {
393
+ absoluteBundlePath = path.isAbsolute(bundleOutFile)
394
+ ? bundleOutFile
395
+ : path.join(projectPath, bundleOutFile);
396
+ await fileSystem.ensureDir(path.dirname(absoluteBundlePath));
397
+ await fileSystem.writeJson(absoluteBundlePath, bundlePayload, { spaces: 2 });
398
+ bundlePayload.out_file = toProjectRelative(projectPath, absoluteBundlePath);
399
+ }
400
+ if (indexOutFile) {
401
+ const absoluteIndexPath = path.isAbsolute(indexOutFile)
402
+ ? indexOutFile
403
+ : path.join(projectPath, indexOutFile);
404
+ await fileSystem.ensureDir(path.dirname(absoluteIndexPath));
405
+ await fileSystem.writeJson(absoluteIndexPath, indexPayload, { spaces: 2 });
406
+ }
407
+ if (receiptOutFile) {
408
+ const absoluteReceiptPath = path.isAbsolute(receiptOutFile)
409
+ ? receiptOutFile
410
+ : path.join(projectPath, receiptOutFile);
411
+ await fileSystem.ensureDir(path.dirname(absoluteReceiptPath));
412
+ await fileSystem.writeJson(absoluteReceiptPath, receiptPayload, { spaces: 2 });
413
+ }
414
+
415
+ let sourceDescriptor = null;
416
+ if (sourceDescriptorOutFile) {
417
+ const absoluteDescriptorPath = path.isAbsolute(sourceDescriptorOutFile)
418
+ ? sourceDescriptorOutFile
419
+ : path.join(projectPath, sourceDescriptorOutFile);
420
+ const sourceBundle = publicBundle || absoluteBundlePath || bundlePayload.out_file || bundleOutFile || null;
421
+ const inferredRoot = publicRoot || inferSourceRootFromSource(sourceBundle || '');
422
+ sourceDescriptor = {
423
+ api_version: SEMANTIC_SHARED_SOURCE_DESCRIPTOR_API_VERSION,
424
+ mode: 'semantic-shared-source-descriptor',
425
+ generated_at: generatedAt,
426
+ spec_id: specId || normalizeString(candidateBundle.spec_id) || null,
427
+ source: {
428
+ name: sourceName,
429
+ enabled: true,
430
+ bundle: sourceBundle,
431
+ root: inferredRoot || null,
432
+ required_release_state: success ? 'approved-central' : 'publish-blocked'
433
+ },
434
+ publication: {
435
+ release_state: bundlePayload.governance.release_state,
436
+ bundle_file: bundlePayload.out_file || bundleOutFile || null,
437
+ receipt_file: receiptOutFile || null
438
+ }
439
+ };
440
+ await fileSystem.ensureDir(path.dirname(absoluteDescriptorPath));
441
+ await fileSystem.writeJson(absoluteDescriptorPath, sourceDescriptor, { spaces: 2 });
442
+ }
443
+
444
+ return {
445
+ ...receiptPayload,
446
+ out_file: bundlePayload.out_file || bundleOutFile || null,
447
+ index_file: indexOutFile || null,
448
+ receipt_file: receiptOutFile || null,
449
+ source_descriptor_file: sourceDescriptorOutFile || null,
450
+ source_descriptor: sourceDescriptor
451
+ };
452
+ }
453
+
454
+ module.exports = {
455
+ SEMANTIC_SHARED_SYNC_RELEASE_RECEIPT_API_VERSION,
456
+ SEMANTIC_SHARED_SOURCE_DESCRIPTOR_API_VERSION,
457
+ resolveDefaultSemanticSharedPublishedBundleOutFile,
458
+ resolveDefaultSemanticSharedPublishedIndexOutFile,
459
+ resolveDefaultSemanticSharedPublishedReceiptOutFile,
460
+ resolveDefaultSemanticSharedPublishedSourceDescriptorOutFile,
461
+ resolveDefaultSemanticSharedPublishedShardOutFile,
462
+ publishSemanticSharedRegistry
463
+ };