@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.
Files changed (64) hide show
  1. package/dist/api/cli.js +192 -1
  2. package/dist/api/cli.js.map +1 -1
  3. package/dist/dashboard/MetricsAggregator.d.ts +38 -0
  4. package/dist/dashboard/MetricsAggregator.js +99 -0
  5. package/dist/dashboard/MetricsAggregator.js.map +1 -0
  6. package/dist/dashboard/index.d.ts +2 -0
  7. package/dist/dashboard/index.js +1 -0
  8. package/dist/dashboard/index.js.map +1 -1
  9. package/dist/dashboard/server.js +1 -1
  10. package/dist/dashboard/server.js.map +1 -1
  11. package/dist/evolution/AutoDefectCreator.d.ts +11 -2
  12. package/dist/evolution/AutoDefectCreator.js +46 -2
  13. package/dist/evolution/AutoDefectCreator.js.map +1 -1
  14. package/dist/evolution/EvolutionEngine.d.ts +3 -0
  15. package/dist/evolution/EvolutionEngine.js +18 -2
  16. package/dist/evolution/EvolutionEngine.js.map +1 -1
  17. package/dist/evolution/RuleMaturity.d.ts +39 -0
  18. package/dist/evolution/RuleMaturity.js +70 -0
  19. package/dist/evolution/RuleMaturity.js.map +1 -0
  20. package/dist/guardrails/ActiveRedTeam.d.ts +46 -0
  21. package/dist/guardrails/ActiveRedTeam.js +203 -0
  22. package/dist/guardrails/ActiveRedTeam.js.map +1 -0
  23. package/dist/guardrails/DependencyAuditor.d.ts +68 -0
  24. package/dist/guardrails/DependencyAuditor.js +331 -0
  25. package/dist/guardrails/DependencyAuditor.js.map +1 -0
  26. package/dist/hooks/HookGeneratorEnhanced.js +18 -18
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.js +5 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/output/GovernanceDashboard.d.ts +2 -0
  31. package/dist/output/GovernanceDashboard.js +31 -0
  32. package/dist/output/GovernanceDashboard.js.map +1 -1
  33. package/dist/routing/PromptCachePolicy.d.ts +37 -0
  34. package/dist/routing/PromptCachePolicy.js +97 -0
  35. package/dist/routing/PromptCachePolicy.js.map +1 -0
  36. package/dist/runtime/ModelUsageLedger.d.ts +50 -0
  37. package/dist/runtime/ModelUsageLedger.js +92 -0
  38. package/dist/runtime/ModelUsageLedger.js.map +1 -0
  39. package/dist/runtime/index.d.ts +1 -0
  40. package/dist/runtime/index.js +1 -0
  41. package/dist/runtime/index.js.map +1 -1
  42. package/dist/workflow/autonomous/BackgroundHunter.d.ts +74 -0
  43. package/dist/workflow/autonomous/BackgroundHunter.js +220 -0
  44. package/dist/workflow/autonomous/BackgroundHunter.js.map +1 -0
  45. package/dist/workflow/autonomous/index.d.ts +1 -0
  46. package/dist/workflow/autonomous/index.js +1 -0
  47. package/dist/workflow/autonomous/index.js.map +1 -1
  48. package/dist/workflow/gates/GateSystem.d.ts +10 -0
  49. package/dist/workflow/gates/GateSystem.js +62 -0
  50. package/dist/workflow/gates/GateSystem.js.map +1 -1
  51. package/dist/workflow/gates/VisualGate.d.ts +41 -0
  52. package/dist/workflow/gates/VisualGate.js +174 -0
  53. package/dist/workflow/gates/VisualGate.js.map +1 -0
  54. package/dist/workflow/index.d.ts +1 -0
  55. package/dist/workflow/index.js +1 -0
  56. package/dist/workflow/index.js.map +1 -1
  57. package/docs/ACTIVE_SECURITY_VISUAL_GATES.md +87 -0
  58. package/docs/BACKGROUND_HUNTER.md +62 -0
  59. package/docs/CONTEXT_BUDGET.md +32 -6
  60. package/docs/DEPENDENCY_AUDIT.md +89 -0
  61. package/docs/EVOLUTION_SHADOW_MODE.md +63 -0
  62. package/docs/GOVERNANCE_DASHBOARD.md +21 -5
  63. package/docs/README.md +22 -12
  64. 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,