scene-capability-engine 3.6.64 → 3.6.67

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 (125) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +17 -6
  3. package/README.zh.md +18 -6
  4. package/bin/scene-capability-engine.js +4 -0
  5. package/docs/README.md +2 -2
  6. package/docs/command-reference.md +385 -8
  7. package/docs/document-governance.md +3 -2
  8. package/docs/integration-modes.md +62 -478
  9. package/docs/integration-philosophy.md +56 -263
  10. package/docs/magicball-cli-invocation-examples.md +1 -0
  11. package/docs/magicball-project-portfolio-contract.md +125 -4
  12. package/docs/project-management/README.md +14 -0
  13. package/docs/project-management/assurance/backup.md +3 -0
  14. package/docs/project-management/assurance/config.md +3 -0
  15. package/docs/project-management/assurance/evidence/README.md +3 -0
  16. package/docs/project-management/assurance/incidents/README.md +3 -0
  17. package/docs/project-management/assurance/logs.md +3 -0
  18. package/docs/project-management/assurance/overview.md +3 -0
  19. package/docs/project-management/assurance/recovery/README.md +3 -0
  20. package/docs/project-management/assurance/resource.md +3 -0
  21. package/docs/project-management/assurance/runbooks/README.md +3 -0
  22. package/docs/project-management/delivery/acceptance/README.md +3 -0
  23. package/docs/project-management/delivery/acceptance/evidence/README.md +3 -0
  24. package/docs/project-management/delivery/acceptance/exceptions/README.md +3 -0
  25. package/docs/project-management/delivery/acceptance/reports/README.md +3 -0
  26. package/docs/project-management/delivery/documents/changes.md +3 -0
  27. package/docs/project-management/delivery/documents/issues.md +3 -0
  28. package/docs/project-management/delivery/documents/overview.md +3 -0
  29. package/docs/project-management/delivery/documents/planning.md +3 -0
  30. package/docs/project-management/delivery/documents/requirements.md +3 -0
  31. package/docs/project-management/delivery/documents/tracking.md +3 -0
  32. package/docs/project-management/delivery/handoffs/README.md +3 -0
  33. package/docs/project-management/delivery/handoffs/evidence/README.md +3 -0
  34. package/docs/project-management/delivery/handoffs/records/README.md +3 -0
  35. package/docs/project-management/delivery/overview.md +10 -0
  36. package/docs/project-management/delivery/releases/README.md +3 -0
  37. package/docs/project-management/delivery/releases/baselines/README.md +3 -0
  38. package/docs/project-management/delivery/releases/evidence/README.md +3 -0
  39. package/docs/project-management/delivery/tables/changes.md +3 -0
  40. package/docs/project-management/delivery/tables/issues.md +3 -0
  41. package/docs/project-management/delivery/tables/planning.md +3 -0
  42. package/docs/project-management/delivery/tables/requirements.md +3 -0
  43. package/docs/project-management/delivery/tables/tracking.md +3 -0
  44. package/docs/project-management/environment/agent-discovery.md +3 -0
  45. package/docs/project-management/environment/development.md +3 -0
  46. package/docs/project-management/environment/overview.md +10 -0
  47. package/docs/project-management/environment/testing.md +3 -0
  48. package/docs/project-management/environment/version-alignment.md +3 -0
  49. package/docs/quick-start-with-ai-tools.md +68 -308
  50. package/docs/releases/README.md +3 -0
  51. package/docs/releases/v3.6.65.md +25 -0
  52. package/docs/releases/v3.6.66.md +23 -0
  53. package/docs/releases/v3.6.67.md +23 -0
  54. package/docs/steering-governance.md +64 -2
  55. package/docs/zh/README.md +2 -2
  56. package/docs/zh/releases/README.md +3 -0
  57. package/docs/zh/releases/v3.6.65.md +25 -0
  58. package/docs/zh/releases/v3.6.66.md +23 -0
  59. package/docs/zh/releases/v3.6.67.md +23 -0
  60. package/lib/commands/adopt.js +24 -0
  61. package/lib/commands/native.js +158 -0
  62. package/lib/commands/project.js +96 -0
  63. package/lib/commands/semantic.js +1459 -0
  64. package/lib/commands/session.js +74 -3
  65. package/lib/commands/spec-bootstrap.js +10 -1
  66. package/lib/commands/spec-gate.js +10 -1
  67. package/lib/commands/spec-pipeline.js +10 -1
  68. package/lib/commands/studio.js +405 -30
  69. package/lib/commands/task.js +141 -7
  70. package/lib/governance/supreme-principles.js +530 -0
  71. package/lib/problem/problem-evaluator.js +4 -0
  72. package/lib/project/candidate-inspection-service.js +24 -1
  73. package/lib/project/portfolio-projection-service.js +315 -5
  74. package/lib/project/project-channel-output.js +94 -0
  75. package/lib/project/project-channel-projection.js +181 -0
  76. package/lib/project/root-onboarding-service.js +107 -7
  77. package/lib/project/semantic-shared-source-projection.js +150 -0
  78. package/lib/project/supervision-action-model.js +277 -0
  79. package/lib/project/supervision-projection-service.js +305 -5
  80. package/lib/project/target-resolution-service.js +70 -5
  81. package/lib/project/visibility-policy.js +93 -0
  82. package/lib/runtime/multi-spec-scene-session.js +8 -1
  83. package/lib/runtime/project-channel-context-store.js +387 -0
  84. package/lib/runtime/project-channel-context.js +406 -0
  85. package/lib/runtime/scene-session-binding.js +46 -0
  86. package/lib/runtime/session-store.js +186 -0
  87. package/lib/runtime/steering-contract.js +7 -1
  88. package/lib/semantic/archive-report.js +283 -0
  89. package/lib/semantic/archive-routing.js +67 -0
  90. package/lib/semantic/backflow-report.js +245 -0
  91. package/lib/semantic/capability-contract.js +30 -0
  92. package/lib/semantic/delta-export.js +145 -0
  93. package/lib/semantic/interaction-observer.js +254 -0
  94. package/lib/semantic/kernel-loader.js +881 -0
  95. package/lib/semantic/native-runtime.js +359 -0
  96. package/lib/semantic/progress-ledger.js +433 -0
  97. package/lib/semantic/replay-evaluator.js +382 -0
  98. package/lib/semantic/shared-publication.js +592 -0
  99. package/lib/semantic/shared-source-config.js +183 -0
  100. package/lib/semantic/shared-source-connect.js +139 -0
  101. package/lib/semantic/shared-source-discovery.js +98 -0
  102. package/lib/semantic/shared-sync-export.js +413 -0
  103. package/lib/semantic/shared-sync-intake.js +592 -0
  104. package/lib/semantic/shared-sync-merge.js +547 -0
  105. package/lib/semantic/shared-sync-release.js +463 -0
  106. package/lib/semantic/supreme-intent-report.js +300 -0
  107. package/lib/state/sce-state-store.js +1360 -0
  108. package/lib/steering/context-sync-manager.js +276 -25
  109. package/lib/studio/spec-intake-governor.js +39 -3
  110. package/lib/studio/task-envelope.js +35 -2
  111. package/lib/workspace/takeover-baseline.js +342 -83
  112. package/package.json +7 -2
  113. package/scripts/agent-governance-baseline-audit.js +395 -0
  114. package/scripts/clarification-first-audit.js +9 -9
  115. package/scripts/deprecated-entry-audit.js +240 -0
  116. package/scripts/release-doc-version-audit.js +24 -0
  117. package/scripts/release-posture-report.js +262 -0
  118. package/template/.sce/README.md +62 -228
  119. package/template/.sce/config/semantic-shared-sources.json +5 -0
  120. package/template/.sce/config/supreme-principles-policy.json +105 -0
  121. package/template/.sce/config/takeover-baseline.json +7 -0
  122. package/template/.sce/steering/CORE_PRINCIPLES.md +23 -63
  123. package/template/.sce/steering/CURRENT_CONTEXT.md +4 -0
  124. package/template/.sce/steering/RULES_GUIDE.md +17 -9
  125. package/template/README.md +32 -96
