poi-plugin-remodel-assistant 1.2.5-beta.1 → 1.2.5-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-remodel-assistant",
3
- "version": "1.2.5-beta.1",
3
+ "version": "1.2.5-beta.2",
4
4
  "description": "View enhanced KanColle improvement data, manage improvement plans, and receive improvement recommendations.",
5
5
  "main": "index.js",
6
6
  "author": {
@@ -5,8 +5,6 @@ exports.executeDecisionSnapshotJob = exports.resetDecisionSnapshotJobState = exp
5
5
 
6
6
  var _pluginMeta = require("../../shared/plugin-meta");
7
7
 
8
- var _kcraTrace__ = require("../../shared/__kcra-trace__");
9
-
10
8
  var _planDecisionIndex = require("../incremental/plan-decision-index");
11
9
 
12
10
  var _decisionSnapshotDomain = require("../decisions/domain/decision-snapshot-domain");
@@ -76,20 +74,7 @@ const publishDecisionSnapshot = ({
76
74
  assignmentFindings: effective.assignmentFindings || [],
77
75
  assignmentDiagnostics: [...(userAllocation && userAllocation.assignmentDiagnostics || []), ...(effective.assignmentDiagnostics || [])]
78
76
  };
79
- const alignmentFindings = logPublishedDecisionSnapshotAlignment(snapshot, effective.currentInventoryBindings || {});
80
- (0, _kcraTrace__.__KCRA_TRACE__)('snapshot.publish.summary', {
81
- itemCount: snapshot.items.length,
82
- workbenchCount: snapshot.workbenchItems.length,
83
- retainedBindingCount: snapshot.retainedBindingCurrentIds.length,
84
- bindingCount: Object.keys(snapshot.assignmentPersistenceBindings || {}).length,
85
- bindingTransitions: snapshot.assignmentBindingTransitions,
86
- assignmentFindings: snapshot.assignmentFindings,
87
- assignmentDiagnosticCount: snapshot.assignmentDiagnostics.length,
88
- alignmentFindings
89
- });
90
- (0, _kcraTrace__.__KCRA_TRACE__)('snapshot.publish.full', snapshot, {
91
- full: true
92
- });
77
+ logPublishedDecisionSnapshotAlignment(snapshot, effective.currentInventoryBindings || {});
93
78
  return snapshot;
94
79
  };
95
80
 
@@ -292,18 +277,20 @@ const buildFullDecisionSnapshotPayload = input => {
292
277
  useitems: job.useitems || {},
293
278
  resourceBudget: job.resourceBudget || {}
294
279
  });
295
- };
280
+ }; // Transient projection caches only. They are optimization state, never Plan/Binding authority.
281
+ // Clearing them must be semantically equivalent to a Full rebuild from current Reality.
282
+
296
283
 
297
284
  exports.buildFullDecisionSnapshotPayload = buildFullDecisionSnapshotPayload;
298
- let baseIncrementalSnapshotState = null;
299
- let effectiveIncrementalSnapshotState = null;
285
+ let baseIncrementalProjectionCacheState = null;
286
+ let effectiveIncrementalProjectionCacheState = null;
300
287
 
