@hongmaple0820/scale-engine 0.28.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -0
- package/README.md +2 -0
- package/dist/api/cli.js +12 -0
- package/dist/api/cli.js.map +1 -1
- package/dist/evolution/SessionLearnings.d.ts +70 -0
- package/dist/evolution/SessionLearnings.js +217 -0
- package/dist/evolution/SessionLearnings.js.map +1 -0
- package/dist/runtime/AiOsRuntime.d.ts +138 -0
- package/dist/runtime/AiOsRuntime.js +671 -14
- package/dist/runtime/AiOsRuntime.js.map +1 -1
- package/dist/skills/RoleSkills.d.ts +20 -0
- package/dist/skills/RoleSkills.js +154 -0
- package/dist/skills/RoleSkills.js.map +1 -0
- package/dist/skills/SkillDiscovery.d.ts +5 -0
- package/dist/skills/SkillDiscovery.js +15 -0
- package/dist/skills/SkillDiscovery.js.map +1 -1
- package/dist/skills/SkillFrontmatter.d.ts +28 -0
- package/dist/skills/SkillFrontmatter.js +152 -0
- package/dist/skills/SkillFrontmatter.js.map +1 -0
- package/dist/skills/SkillRegistry.d.ts +11 -0
- package/dist/skills/SkillRegistry.js +12 -0
- package/dist/skills/SkillRegistry.js.map +1 -1
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/testing/DiffTestSelector.d.ts +22 -0
- package/dist/testing/DiffTestSelector.js +114 -0
- package/dist/testing/DiffTestSelector.js.map +1 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +3 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/workflow/AdaptiveWorkflowRouter.d.ts +37 -0
- package/dist/workflow/AdaptiveWorkflowRouter.js +211 -0
- package/dist/workflow/AdaptiveWorkflowRouter.js.map +1 -0
- package/dist/workflow/EvolutionShadowPromoter.d.ts +46 -0
- package/dist/workflow/EvolutionShadowPromoter.js +73 -0
- package/dist/workflow/EvolutionShadowPromoter.js.map +1 -0
- package/dist/workflow/ReviewAnalyzer.d.ts +15 -0
- package/dist/workflow/ReviewAnalyzer.js +82 -0
- package/dist/workflow/ReviewAnalyzer.js.map +1 -1
- package/dist/workflow/SecurityAudit.d.ts +27 -0
- package/dist/workflow/SecurityAudit.js +294 -0
- package/dist/workflow/SecurityAudit.js.map +1 -0
- package/dist/workflow/SessionPreamble.d.ts +19 -0
- package/dist/workflow/SessionPreamble.js +125 -0
- package/dist/workflow/SessionPreamble.js.map +1 -0
- package/dist/workflow/ShipPipeline.d.ts +30 -0
- package/dist/workflow/ShipPipeline.js +366 -0
- package/dist/workflow/ShipPipeline.js.map +1 -0
- package/dist/workflow/WorkflowGuidance.d.ts +5 -1
- package/dist/workflow/WorkflowGuidance.js +31 -0
- package/dist/workflow/WorkflowGuidance.js.map +1 -1
- package/dist/workflow/index.d.ts +5 -0
- package/dist/workflow/index.js +5 -0
- package/dist/workflow/index.js.map +1 -1
- package/docs/AI_ENGINEERING_OS_POSITIONING.md +15 -0
- package/docs/CONTEXT_BUDGET.md +1 -1
- package/package.json +2 -1
|
@@ -5,10 +5,14 @@ import { createGovernanceRoiReport, } from '../governance/GovernanceRoi.js';
|
|
|
5
5
|
import { evaluateProgressiveGovernance, } from '../governance/ProgressiveGovernance.js';
|
|
6
6
|
import { MemoryFabric, recallMemoryProviders, } from '../memory/index.js';
|
|
7
7
|
import { createSkillPlan, loadSkillRoutingPolicy, } from '../skills/routing/index.js';
|
|
8
|
+
import { routeAdaptiveWorkflow } from '../workflow/AdaptiveWorkflowRouter.js';
|
|
9
|
+
import { proposeShadowRule, buildEvolutionShadowReport, } from '../workflow/EvolutionShadowPromoter.js';
|
|
8
10
|
import { runSafeCommand } from '../tools/SafeCommandRunner.js';
|
|
9
11
|
import { SCALE_ENGINE_VERSION } from '../version.js';
|
|
10
12
|
import { resolveVerificationTargets, } from '../workflow/VerificationProfile.js';
|
|
11
13
|
import { RuntimeEvidenceLedger } from './RuntimeEvidenceLedger.js';
|
|
14
|
+
import { loadRelevantLearnings } from '../evolution/SessionLearnings.js';
|
|
15
|
+
import { collectSessionPreamble } from '../workflow/SessionPreamble.js';
|
|
12
16
|
export async function createAiOsPlan(input) {
|
|
13
17
|
const projectDir = resolve(input.projectDir ?? process.cwd());
|
|
14
18
|
const scaleDir = input.scaleDir ?? '.scale';
|
|
@@ -17,6 +21,8 @@ export async function createAiOsPlan(input) {
|
|
|
17
21
|
const services = input.services ?? [];
|
|
18
22
|
const taskId = input.taskId;
|
|
19
23
|
const budget = input.budget ?? 8_000;
|
|
24
|
+
const preamble = collectSessionPreamble({ projectDir, scaleDir });
|
|
25
|
+
const sessionLearnings = loadRelevantLearnings({ projectDir, scaleDir, task: input.task, limit: 5 });
|
|
20
26
|
const governance = evaluateProgressiveGovernance({
|
|
21
27
|
task: input.task,
|
|
22
28
|
changedFiles: files,
|
|
@@ -62,7 +68,15 @@ export async function createAiOsPlan(input) {
|
|
|
62
68
|
services,
|
|
63
69
|
policy: skillPolicy,
|
|
64
70
|
});
|
|
65
|
-
const
|
|
71
|
+
const evaluator = createEvaluatorIntelligence({
|
|
72
|
+
task: input.task,
|
|
73
|
+
files,
|
|
74
|
+
governance,
|
|
75
|
+
skillPlan,
|
|
76
|
+
});
|
|
77
|
+
const toolStrategy = createToolStrategyPlan(skillPlan);
|
|
78
|
+
const adaptiveWorkflow = createAdaptiveWorkflow(governance, skillPlan, evaluator, toolStrategy);
|
|
79
|
+
const evolutionShadow = createEvolutionShadowProposals(governance, evaluator);
|
|
66
80
|
const roi = createGovernanceRoiReport({
|
|
67
81
|
taskId,
|
|
68
82
|
contextBudget,
|
|
@@ -81,8 +95,12 @@ export async function createAiOsPlan(input) {
|
|
|
81
95
|
files,
|
|
82
96
|
services,
|
|
83
97
|
},
|
|
98
|
+
preamble,
|
|
84
99
|
governance,
|
|
85
100
|
adaptiveWorkflow,
|
|
101
|
+
evaluator,
|
|
102
|
+
toolStrategy,
|
|
103
|
+
evolutionShadow,
|
|
86
104
|
context,
|
|
87
105
|
memory: {
|
|
88
106
|
providerOrder: memoryRecall.providerOrder,
|
|
@@ -93,8 +111,9 @@ export async function createAiOsPlan(input) {
|
|
|
93
111
|
contextPack: memoryPack,
|
|
94
112
|
},
|
|
95
113
|
skillPlan,
|
|
114
|
+
sessionLearnings,
|
|
96
115
|
roi,
|
|
97
|
-
recommendations: recommendations({ governance, context, memoryRecall, skillPlan }),
|
|
116
|
+
recommendations: recommendations({ governance, context, memoryRecall, skillPlan, evaluator, toolStrategy }),
|
|
98
117
|
};
|
|
99
118
|
}
|
|
100
119
|
export async function createAiOsRun(input) {
|
|
@@ -194,6 +213,7 @@ export async function createAiOsBenchmark(input = {}) {
|
|
|
194
213
|
task: scenario.task,
|
|
195
214
|
level: scenario.level,
|
|
196
215
|
governanceMode: plan.governance.effectiveMode,
|
|
216
|
+
workflowProfile: plan.adaptiveWorkflow.profile,
|
|
197
217
|
metrics: {
|
|
198
218
|
estimatedTokens: plan.context.totalEstimatedTokens,
|
|
199
219
|
budget: plan.context.task.budget,
|
|
@@ -202,6 +222,10 @@ export async function createAiOsBenchmark(input = {}) {
|
|
|
202
222
|
selectedProviders: plan.memory.selectedProviders,
|
|
203
223
|
skillSteps: plan.skillPlan.executionPlan.steps.length,
|
|
204
224
|
requiredSkillSteps: plan.skillPlan.executionPlan.steps.filter(step => step.required).length,
|
|
225
|
+
evaluatorGates: plan.evaluator.gates.length,
|
|
226
|
+
toolStrategySteps: plan.toolStrategy.summary.totalSteps,
|
|
227
|
+
toolStrategyCostUnits: plan.toolStrategy.summary.estimatedCostUnits,
|
|
228
|
+
evolutionProposals: plan.evolutionShadow.summary.totalProposals,
|
|
205
229
|
gates: plan.adaptiveWorkflow.gates.length,
|
|
206
230
|
roiModules: plan.roi.modules.length,
|
|
207
231
|
},
|
|
@@ -446,6 +470,15 @@ export function createAiOsStatus(input = {}) {
|
|
|
446
470
|
const verificationRecommendations = buildVerificationRecommendations(projectDir, scaleDir, lang);
|
|
447
471
|
const benchmarkReport = resolveBenchmarkReportPath(projectDir, scaleDir);
|
|
448
472
|
const adoptionReport = resolveAdoptionReportPath(projectDir, scaleDir);
|
|
473
|
+
const intelligence = buildAiOsIntelligenceReport({
|
|
474
|
+
projectDir,
|
|
475
|
+
scaleDir,
|
|
476
|
+
runReports,
|
|
477
|
+
benchmark: readAiOsBenchmarkReport(benchmarkReport, warnings),
|
|
478
|
+
benchmarkStatus: doctor.benchmark.status,
|
|
479
|
+
benchmarkReport,
|
|
480
|
+
lang,
|
|
481
|
+
});
|
|
449
482
|
const checks = [
|
|
450
483
|
{
|
|
451
484
|
id: 'runtime-dirs',
|
|
@@ -526,11 +559,351 @@ export function createAiOsStatus(input = {}) {
|
|
|
526
559
|
summary,
|
|
527
560
|
dashboard,
|
|
528
561
|
doctor,
|
|
562
|
+
intelligence,
|
|
529
563
|
verificationRecommendations,
|
|
530
564
|
nextActions: aiOsStatusNextActions(status, checks, lang, verificationRecommendations),
|
|
531
565
|
warnings: [...warnings, ...doctor.warnings],
|
|
532
566
|
};
|
|
533
567
|
}
|
|
568
|
+
function buildAiOsIntelligenceReport(input) {
|
|
569
|
+
const runMemoryItems = input.runReports.flatMap(report => report.plan.memory.items);
|
|
570
|
+
const benchmarkMemoryItems = input.benchmark?.summary.totalMemoryItems ?? 0;
|
|
571
|
+
const runProviders = input.runReports.flatMap(report => report.plan.memory.selectedProviders);
|
|
572
|
+
const benchmarkProviders = input.benchmark?.scenarios.flatMap(scenario => scenario.metrics.selectedProviders) ?? [];
|
|
573
|
+
const selectedProviders = [...new Set([...runProviders, ...benchmarkProviders])].sort();
|
|
574
|
+
const runTokenSavings = input.runReports.reduce((sum, report) => sum + (report.plan.context.compiler?.estimatedTokenSavings ?? 0), 0);
|
|
575
|
+
const benchmarkTokenSavings = input.benchmark?.summary.totalEstimatedTokenSavings ?? 0;
|
|
576
|
+
const estimatedTokenSavings = runTokenSavings + benchmarkTokenSavings;
|
|
577
|
+
const runSkillSteps = input.runReports.reduce((sum, report) => sum + report.plan.skillPlan.executionPlan.steps.length, 0);
|
|
578
|
+
const benchmarkSkillSteps = input.benchmark?.summary.totalSkillSteps ?? 0;
|
|
579
|
+
const skillSteps = runSkillSteps + benchmarkSkillSteps;
|
|
580
|
+
const totalMemoryItems = runMemoryItems.length + benchmarkMemoryItems;
|
|
581
|
+
const memoryQuality = summarizeMemoryQuality(runMemoryItems);
|
|
582
|
+
const contextQuality = summarizeContextQuality(input.runReports);
|
|
583
|
+
const evaluatorQuality = summarizeEvaluatorQuality(input.runReports, input.benchmark);
|
|
584
|
+
const toolStrategyQuality = summarizeToolStrategyQuality(input.runReports, input.benchmark);
|
|
585
|
+
const evolutionQuality = summarizeEvolutionQuality(input.runReports, input.benchmark);
|
|
586
|
+
const contextSignalStatus = contextQuality.compressionRisk === 'high'
|
|
587
|
+
? 'warning'
|
|
588
|
+
: estimatedTokenSavings > 0 ? 'ready' : input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked';
|
|
589
|
+
const memoryEvidence = [
|
|
590
|
+
...runMemoryItems.map(item => `${item.provider}:${item.id}`),
|
|
591
|
+
...(benchmarkMemoryItems > 0 ? [`benchmark:${input.benchmarkReport}:${benchmarkMemoryItems}`] : []),
|
|
592
|
+
];
|
|
593
|
+
const contextEvidence = [
|
|
594
|
+
...input.runReports.map(report => `${report.artifacts.runReport}:saved=${report.plan.context.compiler?.estimatedTokenSavings ?? 0}`),
|
|
595
|
+
...(input.benchmark ? [`${input.benchmarkReport}:saved=${input.benchmark.summary.totalEstimatedTokenSavings}`] : []),
|
|
596
|
+
];
|
|
597
|
+
const skillEvidence = [
|
|
598
|
+
...input.runReports.flatMap(report => report.plan.skillPlan.executionPlan.steps.map(step => `${report.artifacts.runReport}:${step.id}`)),
|
|
599
|
+
...(input.benchmark ? [`${input.benchmarkReport}:steps=${input.benchmark.summary.totalSkillSteps}`] : []),
|
|
600
|
+
];
|
|
601
|
+
const evaluatorEvidence = [
|
|
602
|
+
...input.runReports.flatMap(report => resolveRunEvaluator(report).gates.map(gate => `${report.artifacts.runReport}:${gate.id}`)),
|
|
603
|
+
...(input.benchmark ? [`${input.benchmarkReport}:evaluator-gates=${input.benchmark.summary.totalEvaluatorGates}`] : []),
|
|
604
|
+
];
|
|
605
|
+
const toolStrategyEvidence = [
|
|
606
|
+
...input.runReports.flatMap(report => resolveRunToolStrategy(report).nodes.map(node => `${report.artifacts.runReport}:${node.id}`)),
|
|
607
|
+
...(input.benchmark ? [`${input.benchmarkReport}:tool-strategy=${input.benchmark.summary.totalToolStrategySteps}`] : []),
|
|
608
|
+
];
|
|
609
|
+
const evolutionEvidence = [
|
|
610
|
+
...input.runReports.flatMap(report => (report.plan.evolutionShadow?.proposals ?? []).map(p => `${report.artifacts.runReport}:${p.id}:${p.maturity.stage}`)),
|
|
611
|
+
...(input.benchmark ? [`${input.benchmarkReport}:evolution-proposals=${input.benchmark.summary.totalEvolutionProposals}`] : []),
|
|
612
|
+
];
|
|
613
|
+
const benchmarkEvidence = input.benchmark ? [
|
|
614
|
+
`${input.benchmarkReport}:scenarios=${input.benchmark.summary.scenarios}`,
|
|
615
|
+
`${input.benchmarkReport}:memory=${input.benchmark.summary.totalMemoryItems}`,
|
|
616
|
+
`${input.benchmarkReport}:skills=${input.benchmark.summary.totalSkillSteps}`,
|
|
617
|
+
`${input.benchmarkReport}:evaluator-gates=${input.benchmark.summary.totalEvaluatorGates}`,
|
|
618
|
+
`${input.benchmarkReport}:tool-strategy=${input.benchmark.summary.totalToolStrategySteps}`,
|
|
619
|
+
] : [input.benchmarkReport];
|
|
620
|
+
const signals = [
|
|
621
|
+
{
|
|
622
|
+
id: 'memory-recall',
|
|
623
|
+
status: totalMemoryItems > 0 ? 'ready' : selectedProviders.length > 0 ? 'warning' : 'blocked',
|
|
624
|
+
summary: totalMemoryItems > 0
|
|
625
|
+
? `${totalMemoryItems} memory item(s) recalled through ${selectedProviders.join(', ') || 'configured providers'}; quality ${memoryQuality.score}/100.`
|
|
626
|
+
: selectedProviders.length > 0
|
|
627
|
+
? `Memory providers were selected (${selectedProviders.join(', ')}) but no relevant item was recalled.`
|
|
628
|
+
: 'No memory recall evidence found in AI OS runs or benchmarks.',
|
|
629
|
+
evidence: memoryEvidence,
|
|
630
|
+
recommendations: totalMemoryItems > 0
|
|
631
|
+
? ['Keep recording memory item ids with every run so later context assembly can explain recall.']
|
|
632
|
+
: ['Run an AI OS task that should match durable project memory before claiming memory intelligence.'],
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: 'context-savings',
|
|
636
|
+
status: contextSignalStatus,
|
|
637
|
+
summary: estimatedTokenSavings > 0
|
|
638
|
+
? `${estimatedTokenSavings} estimated token(s) saved by context compilation evidence; compression risk ${contextQuality.compressionRisk}.`
|
|
639
|
+
: 'Context compiler evidence exists but has not shown measurable token savings yet.',
|
|
640
|
+
evidence: contextEvidence,
|
|
641
|
+
recommendations: contextQuality.evidenceLossWarnings.length > 0
|
|
642
|
+
? ['Review omitted evidence-bearing context before claiming the task has enough context.']
|
|
643
|
+
: estimatedTokenSavings > 0
|
|
644
|
+
? ['Track savings deltas across releases before publishing token reduction claims.']
|
|
645
|
+
: ['Add larger representative tasks to benchmark context slicing and token savings.'],
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
id: 'skill-routing',
|
|
649
|
+
status: skillSteps > 0 ? 'ready' : input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked',
|
|
650
|
+
summary: skillSteps > 0
|
|
651
|
+
? `${skillSteps} skill routing step(s) planned across runs and benchmark scenarios.`
|
|
652
|
+
: 'No skill routing step evidence found.',
|
|
653
|
+
evidence: skillEvidence,
|
|
654
|
+
recommendations: skillSteps > 0
|
|
655
|
+
? ['Use skill routing evidence in reviews to check why a skill, MCP, or CLI path was selected.']
|
|
656
|
+
: ['Create a task with files or services that should trigger required skill routing.'],
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
id: 'evaluator-intelligence',
|
|
660
|
+
status: evaluatorQuality.requiredGates > 0
|
|
661
|
+
? evaluatorQuality.averageUncertainty >= 0.7 ? 'warning' : 'ready'
|
|
662
|
+
: input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked',
|
|
663
|
+
summary: evaluatorQuality.requiredGates > 0
|
|
664
|
+
? `${evaluatorQuality.requiredGates} evaluator gate(s) required; average uncertainty ${evaluatorQuality.averageUncertainty}.`
|
|
665
|
+
: 'No evaluator gate evidence found for architecture, root-cause, security, or release reasoning.',
|
|
666
|
+
evidence: evaluatorEvidence,
|
|
667
|
+
recommendations: evaluatorQuality.requiredGates > 0
|
|
668
|
+
? ['Use evaluator gates to force critique, uncertainty logging, and review evidence before promoting reasoning-heavy work.']
|
|
669
|
+
: ['Run a reasoning-heavy AI OS task so evaluator intelligence can prove critique coverage.'],
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
id: 'tool-strategy',
|
|
673
|
+
status: toolStrategyQuality.totalSteps > 0
|
|
674
|
+
? toolStrategyQuality.fallbackCoverage < 1 ? 'warning' : 'ready'
|
|
675
|
+
: input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked',
|
|
676
|
+
summary: toolStrategyQuality.totalSteps > 0
|
|
677
|
+
? `${toolStrategyQuality.totalSteps} tool strategy step(s); ${toolStrategyQuality.highRiskSteps} high-risk; fallback coverage ${toolStrategyQuality.fallbackCoverage}.`
|
|
678
|
+
: 'No tool strategy graph found for skills, artifacts, CLI, MCP, or verification steps.',
|
|
679
|
+
evidence: toolStrategyEvidence,
|
|
680
|
+
recommendations: toolStrategyQuality.totalSteps > 0
|
|
681
|
+
? ['Use tool strategy evidence to review cost, retry, fallback, and side-effect risk before execution.']
|
|
682
|
+
: ['Create a task that triggers skill routing so the AI OS can build a tool strategy graph.'],
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
id: 'adaptive-workflow',
|
|
686
|
+
status: input.runReports.some(r => r.plan.adaptiveWorkflow.profile) ? 'ready' : input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked',
|
|
687
|
+
summary: summarizeAdaptiveWorkflowSignal(input.runReports, input.benchmark),
|
|
688
|
+
evidence: [
|
|
689
|
+
...input.runReports.map(r => `${r.artifacts.runReport}:profile=${r.plan.adaptiveWorkflow.profile}`),
|
|
690
|
+
...(input.benchmark ? [`${input.benchmarkReport}:profiles=${input.benchmark.summary.workflowProfiles.join(',')}`] : []),
|
|
691
|
+
],
|
|
692
|
+
recommendations: input.runReports.some(r => r.plan.adaptiveWorkflow.profile)
|
|
693
|
+
? ['Use workflow profile distribution to verify that risk signals correctly escalate governance.']
|
|
694
|
+
: ['Run an AI OS task with mixed risk levels to prove adaptive workflow routing.'],
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
id: 'evolution-shadow',
|
|
698
|
+
status: evolutionQuality.proposals > 0
|
|
699
|
+
? evolutionQuality.pendingValidation > 0 ? 'warning' : 'ready'
|
|
700
|
+
: input.runReports.length > 0 || input.benchmark ? 'warning' : 'blocked',
|
|
701
|
+
summary: evolutionQuality.proposals > 0
|
|
702
|
+
? `${evolutionQuality.proposals} shadow proposal(s); ${evolutionQuality.shadowRules} shadow, ${evolutionQuality.candidateHooks} candidate-hook, ${evolutionQuality.approvedBlocking} approved-blocking.`
|
|
703
|
+
: 'No evolution shadow proposals found. Run tasks with high-risk governance signals or evaluator gates to generate shadow rule candidates.',
|
|
704
|
+
evidence: evolutionEvidence,
|
|
705
|
+
recommendations: evolutionQuality.proposals > 0
|
|
706
|
+
? ['Review shadow rule proposals and validate before promotion to candidate-hook or approved-blocking.']
|
|
707
|
+
: ['Run a high-risk AI OS task so evolution shadow promotion can propose rules from governance and evaluator signals.'],
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
id: 'benchmark-intelligence',
|
|
711
|
+
status: input.benchmark && input.benchmarkStatus === 'fresh'
|
|
712
|
+
? 'ready'
|
|
713
|
+
: input.benchmark && input.benchmarkStatus === 'stale' ? 'warning' : 'blocked',
|
|
714
|
+
summary: input.benchmark
|
|
715
|
+
? `${input.benchmark.summary.scenarios} benchmark scenario(s); benchmark status ${input.benchmarkStatus}.`
|
|
716
|
+
: 'No AI OS benchmark report available for intelligence metrics.',
|
|
717
|
+
evidence: benchmarkEvidence,
|
|
718
|
+
recommendations: input.benchmark && input.benchmarkStatus === 'fresh'
|
|
719
|
+
? ['Use intelligence signals alongside benchmark deltas for release readiness reviews.']
|
|
720
|
+
: ['Run `scale ai-os benchmark --json` to refresh memory/context/skill intelligence metrics.'],
|
|
721
|
+
},
|
|
722
|
+
];
|
|
723
|
+
const summary = {
|
|
724
|
+
ready: signals.filter(signal => signal.status === 'ready').length,
|
|
725
|
+
warning: signals.filter(signal => signal.status === 'warning').length,
|
|
726
|
+
blocked: signals.filter(signal => signal.status === 'blocked').length,
|
|
727
|
+
totalMemoryItems,
|
|
728
|
+
selectedProviders,
|
|
729
|
+
memoryQuality,
|
|
730
|
+
contextQuality,
|
|
731
|
+
evaluatorQuality,
|
|
732
|
+
toolStrategyQuality,
|
|
733
|
+
evolutionQuality,
|
|
734
|
+
estimatedTokenSavings,
|
|
735
|
+
skillSteps,
|
|
736
|
+
};
|
|
737
|
+
const status = summary.blocked > 0 ? 'blocked' : summary.warning > 0 ? 'warning' : 'ready';
|
|
738
|
+
const nextActions = aiOsIntelligenceNextActions(status, signals, input.lang);
|
|
739
|
+
return { status, summary, signals, nextActions };
|
|
740
|
+
}
|
|
741
|
+
function summarizeContextQuality(runReports) {
|
|
742
|
+
const omitted = runReports.flatMap(report => report.plan.context.omitted.map(item => {
|
|
743
|
+
const section = report.plan.context.sections.find(candidate => candidate.id === item.id);
|
|
744
|
+
return {
|
|
745
|
+
...item,
|
|
746
|
+
category: section?.category,
|
|
747
|
+
runReport: report.artifacts.runReport,
|
|
748
|
+
};
|
|
749
|
+
}));
|
|
750
|
+
const totalOmittedTokens = omitted.reduce((sum, item) => sum + item.estimatedTokens, 0);
|
|
751
|
+
const highestOmittedTokens = omitted.reduce((max, item) => Math.max(max, item.estimatedTokens), 0);
|
|
752
|
+
const evidenceLossWarnings = omitted
|
|
753
|
+
.filter(item => item.category === 'evidence' || item.id.includes('evidence'))
|
|
754
|
+
.map(item => `${item.id} omitted from ${item.runReport} (${item.estimatedTokens} tokens; ${item.reason}).`);
|
|
755
|
+
const compressionRisk = evidenceLossWarnings.length > 0
|
|
756
|
+
? 'high'
|
|
757
|
+
: omitted.length > 0 ? 'medium' : 'low';
|
|
758
|
+
return {
|
|
759
|
+
omittedSections: omitted.length,
|
|
760
|
+
totalOmittedTokens,
|
|
761
|
+
evidenceLossWarnings,
|
|
762
|
+
highestOmittedTokens,
|
|
763
|
+
compressionRisk,
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function summarizeEvaluatorQuality(runReports, benchmark) {
|
|
767
|
+
const runEvaluators = runReports.map(resolveRunEvaluator);
|
|
768
|
+
const runGates = runEvaluators.flatMap(evaluator => evaluator.gates);
|
|
769
|
+
const benchmarkGateCount = benchmark?.summary.totalEvaluatorGates ?? 0;
|
|
770
|
+
const uncertaintyScores = runEvaluators.map(evaluator => evaluator.uncertainty.score);
|
|
771
|
+
const gateIds = new Set(runGates.map(gate => gate.id));
|
|
772
|
+
if (benchmarkGateCount > 0)
|
|
773
|
+
gateIds.add('uncertainty-decision-log');
|
|
774
|
+
return {
|
|
775
|
+
requiredGates: runGates.filter(gate => gate.required).length + benchmarkGateCount,
|
|
776
|
+
highRiskPlans: runEvaluators.filter(evaluator => evaluator.riskLevel === 'high').length,
|
|
777
|
+
averageUncertainty: roundMetric(average(uncertaintyScores)),
|
|
778
|
+
gateIds: [...gateIds].sort(),
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
function resolveRunEvaluator(report) {
|
|
782
|
+
const plan = report.plan;
|
|
783
|
+
return plan.evaluator ?? createEvaluatorIntelligence({
|
|
784
|
+
task: report.plan.task.task,
|
|
785
|
+
files: report.plan.task.files,
|
|
786
|
+
governance: report.plan.governance,
|
|
787
|
+
skillPlan: report.plan.skillPlan,
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
function summarizeToolStrategyQuality(runReports, benchmark) {
|
|
791
|
+
const runStrategies = runReports.map(resolveRunToolStrategy);
|
|
792
|
+
const runSummary = runStrategies.reduce((summary, strategy) => ({
|
|
793
|
+
totalSteps: summary.totalSteps + strategy.summary.totalSteps,
|
|
794
|
+
requiredSteps: summary.requiredSteps + strategy.summary.requiredSteps,
|
|
795
|
+
highRiskSteps: summary.highRiskSteps + strategy.summary.highRiskSteps,
|
|
796
|
+
estimatedCostUnits: summary.estimatedCostUnits + strategy.summary.estimatedCostUnits,
|
|
797
|
+
fallbackCoveredSteps: summary.fallbackCoveredSteps + strategy.summary.fallbackCoveredSteps,
|
|
798
|
+
}), {
|
|
799
|
+
totalSteps: 0,
|
|
800
|
+
requiredSteps: 0,
|
|
801
|
+
highRiskSteps: 0,
|
|
802
|
+
estimatedCostUnits: 0,
|
|
803
|
+
fallbackCoveredSteps: 0,
|
|
804
|
+
});
|
|
805
|
+
const benchmarkSteps = benchmark?.summary.totalToolStrategySteps ?? 0;
|
|
806
|
+
const benchmarkCost = benchmark?.summary.totalToolStrategyCostUnits ?? 0;
|
|
807
|
+
const totalSteps = runSummary.totalSteps + benchmarkSteps;
|
|
808
|
+
const fallbackCoveredSteps = runSummary.fallbackCoveredSteps + benchmarkSteps;
|
|
809
|
+
return {
|
|
810
|
+
totalSteps,
|
|
811
|
+
requiredSteps: runSummary.requiredSteps,
|
|
812
|
+
highRiskSteps: runSummary.highRiskSteps,
|
|
813
|
+
estimatedCostUnits: runSummary.estimatedCostUnits + benchmarkCost,
|
|
814
|
+
fallbackCoverage: totalSteps > 0 ? roundMetric(fallbackCoveredSteps / totalSteps) : 0,
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
function resolveRunToolStrategy(report) {
|
|
818
|
+
const plan = report.plan;
|
|
819
|
+
return plan.toolStrategy ?? createToolStrategyPlan(report.plan.skillPlan);
|
|
820
|
+
}
|
|
821
|
+
function summarizeEvolutionQuality(runReports, benchmark) {
|
|
822
|
+
const runProposals = runReports.flatMap(r => r.plan.evolutionShadow?.proposals ?? []);
|
|
823
|
+
const benchmarkProposals = benchmark?.summary.totalEvolutionProposals ?? 0;
|
|
824
|
+
const allProposals = runProposals;
|
|
825
|
+
const stageCount = (stage) => allProposals.filter(p => p.maturity.stage === stage).length;
|
|
826
|
+
return {
|
|
827
|
+
proposals: allProposals.length + benchmarkProposals,
|
|
828
|
+
shadowRules: stageCount('shadow'),
|
|
829
|
+
candidateHooks: stageCount('candidate-hook'),
|
|
830
|
+
approvedBlocking: stageCount('approved-blocking'),
|
|
831
|
+
pendingValidation: allProposals.filter(p => p.maturity.stage === 'shadow' && p.maturity.shadowHits < 10).length,
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
function resolveRunEvolutionShadow(report) {
|
|
835
|
+
const plan = report.plan;
|
|
836
|
+
return plan.evolutionShadow ?? buildEvolutionShadowReport([]);
|
|
837
|
+
}
|
|
838
|
+
function summarizeAdaptiveWorkflowSignal(runReports, benchmark) {
|
|
839
|
+
const profiles = runReports.map(r => r.plan.adaptiveWorkflow.profile);
|
|
840
|
+
const benchmarkProfiles = benchmark?.summary.workflowProfiles ?? [];
|
|
841
|
+
const allProfiles = [...profiles, ...benchmarkProfiles];
|
|
842
|
+
if (allProfiles.length === 0)
|
|
843
|
+
return 'No adaptive workflow profile evidence found.';
|
|
844
|
+
const distribution = new Map();
|
|
845
|
+
for (const p of allProfiles)
|
|
846
|
+
distribution.set(p, (distribution.get(p) ?? 0) + 1);
|
|
847
|
+
const parts = [...distribution.entries()].map(([p, n]) => `${p}=${n}`).join(', ');
|
|
848
|
+
const escalated = runReports.filter(r => r.plan.adaptiveWorkflow.escalationReasons.length > 0).length;
|
|
849
|
+
return `${allProfiles.length} run(s) with profile distribution: ${parts}. ${escalated} run(s) had escalation reasons.`;
|
|
850
|
+
}
|
|
851
|
+
function summarizeMemoryQuality(items) {
|
|
852
|
+
if (items.length === 0) {
|
|
853
|
+
return {
|
|
854
|
+
score: 0,
|
|
855
|
+
evidenceBackedItems: 0,
|
|
856
|
+
missingEvidenceItems: 0,
|
|
857
|
+
lowConfidenceItems: 0,
|
|
858
|
+
averageConfidence: 0,
|
|
859
|
+
averageRelevance: 0,
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
const evidenceBackedItems = items.filter(item => item.evidencePaths.length > 0).length;
|
|
863
|
+
const missingEvidenceItems = items.length - evidenceBackedItems;
|
|
864
|
+
const lowConfidenceItems = items.filter(item => item.confidence < 0.7).length;
|
|
865
|
+
const averageConfidence = average(items.map(item => clampUnit(item.confidence)));
|
|
866
|
+
const averageRelevance = average(items.map(item => clampUnit(item.score)));
|
|
867
|
+
const evidenceRatio = evidenceBackedItems / items.length;
|
|
868
|
+
const lowConfidenceRatio = lowConfidenceItems / items.length;
|
|
869
|
+
const score = Math.max(0, Math.round((averageConfidence * 40) + (averageRelevance * 30) + (evidenceRatio * 30) - (lowConfidenceRatio * 10)));
|
|
870
|
+
return {
|
|
871
|
+
score,
|
|
872
|
+
evidenceBackedItems,
|
|
873
|
+
missingEvidenceItems,
|
|
874
|
+
lowConfidenceItems,
|
|
875
|
+
averageConfidence: roundMetric(averageConfidence),
|
|
876
|
+
averageRelevance: roundMetric(averageRelevance),
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function average(values) {
|
|
880
|
+
if (values.length === 0)
|
|
881
|
+
return 0;
|
|
882
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
883
|
+
}
|
|
884
|
+
function clampUnit(value) {
|
|
885
|
+
if (!Number.isFinite(value))
|
|
886
|
+
return 0;
|
|
887
|
+
return Math.max(0, Math.min(1, value));
|
|
888
|
+
}
|
|
889
|
+
function roundMetric(value) {
|
|
890
|
+
return Number(value.toFixed(3));
|
|
891
|
+
}
|
|
892
|
+
function aiOsIntelligenceNextActions(status, signals, lang) {
|
|
893
|
+
const actions = [];
|
|
894
|
+
if (signals.some(signal => signal.status === 'ready')) {
|
|
895
|
+
actions.push('Use intelligence signals during release review to prove memory, context, and skill routing gains.');
|
|
896
|
+
}
|
|
897
|
+
if (status === 'ready')
|
|
898
|
+
return actions;
|
|
899
|
+
const blocked = signals.filter(signal => signal.status === 'blocked').map(signal => signal.id);
|
|
900
|
+
if (lang === 'zh') {
|
|
901
|
+
actions.push(`Refresh AI OS intelligence evidence for: ${blocked.join(', ') || 'warning signals'}.`);
|
|
902
|
+
return actions;
|
|
903
|
+
}
|
|
904
|
+
actions.push(`Refresh AI OS intelligence evidence for: ${blocked.join(', ') || 'warning signals'}.`);
|
|
905
|
+
return actions;
|
|
906
|
+
}
|
|
534
907
|
function buildRunSteps(plan) {
|
|
535
908
|
const steps = new Map();
|
|
536
909
|
const upsert = (step) => steps.set(step.id, step);
|
|
@@ -563,16 +936,20 @@ function buildRunSteps(plan) {
|
|
|
563
936
|
evidence: ['memory.providerOrder', 'memory.selectedProviders', 'memory.items'],
|
|
564
937
|
dependsOn: ['runtime-plan'],
|
|
565
938
|
});
|
|
939
|
+
const profile = plan.adaptiveWorkflow.profile;
|
|
566
940
|
for (const gate of plan.adaptiveWorkflow.gates) {
|
|
567
941
|
if (steps.has(gate))
|
|
568
942
|
continue;
|
|
943
|
+
const gateRequired = profile !== 'light';
|
|
569
944
|
upsert({
|
|
570
945
|
id: gate,
|
|
571
946
|
kind: gate === 'runtime-evidence' ? 'evidence' : 'gate',
|
|
572
947
|
title: `Satisfy ${gate} gate`,
|
|
573
948
|
status: 'planned',
|
|
574
|
-
required:
|
|
575
|
-
summary:
|
|
949
|
+
required: gateRequired,
|
|
950
|
+
summary: gateRequired
|
|
951
|
+
? `Required by ${plan.adaptiveWorkflow.strategy} in ${profile} profile (${plan.adaptiveWorkflow.mode} mode).`
|
|
952
|
+
: `Advisory in ${profile} profile; not blocking completion.`,
|
|
576
953
|
evidence: [`gate.${gate}`],
|
|
577
954
|
dependsOn: ['runtime-plan'],
|
|
578
955
|
});
|
|
@@ -945,6 +1322,22 @@ function inspectBenchmarkReport(projectDir, scaleDir, maxAgeHours, warnings) {
|
|
|
945
1322
|
return { status: 'invalid', reportPath };
|
|
946
1323
|
}
|
|
947
1324
|
}
|
|
1325
|
+
function readAiOsBenchmarkReport(reportPath, warnings) {
|
|
1326
|
+
if (!existsSync(reportPath))
|
|
1327
|
+
return undefined;
|
|
1328
|
+
try {
|
|
1329
|
+
const parsed = JSON.parse(readFileSync(reportPath, 'utf-8'));
|
|
1330
|
+
if (!parsed || !parsed.summary || !Array.isArray(parsed.scenarios)) {
|
|
1331
|
+
warnings.push(`Ignored invalid AI OS benchmark report: ${reportPath}`);
|
|
1332
|
+
return undefined;
|
|
1333
|
+
}
|
|
1334
|
+
return parsed;
|
|
1335
|
+
}
|
|
1336
|
+
catch (error) {
|
|
1337
|
+
warnings.push(`Ignored unreadable AI OS benchmark report: ${reportPath} (${error instanceof Error ? error.message : String(error)})`);
|
|
1338
|
+
return undefined;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
948
1341
|
function summarizeBenchmarkDoctor(benchmark) {
|
|
949
1342
|
if (benchmark.status === 'missing')
|
|
950
1343
|
return 'No AI OS benchmark report found.';
|
|
@@ -1108,7 +1501,12 @@ function summarizeBenchmark(results) {
|
|
|
1108
1501
|
totalMemoryItems: results.reduce((sum, result) => sum + result.metrics.memoryItems, 0),
|
|
1109
1502
|
totalSkillSteps: results.reduce((sum, result) => sum + result.metrics.skillSteps, 0),
|
|
1110
1503
|
requiredSkillSteps: results.reduce((sum, result) => sum + result.metrics.requiredSkillSteps, 0),
|
|
1504
|
+
totalEvaluatorGates: results.reduce((sum, result) => sum + result.metrics.evaluatorGates, 0),
|
|
1505
|
+
totalToolStrategySteps: results.reduce((sum, result) => sum + result.metrics.toolStrategySteps, 0),
|
|
1506
|
+
totalToolStrategyCostUnits: results.reduce((sum, result) => sum + result.metrics.toolStrategyCostUnits, 0),
|
|
1507
|
+
totalEvolutionProposals: results.reduce((sum, result) => sum + result.metrics.evolutionProposals, 0),
|
|
1111
1508
|
governanceModes: [...new Set(results.map(result => result.governanceMode))],
|
|
1509
|
+
workflowProfiles: [...new Set(results.map(result => result.workflowProfile))],
|
|
1112
1510
|
averageTokenUtilization: totalBudget > 0 ? Number((totalEstimatedTokens / totalBudget).toFixed(4)) : 0,
|
|
1113
1511
|
};
|
|
1114
1512
|
}
|
|
@@ -1116,6 +1514,10 @@ function benchmarkRecommendations(summary) {
|
|
|
1116
1514
|
const recommendations = ['Use benchmark deltas in release notes only after comparing the same scenario set across versions.'];
|
|
1117
1515
|
if (summary.totalSkillSteps === 0)
|
|
1118
1516
|
recommendations.push('Skill routing did not produce steps; inspect skill policy detection.');
|
|
1517
|
+
if (summary.totalEvaluatorGates === 0)
|
|
1518
|
+
recommendations.push('Evaluator intelligence did not require any critique gate; add reasoning-heavy benchmark scenarios before claiming evaluator coverage.');
|
|
1519
|
+
if (summary.totalToolStrategySteps === 0)
|
|
1520
|
+
recommendations.push('Tool strategy did not build a cost/retry/fallback graph; inspect skill execution plan coverage.');
|
|
1119
1521
|
if (summary.averageTokenUtilization > 0.9)
|
|
1120
1522
|
recommendations.push('Context utilization is high; lower budgets or improve relevance filtering before scaling.');
|
|
1121
1523
|
if (!summary.governanceModes.includes('critical') && !summary.governanceModes.includes('expanded')) {
|
|
@@ -1123,30 +1525,279 @@ function benchmarkRecommendations(summary) {
|
|
|
1123
1525
|
}
|
|
1124
1526
|
return recommendations;
|
|
1125
1527
|
}
|
|
1126
|
-
function createAdaptiveWorkflow(governance, skillPlan) {
|
|
1528
|
+
function createAdaptiveWorkflow(governance, skillPlan, evaluator, toolStrategy) {
|
|
1529
|
+
const routerResult = routeAdaptiveWorkflow({ governance, evaluator, toolStrategy });
|
|
1127
1530
|
const gates = new Set();
|
|
1128
1531
|
gates.add('context-compiler');
|
|
1129
1532
|
gates.add('memory-provider-recall');
|
|
1130
1533
|
if (skillPlan.required || skillPlan.executionPlan.steps.length > 0)
|
|
1131
1534
|
gates.add('skill-evidence');
|
|
1132
1535
|
gates.add('runtime-evidence');
|
|
1133
|
-
if (
|
|
1536
|
+
if (routerResult.profile === 'strict' || routerResult.profile === 'critical')
|
|
1134
1537
|
gates.add('impact-analysis');
|
|
1135
|
-
if (
|
|
1538
|
+
if (routerResult.profile === 'critical')
|
|
1136
1539
|
gates.add('security-review');
|
|
1540
|
+
for (const gate of evaluator.gates)
|
|
1541
|
+
gates.add(gate.id);
|
|
1542
|
+
for (const override of routerResult.gateOverrides)
|
|
1543
|
+
gates.add(override.gateId);
|
|
1544
|
+
const requiredBehaviors = new Set(governance.requiredBehaviors);
|
|
1545
|
+
for (const constraint of routerResult.behavioralConstraints) {
|
|
1546
|
+
if (constraint.required)
|
|
1547
|
+
requiredBehaviors.add(constraint.description);
|
|
1548
|
+
}
|
|
1137
1549
|
return {
|
|
1138
1550
|
strategy: 'risk-adaptive-runtime-v1',
|
|
1551
|
+
profile: routerResult.profile,
|
|
1552
|
+
escalationReasons: routerResult.escalationReasons,
|
|
1139
1553
|
mode: governance.effectiveMode,
|
|
1140
|
-
requiredBehaviors:
|
|
1554
|
+
requiredBehaviors: Array.from(requiredBehaviors),
|
|
1141
1555
|
gates: Array.from(gates),
|
|
1142
|
-
exitCriteria:
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1556
|
+
exitCriteria: routerResult.exitCriteria,
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
function createEvaluatorIntelligence(input) {
|
|
1560
|
+
const haystack = `${input.task} ${input.files.join(' ')} ${input.governance.signals.map(signal => signal.id).join(' ')}`.toLowerCase();
|
|
1561
|
+
const gates = [];
|
|
1562
|
+
const addGate = (gate) => {
|
|
1563
|
+
if (gates.some(existing => existing.id === gate.id))
|
|
1564
|
+
return;
|
|
1565
|
+
gates.push(gate);
|
|
1566
|
+
};
|
|
1567
|
+
if (/architecture|architectural|design|strategy|boundary|refactor|runtime|platform|framework|架构|方案|设计|边界|平台/.test(haystack)) {
|
|
1568
|
+
addGate({
|
|
1569
|
+
id: 'architecture-critique',
|
|
1570
|
+
required: input.governance.effectiveMode !== 'minimal',
|
|
1571
|
+
reason: 'Architecture, runtime, platform, or design decisions need an explicit critique before implementation claims.',
|
|
1572
|
+
evidence: matchingEvidence(input.files, /architecture|runtime|framework|docs|readme|src/i),
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
if (/root cause|diagnose|debug|failure|incident|postmortem|regression|blocked|根因|排查|故障|事故|回归/.test(haystack)) {
|
|
1576
|
+
addGate({
|
|
1577
|
+
id: 'root-cause-review',
|
|
1578
|
+
required: true,
|
|
1579
|
+
reason: 'Failure diagnosis or root-cause work needs an alternate hypothesis check before closing.',
|
|
1580
|
+
evidence: matchingEvidence(input.files, /test|runtime|debug|log|src|docs/i),
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
if (input.governance.signals.some(signal => signal.id === 'critical-risk-domain' || signal.id === 'critical-file-path')) {
|
|
1584
|
+
addGate({
|
|
1585
|
+
id: 'security-threat-model',
|
|
1586
|
+
required: true,
|
|
1587
|
+
reason: 'Critical auth, data, production, or destructive risk requires threat-model review evidence.',
|
|
1588
|
+
evidence: input.governance.signals.flatMap(signal => signal.evidence).slice(0, 12),
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (/release|publish|deploy|migration|rollback|version|changelog|npm|ci|发版|发布|部署|迁移|回滚/.test(haystack)) {
|
|
1592
|
+
addGate({
|
|
1593
|
+
id: 'release-readiness-review',
|
|
1594
|
+
required: true,
|
|
1595
|
+
reason: 'Release, deployment, migration, or rollback work needs readiness and rollback evidence.',
|
|
1596
|
+
evidence: matchingEvidence(input.files, /package|changelog|release|deploy|migration|workflow|github/i),
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
const drivers = evaluatorUncertaintyDrivers(input, gates);
|
|
1600
|
+
const uncertaintyScore = evaluatorUncertaintyScore(input, gates, drivers);
|
|
1601
|
+
if (gates.length > 0 || uncertaintyScore >= 0.45) {
|
|
1602
|
+
addGate({
|
|
1603
|
+
id: 'uncertainty-decision-log',
|
|
1604
|
+
required: uncertaintyScore >= 0.45 || input.governance.effectiveMode === 'critical',
|
|
1605
|
+
reason: 'The agent must record uncertainty, rejected alternatives, and evidence gaps before completion.',
|
|
1606
|
+
evidence: drivers,
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
const riskLevel = uncertaintyScore >= 0.7
|
|
1610
|
+
? 'high'
|
|
1611
|
+
: uncertaintyScore >= 0.4 || gates.some(gate => gate.required) ? 'medium' : 'low';
|
|
1612
|
+
return {
|
|
1613
|
+
strategy: 'evaluator-intelligence-v1',
|
|
1614
|
+
required: gates.some(gate => gate.required),
|
|
1615
|
+
riskLevel,
|
|
1616
|
+
uncertainty: {
|
|
1617
|
+
score: uncertaintyScore,
|
|
1618
|
+
threshold: 0.45,
|
|
1619
|
+
drivers,
|
|
1620
|
+
},
|
|
1621
|
+
gates,
|
|
1622
|
+
recommendations: evaluatorRecommendations(gates, riskLevel),
|
|
1148
1623
|
};
|
|
1149
1624
|
}
|
|
1625
|
+
function createToolStrategyPlan(skillPlan) {
|
|
1626
|
+
const nodes = skillPlan.executionPlan.steps.map(step => {
|
|
1627
|
+
const risks = toolStepRisks(step.id, step.kind);
|
|
1628
|
+
return {
|
|
1629
|
+
id: `${step.kind}:${step.id}`,
|
|
1630
|
+
kind: step.kind,
|
|
1631
|
+
required: step.required,
|
|
1632
|
+
cost: {
|
|
1633
|
+
units: toolStepCostUnits(step.id, step.kind, step.required, risks),
|
|
1634
|
+
timeRisk: risks.timeRisk,
|
|
1635
|
+
sideEffectRisk: risks.sideEffectRisk,
|
|
1636
|
+
},
|
|
1637
|
+
retry: toolStepRetry(step.id, step.kind, risks),
|
|
1638
|
+
fallback: step.fallback,
|
|
1639
|
+
evidence: [step.evidenceRequired],
|
|
1640
|
+
};
|
|
1641
|
+
});
|
|
1642
|
+
const edges = buildToolStrategyEdges(nodes);
|
|
1643
|
+
const summary = {
|
|
1644
|
+
totalSteps: nodes.length,
|
|
1645
|
+
requiredSteps: nodes.filter(node => node.required).length,
|
|
1646
|
+
highRiskSteps: nodes.filter(node => node.cost.timeRisk === 'high' || node.cost.sideEffectRisk === 'high').length,
|
|
1647
|
+
estimatedCostUnits: nodes.reduce((sum, node) => sum + node.cost.units, 0),
|
|
1648
|
+
fallbackCoveredSteps: nodes.filter(node => node.fallback.trim().length > 0).length,
|
|
1649
|
+
};
|
|
1650
|
+
return {
|
|
1651
|
+
strategy: 'tool-strategy-v1',
|
|
1652
|
+
nodes,
|
|
1653
|
+
edges,
|
|
1654
|
+
summary,
|
|
1655
|
+
recommendations: toolStrategyRecommendations(summary),
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
function createEvolutionShadowProposals(governance, evaluator) {
|
|
1659
|
+
const proposals = [];
|
|
1660
|
+
// Propose shadow rules from governance risk signals (escalated modes)
|
|
1661
|
+
for (const signal of governance.signals) {
|
|
1662
|
+
if (signal.mode === 'expanded' || signal.mode === 'critical') {
|
|
1663
|
+
proposals.push(proposeShadowRule({
|
|
1664
|
+
title: `Governance signal: ${signal.id}`,
|
|
1665
|
+
description: `Shadow rule from governance signal "${signal.id}" (mode=${signal.mode}). ${signal.reason}`,
|
|
1666
|
+
source: 'failure-learning',
|
|
1667
|
+
sourceEvidenceIds: signal.evidence.length > 0 ? signal.evidence : [signal.id],
|
|
1668
|
+
pattern: signal.id,
|
|
1669
|
+
enforcement: signal.mode === 'critical' ? 'hook' : 'prompt',
|
|
1670
|
+
rollback: `Remove shadow rule for governance signal "${signal.id}" if false positive rate exceeds threshold.`,
|
|
1671
|
+
}));
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
// Propose shadow rules from high-risk evaluator gates
|
|
1675
|
+
for (const gate of evaluator.gates) {
|
|
1676
|
+
if (gate.required && (gate.id === 'security-threat-model' || gate.id === 'root-cause-review')) {
|
|
1677
|
+
proposals.push(proposeShadowRule({
|
|
1678
|
+
title: `Evaluator gate: ${gate.id}`,
|
|
1679
|
+
description: `Shadow rule from required evaluator gate "${gate.id}". ${gate.reason}`,
|
|
1680
|
+
source: 'lesson-extraction',
|
|
1681
|
+
sourceEvidenceIds: [gate.id],
|
|
1682
|
+
pattern: gate.id,
|
|
1683
|
+
enforcement: 'prompt',
|
|
1684
|
+
rollback: `Remove shadow rule for evaluator gate "${gate.id}" if it does not reduce defect recurrence.`,
|
|
1685
|
+
}));
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
return buildEvolutionShadowReport(proposals);
|
|
1689
|
+
}
|
|
1690
|
+
function toolStepRisks(id, kind) {
|
|
1691
|
+
const normalized = id.toLowerCase();
|
|
1692
|
+
if (/desktop|cua|deploy|publish|release|migration|rollback|delete|drop|external|cli/.test(normalized)) {
|
|
1693
|
+
return { timeRisk: 'high', sideEffectRisk: 'high' };
|
|
1694
|
+
}
|
|
1695
|
+
if (/browser|e2e|playwright|screenshot|visual|security|threat|audit/.test(normalized)) {
|
|
1696
|
+
return { timeRisk: 'medium', sideEffectRisk: kind === 'verification' ? 'medium' : 'low' };
|
|
1697
|
+
}
|
|
1698
|
+
if (kind === 'artifact')
|
|
1699
|
+
return { timeRisk: 'low', sideEffectRisk: 'low' };
|
|
1700
|
+
if (kind === 'verification')
|
|
1701
|
+
return { timeRisk: 'medium', sideEffectRisk: 'medium' };
|
|
1702
|
+
return { timeRisk: 'medium', sideEffectRisk: 'low' };
|
|
1703
|
+
}
|
|
1704
|
+
function toolStepCostUnits(id, kind, required, risks) {
|
|
1705
|
+
let units = kind === 'artifact' ? 1 : kind === 'verification' ? 2 : 3;
|
|
1706
|
+
if (required)
|
|
1707
|
+
units += 1;
|
|
1708
|
+
if (risks.timeRisk === 'medium')
|
|
1709
|
+
units += 1;
|
|
1710
|
+
if (risks.timeRisk === 'high')
|
|
1711
|
+
units += 2;
|
|
1712
|
+
if (risks.sideEffectRisk === 'high')
|
|
1713
|
+
units += 2;
|
|
1714
|
+
if (/browser|e2e|desktop|external|cli|security|audit/i.test(id))
|
|
1715
|
+
units += 1;
|
|
1716
|
+
return units;
|
|
1717
|
+
}
|
|
1718
|
+
function toolStepRetry(id, kind, risks) {
|
|
1719
|
+
if (risks.sideEffectRisk === 'high')
|
|
1720
|
+
return { maxAttempts: 1, backoff: 'manual-review' };
|
|
1721
|
+
if (kind === 'verification')
|
|
1722
|
+
return { maxAttempts: /browser|e2e|playwright|network/i.test(id) ? 2 : 1, backoff: 'linear' };
|
|
1723
|
+
if (kind === 'skill')
|
|
1724
|
+
return { maxAttempts: 1, backoff: 'manual-review' };
|
|
1725
|
+
return { maxAttempts: 1, backoff: 'none' };
|
|
1726
|
+
}
|
|
1727
|
+
function buildToolStrategyEdges(nodes) {
|
|
1728
|
+
const edges = [];
|
|
1729
|
+
const skillNodes = nodes.filter(node => node.kind === 'skill');
|
|
1730
|
+
const artifactNodes = nodes.filter(node => node.kind === 'artifact');
|
|
1731
|
+
const verificationNodes = nodes.filter(node => node.kind === 'verification');
|
|
1732
|
+
for (const artifact of artifactNodes) {
|
|
1733
|
+
for (const skill of skillNodes.filter(node => node.required || artifact.required)) {
|
|
1734
|
+
edges.push({ from: skill.id, to: artifact.id, reason: 'Skill execution must leave artifact evidence when both are required or review-relevant.' });
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
for (const verification of verificationNodes) {
|
|
1738
|
+
for (const artifact of artifactNodes.filter(node => node.required)) {
|
|
1739
|
+
edges.push({ from: artifact.id, to: verification.id, reason: 'Required artifacts should exist before verification evidence is accepted.' });
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
return edges;
|
|
1743
|
+
}
|
|
1744
|
+
function toolStrategyRecommendations(summary) {
|
|
1745
|
+
if (summary.totalSteps === 0)
|
|
1746
|
+
return ['No tool strategy required; standard verification is enough for this task.'];
|
|
1747
|
+
const recommendations = ['Execute required tool strategy nodes before claiming task completion.'];
|
|
1748
|
+
if (summary.highRiskSteps > 0)
|
|
1749
|
+
recommendations.push('High-risk tool steps require manual review or explicit safe-mode evidence before retry.');
|
|
1750
|
+
if (summary.fallbackCoveredSteps < summary.totalSteps)
|
|
1751
|
+
recommendations.push('Fill fallback policy gaps before autonomous execution.');
|
|
1752
|
+
return recommendations;
|
|
1753
|
+
}
|
|
1754
|
+
function matchingEvidence(files, pattern) {
|
|
1755
|
+
return files.filter(file => pattern.test(file)).slice(0, 12);
|
|
1756
|
+
}
|
|
1757
|
+
function evaluatorUncertaintyDrivers(input, gates) {
|
|
1758
|
+
const drivers = new Set();
|
|
1759
|
+
if (input.governance.effectiveMode === 'critical')
|
|
1760
|
+
drivers.add('critical-governance-mode');
|
|
1761
|
+
if (input.governance.effectiveMode === 'expanded')
|
|
1762
|
+
drivers.add('expanded-governance-mode');
|
|
1763
|
+
if (input.files.length >= 6)
|
|
1764
|
+
drivers.add('wide-file-scope');
|
|
1765
|
+
if (input.skillPlan.executionPlan.steps.some(step => step.required))
|
|
1766
|
+
drivers.add('required-skill-evidence');
|
|
1767
|
+
for (const gate of gates)
|
|
1768
|
+
drivers.add(gate.id);
|
|
1769
|
+
if (/unknown|uncertain|maybe|assume|guess|可能|不确定|假设/.test(input.task.toLowerCase()))
|
|
1770
|
+
drivers.add('explicit-uncertainty-language');
|
|
1771
|
+
return [...drivers];
|
|
1772
|
+
}
|
|
1773
|
+
function evaluatorUncertaintyScore(input, gates, drivers) {
|
|
1774
|
+
let score = 0.15;
|
|
1775
|
+
if (input.governance.effectiveMode === 'standard')
|
|
1776
|
+
score += 0.1;
|
|
1777
|
+
if (input.governance.effectiveMode === 'expanded')
|
|
1778
|
+
score += 0.25;
|
|
1779
|
+
if (input.governance.effectiveMode === 'critical')
|
|
1780
|
+
score += 0.4;
|
|
1781
|
+
score += Math.min(0.2, input.files.length * 0.025);
|
|
1782
|
+
score += Math.min(0.2, gates.filter(gate => gate.required).length * 0.08);
|
|
1783
|
+
if (input.skillPlan.executionPlan.steps.some(step => step.required))
|
|
1784
|
+
score += 0.08;
|
|
1785
|
+
if (drivers.includes('explicit-uncertainty-language'))
|
|
1786
|
+
score += 0.12;
|
|
1787
|
+
return roundMetric(clampUnit(score));
|
|
1788
|
+
}
|
|
1789
|
+
function evaluatorRecommendations(gates, riskLevel) {
|
|
1790
|
+
if (gates.length === 0)
|
|
1791
|
+
return ['No evaluator gate required; keep lightweight verification evidence for low-risk work.'];
|
|
1792
|
+
const recommendations = ['Record evaluator evidence before promoting reasoning-heavy implementation or release claims.'];
|
|
1793
|
+
if (riskLevel === 'high')
|
|
1794
|
+
recommendations.push('Require reviewer sign-off for uncertainty, rejected alternatives, and rollback or mitigation path.');
|
|
1795
|
+
if (gates.some(gate => gate.id === 'root-cause-review'))
|
|
1796
|
+
recommendations.push('List competing root-cause hypotheses and why each was accepted or rejected.');
|
|
1797
|
+
if (gates.some(gate => gate.id === 'security-threat-model'))
|
|
1798
|
+
recommendations.push('Attach threat model or security-review evidence before guarded completion.');
|
|
1799
|
+
return recommendations;
|
|
1800
|
+
}
|
|
1150
1801
|
function recommendations(options) {
|
|
1151
1802
|
const output = [];
|
|
1152
1803
|
if (options.context.compiler?.estimatedTokenSavings) {
|
|
@@ -1161,6 +1812,12 @@ function recommendations(options) {
|
|
|
1161
1812
|
if (options.governance.effectiveMode === 'critical') {
|
|
1162
1813
|
output.push('Critical workflow mode requires security review and rollback or disable strategy.');
|
|
1163
1814
|
}
|
|
1815
|
+
if (options.evaluator.required) {
|
|
1816
|
+
output.push(`Evaluator intelligence requires ${options.evaluator.gates.length} critique gate(s); record uncertainty and review evidence before promotion.`);
|
|
1817
|
+
}
|
|
1818
|
+
if (options.toolStrategy.summary.totalSteps > 0) {
|
|
1819
|
+
output.push(`Tool strategy planner created ${options.toolStrategy.summary.totalSteps} cost/retry/fallback node(s); execute required nodes with evidence.`);
|
|
1820
|
+
}
|
|
1164
1821
|
return output;
|
|
1165
1822
|
}
|
|
1166
1823
|
function normalizeSkillTaskLevel(value) {
|