@@ -0,0 +1,530 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs-extra');
5
+ const { getSceStateStore } = require('../state/sce-state-store');
6
+
7
+ const DEFAULT_SUPREME_PRINCIPLES_POLICY_PATH = '.sce/config/supreme-principles-policy.json';
8
+ const DEFAULT_SUPREME_INTENT_EVIDENCE_PATH = path.join('custom', 'supreme-intent-assessment.json');
9
+ const SUPREME_INTENT_EVIDENCE_API_VERSION = 'sce.supreme-intent-assessment/v0.1';
10
+
11
+ const DEFAULT_SUPREME_PRINCIPLES_POLICY = Object.freeze({
12
+ schema_version: '1.0',
13
+ enabled: true,
14
+ allow_planning_actions: ['allow', 'clarify', 'rewrite', 'narrow'],
15
+ allow_execution_actions: ['allow', 'rewrite', 'narrow'],
16
+ clarify_question: '请先明确你真正要达成的业务目标、作用对象和约束边界。',
17
+ refuse_message: '该请求不符合 SCE 的最高道德规范,不能直接执行。',
18
+ rewrite_message: '原始请求存在失范或越界风险,已收敛为可正当执行的目标。',
19
+ narrow_message: '原始请求风险过高,已收缩为审查、备份、验证优先的安全目标。',
20
+ refuse_rules: [
21
+ {
22
+ id: 'credential-theft',
23
+ keywords: ['steal password', 'dump token', 'exfiltrate', 'keylogger', 'phish', '窃取密码', '盗取令牌', '导出凭证'],
24
+ reason: '请求明显指向凭证盗取、数据外流或钓鱼等恶意行为。'
25
+ },
26
+ {
27
+ id: 'malware-abuse',
28
+ keywords: ['malware', 'ransomware', 'backdoor', 'payload', '木马', '勒索软件', '后门'],
29
+ reason: '请求明显指向恶意控制、破坏或持久化投毒。'
30
+ },
31
+ {
32
+ id: 'audit-evasion',
33
+ keywords: ['delete logs to hide', 'evade audit', 'disable audit trail', '清除日志掩盖', '绕过审计', '删除审计日志'],
34
+ reason: '请求明显指向规避责任、破坏审计或掩盖痕迹。'
35
+ }
36
+ ],
37
+ rewrite_rules: [
38
+ {
39
+ id: 'auth-bypass-to-safe-test-fixture',
40
+ keywords: ['disable auth', 'bypass auth', 'skip login', 'skip approval', '关闭认证', '绕过认证', '跳过登录', '跳过审批'],
41
+ replacement: 'Design a dev/test-only mechanism with explicit scope guard, audit trail, rollback plan, and no production bypass of authentication or approval controls.',
42
+ reason: '将越界的“绕过保护”目标改写为受边界约束的测试/诊断机制。'
43
+ },
44
+ {
45
+ id: 'remove-audit-to-safe-observability',
46
+ keywords: ['remove audit', 'turn off audit', 'delete logs', '关闭审计', '删除日志', '去掉审计'],
47
+ replacement: 'Design a safe observability adjustment that preserves required auditability, keeps retention boundaries, and reduces noise without deleting accountability evidence.',
48
+ reason: '将“去掉审计/日志”改写为保留责任边界的可观测性优化目标。'
49
+ }
50
+ ],
51
+ narrow_rules: [
52
+ {
53
+ id: 'destructive-production-change',
54
+ keywords: ['drop database', 'delete production data', 'truncate table', '删除生产数据', '清空数据表', '删库'],
55
+ replacement: 'Review the destructive change request, produce backup and rollback steps, verify scope, and require explicit confirmation before any irreversible data operation.',
56
+ reason: '高风险破坏性操作必须先收缩为审查、备份和回滚准备。'
57
+ }
58
+ ]
59
+ });
60
+
61
+ function normalizeString(value) {
62
+ if (typeof value !== 'string') {
63
+ return '';
64
+ }
65
+ return value.trim();
66
+ }
67
+
68
+ function normalizeTextForMatch(value) {
69
+ return normalizeString(value).toLowerCase();
70
+ }
71
+
72
+ function normalizeStringList(value = []) {
73
+ if (!Array.isArray(value)) {
74
+ return [];
75
+ }
76
+ return value
77
+ .map((item) => normalizeString(`${item}`))
78
+ .filter(Boolean);
79
+ }
80
+
81
+ function normalizeRule(item = {}) {
82
+ return {
83
+ id: normalizeString(item.id) || 'rule',
84
+ keywords: normalizeStringList(item.keywords).map((entry) => entry.toLowerCase()),
85
+ replacement: normalizeString(item.replacement),
86
+ reason: normalizeString(item.reason)
87
+ };
88
+ }
89
+
90
+ function normalizePolicy(raw = {}) {
91
+ const input = raw && typeof raw === 'object' ? raw : {};
92
+ return {
93
+ schema_version: normalizeString(input.schema_version) || DEFAULT_SUPREME_PRINCIPLES_POLICY.schema_version,
94
+ enabled: input.enabled !== false,
95
+ allow_planning_actions: (() => {
96
+ const values = normalizeStringList(input.allow_planning_actions);
97
+ return values.length > 0 ? values : [...DEFAULT_SUPREME_PRINCIPLES_POLICY.allow_planning_actions];
98
+ })(),
99
+ allow_execution_actions: (() => {
100
+ const values = normalizeStringList(input.allow_execution_actions);
101
+ return values.length > 0 ? values : [...DEFAULT_SUPREME_PRINCIPLES_POLICY.allow_execution_actions];
102
+ })(),
103
+ clarify_question: normalizeString(input.clarify_question) || DEFAULT_SUPREME_PRINCIPLES_POLICY.clarify_question,
104
+ refuse_message: normalizeString(input.refuse_message) || DEFAULT_SUPREME_PRINCIPLES_POLICY.refuse_message,
105
+ rewrite_message: normalizeString(input.rewrite_message) || DEFAULT_SUPREME_PRINCIPLES_POLICY.rewrite_message,
106
+ narrow_message: normalizeString(input.narrow_message) || DEFAULT_SUPREME_PRINCIPLES_POLICY.narrow_message,
107
+ refuse_rules: (() => {
108
+ const values = Array.isArray(input.refuse_rules) ? input.refuse_rules.map(normalizeRule).filter((item) => item.keywords.length > 0) : [];
109
+ return values.length > 0 ? values : DEFAULT_SUPREME_PRINCIPLES_POLICY.refuse_rules.map(normalizeRule);
110
+ })(),
111
+ rewrite_rules: (() => {
112
+ const values = Array.isArray(input.rewrite_rules) ? input.rewrite_rules.map(normalizeRule).filter((item) => item.keywords.length > 0) : [];
113
+ return values.length > 0 ? values : DEFAULT_SUPREME_PRINCIPLES_POLICY.rewrite_rules.map(normalizeRule);
114
+ })(),
115
+ narrow_rules: (() => {
116
+ const values = Array.isArray(input.narrow_rules) ? input.narrow_rules.map(normalizeRule).filter((item) => item.keywords.length > 0) : [];
117
+ return values.length > 0 ? values : DEFAULT_SUPREME_PRINCIPLES_POLICY.narrow_rules.map(normalizeRule);
118
+ })()
119
+ };
120
+ }
121
+
122
+ async function loadSupremePrinciplesPolicy(projectPath = process.cwd(), fileSystem = fs) {
123
+ const policyPath = path.join(projectPath, DEFAULT_SUPREME_PRINCIPLES_POLICY_PATH);
124
+ let payload = {};
125
+ let loadedFrom = 'default';
126
+ if (await fileSystem.pathExists(policyPath)) {
127
+ try {
128
+ payload = await fileSystem.readJson(policyPath);
129
+ loadedFrom = 'file';
130
+ } catch (_error) {
131
+ payload = {};
132
+ loadedFrom = 'default';
133
+ }
134
+ }
135
+ return {
136
+ policy_path: DEFAULT_SUPREME_PRINCIPLES_POLICY_PATH,
137
+ policy_loaded_from: loadedFrom,
138
+ policy: normalizePolicy(payload)
139
+ };
140
+ }
141
+
142
+ function findRuleMatches(text, rules = []) {
143
+ const normalized = normalizeTextForMatch(text);
144
+ if (!normalized) {
145
+ return [];
146
+ }
147
+ const matches = [];
148
+ for (const rule of rules) {
149
+ const matchedKeywords = rule.keywords.filter((keyword) => normalized.includes(keyword));
150
+ if (matchedKeywords.length === 0) {
151
+ continue;
152
+ }
153
+ matches.push({
154
+ id: rule.id,
155
+ matched_keywords: matchedKeywords,
156
+ replacement: rule.replacement,
157
+ reason: rule.reason
158
+ });
159
+ }
160
+ return matches;
161
+ }
162
+
163
+ function buildClarificationQuestions(text = '', policy = DEFAULT_SUPREME_PRINCIPLES_POLICY) {
164
+ const normalized = normalizeString(text);
165
+ if (!normalized) {
166
+ return [
167
+ policy.clarify_question,
168
+ '这件事最终希望影响哪个业务对象、模块或数据范围?',
169
+ '有哪些不能破坏的约束、权限边界或审计要求?'
170
+ ];
171
+ }
172
+ return [
173
+ '你真正要达成的业务结果是什么?',
174
+ '这次动作影响哪个对象、模块、页面、接口或数据范围?',
175
+ '有哪些明确不能被破坏的边界、权限、审计或发布约束?'
176
+ ];
177
+ }
178
+
179
+ function evaluateSupremeIntent(input = {}, policy = DEFAULT_SUPREME_PRINCIPLES_POLICY) {
180
+ const originalText = normalizeString(input.text || input.goal || input.prompt);
181
+ const normalized = normalizeTextForMatch(originalText);
182
+ const clarifyQuestions = buildClarificationQuestions(originalText, policy);
183
+ const worldView = {
184
+ principle: '无善无恶心之始',
185
+ assessment: originalText
186
+ ? '已识别到可分析的目标文本,但仍需基于事实和边界理解其真实意图。'
187
+ : '目标文本为空,尚未形成可判断的真实意图。'
188
+ };
189
+
190
+ if (!policy.enabled) {
191
+ return {
192
+ policy_enabled: false,
193
+ action: 'allow',
194
+ planning_allowed: true,
195
+ execution_allowed: true,
196
+ original_text: originalText,
197
+ effective_text: originalText,
198
+ message: 'Supreme principles policy is disabled.',
199
+ worldview: worldView,
200
+ lifeview: { principle: '有善有恶意之动', assessment: '策略关闭,未执行意图善恶辨析。' },
201
+ values: { principle: '知善知恶是良知', assessment: '策略关闭,未执行价值判断。' },
202
+ methodology: { principle: '为善去恶是格物', assessment: '策略关闭,未执行目标收敛或拒绝。' },
203
+ matched_rules: {
204
+ refuse: [],
205
+ rewrite: [],
206
+ narrow: []
207
+ },
208
+ clarification_questions: clarifyQuestions
209
+ };
210
+ }
211
+
212
+ const refuseMatches = findRuleMatches(normalized, policy.refuse_rules);
213
+ if (refuseMatches.length > 0) {
214
+ return {
215
+ policy_enabled: true,
216
+ action: 'refuse',
217
+ planning_allowed: false,
218
+ execution_allowed: false,
219
+ original_text: originalText,
220
+ effective_text: null,
221
+ message: policy.refuse_message,
222
+ worldview: worldView,
223
+ lifeview: {
224
+ principle: '有善有恶意之动',
225
+ assessment: '该意图已经明确指向伤害、规避责任或越界获利。'
226
+ },
227
+ values: {
228
+ principle: '知善知恶是良知',
229
+ assessment: refuseMatches.map((item) => item.reason).filter(Boolean).join(';') || '该请求不符合正当目标。'
230
+ },
231
+ methodology: {
232
+ principle: '为善去恶是格物',
233
+ assessment: '直接拒绝执行,不调用小九条推进。'
234
+ },
235
+ matched_rules: {
236
+ refuse: refuseMatches,
237
+ rewrite: [],
238
+ narrow: []
239
+ },
240
+ clarification_questions: clarifyQuestions
241
+ };
242
+ }
243
+
244
+ const rewriteMatches = findRuleMatches(normalized, policy.rewrite_rules);
245
+ if (rewriteMatches.length > 0) {
246
+ const replacement = rewriteMatches[0].replacement || originalText;
247
+ return {
248
+ policy_enabled: true,
249
+ action: 'rewrite',
250
+ planning_allowed: true,
251
+ execution_allowed: true,
252
+ original_text: originalText,
253
+ effective_text: replacement,
254
+ message: policy.rewrite_message,
255
+ worldview: worldView,
256
+ lifeview: {
257
+ principle: '有善有恶意之动',
258
+ assessment: '原始意图存在越界倾向,但可改写为守边界、可审计的正当目标。'
259
+ },
260
+ values: {
261
+ principle: '知善知恶是良知',
262
+ assessment: rewriteMatches.map((item) => item.reason).filter(Boolean).join(';') || '已将偏斜目标改写为正当目标。'
263
+ },
264
+ methodology: {
265
+ principle: '为善去恶是格物',
266
+ assessment: '先改写目标,再允许进入小九条执行。'
267
+ },
268
+ matched_rules: {
269
+ refuse: [],
270
+ rewrite: rewriteMatches,
271
+ narrow: []
272
+ },
273
+ clarification_questions: clarifyQuestions
274
+ };
275
+ }
276
+
277
+ const narrowMatches = findRuleMatches(normalized, policy.narrow_rules);
278
+ if (narrowMatches.length > 0) {
279
+ const replacement = narrowMatches[0].replacement || originalText;
280
+ return {
281
+ policy_enabled: true,
282
+ action: 'narrow',
283
+ planning_allowed: true,
284
+ execution_allowed: true,
285
+ original_text: originalText,
286
+ effective_text: replacement,
287
+ message: policy.narrow_message,
288
+ worldview: worldView,
289
+ lifeview: {
290
+ principle: '有善有恶意之动',
291
+ assessment: '原始意图风险过高,必须先压缩为审查、验证、备份和回滚优先的动作。'
292
+ },
293
+ values: {
294
+ principle: '知善知恶是良知',
295
+ assessment: narrowMatches.map((item) => item.reason).filter(Boolean).join(';') || '已将高风险动作收缩为安全目标。'
296
+ },
297
+ methodology: {
298
+ principle: '为善去恶是格物',
299
+ assessment: '先收缩目标,再允许进入小九条执行。'
300
+ },
301
+ matched_rules: {
302
+ refuse: [],
303
+ rewrite: [],
304
+ narrow: narrowMatches
305
+ },
306
+ clarification_questions: clarifyQuestions
307
+ };
308
+ }
309
+
310
+ if (!originalText || originalText.length < 8) {
311
+ return {
312
+ policy_enabled: true,
313
+ action: 'clarify',
314
+ planning_allowed: true,
315
+ execution_allowed: false,
316
+ original_text: originalText,
317
+ effective_text: originalText,
318
+ message: policy.clarify_question,
319
+ worldview: worldView,
320
+ lifeview: {
321
+ principle: '有善有恶意之动',
322
+ assessment: '当前只看到模糊意图,尚不足以判定其导向。'
323
+ },
324
+ values: {
325
+ principle: '知善知恶是良知',
326
+ assessment: '在善恶未明、边界未清前,不应直接进入执行。'
327
+ },
328
+ methodology: {
329
+ principle: '为善去恶是格物',
330
+ assessment: '先澄清目标、对象和约束,再决定是否调用小九条。'
331
+ },
332
+ matched_rules: {
333
+ refuse: [],
334
+ rewrite: [],
335
+ narrow: []
336
+ },
337
+ clarification_questions: clarifyQuestions
338
+ };
339
+ }
340
+
341
+ return {
342
+ policy_enabled: true,
343
+ action: 'allow',
344
+ planning_allowed: true,
345
+ execution_allowed: true,
346
+ original_text: originalText,
347
+ effective_text: originalText,
348
+ message: '该目标当前可按小九条推进。',
349
+ worldview: worldView,
350
+ lifeview: {
351
+ principle: '有善有恶意之动',
352
+ assessment: '当前意图未发现明显伤害、逃责或失范导向。'
353
+ },
354
+ values: {
355
+ principle: '知善知恶是良知',
356
+ assessment: '当前目标可被视为正当的交付、诊断、治理或改进事项。'
357
+ },
358
+ methodology: {
359
+ principle: '为善去恶是格物',
360
+ assessment: '允许进入小九条执行。'
361
+ },
362
+ matched_rules: {
363
+ refuse: [],
364
+ rewrite: [],
365
+ narrow: []
366
+ },
367
+ clarification_questions: clarifyQuestions
368
+ };
369
+ }
370
+
371
+ async function assessSupremeIntent(input = {}, dependencies = {}) {
372
+ const projectPath = dependencies.projectPath || process.cwd();
373
+ const fileSystem = dependencies.fileSystem || fs;
374
+ const loaded = dependencies.policy && typeof dependencies.policy === 'object'
375
+ ? { policy_path: '(inline)', policy_loaded_from: 'inline', policy: normalizePolicy(dependencies.policy) }
376
+ : await loadSupremePrinciplesPolicy(projectPath, fileSystem);
377
+ const assessment = evaluateSupremeIntent(input, loaded.policy);
378
+ return {
379
+ ...assessment,
380
+ policy_path: loaded.policy_path,
381
+ policy_loaded_from: loaded.policy_loaded_from,
382
+ source_kind: normalizeString(input.source_kind || input.sourceKind) || 'unknown',
383
+ scene_id: normalizeString(input.scene_id || input.sceneId) || null,
384
+ spec_id: normalizeString(input.spec_id || input.specId) || null
385
+ };
386
+ }
387
+
388
+ function buildSupremeRefusalError(assessment = {}) {
389
+ const values = assessment && assessment.values ? normalizeString(assessment.values.assessment) : '';
390
+ const methodology = assessment && assessment.methodology ? normalizeString(assessment.methodology.assessment) : '';
391
+ const details = [normalizeString(assessment.message), values, methodology].filter(Boolean).join(' ');
392
+ return new Error(details || 'request blocked by supreme principles');
393
+ }
394
+
395
+ function buildNativeGovernedReply(assessment = {}) {
396
+ const action = normalizeString(assessment.action);
397
+ if (action === 'refuse') {
398
+ return {
399
+ text: [
400
+ normalizeString(assessment.message) || '该请求不符合 SCE 的最高道德规范。',
401
+ normalizeString(assessment.values && assessment.values.assessment),
402
+ '请改为正当、守边界、可审计的目标后再继续。'
403
+ ].filter(Boolean).join('\n')
404
+ };
405
+ }
406
+ if (action === 'clarify') {
407
+ return {
408
+ text: [
409
+ normalizeString(assessment.message),
410
+ ...(Array.isArray(assessment.clarification_questions) ? assessment.clarification_questions.slice(0, 3) : [])
411
+ ].filter(Boolean).join('\n')
412
+ };
413
+ }
414
+ if (action === 'rewrite' || action === 'narrow') {
415
+ return {
416
+ text: [
417
+ normalizeString(assessment.message),
418
+ `已收敛目标:${normalizeString(assessment.effective_text)}`,
419
+ normalizeString(assessment.methodology && assessment.methodology.assessment)
420
+ ].filter(Boolean).join('\n')
421
+ };
422
+ }
423
+ return null;
424
+ }
425
+
426
+ async function writeSupremeIntentEvidence(projectPath = process.cwd(), specId, payload = {}, dependencies = {}) {
427
+ const normalizedSpecId = normalizeString(specId);
428
+ if (!normalizedSpecId) {
429
+ return null;
430
+ }
431
+ const fileSystem = dependencies.fileSystem || fs;
432
+ const specRoot = path.join(projectPath, '.sce', 'specs', normalizedSpecId);
433
+ if (!await fileSystem.pathExists(specRoot)) {
434
+ return null;
435
+ }
436
+ const targetPath = path.join(projectPath, '.sce', 'specs', normalizedSpecId, DEFAULT_SUPREME_INTENT_EVIDENCE_PATH);
437
+ const existing = await (async () => {
438
+ if (!await fileSystem.pathExists(targetPath)) {
439
+ return null;
440
+ }
441
+ try {
442
+ return await fileSystem.readJson(targetPath);
443
+ } catch (_error) {
444
+ return null;
445
+ }
446
+ })();
447
+
448
+ const entry = {
449
+ assessed_at: new Date().toISOString(),
450
+ action: normalizeString(payload.action),
451
+ planning_allowed: payload.planning_allowed === true,
452
+ execution_allowed: payload.execution_allowed === true,
453
+ source_kind: normalizeString(payload.source_kind),
454
+ original_text: normalizeString(payload.original_text),
455
+ effective_text: normalizeString(payload.effective_text),
456
+ message: normalizeString(payload.message),
457
+ worldview: payload.worldview || null,
458
+ lifeview: payload.lifeview || null,
459
+ values: payload.values || null,
460
+ methodology: payload.methodology || null,
461
+ matched_rules: payload.matched_rules || {},
462
+ policy_path: normalizeString(payload.policy_path) || DEFAULT_SUPREME_PRINCIPLES_POLICY_PATH,
463
+ policy_loaded_from: normalizeString(payload.policy_loaded_from) || 'default'
464
+ };
465
+
466
+ const history = Array.isArray(existing && existing.history) ? existing.history.slice(0, 19) : [];
467
+ const next = {
468
+ api_version: SUPREME_INTENT_EVIDENCE_API_VERSION,
469
+ spec_id: normalizedSpecId,
470
+ updated_at: entry.assessed_at,
471
+ latest: entry,
472
+ history: [entry, ...history]
473
+ };
474
+
475
+ await fileSystem.ensureDir(path.dirname(targetPath));
476
+ await fileSystem.writeJson(targetPath, next, { spaces: 2 });
477
+ return {
478
+ relative_path: path.relative(projectPath, targetPath).replace(/\\/g, '/'),
479
+ entry
480
+ };
481
+ }
482
+
483
+ async function recordSupremeIntentAssessment(record = {}, dependencies = {}) {
484
+ const projectPath = dependencies.projectPath || process.cwd();
485
+ const store = dependencies.stateStore || getSceStateStore(projectPath, {
486
+ fileSystem: dependencies.fileSystem,
487
+ env: dependencies.env,
488
+ sqliteModule: dependencies.sqliteModule,
489
+ noCache: dependencies.noCache === true
490
+ });
491
+
492
+ return store.appendSupremeIntentAssessment({
493
+ project_id: record.project_id || record.projectId || null,
494
+ channel_id: record.channel_id || record.channelId || null,
495
+ session_id: record.session_id || record.sessionId || null,
496
+ scene_id: record.scene_id || record.sceneId || null,
497
+ spec_id: record.spec_id || record.specId || null,
498
+ job_id: record.job_id || record.jobId || null,
499
+ source_kind: record.source_kind || record.sourceKind,
500
+ action: record.action,
501
+ planning_allowed: record.planning_allowed,
502
+ execution_allowed: record.execution_allowed,
503
+ policy_path: record.policy_path,
504
+ policy_loaded_from: record.policy_loaded_from,
505
+ original_text: record.original_text,
506
+ effective_text: record.effective_text,
507
+ message: record.message,
508
+ evidence_path: record.evidence_path || record.evidencePath || null,
509
+ worldview: record.worldview,
510
+ lifeview: record.lifeview,
511
+ values: record.values,
512
+ methodology: record.methodology,
513
+ matched_rules: record.matched_rules,
514
+ clarification_questions: record.clarification_questions,
515
+ metadata: record.metadata
516
+ });
517
+ }
518
+
519
+ module.exports = {
520
+ DEFAULT_SUPREME_PRINCIPLES_POLICY_PATH,
521
+ DEFAULT_SUPREME_INTENT_EVIDENCE_PATH,
522
+ DEFAULT_SUPREME_PRINCIPLES_POLICY,
523
+ loadSupremePrinciplesPolicy,
524
+ evaluateSupremeIntent,
525
+ assessSupremeIntent,
526
+ buildSupremeRefusalError,
527
+ buildNativeGovernedReply,
528
+ writeSupremeIntentEvidence,
529
+ recordSupremeIntentAssessment
530
+ };
@@ -833,7 +833,11 @@ function evaluateProblemContext(context = {}, policy = DEFAULT_PROBLEM_EVAL_POLI
833
833
 
834
834
  const recommendations = [];
835
835
  if (strategy.strategy === 'debug-first') {
836
+ recommendations.push('Record or update an errorbook staging incident before the next patch attempt.');
836
837
  recommendations.push('Capture debug trace/log evidence before the next patch attempt.');
838
+ recommendations.push(
839
+ 'Use bisection-style debug logs to halve the failing scope by module, call path, data slice, or change set on each iteration.'
840
+ );
837
841
  }
838
842
  if (strategy.strategy === 'evidence-first' || evidence.score < 45) {
839
843
  recommendations.push('Refresh domain artifacts and verify ontology coverage before execution.');
@@ -5,6 +5,9 @@ const {
5
5
  buildLocalProjectId,
6
6
  buildWorkspaceProjectId
7
7
  } = require('./portfolio-projection-service');
8
+ const {
9
+ isEphemeralProjectRoot
10
+ } = require('./visibility-policy');
8
11
 
9
12
  const PROJECT_CANDIDATE_REASON_CODES = {
10
13
  ROOT_ACCESSIBLE: 'project.root.accessible',
@@ -14,7 +17,8 @@ const PROJECT_CANDIDATE_REASON_CODES = {
14
17
  SCE_PRESENT: 'project.sce.present',
15
18
  ROOT_NOT_INITIALIZED: 'project.root.not_initialized',
16
19
  INVALID_PROJECT_METADATA: 'project.metadata.invalid',
17
- UNREGISTERED_PROJECT: 'project.sce.unregistered'
20
+ UNREGISTERED_PROJECT: 'project.sce.unregistered',
21
+ EPHEMERAL_ROOT: 'project.root.ephemeral'
18
22
  };
19
23
 
20
24
  function normalizeString(value) {
@@ -152,6 +156,25 @@ async function inspectProjectCandidate(options = {}, dependencies = {}) {
152
156
  };
153
157
  }
154
158
 
159
+ if (isEphemeralProjectRoot({
160
+ projectRoot: rootDir,
161
+ projectName
162
+ })) {
163
+ return {
164
+ inspectedAt,
165
+ rootDir,
166
+ kind: 'invalid',
167
+ projectName,
168
+ readiness: 'blocked',
169
+ availability: 'accessible',
170
+ localCandidate: false,
171
+ reasonCodes: [
172
+ PROJECT_CANDIDATE_REASON_CODES.ROOT_ACCESSIBLE,
173
+ PROJECT_CANDIDATE_REASON_CODES.EPHEMERAL_ROOT
174
+ ]
175
+ };
176
+ }
177
+
155
178
  const workspace = await resolveExactWorkspaceByRoot(absoluteRoot, stateManager);
156
179
  const sceInspection = await inspectSceMetadata(absoluteRoot, fileSystem);
157
180
  const metadataBlocked = sceInspection.scePresent && !sceInspection.metadataValid;