301
288
  const buildDecisionSnapshotPayload = (input, profile = null) => {
302
289
  const job = input || {};
303
290
 
304
291
  if (_pluginMeta.FORCE_FULL_DECISION_REBUILD) {
305
- baseIncrementalSnapshotState = null;
306
- effectiveIncrementalSnapshotState = null;
292
+ baseIncrementalProjectionCacheState = null;
293
+ effectiveIncrementalProjectionCacheState = null;
307
294
  return buildFullDecisionSnapshotPayload(job, profile);
308
295
  }
309
296
 
@@ -316,15 +303,15 @@ const buildDecisionSnapshotPayload = (input, profile = null) => {
316
303
 
317
304
  const baseResult = (0, _planDecisionIndex.buildIncrementalDecisionSnapshot)(_extends({}, job, {
318
305
  currentInventoryBindings: baseBindings,
319
- previous: baseIncrementalSnapshotState,
306
+ previous: baseIncrementalProjectionCacheState,
320
307
  allocationScope: 'user',
321
308
  profile: prefixedProfile(profile, 'base')
322
309
  }));
323
310
  measureProfile(profile, 'base-core-total', phaseStartedAt, {
324
- hadPrevious: Boolean(baseIncrementalSnapshotState),
311
+ hadPrevious: Boolean(baseIncrementalProjectionCacheState),
325
312
  planGroupCount: Object.keys(job.plans || {}).length
326
313
  });
327
- baseIncrementalSnapshotState = baseResult.state;
314
+ baseIncrementalProjectionCacheState = baseResult.state;
328
315
  const base = baseResult.value;
329
316
  observeAllocationStage(job, 'UserAllocation', _extends({
330
317
  mode: 'incremental'
@@ -367,8 +354,8 @@ const buildDecisionSnapshotPayload = (input, profile = null) => {
367
354
  // incremental diff remains the correctness gate and recomputes every changed
368
355
  // Plan/Binding target.
369
356
 
370
- const effectivePrevious = effectiveIncrementalSnapshotState || baseResult.state;
371
- const seededEffectiveFromBase = !effectiveIncrementalSnapshotState && Boolean(baseResult.state);
357
+ const effectivePrevious = effectiveIncrementalProjectionCacheState || baseResult.state;
358
+ const seededEffectiveFromBase = !effectiveIncrementalProjectionCacheState && Boolean(baseResult.state);
372
359
  const effectiveResult = (0, _planDecisionIndex.buildIncrementalDecisionSnapshot)(_extends({}, job, {
373
360
  plans: composition.plans,
374
361
  currentInventoryBindings: effectiveBindings,
@@ -381,7 +368,7 @@ const buildDecisionSnapshotPayload = (input, profile = null) => {
381
368
  seededFromBase: seededEffectiveFromBase,
382
369
  planGroupCount: Object.keys(composition.plans || {}).length
383
370
  });
384
- effectiveIncrementalSnapshotState = effectiveResult.state;
371
+ effectiveIncrementalProjectionCacheState = effectiveResult.state;
385
372
  const effective = effectiveResult.value;
386
373
  observeAllocationStage(job, 'ConsumableAllocation', _extends({
387
374
  mode: 'incremental'
@@ -404,8 +391,8 @@ const buildDecisionSnapshotPayload = (input, profile = null) => {
404
391
  exports.buildDecisionSnapshotPayload = buildDecisionSnapshotPayload;
405
392
 
406
393
  const resetDecisionSnapshotJobState = () => {
407
- baseIncrementalSnapshotState = null;
408
- effectiveIncrementalSnapshotState = null;
394
+ baseIncrementalProjectionCacheState = null;
395
+ effectiveIncrementalProjectionCacheState = null;
409
396
  };
410
397
 
411
398
  exports.resetDecisionSnapshotJobState = resetDecisionSnapshotJobState;
@@ -9,6 +9,8 @@ var _startupPerformance = require("../../shared/startup-performance");
9
9
 
10
10
  var _equipmentBlacklistDomain = require("../equipment/domain/equipment-blacklist-domain");
11
11
 
12
+ var _pluginResourcePaths = require("../../shared/plugin-resource-paths");
13
+
12
14
  var _decisionSnapshotJobs = require("./decision-snapshot-jobs");
13
15
 
14
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -173,7 +175,8 @@ const requestDecisionSnapshot = inputs => {
173
175
  planRouteSelections: inputs.planRouteSelections,
174
176
  routeAcquisitionIndex: inputs.routeAcquisitionIndex || {},
175
177
  currentInventoryBindings: inputs.currentInventoryBindings || {},
176
- lowPriorityEquipmentIds: (0, _equipmentBlacklistDomain.getLowPriorityEquipmentIds)(inputs.equipmentBlacklist)
178
+ lowPriorityEquipmentIds: (0, _equipmentBlacklistDomain.getLowPriorityEquipmentIds)(inputs.equipmentBlacklist),
179
+ startupSnapshotPath: (0, _pluginResourcePaths.getStartupSnapshotPath)()
177
180
  };
178
181
 
179
182
  if (workerRuntime() === 'inline') {
@@ -7,10 +7,33 @@ const {
7
7
  executeDecisionSnapshotJob
8
8
  } = require('./decision-snapshot-jobs');
9
9
 
10
+ const {
11
+ writePersistentStartupDecisionSnapshot
12
+ } = require('./startup-decision-snapshot-storage');
13
+
14
+ let startupSnapshotPersistTimer = null;
15
+ let pendingStartupSnapshotPersistence = null;
16
+
10
17
  const send = message => {
11
18
  if (parentPort) parentPort.postMessage(message);else if (typeof process.send === 'function') process.send(message);
12
19
  };
13
20
 
21
+ const scheduleStartupSnapshotPersistence = (filePath, snapshot) => {
22
+ if (!filePath || !snapshot) return;
23
+ pendingStartupSnapshotPersistence = {
24
+ filePath,
25
+ snapshot
26
+ };
27
+ if (startupSnapshotPersistTimer) clearTimeout(startupSnapshotPersistTimer);
28
+ startupSnapshotPersistTimer = setTimeout(() => {
29
+ startupSnapshotPersistTimer = null;
30
+ const pending = pendingStartupSnapshotPersistence;
31
+ pendingStartupSnapshotPersistence = null;
32
+ if (!pending) return;
33
+ writePersistentStartupDecisionSnapshot(pending.snapshot, pending.filePath);
34
+ }, 1000);
35
+ };
36
+
14
37
  const respond = (requestId, job) => {
15
38
  try {
16
39
  const result = executeDecisionSnapshotJob(job);
@@ -18,7 +41,10 @@ const respond = (requestId, job) => {
18
41
  requestId,
19
42
  ok: true,
20
43
  result
21
- });
44
+ }); // Persistence is deliberately scheduled only after the calculated snapshot
45
+ // has been returned to Poi. It therefore cannot delay renderer publication.
46
+
47
+ scheduleStartupSnapshotPersistence(job && job.startupSnapshotPath, result);
22
48
  } catch (error) {
23
49
  send({
24
50
  requestId,
@@ -17,8 +17,6 @@ var _core = require("@blueprintjs/core");
17
17
 
18
18
  var _pluginMeta = require("../../shared/plugin-meta");
19
19
 
20
- var _kcraTrace__ = require("../../shared/__kcra-trace__");
21
-
22
20
  var _startupPerformance = require("../../shared/startup-performance");
23
21
 
24
22
  var _dataPackageDomain = require("../../shared/domain/data-package-domain");
@@ -29,6 +27,8 @@ var _decisionFoundationService = require("./decision-foundation-service");
29
27
 
30
28
  var _decisionSnapshotService = require("./decision-snapshot-service");
31
29
 
30
+ var _startupDecisionSnapshotStorage = require("./startup-decision-snapshot-storage");
31
+
32
32
  var _decisionSnapshotRequestGate = require("./decision-snapshot-request-gate");
33
33
 
34
34
  var _search = require("../../shared/search");
@@ -205,8 +205,9 @@ class NewInterfaceArea extends _react.Component {
205
205
  this.plansOverrideBase = null;
206
206
  this.decisionSnapshotTaskId = 0;
207
207
  this.decisionSnapshotRequestGate = (0, _decisionSnapshotRequestGate.createDecisionSnapshotRequestGate)();
208
- this.decisionSnapshotRefreshQueued = false;
209
- this.pendingDecisionAfterReady = [];
208
+ this.decisionSnapshotInvalidationQueue = [];
209
+ this.decisionSnapshotInvalidationDrainScheduled = false;
210
+ this.decisionRealityReadyCallbacks = [];
210
211
  this.exclusionRecommendationTaskId = 0;
211
212
  const workbenchFilters = (0, _uiPreferences.getWorkbenchFilters)(_pluginStateStorage.pluginConfig);
212
213
  this.state = {
@@ -245,16 +246,29 @@ class NewInterfaceArea extends _react.Component {
245
246
  this.planEquipmentAssignments = persistedPlanEquipmentAssignments();
246
247
  const snapshotInputs = decisionSnapshotInputsFor(props, this.state, this.plansOverride, this.plansOverrideBase, this.planEquipmentAssignments);
247
248
  const processCacheStartedAt = (0, _startupPerformance.startupPerformanceNow)();
248
- this.currentDecisionSnapshot = (0, _legacyAssignmentRecovery.hasUnfinishedLegacyAssignmentRecovery)((0, _pluginStateStorage.getPluginStateSnapshot)()) ? null : (0, _decisionSnapshotCache.readProcessDecisionSnapshotCache)(snapshotInputs);
249
+ const legacyRecoveryPending = (0, _legacyAssignmentRecovery.hasUnfinishedLegacyAssignmentRecovery)((0, _pluginStateStorage.getPluginStateSnapshot)());
250
+ const processSnapshot = legacyRecoveryPending ? null : (0, _decisionSnapshotCache.readProcessDecisionSnapshotCache)(snapshotInputs);
251
+ const startupSnapshot = !legacyRecoveryPending && !processSnapshot ? (0, _startupDecisionSnapshotStorage.readPersistentStartupDecisionSnapshot)() : null;
252
+ this.currentDecisionSnapshot = processSnapshot || startupSnapshot;
249
253
  (0, _startupPerformance.measureStartupPerformance)('decision.process-cache-lookup', processCacheStartedAt, {
250
- cacheHit: Boolean(this.currentDecisionSnapshot)
254
+ cacheHit: Boolean(processSnapshot),
255
+ persistentStartupHit: Boolean(startupSnapshot)
251
256
  });
252
257
 
253
- if (!this.currentDecisionSnapshot) {
258
+ if (!processSnapshot) {
254
259
  (0, _startupPerformance.markStartupPerformance)('decision.process-cache-miss-detail', (0, _decisionSnapshotCache.inspectDecisionSnapshotCache)(snapshotInputs));
255
260
  }
256
261
 
257
- this.currentDecisionSnapshotInputs = this.currentDecisionSnapshot ? snapshotInputs : null;
262
+ if (startupSnapshot) {
263
+ (0, _startupPerformance.markStartupPerformance)('decision.persistent-startup-snapshot-published', {
264
+ itemCount: Array.isArray(startupSnapshot.items) ? startupSnapshot.items.length : 0
265
+ });
266
+ } // A persistent startup snapshot is presentation-only stale state. Never give
267
+ // it current input identity: componentDidMount must still run the current
268
+ // Reality Full path instead of treating the stale snapshot as an exact cache hit.
269
+
270
+
271
+ this.currentDecisionSnapshotInputs = processSnapshot ? snapshotInputs : null;
258
272
  this.decisionSnapshotFeedbackGuard = (0, _decisionSnapshotRequestGate.createDecisionSnapshotFeedbackGuard)();
259
273
  this.latestStableStateValidation = null;
260
274
  if (this.currentDecisionSnapshot) this.state.decisionSnapshotLoading = false;
@@ -307,8 +321,11 @@ class NewInterfaceArea extends _react.Component {
307
321
  this.mounted = false;
308
322
  this.decisionSnapshotTaskId += 1;
309
323
  this.decisionSnapshotRequestGate.reset();
310
- this.decisionSnapshotRefreshQueued = false;
311
- this.pendingDecisionAfterReady = [];
324
+ this.decisionSnapshotInvalidationQueue.splice(0).forEach(item => {
325
+ if (item && typeof item.resolve === 'function') item.resolve(null);
326
+ });
327
+ this.decisionSnapshotInvalidationDrainScheduled = false;
328
+ this.decisionRealityReadyCallbacks = [];
312
329
  this.exclusionRecommendationTaskId += 1;
313
330
  this.stopObservingWorkspaceSize();
314
331
  this.setEquipmentDividerRef(null);
@@ -743,9 +760,6 @@ var _initialiseProps = function () {
743
760
  snapshot
744
761
  });
745
762
  this.latestStableStateValidation = stableValidation;
746
- (0, _kcraTrace__.__KCRA_TRACE__)('validator.stable-state', stableValidation, {
747
- full: true
748
- });
749
763
  return {
750
764
  ok: true,
751
765
  stableValidation
@@ -774,7 +788,7 @@ var _initialiseProps = function () {
774
788
 
775
789
  if (!snapshotInputs.equipmentRealityReady) {
776
790
  (0, _startupPerformance.markStartupPerformance)('decision.waiting-for-reality');
777
- if (afterReady) this.pendingDecisionAfterReady.push(afterReady);
791
+ if (afterReady) this.decisionRealityReadyCallbacks.push(afterReady);
778
792
  return Promise.resolve(null);
779
793
  }
780
794
 
@@ -782,15 +796,6 @@ var _initialiseProps = function () {
782
796
  planGroupCount: Object.keys(snapshotInputs.plans || {}).length,
783
797
  bindingCount: Object.keys(snapshotInputs.currentInventoryBindings || {}).length
784
798
  });
785
- (0, _kcraTrace__.__KCRA_TRACE__)('snapshot.request.inputs', {
786
- plans: snapshotInputs.plans,
787
- planRouteSelections: snapshotInputs.planRouteSelections,
788
- currentInventoryBindings: snapshotInputs.currentInventoryBindings,
789
- equipmentRealityReady: snapshotInputs.equipmentRealityReady,
790
- actualEquipInventory: snapshotInputs.actualEquipInventory
791
- }, {
792
- full: true
793
- });
794
799
  const recoveryStartedAt = (0, _startupPerformance.startupPerformanceNow)();
795
800
  const recovery = (0, _pluginStateCommands.runPendingLegacyAssignmentRecovery)({
796
801
  equipInventory: snapshotInputs.actualEquipInventory
@@ -816,8 +821,8 @@ var _initialiseProps = function () {
816
821
  });
817
822
  }
818
823
 
819
- const deferredAfterReady = afterReady || this.pendingDecisionAfterReady.length > 0 ? snapshot => {
820
- const callbacks = this.pendingDecisionAfterReady.splice(0);
824
+ const deferredAfterReady = afterReady || this.decisionRealityReadyCallbacks.length > 0 ? snapshot => {
825
+ const callbacks = this.decisionRealityReadyCallbacks.splice(0);
821
826
  callbacks.forEach(callback => callback(snapshot));
822
827
  if (afterReady) afterReady(snapshot);
823
828
  } : null;
@@ -838,32 +843,49 @@ var _initialiseProps = function () {
838
843
  const activeRequest = this.decisionSnapshotRequestGate.readActive();
839
844
 
840
845
  if (activeRequest) {
841
- if (afterReady) this.pendingDecisionAfterReady.push(afterReady);
842
-
843
- if (!this.decisionSnapshotRefreshQueued) {
844
- this.decisionSnapshotRefreshQueued = true;
845
- activeRequest.then(() => {
846
- if (!this.mounted) return null;
847
- this.decisionSnapshotRefreshQueued = false;
848
- const callbacks = this.pendingDecisionAfterReady.splice(0);
849
-
850
- if (!this.decisionSnapshotRequestGate.shouldRefresh(this.getDecisionSnapshotInputs())) {
851
- callbacks.forEach(callback => {
852
- if (this.currentDecisionSnapshot) callback(this.currentDecisionSnapshot);
853
- });
854
- return this.currentDecisionSnapshot;
846
+ // Snapshot invalidations are a FIFO work queue, not a coalescing flag. Each
847
+ // invalidation is consumed after the current isolated Snapshot finishes. A
848
+ // queued item intentionally reads the latest Reality when it starts; this
849
+ // runtime requires eventual consistency, not historical event replay.
850
+ const queued = new Promise(resolve => {
851
+ this.decisionSnapshotInvalidationQueue.push({
852
+ afterReady,
853
+ resolve
854
+ });
855
+ });
856
+
857
+ if (!this.decisionSnapshotInvalidationDrainScheduled) {
858
+ this.decisionSnapshotInvalidationDrainScheduled = true;
859
+
860
+ const drain = () => {
861
+ if (!this.mounted) {
862
+ this.decisionSnapshotInvalidationDrainScheduled = false;
863
+ this.decisionSnapshotInvalidationQueue.splice(0).forEach(item => item.resolve(null));
864
+ return null;
865
+ }
866
+
867
+ const item = this.decisionSnapshotInvalidationQueue.shift();
868
+
869
+ if (!item) {
870
+ this.decisionSnapshotInvalidationDrainScheduled = false;
871
+ return null;
855
872
  }
856
873
 
857
874
  return this.scheduleDecisionSnapshotRefresh({
858
- afterReady: snapshot => callbacks.forEach(callback => callback(snapshot))
875
+ afterReady: item.afterReady
876
+ }).then(snapshot => {
877
+ item.resolve(snapshot);
878
+ return drain();
879
+ }, () => {
880
+ item.resolve(null);
881
+ return drain();
859
882
  });
860
- }, () => {
861
- this.decisionSnapshotRefreshQueued = false;
862
- if (this.mounted && this.decisionSnapshotRequestGate.shouldRefresh(this.getDecisionSnapshotInputs())) this.scheduleDecisionSnapshotRefresh();
863
- });
883
+ };
884
+
885
+ activeRequest.then(drain, drain);
864
886
  }
865
887
 
866
- return activeRequest;
888
+ return queued;
867
889
  }
868
890
 
869
891
  const taskId = this.decisionSnapshotTaskId + 1;
@@ -1030,9 +1052,6 @@ var _initialiseProps = function () {
1030
1052
  snapshot: this.currentDecisionSnapshot
1031
1053
  });
1032
1054
  this.latestStableStateValidation = result;
1033
- (0, _kcraTrace__.__KCRA_TRACE__)('validator.manual-stable-state', result, {
1034
- full: true
1035
- });
1036
1055
  return result;
1037
1056
  }
1038
1057
  });
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.STARTUP_DECISION_SNAPSHOT_SCHEMA = exports.STARTUP_DECISION_SNAPSHOT_FORMAT = exports.clearPersistentStartupDecisionSnapshot = exports.writePersistentStartupDecisionSnapshot = exports.readPersistentStartupDecisionSnapshot = void 0;
5
+
6
+ var _fs = _interopRequireDefault(require("fs"));
7
+
8
+ var _path = _interopRequireDefault(require("path"));
9
+
10
+ var _pluginMeta = require("../../shared/plugin-meta");
11
+
12
+ var _pluginResourcePaths = require("../../shared/plugin-resource-paths");
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ const v8 = require('v8');
17
+
18
+ const STARTUP_DECISION_SNAPSHOT_FORMAT = `${_pluginMeta.PLUGIN_ID}.startup-decision-snapshot`;
19
+ exports.STARTUP_DECISION_SNAPSHOT_FORMAT = STARTUP_DECISION_SNAPSHOT_FORMAT;
20
+ const STARTUP_DECISION_SNAPSHOT_SCHEMA = 2;
21
+ exports.STARTUP_DECISION_SNAPSHOT_SCHEMA = STARTUP_DECISION_SNAPSHOT_SCHEMA;
22
+
23
+ const isPlainObject = value => value != null && typeof value === 'object' && !Array.isArray(value);
24
+
25
+ const snapshotEnvelope = snapshot => ({
26
+ format: STARTUP_DECISION_SNAPSHOT_FORMAT,
27
+ schemaVersion: STARTUP_DECISION_SNAPSHOT_SCHEMA,
28
+ snapshot
29
+ }); // Startup Snapshot is disposable derived presentation state. The renderer reads
30
+ // it synchronously so the previous UI can paint before the current-Reality Full.
31
+ // V8 structured serialization is used because the Decision Snapshot is already
32
+ // transferred through advanced IPC and is not guaranteed to be JSON-serializable.
33
+
34
+
35
+ const readPersistentStartupDecisionSnapshot = () => {
36
+ const filePath = (0, _pluginResourcePaths.getStartupSnapshotPath)();
37
+
38
+ try {
39
+ if (!_fs.default.existsSync(filePath)) return null;
40
+ const value = v8.deserialize(_fs.default.readFileSync(filePath));
41
+
42
+ if (!isPlainObject(value) || value.format !== STARTUP_DECISION_SNAPSHOT_FORMAT || Number(value.schemaVersion) !== STARTUP_DECISION_SNAPSHOT_SCHEMA || !isPlainObject(value.snapshot)) {
43
+ return null;
44
+ }
45
+
46
+ return value.snapshot;
47
+ } catch (error) {
48
+ return null;
49
+ }
50
+ }; // This function is intended for the Decision worker, never the Poi renderer.
51
+ // Cache durability is deliberately best-effort: a partial/corrupt write simply
52
+ // becomes a cache miss at the next startup and the normal Full path rebuilds it.
53
+
54
+
55
+ exports.readPersistentStartupDecisionSnapshot = readPersistentStartupDecisionSnapshot;
56
+
57
+ const writePersistentStartupDecisionSnapshot = (snapshot, filePath = null) => {
58
+ if (!isPlainObject(snapshot)) return false;
59
+ const targetPath = filePath || (0, _pluginResourcePaths.getStartupSnapshotPath)();
60
+ const directory = filePath ? _path.default.dirname(targetPath) : (0, _pluginResourcePaths.getStartupSnapshotDirectory)();
61
+
62
+ try {
63
+ _fs.default.mkdirSync(directory, {
64
+ recursive: true
65
+ });
66
+
67
+ _fs.default.writeFileSync(targetPath, v8.serialize(snapshotEnvelope(snapshot)));
68
+
69
+ return true;
70
+ } catch (error) {
71
+ return false;
72
+ }
73
+ };
74
+
75
+ exports.writePersistentStartupDecisionSnapshot = writePersistentStartupDecisionSnapshot;
76
+
77
+ const clearPersistentStartupDecisionSnapshot = () => {
78
+ try {
79
+ _fs.default.unlinkSync((0, _pluginResourcePaths.getStartupSnapshotPath)());
80
+ } catch (error) {// Best-effort cache cleanup: missing/unremovable cache is not fatal.
81
+ }
82
+ };
83
+
84
+ exports.clearPersistentStartupDecisionSnapshot = clearPersistentStartupDecisionSnapshot;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.buildIncrementalDecisionSnapshot = void 0;
4
+ exports.buildIncrementalDecisionSnapshot = exports.plansAcceptingEquipmentIds = exports.buildPlanAcceptIndex = void 0;
5
5
 
6
6
  var _decisionChainDomain = require("../decisions/domain/decision-chain-domain");
7
7
 
@@ -81,23 +81,64 @@ const projectDecisionItemDay = (item, today, ownedShipMasterIds, edgeCostResolve
81
81
  routeChoice,
82
82
  planCost
83
83
  });
84
- };
84
+ }; // Accept Index is an inverted structural dependency index: equipmentId -> Plan target ids
85
+ // whose compiled Route Metadata contains that equipment state. It is deliberately
86
+ // conservative and has no Allocation authority. False positives only cause a cheap
87
+ // Plan recomputation; false negatives would be a correctness defect.
88
+ //
89
+ // Build this index from durable Plan intent + structural Route Metadata, not from
90
+ // the previous pending-planning projection. Completed Plans intentionally have no
91
+ // pending occurrences, but an Equipment Reality change may make their completion
92
+ // predicate false again; they must therefore remain discoverable here.
93
+
94
+
95
+ const buildPlanAcceptIndex = ({
96
+ plans = {},
97
+ preparedGraph = null,
98
+ routeAcquisitionIndex = {}
99
+ } = {}) => {
100
+ const acceptedByEquipmentId = {};
101
+
102
+ const add = (equipmentId, planId) => {
103
+ const equipment = Number(equipmentId);
104
+ const plan = Number(planId);
105
+ if (!Number.isInteger(equipment) || equipment <= 0 || !Number.isInteger(plan) || plan <= 0) return;
106
+ if (!acceptedByEquipmentId[equipment]) acceptedByEquipmentId[equipment] = new Set();
107
+ acceptedByEquipmentId[equipment].add(plan);
108
+ };
85
109
 
86
- const plansInFamilies = (foundation, plans, itemIds) => {
87
- const affectedFamilies = new Set();
88
- const ids = itemIds || [];
89
- ids.forEach(id => {
90
- const dependency = foundation.dependencyIndex || {};
91
- const familyKey = (dependency.familyByItem || {})[id];
92
- if (familyKey) affectedFamilies.add(familyKey);
93
- });
94
- return Object.keys(plans || {}).map(Number).filter(id => {
95
- const dependency = foundation.dependencyIndex || {};
96
- const familyKey = (dependency.familyByItem || {})[id];
97
- return affectedFamilies.has(familyKey) || (itemIds || []).includes(id);
110
+ Object.keys(plans || {}).forEach(rawPlanId => {
111
+ const planId = Number(rawPlanId);
112
+ if (!Number.isInteger(planId) || planId <= 0) return;
113
+ (0, _planFactsDomain.configuredPlanGoals)(plans[rawPlanId] || {}).forEach(goal => {
114
+ const targetLevel = Number(goal && goal.star);
115
+ if (!Number.isInteger(targetLevel) || targetLevel < 0) return;
116
+ const metadata = (0, _currentStartCandidateDomain.buildPlanRouteMetadata)({
117
+ preparedGraph,
118
+ target: {
119
+ id: planId,
120
+ level: targetLevel
121
+ },
122
+ routeAcquisitionIndex
123
+ });
124
+ Object.keys(metadata && metadata.stateIndex || {}).forEach(key => {
125
+ const state = metadata.stateIndex[key];
126
+ add(state && state.equipmentId, planId);
127
+ });
128
+ });
98
129
  });
130
+ return Object.keys(acceptedByEquipmentId).reduce((result, equipmentId) => {
131
+ result[equipmentId] = Array.from(acceptedByEquipmentId[equipmentId]).sort((a, b) => a - b);
132
+ return result;
133
+ }, {});
99
134
  };
100
135
 
136
+ exports.buildPlanAcceptIndex = buildPlanAcceptIndex;
137
+
138
+ const plansAcceptingEquipmentIds = (acceptIndex = {}, equipmentIds = []) => numericIds((equipmentIds || []).reduce((result, equipmentId) => result.concat(acceptIndex[Number(equipmentId)] || []), []));
139
+
140
+ exports.plansAcceptingEquipmentIds = plansAcceptingEquipmentIds;
141
+
101
142
  const changedRouteSelectionTargets = (previousSelections = {}, nextSelections = {}) => {
102
143
  const previous = previousSelections || {};
103
144
  const next = nextSelections || {};
@@ -231,10 +272,14 @@ const buildIncrementalDecisionSnapshot = ({
231
272
  affectedPlanCount: 0,
232
273
  recomputedPlanCount: 0,
233
274
  affectedPlanIds: [],
275
+ routePlanningWorkPlanIds: [],
234
276
  recomputedPlanIds: [],
277
+ recomputedRoutePlanningPlanIds: [],
235
278
  recomputedDecisionItemCount: 0,
236
279
  recomputedDecisionItemIds: [],
280
+ decisionProjectionDirtyItemIds: [],
237
281
  recomputedTodayEntryPlanCount: 0,
282
+ todayProjectionDirtyPlanIds: [],
238
283
  dateChanged: false,
239
284
  durationMs: Date.now() - startedAt
240
285
  }
@@ -261,9 +306,11 @@ const buildIncrementalDecisionSnapshot = ({
261
306
  phaseStartedAt = profileNow();
262
307
  const edgeCostResolver = (0, _edgeCostIndex.createEdgeCostResolver)(foundation.edgeCostIndex || {});
263
308
  const decisionItemById = previous ? _extends({}, previous.decisionItemById || {}) : {};
264
- const evolutionTargetIds = evolutionTargets(foundation.effectiveData || []);
265
- const recomputedDecisionItemIds = previous ? numericIds(changedPlanIds.concat(changedInventoryItemIds).concat(changedDecisionSelectionItemIds).concat(changedInventoryBindingTargets).concat(foundationAffectedIds).concat(changedLowPriorityItemIds).concat(ownedShipsChanged ? rowIds : [])) : rowIds;
266
- recomputedDecisionItemIds.forEach(id => {
309
+ const evolutionTargetIds = evolutionTargets(foundation.effectiveData || []); // Projection dirty-set: these ids rebuild Decision presentation/facts only.
310
+ // They are not concrete Binding work and carry no Allocation authority.
311
+
312
+ const decisionProjectionDirtyItemIds = previous ? numericIds(changedPlanIds.concat(changedInventoryItemIds).concat(changedDecisionSelectionItemIds).concat(changedInventoryBindingTargets).concat(foundationAffectedIds).concat(changedLowPriorityItemIds).concat(ownedShipsChanged ? rowIds : [])) : rowIds;
313
+ decisionProjectionDirtyItemIds.forEach(id => {
267
314
  if (!rowsById[id]) return;
268
315
  decisionItemById[id] = (0, _decisionDomain.buildDecisionItem)(rowsById[id], {
269
316
  plans,
@@ -285,12 +332,12 @@ const buildIncrementalDecisionSnapshot = ({
285
332
  if (!rowsById[id]) delete decisionItemById[id];
286
333
  });
287
334
  measureProfile(profile, 'decision-items', phaseStartedAt, {
288
- recomputedDecisionItemCount: recomputedDecisionItemIds.length
335
+ recomputedDecisionItemCount: decisionProjectionDirtyItemIds.length
289
336
  });
290
337
  phaseStartedAt = profileNow();
291
338
  const dayItemById = previous ? _extends({}, previous.dayItemById || {}) : {};
292
- const dayAffectedItemIds = !previous || dateChanged || ownedShipsChanged ? rowIds : recomputedDecisionItemIds;
293
- dayAffectedItemIds.forEach(id => {
339
+ const dayProjectionDirtyItemIds = !previous || dateChanged || ownedShipsChanged ? rowIds : decisionProjectionDirtyItemIds;
340
+ dayProjectionDirtyItemIds.forEach(id => {
294
341
  if (!decisionItemById[id]) return;
295
342
  dayItemById[id] = projectDecisionItemDay(decisionItemById[id], initialDay, ownedShipMasterIds, edgeCostResolver);
296
343
  });
@@ -299,25 +346,47 @@ const buildIncrementalDecisionSnapshot = ({
299
346
  });
300
347
  const dayItems = rowIds.map(id => dayItemById[id]).filter(Boolean);
301
348
  measureProfile(profile, 'day-projection', phaseStartedAt, {
302
- affectedItemCount: dayAffectedItemIds.length,
349
+ affectedItemCount: dayProjectionDirtyItemIds.length,
303
350
  dayItemCount: dayItems.length
304
351
  });
305
352
  phaseStartedAt = profileNow();
306
353
  const routePlanningById = previous ? _extends({}, previous.routePlanningById || {}) : {};
307
354
  const planEntryById = previous ? _extends({}, previous.planEntryById || {}) : {};
308
- const routeAffectedSeeds = numericIds(changedPlanIds.concat(changedInventoryItemIds).concat(changedAcquisitionItemIds).concat(changedSelectionTargets).concat(changedInventoryBindingTargets).concat(foundationAffectedIds));
309
- const affectedPlanIds = previous ? numericIds(routeAffectedSeeds.concat(plansInFamilies(foundation, plans, routeAffectedSeeds))) : numericIds(Object.keys(plans));
310
- const recomputedPlanIds = [];
311
- const activeAffectedPlanIds = affectedPlanIds.filter(id => Object.prototype.hasOwnProperty.call(plans, id) || Object.prototype.hasOwnProperty.call(plans, String(id)));
312
- const affectedPlans = activeAffectedPlanIds.reduce((result, id) => {
355
+ const previousAcceptIndex = previous ? previous.planAcceptIndex || buildPlanAcceptIndex({
356
+ plans,
357
+ preparedGraph: foundation.improvementGraph || null,
358
+ routeAcquisitionIndex
359
+ }) : {};
360
+ const currentAcceptIndex = buildPlanAcceptIndex({
361
+ plans,
362
+ preparedGraph: foundation.improvementGraph || null,
363
+ routeAcquisitionIndex
364
+ });
365
+ const inventoryRoutePlanningCandidateIds = previous ? plansAcceptingEquipmentIds(previousAcceptIndex, changedInventoryItemIds) : []; // Acquisition facts participate in compiled Route Metadata. Use both the old and
366
+ // current Accept Index so additions and removals are symmetric: a Plan affected
367
+ // only before or only after the acquisition change is still rediscovered.
368
+
369
+ const acquisitionRoutePlanningCandidateIds = previous ? numericIds(plansAcceptingEquipmentIds(previousAcceptIndex, changedAcquisitionItemIds).concat(plansAcceptingEquipmentIds(currentAcceptIndex, changedAcquisitionItemIds))) : []; // Route selection and Binding changes already carry target Plan ids. Foundation
370
+ // `affectedItemIds` is structurally closed by the Foundation engine (including
371
+ // topology-family propagation), so expanding families again here would be a
372
+ // second dependency authority.
373
+
374
+ const directRoutePlanningSeedIds = numericIds(changedPlanIds.concat(changedSelectionTargets).concat(changedInventoryBindingTargets).concat(foundationAffectedIds)); // Route Planning work-set: legal-route analysis is read-only and Plan-local.
375
+ // This set must not be confused with the concrete Assignment Coordinator,
376
+ // which still performs one ordered frozen Allocation round below.
377
+
378
+ const routePlanningWorkPlanIds = previous ? numericIds(directRoutePlanningSeedIds.concat(inventoryRoutePlanningCandidateIds).concat(acquisitionRoutePlanningCandidateIds)) : numericIds(Object.keys(plans));
379
+ const recomputedRoutePlanningPlanIds = [];
380
+ const activeRoutePlanningWorkPlanIds = routePlanningWorkPlanIds.filter(id => Object.prototype.hasOwnProperty.call(plans, id) || Object.prototype.hasOwnProperty.call(plans, String(id)));
381
+ const routePlanningWorkPlans = activeRoutePlanningWorkPlanIds.reduce((result, id) => {
313
382
  result[id] = plans[id] || plans[String(id)] || {};
314
383
  return result;
315
384
  }, {});
316
385
 
317
- if (activeAffectedPlanIds.length > 0) {
386
+ if (activeRoutePlanningWorkPlanIds.length > 0) {
318
387
  const refreshed = (0, _currentStartCandidateDomain.buildCurrentStartPlanningStates)({
319
388
  data: foundation.effectiveData || [],
320
- plans: affectedPlans,
389
+ plans: routePlanningWorkPlans,
321
390
  equipLevels,
322
391
  equipInventory,
323
392
  routeAcquisitionIndex,
@@ -329,23 +398,23 @@ const buildIncrementalDecisionSnapshot = ({
329
398
  });
330
399
  refreshed.forEach(planning => {
331
400
  routePlanningById[Number(planning.id)] = planning;
332
- recomputedPlanIds.push(Number(planning.id));
401
+ recomputedRoutePlanningPlanIds.push(Number(planning.id));
333
402
  });
334
403
  }
335
404
 
336
- affectedPlanIds.forEach(id => {
405
+ routePlanningWorkPlanIds.forEach(id => {
337
406
  if (!Object.prototype.hasOwnProperty.call(plans, id) && !Object.prototype.hasOwnProperty.call(plans, String(id))) {
338
407
  delete routePlanningById[id];
339
408
  delete planEntryById[id];
340
409
  }
341
410
  });
342
411
  measureProfile(profile, 'route-planning', phaseStartedAt, {
343
- affectedPlanCount: affectedPlanIds.length,
344
- recomputedPlanCount: recomputedPlanIds.length
412
+ affectedPlanCount: routePlanningWorkPlanIds.length,
413
+ recomputedPlanCount: recomputedRoutePlanningPlanIds.length
345
414
  });
346
415
  phaseStartedAt = profileNow();
347
- const todayAffectedPlanIds = !previous || dateChanged || ownedShipsChanged ? numericIds(Object.keys(plans)) : numericIds(affectedPlanIds.concat(changedDecisionSelectionItemIds).concat(changedLowPriorityItemIds));
348
- todayAffectedPlanIds.forEach(id => {
416
+ const todayProjectionDirtyPlanIds = !previous || dateChanged || ownedShipsChanged ? numericIds(Object.keys(plans)) : numericIds(routePlanningWorkPlanIds.concat(changedDecisionSelectionItemIds).concat(changedLowPriorityItemIds));
417
+ todayProjectionDirtyPlanIds.forEach(id => {
349
418
  const item = dayItemById[id];
350
419
  const planning = routePlanningById[id] || defaultRoutePlanning(item || {
351
420
  id,
@@ -366,7 +435,7 @@ const buildIncrementalDecisionSnapshot = ({
366
435
  });
367
436
  const projectedWorkbenchItems = (0, _decisionDomain.sortDecisionItems)(rowIds.reduce((result, id) => result.concat(planEntryById[id] || []), []));
368
437
  measureProfile(profile, 'today-entry-projection', phaseStartedAt, {
369
- affectedPlanCount: todayAffectedPlanIds.length,
438
+ affectedPlanCount: todayProjectionDirtyPlanIds.length,
370
439
  workbenchCount: projectedWorkbenchItems.length
371
440
  });
372
441
  phaseStartedAt = profileNow();
@@ -377,7 +446,10 @@ const buildIncrementalDecisionSnapshot = ({
377
446
  const allocationRetainedBindingCurrentIds = (0, _currentStartAssignmentDomain.finalRetainedBindingCurrentIds)({
378
447
  plans,
379
448
  routePlannings: numericIds(Object.keys(routePlanningById)).map(id => routePlanningById[id])
380
- });
449
+ }); // Concrete Binding authority. The Coordinator itself is the synchronous
450
+ // authority-ordered consumer; incremental dirty-sets above only avoid rebuilding
451
+ // read-only Plan/Projection inputs and never decide inventory ownership.
452
+
381
453
  const ownership = (0, _currentStartAssignmentDomain.reconcileCurrentStartAssignments)({
382
454
  entries: projectedWorkbenchItems,
383
455
  equipInventory,
@@ -463,13 +535,17 @@ const buildIncrementalDecisionSnapshot = ({
463
535
  changedPlanIds,
464
536
  changedAcquisitionItemCount: changedAcquisitionItemIds.length,
465
537
  changedAcquisitionItemIds,
466
- affectedPlanCount: affectedPlanIds.length,
467
- recomputedPlanCount: recomputedPlanIds.length,
468
- affectedPlanIds,
469
- recomputedPlanIds,
470
- recomputedDecisionItemCount: recomputedDecisionItemIds.length,
471
- recomputedDecisionItemIds,
472
- recomputedTodayEntryPlanCount: todayAffectedPlanIds.length,
538
+ affectedPlanCount: routePlanningWorkPlanIds.length,
539
+ affectedPlanIds: routePlanningWorkPlanIds,
540
+ recomputedPlanCount: recomputedRoutePlanningPlanIds.length,
541
+ routePlanningWorkPlanIds,
542
+ recomputedPlanIds: recomputedRoutePlanningPlanIds,
543
+ recomputedRoutePlanningPlanIds,
544
+ recomputedDecisionItemCount: decisionProjectionDirtyItemIds.length,
545
+ recomputedDecisionItemIds: decisionProjectionDirtyItemIds,
546
+ decisionProjectionDirtyItemIds,
547
+ recomputedTodayEntryPlanCount: todayProjectionDirtyPlanIds.length,
548
+ todayProjectionDirtyPlanIds,
473
549
  dateChanged,
474
550
  durationMs: Date.now() - startedAt
475
551
  }
@@ -485,6 +561,7 @@ const buildIncrementalDecisionSnapshot = ({
485
561
  acquisitionSignatures: currentAcquisitionSignatures,
486
562
  routeAcquisitionIndexRef: routeAcquisitionIndex,
487
563
  routePlanningById,
564
+ planAcceptIndex: currentAcceptIndex,
488
565
  planEntryById,
489
566
  planRouteSelections,
490
567
  decisionSelections,
@@ -383,7 +383,8 @@ class DetailPanel extends _react.Component {
383
383
  const showUpgradeRoute = mode === 'equipment' && item && Number(item.id) === Number(upgradeRouteItemId);
384
384
  const executionLevel = hasResolvedExecutionItem ? currentExecutionLevel(displayItem) : null;
385
385
  const selectablePlanEntries = isPlanWorkbenchItem && Array.isArray(item.planEntries) ? item.planEntries : [];
386
- const relatedPlans = isPlanWorkbenchItem && selectablePlanEntries.length === 0 ? buildRelatedPlanReferences(item) : [];
386
+ const allRelatedPlans = isPlanWorkbenchItem ? buildRelatedPlanReferences(item) : [];
387
+ const relatedPlans = selectablePlanEntries.length === 0 ? allRelatedPlans : allRelatedPlans.filter(reference => reference.kind === 'consumable');
387
388
  return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("div", {
388
389
  className: "decision-detail-dock is-open"
389
390
  }, _react.default.createElement("aside", {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.getPluginStatePaths = exports.getPluginBackupDirectory = exports.getPluginStateDirectory = exports.getPluginDataDirectory = exports.resolvePoiAppDataPath = void 0;
4
+ exports.getPluginStatePaths = exports.getStartupSnapshotPath = exports.getStartupSnapshotDirectory = exports.getPluginBackupDirectory = exports.getPluginStateDirectory = exports.getPluginDataDirectory = exports.resolvePoiAppDataPath = void 0;
5
5
 
6
6
  var _os = _interopRequireDefault(require("os"));
7
7
 
@@ -45,6 +45,14 @@ const getPluginBackupDirectory = () => _path.default.join(getPluginDataDirectory
45
45
 
46
46
  exports.getPluginBackupDirectory = getPluginBackupDirectory;
47
47
 
48
+ const getStartupSnapshotDirectory = () => _path.default.join(getPluginDataDirectory(), 'startup-snapshot');
49
+
50
+ exports.getStartupSnapshotDirectory = getStartupSnapshotDirectory;
51
+
52
+ const getStartupSnapshotPath = () => _path.default.join(getStartupSnapshotDirectory(), 'current.bin');
53
+
54
+ exports.getStartupSnapshotPath = getStartupSnapshotPath;
55
+
48
56
  const getPluginStatePaths = () => {
49
57
  const base = getPluginStateDirectory();
50
58
  return {
@@ -3,8 +3,6 @@
3
3
  exports.__esModule = true;
4
4
  exports.commitDecisionSnapshotRuntimeState = exports.commitCurrentPlanRuntimeState = exports.finalizeLegacyAssignmentRecoveryFromSnapshot = exports.runPendingLegacyAssignmentRecovery = void 0;
5
5
 
6
- var _kcraTrace__ = require("./__kcra-trace__");
7
-
8
6
  var _pluginStateStorage = require("./plugin-state-storage");
9
7
 
10
8
  var _currentStartSelectionDomain = require("../new-interface/plan/domain/current-start-selection-domain");
@@ -33,15 +31,6 @@ const runPendingLegacyAssignmentRecovery = ({
33
31
  };
34
32
  }
35
33
 
36
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.pending.input', {
37
- stateRevision: Number(snapshot.revision) || 0,
38
- routeSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(snapshot),
39
- assignments: (0, _pluginStateSchema.getStatePlanEquipmentAssignments)(snapshot),
40
- recovery: snapshot.migration && snapshot.migration.assignmentRecovery,
41
- equipInventory
42
- }, {
43
- full: true
44
- });
45
34
  const result = (0, _legacyAssignmentRecovery.recoverLegacyAssignmentState)({
46
35
  plans: snapshot.user && snapshot.user.plans || {},
47
36
  currentRouteSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(snapshot),
@@ -53,13 +42,6 @@ const runPendingLegacyAssignmentRecovery = ({
53
42
  state: snapshot,
54
43
  audit: result.audit
55
44
  };
56
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.pending.candidate', {
57
- routeSelections: result.routeSelections,
58
- assignments: result.assignments,
59
- audit: result.audit
60
- }, {
61
- full: true
62
- });
63
45
  const state = (0, _pluginStateStorage.mutatePluginState)(draft => {
64
46
  (0, _pluginStateSchema.setStateCurrentStartSelections)(draft, result.routeSelections);
65
47
  (0, _pluginStateSchema.setStatePlanEquipmentAssignments)(draft, result.assignments);
@@ -68,14 +50,6 @@ const runPendingLegacyAssignmentRecovery = ({
68
50
  const cleanup = draft.migration.assignmentCleanup;
69
51
  if (cleanup) (0, _pluginStateSchema.setStatePendingRebindCurrentIds)(draft, []);
70
52
  });
71
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.pending.persisted', {
72
- stateRevision: Number(state.revision) || 0,
73
- routeSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(state),
74
- assignments: (0, _pluginStateSchema.getStatePlanEquipmentAssignments)(state),
75
- audit: state.migration && state.migration.assignmentRecovery
76
- }, {
77
- full: true
78
- });
79
53
  return {
80
54
  changed: true,
81
55
  state,
@@ -101,14 +75,6 @@ const finalizeLegacyAssignmentRecoveryFromSnapshot = ({
101
75
  };
102
76
  }
103
77
 
104
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.validation.input', {
105
- stateRevision: Number(state.revision) || 0,
106
- recovery,
107
- assignmentBindingTransitions: snapshot && snapshot.assignmentBindingTransitions || [],
108
- assignmentFindings: snapshot && snapshot.assignmentFindings || []
109
- }, {
110
- full: true
111
- });
112
78
  const protectedIds = new Set((recovery.protectedLegacyRouteCurrentIds || []).map(value => String(value || '').trim()).filter(Boolean));
113
79
  const invalidProtectedIds = Array.from(new Set((snapshot && snapshot.assignmentBindingTransitions || []).filter(transition => transition && transition.type === 'invalid-persisted-binding-released' && protectedIds.has(String(transition.currentId || '').trim())).map(transition => String(transition.currentId || '').trim()).filter(Boolean)));
114
80
 
@@ -130,14 +96,6 @@ const finalizeLegacyAssignmentRecoveryFromSnapshot = ({
130
96
  routeValidationFailedCurrentIds: invalidProtectedIds
131
97
  });
132
98
  });
133
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.validation.degraded-and-retry', {
134
- invalidProtectedIds,
135
- routeSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(committed),
136
- assignments: (0, _pluginStateSchema.getStatePlanEquipmentAssignments)(committed),
137
- audit: committed.migration && committed.migration.assignmentRecovery
138
- }, {
139
- full: true
140
- });
141
99
  return {
142
100
  changed: true,
143
101
  retry: true,
@@ -153,13 +111,6 @@ const finalizeLegacyAssignmentRecoveryFromSnapshot = ({
153
111
  routeValidationFailedCurrentIds: []
154
112
  });
155
113
  });
156
- (0, _kcraTrace__.__KCRA_TRACE__)('recovery.validation.completed', {
157
- routeSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(committed),
158
- assignments: (0, _pluginStateSchema.getStatePlanEquipmentAssignments)(committed),
159
- audit: committed.migration && committed.migration.assignmentRecovery
160
- }, {
161
- full: true
162
- });
163
114
  return {
164
115
  changed: true,
165
116
  retry: false,
@@ -243,38 +194,15 @@ const commitDecisionSnapshotRuntimeState = ({
243
194
  const pendingChanged = Array.isArray(pendingRebind) && pendingRebind.length > 0;
244
195
 
245
196
  if (sameValue(nextSelections, currentSelections) && sameValue(nextAssignments, currentAssignments) && !pendingChanged) {
246
- (0, _kcraTrace__.__KCRA_TRACE__)('state.binding-commit.noop', {
247
- stateRevision: Number(snapshot.revision) || 0,
248
- activeCurrentIds: Array.from(active),
249
- assignments: currentAssignments
250
- });
251
197
  return snapshot;
252
198
  }
253
199
 
254
- (0, _kcraTrace__.__KCRA_TRACE__)('state.binding-commit.before', {
255
- stateRevision: Number(snapshot.revision) || 0,
256
- activeCurrentIds: Array.from(active),
257
- currentAssignments,
258
- proposedAssignments: nextAssignments,
259
- currentSelections,
260
- nextSelections,
261
- pendingRebind
262
- }, {
263
- full: true
264
- });
265
200
  const committed = (0, _pluginStateStorage.mutatePluginState)(state => {
266
201
  (0, _pluginStateSchema.setStateCurrentStartSelections)(state, nextSelections);
267
202
  (0, _pluginStateSchema.setStatePlanEquipmentAssignments)(state, nextAssignments);
268
203
  const stateCleanup = state.migration && state.migration.assignmentCleanup;
269
204
  if (stateCleanup && pendingChanged) (0, _pluginStateSchema.setStatePendingRebindCurrentIds)(state, []);
270
205
  });
271
- (0, _kcraTrace__.__KCRA_TRACE__)('state.binding-commit.after', {
272
- stateRevision: Number(committed.revision) || 0,
273
- assignments: (0, _pluginStateSchema.getStatePlanEquipmentAssignments)(committed),
274
- routeSelections: (0, _pluginStateSchema.getStateCurrentStartSelections)(committed)
275
- }, {
276
- full: true
277
- });
278
206
  return committed;
279
207
  };
280
208