scene-capability-engine 3.0.7 → 3.1.0

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 (51) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/docs/331-poc-adaptation-roadmap.md +21 -2
  3. package/docs/331-poc-dual-track-integration-guide.md +10 -6
  4. package/docs/331-poc-weekly-delivery-checklist.md +15 -0
  5. package/docs/README.md +6 -0
  6. package/docs/command-reference.md +279 -5
  7. package/docs/handoff-profile-integration-guide.md +88 -0
  8. package/docs/interactive-customization/331-poc-sce-integration-checklist.md +148 -0
  9. package/docs/interactive-customization/README.md +354 -0
  10. package/docs/interactive-customization/adapter-extension-contract.md +55 -0
  11. package/docs/interactive-customization/adapter-extension-contract.sample.json +59 -0
  12. package/docs/interactive-customization/adapter-extension-contract.schema.json +192 -0
  13. package/docs/interactive-customization/change-intent.schema.json +72 -0
  14. package/docs/interactive-customization/change-plan.sample.json +41 -0
  15. package/docs/interactive-customization/change-plan.schema.json +125 -0
  16. package/docs/interactive-customization/cross-industry-replication-guide.md +49 -0
  17. package/docs/interactive-customization/dialogue-governance-policy-baseline.json +49 -0
  18. package/docs/interactive-customization/domain-pack-extension-flow.md +71 -0
  19. package/docs/interactive-customization/execution-record.schema.json +62 -0
  20. package/docs/interactive-customization/governance-alert-playbook.md +51 -0
  21. package/docs/interactive-customization/governance-report-template.md +46 -0
  22. package/docs/interactive-customization/governance-threshold-baseline.json +14 -0
  23. package/docs/interactive-customization/guardrail-policy-baseline.json +27 -0
  24. package/docs/interactive-customization/high-risk-action-catalog.json +22 -0
  25. package/docs/interactive-customization/moqui-adapter-interface.md +40 -0
  26. package/docs/interactive-customization/moqui-context-provider.sample.json +72 -0
  27. package/docs/interactive-customization/moqui-copilot-context-contract.json +50 -0
  28. package/docs/interactive-customization/moqui-copilot-integration-guide.md +100 -0
  29. package/docs/interactive-customization/moqui-interactive-template-playbook.md +94 -0
  30. package/docs/interactive-customization/non-technical-usability-report.md +57 -0
  31. package/docs/interactive-customization/page-context.sample.json +73 -0
  32. package/docs/interactive-customization/page-context.schema.json +150 -0
  33. package/docs/interactive-customization/phase-acceptance-evidence.md +110 -0
  34. package/docs/interactive-customization/runtime-mode-policy-baseline.json +99 -0
  35. package/docs/moqui-template-core-library-playbook.md +71 -0
  36. package/docs/release-checklist.md +29 -4
  37. package/docs/security-governance-default-baseline.md +53 -0
  38. package/docs/starter-kit/README.md +50 -0
  39. package/docs/starter-kit/handoff-manifest.starter.json +32 -0
  40. package/docs/starter-kit/handoff-profile-ci.sample.yml +53 -0
  41. package/docs/starter-kit/release.workflow.sample.yml +41 -0
  42. package/docs/zh/README.md +12 -0
  43. package/lib/auto/moqui-recovery-sequence.js +62 -0
  44. package/lib/commands/auto.js +325 -42
  45. package/lib/commands/scene.js +837 -0
  46. package/lib/data/moqui-capability-lexicon.json +14 -1
  47. package/lib/interactive-customization/change-plan-gate-core.js +201 -0
  48. package/lib/interactive-customization/index.js +9 -0
  49. package/lib/interactive-customization/moqui-interactive-adapter.js +732 -0
  50. package/lib/orchestrator/orchestration-engine.js +64 -6
  51. package/package.json +28 -2
@@ -6,6 +6,7 @@ const AutonomousEngine = require('../auto/autonomous-engine');
6
6
  const { mergeConfigs, DEFAULT_CONFIG } = require('../auto/config-schema');
7
7
  const { runAutoCloseLoop } = require('../auto/close-loop-runner');
8
8
  const { analyzeGoalSemantics } = require('../auto/semantic-decomposer');
9
+ const { buildMoquiRegressionRecoverySequenceLines } = require('../auto/moqui-recovery-sequence');
9
10
  const MOQUI_CAPABILITY_LEXICON = require('../data/moqui-capability-lexicon.json');
10
11
  const fs = require('fs-extra');
11
12
  const path = require('path');
