scene-capability-engine 3.0.7 → 3.0.8

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/CHANGELOG.md CHANGED
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
  - **Capability lexicon hard gate end-to-end defaultization**: `sce auto handoff run` and `sce auto handoff capability-matrix` now enforce unknown Moqui capability alias blocking by default (expected/provided), emit lexicon gate telemetry into release evidence, and promote those signals into governance risk/concern/recommendation/close-loop block decisions.
12
+ - **Moqui release summary report helper**: Added `node scripts/moqui-release-summary.js` (and npm alias `npm run report:moqui-summary`) to consolidate handoff evidence + baseline + lexicon + capability-matrix into a single release-gate verdict (`passed|failed|incomplete`) with remediation commands.
12
13
  - **SCE naming consolidation + compatibility bridge**: Rebranded product naming to `Scene Capability Engine`, moved package to `scene-capability-engine`, promoted `sce` as the primary CLI command, and preserved `sco` / `sce` / `scene-capability-engine` aliases for migration continuity.
13
14
  - **Official template library v1.5.0 alignment**: Synced with `scene-capability-engine-templates` `v1.5.0`, adding scene orchestration template coverage for canvas visualization, interaction hardening, execution playbook, dependency drilldown, decision cockpit, runbook export, action queue orchestration, action pack export, and unified scene governance closure.
14
15
  - **Branding consistency release guard**: Added `test:brand-consistency` to block publish when legacy repository/package/product naming reappears in tracked source files.
@@ -138,6 +139,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
138
139
  - **Autonomous operator UX**: Expanded docs with semantic decomposition and live stream behavior for close-loop command usage.
139
140
 
140
141
  ### Fixed
142
+ - **Orchestrator 429 backoff stall behavior**: `orchestration-engine` now clamps `Retry-After` retry waits by `rateLimitBackoffMaxMs` and interrupts pending retry sleeps immediately on `stop()`, preventing long backoff waits from appearing as deadlocks.
141
143
  - **Scene runtime 429 failure behavior under high request pressure**: Moqui HTTP client now retries on `429` with `Retry-After` support and bounded exponential backoff, reducing multi-agent stalls caused by transient service-side request limits.
142
144
  - **Moqui adapter matching fallback safety**: `spec.erp.*` bindings no longer get captured by Moqui handler when no adapter config exists, preventing false hard-fail paths and restoring expected simulator fallback behavior.
143
145
  - **Controller summary semantics**: `close-loop-controller` now reports final `pending_goals` from the persisted queue snapshot and only marks `cycle-limit-reached` as exhausted when pending work remains (or empty-polling mode explicitly consumes cycle budget).
@@ -23,6 +23,12 @@ Use this checklist before each integration batch.
23
23
  - `ontology_validation` exists and is recent.
24
24
  - Dependency relations (`depends_on`) are present for multi-spec batches.
25
25
  - High-risk gaps have mitigation notes.
26
+ - Moqui baseline matrix has no hard-gate regressions:
27
+ - `compare.coverage_matrix_regressions.length == 0`
28
+ - `summary.coverage_matrix.baseline_passed.rate_percent == 100`
29
+ - Capability lexicon has no unknown aliases:
30
+ - `summary.expected_unknown_count == 0`
31
+ - `summary.provided_unknown_count == 0`
26
32
 
27
33
  ## sce Acceptance Commands
28
34
 
@@ -34,6 +40,10 @@ npx sce auto handoff run --manifest ../331-poc/docs/handoffs/handoff-manifest.js
34
40
 
35
41
  npx sce auto handoff template-diff --manifest ../331-poc/docs/handoffs/handoff-manifest.json --json
36
42
  npx sce auto handoff regression --session-id latest --json
