scene-capability-engine 3.6.47 → 3.6.48
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 +9 -0
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.48.md +19 -0
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.48.md +19 -0
- package/lib/studio/spec-intake-governor.js +27 -5
- package/lib/workspace/takeover-baseline.js +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.6.48] - 2026-03-14
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Added `governance.duplicate_detection_scope` to studio spec governance policy with supported values `all`, `non_completed`, and `active_only`.
|
|
14
|
+
- Changed the default duplicate governance scope to `non_completed`, so duplicate detection compares active and stale specs but no longer treats completed historical specs as duplicate noise.
|
|
15
|
+
- Updated studio intake normalization and scene governance reporting to filter duplicate candidate sets by the configured scope before generating duplicate alerts.
|
|
16
|
+
- Synced the new duplicate governance scope into takeover baseline defaults so adopted and upgraded projects inherit the same non-completed duplicate detection behavior by default.
|
|
17
|
+
- Added regression coverage proving completed history specs do not trigger duplicate governance alerts under the new default scope.
|
|
18
|
+
|
|
10
19
|
## [3.6.47] - 2026-03-14
|
|
11
20
|
|
|
12
21
|
### Changed
|
package/docs/releases/README.md
CHANGED
|
@@ -9,6 +9,7 @@ This directory stores release-facing documents:
|
|
|
9
9
|
## Archived Versions
|
|
10
10
|
|
|
11
11
|
- [Release checklist](../release-checklist.md)
|
|
12
|
+
- [v3.6.48 release notes](./v3.6.48.md)
|
|
12
13
|
- [v3.6.47 release notes](./v3.6.47.md)
|
|
13
14
|
- [v3.6.46 release notes](./v3.6.46.md)
|
|
14
15
|
- [v3.6.45 release notes](./v3.6.45.md)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# v3.6.48 Release Notes
|
|
2
|
+
|
|
3
|
+
Release date: 2026-03-14
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- Added `governance.duplicate_detection_scope` to studio spec governance with three supported values: `all`, `non_completed`, and `active_only`.
|
|
8
|
+
- Changed the default duplicate governance scope to `non_completed`, so duplicate checks now compare active and stale specs while excluding completed historical specs from duplicate pair detection.
|
|
9
|
+
- Synced the same default into takeover baseline, so adopted and upgraded projects inherit the lower-noise duplicate governance behavior automatically.
|
|
10
|
+
|
|
11
|
+
## Validation
|
|
12
|
+
|
|
13
|
+
- `npx jest tests/unit/studio/spec-intake-governor.test.js --runInBand`
|
|
14
|
+
- `npm run prepublishOnly`
|
|
15
|
+
|
|
16
|
+
## Release Notes
|
|
17
|
+
|
|
18
|
+
- This patch reduces governance noise in repositories with many completed template-style specs, where historical completed work previously flooded duplicate alerts and hid active governance problems.
|
|
19
|
+
- The default keeps duplicate sensitivity on unclosed work (`active` + `stale`) without requiring every upgraded project to hand-tune its own studio intake policy.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# v3.6.48 发布说明
|
|
2
|
+
|
|
3
|
+
发布日期:2026-03-14
|
|
4
|
+
|
|
5
|
+
## 重点变化
|
|
6
|
+
|
|
7
|
+
- 为 studio spec governance 增加 `governance.duplicate_detection_scope`,支持 `all`、`non_completed`、`active_only` 三种取值。
|
|
8
|
+
- 将默认 duplicate 检测策略调整为 `non_completed`:只比较 `active` 与 `stale` spec,不再把 `completed` 历史 spec 纳入 duplicate 对比。
|
|
9
|
+
- 将同样的默认值同步到 takeover baseline,确保 adopt / upgrade 后的项目自动继承这套降噪后的治理行为。
|
|
10
|
+
|
|
11
|
+
## 验证
|
|
12
|
+
|
|
13
|
+
- `npx jest tests/unit/studio/spec-intake-governor.test.js --runInBand`
|
|
14
|
+
- `npm run prepublishOnly`
|
|
15
|
+
|
|
16
|
+
## 发布说明
|
|
17
|
+
|
|
18
|
+
- 这个补丁版主要解决“历史 completed spec 太多时 duplicate 告警淹没真实 active 治理问题”的噪音问题。
|
|
19
|
+
- 新默认值仍保留对未收口 spec 的治理敏感度,但不再让历史归档 spec 持续制造无效 duplicate 告警。
|
|
@@ -82,7 +82,8 @@ const DEFAULT_STUDIO_INTAKE_POLICY = Object.freeze({
|
|
|
82
82
|
require_auto_on_plan: true,
|
|
83
83
|
max_active_specs_per_scene: 3,
|
|
84
84
|
stale_days: 14,
|
|
85
|
-
duplicate_similarity_threshold: 0.66
|
|
85
|
+
duplicate_similarity_threshold: 0.66,
|
|
86
|
+
duplicate_detection_scope: 'non_completed'
|
|
86
87
|
},
|
|
87
88
|
backfill: {
|
|
88
89
|
enabled: true,
|
|
@@ -132,6 +133,14 @@ function normalizeBoolean(value, fallback = false) {
|
|
|
132
133
|
return fallback;
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
function normalizeDuplicateDetectionScope(value, fallback = 'non_completed') {
|
|
137
|
+
const normalized = normalizeText(value).toLowerCase();
|
|
138
|
+
if (['all', 'non_completed', 'active_only'].includes(normalized)) {
|
|
139
|
+
return normalized;
|
|
140
|
+
}
|
|
141
|
+
return fallback;
|
|
142
|
+
}
|
|
143
|
+
|
|
135
144
|
function normalizeTextList(value = []) {
|
|
136
145
|
if (!Array.isArray(value)) {
|
|
137
146
|
return [];
|
|
@@ -330,6 +339,10 @@ function normalizeStudioIntakePolicy(raw = {}) {
|
|
|
330
339
|
governance.duplicate_similarity_threshold,
|
|
331
340
|
DEFAULT_STUDIO_INTAKE_POLICY.governance.duplicate_similarity_threshold
|
|
332
341
|
))
|
|
342
|
+
),
|
|
343
|
+
duplicate_detection_scope: normalizeDuplicateDetectionScope(
|
|
344
|
+
governance.duplicate_detection_scope,
|
|
345
|
+
DEFAULT_STUDIO_INTAKE_POLICY.governance.duplicate_detection_scope
|
|
333
346
|
)
|
|
334
347
|
},
|
|
335
348
|
backfill: {
|
|
@@ -898,6 +911,10 @@ function buildSceneGovernanceReport(records = [], policy = DEFAULT_STUDIO_INTAKE
|
|
|
898
911
|
const governance = policy.governance || DEFAULT_STUDIO_INTAKE_POLICY.governance;
|
|
899
912
|
const threshold = normalizeNumber(governance.duplicate_similarity_threshold, 0.66);
|
|
900
913
|
const maxActive = normalizeInteger(governance.max_active_specs_per_scene, 3, 1, 200);
|
|
914
|
+
const duplicateScope = normalizeDuplicateDetectionScope(
|
|
915
|
+
governance.duplicate_detection_scope,
|
|
916
|
+
DEFAULT_STUDIO_INTAKE_POLICY.governance.duplicate_detection_scope
|
|
917
|
+
);
|
|
901
918
|
|
|
902
919
|
const sceneMap = new Map();
|
|
903
920
|
for (const record of records) {
|
|
@@ -918,12 +935,17 @@ function buildSceneGovernanceReport(records = [], policy = DEFAULT_STUDIO_INTAKE
|
|
|
918
935
|
const activeSpecs = sortedSpecs.filter((item) => item.lifecycle_state === 'active');
|
|
919
936
|
const staleSpecs = sortedSpecs.filter((item) => item.lifecycle_state === 'stale');
|
|
920
937
|
const completedSpecs = sortedSpecs.filter((item) => item.lifecycle_state === 'completed');
|
|
938
|
+
const duplicateCandidateSpecs = duplicateScope === 'active_only'
|
|
939
|
+
? activeSpecs
|
|
940
|
+
: (duplicateScope === 'non_completed'
|
|
941
|
+
? sortedSpecs.filter((item) => item.lifecycle_state !== 'completed')
|
|
942
|
+
: sortedSpecs);
|
|
921
943
|
|
|
922
944
|
const duplicates = [];
|
|
923
|
-
for (let i = 0; i <
|
|
924
|
-
for (let j = i + 1; j <
|
|
925
|
-
const left =
|
|
926
|
-
const right =
|
|
945
|
+
for (let i = 0; i < duplicateCandidateSpecs.length; i += 1) {
|
|
946
|
+
for (let j = i + 1; j < duplicateCandidateSpecs.length; j += 1) {
|
|
947
|
+
const left = duplicateCandidateSpecs[i];
|
|
948
|
+
const right = duplicateCandidateSpecs[j];
|
|
927
949
|
const similarity = computeJaccard(left.tokens, right.tokens);
|
|
928
950
|
if (similarity >= threshold) {
|
|
929
951
|
duplicatePairs += 1;
|
|
@@ -235,7 +235,8 @@ const STUDIO_INTAKE_POLICY_DEFAULTS = Object.freeze({
|
|
|
235
235
|
require_auto_on_plan: true,
|
|
236
236
|
max_active_specs_per_scene: 3,
|
|
237
237
|
stale_days: 14,
|
|
238
|
-
duplicate_similarity_threshold: 0.66
|
|
238
|
+
duplicate_similarity_threshold: 0.66,
|
|
239
|
+
duplicate_detection_scope: 'non_completed'
|
|
239
240
|
},
|
|
240
241
|
backfill: {
|
|
241
242
|
enabled: true,
|
|
@@ -319,7 +320,8 @@ const TAKEOVER_DEFAULTS = Object.freeze({
|
|
|
319
320
|
require_auto_on_plan: true,
|
|
320
321
|
max_active_specs_per_scene: 3,
|
|
321
322
|
stale_days: 14,
|
|
322
|
-
duplicate_similarity_threshold: 0.66
|
|
323
|
+
duplicate_similarity_threshold: 0.66,
|
|
324
|
+
duplicate_detection_scope: 'non_completed'
|
|
323
325
|
},
|
|
324
326
|
backfill: {
|
|
325
327
|
enabled: true,
|
package/package.json
CHANGED