scene-capability-engine 3.6.32 → 3.6.36

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 (83) hide show
  1. package/CHANGELOG.md +86 -1
  2. package/README.md +119 -122
  3. package/README.zh.md +123 -121
  4. package/bin/scene-capability-engine.js +11 -0
  5. package/docs/README.md +21 -32
  6. package/docs/auto-refactor-index.md +384 -0
  7. package/docs/command-reference.md +94 -2
  8. package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
  9. package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
  10. package/docs/magicball-capability-iteration-api.md +2 -0
  11. package/docs/magicball-capability-iteration-ui.md +2 -0
  12. package/docs/magicball-capability-library.md +2 -0
  13. package/docs/magicball-cli-invocation-examples.md +336 -0
  14. package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
  15. package/docs/magicball-integration-doc-index.md +137 -0
  16. package/docs/magicball-integration-issue-tracker.md +218 -0
  17. package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
  18. package/docs/magicball-sce-adaptation-guide.md +203 -0
  19. package/docs/magicball-three-mode-alignment-plan.md +551 -0
  20. package/docs/magicball-ui-surface-checklist.md +126 -0
  21. package/docs/magicball-write-auth-adaptation-guide.md +328 -0
  22. package/docs/refactor-completion-roadmap.md +116 -0
  23. package/docs/zh/README.md +27 -30
  24. package/docs/zh/refactor-completion-roadmap.md +116 -0
  25. package/lib/app/registry-config.js +73 -0
  26. package/lib/app/registry-sync-service.js +228 -0
  27. package/lib/auto/archive-schema-service.js +276 -0
  28. package/lib/auto/archive-summary.js +60 -0
  29. package/lib/auto/batch-goal-input-service.js +543 -0
  30. package/lib/auto/batch-output.js +201 -0
  31. package/lib/auto/batch-summary-storage-service.js +110 -0
  32. package/lib/auto/close-loop-batch-service.js +116 -0
  33. package/lib/auto/close-loop-controller-service.js +287 -0
  34. package/lib/auto/close-loop-program-service.js +283 -0
  35. package/lib/auto/close-loop-recovery-service.js +191 -0
  36. package/lib/auto/close-loop-session-storage-service.js +50 -0
  37. package/lib/auto/controller-lock-service.js +55 -0
  38. package/lib/auto/controller-output.js +32 -0
  39. package/lib/auto/controller-queue-service.js +127 -0
  40. package/lib/auto/controller-session-storage-service.js +105 -0
  41. package/lib/auto/governance-advisory-service.js +208 -0
  42. package/lib/auto/governance-close-loop-service.js +411 -0
  43. package/lib/auto/governance-maintenance-presenter.js +162 -0
  44. package/lib/auto/governance-maintenance-service.js +112 -0
  45. package/lib/auto/governance-session-presenter.js +70 -0
  46. package/lib/auto/governance-session-storage-service.js +198 -0
  47. package/lib/auto/governance-signals.js +139 -0
  48. package/lib/auto/governance-stats-presenter.js +337 -0
  49. package/lib/auto/governance-stats-service.js +115 -0
  50. package/lib/auto/governance-summary.js +703 -0
  51. package/lib/auto/handoff-capability-matrix-service.js +281 -0
  52. package/lib/auto/handoff-evidence-review-service.js +251 -0
  53. package/lib/auto/handoff-release-evidence-service.js +190 -0
  54. package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
  55. package/lib/auto/handoff-release-gate-history-service.js +257 -0
  56. package/lib/auto/handoff-reporting-service.js +1407 -0
  57. package/lib/auto/handoff-run-service.js +486 -0
  58. package/lib/auto/handoff-snapshots-service.js +645 -0
  59. package/lib/auto/observability-service.js +132 -0
  60. package/lib/auto/output-writer.js +34 -0
  61. package/lib/auto/program-auto-remediation-service.js +130 -0
  62. package/lib/auto/program-diagnostics.js +138 -0
  63. package/lib/auto/program-governance-helpers.js +306 -0
  64. package/lib/auto/program-governance-loop-service.js +413 -0
  65. package/lib/auto/program-output.js +106 -0
  66. package/lib/auto/program-summary.js +183 -0
  67. package/lib/auto/recovery-memory-service.js +684 -0
  68. package/lib/auto/recovery-selection-service.js +52 -0
  69. package/lib/auto/retention-policy.js +98 -0
  70. package/lib/auto/session-persistence-service.js +106 -0
  71. package/lib/auto/session-presenter.js +105 -0
  72. package/lib/auto/session-prune-service.js +190 -0
  73. package/lib/auto/session-query-service.js +249 -0
  74. package/lib/auto/spec-protection.js +141 -0
  75. package/lib/commands/app.js +911 -0
  76. package/lib/commands/assurance.js +212 -0
  77. package/lib/commands/auto.js +1091 -11063
  78. package/lib/commands/mode.js +321 -0
  79. package/lib/commands/ontology.js +415 -0
  80. package/lib/commands/pm.js +422 -0
  81. package/lib/ontology/seed-profiles.js +160 -0
  82. package/lib/state/sce-state-store.js +3369 -1200
  83. package/package.json +1 -1