43
+ npx sce auto handoff capability-matrix --manifest ../331-poc/docs/handoffs/handoff-manifest.json --fail-on-gap --json
44
+ npx sce scene moqui-baseline --compare-with .kiro/reports/release-evidence/moqui-template-baseline-prev.json --fail-on-portfolio-fail --json
45
+ node scripts/moqui-lexicon-audit.js --manifest ../331-poc/docs/handoffs/handoff-manifest.json --fail-on-gap --json
46
+ node scripts/moqui-release-summary.js --fail-on-gate-fail --json
37
47
  ```
38
48
 
39
49
  ## Scene Package Gate Commands
@@ -602,7 +602,7 @@ Close-loop batch (`sce auto close-loop-batch <goals-file>`) options:
602
602
  - Batch summary includes `resource_plan` (budget/effective parallel/per-goal maxParallel/scheduling strategy/aging/starvation wait metrics/criticality summary) and `metrics` (`success_rate_percent`, `status_breakdown`, `average_sub_specs_per_goal`, `average_replan_cycles_per_goal`, `total_rate_limit_signals`, `average_rate_limit_signals_per_goal`, `total_rate_limit_backoff_ms`)
603
603
  - Under budget mode, scheduler is complexity-weighted (`goal_weight`/`scheduling_weight`) so higher-complexity goals consume more shared slots and can reduce same-batch concurrency.
604
604
  - Batch summary includes `batch_retry` telemetry (strategy, until-complete mode, configured/max/performed rounds, exhausted flag, per-round history).
605
- - Under `--batch-retry-strategy adaptive`, retry history includes rate-limit pressure and next-round backpressure decisions (`applied_batch_parallel`, `next_batch_parallel`, `adaptive_backpressure_applied`).
605
+ - Under `--batch-retry-strategy adaptive`, retry history includes rate-limit pressure and next-round backpressure decisions (`applied_batch_parallel`, `next_batch_parallel`, `adaptive_backpressure_applied`, `backpressure_level`). Severe pressure automatically halves `batch_parallel` / `batch_agent_budget` for the next retry round.
606
606
  - Batch summary includes `batch_session` metadata when persisted (session id + file path).
607
607
  - When using `--decompose-goal`, summary includes `generated_from_goal` metadata (strategy, target count, produced count, clause/category diagnostics, decomposition `quality`, and refinement telemetry).
608
608
 
@@ -833,6 +833,18 @@ Moqui template library lexicon audit (script-level governance helper):
833
833
  - By default, template capability auditing is scoped to `manifest.templates` (when matched), reducing noise from unrelated templates.
834
834
  - Template scope matching normalizes `sce.scene--*` / `kse.scene--*` prefixes, so renamed template namespaces still map correctly.
835
835
 
836
+ Moqui release summary helper (script-level consolidated gate view):
837
+ - `node scripts/moqui-release-summary.js [--evidence <path>] [--baseline <path>] [--lexicon <path>] [--capability-matrix <path>] [--out <path>] [--markdown-out <path>] [--fail-on-gate-fail] [--json]`: merge handoff release-evidence + baseline + lexicon + capability-matrix into one Moqui release gate summary (`passed | failed | incomplete`) with executable remediation recommendations.
838
+ - Default inputs:
839
+ - `.kiro/reports/release-evidence/handoff-runs.json`
840
+ - `.kiro/reports/release-evidence/moqui-template-baseline.json`
841
+ - `.kiro/reports/release-evidence/moqui-lexicon-audit.json`
842
+ - `.kiro/reports/handoff-capability-matrix.json`
843
+ - Default outputs:
844
+ - `.kiro/reports/release-evidence/moqui-release-summary.json`
845
+ - `.kiro/reports/release-evidence/moqui-release-summary.md`
846
+ - `--fail-on-gate-fail` exits with code `2` when summary gate is `failed`.
847
+
836
848
  Moqui standard rebuild helper (script-level recovery bootstrap):
837
849
  - `node scripts/moqui-standard-rebuild.js [--metadata <path>] [--out <path>] [--markdown-out <path>] [--bundle-out <path>] [--json]`: build a standard Moqui recovery bundle from metadata, including recommended SCE template matrix, recovery spec plan, handoff manifest seed, ontology seed, and page-copilot context contract.
838
850
  - Output now includes `recovery.readiness_matrix`, `recovery.readiness_summary`, and `recovery.prioritized_gaps` for template capability matrix scoring and remediation planning.
@@ -872,7 +884,7 @@ Recommended `.kiro/config/orchestrator.json`:
872
884
  }
873
885
  ```
874
886
 
875
- `rateLimit*` settings provide dedicated retry/backoff and adaptive parallel throttling when providers return 429 / too-many-requests errors. Engine retry now also honors `Retry-After` / `try again in ...` hints from provider error messages when present, and pauses launching new pending specs during the active backoff window to reduce request bursts (launch hold remains active even if adaptive parallel throttling is disabled).
887
+ `rateLimit*` settings provide dedicated retry/backoff and adaptive parallel throttling when providers return 429 / too-many-requests errors. Engine retry honors `Retry-After` / `try again in ...` hints from provider error messages and clamps final retry waits by `rateLimitBackoffMaxMs` to avoid unbounded pause windows. During active backoff windows, new pending spec launches are paused to reduce request bursts (launch hold remains active even if adaptive parallel throttling is disabled). `orchestrate stop` now interrupts pending retry waits immediately so long backoff does not look like a deadlock.
876
888
 
