scene-capability-engine 3.6.39 → 3.6.44
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 +45 -0
- package/bin/scene-capability-engine.js +42 -2
- package/docs/developer-guide.md +1 -1
- package/docs/releases/README.md +5 -0
- package/docs/releases/v3.6.40.md +19 -0
- package/docs/releases/v3.6.41.md +20 -0
- package/docs/releases/v3.6.42.md +19 -0
- package/docs/releases/v3.6.43.md +17 -0
- package/docs/releases/v3.6.44.md +17 -0
- package/docs/spec-collaboration-guide.md +1 -1
- package/docs/zh/releases/README.md +5 -0
- package/docs/zh/releases/v3.6.40.md +19 -0
- package/docs/zh/releases/v3.6.41.md +20 -0
- package/docs/zh/releases/v3.6.42.md +19 -0
- package/docs/zh/releases/v3.6.43.md +17 -0
- package/docs/zh/releases/v3.6.44.md +17 -0
- package/lib/adoption/adoption-logger.js +1 -1
- package/lib/adoption/adoption-strategy.js +29 -29
- package/lib/adoption/detection-engine.js +16 -13
- package/lib/adoption/smart-orchestrator.js +3 -3
- package/lib/adoption/strategy-selector.js +19 -15
- package/lib/adoption/template-sync.js +3 -3
- package/lib/auto/autonomous-engine.js +5 -5
- package/lib/auto/handoff-release-gate-history-loaders-service.js +24 -4
- package/lib/auto/handoff-run-service.js +37 -0
- package/lib/backup/backup-system.js +10 -10
- package/lib/collab/collab-manager.js +8 -5
- package/lib/collab/dependency-manager.js +1 -1
- package/lib/commands/adopt.js +2 -2
- package/lib/commands/auto.js +239 -97
- package/lib/commands/collab.js +10 -4
- package/lib/commands/status.js +3 -3
- package/lib/commands/studio.js +8 -0
- package/lib/repo/config-manager.js +2 -2
- package/lib/spec/bootstrap/context-collector.js +5 -4
- package/lib/spec-gate/rules/default-rules.js +8 -8
- package/lib/upgrade/migration-engine.js +5 -5
- package/lib/upgrade/migrations/1.0.0-to-1.1.0.js +3 -3
- package/lib/utils/tool-detector.js +4 -4
- package/lib/utils/validation.js +6 -6
- package/lib/workspace/multi/workspace-context-resolver.js +3 -3
- package/lib/workspace/multi/workspace-registry.js +3 -3
- package/lib/workspace/multi/workspace-state-manager.js +3 -3
- package/lib/workspace/spec-delivery-audit.js +553 -0
- package/package.json +1 -1
package/lib/commands/auto.js
CHANGED
|
@@ -60,6 +60,7 @@ const fs = require('fs-extra');
|
|
|
60
60
|
const path = require('path');
|
|
61
61
|
const chalk = require('chalk');
|
|
62
62
|
const { spawnSync } = require('child_process');
|
|
63
|
+
const { auditSpecDeliverySync } = require('../workspace/spec-delivery-audit');
|
|
63
64
|
|
|
64
65
|
const AUTO_ARCHIVE_SCHEMA_VERSION = '1.0';
|
|
65
66
|
const AUTO_ARCHIVE_SCHEMA_SUPPORTED_VERSIONS = new Set([AUTO_ARCHIVE_SCHEMA_VERSION]);
|
|
@@ -95,6 +96,7 @@ const AUTO_HANDOFF_POLICY_PROFILE_PRESETS = {
|
|
|
95
96
|
require_capability_coverage: true,
|
|
96
97
|
require_capability_semantic: true,
|
|
97
98
|
require_capability_lexicon: true,
|
|
99
|
+
require_spec_delivery_sync: true,
|
|
98
100
|
require_release_gate_preflight: true,
|
|
99
101
|
dependency_batching: true,
|
|
100
102
|
release_evidence_window: 5
|
|
@@ -114,6 +116,7 @@ const AUTO_HANDOFF_POLICY_PROFILE_PRESETS = {
|
|
|
114
116
|
require_capability_coverage: true,
|
|
115
117
|
require_capability_semantic: true,
|
|
116
118
|
require_capability_lexicon: true,
|
|
119
|
+
require_spec_delivery_sync: true,
|
|
117
120
|
require_release_gate_preflight: true,
|
|
118
121
|
dependency_batching: true,
|
|
119
122
|
release_evidence_window: 5
|
|
@@ -133,6 +136,7 @@ const AUTO_HANDOFF_POLICY_PROFILE_PRESETS = {
|
|
|
133
136
|
require_capability_coverage: true,
|
|
134
137
|
require_capability_semantic: true,
|
|
135
138
|
require_capability_lexicon: true,
|
|
139
|
+
require_spec_delivery_sync: true,
|
|
136
140
|
require_release_gate_preflight: true,
|
|
137
141
|
dependency_batching: true,
|
|
138
142
|
release_evidence_window: 10
|
|
@@ -1983,6 +1987,8 @@ function registerAutoCommands(program) {
|
|
|
1983
1987
|
.description('Evaluate release-gate preflight readiness from gate-history signals')
|
|
1984
1988
|
.option('--profile <profile>', 'Handoff policy profile: default|moqui|enterprise (default: default)', 'default')
|
|
1985
1989
|
.option('--history-file <path>', `Release gate history file (default: ${AUTO_HANDOFF_RELEASE_GATE_HISTORY_FILE})`)
|
|
1990
|
+
.option('--require-spec-delivery-sync', 'Gate: require declared spec deliverables to be tracked, committed, and upstream-synced when manifests exist (default: enabled)')
|
|
1991
|
+
.option('--no-require-spec-delivery-sync', 'Gate: disable spec delivery sync hard requirement (not recommended)')
|
|
1986
1992
|
.option('--require-release-gate-preflight', 'Gate: require release-gate preflight signal to be available and unblocked (default: enabled)')
|
|
1987
1993
|
.option('--no-require-release-gate-preflight', 'Gate: disable release-gate preflight hard requirement (not recommended)')
|
|
1988
1994
|
.option('--release-evidence-window <n>', 'Release evidence trend window size (2-50, default from profile)', parseInt)
|
|
@@ -1997,10 +2003,15 @@ function registerAutoCommands(program) {
|
|
|
1997
2003
|
console.log(chalk.blue('Auto handoff preflight check:'));
|
|
1998
2004
|
console.log(chalk.gray(` Status: ${result.status}`));
|
|
1999
2005
|
console.log(chalk.gray(` Profile: ${result.policy.profile}`));
|
|
2006
|
+
console.log(chalk.gray(` Spec delivery sync: ${result.policy.require_spec_delivery_sync ? 'enabled' : 'advisory'}`));
|
|
2000
2007
|
console.log(chalk.gray(` Hard-gate preflight: ${result.policy.require_release_gate_preflight ? 'enabled' : 'advisory'}`));
|
|
2001
2008
|
console.log(chalk.gray(` History file: ${result.release_gate_preflight.file || 'n/a'}`));
|
|
2002
2009
|
console.log(chalk.gray(` Preflight available: ${result.release_gate_preflight.available === true ? 'yes' : 'no'}`));
|
|
2003
2010
|
console.log(chalk.gray(` Preflight blocked: ${result.release_gate_preflight.blocked === true ? 'yes' : 'no'}`));
|
|
2011
|
+
if (result.spec_delivery_sync) {
|
|
2012
|
+
console.log(chalk.gray(` Delivery manifests: ${result.spec_delivery_sync.summary.manifest_count}`));
|
|
2013
|
+
console.log(chalk.gray(` Delivery sync passed: ${result.spec_delivery_sync.passed === true ? 'yes' : 'no'}`));
|
|
2014
|
+
}
|
|
2004
2015
|
if (result.release_gate_preflight.latest_tag) {
|
|
2005
2016
|
console.log(chalk.gray(` Latest tag: ${result.release_gate_preflight.latest_tag}`));
|
|
2006
2017
|
}
|
|
@@ -2088,6 +2099,8 @@ function registerAutoCommands(program) {
|
|
|
2088
2099
|
.option('--no-require-capability-coverage', 'Gate: disable capability coverage requirement (not recommended)')
|
|
2089
2100
|
.option('--require-capability-lexicon', 'Gate: require capability lexicon normalization (unknown expected/provided aliases not allowed, default: enabled)')
|
|
2090
2101
|
.option('--no-require-capability-lexicon', 'Gate: disable capability lexicon normalization requirement (not recommended)')
|
|
2102
|
+
.option('--require-spec-delivery-sync', 'Gate: require declared spec deliverables to be tracked, committed, and upstream-synced when manifests exist (default: enabled)')
|
|
2103
|
+
.option('--no-require-spec-delivery-sync', 'Gate: disable spec delivery sync hard requirement (not recommended)')
|
|
2091
2104
|
.option('--require-release-gate-preflight', 'Gate: require release-gate preflight signal to be available and unblocked (default: enabled)')
|
|
2092
2105
|
.option('--no-require-release-gate-preflight', 'Gate: disable release-gate preflight hard requirement (not recommended)')
|
|
2093
2106
|
.option('--release-evidence-window <n>', 'Release evidence trend window size (2-50, default: 5)', parseInt)
|
|
@@ -2108,6 +2121,10 @@ function registerAutoCommands(program) {
|
|
|
2108
2121
|
if (result.template_diff) {
|
|
2109
2122
|
console.log(chalk.gray(` Template compatibility: ${result.template_diff.compatibility}`));
|
|
2110
2123
|
}
|
|
2124
|
+
if (result.spec_delivery_sync) {
|
|
2125
|
+
console.log(chalk.gray(` Delivery manifests: ${result.spec_delivery_sync.summary.manifest_count}`));
|
|
2126
|
+
console.log(chalk.gray(` Delivery sync passed: ${result.spec_delivery_sync.passed === true ? 'yes' : 'no'}`));
|
|
2127
|
+
}
|
|
2111
2128
|
if (result.dependency_execution && Array.isArray(result.dependency_execution.batches)) {
|
|
2112
2129
|
console.log(chalk.gray(` Execution batches: ${result.dependency_execution.batches.length}`));
|
|
2113
2130
|
}
|
|
@@ -7326,6 +7343,10 @@ function buildAutoHandoffRunPolicy(options = {}) {
|
|
|
7326
7343
|
options.requireCapabilityLexicon,
|
|
7327
7344
|
preset.require_capability_lexicon
|
|
7328
7345
|
),
|
|
7346
|
+
require_spec_delivery_sync: resolveAutoHandoffPolicyOptionBoolean(
|
|
7347
|
+
options.requireSpecDeliverySync,
|
|
7348
|
+
preset.require_spec_delivery_sync
|
|
7349
|
+
),
|
|
7329
7350
|
require_release_gate_preflight: resolveAutoHandoffPolicyOptionBoolean(
|
|
7330
7351
|
options.requireReleaseGatePreflight,
|
|
7331
7352
|
preset.require_release_gate_preflight
|
|
@@ -7899,6 +7920,34 @@ function evaluateAutoHandoffReleaseGatePreflightGateReasons(policy = {}, preflig
|
|
|
7899
7920
|
return reasons;
|
|
7900
7921
|
}
|
|
7901
7922
|
|
|
7923
|
+
function evaluateAutoHandoffSpecDeliveryGateReasons(policy = {}, deliveryAudit = null) {
|
|
7924
|
+
const reasons = [];
|
|
7925
|
+
if (policy.require_spec_delivery_sync !== true) {
|
|
7926
|
+
return reasons;
|
|
7927
|
+
}
|
|
7928
|
+
|
|
7929
|
+
const snapshot = deliveryAudit && typeof deliveryAudit === 'object' && !Array.isArray(deliveryAudit)
|
|
7930
|
+
? deliveryAudit
|
|
7931
|
+
: null;
|
|
7932
|
+
if (!snapshot) {
|
|
7933
|
+
reasons.push('spec delivery audit snapshot missing');
|
|
7934
|
+
return reasons;
|
|
7935
|
+
}
|
|
7936
|
+
if (snapshot.reason === 'no-manifests') {
|
|
7937
|
+
return reasons;
|
|
7938
|
+
}
|
|
7939
|
+
if (snapshot.passed !== true) {
|
|
7940
|
+
const violations = Array.isArray(snapshot.violations) ? snapshot.violations : [];
|
|
7941
|
+
if (violations.length > 0) {
|
|
7942
|
+
reasons.push(...violations);
|
|
7943
|
+
} else {
|
|
7944
|
+
reasons.push('spec delivery sync audit reported violations');
|
|
7945
|
+
}
|
|
7946
|
+
}
|
|
7947
|
+
|
|
7948
|
+
return reasons;
|
|
7949
|
+
}
|
|
7950
|
+
|
|
7902
7951
|
function buildAutoHandoffReleaseGatePreflight(signals = null) {
|
|
7903
7952
|
const source = signals && typeof signals === 'object' && !Array.isArray(signals)
|
|
7904
7953
|
? signals
|
|
@@ -7969,6 +8018,9 @@ function buildAutoHandoffPreflightCheckRecommendations(projectPath, result = {})
|
|
|
7969
8018
|
const preflight = result && result.release_gate_preflight && typeof result.release_gate_preflight === 'object'
|
|
7970
8019
|
? result.release_gate_preflight
|
|
7971
8020
|
: {};
|
|
8021
|
+
const deliveryAudit = result && result.spec_delivery_sync && typeof result.spec_delivery_sync === 'object'
|
|
8022
|
+
? result.spec_delivery_sync
|
|
8023
|
+
: {};
|
|
7972
8024
|
const reasons = Array.isArray(result.reasons) ? result.reasons : [];
|
|
7973
8025
|
const windowSize = Number.isInteger(policy.release_evidence_window)
|
|
7974
8026
|
? policy.release_evidence_window
|
|
@@ -7984,6 +8036,16 @@ function buildAutoHandoffPreflightCheckRecommendations(projectPath, result = {})
|
|
|
7984
8036
|
if (result.status !== 'pass' || preflight.blocked === true) {
|
|
7985
8037
|
push(`sce auto handoff evidence --window ${windowSize} --json`);
|
|
7986
8038
|
}
|
|
8039
|
+
if (
|
|
8040
|
+
deliveryAudit.reason === 'missing-manifest' ||
|
|
8041
|
+
deliveryAudit.reason === 'violations'
|
|
8042
|
+
) {
|
|
8043
|
+
push('sce workspace delivery-audit --json --strict');
|
|
8044
|
+
}
|
|
8045
|
+
if (Number.isFinite(Number(deliveryAudit.git && deliveryAudit.git.ahead)) && Number(deliveryAudit.git.ahead) > 0) {
|
|
8046
|
+
const branch = normalizeHandoffText(deliveryAudit.git && deliveryAudit.git.branch) || '<branch>';
|
|
8047
|
+
push(`git push origin ${branch}`);
|
|
8048
|
+
}
|
|
7987
8049
|
|
|
7988
8050
|
if (preflight.blocked === true) {
|
|
7989
8051
|
const governanceRecommendations = buildGovernanceCloseLoopRecommendations(
|
|
@@ -8014,23 +8076,41 @@ function buildAutoHandoffPreflightCheckRecommendations(projectPath, result = {})
|
|
|
8014
8076
|
'Ensure release workflow publishes `release-gate-history.json` and rerun preflight check.'
|
|
8015
8077
|
);
|
|
8016
8078
|
}
|
|
8079
|
+
if (reasons.some(item => `${item}`.includes('spec delivery'))) {
|
|
8080
|
+
push(
|
|
8081
|
+
'Declare feature deliverables in `.sce/specs/<spec>/deliverables.json`, commit tracked files, and push upstream before handoff.'
|
|
8082
|
+
);
|
|
8083
|
+
}
|
|
8017
8084
|
|
|
8018
8085
|
return recommendations;
|
|
8019
8086
|
}
|
|
8020
8087
|
|
|
8021
8088
|
async function buildAutoHandoffPreflightCheck(projectPath, options = {}) {
|
|
8022
8089
|
const policy = buildAutoHandoffRunPolicy(options);
|
|
8090
|
+
const specDeliverySync = await auditSpecDeliverySync(projectPath, {
|
|
8091
|
+
requireManifest: false
|
|
8092
|
+
});
|
|
8023
8093
|
const releaseGateSignals = await loadGovernanceReleaseGateSignals(projectPath, {
|
|
8024
8094
|
historyFile: options.historyFile
|
|
8025
8095
|
});
|
|
8026
8096
|
const releaseGatePreflight = buildAutoHandoffReleaseGatePreflight(releaseGateSignals);
|
|
8027
|
-
const hardGateReasons =
|
|
8028
|
-
policy,
|
|
8029
|
-
releaseGatePreflight
|
|
8030
|
-
|
|
8097
|
+
const hardGateReasons = [
|
|
8098
|
+
...evaluateAutoHandoffSpecDeliveryGateReasons(policy, specDeliverySync),
|
|
8099
|
+
...evaluateAutoHandoffReleaseGatePreflightGateReasons(policy, releaseGatePreflight)
|
|
8100
|
+
];
|
|
8031
8101
|
|
|
8032
8102
|
const advisoryReasons = [];
|
|
8033
8103
|
if (hardGateReasons.length === 0) {
|
|
8104
|
+
if (
|
|
8105
|
+
policy.require_spec_delivery_sync !== true &&
|
|
8106
|
+
specDeliverySync.reason !== 'no-manifests' &&
|
|
8107
|
+
specDeliverySync.passed !== true
|
|
8108
|
+
) {
|
|
8109
|
+
const deliveryReasons = Array.isArray(specDeliverySync.violations) && specDeliverySync.violations.length > 0
|
|
8110
|
+
? specDeliverySync.violations
|
|
8111
|
+
: ['spec delivery sync audit reported warnings'];
|
|
8112
|
+
advisoryReasons.push(...deliveryReasons.map((item) => `spec delivery sync advisory: ${item}`));
|
|
8113
|
+
}
|
|
8034
8114
|
if (releaseGatePreflight.parse_error) {
|
|
8035
8115
|
advisoryReasons.push(`release gate preflight parse error: ${releaseGatePreflight.parse_error}`);
|
|
8036
8116
|
} else if (releaseGatePreflight.available !== true) {
|
|
@@ -8055,9 +8135,11 @@ async function buildAutoHandoffPreflightCheck(projectPath, options = {}) {
|
|
|
8055
8135
|
hard_gate_reasons: hardGateReasons,
|
|
8056
8136
|
policy: {
|
|
8057
8137
|
profile: policy.profile,
|
|
8138
|
+
require_spec_delivery_sync: policy.require_spec_delivery_sync === true,
|
|
8058
8139
|
require_release_gate_preflight: policy.require_release_gate_preflight === true,
|
|
8059
8140
|
release_evidence_window: policy.release_evidence_window
|
|
8060
8141
|
},
|
|
8142
|
+
spec_delivery_sync: specDeliverySync,
|
|
8061
8143
|
release_gate_preflight: releaseGatePreflight,
|
|
8062
8144
|
signals: {
|
|
8063
8145
|
history_file: releaseGateSignals.file || releaseGatePreflight.file || null,
|
|
@@ -8571,6 +8653,9 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
|
|
|
8571
8653
|
const releaseGatePreflight = result && result.release_gate_preflight && typeof result.release_gate_preflight === 'object'
|
|
8572
8654
|
? result.release_gate_preflight
|
|
8573
8655
|
: null;
|
|
8656
|
+
const specDeliverySync = result && result.spec_delivery_sync && typeof result.spec_delivery_sync === 'object'
|
|
8657
|
+
? result.spec_delivery_sync
|
|
8658
|
+
: null;
|
|
8574
8659
|
if (releaseGatePreflight && releaseGatePreflight.blocked === true) {
|
|
8575
8660
|
push('sce auto handoff evidence --window 5 --json');
|
|
8576
8661
|
if (
|
|
@@ -8596,6 +8681,17 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
|
|
|
8596
8681
|
'--out .sce/reports/release-evidence/release-gate-history.json --json'
|
|
8597
8682
|
);
|
|
8598
8683
|
}
|
|
8684
|
+
if (
|
|
8685
|
+
specDeliverySync &&
|
|
8686
|
+
specDeliverySync.reason !== 'no-manifests' &&
|
|
8687
|
+
specDeliverySync.passed !== true
|
|
8688
|
+
) {
|
|
8689
|
+
push('sce workspace delivery-audit --json --strict');
|
|
8690
|
+
if (Number.isFinite(Number(specDeliverySync.git && specDeliverySync.git.ahead)) && Number(specDeliverySync.git.ahead) > 0) {
|
|
8691
|
+
const branch = normalizeHandoffText(specDeliverySync.git && specDeliverySync.git.branch) || '<branch>';
|
|
8692
|
+
push(`git push origin ${branch}`);
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
8599
8695
|
|
|
8600
8696
|
const riskLevel = result && result.gates && result.gates.actual && typeof result.gates.actual.risk_level === 'string'
|
|
8601
8697
|
? result.gates.actual.risk_level.trim().toLowerCase()
|
|
@@ -9888,6 +9984,8 @@ async function runAutoHandoff(projectPath, options = {}) {
|
|
|
9888
9984
|
loadGovernanceReleaseGateSignals,
|
|
9889
9985
|
completeAutoHandoffRunPhase,
|
|
9890
9986
|
evaluateAutoHandoffOntologyGateReasons,
|
|
9987
|
+
auditSpecDeliverySync,
|
|
9988
|
+
evaluateAutoHandoffSpecDeliveryGateReasons,
|
|
9891
9989
|
evaluateAutoHandoffReleaseGatePreflightGateReasons,
|
|
9892
9990
|
failAutoHandoffRunPhase,
|
|
9893
9991
|
buildAutoHandoffMoquiBaselineSnapshot,
|
|
@@ -11717,6 +11815,130 @@ async function loadGovernanceReleaseGateSignals(projectPath, options = {}) {
|
|
|
11717
11815
|
const parsed = Number(value);
|
|
11718
11816
|
return Number.isFinite(parsed) ? parsed : null;
|
|
11719
11817
|
};
|
|
11818
|
+
const buildSignalsSnapshot = ({ file, totalEntries, latest, aggregates, parseError = null }) => {
|
|
11819
|
+
const latestRiskLevel = normalizeHandoffText(latest && latest.risk_level);
|
|
11820
|
+
const latestWeeklyOpsRiskLevel = normalizeHandoffText(latest && latest.weekly_ops_risk_level);
|
|
11821
|
+
const normalizedTotalEntries = Number.isFinite(Number(totalEntries))
|
|
11822
|
+
? Number(totalEntries)
|
|
11823
|
+
: 0;
|
|
11824
|
+
const hasEntries = normalizedTotalEntries > 0 || Boolean(latest);
|
|
11825
|
+
return {
|
|
11826
|
+
...base,
|
|
11827
|
+
available: hasEntries,
|
|
11828
|
+
file: normalizeHandoffText(file) || base.file,
|
|
11829
|
+
total_entries: normalizedTotalEntries,
|
|
11830
|
+
latest_tag: normalizeHandoffText(latest && latest.tag) || null,
|
|
11831
|
+
latest_gate_passed: parseAutoHandoffGateBoolean(latest && latest.gate_passed, null),
|
|
11832
|
+
latest_risk_level: latestRiskLevel
|
|
11833
|
+
? normalizeAutoHandoffGateRiskLevel(latestRiskLevel)
|
|
11834
|
+
: null,
|
|
11835
|
+
pass_rate_percent: toNumber(aggregates && aggregates.pass_rate_percent),
|
|
11836
|
+
scene_package_batch_pass_rate_percent: toNumber(
|
|
11837
|
+
aggregates && aggregates.scene_package_batch_pass_rate_percent
|
|
11838
|
+
),
|
|
11839
|
+
scene_package_batch_failed_count: toNumber(
|
|
11840
|
+
aggregates && aggregates.scene_package_batch_failed_count
|
|
11841
|
+
),
|
|
11842
|
+
drift_alert_rate_percent: toNumber(aggregates && aggregates.drift_alert_rate_percent),
|
|
11843
|
+
drift_alert_runs: toNumber(aggregates && aggregates.drift_alert_runs),
|
|
11844
|
+
drift_blocked_runs: toNumber(aggregates && aggregates.drift_blocked_runs),
|
|
11845
|
+
latest_weekly_ops_blocked: parseAutoHandoffGateBoolean(latest && latest.weekly_ops_blocked, null),
|
|
11846
|
+
latest_weekly_ops_risk_level: latestWeeklyOpsRiskLevel
|
|
11847
|
+
? normalizeAutoHandoffGateRiskLevel(latestWeeklyOpsRiskLevel)
|
|
11848
|
+
: null,
|
|
11849
|
+
latest_weekly_ops_governance_status: normalizeHandoffText(
|
|
11850
|
+
latest && latest.weekly_ops_governance_status
|
|
11851
|
+
) || null,
|
|
11852
|
+
latest_weekly_ops_authorization_tier_block_rate_percent: toNumber(
|
|
11853
|
+
latest && latest.weekly_ops_authorization_tier_block_rate_percent
|
|
11854
|
+
),
|
|
11855
|
+
latest_weekly_ops_dialogue_authorization_block_rate_percent: toNumber(
|
|
11856
|
+
latest && latest.weekly_ops_dialogue_authorization_block_rate_percent
|
|
11857
|
+
),
|
|
11858
|
+
latest_weekly_ops_config_warning_count: toNumber(
|
|
11859
|
+
latest && latest.weekly_ops_config_warning_count
|
|
11860
|
+
),
|
|
11861
|
+
latest_weekly_ops_runtime_block_rate_percent: toNumber(
|
|
11862
|
+
latest && latest.weekly_ops_runtime_block_rate_percent
|
|
11863
|
+
),
|
|
11864
|
+
latest_weekly_ops_runtime_ui_mode_violation_total: toNumber(
|
|
11865
|
+
latest && latest.weekly_ops_runtime_ui_mode_violation_total
|
|
11866
|
+
),
|
|
11867
|
+
latest_weekly_ops_runtime_ui_mode_violation_rate_percent: toNumber(
|
|
11868
|
+
latest && latest.weekly_ops_runtime_ui_mode_violation_rate_percent
|
|
11869
|
+
),
|
|
11870
|
+
weekly_ops_known_runs: toNumber(aggregates && aggregates.weekly_ops_known_runs),
|
|
11871
|
+
weekly_ops_blocked_runs: toNumber(aggregates && aggregates.weekly_ops_blocked_runs),
|
|
11872
|
+
weekly_ops_block_rate_percent: toNumber(aggregates && aggregates.weekly_ops_block_rate_percent),
|
|
11873
|
+
weekly_ops_violations_total: toNumber(aggregates && aggregates.weekly_ops_violations_total),
|
|
11874
|
+
weekly_ops_warnings_total: toNumber(aggregates && aggregates.weekly_ops_warnings_total),
|
|
11875
|
+
weekly_ops_config_warnings_total: toNumber(
|
|
11876
|
+
aggregates && aggregates.weekly_ops_config_warnings_total
|
|
11877
|
+
),
|
|
11878
|
+
weekly_ops_authorization_tier_block_rate_max_percent: toNumber(
|
|
11879
|
+
aggregates && aggregates.weekly_ops_authorization_tier_block_rate_max_percent
|
|
11880
|
+
),
|
|
11881
|
+
weekly_ops_dialogue_authorization_block_rate_max_percent: toNumber(
|
|
11882
|
+
aggregates && aggregates.weekly_ops_dialogue_authorization_block_rate_max_percent
|
|
11883
|
+
),
|
|
11884
|
+
weekly_ops_runtime_block_rate_avg_percent: toNumber(
|
|
11885
|
+
aggregates && aggregates.weekly_ops_runtime_block_rate_avg_percent
|
|
11886
|
+
),
|
|
11887
|
+
weekly_ops_runtime_block_rate_max_percent: toNumber(
|
|
11888
|
+
aggregates && aggregates.weekly_ops_runtime_block_rate_max_percent
|
|
11889
|
+
),
|
|
11890
|
+
weekly_ops_runtime_ui_mode_violation_known_runs: toNumber(
|
|
11891
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_known_runs
|
|
11892
|
+
),
|
|
11893
|
+
weekly_ops_runtime_ui_mode_violation_runs: toNumber(
|
|
11894
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_runs
|
|
11895
|
+
),
|
|
11896
|
+
weekly_ops_runtime_ui_mode_violation_run_rate_percent: toNumber(
|
|
11897
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_run_rate_percent
|
|
11898
|
+
),
|
|
11899
|
+
weekly_ops_runtime_ui_mode_violation_total: toNumber(
|
|
11900
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_total
|
|
11901
|
+
),
|
|
11902
|
+
weekly_ops_runtime_ui_mode_violation_rate_avg_percent: toNumber(
|
|
11903
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_rate_avg_percent
|
|
11904
|
+
),
|
|
11905
|
+
weekly_ops_runtime_ui_mode_violation_rate_max_percent: toNumber(
|
|
11906
|
+
aggregates && aggregates.weekly_ops_runtime_ui_mode_violation_rate_max_percent
|
|
11907
|
+
),
|
|
11908
|
+
parse_error: parseError
|
|
11909
|
+
};
|
|
11910
|
+
};
|
|
11911
|
+
const loadFallbackSnapshot = async (parseError = null) => {
|
|
11912
|
+
const reportDir = path.dirname(historyFile);
|
|
11913
|
+
const reportResult = await loadAutoHandoffReleaseGateReports(projectPath, reportDir);
|
|
11914
|
+
const mergedEntries = mergeAutoHandoffReleaseGateHistoryEntries(reportResult.entries);
|
|
11915
|
+
if (mergedEntries.length === 0) {
|
|
11916
|
+
return parseError
|
|
11917
|
+
? {
|
|
11918
|
+
...base,
|
|
11919
|
+
parse_error: parseError
|
|
11920
|
+
}
|
|
11921
|
+
: base;
|
|
11922
|
+
}
|
|
11923
|
+
mergedEntries.sort((left, right) => {
|
|
11924
|
+
const leftTs = toAutoHandoffTimestamp(left && left.evaluated_at);
|
|
11925
|
+
const rightTs = toAutoHandoffTimestamp(right && right.evaluated_at);
|
|
11926
|
+
if (rightTs !== leftTs) {
|
|
11927
|
+
return rightTs - leftTs;
|
|
11928
|
+
}
|
|
11929
|
+
const leftTag = normalizeHandoffText(left && left.tag) || '';
|
|
11930
|
+
const rightTag = normalizeHandoffText(right && right.tag) || '';
|
|
11931
|
+
return rightTag.localeCompare(leftTag);
|
|
11932
|
+
});
|
|
11933
|
+
const latest = mergedEntries[0] || null;
|
|
11934
|
+
return buildSignalsSnapshot({
|
|
11935
|
+
file: normalizeHandoffText(latest && latest.file) || reportDir,
|
|
11936
|
+
totalEntries: mergedEntries.length,
|
|
11937
|
+
latest,
|
|
11938
|
+
aggregates: buildAutoHandoffReleaseGateHistoryAggregates(mergedEntries),
|
|
11939
|
+
parseError: null
|
|
11940
|
+
});
|
|
11941
|
+
};
|
|
11720
11942
|
const base = {
|
|
11721
11943
|
available: false,
|
|
11722
11944
|
file: historyFile,
|
|
@@ -11758,22 +11980,16 @@ async function loadGovernanceReleaseGateSignals(projectPath, options = {}) {
|
|
|
11758
11980
|
parse_error: null
|
|
11759
11981
|
};
|
|
11760
11982
|
if (!(await fs.pathExists(historyFile))) {
|
|
11761
|
-
return
|
|
11983
|
+
return loadFallbackSnapshot();
|
|
11762
11984
|
}
|
|
11763
11985
|
let payload = null;
|
|
11764
11986
|
try {
|
|
11765
11987
|
payload = await fs.readJson(historyFile);
|
|
11766
11988
|
} catch (error) {
|
|
11767
|
-
return {
|
|
11768
|
-
...base,
|
|
11769
|
-
parse_error: `${error.message}`
|
|
11770
|
-
};
|
|
11989
|
+
return loadFallbackSnapshot(`${error.message}`);
|
|
11771
11990
|
}
|
|
11772
11991
|
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
11773
|
-
return
|
|
11774
|
-
...base,
|
|
11775
|
-
parse_error: 'invalid release gate history payload'
|
|
11776
|
-
};
|
|
11992
|
+
return loadFallbackSnapshot('invalid release gate history payload');
|
|
11777
11993
|
}
|
|
11778
11994
|
const entries = Array.isArray(payload.entries) ? payload.entries : [];
|
|
11779
11995
|
const latest = payload.latest && typeof payload.latest === 'object'
|
|
@@ -11782,86 +11998,16 @@ async function loadGovernanceReleaseGateSignals(projectPath, options = {}) {
|
|
|
11782
11998
|
const aggregates = payload.aggregates && typeof payload.aggregates === 'object'
|
|
11783
11999
|
? payload.aggregates
|
|
11784
12000
|
: {};
|
|
11785
|
-
|
|
11786
|
-
|
|
11787
|
-
|
|
11788
|
-
|
|
11789
|
-
|
|
11790
|
-
|
|
11791
|
-
|
|
11792
|
-
|
|
11793
|
-
|
|
11794
|
-
|
|
11795
|
-
: null,
|
|
11796
|
-
pass_rate_percent: toNumber(aggregates.pass_rate_percent),
|
|
11797
|
-
scene_package_batch_pass_rate_percent: toNumber(aggregates.scene_package_batch_pass_rate_percent),
|
|
11798
|
-
scene_package_batch_failed_count: toNumber(aggregates.scene_package_batch_failed_count),
|
|
11799
|
-
drift_alert_rate_percent: toNumber(aggregates.drift_alert_rate_percent),
|
|
11800
|
-
drift_alert_runs: toNumber(aggregates.drift_alert_runs),
|
|
11801
|
-
drift_blocked_runs: toNumber(aggregates.drift_blocked_runs),
|
|
11802
|
-
latest_weekly_ops_blocked: parseAutoHandoffGateBoolean(latest && latest.weekly_ops_blocked, null),
|
|
11803
|
-
latest_weekly_ops_risk_level: latestWeeklyOpsRiskLevel
|
|
11804
|
-
? normalizeAutoHandoffGateRiskLevel(latestWeeklyOpsRiskLevel)
|
|
11805
|
-
: null,
|
|
11806
|
-
latest_weekly_ops_governance_status: normalizeHandoffText(
|
|
11807
|
-
latest && latest.weekly_ops_governance_status
|
|
11808
|
-
) || null,
|
|
11809
|
-
latest_weekly_ops_authorization_tier_block_rate_percent: toNumber(
|
|
11810
|
-
latest && latest.weekly_ops_authorization_tier_block_rate_percent
|
|
11811
|
-
),
|
|
11812
|
-
latest_weekly_ops_dialogue_authorization_block_rate_percent: toNumber(
|
|
11813
|
-
latest && latest.weekly_ops_dialogue_authorization_block_rate_percent
|
|
11814
|
-
),
|
|
11815
|
-
latest_weekly_ops_config_warning_count: toNumber(
|
|
11816
|
-
latest && latest.weekly_ops_config_warning_count
|
|
11817
|
-
),
|
|
11818
|
-
latest_weekly_ops_runtime_block_rate_percent: toNumber(
|
|
11819
|
-
latest && latest.weekly_ops_runtime_block_rate_percent
|
|
11820
|
-
),
|
|
11821
|
-
latest_weekly_ops_runtime_ui_mode_violation_total: toNumber(
|
|
11822
|
-
latest && latest.weekly_ops_runtime_ui_mode_violation_total
|
|
11823
|
-
),
|
|
11824
|
-
latest_weekly_ops_runtime_ui_mode_violation_rate_percent: toNumber(
|
|
11825
|
-
latest && latest.weekly_ops_runtime_ui_mode_violation_rate_percent
|
|
11826
|
-
),
|
|
11827
|
-
weekly_ops_known_runs: toNumber(aggregates.weekly_ops_known_runs),
|
|
11828
|
-
weekly_ops_blocked_runs: toNumber(aggregates.weekly_ops_blocked_runs),
|
|
11829
|
-
weekly_ops_block_rate_percent: toNumber(aggregates.weekly_ops_block_rate_percent),
|
|
11830
|
-
weekly_ops_violations_total: toNumber(aggregates.weekly_ops_violations_total),
|
|
11831
|
-
weekly_ops_warnings_total: toNumber(aggregates.weekly_ops_warnings_total),
|
|
11832
|
-
weekly_ops_config_warnings_total: toNumber(aggregates.weekly_ops_config_warnings_total),
|
|
11833
|
-
weekly_ops_authorization_tier_block_rate_max_percent: toNumber(
|
|
11834
|
-
aggregates.weekly_ops_authorization_tier_block_rate_max_percent
|
|
11835
|
-
),
|
|
11836
|
-
weekly_ops_dialogue_authorization_block_rate_max_percent: toNumber(
|
|
11837
|
-
aggregates.weekly_ops_dialogue_authorization_block_rate_max_percent
|
|
11838
|
-
),
|
|
11839
|
-
weekly_ops_runtime_block_rate_avg_percent: toNumber(
|
|
11840
|
-
aggregates.weekly_ops_runtime_block_rate_avg_percent
|
|
11841
|
-
),
|
|
11842
|
-
weekly_ops_runtime_block_rate_max_percent: toNumber(
|
|
11843
|
-
aggregates.weekly_ops_runtime_block_rate_max_percent
|
|
11844
|
-
),
|
|
11845
|
-
weekly_ops_runtime_ui_mode_violation_known_runs: toNumber(
|
|
11846
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_known_runs
|
|
11847
|
-
),
|
|
11848
|
-
weekly_ops_runtime_ui_mode_violation_runs: toNumber(
|
|
11849
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_runs
|
|
11850
|
-
),
|
|
11851
|
-
weekly_ops_runtime_ui_mode_violation_run_rate_percent: toNumber(
|
|
11852
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_run_rate_percent
|
|
11853
|
-
),
|
|
11854
|
-
weekly_ops_runtime_ui_mode_violation_total: toNumber(
|
|
11855
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_total
|
|
11856
|
-
),
|
|
11857
|
-
weekly_ops_runtime_ui_mode_violation_rate_avg_percent: toNumber(
|
|
11858
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_rate_avg_percent
|
|
11859
|
-
),
|
|
11860
|
-
weekly_ops_runtime_ui_mode_violation_rate_max_percent: toNumber(
|
|
11861
|
-
aggregates.weekly_ops_runtime_ui_mode_violation_rate_max_percent
|
|
11862
|
-
),
|
|
11863
|
-
parse_error: null
|
|
11864
|
-
};
|
|
12001
|
+
if (entries.length === 0 && !latest) {
|
|
12002
|
+
return loadFallbackSnapshot();
|
|
12003
|
+
}
|
|
12004
|
+
return buildSignalsSnapshot({
|
|
12005
|
+
file: historyFile,
|
|
12006
|
+
totalEntries: toNumber(payload.total_entries) || entries.length,
|
|
12007
|
+
latest,
|
|
12008
|
+
aggregates,
|
|
12009
|
+
parseError: null
|
|
12010
|
+
});
|
|
11865
12011
|
}
|
|
11866
12012
|
|
|
11867
12013
|
async function loadGovernanceHandoffQualitySignals(projectPath) {
|
|
@@ -12799,9 +12945,6 @@ function evaluateGovernanceReleaseGateBlockState(assessment) {
|
|
|
12799
12945
|
) {
|
|
12800
12946
|
reasons.push(`scene-batch-pass-rate-low:${snapshot.scene_package_batch_pass_rate_percent}`);
|
|
12801
12947
|
}
|
|
12802
|
-
if (Number.isFinite(snapshot.drift_alert_rate_percent) && snapshot.drift_alert_rate_percent > 0) {
|
|
12803
|
-
reasons.push(`drift-alert-rate-positive:${snapshot.drift_alert_rate_percent}`);
|
|
12804
|
-
}
|
|
12805
12948
|
if (Number.isFinite(snapshot.drift_blocked_runs) && snapshot.drift_blocked_runs > 0) {
|
|
12806
12949
|
reasons.push(`drift-blocked-runs-positive:${snapshot.drift_blocked_runs}`);
|
|
12807
12950
|
}
|
|
@@ -12995,7 +13138,6 @@ function evaluateGovernanceReleaseGateBlockState(assessment) {
|
|
|
12995
13138
|
snapshot.available === true &&
|
|
12996
13139
|
(
|
|
12997
13140
|
snapshot.latest_gate_passed === false ||
|
|
12998
|
-
(Number.isFinite(snapshot.drift_alert_rate_percent) && snapshot.drift_alert_rate_percent > 0) ||
|
|
12999
13141
|
(Number.isFinite(snapshot.drift_blocked_runs) && snapshot.drift_blocked_runs > 0)
|
|
13000
13142
|
)
|
|
13001
13143
|
);
|
package/lib/commands/collab.js
CHANGED
|
@@ -90,7 +90,10 @@ function registerCollabCommands(program) {
|
|
|
90
90
|
console.log(chalk.gray('Type:'), status.metadata.type);
|
|
91
91
|
console.log(chalk.gray('Status:'), status.metadata.status.current);
|
|
92
92
|
if (status.metadata.assignment) {
|
|
93
|
-
console.log(
|
|
93
|
+
console.log(
|
|
94
|
+
chalk.gray('Assigned to:'),
|
|
95
|
+
status.metadata.assignment.sceInstance || status.metadata.assignment.kiroInstance
|
|
96
|
+
);
|
|
94
97
|
}
|
|
95
98
|
if (status.metadata.dependencies && status.metadata.dependencies.length > 0) {
|
|
96
99
|
console.log(chalk.gray('Dependencies:'));
|
|
@@ -105,8 +108,11 @@ function registerCollabCommands(program) {
|
|
|
105
108
|
|
|
106
109
|
for (const { name, metadata } of status.specs) {
|
|
107
110
|
const symbol = getStatusSymbol(metadata.status.current);
|
|
111
|
+
const assignedInstance = metadata.assignment
|
|
112
|
+
? (metadata.assignment.sceInstance || metadata.assignment.kiroInstance)
|
|
113
|
+
: null;
|
|
108
114
|
const assignment = metadata.assignment
|
|
109
|
-
? chalk.gray(`(${
|
|
115
|
+
? chalk.gray(`(${assignedInstance})`)
|
|
110
116
|
: chalk.gray('(unassigned)');
|
|
111
117
|
console.log(`${symbol} ${name} ${assignment}`);
|
|
112
118
|
}
|
|
@@ -127,12 +133,12 @@ function registerCollabCommands(program) {
|
|
|
127
133
|
collab
|
|
128
134
|
.command('assign <spec-name> <SCE-instance>')
|
|
129
135
|
.description('Assign a spec to a SCE instance')
|
|
130
|
-
.action(async (specName,
|
|
136
|
+
.action(async (specName, sceInstance) => {
|
|
131
137
|
try {
|
|
132
138
|
const workspaceRoot = process.cwd();
|
|
133
139
|
const manager = new CollaborationManager(workspaceRoot);
|
|
134
140
|
|
|
135
|
-
const result = await manager.assignSpec(specName,
|
|
141
|
+
const result = await manager.assignSpec(specName, sceInstance);
|
|
136
142
|
|
|
137
143
|
if (result.success) {
|
|
138
144
|
console.log(chalk.green('✓'), result.message);
|
package/lib/commands/status.js
CHANGED
|
@@ -30,10 +30,10 @@ async function statusCommand(options = {}) {
|
|
|
30
30
|
|
|
31
31
|
try {
|
|
32
32
|
// 1. Check if .sce/ exists
|
|
33
|
-
const
|
|
34
|
-
const
|
|
33
|
+
const scePath = path.join(projectPath, '.sce');
|
|
34
|
+
const sceExists = await fs.pathExists(scePath);
|
|
35
35
|
|
|
36
|
-
if (!
|
|
36
|
+
if (!sceExists) {
|
|
37
37
|
console.log(chalk.yellow('⚠️ No .sce/ directory found'));
|
|
38
38
|
console.log();
|
|
39
39
|
console.log('This project has not been adopted yet.');
|
package/lib/commands/studio.js
CHANGED
|
@@ -502,6 +502,14 @@ async function buildReleaseGateSteps(options = {}, dependencies = {}) {
|
|
|
502
502
|
required: true
|
|
503
503
|
});
|
|
504
504
|
|
|
505
|
+
steps.push({
|
|
506
|
+
id: 'spec-delivery-audit',
|
|
507
|
+
name: 'spec delivery sync audit',
|
|
508
|
+
command: 'node',
|
|
509
|
+
args: ['bin/sce.js', 'workspace', 'delivery-audit', '--json', '--strict'],
|
|
510
|
+
required: true
|
|
511
|
+
});
|
|
512
|
+
|
|
505
513
|
const gitManagedGateScript = path.join(projectPath, 'scripts', 'git-managed-gate.js');
|
|
506
514
|
const hasGitManagedGateScript = await fileSystem.pathExists(gitManagedGateScript);
|
|
507
515
|
steps.push({
|
|
@@ -131,8 +131,8 @@ class ConfigManager {
|
|
|
131
131
|
|
|
132
132
|
try {
|
|
133
133
|
// Ensure .sce directory exists
|
|
134
|
-
const
|
|
135
|
-
await fs.mkdir(
|
|
134
|
+
const sceDir = path.dirname(configPath);
|
|
135
|
+
await fs.mkdir(sceDir, { recursive: true });
|
|
136
136
|
|
|
137
137
|
// Write configuration with pretty formatting
|
|
138
138
|
const jsonContent = JSON.stringify(config, null, 2);
|
|
@@ -7,14 +7,15 @@ class ContextCollector {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
async collect() {
|
|
10
|
-
const
|
|
11
|
-
const specsDir = path.join(
|
|
12
|
-
const
|
|
10
|
+
const sceDir = path.join(this.projectPath, '.sce');
|
|
11
|
+
const specsDir = path.join(sceDir, 'specs');
|
|
12
|
+
const hasSceDir = await fs.pathExists(sceDir);
|
|
13
13
|
const existingSpecs = await this._listSpecs(specsDir);
|
|
14
14
|
|
|
15
15
|
return {
|
|
16
16
|
projectPath: this.projectPath,
|
|
17
|
-
|
|
17
|
+
hasSceDir,
|
|
18
|
+
hasKiro: hasSceDir,
|
|
18
19
|
specsDir,
|
|
19
20
|
existingSpecs,
|
|
20
21
|
totalSpecs: existingSpecs.length,
|
|
@@ -87,25 +87,25 @@ function createDefaultRules(projectPath = process.cwd()) {
|
|
|
87
87
|
id: 'config_consistency',
|
|
88
88
|
description: 'Verify project-level sce config baseline exists',
|
|
89
89
|
async execute() {
|
|
90
|
-
const
|
|
91
|
-
const configDir = path.join(
|
|
92
|
-
const
|
|
90
|
+
const sceDir = path.join(projectPath, '.sce');
|
|
91
|
+
const configDir = path.join(sceDir, 'config');
|
|
92
|
+
const hasSceDir = await fs.pathExists(sceDir);
|
|
93
93
|
const hasConfig = await fs.pathExists(configDir);
|
|
94
94
|
|
|
95
|
-
const ratio =
|
|
95
|
+
const ratio = hasSceDir && hasConfig ? 1 : hasSceDir ? 0.5 : 0;
|
|
96
96
|
const warnings = [];
|
|
97
|
-
if (!
|
|
97
|
+
if (!hasSceDir) {
|
|
98
98
|
warnings.push('.sce directory missing');
|
|
99
99
|
}
|
|
100
|
-
if (
|
|
100
|
+
if (hasSceDir && !hasConfig) {
|
|
101
101
|
warnings.push('.sce/config directory missing');
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
return {
|
|
105
|
-
passed:
|
|
105
|
+
passed: hasSceDir,
|
|
106
106
|
ratio,
|
|
107
107
|
details: {
|
|
108
|
-
|
|
108
|
+
hasSceDir,
|
|
109
109
|
hasConfig
|
|
110
110
|
},
|
|
111
111
|
warnings
|