@@ -27,8 +28,68 @@ const AUTO_HANDOFF_SCENE_PACKAGE_BATCH_TASK_QUEUE_FILE = '.kiro/auto/ontology-re
27
28
  const AUTO_HANDOFF_MOQUI_CAPABILITY_COVERAGE_JSON_FILE = '.kiro/reports/release-evidence/moqui-capability-coverage.json';
28
29
  const AUTO_HANDOFF_MOQUI_CAPABILITY_COVERAGE_MARKDOWN_FILE = '.kiro/reports/release-evidence/moqui-capability-coverage.md';
29
30
  const AUTO_HANDOFF_MOQUI_REMEDIATION_QUEUE_FILE = '.kiro/auto/moqui-remediation.lines';
31
+ const AUTO_HANDOFF_MOQUI_CLUSTER_REMEDIATION_FILE = '.kiro/auto/matrix-remediation.capability-clusters.json';
30
32
  const AUTO_HANDOFF_CLI_SCRIPT_FILE = path.resolve(__dirname, '..', '..', 'bin', 'scene-capability-engine.js');
31
33
  const MOQUI_CAPABILITY_LEXICON_INDEX = buildMoquiCapabilityLexiconIndex(MOQUI_CAPABILITY_LEXICON);
34
+ const AUTO_HANDOFF_POLICY_PROFILE_PRESETS = {
35
+ default: {
36
+ min_spec_success_rate: 100,
37
+ max_risk_level: 'high',
38
+ min_ontology_score: 0,
39
+ min_capability_coverage_percent: 100,
40
+ min_capability_semantic_percent: 100,
41
+ max_moqui_matrix_regressions: 0,
42
+ max_unmapped_rules: null,
43
+ max_undecided_decisions: null,
44
+ require_ontology_validation: true,
45
+ require_moqui_baseline: true,
46
+ require_scene_package_batch: true,
47
+ require_capability_coverage: true,
48
+ require_capability_semantic: true,
49
+ require_capability_lexicon: true,
50
+ require_release_gate_preflight: false,
51
+ dependency_batching: true,
52
+ release_evidence_window: 5
53
+ },
54
+ moqui: {
55
+ min_spec_success_rate: 100,
56
+ max_risk_level: 'high',
57
+ min_ontology_score: 0,
58
+ min_capability_coverage_percent: 100,
59
+ min_capability_semantic_percent: 100,
60
+ max_moqui_matrix_regressions: 0,
61
+ max_unmapped_rules: null,
62
+ max_undecided_decisions: null,
63
+ require_ontology_validation: true,
64
+ require_moqui_baseline: true,
65
+ require_scene_package_batch: true,
66
+ require_capability_coverage: true,
67
+ require_capability_semantic: true,
68
+ require_capability_lexicon: true,
69
+ require_release_gate_preflight: false,
70
+ dependency_batching: true,
71
+ release_evidence_window: 5
72
+ },
73
+ enterprise: {
74
+ min_spec_success_rate: 100,
75
+ max_risk_level: 'medium',
76
+ min_ontology_score: 0,
77
+ min_capability_coverage_percent: 100,
78
+ min_capability_semantic_percent: 100,
79
+ max_moqui_matrix_regressions: 0,
80
+ max_unmapped_rules: null,
81
+ max_undecided_decisions: null,
82
+ require_ontology_validation: true,
83
+ require_moqui_baseline: true,
84
+ require_scene_package_batch: true,
85
+ require_capability_coverage: true,
86
+ require_capability_semantic: true,
87
+ require_capability_lexicon: true,
88
+ require_release_gate_preflight: true,
89
+ dependency_batching: true,
90
+ release_evidence_window: 10
91
+ }
92
+ };
32
93
 