877
889
  ### Scene Template Engine
878
890
 
@@ -957,6 +969,9 @@ sce scene moqui-baseline --json
957
969
  # Script alias (same behavior)
958
970
  npm run report:moqui-baseline
959
971
 
972
+ # Consolidated Moqui release gate summary (recommended before tag/publish)
973
+ npm run report:moqui-summary
974
+
960
975
  # Score all scene templates instead of the default Moqui + orchestration subset
961
976
  sce scene moqui-baseline --include-all --json
962
977
 
@@ -977,6 +992,7 @@ sce scene moqui-baseline \
977
992
 
978
993
  Release workflow default:
979
994
  - Publishes `moqui-template-baseline.json` + `moqui-template-baseline.md` as release assets.
995
+ - Publishes `moqui-release-summary.json` + `moqui-release-summary.md` as release review assets.
980
996
  - Enforces baseline portfolio gate by default (`KSE_MOQUI_BASELINE_ENFORCE` defaults to `true` when unset).
981
997
 
982
998
  ### Moqui ERP Integration
@@ -33,6 +33,42 @@ Emergency bypass exists but is not recommended:
33
33
  - `--no-require-moqui-baseline`
34
34
  - `--no-require-capability-coverage`
35
35
 
36
+ ## Template Capability Matrix Contract
37
+
38
+ Use the baseline report as the canonical matrix contract (`.kiro/reports/moqui-template-baseline.json`):
39
+
40
+ | Matrix Dimension | Meaning | Default Gate Target |
41
+ | --- | --- | --- |
42
+ | `graph_valid.rate_percent` | Ontology graph structural validity | `100%` |
43
+ | `score_passed.rate_percent` | Semantic score above baseline threshold | `100%` |
44
+ | `entity_coverage.rate_percent` | Entity model coverage | `100%` |
45
+ | `relation_coverage.rate_percent` | Entity relation coverage | `100%` |
46
+ | `business_rule_coverage.rate_percent` | Business-rule presence coverage | `100%` |
47
+ | `business_rule_closed.among_covered_rate_percent` | No unmapped rules among covered templates | `100%` |
48
+ | `decision_coverage.rate_percent` | Decision logic presence coverage | `100%` |
49
+ | `decision_closed.among_covered_rate_percent` | No undecided decisions among covered templates | `100%` |
50
+ | `baseline_passed.rate_percent` | Full matrix closure rate | `100%` |
51
+
52
+ Trend regression should stay hard-gated by default:
53
+
54
+ - `compare.coverage_matrix_regressions.length` must be `0`
55
+ - `sce auto handoff run` default `--max-moqui-matrix-regressions 0`
56
+
57
+ ## External POC Handoff Requirements
58
+
59
+ When an upstream business project (e.g. a POC) feeds templates into sce, require the following by default:
60
+
61
+ - Every handoff spec contains:
62
+ - `custom/scene.yaml` with entity/service/screen binding refs
63
+ - `custom/scene-package.json` with explicit `capabilities.expected/provided`
64
+ - ontology semantics for entity, relation, business-rule, and decision dimensions
65
+ - Handoff evidence includes:
66
+ - latest `moqui-template-baseline.json|.md`
67
+ - latest `handoff-capability-matrix` report
68
+ - latest `moqui-lexicon-audit` report
69
+ - ontology batch report from `scene package-publish-batch --dry-run`
70
+ - New/updated templates must provide deterministic IDs and version bumps so baseline comparisons are stable across releases.
71
+
36
72
  ## One-Shot Intake Flow
37
73
 
