@hongmaple0820/scale-engine 0.23.0 → 0.24.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/dist/api/cli.js +192 -1
- package/dist/api/cli.js.map +1 -1
- package/dist/dashboard/MetricsAggregator.d.ts +38 -0
- package/dist/dashboard/MetricsAggregator.js +99 -0
- package/dist/dashboard/MetricsAggregator.js.map +1 -0
- package/dist/dashboard/index.d.ts +2 -0
- package/dist/dashboard/index.js +1 -0
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/server.js.map +1 -1
- package/dist/evolution/AutoDefectCreator.d.ts +11 -2
- package/dist/evolution/AutoDefectCreator.js +46 -2
- package/dist/evolution/AutoDefectCreator.js.map +1 -1
- package/dist/evolution/EvolutionEngine.d.ts +3 -0
- package/dist/evolution/EvolutionEngine.js +18 -2
- package/dist/evolution/EvolutionEngine.js.map +1 -1
- package/dist/evolution/RuleMaturity.d.ts +39 -0
- package/dist/evolution/RuleMaturity.js +70 -0
- package/dist/evolution/RuleMaturity.js.map +1 -0
- package/dist/guardrails/ActiveRedTeam.d.ts +46 -0
- package/dist/guardrails/ActiveRedTeam.js +203 -0
- package/dist/guardrails/ActiveRedTeam.js.map +1 -0
- package/dist/guardrails/DependencyAuditor.d.ts +68 -0
- package/dist/guardrails/DependencyAuditor.js +331 -0
- package/dist/guardrails/DependencyAuditor.js.map +1 -0
- package/dist/hooks/HookGeneratorEnhanced.js +18 -18
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/output/GovernanceDashboard.d.ts +2 -0
- package/dist/output/GovernanceDashboard.js +31 -0
- package/dist/output/GovernanceDashboard.js.map +1 -1
- package/dist/routing/PromptCachePolicy.d.ts +37 -0
- package/dist/routing/PromptCachePolicy.js +97 -0
- package/dist/routing/PromptCachePolicy.js.map +1 -0
- package/dist/runtime/ModelUsageLedger.d.ts +50 -0
- package/dist/runtime/ModelUsageLedger.js +92 -0
- package/dist/runtime/ModelUsageLedger.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/workflow/autonomous/BackgroundHunter.d.ts +74 -0
- package/dist/workflow/autonomous/BackgroundHunter.js +220 -0
- package/dist/workflow/autonomous/BackgroundHunter.js.map +1 -0
- package/dist/workflow/autonomous/index.d.ts +1 -0
- package/dist/workflow/autonomous/index.js +1 -0
- package/dist/workflow/autonomous/index.js.map +1 -1
- package/dist/workflow/gates/GateSystem.d.ts +10 -0
- package/dist/workflow/gates/GateSystem.js +62 -0
- package/dist/workflow/gates/GateSystem.js.map +1 -1
- package/dist/workflow/gates/VisualGate.d.ts +41 -0
- package/dist/workflow/gates/VisualGate.js +174 -0
- package/dist/workflow/gates/VisualGate.js.map +1 -0
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.js +1 -0
- package/dist/workflow/index.js.map +1 -1
- package/docs/ACTIVE_SECURITY_VISUAL_GATES.md +87 -0
- package/docs/BACKGROUND_HUNTER.md +62 -0
- package/docs/CONTEXT_BUDGET.md +32 -6
- package/docs/DEPENDENCY_AUDIT.md +89 -0
- package/docs/EVOLUTION_SHADOW_MODE.md +63 -0
- package/docs/GOVERNANCE_DASHBOARD.md +21 -5
- package/docs/README.md +22 -12
- package/package.json +13 -9
package/dist/api/cli.js
CHANGED
|
@@ -9,10 +9,12 @@ import { registerAllFSMs, INITIAL_STATES } from '../artifact/fsmDefinitions.js';
|
|
|
9
9
|
import { Gateway } from '../guardrails/Gateway.js';
|
|
10
10
|
import { BruteRetryDetector, PrematureDoneDetector, BlameShiftDetector } from '../guardrails/detectors.js';
|
|
11
11
|
import { DangerousCommandDetector, SecretLeakDetector, RoleGateDetector, ScopeCreepDetector, BUILT_IN_ROLES } from '../guardrails/advancedDetectors.js';
|
|
12
|
+
import { auditDependencies } from '../guardrails/DependencyAuditor.js';
|
|
12
13
|
import { SQLiteKnowledgeBase } from '../knowledge/SQLiteKnowledgeBase.js';
|
|
13
14
|
import { ContextBuilder } from '../context/ContextBuilder.js';
|
|
14
15
|
import { ProjectAnatomy } from '../context/ProjectAnatomy.js';
|
|
15
16
|
import { buildContextPack, doctorContextBudget, scanContextBudget, writeContextBudgetReport, } from '../context/ContextBudget.js';
|
|
17
|
+
import { resolvePromptCachePolicy } from '../routing/PromptCachePolicy.js';
|
|
16
18
|
import { CerebrumManager } from '../knowledge/CerebrumManager.js';
|
|
17
19
|
import { buildCodeGraphContext, createCodeGraphRoiReport, impactCodeGraph, inspectCodeIntelligence, queryCodeGraph, writeCodeIntelligenceConfig, } from '../codegraph/CodeIntelligence.js';
|
|
18
20
|
import { WorkflowEvalStore, compareWorkflowEvalRuns, renderWorkflowEvalReport, runWorkflowEvalSuite, } from '../eval/WorkflowEval.js';
|
|
@@ -47,6 +49,7 @@ import { baselineEngineeringStandards, doctorEngineeringStandards, scanEngineeri
|
|
|
47
49
|
import { doctorResourceAssets, scanResourceAssets, settleResourceAssets } from '../workflow/ResourceGovernance.js';
|
|
48
50
|
import { analyzeContextGovernance, renderContextGrillPrompt, writeContextGovernanceTemplates, } from '../workflow/ContextGovernance.js';
|
|
49
51
|
import { createDiagnosticLoop, renderDiagnosticLoopMarkdown, validateDiagnosticLoop, } from '../workflow/DiagnosticLoop.js';
|
|
52
|
+
import { BackgroundHunter, HuntFindingStore } from '../workflow/autonomous/BackgroundHunter.js';
|
|
50
53
|
import { createTddSlice, evaluateTddSlice, renderTddSliceMarkdown, } from '../workflow/TddLoop.js';
|
|
51
54
|
import { nextWorkflowOpenTask, removeWorkflowOpenTask, toolEvidenceRunCompletesOpenTask } from '../workflow/WorkflowOpenTasks.js';
|
|
52
55
|
import { TaskMetricsStore } from '../workflow/TaskMetricsStore.js';
|
|
@@ -1012,6 +1015,7 @@ const contextBudget = defineCommand({
|
|
|
1012
1015
|
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1013
1016
|
'max-always': { type: 'string', description: 'Maximum Always-loaded estimated tokens' },
|
|
1014
1017
|
'max-task': { type: 'string', description: 'Maximum task context estimated tokens' },
|
|
1018
|
+
provider: { type: 'string', default: 'generic', description: 'Model provider for prompt cache policy: anthropic, openai, or generic' },
|
|
1015
1019
|
write: { type: 'boolean', default: false, description: 'Write .scale/context-budget.json' },
|
|
1016
1020
|
json: { type: 'boolean', default: false },
|
|
1017
1021
|
},
|
|
@@ -1024,9 +1028,13 @@ const contextBudget = defineCommand({
|
|
|
1024
1028
|
maxAlwaysTokens: parsePositiveIntArg(args['max-always'], '--max-always'),
|
|
1025
1029
|
maxTaskTokens: parsePositiveIntArg(args['max-task'], '--max-task'),
|
|
1026
1030
|
});
|
|
1031
|
+
const promptCache = resolvePromptCachePolicy({
|
|
1032
|
+
provider: String(args.provider ?? 'generic'),
|
|
1033
|
+
entries: report.entries,
|
|
1034
|
+
});
|
|
1027
1035
|
const path = isTruthyFlag(args.write) ? writeContextBudgetReport(report) : undefined;
|
|
1028
1036
|
if (args.json) {
|
|
1029
|
-
console.log(JSON.stringify({ ...report, path }, null, 2));
|
|
1037
|
+
console.log(JSON.stringify({ ...report, promptCache, path }, null, 2));
|
|
1030
1038
|
return;
|
|
1031
1039
|
}
|
|
1032
1040
|
console.log('SCALE Context Budget');
|
|
@@ -1036,6 +1044,9 @@ const contextBudget = defineCommand({
|
|
|
1036
1044
|
for (const [category, summary] of Object.entries(report.summary.byCategory)) {
|
|
1037
1045
|
console.log(` ${category}: ${summary.tokens} tokens in ${summary.files} files`);
|
|
1038
1046
|
}
|
|
1047
|
+
console.log(` Prompt cache provider: ${promptCache.provider}`);
|
|
1048
|
+
console.log(` Prompt cache strategy: ${promptCache.strategy}${promptCache.supported ? '' : ' (usage ledger only)'}`);
|
|
1049
|
+
console.log(` Cache eligible: ${promptCache.cacheEligibleTokens} tokens across ${promptCache.cacheEligiblePaths.length} paths`);
|
|
1039
1050
|
for (const recommendation of report.recommendations)
|
|
1040
1051
|
console.log(` recommendation: ${recommendation}`);
|
|
1041
1052
|
if (path)
|
|
@@ -1661,6 +1672,184 @@ const diagnose = defineCommand({
|
|
|
1661
1672
|
subCommands: { plan: diagnosePlanCommand },
|
|
1662
1673
|
});
|
|
1663
1674
|
// ============================================================================
|
|
1675
|
+
// hunt command - readonly proactive governance scan
|
|
1676
|
+
// ============================================================================
|
|
1677
|
+
function createBackgroundHunter(args) {
|
|
1678
|
+
return new BackgroundHunter({ projectDir: args.dir ? String(args.dir) : PROJECT_DIR });
|
|
1679
|
+
}
|
|
1680
|
+
const huntScanCommand = defineCommand({
|
|
1681
|
+
meta: { name: 'scan', description: 'Run a readonly proactive governance scan' },
|
|
1682
|
+
args: {
|
|
1683
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1684
|
+
changed: { type: 'boolean', default: false, description: 'Scan changed Git files only' },
|
|
1685
|
+
'changed-files': { type: 'string', description: 'Comma or newline separated file list to scan' },
|
|
1686
|
+
json: { type: 'boolean', default: false },
|
|
1687
|
+
},
|
|
1688
|
+
run({ args }) {
|
|
1689
|
+
const report = createBackgroundHunter(args).scan({
|
|
1690
|
+
changedFiles: resolveChangedFilesArg(args),
|
|
1691
|
+
});
|
|
1692
|
+
if (args.json) {
|
|
1693
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
printHuntReport(report);
|
|
1697
|
+
},
|
|
1698
|
+
});
|
|
1699
|
+
const huntReportCommand = defineCommand({
|
|
1700
|
+
meta: { name: 'report', description: 'Print open and ignored hunt findings' },
|
|
1701
|
+
args: {
|
|
1702
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1703
|
+
changed: { type: 'boolean', default: false, description: 'Scan changed Git files only' },
|
|
1704
|
+
'changed-files': { type: 'string', description: 'Comma or newline separated file list to scan' },
|
|
1705
|
+
json: { type: 'boolean', default: false },
|
|
1706
|
+
},
|
|
1707
|
+
run({ args }) {
|
|
1708
|
+
const report = createBackgroundHunter(args).scan({
|
|
1709
|
+
changedFiles: resolveChangedFilesArg(args),
|
|
1710
|
+
});
|
|
1711
|
+
if (args.json) {
|
|
1712
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
printHuntReport(report);
|
|
1716
|
+
},
|
|
1717
|
+
});
|
|
1718
|
+
const huntDiagnoseCommand = defineCommand({
|
|
1719
|
+
meta: { name: 'diagnose', description: 'Create a diagnostic loop from a hunt finding' },
|
|
1720
|
+
args: {
|
|
1721
|
+
id: { type: 'positional', required: true, description: 'Hunt finding id' },
|
|
1722
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1723
|
+
changed: { type: 'boolean', default: false, description: 'Scan changed Git files only' },
|
|
1724
|
+
'changed-files': { type: 'string', description: 'Comma or newline separated file list to scan' },
|
|
1725
|
+
json: { type: 'boolean', default: false },
|
|
1726
|
+
},
|
|
1727
|
+
run({ args }) {
|
|
1728
|
+
const report = createBackgroundHunter(args).scan({
|
|
1729
|
+
changedFiles: resolveChangedFilesArg(args),
|
|
1730
|
+
});
|
|
1731
|
+
const finding = report.findings.find(item => item.id === String(args.id));
|
|
1732
|
+
if (!finding) {
|
|
1733
|
+
console.error(`Hunt finding not found: ${String(args.id)}`);
|
|
1734
|
+
process.exitCode = 1;
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1737
|
+
const loop = createDiagnosticLoop(finding.diagnosticInput);
|
|
1738
|
+
const validation = validateDiagnosticLoop(loop);
|
|
1739
|
+
if (args.json) {
|
|
1740
|
+
console.log(JSON.stringify({ finding, loop, validation }, null, 2));
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
console.log(renderDiagnosticLoopMarkdown(loop));
|
|
1744
|
+
if (!validation.ready) {
|
|
1745
|
+
console.log('\nBlockers:');
|
|
1746
|
+
for (const blocker of validation.blockers)
|
|
1747
|
+
console.log(` - ${blocker}`);
|
|
1748
|
+
}
|
|
1749
|
+
},
|
|
1750
|
+
});
|
|
1751
|
+
const huntIgnoreCommand = defineCommand({
|
|
1752
|
+
meta: { name: 'ignore', description: 'Ignore a stable hunt finding fingerprint' },
|
|
1753
|
+
args: {
|
|
1754
|
+
id: { type: 'positional', required: true, description: 'Hunt finding id' },
|
|
1755
|
+
reason: { type: 'string', description: 'Why this finding is accepted or deferred' },
|
|
1756
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1757
|
+
changed: { type: 'boolean', default: false, description: 'Scan changed Git files only' },
|
|
1758
|
+
'changed-files': { type: 'string', description: 'Comma or newline separated file list to scan' },
|
|
1759
|
+
json: { type: 'boolean', default: false },
|
|
1760
|
+
},
|
|
1761
|
+
run({ args }) {
|
|
1762
|
+
const projectDir = args.dir ? String(args.dir) : PROJECT_DIR;
|
|
1763
|
+
const report = new BackgroundHunter({ projectDir }).scan({
|
|
1764
|
+
changedFiles: resolveChangedFilesArg(args),
|
|
1765
|
+
});
|
|
1766
|
+
const finding = report.findings.find(item => item.id === String(args.id));
|
|
1767
|
+
if (!finding) {
|
|
1768
|
+
console.error(`Hunt finding not found: ${String(args.id)}`);
|
|
1769
|
+
process.exitCode = 1;
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
const ignored = new HuntFindingStore({ projectDir }).ignore({
|
|
1773
|
+
id: finding.id,
|
|
1774
|
+
fingerprint: finding.fingerprint,
|
|
1775
|
+
reason: args.reason ? String(args.reason) : undefined,
|
|
1776
|
+
ignoredAt: new Date().toISOString(),
|
|
1777
|
+
});
|
|
1778
|
+
if (args.json) {
|
|
1779
|
+
console.log(JSON.stringify({ ignored }, null, 2));
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
console.log(`Ignored hunt finding: ${ignored.id}`);
|
|
1783
|
+
if (ignored.reason)
|
|
1784
|
+
console.log(` Reason: ${ignored.reason}`);
|
|
1785
|
+
},
|
|
1786
|
+
});
|
|
1787
|
+
const hunt = defineCommand({
|
|
1788
|
+
meta: { name: 'hunt', description: 'Readonly proactive governance scans' },
|
|
1789
|
+
subCommands: {
|
|
1790
|
+
scan: huntScanCommand,
|
|
1791
|
+
report: huntReportCommand,
|
|
1792
|
+
diagnose: huntDiagnoseCommand,
|
|
1793
|
+
ignore: huntIgnoreCommand,
|
|
1794
|
+
},
|
|
1795
|
+
});
|
|
1796
|
+
function printHuntReport(report) {
|
|
1797
|
+
console.log('SCALE Hunt Report');
|
|
1798
|
+
console.log(` Project: ${report.projectDir}`);
|
|
1799
|
+
console.log(` Open findings: ${report.summary.open}`);
|
|
1800
|
+
console.log(` Ignored findings: ${report.summary.ignored}`);
|
|
1801
|
+
console.log(` Blocking findings: ${report.summary.blocking}`);
|
|
1802
|
+
for (const finding of report.findings.slice(0, 20)) {
|
|
1803
|
+
const line = finding.line ? `:${finding.line}` : '';
|
|
1804
|
+
const status = finding.status === 'ignored' ? 'IGNORED' : finding.severity.toUpperCase();
|
|
1805
|
+
console.log(` [${status}] ${finding.id} ${finding.ruleId} ${finding.path ?? 'project'}${line}: ${finding.message}`);
|
|
1806
|
+
}
|
|
1807
|
+
if (report.findings.length > 20)
|
|
1808
|
+
console.log(` ... ${report.findings.length - 20} more finding(s)`);
|
|
1809
|
+
}
|
|
1810
|
+
// ============================================================================
|
|
1811
|
+
// dependency command - supply-chain security audit
|
|
1812
|
+
// ============================================================================
|
|
1813
|
+
const dependencyAuditCommand = defineCommand({
|
|
1814
|
+
meta: { name: 'audit', description: 'Audit lockfile-scoped dependency supply-chain risk' },
|
|
1815
|
+
args: {
|
|
1816
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1817
|
+
mode: { type: 'string', description: 'Audit mode: compatibility, strict, or offline' },
|
|
1818
|
+
'changed-packages': { type: 'string', description: 'Comma-separated package names to audit instead of direct dependencies' },
|
|
1819
|
+
json: { type: 'boolean', default: false },
|
|
1820
|
+
},
|
|
1821
|
+
run({ args }) {
|
|
1822
|
+
const mode = args.mode === 'compatibility' || args.mode === 'strict' || args.mode === 'offline'
|
|
1823
|
+
? args.mode
|
|
1824
|
+
: undefined;
|
|
1825
|
+
const report = auditDependencies({
|
|
1826
|
+
projectDir: args.dir ? String(args.dir) : PROJECT_DIR,
|
|
1827
|
+
mode,
|
|
1828
|
+
changedPackages: parseCommaList(args['changed-packages']),
|
|
1829
|
+
});
|
|
1830
|
+
if (args.json) {
|
|
1831
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1832
|
+
}
|
|
1833
|
+
else {
|
|
1834
|
+
console.log(`SCALE Dependency Audit: ${report.ok ? 'OK' : 'FAILED'}`);
|
|
1835
|
+
console.log(` Packages audited: ${report.summary.packagesAudited}`);
|
|
1836
|
+
console.log(` Findings: ${report.summary.totalFindings}`);
|
|
1837
|
+
console.log(` Mode: ${report.mode}`);
|
|
1838
|
+
for (const finding of report.findings.slice(0, 20)) {
|
|
1839
|
+
console.log(` [${finding.severity}] ${finding.ruleId} ${finding.packageName}${finding.version ? `@${finding.version}` : ''}: ${finding.message}`);
|
|
1840
|
+
}
|
|
1841
|
+
if (report.findings.length > 20)
|
|
1842
|
+
console.log(` ... ${report.findings.length - 20} more finding(s)`);
|
|
1843
|
+
}
|
|
1844
|
+
if (!report.ok)
|
|
1845
|
+
process.exitCode = 1;
|
|
1846
|
+
},
|
|
1847
|
+
});
|
|
1848
|
+
const dependency = defineCommand({
|
|
1849
|
+
meta: { name: 'dependency', description: 'Supply-chain dependency governance' },
|
|
1850
|
+
subCommands: { audit: dependencyAuditCommand },
|
|
1851
|
+
});
|
|
1852
|
+
// ============================================================================
|
|
1664
1853
|
// tdd command - vertical slice RED/GREEN/REFACTOR loop
|
|
1665
1854
|
// ============================================================================
|
|
1666
1855
|
const tddSliceCommand = defineCommand({
|
|
@@ -5084,6 +5273,8 @@ const main = defineCommand({
|
|
|
5084
5273
|
runtime,
|
|
5085
5274
|
memory,
|
|
5086
5275
|
diagnose,
|
|
5276
|
+
hunt,
|
|
5277
|
+
dependency,
|
|
5087
5278
|
tdd,
|
|
5088
5279
|
tool,
|
|
5089
5280
|
tools: tool,
|