scene-capability-engine 3.6.32 → 3.6.37
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 +109 -11
- package/README.md +119 -122
- package/README.zh.md +123 -121
- package/bin/scene-capability-engine.js +12 -1
- package/docs/331-poc-adaptation-roadmap.md +3 -3
- package/docs/README.md +21 -32
- package/docs/auto-refactor-index.md +384 -0
- package/docs/command-reference.md +99 -7
- package/docs/faq.md +1 -1
- package/docs/interactive-customization/331-poc-sce-integration-checklist.md +3 -3
- package/docs/interactive-customization/moqui-interactive-template-playbook.md +4 -4
- package/docs/interactive-customization/phase-acceptance-evidence.md +2 -2
- package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
- package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
- package/docs/magicball-capability-iteration-api.md +2 -0
- package/docs/magicball-capability-iteration-ui.md +2 -0
- package/docs/magicball-capability-library.md +2 -0
- package/docs/magicball-cli-invocation-examples.md +336 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
- package/docs/magicball-integration-doc-index.md +137 -0
- package/docs/magicball-integration-issue-tracker.md +218 -0
- package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
- package/docs/magicball-sce-adaptation-guide.md +203 -0
- package/docs/magicball-three-mode-alignment-plan.md +551 -0
- package/docs/magicball-ui-surface-checklist.md +126 -0
- package/docs/magicball-write-auth-adaptation-guide.md +328 -0
- package/docs/moqui-standard-rebuild-guide.md +6 -6
- package/docs/moqui-template-core-library-playbook.md +1 -1
- package/docs/refactor-completion-roadmap.md +116 -0
- package/docs/release-checklist.md +50 -27
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.37.md +22 -0
- package/docs/steering-strategy-guide.md +7 -7
- package/docs/troubleshooting.md +1 -1
- package/docs/zh/README.md +27 -30
- package/docs/zh/refactor-completion-roadmap.md +116 -0
- package/docs/zh/release-checklist.md +40 -17
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.37.md +22 -0
- package/lib/app/registry-config.js +73 -0
- package/lib/app/registry-sync-service.js +228 -0
- package/lib/auto/archive-schema-service.js +276 -0
- package/lib/auto/archive-summary.js +60 -0
- package/lib/auto/batch-goal-input-service.js +543 -0
- package/lib/auto/batch-output.js +201 -0
- package/lib/auto/batch-summary-storage-service.js +110 -0
- package/lib/auto/close-loop-batch-service.js +116 -0
- package/lib/auto/close-loop-controller-service.js +287 -0
- package/lib/auto/close-loop-program-service.js +283 -0
- package/lib/auto/close-loop-recovery-service.js +191 -0
- package/lib/auto/close-loop-session-storage-service.js +50 -0
- package/lib/auto/controller-lock-service.js +55 -0
- package/lib/auto/controller-output.js +32 -0
- package/lib/auto/controller-queue-service.js +127 -0
- package/lib/auto/controller-session-storage-service.js +105 -0
- package/lib/auto/governance-advisory-service.js +208 -0
- package/lib/auto/governance-close-loop-service.js +411 -0
- package/lib/auto/governance-maintenance-presenter.js +162 -0
- package/lib/auto/governance-maintenance-service.js +112 -0
- package/lib/auto/governance-session-presenter.js +70 -0
- package/lib/auto/governance-session-storage-service.js +198 -0
- package/lib/auto/governance-signals.js +139 -0
- package/lib/auto/governance-stats-presenter.js +337 -0
- package/lib/auto/governance-stats-service.js +115 -0
- package/lib/auto/governance-summary.js +703 -0
- package/lib/auto/handoff-capability-matrix-service.js +281 -0
- package/lib/auto/handoff-evidence-review-service.js +251 -0
- package/lib/auto/handoff-release-evidence-service.js +190 -0
- package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
- package/lib/auto/handoff-release-gate-history-service.js +257 -0
- package/lib/auto/handoff-reporting-service.js +1407 -0
- package/lib/auto/handoff-run-service.js +486 -0
- package/lib/auto/handoff-snapshots-service.js +645 -0
- package/lib/auto/observability-service.js +132 -0
- package/lib/auto/output-writer.js +34 -0
- package/lib/auto/program-auto-remediation-service.js +130 -0
- package/lib/auto/program-diagnostics.js +138 -0
- package/lib/auto/program-governance-helpers.js +306 -0
- package/lib/auto/program-governance-loop-service.js +413 -0
- package/lib/auto/program-output.js +106 -0
- package/lib/auto/program-summary.js +183 -0
- package/lib/auto/recovery-memory-service.js +684 -0
- package/lib/auto/recovery-selection-service.js +52 -0
- package/lib/auto/retention-policy.js +98 -0
- package/lib/auto/session-persistence-service.js +106 -0
- package/lib/auto/session-presenter.js +105 -0
- package/lib/auto/session-prune-service.js +190 -0
- package/lib/auto/session-query-service.js +249 -0
- package/lib/auto/spec-protection.js +141 -0
- package/lib/commands/adopt.js +4 -4
- package/lib/commands/app.js +911 -0
- package/lib/commands/assurance.js +212 -0
- package/lib/commands/auto.js +1093 -11065
- package/lib/commands/mode.js +321 -0
- package/lib/commands/ontology.js +415 -0
- package/lib/commands/pm.js +422 -0
- package/lib/ontology/seed-profiles.js +160 -0
- package/lib/spec/bootstrap/context-collector.js +1 -1
- package/lib/state/sce-state-store.js +3369 -1200
- package/lib/steering/adoption-config.js +2 -2
- package/lib/steering/compliance-cache.js +2 -2
- package/lib/steering/steering-manager.js +4 -4
- package/lib/task/task-claimer.js +1 -2
- package/lib/workspace/multi/workspace-context-resolver.js +3 -3
- package/lib/workspace/multi/workspace-state-manager.js +0 -164
- package/lib/workspace/sce-tracking-audit.js +1 -1
- package/lib/workspace/takeover-baseline.js +1 -1
- package/package.json +1 -1
- package/template/.sce/README.md +1 -1
- package/template/.sce/steering/CORE_PRINCIPLES.md +1 -1
- package/bin/kse.js +0 -3
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
function normalizeHandoffText(value) {
|
|
2
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function parseAutoHandoffGateBoolean(value, fallback = null) {
|
|
6
|
+
if (typeof value === 'boolean') {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
const normalized = normalizeHandoffText(value).toLowerCase();
|
|
10
|
+
if (!normalized) {
|
|
11
|
+
return fallback;
|
|
12
|
+
}
|
|
13
|
+
if (['1', 'true', 'yes', 'y', 'on', 'passed', 'pass'].includes(normalized)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
if (['0', 'false', 'no', 'n', 'off', 'failed', 'fail', 'blocked'].includes(normalized)) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizeAutoHandoffGateRiskLevel(levelCandidate) {
|
|
23
|
+
const normalized = normalizeHandoffText(levelCandidate).toLowerCase();
|
|
24
|
+
if (!normalized) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (['low', 'medium', 'high', 'critical'].includes(normalized)) {
|
|
28
|
+
return normalized;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function toGovernanceReleaseGateNumber(value) {
|
|
34
|
+
if (value === null || value === undefined || value === '') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const parsed = Number(value);
|
|
38
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function normalizeGovernanceReleaseGateSnapshot(snapshotCandidate) {
|
|
42
|
+
if (!snapshotCandidate || typeof snapshotCandidate !== 'object' || Array.isArray(snapshotCandidate)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
available: snapshotCandidate.available === true,
|
|
47
|
+
latest_gate_passed: parseAutoHandoffGateBoolean(snapshotCandidate.latest_gate_passed, null),
|
|
48
|
+
pass_rate_percent: toGovernanceReleaseGateNumber(snapshotCandidate.pass_rate_percent),
|
|
49
|
+
scene_package_batch_pass_rate_percent: toGovernanceReleaseGateNumber(snapshotCandidate.scene_package_batch_pass_rate_percent),
|
|
50
|
+
drift_alert_rate_percent: toGovernanceReleaseGateNumber(snapshotCandidate.drift_alert_rate_percent),
|
|
51
|
+
drift_blocked_runs: toGovernanceReleaseGateNumber(snapshotCandidate.drift_blocked_runs)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function normalizeGovernanceWeeklyOpsStopDetail(detailCandidate) {
|
|
56
|
+
if (!detailCandidate || typeof detailCandidate !== 'object' || Array.isArray(detailCandidate)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const latestCandidate = detailCandidate.latest && typeof detailCandidate.latest === 'object' ? detailCandidate.latest : {};
|
|
60
|
+
const aggregatesCandidate = detailCandidate.aggregates && typeof detailCandidate.aggregates === 'object' ? detailCandidate.aggregates : {};
|
|
61
|
+
const pressureCandidate = detailCandidate.pressure && typeof detailCandidate.pressure === 'object' ? detailCandidate.pressure : {};
|
|
62
|
+
|
|
63
|
+
const latestRiskLevelRaw = normalizeHandoffText(latestCandidate.risk_level);
|
|
64
|
+
const latestRiskLevel = latestRiskLevelRaw ? normalizeAutoHandoffGateRiskLevel(latestRiskLevelRaw) : null;
|
|
65
|
+
const normalized = {
|
|
66
|
+
latest: {
|
|
67
|
+
blocked: parseAutoHandoffGateBoolean(latestCandidate.blocked, null),
|
|
68
|
+
risk_level: latestRiskLevel,
|
|
69
|
+
governance_status: normalizeHandoffText(latestCandidate.governance_status),
|
|
70
|
+
authorization_tier_block_rate_percent: toGovernanceReleaseGateNumber(latestCandidate.authorization_tier_block_rate_percent),
|
|
71
|
+
dialogue_authorization_block_rate_percent: toGovernanceReleaseGateNumber(latestCandidate.dialogue_authorization_block_rate_percent),
|
|
72
|
+
config_warning_count: toGovernanceReleaseGateNumber(latestCandidate.config_warning_count),
|
|
73
|
+
runtime_block_rate_percent: toGovernanceReleaseGateNumber(latestCandidate.runtime_block_rate_percent),
|
|
74
|
+
runtime_ui_mode_violation_total: toGovernanceReleaseGateNumber(latestCandidate.runtime_ui_mode_violation_total),
|
|
75
|
+
runtime_ui_mode_violation_rate_percent: toGovernanceReleaseGateNumber(latestCandidate.runtime_ui_mode_violation_rate_percent)
|
|
76
|
+
},
|
|
77
|
+
aggregates: {
|
|
78
|
+
blocked_runs: toGovernanceReleaseGateNumber(aggregatesCandidate.blocked_runs),
|
|
79
|
+
block_rate_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.block_rate_percent),
|
|
80
|
+
violations_total: toGovernanceReleaseGateNumber(aggregatesCandidate.violations_total),
|
|
81
|
+
warnings_total: toGovernanceReleaseGateNumber(aggregatesCandidate.warnings_total),
|
|
82
|
+
config_warnings_total: toGovernanceReleaseGateNumber(aggregatesCandidate.config_warnings_total),
|
|
83
|
+
authorization_tier_block_rate_max_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.authorization_tier_block_rate_max_percent),
|
|
84
|
+
dialogue_authorization_block_rate_max_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.dialogue_authorization_block_rate_max_percent),
|
|
85
|
+
runtime_block_rate_max_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.runtime_block_rate_max_percent),
|
|
86
|
+
runtime_ui_mode_violation_total: toGovernanceReleaseGateNumber(aggregatesCandidate.runtime_ui_mode_violation_total),
|
|
87
|
+
runtime_ui_mode_violation_run_rate_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.runtime_ui_mode_violation_run_rate_percent),
|
|
88
|
+
runtime_ui_mode_violation_rate_max_percent: toGovernanceReleaseGateNumber(aggregatesCandidate.runtime_ui_mode_violation_rate_max_percent)
|
|
89
|
+
},
|
|
90
|
+
pressure: {
|
|
91
|
+
blocked: parseAutoHandoffGateBoolean(pressureCandidate.blocked, null),
|
|
92
|
+
high: parseAutoHandoffGateBoolean(pressureCandidate.high, null),
|
|
93
|
+
config_warning_positive: parseAutoHandoffGateBoolean(pressureCandidate.config_warning_positive, null),
|
|
94
|
+
auth_tier_block_rate_high: parseAutoHandoffGateBoolean(pressureCandidate.auth_tier_block_rate_high, null),
|
|
95
|
+
dialogue_authorization_block_rate_high: parseAutoHandoffGateBoolean(pressureCandidate.dialogue_authorization_block_rate_high, null),
|
|
96
|
+
runtime_block_rate_high: parseAutoHandoffGateBoolean(pressureCandidate.runtime_block_rate_high, null),
|
|
97
|
+
runtime_ui_mode_violation_high: parseAutoHandoffGateBoolean(pressureCandidate.runtime_ui_mode_violation_high, null)
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const hasSignal = (
|
|
101
|
+
typeof normalized.latest.blocked === 'boolean' ||
|
|
102
|
+
!!normalized.latest.risk_level ||
|
|
103
|
+
!!normalized.latest.governance_status ||
|
|
104
|
+
Number.isFinite(normalized.latest.authorization_tier_block_rate_percent) ||
|
|
105
|
+
Number.isFinite(normalized.latest.dialogue_authorization_block_rate_percent) ||
|
|
106
|
+
Number.isFinite(normalized.latest.config_warning_count) ||
|
|
107
|
+
Number.isFinite(normalized.latest.runtime_block_rate_percent) ||
|
|
108
|
+
Number.isFinite(normalized.latest.runtime_ui_mode_violation_total) ||
|
|
109
|
+
Number.isFinite(normalized.latest.runtime_ui_mode_violation_rate_percent) ||
|
|
110
|
+
Number.isFinite(normalized.aggregates.blocked_runs) ||
|
|
111
|
+
Number.isFinite(normalized.aggregates.block_rate_percent) ||
|
|
112
|
+
Number.isFinite(normalized.aggregates.violations_total) ||
|
|
113
|
+
Number.isFinite(normalized.aggregates.warnings_total) ||
|
|
114
|
+
Number.isFinite(normalized.aggregates.config_warnings_total) ||
|
|
115
|
+
Number.isFinite(normalized.aggregates.authorization_tier_block_rate_max_percent) ||
|
|
116
|
+
Number.isFinite(normalized.aggregates.dialogue_authorization_block_rate_max_percent) ||
|
|
117
|
+
Number.isFinite(normalized.aggregates.runtime_block_rate_max_percent) ||
|
|
118
|
+
Number.isFinite(normalized.aggregates.runtime_ui_mode_violation_total) ||
|
|
119
|
+
Number.isFinite(normalized.aggregates.runtime_ui_mode_violation_run_rate_percent) ||
|
|
120
|
+
Number.isFinite(normalized.aggregates.runtime_ui_mode_violation_rate_max_percent) ||
|
|
121
|
+
typeof normalized.pressure.blocked === 'boolean' ||
|
|
122
|
+
typeof normalized.pressure.high === 'boolean' ||
|
|
123
|
+
typeof normalized.pressure.config_warning_positive === 'boolean' ||
|
|
124
|
+
typeof normalized.pressure.auth_tier_block_rate_high === 'boolean' ||
|
|
125
|
+
typeof normalized.pressure.dialogue_authorization_block_rate_high === 'boolean' ||
|
|
126
|
+
typeof normalized.pressure.runtime_block_rate_high === 'boolean' ||
|
|
127
|
+
typeof normalized.pressure.runtime_ui_mode_violation_high === 'boolean'
|
|
128
|
+
);
|
|
129
|
+
return hasSignal ? normalized : null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
normalizeHandoffText,
|
|
134
|
+
parseAutoHandoffGateBoolean,
|
|
135
|
+
normalizeAutoHandoffGateRiskLevel,
|
|
136
|
+
toGovernanceReleaseGateNumber,
|
|
137
|
+
normalizeGovernanceReleaseGateSnapshot,
|
|
138
|
+
normalizeGovernanceWeeklyOpsStopDetail
|
|
139
|
+
};
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
function presentGovernanceSessionStats(projectPath, filteredSessions, options = {}, dependencies = {}) {
|
|
2
|
+
const sessions = Array.isArray(filteredSessions) ? filteredSessions : [];
|
|
3
|
+
const normalizeStatusToken = dependencies.normalizeStatusToken || ((value) => String(value || '').trim().toLowerCase());
|
|
4
|
+
const isCompletedStatus = dependencies.isCompletedStatus || ((status) => normalizeStatusToken(status) === 'completed');
|
|
5
|
+
const isFailedStatus = dependencies.isFailedStatus || ((status) => ['failed', 'partial-failed', 'error', 'invalid'].includes(normalizeStatusToken(status)));
|
|
6
|
+
const calculatePercent = dependencies.calculatePercent || ((a, b) => (Number(b) > 0 ? Number(((Number(a) / Number(b)) * 100).toFixed(2)) : 0));
|
|
7
|
+
const toGovernanceReleaseGateNumber = dependencies.toGovernanceReleaseGateNumber || ((value) => {
|
|
8
|
+
if (value === null || value === undefined || value === '') {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const parsed = Number(value);
|
|
12
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
13
|
+
});
|
|
14
|
+
const getGovernanceCloseLoopSessionDir = dependencies.getGovernanceCloseLoopSessionDir || ((value) => value);
|
|
15
|
+
const buildStatusCounts = dependencies.buildStatusCounts || (() => ({}));
|
|
16
|
+
const parseAutoHandoffGateBoolean = dependencies.parseAutoHandoffGateBoolean || ((value, fallback = null) => {
|
|
17
|
+
if (value === true) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
if (value === false) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return fallback;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const days = options.days ?? null;
|
|
27
|
+
const statusFilter = Array.isArray(options.status_filter) ? options.status_filter : [];
|
|
28
|
+
const resumeOnly = Boolean(options.resume_only);
|
|
29
|
+
const cutoffMs = options.cutoff_ms ?? null;
|
|
30
|
+
|
|
31
|
+
let completedSessions = 0;
|
|
32
|
+
let failedSessions = 0;
|
|
33
|
+
let stoppedSessions = 0;
|
|
34
|
+
let convergedSessions = 0;
|
|
35
|
+
let advisoryEnabledSessions = 0;
|
|
36
|
+
let advisoryFailedActionsSum = 0;
|
|
37
|
+
let performedRoundsSum = 0;
|
|
38
|
+
let sessionsWithRounds = 0;
|
|
39
|
+
let resumedSessions = 0;
|
|
40
|
+
let releaseGateObservedSessions = 0;
|
|
41
|
+
let releaseGateFailedSessions = 0;
|
|
42
|
+
let releaseGateDriftAlertSessions = 0;
|
|
43
|
+
let releaseGateBlockedSessions = 0;
|
|
44
|
+
let releaseGatePassRateSum = 0;
|
|
45
|
+
let releaseGatePassRateCount = 0;
|
|
46
|
+
let releaseGateSceneBatchPassRateSum = 0;
|
|
47
|
+
let releaseGateSceneBatchPassRateCount = 0;
|
|
48
|
+
let releaseGateDriftAlertRateSum = 0;
|
|
49
|
+
let releaseGateDriftAlertRateCount = 0;
|
|
50
|
+
let roundReleaseGateObservedSum = 0;
|
|
51
|
+
let roundReleaseGateChangedSum = 0;
|
|
52
|
+
let weeklyOpsStopSessions = 0;
|
|
53
|
+
let weeklyOpsBlockedStopSessions = 0;
|
|
54
|
+
let weeklyOpsHighPressureStopSessions = 0;
|
|
55
|
+
let weeklyOpsConfigWarningPositiveStopSessions = 0;
|
|
56
|
+
let weeklyOpsAuthTierPressureStopSessions = 0;
|
|
57
|
+
let weeklyOpsDialoguePressureStopSessions = 0;
|
|
58
|
+
let weeklyOpsRuntimeBlockRateHighStopSessions = 0;
|
|
59
|
+
let weeklyOpsRuntimeUiModeViolationHighStopSessions = 0;
|
|
60
|
+
let weeklyOpsBlockedRunsSum = 0;
|
|
61
|
+
let weeklyOpsBlockedRunsCount = 0;
|
|
62
|
+
let weeklyOpsBlockRateSum = 0;
|
|
63
|
+
let weeklyOpsBlockRateCount = 0;
|
|
64
|
+
let weeklyOpsConfigWarningsTotalSum = 0;
|
|
65
|
+
let weeklyOpsConfigWarningsTotalCount = 0;
|
|
66
|
+
let weeklyOpsAuthTierBlockRateSum = 0;
|
|
67
|
+
let weeklyOpsAuthTierBlockRateCount = 0;
|
|
68
|
+
let weeklyOpsDialogueBlockRateSum = 0;
|
|
69
|
+
let weeklyOpsDialogueBlockRateCount = 0;
|
|
70
|
+
let weeklyOpsRuntimeBlockRateSum = 0;
|
|
71
|
+
let weeklyOpsRuntimeBlockRateCount = 0;
|
|
72
|
+
let weeklyOpsRuntimeUiModeViolationTotalSum = 0;
|
|
73
|
+
let weeklyOpsRuntimeUiModeViolationTotalCount = 0;
|
|
74
|
+
let weeklyOpsRuntimeUiModeViolationRateSum = 0;
|
|
75
|
+
let weeklyOpsRuntimeUiModeViolationRateCount = 0;
|
|
76
|
+
const stopReasonCounts = {};
|
|
77
|
+
const finalRiskCounts = {};
|
|
78
|
+
const resumedFromCounts = {};
|
|
79
|
+
|
|
80
|
+
for (const session of sessions) {
|
|
81
|
+
const status = normalizeStatusToken(session && session.status) || 'unknown';
|
|
82
|
+
if (isCompletedStatus(status)) {
|
|
83
|
+
completedSessions += 1;
|
|
84
|
+
} else if (isFailedStatus(status)) {
|
|
85
|
+
failedSessions += 1;
|
|
86
|
+
} else if (status === 'stopped') {
|
|
87
|
+
stoppedSessions += 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (session && session.converged === true) {
|
|
91
|
+
convergedSessions += 1;
|
|
92
|
+
}
|
|
93
|
+
if (session && session.execute_advisory === true) {
|
|
94
|
+
advisoryEnabledSessions += 1;
|
|
95
|
+
}
|
|
96
|
+
advisoryFailedActionsSum += Number(session && session.advisory_failed_actions) || 0;
|
|
97
|
+
|
|
98
|
+
const performedRounds = Number(session && session.performed_rounds);
|
|
99
|
+
if (Number.isFinite(performedRounds)) {
|
|
100
|
+
performedRoundsSum += performedRounds;
|
|
101
|
+
sessionsWithRounds += 1;
|
|
102
|
+
}
|
|
103
|
+
if (session && session.resumed_from_governance_session_id) {
|
|
104
|
+
resumedSessions += 1;
|
|
105
|
+
const parentId = String(session.resumed_from_governance_session_id).trim() || 'unknown';
|
|
106
|
+
resumedFromCounts[parentId] = (resumedFromCounts[parentId] || 0) + 1;
|
|
107
|
+
}
|
|
108
|
+
if (session && session.release_gate_available === true) {
|
|
109
|
+
releaseGateObservedSessions += 1;
|
|
110
|
+
const latestGatePassed = parseAutoHandoffGateBoolean(session.release_gate_latest_gate_passed, null);
|
|
111
|
+
if (latestGatePassed === false) {
|
|
112
|
+
releaseGateFailedSessions += 1;
|
|
113
|
+
}
|
|
114
|
+
const releaseGatePassRate = Number(session.release_gate_pass_rate_percent);
|
|
115
|
+
if (Number.isFinite(releaseGatePassRate)) {
|
|
116
|
+
releaseGatePassRateSum += releaseGatePassRate;
|
|
117
|
+
releaseGatePassRateCount += 1;
|
|
118
|
+
}
|
|
119
|
+
const sceneBatchPassRate = Number(session.release_gate_scene_package_batch_pass_rate_percent);
|
|
120
|
+
if (Number.isFinite(sceneBatchPassRate)) {
|
|
121
|
+
releaseGateSceneBatchPassRateSum += sceneBatchPassRate;
|
|
122
|
+
releaseGateSceneBatchPassRateCount += 1;
|
|
123
|
+
}
|
|
124
|
+
const driftAlertRate = Number(session.release_gate_drift_alert_rate_percent);
|
|
125
|
+
if (Number.isFinite(driftAlertRate)) {
|
|
126
|
+
releaseGateDriftAlertRateSum += driftAlertRate;
|
|
127
|
+
releaseGateDriftAlertRateCount += 1;
|
|
128
|
+
if (driftAlertRate > 0) {
|
|
129
|
+
releaseGateDriftAlertSessions += 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const driftBlockedRuns = Number(session.release_gate_drift_blocked_runs);
|
|
133
|
+
if (Number.isFinite(driftBlockedRuns) && driftBlockedRuns > 0) {
|
|
134
|
+
releaseGateBlockedSessions += 1;
|
|
135
|
+
}
|
|
136
|
+
roundReleaseGateObservedSum += Number(session.round_release_gate_observed) || 0;
|
|
137
|
+
roundReleaseGateChangedSum += Number(session.round_release_gate_changed) || 0;
|
|
138
|
+
}
|
|
139
|
+
if (session && session.stop_detail_weekly_ops_available === true) {
|
|
140
|
+
weeklyOpsStopSessions += 1;
|
|
141
|
+
}
|
|
142
|
+
if (session && session.stop_detail_weekly_ops_blocked === true) {
|
|
143
|
+
weeklyOpsBlockedStopSessions += 1;
|
|
144
|
+
}
|
|
145
|
+
if (session && session.stop_detail_weekly_ops_high_pressure === true) {
|
|
146
|
+
weeklyOpsHighPressureStopSessions += 1;
|
|
147
|
+
}
|
|
148
|
+
if (session && session.stop_detail_weekly_ops_config_warning_positive === true) {
|
|
149
|
+
weeklyOpsConfigWarningPositiveStopSessions += 1;
|
|
150
|
+
}
|
|
151
|
+
if (session && session.stop_detail_weekly_ops_auth_tier_block_rate_high === true) {
|
|
152
|
+
weeklyOpsAuthTierPressureStopSessions += 1;
|
|
153
|
+
}
|
|
154
|
+
if (session && session.stop_detail_weekly_ops_dialogue_authorization_block_rate_high === true) {
|
|
155
|
+
weeklyOpsDialoguePressureStopSessions += 1;
|
|
156
|
+
}
|
|
157
|
+
if (session && session.stop_detail_weekly_ops_runtime_block_rate_high === true) {
|
|
158
|
+
weeklyOpsRuntimeBlockRateHighStopSessions += 1;
|
|
159
|
+
}
|
|
160
|
+
if (session && session.stop_detail_weekly_ops_runtime_ui_mode_violation_high === true) {
|
|
161
|
+
weeklyOpsRuntimeUiModeViolationHighStopSessions += 1;
|
|
162
|
+
}
|
|
163
|
+
const weeklyOpsBlockedRuns = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_blocked_runs);
|
|
164
|
+
if (Number.isFinite(weeklyOpsBlockedRuns)) {
|
|
165
|
+
weeklyOpsBlockedRunsSum += weeklyOpsBlockedRuns;
|
|
166
|
+
weeklyOpsBlockedRunsCount += 1;
|
|
167
|
+
}
|
|
168
|
+
const weeklyOpsBlockRate = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_block_rate_percent);
|
|
169
|
+
if (Number.isFinite(weeklyOpsBlockRate)) {
|
|
170
|
+
weeklyOpsBlockRateSum += weeklyOpsBlockRate;
|
|
171
|
+
weeklyOpsBlockRateCount += 1;
|
|
172
|
+
}
|
|
173
|
+
const weeklyOpsConfigWarningsTotal = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_config_warnings_total);
|
|
174
|
+
if (Number.isFinite(weeklyOpsConfigWarningsTotal)) {
|
|
175
|
+
weeklyOpsConfigWarningsTotalSum += weeklyOpsConfigWarningsTotal;
|
|
176
|
+
weeklyOpsConfigWarningsTotalCount += 1;
|
|
177
|
+
}
|
|
178
|
+
const weeklyOpsAuthTierBlockRate = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_auth_tier_block_rate_percent);
|
|
179
|
+
if (Number.isFinite(weeklyOpsAuthTierBlockRate)) {
|
|
180
|
+
weeklyOpsAuthTierBlockRateSum += weeklyOpsAuthTierBlockRate;
|
|
181
|
+
weeklyOpsAuthTierBlockRateCount += 1;
|
|
182
|
+
}
|
|
183
|
+
const weeklyOpsDialogueBlockRate = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_dialogue_authorization_block_rate_percent);
|
|
184
|
+
if (Number.isFinite(weeklyOpsDialogueBlockRate)) {
|
|
185
|
+
weeklyOpsDialogueBlockRateSum += weeklyOpsDialogueBlockRate;
|
|
186
|
+
weeklyOpsDialogueBlockRateCount += 1;
|
|
187
|
+
}
|
|
188
|
+
const weeklyOpsRuntimeBlockRate = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_runtime_block_rate_percent);
|
|
189
|
+
if (Number.isFinite(weeklyOpsRuntimeBlockRate)) {
|
|
190
|
+
weeklyOpsRuntimeBlockRateSum += weeklyOpsRuntimeBlockRate;
|
|
191
|
+
weeklyOpsRuntimeBlockRateCount += 1;
|
|
192
|
+
}
|
|
193
|
+
const weeklyOpsRuntimeUiModeViolationTotal = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_runtime_ui_mode_violation_total);
|
|
194
|
+
if (Number.isFinite(weeklyOpsRuntimeUiModeViolationTotal)) {
|
|
195
|
+
weeklyOpsRuntimeUiModeViolationTotalSum += weeklyOpsRuntimeUiModeViolationTotal;
|
|
196
|
+
weeklyOpsRuntimeUiModeViolationTotalCount += 1;
|
|
197
|
+
}
|
|
198
|
+
const weeklyOpsRuntimeUiModeViolationRate = toGovernanceReleaseGateNumber(session && session.stop_detail_weekly_ops_runtime_ui_mode_violation_rate_percent);
|
|
199
|
+
if (Number.isFinite(weeklyOpsRuntimeUiModeViolationRate)) {
|
|
200
|
+
weeklyOpsRuntimeUiModeViolationRateSum += weeklyOpsRuntimeUiModeViolationRate;
|
|
201
|
+
weeklyOpsRuntimeUiModeViolationRateCount += 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const stopReason = String(session && session.stop_reason ? session.stop_reason : '').trim().toLowerCase() || 'unknown';
|
|
205
|
+
stopReasonCounts[stopReason] = (stopReasonCounts[stopReason] || 0) + 1;
|
|
206
|
+
|
|
207
|
+
const finalRisk = String(session && session.final_risk ? session.final_risk : '').trim().toLowerCase() || 'unknown';
|
|
208
|
+
finalRiskCounts[finalRisk] = (finalRiskCounts[finalRisk] || 0) + 1;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const totalSessions = sessions.length;
|
|
212
|
+
const completionRate = totalSessions > 0 ? Number(((completedSessions / totalSessions) * 100).toFixed(2)) : 0;
|
|
213
|
+
const failureRate = totalSessions > 0 ? Number(((failedSessions / totalSessions) * 100).toFixed(2)) : 0;
|
|
214
|
+
const averagePerformedRounds = sessionsWithRounds > 0 ? Number((performedRoundsSum / sessionsWithRounds).toFixed(2)) : 0;
|
|
215
|
+
const resumedRate = totalSessions > 0 ? Number(((resumedSessions / totalSessions) * 100).toFixed(2)) : 0;
|
|
216
|
+
const latestSession = totalSessions > 0 ? sessions[0] : null;
|
|
217
|
+
const oldestSession = totalSessions > 0 ? sessions[sessions.length - 1] : null;
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
mode: 'auto-governance-session-stats',
|
|
221
|
+
session_dir: getGovernanceCloseLoopSessionDir(projectPath),
|
|
222
|
+
criteria: {
|
|
223
|
+
days,
|
|
224
|
+
status_filter: statusFilter,
|
|
225
|
+
resume_only: resumeOnly,
|
|
226
|
+
since: cutoffMs === null ? null : new Date(cutoffMs).toISOString()
|
|
227
|
+
},
|
|
228
|
+
total_sessions: totalSessions,
|
|
229
|
+
resumed_sessions: resumedSessions,
|
|
230
|
+
fresh_sessions: totalSessions - resumedSessions,
|
|
231
|
+
resumed_rate_percent: resumedRate,
|
|
232
|
+
completed_sessions: completedSessions,
|
|
233
|
+
failed_sessions: failedSessions,
|
|
234
|
+
stopped_sessions: stoppedSessions,
|
|
235
|
+
converged_sessions: convergedSessions,
|
|
236
|
+
advisory_enabled_sessions: advisoryEnabledSessions,
|
|
237
|
+
advisory_failed_actions_sum: advisoryFailedActionsSum,
|
|
238
|
+
completion_rate_percent: completionRate,
|
|
239
|
+
failure_rate_percent: failureRate,
|
|
240
|
+
average_performed_rounds: averagePerformedRounds,
|
|
241
|
+
release_gate: {
|
|
242
|
+
observed_sessions: releaseGateObservedSessions,
|
|
243
|
+
failed_sessions: releaseGateFailedSessions,
|
|
244
|
+
failed_rate_percent: calculatePercent(releaseGateFailedSessions, releaseGateObservedSessions),
|
|
245
|
+
drift_alert_sessions: releaseGateDriftAlertSessions,
|
|
246
|
+
drift_alert_session_rate_percent: calculatePercent(releaseGateDriftAlertSessions, releaseGateObservedSessions),
|
|
247
|
+
blocked_sessions: releaseGateBlockedSessions,
|
|
248
|
+
average_pass_rate_percent: releaseGatePassRateCount > 0 ? Number((releaseGatePassRateSum / releaseGatePassRateCount).toFixed(2)) : null,
|
|
249
|
+
average_scene_package_batch_pass_rate_percent: releaseGateSceneBatchPassRateCount > 0 ? Number((releaseGateSceneBatchPassRateSum / releaseGateSceneBatchPassRateCount).toFixed(2)) : null,
|
|
250
|
+
average_drift_alert_rate_percent: releaseGateDriftAlertRateCount > 0 ? Number((releaseGateDriftAlertRateSum / releaseGateDriftAlertRateCount).toFixed(2)) : null,
|
|
251
|
+
round_telemetry_observed: roundReleaseGateObservedSum,
|
|
252
|
+
round_telemetry_changed: roundReleaseGateChangedSum,
|
|
253
|
+
round_telemetry_change_rate_percent: calculatePercent(roundReleaseGateChangedSum, roundReleaseGateObservedSum),
|
|
254
|
+
weekly_ops_stop: {
|
|
255
|
+
sessions: weeklyOpsStopSessions,
|
|
256
|
+
session_rate_percent: calculatePercent(weeklyOpsStopSessions, totalSessions),
|
|
257
|
+
blocked_sessions: weeklyOpsBlockedStopSessions,
|
|
258
|
+
blocked_session_rate_percent: calculatePercent(weeklyOpsBlockedStopSessions, weeklyOpsStopSessions),
|
|
259
|
+
high_pressure_sessions: weeklyOpsHighPressureStopSessions,
|
|
260
|
+
high_pressure_session_rate_percent: calculatePercent(weeklyOpsHighPressureStopSessions, weeklyOpsStopSessions),
|
|
261
|
+
config_warning_positive_sessions: weeklyOpsConfigWarningPositiveStopSessions,
|
|
262
|
+
config_warning_positive_rate_percent: calculatePercent(weeklyOpsConfigWarningPositiveStopSessions, weeklyOpsStopSessions),
|
|
263
|
+
auth_tier_pressure_sessions: weeklyOpsAuthTierPressureStopSessions,
|
|
264
|
+
auth_tier_pressure_rate_percent: calculatePercent(weeklyOpsAuthTierPressureStopSessions, weeklyOpsStopSessions),
|
|
265
|
+
dialogue_authorization_pressure_sessions: weeklyOpsDialoguePressureStopSessions,
|
|
266
|
+
dialogue_authorization_pressure_rate_percent: calculatePercent(weeklyOpsDialoguePressureStopSessions, weeklyOpsStopSessions),
|
|
267
|
+
runtime_block_rate_high_sessions: weeklyOpsRuntimeBlockRateHighStopSessions,
|
|
268
|
+
runtime_block_rate_high_rate_percent: calculatePercent(weeklyOpsRuntimeBlockRateHighStopSessions, weeklyOpsStopSessions),
|
|
269
|
+
runtime_ui_mode_violation_high_sessions: weeklyOpsRuntimeUiModeViolationHighStopSessions,
|
|
270
|
+
runtime_ui_mode_violation_high_rate_percent: calculatePercent(weeklyOpsRuntimeUiModeViolationHighStopSessions, weeklyOpsStopSessions),
|
|
271
|
+
blocked_runs_sum: weeklyOpsBlockedRunsSum,
|
|
272
|
+
average_blocked_runs: weeklyOpsBlockedRunsCount > 0 ? Number((weeklyOpsBlockedRunsSum / weeklyOpsBlockedRunsCount).toFixed(2)) : null,
|
|
273
|
+
average_block_rate_percent: weeklyOpsBlockRateCount > 0 ? Number((weeklyOpsBlockRateSum / weeklyOpsBlockRateCount).toFixed(2)) : null,
|
|
274
|
+
config_warnings_total_sum: weeklyOpsConfigWarningsTotalSum,
|
|
275
|
+
average_config_warnings_total: weeklyOpsConfigWarningsTotalCount > 0 ? Number((weeklyOpsConfigWarningsTotalSum / weeklyOpsConfigWarningsTotalCount).toFixed(2)) : null,
|
|
276
|
+
average_auth_tier_block_rate_percent: weeklyOpsAuthTierBlockRateCount > 0 ? Number((weeklyOpsAuthTierBlockRateSum / weeklyOpsAuthTierBlockRateCount).toFixed(2)) : null,
|
|
277
|
+
average_dialogue_authorization_block_rate_percent: weeklyOpsDialogueBlockRateCount > 0 ? Number((weeklyOpsDialogueBlockRateSum / weeklyOpsDialogueBlockRateCount).toFixed(2)) : null,
|
|
278
|
+
average_runtime_block_rate_percent: weeklyOpsRuntimeBlockRateCount > 0 ? Number((weeklyOpsRuntimeBlockRateSum / weeklyOpsRuntimeBlockRateCount).toFixed(2)) : null,
|
|
279
|
+
runtime_ui_mode_violation_total_sum: weeklyOpsRuntimeUiModeViolationTotalSum,
|
|
280
|
+
average_runtime_ui_mode_violation_total: weeklyOpsRuntimeUiModeViolationTotalCount > 0 ? Number((weeklyOpsRuntimeUiModeViolationTotalSum / weeklyOpsRuntimeUiModeViolationTotalCount).toFixed(2)) : null,
|
|
281
|
+
average_runtime_ui_mode_violation_rate_percent: weeklyOpsRuntimeUiModeViolationRateCount > 0 ? Number((weeklyOpsRuntimeUiModeViolationRateSum / weeklyOpsRuntimeUiModeViolationRateCount).toFixed(2)) : null
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
status_counts: buildStatusCounts(sessions),
|
|
285
|
+
stop_reason_counts: stopReasonCounts,
|
|
286
|
+
final_risk_counts: finalRiskCounts,
|
|
287
|
+
resumed_from_counts: resumedFromCounts,
|
|
288
|
+
latest_updated_at: latestSession ? latestSession.updated_at : null,
|
|
289
|
+
oldest_updated_at: oldestSession ? oldestSession.updated_at : null,
|
|
290
|
+
latest_sessions: sessions.slice(0, 10).map((item) => ({
|
|
291
|
+
id: item.id,
|
|
292
|
+
status: item.status,
|
|
293
|
+
target_risk: item.target_risk,
|
|
294
|
+
final_risk: item.final_risk,
|
|
295
|
+
performed_rounds: item.performed_rounds,
|
|
296
|
+
max_rounds: item.max_rounds,
|
|
297
|
+
converged: item.converged,
|
|
298
|
+
execute_advisory: item.execute_advisory,
|
|
299
|
+
advisory_failed_actions: item.advisory_failed_actions,
|
|
300
|
+
release_gate_available: item.release_gate_available,
|
|
301
|
+
release_gate_latest_gate_passed: item.release_gate_latest_gate_passed,
|
|
302
|
+
release_gate_pass_rate_percent: item.release_gate_pass_rate_percent,
|
|
303
|
+
release_gate_drift_alert_rate_percent: item.release_gate_drift_alert_rate_percent,
|
|
304
|
+
round_release_gate_observed: item.round_release_gate_observed,
|
|
305
|
+
round_release_gate_changed: item.round_release_gate_changed,
|
|
306
|
+
stop_detail_weekly_ops_available: item.stop_detail_weekly_ops_available,
|
|
307
|
+
stop_detail_weekly_ops_blocked: item.stop_detail_weekly_ops_blocked,
|
|
308
|
+
stop_detail_weekly_ops_high_pressure: item.stop_detail_weekly_ops_high_pressure,
|
|
309
|
+
stop_detail_weekly_ops_config_warning_positive: item.stop_detail_weekly_ops_config_warning_positive,
|
|
310
|
+
stop_detail_weekly_ops_auth_tier_block_rate_high: item.stop_detail_weekly_ops_auth_tier_block_rate_high,
|
|
311
|
+
stop_detail_weekly_ops_dialogue_authorization_block_rate_high:
|
|
312
|
+
item.stop_detail_weekly_ops_dialogue_authorization_block_rate_high,
|
|
313
|
+
stop_detail_weekly_ops_runtime_block_rate_high: item.stop_detail_weekly_ops_runtime_block_rate_high,
|
|
314
|
+
stop_detail_weekly_ops_runtime_ui_mode_violation_high:
|
|
315
|
+
item.stop_detail_weekly_ops_runtime_ui_mode_violation_high,
|
|
316
|
+
stop_detail_weekly_ops_blocked_runs: item.stop_detail_weekly_ops_blocked_runs,
|
|
317
|
+
stop_detail_weekly_ops_block_rate_percent: item.stop_detail_weekly_ops_block_rate_percent,
|
|
318
|
+
stop_detail_weekly_ops_config_warnings_total: item.stop_detail_weekly_ops_config_warnings_total,
|
|
319
|
+
stop_detail_weekly_ops_auth_tier_block_rate_percent: item.stop_detail_weekly_ops_auth_tier_block_rate_percent,
|
|
320
|
+
stop_detail_weekly_ops_dialogue_authorization_block_rate_percent:
|
|
321
|
+
item.stop_detail_weekly_ops_dialogue_authorization_block_rate_percent,
|
|
322
|
+
stop_detail_weekly_ops_runtime_block_rate_percent: item.stop_detail_weekly_ops_runtime_block_rate_percent,
|
|
323
|
+
stop_detail_weekly_ops_runtime_ui_mode_violation_total:
|
|
324
|
+
item.stop_detail_weekly_ops_runtime_ui_mode_violation_total,
|
|
325
|
+
stop_detail_weekly_ops_runtime_ui_mode_violation_rate_percent:
|
|
326
|
+
item.stop_detail_weekly_ops_runtime_ui_mode_violation_rate_percent,
|
|
327
|
+
stop_reason: item.stop_reason,
|
|
328
|
+
resumed_from_governance_session_id: item.resumed_from_governance_session_id,
|
|
329
|
+
updated_at: item.updated_at,
|
|
330
|
+
parse_error: item.parse_error
|
|
331
|
+
}))
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
module.exports = {
|
|
336
|
+
presentGovernanceSessionStats
|
|
337
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
async function buildAutoGovernanceStats(projectPath, options = {}, dependencies = {}) {
|
|
2
|
+
const {
|
|
3
|
+
normalizeStatsWindowDays,
|
|
4
|
+
normalizeStatusFilter,
|
|
5
|
+
statsCloseLoopSessions,
|
|
6
|
+
statsCloseLoopBatchSummarySessions,
|
|
7
|
+
statsCloseLoopControllerSessions,
|
|
8
|
+
showCloseLoopRecoveryMemory,
|
|
9
|
+
loadGovernanceReleaseGateSignals,
|
|
10
|
+
loadGovernanceHandoffQualitySignals,
|
|
11
|
+
calculatePercent,
|
|
12
|
+
deriveGovernanceRiskLevel,
|
|
13
|
+
buildGovernanceConcerns,
|
|
14
|
+
buildGovernanceRecommendations,
|
|
15
|
+
buildTopCountEntries,
|
|
16
|
+
now = () => new Date()
|
|
17
|
+
} = dependencies;
|
|
18
|
+
|
|
19
|
+
const days = normalizeStatsWindowDays(options.days);
|
|
20
|
+
const statusFilter = normalizeStatusFilter(options.status);
|
|
21
|
+
const normalizedOptions = {
|
|
22
|
+
days,
|
|
23
|
+
status: statusFilter.length > 0 ? statusFilter.join(',') : undefined
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const [sessionStats, batchStats, controllerStats, recoveryMemory, releaseGateSignals, handoffQualitySignals] = await Promise.all([
|
|
27
|
+
statsCloseLoopSessions(projectPath, normalizedOptions),
|
|
28
|
+
statsCloseLoopBatchSummarySessions(projectPath, normalizedOptions),
|
|
29
|
+
statsCloseLoopControllerSessions(projectPath, normalizedOptions),
|
|
30
|
+
showCloseLoopRecoveryMemory(projectPath, {}),
|
|
31
|
+
loadGovernanceReleaseGateSignals(projectPath),
|
|
32
|
+
loadGovernanceHandoffQualitySignals(projectPath)
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const totalSessions =
|
|
36
|
+
(Number(sessionStats.total_sessions) || 0) +
|
|
37
|
+
(Number(batchStats.total_sessions) || 0) +
|
|
38
|
+
(Number(controllerStats.total_sessions) || 0);
|
|
39
|
+
const completedSessions =
|
|
40
|
+
(Number(sessionStats.completed_sessions) || 0) +
|
|
41
|
+
(Number(batchStats.completed_sessions) || 0) +
|
|
42
|
+
(Number(controllerStats.completed_sessions) || 0);
|
|
43
|
+
const failedSessions =
|
|
44
|
+
(Number(sessionStats.failed_sessions) || 0) +
|
|
45
|
+
(Number(batchStats.failed_sessions) || 0) +
|
|
46
|
+
(Number(controllerStats.failed_sessions) || 0);
|
|
47
|
+
const pendingGoalsSum = Number(controllerStats.pending_goals_sum) || 0;
|
|
48
|
+
const recoverySignatureCount = Number(recoveryMemory && recoveryMemory.stats && recoveryMemory.stats.signature_count) || 0;
|
|
49
|
+
const summary = {
|
|
50
|
+
total_sessions: totalSessions,
|
|
51
|
+
completed_sessions: completedSessions,
|
|
52
|
+
failed_sessions: failedSessions,
|
|
53
|
+
failure_rate_percent: calculatePercent(failedSessions, totalSessions),
|
|
54
|
+
completion_rate_percent: calculatePercent(completedSessions, totalSessions),
|
|
55
|
+
pending_goals_sum: pendingGoalsSum,
|
|
56
|
+
recovery_signature_count: recoverySignatureCount,
|
|
57
|
+
release_gate: releaseGateSignals,
|
|
58
|
+
handoff_quality: handoffQualitySignals
|
|
59
|
+
};
|
|
60
|
+
const riskLevel = deriveGovernanceRiskLevel(summary);
|
|
61
|
+
const concerns = buildGovernanceConcerns(summary);
|
|
62
|
+
const recommendations = buildGovernanceRecommendations({
|
|
63
|
+
...summary,
|
|
64
|
+
risk_level: riskLevel
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
mode: 'auto-governance-stats',
|
|
69
|
+
generated_at: new Date().toISOString(),
|
|
70
|
+
criteria: {
|
|
71
|
+
days,
|
|
72
|
+
status_filter: statusFilter,
|
|
73
|
+
since: days === null
|
|
74
|
+
? null
|
|
75
|
+
: new Date(Date.now() - (days * 24 * 60 * 60 * 1000)).toISOString()
|
|
76
|
+
},
|
|
77
|
+
totals: {
|
|
78
|
+
total_sessions: totalSessions,
|
|
79
|
+
completed_sessions: completedSessions,
|
|
80
|
+
failed_sessions: failedSessions,
|
|
81
|
+
completion_rate_percent: summary.completion_rate_percent,
|
|
82
|
+
failure_rate_percent: summary.failure_rate_percent
|
|
83
|
+
},
|
|
84
|
+
throughput: {
|
|
85
|
+
sub_spec_count_sum: Number(sessionStats.sub_spec_count_sum) || 0,
|
|
86
|
+
batch_total_goals_sum: Number(batchStats.total_goals_sum) || 0,
|
|
87
|
+
batch_processed_goals_sum: Number(batchStats.processed_goals_sum) || 0,
|
|
88
|
+
controller_processed_goals_sum: Number(controllerStats.processed_goals_sum) || 0,
|
|
89
|
+
controller_pending_goals_sum: pendingGoalsSum
|
|
90
|
+
},
|
|
91
|
+
top_master_specs: buildTopCountEntries(sessionStats.master_spec_counts, 10),
|
|
92
|
+
health: {
|
|
93
|
+
risk_level: riskLevel,
|
|
94
|
+
concerns,
|
|
95
|
+
recommendations,
|
|
96
|
+
release_gate: releaseGateSignals,
|
|
97
|
+
handoff_quality: handoffQualitySignals
|
|
98
|
+
},
|
|
99
|
+
recovery_memory: {
|
|
100
|
+
file: recoveryMemory.file,
|
|
101
|
+
scope: recoveryMemory.scope,
|
|
102
|
+
signature_count: recoverySignatureCount,
|
|
103
|
+
action_count: Number(recoveryMemory && recoveryMemory.stats && recoveryMemory.stats.action_count) || 0
|
|
104
|
+
},
|
|
105
|
+
archives: {
|
|
106
|
+
session: sessionStats,
|
|
107
|
+
batch_session: batchStats,
|
|
108
|
+
controller_session: controllerStats
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
buildAutoGovernanceStats
|
|
115
|
+
};
|