38
74
  ```bash
@@ -60,6 +96,11 @@ node scripts/moqui-lexicon-audit.js \
60
96
  --fail-on-gap \
61
97
  --json
62
98
 
99
+ # 0.4) Consolidated release gate summary (single-file pass/fail/incomplete verdict)
100
+ node scripts/moqui-release-summary.js \
101
+ --fail-on-gate-fail \
102
+ --json
103
+
63
104
  # 1) Handoff close-loop
64
105
  sce auto handoff run --manifest docs/handoffs/handoff-manifest.json --json
65
106
 
@@ -99,6 +140,8 @@ Required artifacts for each intake batch:
99
140
  - `.kiro/reports/release-evidence/moqui-capability-coverage.md`
100
141
  - `.kiro/reports/release-evidence/moqui-lexicon-audit.json`
101
142
  - `.kiro/reports/release-evidence/moqui-lexicon-audit.md`
143
+ - `.kiro/reports/release-evidence/moqui-release-summary.json`
144
+ - `.kiro/reports/release-evidence/moqui-release-summary.md`
102
145
  - `.kiro/reports/handoff-capability-matrix.md` (or JSON equivalent from `sce auto handoff capability-matrix`)
103
146
  - `.kiro/reports/handoff-runs/<session>.json`
104
147
  - `.kiro/reports/scene-package-ontology-batch.json`
@@ -4701,6 +4701,67 @@ function buildBatchMetrics(results, totalGoals) {
4701
4701
  };
4702
4702
  }
4703
4703
 
4704
+ function applyAdaptiveRateLimitBackpressure({
4705
+ currentBatchParallel,
4706
+ currentBatchAgentBudget,
4707
+ rateLimitSignals,
4708
+ rateLimitBackoffMs,
4709
+ rateLimitLaunchHoldMs,
4710
+ inputGoals
4711
+ }) {
4712
+ const next = {
4713
+ batchParallel: Number.isInteger(currentBatchParallel) ? currentBatchParallel : 1,
4714
+ batchAgentBudget: currentBatchAgentBudget,
4715
+ applied: false,
4716
+ level: 'none',
4717
+ signalsPerGoal: 0
4718
+ };
4719
+
4720
+ const safeGoals = Math.max(1, Number(inputGoals) || 1);
4721
+ const normalizedSignals = Math.max(0, Number(rateLimitSignals) || 0);
4722
+ const normalizedBackoffMs = Math.max(0, Number(rateLimitBackoffMs) || 0);
4723
+ const normalizedLaunchHoldMs = Math.max(0, Number(rateLimitLaunchHoldMs) || 0);
4724
+ const signalsPerGoal = normalizedSignals / safeGoals;
4725
+ next.signalsPerGoal = Number(signalsPerGoal.toFixed(2));
4726
+
4727
+ if (normalizedSignals <= 0 && normalizedBackoffMs <= 0 && normalizedLaunchHoldMs <= 0) {
4728
+ return next;
4729
+ }
4730
+
4731
+ const severePressure = (
4732
+ signalsPerGoal >= 1.5 ||
4733
+ normalizedBackoffMs >= 4000 ||
4734
+ normalizedLaunchHoldMs >= 2000
4735
+ );
4736
+ next.level = severePressure ? 'severe' : 'mild';
4737
+
4738
+ const normalizePositiveInteger = (value, fallback = 1) => {
4739
+ const parsed = Number(value);
4740
+ if (!Number.isInteger(parsed) || parsed < 1) {
4741
+ return fallback;
4742
+ }
4743
+ return parsed;
4744
+ };
4745
+
4746
+ const currentParallel = normalizePositiveInteger(next.batchParallel, 1);
4747
+ const reducedParallel = severePressure
4748
+ ? Math.max(1, Math.floor(currentParallel / 2))
4749
+ : Math.max(1, currentParallel - 1);
4750
+ next.batchParallel = reducedParallel;
4751
+ next.applied = reducedParallel !== currentParallel;
4752
+
4753
+ if (currentBatchAgentBudget !== null && currentBatchAgentBudget !== undefined) {
4754
+ const currentBudget = normalizePositiveInteger(currentBatchAgentBudget, 1);
4755
+ const reducedBudget = severePressure
4756
+ ? Math.max(1, Math.floor(currentBudget / 2))
4757
+ : Math.max(1, currentBudget - 1);
4758
+ next.batchAgentBudget = reducedBudget;
4759
+ next.applied = next.applied || reducedBudget !== currentBudget;
4760
+ }
4761
+
4762
+ return next;
4763
+ }
4764
+
4704
4765
  async function runCloseLoopBatchGoals(goals, options) {
4705
4766
  const continueOnError = Boolean(options.continueOnError);
4706
4767
  const batchParallel = normalizeBatchParallel(options.batchParallel);
@@ -4996,16 +5057,25 @@ async function runCloseLoopBatchWithRetries(goals, options) {
4996
5057
  let nextBatchParallel = adaptiveBatchParallel;
4997
5058
  let nextBatchAgentBudget = adaptiveBatchAgentBudget;
4998
5059
  let adaptiveBackpressureApplied = false;
5060
+ let backpressureLevel = 'none';
5061
+ let roundRateLimitSignalsPerGoal = Number(
5062
+ (roundRateLimitSignals / Math.max(1, pendingEntries.length)).toFixed(2)
5063
+ );
4999
5064
  const hasRateLimitPressure = roundRateLimitSignals > 0 || roundRateLimitBackoffMs > 0 || roundMaxLaunchHoldMs > 0;
5000
5065
  if (retryStrategy === 'adaptive' && retryEntries.length > 0 && hasRateLimitPressure) {
5001
- if (nextBatchParallel > 1) {
5002
- nextBatchParallel -= 1;
5003
- adaptiveBackpressureApplied = true;
5004
- }
5005
- if (nextBatchAgentBudget !== null && nextBatchAgentBudget > 1) {
5006
- nextBatchAgentBudget -= 1;
5007
- adaptiveBackpressureApplied = true;
5008
- }
5066
+ const backpressure = applyAdaptiveRateLimitBackpressure({
5067
+ currentBatchParallel: adaptiveBatchParallel,
5068
+ currentBatchAgentBudget: adaptiveBatchAgentBudget,
5069
+ rateLimitSignals: roundRateLimitSignals,
5070
+ rateLimitBackoffMs: roundRateLimitBackoffMs,
5071
+ rateLimitLaunchHoldMs: roundMaxLaunchHoldMs,
5072
+ inputGoals: pendingEntries.length
5073
+ });
5074
+ nextBatchParallel = backpressure.batchParallel;
5075
+ nextBatchAgentBudget = backpressure.batchAgentBudget;
5076
+ adaptiveBackpressureApplied = backpressure.applied;
5077
+ backpressureLevel = backpressure.level;
5078
+ roundRateLimitSignalsPerGoal = backpressure.signalsPerGoal;
5009
5079
  }
5010
5080
 
5011
5081
  retryHistory.push({
@@ -5019,9 +5089,11 @@ async function runCloseLoopBatchWithRetries(goals, options) {
5019
5089
  unprocessed_goals: unprocessedCount,
5020
5090
  stopped_early: Boolean(run.stoppedEarly),
5021
5091
  rate_limit_signals: roundRateLimitSignals,
5092
+ rate_limit_signals_per_goal: roundRateLimitSignalsPerGoal,
5022
5093
  rate_limit_backoff_ms: roundRateLimitBackoffMs,
5023
5094
  rate_limit_launch_hold_ms: roundMaxLaunchHoldMs,
5024
5095
  adaptive_backpressure_applied: adaptiveBackpressureApplied,
5096
+ backpressure_level: backpressureLevel,
5025
5097
  next_batch_parallel: nextBatchParallel,
5026
5098
  next_batch_agent_budget: nextBatchAgentBudget
5027
5099
  });
@@ -107,6 +107,8 @@ class OrchestrationEngine extends EventEmitter {
107
107
  this._launchBudgetLastHoldSignalAt = 0;
108
108
  /** @type {number} last launch-budget hold duration emitted to telemetry (ms) */
109
109
  this._launchBudgetLastHoldMs = 0;
110
+ /** @type {Set<{timer: NodeJS.Timeout|null, resolve: (() => void)|null}>} cancellable sleep waiters */
111
+ this._pendingSleeps = new Set();
110
112
  /** @type {number} fallback wait timeout to avoid indefinite hangs when lifecycle events are missing */
111
113
  this._agentWaitTimeoutMs = (DEFAULT_AGENT_WAIT_TIMEOUT_SECONDS * 1000) + AGENT_WAIT_TIMEOUT_GRACE_MS;
112
114
  /** @type {() => number} */
@@ -230,6 +232,7 @@ class OrchestrationEngine extends EventEmitter {
230
232
  */
231
233
  async stop() {
232
234
  this._stopped = true;
235
+ this._cancelPendingSleeps();
233
236
 
234
237
  if (this._state !== 'running') {
235
238
  return;
@@ -520,10 +523,7 @@ class OrchestrationEngine extends EventEmitter {
520
523
  this._statusMonitor.updateSpecStatus(specName, 'pending', null, resolvedError);
521
524
 
522
525
  const retryDelayMs = isRateLimitError
523
- ? Math.max(
524
- this._calculateRateLimitBackoffMs(retryCount),
525
- this._extractRateLimitRetryAfterMs(resolvedError)
526
- )
526
+ ? this._resolveRateLimitRetryDelayMs(resolvedError, retryCount)
527
527
  : 0;
528
528
  if (retryDelayMs > 0) {
529
529
  this._onRateLimitSignal(retryDelayMs);
@@ -1156,16 +1156,73 @@ class OrchestrationEngine extends EventEmitter {
1156
1156
  return Math.max(1, Math.round(cappedBaseDelay * jitterFactor));
1157
1157
  }
1158
1158
 
1159
+ /**
1160
+ * Resolve final retry delay for rate-limit failures.
1161
+ * Uses larger of computed backoff and retry-after hint, then clamps to configured max.
1162
+ *
1163
+ * @param {string} error
1164
+ * @param {number} retryCount
1165
+ * @returns {number}
1166
+ * @private
1167
+ */
1168
+ _resolveRateLimitRetryDelayMs(error, retryCount) {
1169
+ const computedBackoffMs = this._calculateRateLimitBackoffMs(retryCount);
1170
+ const hintedRetryAfterMs = this._extractRateLimitRetryAfterMs(error);
1171
+ const candidateDelayMs = Math.max(computedBackoffMs, hintedRetryAfterMs);
1172
+ const maxDelayMs = this._toPositiveInteger(
1173
+ this._rateLimitBackoffMaxMs,
1174
+ DEFAULT_RATE_LIMIT_BACKOFF_MAX_MS
1175
+ );
1176
+ return Math.max(1, Math.min(candidateDelayMs, maxDelayMs));
1177
+ }
1178
+
1159
1179
  /**
1160
1180
  * @param {number} ms
1161
1181
  * @returns {Promise<void>}
1162
1182
  * @private
1163
1183
  */
1164
1184
  _sleep(ms) {
1165
- if (!ms || ms <= 0) {
1185
+ if (!ms || ms <= 0 || this._stopped) {
1166
1186
  return Promise.resolve();
1167
1187
  }
1168
- return new Promise((resolve) => setTimeout(resolve, ms));
1188
+ return new Promise((resolve) => {
1189
+ let settled = false;
1190
+ const entry = { timer: null, resolve: null };
1191
+ entry.resolve = () => {
1192
+ if (settled) {
1193
+ return;
1194
+ }
1195
+ settled = true;
1196
+ if (entry.timer) {
1197
+ clearTimeout(entry.timer);
1198
+ }
1199
+ this._pendingSleeps.delete(entry);
1200
+ resolve();
1201
+ };
1202
+ entry.timer = setTimeout(() => {
1203
+ if (entry.resolve) {
1204
+ entry.resolve();
1205
+ }
1206
+ }, ms);
1207
+ this._pendingSleeps.add(entry);
1208
+ });
1209
+ }
1210
+
1211
+ /**
1212
+ * Cancel all pending sleeps so stop() does not block behind long retry waits.
1213
+ *
1214
+ * @private
1215
+ */
1216
+ _cancelPendingSleeps() {
1217
+ if (!this._pendingSleeps || this._pendingSleeps.size === 0) {
1218
+ return;
1219
+ }
1220
+ for (const entry of Array.from(this._pendingSleeps)) {
1221
+ if (entry && typeof entry.resolve === 'function') {
1222
+ entry.resolve();
1223
+ }
1224
+ }
1225
+ this._pendingSleeps.clear();
1169
1226
  }
1170
1227
 
1171
1228
  /**
@@ -1300,6 +1357,7 @@ class OrchestrationEngine extends EventEmitter {
1300
1357
  * @private
1301
1358
  */
1302
1359
  _reset() {
1360
+ this._cancelPendingSleeps();
1303
1361
  this._runningAgents.clear();
1304
1362
  this._retryCounts.clear();
1305
1363
  this._failedSpecs.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scene-capability-engine",
3
- "version": "3.0.7",
3
+ "version": "3.0.8",
4
4
  "description": "SCE (Scene Capability Engine) - A CLI tool and npm package for spec-driven development with AI coding assistants.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -39,6 +39,7 @@
39
39
  "report:moqui-rebuild": "node scripts/moqui-standard-rebuild.js --json",
40
40
  "gate:moqui-rebuild": "node scripts/moqui-rebuild-gate.js",
41
41
  "report:moqui-baseline": "node scripts/moqui-template-baseline-report.js --json",
42
+ "report:moqui-summary": "node scripts/moqui-release-summary.js --json",
42
43
  "report:moqui-core-regression": "node scripts/moqui-core-regression-suite.js --json",
43
44
  "prepublishOnly": "npm run test:full && npm run test:skip-audit && npm run test:brand-consistency",
44
45
  "publish:manual": "npm publish --access public",