@feng0531/dsh-code-review 0.87.1 → 0.87.3

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.
@@ -1,5 +1,5 @@
1
1
  import { createHash } from 'node:crypto';
2
- const KINDS = new Set(['verification', 'synthesis', 'interaction']);
2
+ const KINDS = new Set(['primary', 'verification', 'synthesis', 'interaction']);
3
3
  const REASONS = new Set(['READER_CALL_BUDGET_EXCEEDED', 'READER_OUTPUT_BUDGET_EXCEEDED', 'STAGE_INTERRUPTED', 'STAGE_CANCELLED', 'STAGE_TIMEOUT', 'STAGE_NO_PROGRESS', 'STAGE_ATTEMPTS_EXHAUSTED', 'STAGE_FAILED']);
4
4
  const fail = code => Object.assign(new Error(code), { code });
5
5
  const canonical = value => Array.isArray(value) ? value.map(canonical) : value && typeof value === 'object' ? Object.fromEntries(Object.keys(value).sort().filter(key => value[key] !== undefined).map(key => [key, canonical(value[key])])) : value;
@@ -40,7 +40,17 @@ export function createStageContinuation(snapshot, options, { completedPrimary =
40
40
  }
41
41
  }
42
42
  const get = id => { const state=states.get(id); if (!state) throw fail('UNKNOWN_STAGE_UNIT'); return state; };
43
- const dependenciesReady = state => state.fileIds.every(id => primary.includes(id)) && state.dependencies.every(dep => dep.startsWith('primary:') ? primary.includes(dep.slice(8)) : get(dep).status === 'completed');
43
+ // The completedPrimary baseline is immutable. A pending primary may run without
44
+ // belonging to it; secondary work must name a completed primary unit explicitly
45
+ // when relying on primary work performed by this continuation. Reserved
46
+ // primary:<fileId> dependencies still refer only to the completed baseline.
47
+ const dependencyCompleted = dep => dep.startsWith('primary:') ? primary.includes(dep.slice(8)) : get(dep).status === 'completed';
48
+ const primaryCompleted = (state, fileId) => primary.includes(fileId) || state.dependencies.some(dep => {
49
+ if (dep.startsWith('primary:')) return false;
50
+ const prerequisite = get(dep);
51
+ return prerequisite.kind === 'primary' && prerequisite.status === 'completed' && prerequisite.fileIds.includes(fileId);
52
+ });
53
+ const dependenciesReady = state => (state.kind === 'primary' || state.fileIds.every(id => primaryCompleted(state, id))) && state.dependencies.every(dependencyCompleted);
44
54
  for (const state of states.values()) {
45
55
  if (state.status === 'completed' && (!dependenciesReady(state) || state.stopped || state.pendingReason !== null)) throw fail('INVALID_STAGE_CHECKPOINT');
46
56
  }