33
94
  /**
34
95
  * Register auto commands
@@ -1532,6 +1593,7 @@ function registerAutoCommands(program) {
1532
1593
  .command('capability-matrix')
1533
1594
  .description('Build Moqui template capability matrix from handoff manifest and local template library')
1534
1595
  .requiredOption('--manifest <path>', 'Path to handoff-manifest.json')
1596
+ .option('--profile <profile>', 'Handoff policy profile: default|moqui|enterprise (default: default)', 'default')
1535
1597
  .option('--strict', 'Fail when manifest validation contains errors')
1536
1598
  .option('--strict-warnings', 'Fail when manifest validation contains warnings')
1537
1599
  .option('--min-capability-coverage <n>', 'Minimum Moqui capability coverage percent (default: 100)', parseFloat)
@@ -1567,6 +1629,7 @@ function registerAutoCommands(program) {
1567
1629
  console.log(chalk.blue('Auto handoff capability matrix:'));
1568
1630
  console.log(chalk.gray(` Status: ${result.status}`));
1569
1631
  console.log(chalk.gray(` Manifest: ${result.manifest_path}`));
1632
+ console.log(chalk.gray(` Policy profile: ${result.policy && result.policy.profile ? result.policy.profile : 'default'}`));
1570
1633
  console.log(chalk.gray(` Capabilities: ${result.handoff.capability_count}`));
1571
1634
  if (result.capability_coverage && result.capability_coverage.summary) {
1572
1635
  const summary = result.capability_coverage.summary;
@@ -1871,6 +1934,7 @@ function registerAutoCommands(program) {
1871
1934
  .command('run')
1872
1935
  .description('Execute handoff integration pipeline: plan -> queue -> close-loop-batch -> observability')
1873
1936
  .requiredOption('--manifest <path>', 'Path to handoff-manifest.json')
1937
+ .option('--profile <profile>', 'Handoff policy profile: default|moqui|enterprise (default: default)', 'default')
1874
1938
  .option('--out <path>', 'Write handoff run report JSON to file')
1875
1939
  .option('--queue-out <path>', `Queue output file (default: ${AUTO_HANDOFF_DEFAULT_QUEUE_FILE})`, AUTO_HANDOFF_DEFAULT_QUEUE_FILE)
1876
1940
  .option('--append', 'Append generated goals to existing queue file')
@@ -1889,7 +1953,7 @@ function registerAutoCommands(program) {
1889
1953
  .option('--batch-retry-until-complete', 'Retry until all goals complete or retry max is reached')
1890
1954
  .option('--batch-retry-max-rounds <n>', 'Max retry rounds when --batch-retry-until-complete is enabled', parseInt)
1891
1955
  .option('--min-spec-success-rate <n>', 'Gate: minimum handoff spec success rate percent (default: 100)', parseFloat)
1892
- .option('--max-risk-level <level>', 'Gate: maximum allowed risk level (low|medium|high)', 'high')
1956
+ .option('--max-risk-level <level>', 'Gate: maximum allowed risk level (low|medium|high)')
1893
1957
  .option('--min-ontology-score <n>', 'Gate: minimum ontology quality score (0-100, default: 0)', parseFloat)
1894
1958
  .option('--max-unmapped-rules <n>', 'Gate: maximum allowed unmapped business rules (optional)', parseInt)
1895
1959
  .option('--max-undecided-decisions <n>', 'Gate: maximum allowed undecided decisions (optional)', parseInt)
@@ -1919,6 +1983,7 @@ function registerAutoCommands(program) {
1919
1983
  console.log(chalk.gray(` Session: ${result.session_id}`));
1920
1984
  console.log(chalk.gray(` Status: ${result.status}`));
1921
1985
  console.log(chalk.gray(` Manifest: ${result.manifest_path}`));
1986
+ console.log(chalk.gray(` Policy profile: ${result.policy && result.policy.profile ? result.policy.profile : 'default'}`));
1922
1987
  console.log(chalk.gray(` Specs: ${result.handoff && result.handoff.spec_count ? result.handoff.spec_count : 0}`));
1923
1988
  console.log(chalk.gray(` Queue goals: ${result.queue && result.queue.goal_count ? result.queue.goal_count : 0}`));
1924
1989
  if (result.template_diff) {
@@ -4701,6 +4766,67 @@ function buildBatchMetrics(results, totalGoals) {
4701
4766
  };
4702
4767
  }
4703
4768
 
4769
+ function applyAdaptiveRateLimitBackpressure({
4770
+ currentBatchParallel,
4771
+ currentBatchAgentBudget,
4772
+ rateLimitSignals,
4773
+ rateLimitBackoffMs,
4774
+ rateLimitLaunchHoldMs,
4775
+ inputGoals
4776
+ }) {
4777
+ const next = {
4778
+ batchParallel: Number.isInteger(currentBatchParallel) ? currentBatchParallel : 1,
4779
+ batchAgentBudget: currentBatchAgentBudget,
4780
+ applied: false,
4781
+ level: 'none',
4782
+ signalsPerGoal: 0
4783
+ };
4784
+
4785
+ const safeGoals = Math.max(1, Number(inputGoals) || 1);
4786
+ const normalizedSignals = Math.max(0, Number(rateLimitSignals) || 0);
4787
+ const normalizedBackoffMs = Math.max(0, Number(rateLimitBackoffMs) || 0);
4788
+ const normalizedLaunchHoldMs = Math.max(0, Number(rateLimitLaunchHoldMs) || 0);
4789
+ const signalsPerGoal = normalizedSignals / safeGoals;
4790
+ next.signalsPerGoal = Number(signalsPerGoal.toFixed(2));
4791
+
4792
+ if (normalizedSignals <= 0 && normalizedBackoffMs <= 0 && normalizedLaunchHoldMs <= 0) {
4793
+ return next;
4794
+ }
4795
+
4796
+ const severePressure = (
4797
+ signalsPerGoal >= 1.5 ||
4798
+ normalizedBackoffMs >= 4000 ||
4799
+ normalizedLaunchHoldMs >= 2000
4800
+ );
4801
+ next.level = severePressure ? 'severe' : 'mild';
4802
+
4803
+ const normalizePositiveInteger = (value, fallback = 1) => {
4804
+ const parsed = Number(value);
4805
+ if (!Number.isInteger(parsed) || parsed < 1) {
4806
+ return fallback;
4807
+ }
4808
+ return parsed;
4809
+ };
4810
+
4811
+ const currentParallel = normalizePositiveInteger(next.batchParallel, 1);
4812
+ const reducedParallel = severePressure
4813
+ ? Math.max(1, Math.floor(currentParallel / 2))
4814
+ : Math.max(1, currentParallel - 1);
4815
+ next.batchParallel = reducedParallel;
4816
+ next.applied = reducedParallel !== currentParallel;
4817
+
4818
+ if (currentBatchAgentBudget !== null && currentBatchAgentBudget !== undefined) {
4819
+ const currentBudget = normalizePositiveInteger(currentBatchAgentBudget, 1);
4820
+ const reducedBudget = severePressure
4821
+ ? Math.max(1, Math.floor(currentBudget / 2))
4822
+ : Math.max(1, currentBudget - 1);
4823
+ next.batchAgentBudget = reducedBudget;
4824
+ next.applied = next.applied || reducedBudget !== currentBudget;
4825
+ }
4826
+
4827
+ return next;
4828
+ }
4829
+
4704
4830
  async function runCloseLoopBatchGoals(goals, options) {
4705
4831
  const continueOnError = Boolean(options.continueOnError);
4706
4832
  const batchParallel = normalizeBatchParallel(options.batchParallel);
@@ -4996,16 +5122,25 @@ async function runCloseLoopBatchWithRetries(goals, options) {
4996
5122
  let nextBatchParallel = adaptiveBatchParallel;
4997
5123
  let nextBatchAgentBudget = adaptiveBatchAgentBudget;
4998
5124
  let adaptiveBackpressureApplied = false;
5125
+ let backpressureLevel = 'none';
5126
+ let roundRateLimitSignalsPerGoal = Number(
5127
+ (roundRateLimitSignals / Math.max(1, pendingEntries.length)).toFixed(2)
5128
+ );
4999
5129
  const hasRateLimitPressure = roundRateLimitSignals > 0 || roundRateLimitBackoffMs > 0 || roundMaxLaunchHoldMs > 0;
5000
5130
  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
- }
5131
+ const backpressure = applyAdaptiveRateLimitBackpressure({
5132
+ currentBatchParallel: adaptiveBatchParallel,
5133
+ currentBatchAgentBudget: adaptiveBatchAgentBudget,
5134
+ rateLimitSignals: roundRateLimitSignals,
5135
+ rateLimitBackoffMs: roundRateLimitBackoffMs,
5136
+ rateLimitLaunchHoldMs: roundMaxLaunchHoldMs,
5137
+ inputGoals: pendingEntries.length
5138
+ });
5139
+ nextBatchParallel = backpressure.batchParallel;
5140
+ nextBatchAgentBudget = backpressure.batchAgentBudget;
5141
+ adaptiveBackpressureApplied = backpressure.applied;
5142
+ backpressureLevel = backpressure.level;
5143
+ roundRateLimitSignalsPerGoal = backpressure.signalsPerGoal;
5009
5144
  }
5010
5145
 
5011
5146
  retryHistory.push({
@@ -5019,9 +5154,11 @@ async function runCloseLoopBatchWithRetries(goals, options) {
5019
5154
  unprocessed_goals: unprocessedCount,
5020
5155
  stopped_early: Boolean(run.stoppedEarly),
5021
5156
  rate_limit_signals: roundRateLimitSignals,
5157
+ rate_limit_signals_per_goal: roundRateLimitSignalsPerGoal,
5022
5158
  rate_limit_backoff_ms: roundRateLimitBackoffMs,
5023
5159
  rate_limit_launch_hold_ms: roundMaxLaunchHoldMs,
5024
5160
  adaptive_backpressure_applied: adaptiveBackpressureApplied,
5161
+ backpressure_level: backpressureLevel,
5025
5162
  next_batch_parallel: nextBatchParallel,
5026
5163
  next_batch_agent_budget: nextBatchAgentBudget
5027
5164
  });
@@ -8640,6 +8777,12 @@ function buildAutoHandoffRegressionRecommendations(payload = {}) {
8640
8777
  'Recover Moqui matrix regressions and rerun baseline gate: ' +
8641
8778
  '`sce scene moqui-baseline --include-all --compare-with .kiro/reports/release-evidence/moqui-template-baseline.json --json`.'
8642
8779
  );
8780
+ for (const line of buildMoquiRegressionRecoverySequenceLines({
8781
+ wrapCommands: true,
8782
+ withPeriod: true
8783
+ })) {
8784
+ push(line);
8785
+ }
8643
8786
  }
8644
8787
 
8645
8788
  if ((payload.window && Number(payload.window.actual) > 0) && (payload.window.requested !== payload.window.actual)) {
@@ -10778,29 +10921,144 @@ function normalizeHandoffReleaseEvidenceWindow(windowCandidate) {
10778
10921
  return parsed;
10779
10922
  }
10780
10923
 
10924
+ function normalizeAutoHandoffPolicyProfile(profileCandidate, optionName = '--profile') {
10925
+ const normalized = typeof profileCandidate === 'string'
10926
+ ? profileCandidate.trim().toLowerCase()
10927
+ : 'default';
10928
+ if (!normalized) {
10929
+ return 'default';
10930
+ }
10931
+ if (!AUTO_HANDOFF_POLICY_PROFILE_PRESETS[normalized]) {
10932
+ const allowed = Object.keys(AUTO_HANDOFF_POLICY_PROFILE_PRESETS).join(', ');
10933
+ throw new Error(`${optionName} must be one of: ${allowed}.`);
10934
+ }
10935
+ return normalized;
10936
+ }
10937
+
10938
+ function resolveAutoHandoffPolicyPreset(profileCandidate, optionName) {
10939
+ const profile = normalizeAutoHandoffPolicyProfile(profileCandidate, optionName);
10940
+ const preset = AUTO_HANDOFF_POLICY_PROFILE_PRESETS[profile];
10941
+ return {
10942
+ profile,
10943
+ preset: {
10944
+ ...preset
10945
+ }
10946
+ };
10947
+ }
10948
+
10949
+ function resolveAutoHandoffPolicyOptionNumber(valueCandidate, fallbackValue) {
10950
+ if (valueCandidate === undefined || valueCandidate === null || valueCandidate === '') {
10951
+ return fallbackValue;
10952
+ }
10953
+ return valueCandidate;
10954
+ }
10955
+
10956
+ function resolveAutoHandoffPolicyOptionBoolean(valueCandidate, fallbackValue) {
10957
+ if (valueCandidate === undefined || valueCandidate === null) {
10958
+ return fallbackValue === true;
10959
+ }
10960
+ return valueCandidate === true;
10961
+ }
10962
+
10781
10963
  function buildAutoHandoffRunPolicy(options = {}) {
10964
+ const { profile, preset } = resolveAutoHandoffPolicyPreset(options.profile, '--profile');
10782
10965
  return {
10783
- min_spec_success_rate: normalizeHandoffMinSpecSuccessRate(options.minSpecSuccessRate),
10784
- max_risk_level: normalizeHandoffRiskLevel(options.maxRiskLevel),
10785
- min_ontology_score: normalizeHandoffMinOntologyScore(options.minOntologyScore),
10786
- min_capability_coverage_percent: normalizeHandoffMinCapabilityCoverage(options.minCapabilityCoverage),
10787
- max_moqui_matrix_regressions: normalizeHandoffMaxMoquiMatrixRegressions(options.maxMoquiMatrixRegressions),
10966
+ profile,
10967
+ min_spec_success_rate: normalizeHandoffMinSpecSuccessRate(
10968
+ resolveAutoHandoffPolicyOptionNumber(options.minSpecSuccessRate, preset.min_spec_success_rate)
10969
+ ),
10970
+ max_risk_level: normalizeHandoffRiskLevel(
10971
+ resolveAutoHandoffPolicyOptionNumber(options.maxRiskLevel, preset.max_risk_level)
10972
+ ),
10973
+ min_ontology_score: normalizeHandoffMinOntologyScore(
10974
+ resolveAutoHandoffPolicyOptionNumber(options.minOntologyScore, preset.min_ontology_score)
10975
+ ),
10976
+ min_capability_coverage_percent: normalizeHandoffMinCapabilityCoverage(
10977
+ resolveAutoHandoffPolicyOptionNumber(
10978
+ options.minCapabilityCoverage,
10979
+ preset.min_capability_coverage_percent
10980
+ )
10981
+ ),
10982
+ max_moqui_matrix_regressions: normalizeHandoffMaxMoquiMatrixRegressions(
10983
+ resolveAutoHandoffPolicyOptionNumber(
10984
+ options.maxMoquiMatrixRegressions,
10985
+ preset.max_moqui_matrix_regressions
10986
+ )
10987
+ ),
10788
10988
  max_unmapped_rules: normalizeHandoffOptionalNonNegativeInteger(
10789
- options.maxUnmappedRules,
10989
+ resolveAutoHandoffPolicyOptionNumber(options.maxUnmappedRules, preset.max_unmapped_rules),
10790
10990
  '--max-unmapped-rules'
10791
10991
  ),
10792
10992
  max_undecided_decisions: normalizeHandoffOptionalNonNegativeInteger(
10793
- options.maxUndecidedDecisions,
10993
+ resolveAutoHandoffPolicyOptionNumber(options.maxUndecidedDecisions, preset.max_undecided_decisions),
10794
10994
  '--max-undecided-decisions'
10795
10995
  ),
10796
- require_ontology_validation: options.requireOntologyValidation !== false,
10797
- require_moqui_baseline: options.requireMoquiBaseline !== false,
10798
- require_scene_package_batch: options.requireScenePackageBatch !== false,
10799
- require_capability_coverage: options.requireCapabilityCoverage !== false,
10800
- require_capability_lexicon: options.requireCapabilityLexicon !== false,
10801
- require_release_gate_preflight: options.requireReleaseGatePreflight === true,
10802
- dependency_batching: options.dependencyBatching !== false,
10803
- release_evidence_window: normalizeHandoffReleaseEvidenceWindow(options.releaseEvidenceWindow)
10996
+ require_ontology_validation: resolveAutoHandoffPolicyOptionBoolean(
10997
+ options.requireOntologyValidation,
10998
+ preset.require_ontology_validation
10999
+ ),
11000
+ require_moqui_baseline: resolveAutoHandoffPolicyOptionBoolean(
11001
+ options.requireMoquiBaseline,
11002
+ preset.require_moqui_baseline
11003
+ ),
11004
+ require_scene_package_batch: resolveAutoHandoffPolicyOptionBoolean(
11005
+ options.requireScenePackageBatch,
11006
+ preset.require_scene_package_batch
11007
+ ),
11008
+ require_capability_coverage: resolveAutoHandoffPolicyOptionBoolean(
11009
+ options.requireCapabilityCoverage,
11010
+ preset.require_capability_coverage
11011
+ ),
11012
+ require_capability_lexicon: resolveAutoHandoffPolicyOptionBoolean(
11013
+ options.requireCapabilityLexicon,
11014
+ preset.require_capability_lexicon
11015
+ ),
11016
+ require_release_gate_preflight: resolveAutoHandoffPolicyOptionBoolean(
11017
+ options.requireReleaseGatePreflight,
11018
+ preset.require_release_gate_preflight
11019
+ ),
11020
+ dependency_batching: resolveAutoHandoffPolicyOptionBoolean(
11021
+ options.dependencyBatching,
11022
+ preset.dependency_batching
11023
+ ),
11024
+ release_evidence_window: normalizeHandoffReleaseEvidenceWindow(
11025
+ resolveAutoHandoffPolicyOptionNumber(options.releaseEvidenceWindow, preset.release_evidence_window)
11026
+ )
11027
+ };
11028
+ }
11029
+
11030
+ function buildAutoHandoffCapabilityMatrixPolicy(options = {}) {
11031
+ const { profile, preset } = resolveAutoHandoffPolicyPreset(options.profile, '--profile');
11032
+ return {
11033
+ profile,
11034
+ min_capability_coverage_percent: normalizeHandoffMinCapabilityCoverage(
11035
+ resolveAutoHandoffPolicyOptionNumber(
11036
+ options.minCapabilityCoverage,
11037
+ preset.min_capability_coverage_percent
11038
+ )
11039
+ ),
11040
+ min_capability_semantic_percent: normalizeHandoffMinCapabilitySemantic(
11041
+ resolveAutoHandoffPolicyOptionNumber(
11042
+ options.minCapabilitySemantic,
11043
+ preset.min_capability_semantic_percent
11044
+ )
11045
+ ),
11046
+ require_capability_coverage: resolveAutoHandoffPolicyOptionBoolean(
11047
+ options.requireCapabilityCoverage,
11048
+ preset.require_capability_coverage
11049
+ ),
11050
+ require_capability_semantic: resolveAutoHandoffPolicyOptionBoolean(
11051
+ options.requireCapabilitySemantic,
11052
+ preset.require_capability_semantic
11053
+ ),
11054
+ require_capability_lexicon: resolveAutoHandoffPolicyOptionBoolean(
11055
+ options.requireCapabilityLexicon,
11056
+ preset.require_capability_lexicon
11057
+ ),
11058
+ require_moqui_baseline: resolveAutoHandoffPolicyOptionBoolean(
11059
+ options.requireMoquiBaseline,
11060
+ preset.require_moqui_baseline
11061
+ )
10804
11062
  };
10805
11063
  }
10806
11064
 
@@ -11669,6 +11927,27 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
11669
11927
  const processedGoals = Number(summary && summary.processed_goals) || 0;
11670
11928
  const failedGoals = Number(summary && summary.failed_goals) || 0;
11671
11929
  const hasPendingOrFailed = totalGoals > 0 && (failedGoals > 0 || processedGoals < totalGoals);
11930
+ const moquiBaseline = result && result.moqui_baseline && typeof result.moqui_baseline === 'object'
11931
+ ? result.moqui_baseline
11932
+ : null;
11933
+ const moquiSummary = moquiBaseline && moquiBaseline.summary && typeof moquiBaseline.summary === 'object'
11934
+ ? moquiBaseline.summary
11935
+ : null;
11936
+ const moquiCompare = moquiBaseline && moquiBaseline.compare && typeof moquiBaseline.compare === 'object'
11937
+ ? moquiBaseline.compare
11938
+ : {};
11939
+ const moquiCoverageRegressions = buildAutoHandoffMoquiCoverageRegressions(moquiCompare);
11940
+ const pushMoquiClusterFirstRecoverySequence = () => {
11941
+ const lines = buildMoquiRegressionRecoverySequenceLines({
11942
+ clusterGoalsArg: quoteCliArg(AUTO_HANDOFF_MOQUI_CLUSTER_REMEDIATION_FILE),
11943
+ baselineArg: quoteCliArg(AUTO_HANDOFF_MOQUI_BASELINE_JSON_FILE),
11944
+ wrapCommands: false,
11945
+ withPeriod: false
11946
+ });
11947
+ for (const line of lines) {
11948
+ push(line);
11949
+ }
11950
+ };
11672
11951
 
11673
11952
  if (manifestPath && result.session_id && hasPendingOrFailed) {
11674
11953
  push(
@@ -11762,18 +12041,11 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
11762
12041
  toAutoHandoffCliPath(projectPath, result.remediation_queue.file)
11763
12042
  )} --format lines --json`
11764
12043
  );
12044
+ if (moquiCoverageRegressions.length > 0) {
12045
+ pushMoquiClusterFirstRecoverySequence();
12046
+ }
11765
12047
  }
11766
12048
 
11767
- const moquiBaseline = result && result.moqui_baseline && typeof result.moqui_baseline === 'object'
11768
- ? result.moqui_baseline
11769
- : null;
11770
- const moquiSummary = moquiBaseline && moquiBaseline.summary && typeof moquiBaseline.summary === 'object'
11771
- ? moquiBaseline.summary
11772
- : null;
11773
- const moquiCompare = moquiBaseline && moquiBaseline.compare && typeof moquiBaseline.compare === 'object'
11774
- ? moquiBaseline.compare
11775
- : {};
11776
- const moquiCoverageRegressions = buildAutoHandoffMoquiCoverageRegressions(moquiCompare);
11777
12049
  if (moquiBaseline && moquiBaseline.status === 'error') {
11778
12050
  push('sce scene moqui-baseline --json');
11779
12051
  } else if (moquiSummary && moquiSummary.portfolio_passed === false) {
@@ -11795,6 +12067,7 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
11795
12067
  'sce scene moqui-baseline --include-all ' +
11796
12068
  '--compare-with .kiro/reports/release-evidence/moqui-template-baseline.json --json'
11797
12069
  );
12070
+ pushMoquiClusterFirstRecoverySequence();
11798
12071
  if (manifestPath) {
11799
12072
  push(
11800
12073
  `sce auto handoff run --manifest ${manifestCli} ` +
@@ -13337,6 +13610,14 @@ function buildAutoHandoffCapabilityMatrixRecommendations(result = {}) {
13337
13610
  `Recover Moqui matrix regressions: ` +
13338
13611
  `${baselineRegressions.slice(0, 3).map(item => `${item.label}:${item.delta_rate_percent}%`).join(' | ')}`
13339
13612
  );
13613
+ for (const line of buildMoquiRegressionRecoverySequenceLines({
13614
+ clusterGoalsArg: quoteCliArg(AUTO_HANDOFF_MOQUI_CLUSTER_REMEDIATION_FILE),
13615
+ baselineArg: quoteCliArg(AUTO_HANDOFF_MOQUI_BASELINE_JSON_FILE),
13616
+ wrapCommands: false,
13617
+ withPeriod: false
13618
+ })) {
13619
+ push(line);
13620
+ }
13340
13621
  }
13341
13622
  if (capabilityCoverage.status === 'skipped') {
13342
13623
  push('Declare `capabilities` in handoff manifest to enable capability matrix coverage gates.');
@@ -13433,6 +13714,7 @@ function renderAutoHandoffCapabilityMatrixMarkdown(payload = {}) {
13433
13714
  `- Specs: ${handoff.spec_count !== undefined ? handoff.spec_count : 'n/a'}`,
13434
13715
  `- Templates: ${handoff.template_count !== undefined ? handoff.template_count : 'n/a'}`,
13435
13716
  `- Capabilities: ${handoff.capability_count !== undefined ? handoff.capability_count : 'n/a'}`,
13717
+ `- Policy profile: ${policy.profile || 'default'}`,
13436
13718
  `- Min capability coverage: ${policy.min_capability_coverage_percent !== undefined ? `${policy.min_capability_coverage_percent}%` : 'n/a'}`,
13437
13719
  `- Min capability semantic completeness: ${policy.min_capability_semantic_percent !== undefined ? `${policy.min_capability_semantic_percent}%` : 'n/a'}`,
13438
13720
  `- Capability lexicon gate: ${policy.require_capability_lexicon === false ? 'disabled' : 'enabled'}`,
@@ -13527,14 +13809,7 @@ async function buildAutoHandoffCapabilityMatrix(projectPath, options = {}) {
13527
13809
  strictWarnings: options.strictWarnings
13528
13810
  });
13529
13811
 
13530
- const policy = {
13531
- min_capability_coverage_percent: normalizeHandoffMinCapabilityCoverage(options.minCapabilityCoverage),
13532
- min_capability_semantic_percent: normalizeHandoffMinCapabilitySemantic(options.minCapabilitySemantic),
13533
- require_capability_coverage: true,
13534
- require_capability_semantic: options.requireCapabilitySemantic !== false,
13535
- require_capability_lexicon: options.requireCapabilityLexicon !== false,
13536
- require_moqui_baseline: true
13537
- };
13812
+ const policy = buildAutoHandoffCapabilityMatrixPolicy(options);
13538
13813
 
13539
13814
  const [templateDiff, moquiBaseline, capabilityCoverage] = await Promise.all([
13540
13815
  buildAutoHandoffTemplateDiff(projectPath, { handoff: plan.handoff }),
@@ -18839,6 +19114,10 @@ function buildGovernanceRecommendations(summary) {
18839
19114
  '`sce scene moqui-baseline --include-all ' +
18840
19115
  '--compare-with .kiro/reports/release-evidence/moqui-template-baseline.json --json`.'
18841
19116
  );
19117
+ recommendations.push(...buildMoquiRegressionRecoverySequenceLines({
19118
+ wrapCommands: true,
19119
+ withPeriod: true
19120
+ }));
18842
19121
  }
18843
19122
  }
18844
19123
 
@@ -20320,6 +20599,10 @@ function buildGovernanceCloseLoopRecommendations(finalAssessment, stopReason, st
20320
20599
  '`sce scene moqui-baseline --include-all ' +
20321
20600
  '--compare-with .kiro/reports/release-evidence/moqui-template-baseline.json --json`.'
20322
20601
  );
20602
+ base.push(...buildMoquiRegressionRecoverySequenceLines({
20603
+ wrapCommands: true,
20604
+ withPeriod: true
20605
+ }));
20323
20606
  }
20324
20607
  if (reasons.some(item => `${item}`.startsWith('handoff-capability-') && `${item}`.includes('unknown'))) {
20325
20608
  base.push(