@@ -0,0 +1,321 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs-extra');
3
+ const { getSceStateStore } = require('../state/sce-state-store');
4
+ const { resolveOntologySeedProfile, listOntologySeedProfiles } = require('../ontology/seed-profiles');
5
+
6
+ function normalizeString(value) {
7
+ if (typeof value !== 'string') {
8
+ return '';
9
+ }
10
+ return value.trim();
11
+ }
12
+
13
+ function createStore(dependencies = {}) {
14
+ const projectPath = dependencies.projectPath || process.cwd();
15
+ const fileSystem = dependencies.fileSystem || fs;
16
+ const env = dependencies.env || process.env;
17
+ return dependencies.stateStore || getSceStateStore(projectPath, {
18
+ fileSystem,
19
+ env
20
+ });
21
+ }
22
+
23
+ function normalizePositiveInteger(value, fallback = 5, max = 3600) {
24
+ const parsed = Number.parseInt(`${value}`, 10);
25
+ if (!Number.isFinite(parsed) || parsed <= 0) {
26
+ return fallback;
27
+ }
28
+ return Math.min(parsed, max);
29
+ }
30
+
31
+ function isFreshProjectionCache(cacheRecord, ttlSeconds) {
32
+ const generatedAt = cacheRecord && cacheRecord.generated_at ? Date.parse(cacheRecord.generated_at) : NaN;
33
+ if (!Number.isFinite(generatedAt)) {
34
+ return false;
35
+ }
36
+ const maxAgeMs = normalizePositiveInteger(ttlSeconds, 5, 3600) * 1000;
37
+ return (Date.now() - generatedAt) <= maxAgeMs;
38
+ }
39
+
40
+ async function buildApplicationHome(graph = {}, dependencies = {}) {
41
+ const bundle = graph.bundle || {};
42
+ const runtimeRelease = graph.runtime_release || {};
43
+ const sceneBindings = Array.isArray(graph.scene_bindings) ? graph.scene_bindings : [];
44
+ const metadata = bundle.metadata && typeof bundle.metadata === 'object' ? bundle.metadata : {};
45
+ const installation = metadata.runtime_installation && typeof metadata.runtime_installation === 'object'
46
+ ? metadata.runtime_installation
47
+ : {};
48
+ const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object'
49
+ ? metadata.service_catalog
50
+ : {};
51
+ const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
52
+ return {
53
+ mode: 'application-home',
54
+ query: {
55
+ app_id: bundle.app_id || null
56
+ },
57
+ summary: {
58
+ app_name: bundle.app_name || null,
59
+ runtime_version: runtimeRelease.runtime_version || null,
60
+ environment: bundle.environment || null,
61
+ release_status: runtimeRelease.release_status || null,
62
+ runtime_status: runtimeRelease.runtime_status || null,
63
+ install_status: installation.status || 'not-installed',
64
+ release_count: releases.length
65
+ },
66
+ relations: {
67
+ runtime_release_id: bundle.runtime_release_id || null,
68
+ ontology_bundle_id: bundle.ontology_bundle_id || null,
69
+ engineering_project_id: bundle.engineering_project_id || null,
70
+ default_scene_id: bundle.default_scene_id || null
71
+ },
72
+ items: releases,
73
+ view_model: {
74
+ projection: 'application',
75
+ app_id: bundle.app_id || null,
76
+ app_key: bundle.app_key || null,
77
+ app_name: bundle.app_name || null,
78
+ entrypoint: runtimeRelease.entrypoint || null,
79
+ current_release: installation.release_id || runtimeRelease.release_id || null,
80
+ current_environment: bundle.environment || installation.current_environment || null,
81
+ install_root: installation.install_root || null,
82
+ scene_binding_count: sceneBindings.length,
83
+ release_count: releases.length
84
+ },
85
+ mb_status: runtimeRelease.runtime_status || installation.status || bundle.status || 'unknown'
86
+ };
87
+ }
88
+
89
+ async function buildOntologyHome(graph = {}, dependencies = {}) {
90
+ const bundle = graph.bundle || {};
91
+ const ontologyBundle = graph.ontology_bundle || {};
92
+ const store = dependencies.store;
93
+ const triad = store
94
+ ? await store.buildOntologyTriadSummary({ limit: 1000 })
95
+ : {
96
+ ontology_core: { entity_relation: [], business_rules: [], decision_strategy: [] },
97
+ ontology_core_ui: { ready: false, coverage_percent: 0, missing: ['entity_relation', 'business_rules', 'decision_strategy'], triads: {} },
98
+ counts: { entity_relation: 0, business_rules: 0, decision_strategy: 0 }
99
+ };
100
+ const recommendedSeed = resolveOntologySeedProfile(bundle.app_key || '')
101
+ || resolveOntologySeedProfile('customer-order-demo')
102
+ || (listOntologySeedProfiles()[0] ? { profile: listOntologySeedProfiles()[0].profile, label: listOntologySeedProfiles()[0].label } : null);
103
+ const starterSeed = triad.ontology_core_ui.ready === true
104
+ ? null
105
+ : {
106
+ recommended_profile: recommendedSeed ? recommendedSeed.profile : null,
107
+ recommended_label: recommendedSeed ? recommendedSeed.label : null,
108
+ recommended_command: recommendedSeed
109
+ ? `sce ontology seed apply --profile ${recommendedSeed.profile} --json`
110
+ : null
111
+ };
112
+ return {
113
+ mode: 'ontology-home',
114
+ query: {
115
+ app_id: bundle.app_id || null
116
+ },
117
+ summary: {
118
+ app_name: bundle.app_name || null,
119
+ ontology_version: ontologyBundle.ontology_version || null,
120
+ template_version: ontologyBundle.template_version || null,
121
+ triad_status: ontologyBundle.triad_status || null,
122
+ publish_readiness: ontologyBundle.publish_readiness || null,
123
+ triad_ready: triad.ontology_core_ui.ready === true,
124
+ triad_coverage_percent: triad.ontology_core_ui.coverage_percent
125
+ },
126
+ relations: {
127
+ ontology_bundle_id: bundle.ontology_bundle_id || null,
128
+ engineering_project_id: bundle.engineering_project_id || null,
129
+ runtime_release_id: bundle.runtime_release_id || null
130
+ },
131
+ items: [],
132
+ ontology_core: triad.ontology_core,
133
+ ontology_core_ui: triad.ontology_core_ui,
134
+ starter_seed: starterSeed,
135
+ view_model: {
136
+ projection: 'ontology',
137
+ ontology_bundle_id: ontologyBundle.ontology_bundle_id || null,
138
+ triad_status: ontologyBundle.triad_status || null,
139
+ template_source: ontologyBundle.template_source || null,
140
+ capability_count: Array.isArray(ontologyBundle.capability_set) ? ontologyBundle.capability_set.length : 0,
141
+ summary: ontologyBundle.summary || {},
142
+ ontology_counts: triad.counts,
143
+ triad_summary: triad.ontology_core_ui,
144
+ starter_seed: starterSeed
145
+ },
146
+ mb_status: ontologyBundle.publish_readiness || ontologyBundle.triad_status || (triad.ontology_core_ui.ready ? 'ready' : 'partial') || bundle.status || 'unknown'
147
+ };
148
+ }
149
+
150
+ async function buildEngineeringHome(graph = {}, dependencies = {}) {
151
+ const bundle = graph.bundle || {};
152
+ const engineeringProject = graph.engineering_project || {};
153
+ const sceneBindings = Array.isArray(graph.scene_bindings) ? graph.scene_bindings : [];
154
+ const store = dependencies.store;
155
+ const [requirements, tracking, plans, changes, issues, resources, logs, backups, switches] = store
156
+ ? await Promise.all([
157
+ store.listPmRequirements({ limit: 1000 }),
158
+ store.listPmTracking({ limit: 1000 }),
159
+ store.listPmPlans({ limit: 1000 }),
160
+ store.listPmChanges({ limit: 1000 }),
161
+ store.listPmIssues({ limit: 1000 }),
162
+ store.listAssuranceResourceSnapshots({ limit: 1000 }),
163
+ store.listAssuranceLogViews({ limit: 1000 }),
164
+ store.listAssuranceBackupRecords({ limit: 1000 }),
165
+ store.listAssuranceConfigSwitches({ limit: 1000 })
166
+ ])
167
+ : [[], [], [], [], [], [], [], [], []];
168
+ return {
169
+ mode: 'engineering-home',
170
+ query: {
171
+ app_id: bundle.app_id || null
172
+ },
173
+ summary: {
174
+ app_name: bundle.app_name || null,
175
+ runtime_version: graph.runtime_release && graph.runtime_release.runtime_version ? graph.runtime_release.runtime_version : null,
176
+ code_version: engineeringProject.code_version || null,
177
+ current_branch: engineeringProject.current_branch || null,
178
+ dirty_state: engineeringProject.dirty_state === true,
179
+ scene_count: sceneBindings.length,
180
+ requirement_count: Array.isArray(requirements) ? requirements.length : 0,
181
+ issue_count: Array.isArray(issues) ? issues.length : 0,
182
+ plan_count: Array.isArray(plans) ? plans.length : 0,
183
+ assurance_resource_count: Array.isArray(resources) ? resources.length : 0
184
+ },
185
+ relations: {
186
+ engineering_project_id: bundle.engineering_project_id || null,
187
+ ontology_bundle_id: bundle.ontology_bundle_id || null,
188
+ runtime_release_id: bundle.runtime_release_id || null,
189
+ default_scene_id: bundle.default_scene_id || null
190
+ },
191
+ items: [],
192
+ view_model: {
193
+ projection: 'engineering',
194
+ primary_sections: ['source', 'timeline', 'diff', 'delivery', 'capability', 'assurance'],
195
+ project_name: engineeringProject.project_name || bundle.app_name || null,
196
+ repo_url: engineeringProject.repo_url || null,
197
+ workspace_path: engineeringProject.workspace_path || null,
198
+ default_scene_id: bundle.default_scene_id || null,
199
+ delivery_summary: {
200
+ requirements: Array.isArray(requirements) ? requirements.length : 0,
201
+ tracking: Array.isArray(tracking) ? tracking.length : 0,
202
+ plans: Array.isArray(plans) ? plans.length : 0,
203
+ changes: Array.isArray(changes) ? changes.length : 0,
204
+ issues: Array.isArray(issues) ? issues.length : 0
205
+ },
206
+ assurance_summary: {
207
+ resources: Array.isArray(resources) ? resources.length : 0,
208
+ logs: Array.isArray(logs) ? logs.length : 0,
209
+ backups: Array.isArray(backups) ? backups.length : 0,
210
+ config_switches: Array.isArray(switches) ? switches.length : 0
211
+ }
212
+ },
213
+ mb_status: engineeringProject.dirty_state === true ? 'dirty' : (bundle.status || 'unknown')
214
+ };
215
+ }
216
+
217
+ function printPayload(payload, options = {}, title = 'Mode Home') {
218
+ if (options.json) {
219
+ console.log(JSON.stringify(payload, null, 2));
220
+ return;
221
+ }
222
+ console.log(chalk.blue(title));
223
+ if (payload.mode) {
224
+ console.log(` Mode: ${payload.mode}`);
225
+ }
226
+ if (payload.summary && typeof payload.summary === 'object') {
227
+ for (const [key, value] of Object.entries(payload.summary)) {
228
+ console.log(` ${key}: ${value}`);
229
+ }
230
+ }
231
+ }
232
+
233
+ async function runModeHomeCommand(projection, options = {}, dependencies = {}) {
234
+ const appRef = normalizeString(options.app || options.appRef);
235
+ if (!appRef) {
236
+ throw new Error('--app is required');
237
+ }
238
+ const store = createStore(dependencies);
239
+ const useCache = options.cache !== false;
240
+ const cacheTtlSeconds = normalizePositiveInteger(options.cacheTtlSeconds, 5, 3600);
241
+
242
+ if (useCache) {
243
+ const cached = await store.getAppBundleProjectionCache(appRef, projection);
244
+ if (cached && isFreshProjectionCache(cached, cacheTtlSeconds)) {
245
+ const payload = cached.payload && typeof cached.payload === 'object' ? { ...cached.payload } : {};
246
+ payload.cache = {
247
+ hit: true,
248
+ generated_at: cached.generated_at,
249
+ ttl_seconds: cacheTtlSeconds
250
+ };
251
+ printPayload(payload, options, `${projection} home`);
252
+ return payload;
253
+ }
254
+ }
255
+
256
+ const graph = await store.getAppBundleGraph(appRef);
257
+ if (!graph) {
258
+ throw new Error(`app bundle not found: ${appRef}`);
259
+ }
260
+ let payload;
261
+ if (projection === 'application') {
262
+ payload = await buildApplicationHome(graph, { store });
263
+ } else if (projection === 'ontology') {
264
+ payload = await buildOntologyHome(graph, { store });
265
+ } else {
266
+ payload = await buildEngineeringHome(graph, { store });
267
+ }
268
+ payload.cache = {
269
+ hit: false,
270
+ ttl_seconds: cacheTtlSeconds
271
+ };
272
+ if (useCache && graph.bundle && graph.bundle.app_id) {
273
+ await store.saveAppBundleProjectionCache(
274
+ graph.bundle.app_id,
275
+ projection,
276
+ payload,
277
+ graph.bundle.updated_at || null
278
+ );
279
+ }
280
+ printPayload(payload, options, `${projection} home`);
281
+ return payload;
282
+ }
283
+
284
+ function safeRun(handler, options = {}, context = 'mode command') {
285
+ Promise.resolve(handler(options))
286
+ .catch((error) => {
287
+ if (options.json) {
288
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
289
+ } else {
290
+ console.error(chalk.red(`${context} failed:`), error.message);
291
+ }
292
+ process.exitCode = 1;
293
+ });
294
+ }
295
+
296
+ function registerModeCommands(program) {
297
+ const mode = program
298
+ .command('mode')
299
+ .description('Resolve MagicBall mode projections from SCE app bundle state');
300
+
301
+ ['application', 'ontology', 'engineering'].forEach((projection) => {
302
+ const projectionCommand = mode
303
+ .command(projection)
304
+ .description(`Resolve ${projection} mode projection`);
305
+
306
+ projectionCommand
307
+ .command('home')
308
+ .description(`Build ${projection} mode home projection for one app bundle`)
309
+ .requiredOption('--app <app-id-or-key>', 'App id or app key')
310
+ .option('--json', 'Print machine-readable JSON output')
311
+ .action((options) => safeRun((runtimeOptions) => runModeHomeCommand(projection, runtimeOptions), options, `mode ${projection} home`));
312
+ });
313
+ }
314
+
315
+ module.exports = {
316
+ buildApplicationHome,
317
+ buildOntologyHome,
318
+ buildEngineeringHome,
319
+ runModeHomeCommand,
320
+ registerModeCommands
321
+ };