@hongmaple0820/scale-engine 0.19.0 → 0.20.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 (43) hide show
  1. package/README.en.md +17 -3
  2. package/README.md +107 -9
  3. package/dist/api/cli.js +988 -11
  4. package/dist/api/cli.js.map +1 -1
  5. package/dist/codegraph/CodeIntelligence.d.ts +135 -0
  6. package/dist/codegraph/CodeIntelligence.js +460 -0
  7. package/dist/codegraph/CodeIntelligence.js.map +1 -0
  8. package/dist/context/ContextBudget.d.ts +90 -0
  9. package/dist/context/ContextBudget.js +322 -0
  10. package/dist/context/ContextBudget.js.map +1 -0
  11. package/dist/eval/WorkflowEval.d.ts +161 -0
  12. package/dist/eval/WorkflowEval.js +379 -0
  13. package/dist/eval/WorkflowEval.js.map +1 -0
  14. package/dist/governance/GovernanceRoi.d.ts +25 -0
  15. package/dist/governance/GovernanceRoi.js +70 -0
  16. package/dist/governance/GovernanceRoi.js.map +1 -0
  17. package/dist/governance/ProgressiveGovernance.d.ts +22 -0
  18. package/dist/governance/ProgressiveGovernance.js +159 -0
  19. package/dist/governance/ProgressiveGovernance.js.map +1 -0
  20. package/dist/memory/MemoryBrain.d.ts +135 -0
  21. package/dist/memory/MemoryBrain.js +635 -0
  22. package/dist/memory/MemoryBrain.js.map +1 -0
  23. package/dist/memory/index.d.ts +1 -0
  24. package/dist/memory/index.js +1 -0
  25. package/dist/memory/index.js.map +1 -1
  26. package/dist/output/GovernanceDashboard.d.ts +57 -0
  27. package/dist/output/GovernanceDashboard.js +250 -0
  28. package/dist/output/GovernanceDashboard.js.map +1 -0
  29. package/dist/output/index.d.ts +2 -0
  30. package/dist/output/index.js +1 -0
  31. package/dist/output/index.js.map +1 -1
  32. package/dist/skills/SkillRadar.d.ts +83 -0
  33. package/dist/skills/SkillRadar.js +384 -0
  34. package/dist/skills/SkillRadar.js.map +1 -0
  35. package/dist/workflow/GovernanceTemplates.js +194 -194
  36. package/docs/CODE_INTELLIGENCE.md +138 -0
  37. package/docs/CONTEXT_BUDGET.md +87 -0
  38. package/docs/GOVERNANCE_DASHBOARD.md +69 -0
  39. package/docs/MEMORY_BRAIN.md +104 -0
  40. package/docs/README.md +16 -8
  41. package/docs/SKILL_RADAR.md +115 -0
  42. package/docs/WORKFLOW_EVAL.md +151 -0
  43. package/package.json +7 -1
@@ -202,10 +202,10 @@ scale verify <task-id> --profile default
202
202
  scale verify <task-id> --service <service-name>
203
203
  scale verify <task-id> --artifact-gate warn
204
204
  scale verify <task-id> --artifact-gate block
205
- scale verify <task-id> --require-installed-skills
206
- scale verify <task-id> --profile productSmoke
207
- scale task-artifacts check --dir docs/worklog/tasks/<task-dir> --level L
208
- scale artifact render --task-id <task-dir> --type release-report
205
+ scale verify <task-id> --require-installed-skills
206
+ scale verify <task-id> --profile productSmoke
207
+ scale task-artifacts check --dir docs/worklog/tasks/<task-dir> --level L
208
+ scale artifact render --task-id <task-dir> --type release-report
209
209
  scale artifact doctor --task-id <task-dir>
210
210
  \`\`\`
211
211
 
@@ -301,15 +301,15 @@ Default policy:
301
301
  - unsafe HTML sinks, dynamic code execution, empty catch blocks, and type suppressions require remediation before release.
302
302
  - framework and architecture rules live in \`.scale/frameworks.json\` and module standards docs.
303
303
  - \`.scale/frameworks.json > bannedImports\` blocks direct use of deprecated ORMs, unsafe SDKs, or off-system UI components.
304
- - \`.scale/frameworks.json > lastReviewedAt/reviewIntervalDays\` warns when module framework decisions need review.
305
- - \`.scale/engineering-standards.json > blockingRules\` promotes selected warning rule IDs to release-blocking findings.
306
- - \`.scale/engineering-standards.json > allowedFindingPatterns\` allows narrow rule/path/evidence exceptions without hiding unrelated findings in the same file.
307
- - \`.scale/engineering-standards-baseline.json\` may hold known legacy findings during rollout, but normal task gates should prefer \`--changed\` or \`--changed-files\` so new work is blocked without forcing a whole-repo cleanup.
308
- - \`.scale/verification.json > policy.engineeringStandardsGate\` controls whether preflight and task verification treat standards as \`off\`, \`warn\`, or \`block\`.
309
- - \`.scale/product-smoke.json\` defines real product-path probes. Use it to prove a routed user/business flow, not only build, unit tests, or \`/health\`.
310
- - \`.scale/verification.json > policy.productSmokeGate\` controls whether missing or failed product smoke evidence warns or blocks M/L/CRITICAL delivery.
311
- - Full standards scans are for release readiness, scheduled remediation, and architecture cleanup. Changed-file scans are the default for day-to-day feature and bug branches.
312
- - Use \`scale standards baseline --write\` only during an explicit rollout or remediation planning task. It writes the machine-readable baseline and a \`standards-legacy-debt.md\` classification report for staged cleanup.
304
+ - \`.scale/frameworks.json > lastReviewedAt/reviewIntervalDays\` warns when module framework decisions need review.
305
+ - \`.scale/engineering-standards.json > blockingRules\` promotes selected warning rule IDs to release-blocking findings.
306
+ - \`.scale/engineering-standards.json > allowedFindingPatterns\` allows narrow rule/path/evidence exceptions without hiding unrelated findings in the same file.
307
+ - \`.scale/engineering-standards-baseline.json\` may hold known legacy findings during rollout, but normal task gates should prefer \`--changed\` or \`--changed-files\` so new work is blocked without forcing a whole-repo cleanup.
308
+ - \`.scale/verification.json > policy.engineeringStandardsGate\` controls whether preflight and task verification treat standards as \`off\`, \`warn\`, or \`block\`.
309
+ - \`.scale/product-smoke.json\` defines real product-path probes. Use it to prove a routed user/business flow, not only build, unit tests, or \`/health\`.
310
+ - \`.scale/verification.json > policy.productSmokeGate\` controls whether missing or failed product smoke evidence warns or blocks M/L/CRITICAL delivery.
311
+ - Full standards scans are for release readiness, scheduled remediation, and architecture cleanup. Changed-file scans are the default for day-to-day feature and bug branches.
312
+ - Use \`scale standards baseline --write\` only during an explicit rollout or remediation planning task. It writes the machine-readable baseline and a \`standards-legacy-debt.md\` classification report for staged cleanup.
313
313
 
314
314
  ## Automation Templates
315
315
 
@@ -742,67 +742,67 @@ TBD
742
742
  `;
743
743
  }
744
744
  function productSmokeTemplate() {
745
- return `# Product Smoke
746
-
747
- ## Real Product Path
748
-
749
- Describe the smallest end-to-end path that proves the change works through the real product boundary.
750
-
751
- Example:
752
-
753
- \`\`\`text
754
- UI or client -> gateway/router -> service -> database/storage/queue -> observable result
755
- \`\`\`
756
-
757
- Do not use a green health endpoint as the only proof when the user-facing path depends on routing, authentication, storage, async tasks, browser behavior, or third-party integration.
758
-
759
- ## Quick Setup
760
-
761
- 1. Open \`.scale/product-smoke.json\`.
762
- 2. Replace the example command with one real product path command.
763
- 3. Set that probe's \`enabled\` field to \`true\`.
764
- 4. Run \`scale preflight --profile productSmoke --json\`.
765
- 5. Run \`scale runtime final-check --level M --json\`.
766
-
767
- \`status: "skipped"\` means no real product path was exercised. It does not count as completion evidence.
768
-
769
- ## Setup
770
-
771
- - Base URL:
772
- - Test user or tenant:
773
- - Required fixtures:
774
- - Services that must be running:
775
-
776
- ## Smoke Commands
777
-
778
- | Command | Expected Result | Evidence Artifact |
779
- | --- | --- | --- |
780
- | TBD | TBD | TBD |
781
-
782
- ## Runtime Evidence
783
-
784
- Record at least one runtime evidence item:
785
-
786
- \`\`\`bash
787
- scale runtime record \\
788
- --kind command \\
789
- --title "Product smoke: <flow>" \\
790
- --status passed \\
791
- --command "<exact smoke command>" \\
792
- --exit-code 0 \\
793
- --summary "<business result, task id, status, or observable output>" \\
794
- --artifacts ".agent/logs/<service>/<smoke>.json" \\
795
- --metadata-json '{"productSmoke":true,"realProductPath":true}'
796
- \`\`\`
797
-
798
- ## Assertions
799
-
800
- - [ ] Request crossed the real product boundary, not only an isolated unit.
801
- - [ ] Authentication or user identity path was exercised when relevant.
802
- - [ ] Persistence/storage/queue side effect was verified when relevant.
803
- - [ ] Async task or eventual state was polled to terminal status when relevant.
804
- - [ ] Failure output is specific enough to diagnose the failing layer.
805
- - [ ] Runtime artifacts are ignored or deliberately promoted according to resource governance.
745
+ return `# Product Smoke
746
+
747
+ ## Real Product Path
748
+
749
+ Describe the smallest end-to-end path that proves the change works through the real product boundary.
750
+
751
+ Example:
752
+
753
+ \`\`\`text
754
+ UI or client -> gateway/router -> service -> database/storage/queue -> observable result
755
+ \`\`\`
756
+
757
+ Do not use a green health endpoint as the only proof when the user-facing path depends on routing, authentication, storage, async tasks, browser behavior, or third-party integration.
758
+
759
+ ## Quick Setup
760
+
761
+ 1. Open \`.scale/product-smoke.json\`.
762
+ 2. Replace the example command with one real product path command.
763
+ 3. Set that probe's \`enabled\` field to \`true\`.
764
+ 4. Run \`scale preflight --profile productSmoke --json\`.
765
+ 5. Run \`scale runtime final-check --level M --json\`.
766
+
767
+ \`status: "skipped"\` means no real product path was exercised. It does not count as completion evidence.
768
+
769
+ ## Setup
770
+
771
+ - Base URL:
772
+ - Test user or tenant:
773
+ - Required fixtures:
774
+ - Services that must be running:
775
+
776
+ ## Smoke Commands
777
+
778
+ | Command | Expected Result | Evidence Artifact |
779
+ | --- | --- | --- |
780
+ | TBD | TBD | TBD |
781
+
782
+ ## Runtime Evidence
783
+
784
+ Record at least one runtime evidence item:
785
+
786
+ \`\`\`bash
787
+ scale runtime record \\
788
+ --kind command \\
789
+ --title "Product smoke: <flow>" \\
790
+ --status passed \\
791
+ --command "<exact smoke command>" \\
792
+ --exit-code 0 \\
793
+ --summary "<business result, task id, status, or observable output>" \\
794
+ --artifacts ".agent/logs/<service>/<smoke>.json" \\
795
+ --metadata-json '{"productSmoke":true,"realProductPath":true}'
796
+ \`\`\`
797
+
798
+ ## Assertions
799
+
800
+ - [ ] Request crossed the real product boundary, not only an isolated unit.
801
+ - [ ] Authentication or user identity path was exercised when relevant.
802
+ - [ ] Persistence/storage/queue side effect was verified when relevant.
803
+ - [ ] Async task or eventual state was polled to terminal status when relevant.
804
+ - [ ] Failure output is specific enough to diagnose the failing layer.
805
+ - [ ] Runtime artifacts are ignored or deliberately promoted according to resource governance.
806
806
  `;
807
807
  }
808
808
  function planTemplate() {
@@ -983,132 +983,132 @@ function productSmokeConfigTemplate(mode) {
983
983
  }, null, 2) + '\n';
984
984
  }
985
985
  function productSmokePowerShellScript() {
986
- return `# Product smoke probe runner generated by scale-engine.
987
- $ErrorActionPreference = "Stop"
988
-
989
- $Root = (Resolve-Path (Join-Path $PSScriptRoot "..\\..")).Path
990
- $ConfigPath = Join-Path $Root ".scale\\product-smoke.json"
991
- $LogDir = Join-Path $Root ".agent\\logs"
992
- $LogPath = Join-Path $LogDir "product-smoke.json"
993
-
994
- New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
995
-
996
- $NodeProgram = @'
997
- ${productSmokeNodeProgram()}
998
- '@
999
-
1000
- $TempFile = [System.IO.Path]::GetTempFileName() + ".js"
1001
- Set-Content -Path $TempFile -Value $NodeProgram -Encoding UTF8
1002
- try {
1003
- node $TempFile $ConfigPath $LogPath
1004
- exit $LASTEXITCODE
1005
- } finally {
1006
- Remove-Item -Force $TempFile -ErrorAction SilentlyContinue
1007
- }
986
+ return `# Product smoke probe runner generated by scale-engine.
987
+ $ErrorActionPreference = "Stop"
988
+
989
+ $Root = (Resolve-Path (Join-Path $PSScriptRoot "..\\..")).Path
990
+ $ConfigPath = Join-Path $Root ".scale\\product-smoke.json"
991
+ $LogDir = Join-Path $Root ".agent\\logs"
992
+ $LogPath = Join-Path $LogDir "product-smoke.json"
993
+
994
+ New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
995
+
996
+ $NodeProgram = @'
997
+ ${productSmokeNodeProgram()}
998
+ '@
999
+
1000
+ $TempFile = [System.IO.Path]::GetTempFileName() + ".js"
1001
+ Set-Content -Path $TempFile -Value $NodeProgram -Encoding UTF8
1002
+ try {
1003
+ node $TempFile $ConfigPath $LogPath
1004
+ exit $LASTEXITCODE
1005
+ } finally {
1006
+ Remove-Item -Force $TempFile -ErrorAction SilentlyContinue
1007
+ }
1008
1008
  `;
1009
1009
  }
1010
1010
  function productSmokeShellScript() {
1011
- return `#!/usr/bin/env sh
1012
- set -eu
1013
-
1014
- ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
1015
- CONFIG_PATH="$ROOT/.scale/product-smoke.json"
1016
- LOG_DIR="$ROOT/.agent/logs"
1017
- LOG_PATH="$LOG_DIR/product-smoke.json"
1018
-
1019
- mkdir -p "$LOG_DIR"
1020
-
1021
- node - "$CONFIG_PATH" "$LOG_PATH" <<'NODE'
1022
- ${productSmokeNodeProgram()}
1023
- NODE
1011
+ return `#!/usr/bin/env sh
1012
+ set -eu
1013
+
1014
+ ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
1015
+ CONFIG_PATH="$ROOT/.scale/product-smoke.json"
1016
+ LOG_DIR="$ROOT/.agent/logs"
1017
+ LOG_PATH="$LOG_DIR/product-smoke.json"
1018
+
1019
+ mkdir -p "$LOG_DIR"
1020
+
1021
+ node - "$CONFIG_PATH" "$LOG_PATH" <<'NODE'
1022
+ ${productSmokeNodeProgram()}
1023
+ NODE
1024
1024
  `;
1025
1025
  }
1026
1026
  function productSmokeNodeProgram() {
1027
- return `const fs = require('fs');
1028
- const cp = require('child_process');
1029
- const path = require('path');
1030
-
1031
- const configPath = process.argv[2];
1032
- const logPath = process.argv[3];
1033
-
1034
- function writeReport(report) {
1035
- fs.mkdirSync(path.dirname(logPath), { recursive: true });
1036
- fs.writeFileSync(logPath, JSON.stringify(report, null, 2) + '\\n', 'utf8');
1037
- process.stdout.write(JSON.stringify(report, null, 2) + '\\n');
1038
- }
1039
-
1040
- if (!fs.existsSync(configPath)) {
1041
- writeReport({
1042
- version: 1,
1043
- status: 'failed',
1044
- verifiedAt: new Date().toISOString(),
1045
- message: 'Missing .scale/product-smoke.json',
1046
- results: []
1047
- });
1048
- process.exit(1);
1049
- }
1050
-
1051
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8').replace(/^\\uFEFF/, ''));
1052
- const probes = Array.isArray(config.probes) ? config.probes.filter(probe => probe && probe.enabled === true) : [];
1053
-
1054
- if (probes.length === 0) {
1055
- const status = config.emptyProbeBehavior === 'block' ? 'failed' : 'skipped';
1056
- writeReport({
1057
- version: 1,
1058
- status,
1059
- verifiedAt: new Date().toISOString(),
1060
- message: 'No enabled product smoke probes. Enable probes in .scale/product-smoke.json after defining the real product path.',
1061
- results: []
1062
- });
1063
- process.exit(status === 'failed' ? 1 : 0);
1064
- }
1065
-
1066
- const results = probes.map((probe) => {
1067
- const startedAt = new Date().toISOString();
1068
- const expectedExitCode = Number.isInteger(probe.expected && probe.expected.exitCode) ? probe.expected.exitCode : 0;
1069
- const command = String(probe.command || '');
1070
- if (!command.trim()) {
1071
- return {
1072
- id: String(probe.id || 'unnamed-probe'),
1073
- description: String(probe.description || ''),
1074
- command,
1075
- expectedExitCode,
1076
- exitCode: 1,
1077
- status: 'failed',
1078
- startedAt,
1079
- endedAt: new Date().toISOString(),
1080
- outputTail: 'Probe command is empty'
1081
- };
1082
- }
1083
- const result = cp.spawnSync(command, {
1084
- cwd: process.cwd(),
1085
- shell: true,
1086
- encoding: 'utf8',
1087
- timeout: Number(config.timeoutMs || 180000)
1088
- });
1089
- const output = String(result.stdout || '') + String(result.stderr || '') + String(result.error ? result.error.message : '');
1090
- const exitCode = typeof result.status === 'number' ? result.status : 1;
1091
- return {
1092
- id: String(probe.id || 'unnamed-probe'),
1093
- description: String(probe.description || ''),
1094
- command,
1095
- expectedExitCode,
1096
- exitCode,
1097
- status: exitCode === expectedExitCode ? 'passed' : 'failed',
1098
- startedAt,
1099
- endedAt: new Date().toISOString(),
1100
- outputTail: output.length > 2000 ? output.slice(-2000) : output
1101
- };
1102
- });
1103
-
1104
- const failed = results.filter(result => result.status !== 'passed');
1105
- writeReport({
1106
- version: 1,
1107
- status: failed.length === 0 ? 'passed' : 'failed',
1108
- verifiedAt: new Date().toISOString(),
1109
- results
1110
- });
1111
- process.exit(failed.length === 0 ? 0 : 1);
1027
+ return `const fs = require('fs');
1028
+ const cp = require('child_process');
1029
+ const path = require('path');
1030
+
1031
+ const configPath = process.argv[2];
1032
+ const logPath = process.argv[3];
1033
+
1034
+ function writeReport(report) {
1035
+ fs.mkdirSync(path.dirname(logPath), { recursive: true });
1036
+ fs.writeFileSync(logPath, JSON.stringify(report, null, 2) + '\\n', 'utf8');
1037
+ process.stdout.write(JSON.stringify(report, null, 2) + '\\n');
1038
+ }
1039
+
1040
+ if (!fs.existsSync(configPath)) {
1041
+ writeReport({
1042
+ version: 1,
1043
+ status: 'failed',
1044
+ verifiedAt: new Date().toISOString(),
1045
+ message: 'Missing .scale/product-smoke.json',
1046
+ results: []
1047
+ });
1048
+ process.exit(1);
1049
+ }
1050
+
1051
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8').replace(/^\\uFEFF/, ''));
1052
+ const probes = Array.isArray(config.probes) ? config.probes.filter(probe => probe && probe.enabled === true) : [];
1053
+
1054
+ if (probes.length === 0) {
1055
+ const status = config.emptyProbeBehavior === 'block' ? 'failed' : 'skipped';
1056
+ writeReport({
1057
+ version: 1,
1058
+ status,
1059
+ verifiedAt: new Date().toISOString(),
1060
+ message: 'No enabled product smoke probes. Enable probes in .scale/product-smoke.json after defining the real product path.',
1061
+ results: []
1062
+ });
1063
+ process.exit(status === 'failed' ? 1 : 0);
1064
+ }
1065
+
1066
+ const results = probes.map((probe) => {
1067
+ const startedAt = new Date().toISOString();
1068
+ const expectedExitCode = Number.isInteger(probe.expected && probe.expected.exitCode) ? probe.expected.exitCode : 0;
1069
+ const command = String(probe.command || '');
1070
+ if (!command.trim()) {
1071
+ return {
1072
+ id: String(probe.id || 'unnamed-probe'),
1073
+ description: String(probe.description || ''),
1074
+ command,
1075
+ expectedExitCode,
1076
+ exitCode: 1,
1077
+ status: 'failed',
1078
+ startedAt,
1079
+ endedAt: new Date().toISOString(),
1080
+ outputTail: 'Probe command is empty'
1081
+ };
1082
+ }
1083
+ const result = cp.spawnSync(command, {
1084
+ cwd: process.cwd(),
1085
+ shell: true,
1086
+ encoding: 'utf8',
1087
+ timeout: Number(config.timeoutMs || 180000)
1088
+ });
1089
+ const output = String(result.stdout || '') + String(result.stderr || '') + String(result.error ? result.error.message : '');
1090
+ const exitCode = typeof result.status === 'number' ? result.status : 1;
1091
+ return {
1092
+ id: String(probe.id || 'unnamed-probe'),
1093
+ description: String(probe.description || ''),
1094
+ command,
1095
+ expectedExitCode,
1096
+ exitCode,
1097
+ status: exitCode === expectedExitCode ? 'passed' : 'failed',
1098
+ startedAt,
1099
+ endedAt: new Date().toISOString(),
1100
+ outputTail: output.length > 2000 ? output.slice(-2000) : output
1101
+ };
1102
+ });
1103
+
1104
+ const failed = results.filter(result => result.status !== 'passed');
1105
+ writeReport({
1106
+ version: 1,
1107
+ status: failed.length === 0 ? 'passed' : 'failed',
1108
+ verifiedAt: new Date().toISOString(),
1109
+ results
1110
+ });
1111
+ process.exit(failed.length === 0 ? 0 : 1);
1112
1112
  `;
1113
1113
  }
1114
1114
  function packageVersion() {
@@ -0,0 +1,138 @@
1
+ # Code Intelligence
2
+
3
+ SCALE uses an adapter-first code intelligence layer. It can consume external code graph tools when they exist, read graph artifacts such as Graphify outputs, and fall back to a scoped internal source scan when no provider is available.
4
+
5
+ The goal is not to replace IDE indexing. The goal is to make exploration measurable:
6
+
7
+ - which provider answered the query
8
+ - whether fallback was used
9
+ - which files are likely relevant
10
+ - how many file reads were avoided
11
+ - what confidence the result has
12
+
13
+ ## Quick Start
14
+
15
+ Create the optional provider configuration:
16
+
17
+ ```bash
18
+ scale codegraph init
19
+ ```
20
+
21
+ Inspect provider availability:
22
+
23
+ ```bash
24
+ scale codegraph status
25
+ scale codegraph status --json
26
+ ```
27
+
28
+ Query code intelligence:
29
+
30
+ ```bash
31
+ scale codegraph query "UserService.create"
32
+ scale codegraph impact --symbol UserService.create
33
+ scale codegraph context --symbol UserService.create --budget 2000
34
+ scale codegraph roi --symbol UserService.create
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ The configuration file lives at:
40
+
41
+ ```text
42
+ .scale/code-intelligence.json
43
+ ```
44
+
45
+ Default shape:
46
+
47
+ ```json
48
+ {
49
+ "version": "1.0",
50
+ "providers": [
51
+ {
52
+ "id": "codegraph",
53
+ "type": "external-cli",
54
+ "enabled": true,
55
+ "command": "codegraph",
56
+ "capabilities": ["symbols", "callers", "callees", "impact", "context"]
57
+ },
58
+ {
59
+ "id": "graphify",
60
+ "type": "artifact",
61
+ "enabled": true,
62
+ "manifest": "graphify-out/GRAPH_REPORT.md",
63
+ "capabilities": ["summary", "module-map", "context"]
64
+ }
65
+ ],
66
+ "fallback": {
67
+ "enabled": true,
68
+ "tools": ["internal-scan", "rg", "read"]
69
+ }
70
+ }
71
+ ```
72
+
73
+ ## Provider Types
74
+
75
+ | Type | Use |
76
+ | --- | --- |
77
+ | `external-cli` | Detects an installed external code graph command. SCALE does not auto-install it. The first version treats this as availability evidence until a stable command contract is configured. |
78
+ | `artifact` | Reads a local graph manifest or report file. JSON manifests can provide symbol impact data. |
79
+ | fallback | Uses a bounded internal source scan when providers are unavailable or return no hits. |
80
+
81
+ ## JSON Artifact Provider
82
+
83
+ Artifact providers can point at a JSON manifest:
84
+
85
+ ```json
86
+ {
87
+ "symbols": [
88
+ {
89
+ "name": "UserService.create",
90
+ "file": "src/user.ts",
91
+ "callers": ["src/api.ts"],
92
+ "callees": ["src/db.ts"]
93
+ }
94
+ ],
95
+ "files": [
96
+ {
97
+ "path": "src/user.ts",
98
+ "symbols": ["UserService.create"]
99
+ }
100
+ ]
101
+ }
102
+ ```
103
+
104
+ This allows SCALE to answer impact queries without reading the whole repository.
105
+
106
+ ## ROI Metrics
107
+
108
+ Code intelligence reports include:
109
+
110
+ | Metric | Meaning |
111
+ | --- | --- |
112
+ | `graphHits` | Number of hits from graph providers. |
113
+ | `fallbackCount` | Whether fallback was needed. |
114
+ | `baselineFileReads` | Estimated broad exploration file reads. |
115
+ | `recommendedFileReads` | Scoped file reads recommended by the query result. |
116
+ | `fileReadsSaved` | Estimated avoided reads. |
117
+ | `toolCallsSaved` | Estimated avoided exploration tool calls. |
118
+
119
+ These numbers are deliberately conservative. They are a local signal for whether graph-assisted exploration is worth keeping default for a task class.
120
+
121
+ ## Governance ROI
122
+
123
+ `scale governance roi` can include code intelligence:
124
+
125
+ ```bash
126
+ scale governance roi --symbol UserService.create
127
+ scale governance roi --code-query createUser
128
+ ```
129
+
130
+ When a graph provider answers, the module is reported as measured evidence. When fallback is used, the module is reported as estimated and needs more evidence before becoming a stronger default.
131
+
132
+ ## Policy
133
+
134
+ - SCALE must run when no code graph provider is installed.
135
+ - Missing providers must produce explicit fallback, not silent success.
136
+ - External tools are detected but not installed automatically.
137
+ - Source files are read only through a bounded fallback scan.
138
+ - Large generated graph outputs should stay outside default prompt context; use summaries and file paths.
@@ -0,0 +1,87 @@
1
+ # Context Budget And Progressive Governance
2
+
3
+ Status: implemented baseline
4
+ Since: v0.20 development branch
5
+
6
+ This feature keeps SCALE from becoming its own context pollution source. It separates always-loaded rules from on-demand documents, runtime evidence, historical archives, and generated artifacts.
7
+
8
+ ## Commands
9
+
10
+ Report token cost by context category:
11
+
12
+ ```bash
13
+ scale context budget --json
14
+ ```
15
+
16
+ Write the report to `.scale/context-budget.json`:
17
+
18
+ ```bash
19
+ scale context budget --write
20
+ ```
21
+
22
+ Check thresholds:
23
+
24
+ ```bash
25
+ scale context doctor --max-always 2500 --max-task 8000
26
+ ```
27
+
28
+ Build a lazy-loaded task context pack:
29
+
30
+ ```bash
31
+ scale context pack \
32
+ --task "Review frontend route with browser evidence" \
33
+ --level L \
34
+ --files src/routes/upload.tsx \
35
+ --budget 4000 \
36
+ --json
37
+ ```
38
+
39
+ Evaluate progressive governance mode:
40
+
41
+ ```bash
42
+ scale governance mode \
43
+ --task "Change auth permissions and database migration" \
44
+ --files src/auth/user.ts,migrations/001.sql \
45
+ --requested-mode minimal \
46
+ --json
47
+ ```
48
+
49
+ Report governance benefit and overhead:
50
+
51
+ ```bash
52
+ scale governance roi \
53
+ --task-id TASK-123 \
54
+ --task "Review frontend route with browser evidence" \
55
+ --files src/routes/upload.tsx \
56
+ --json
57
+ ```
58
+
59
+ ## Categories
60
+
61
+ | Category | Meaning | Loading Policy |
62
+ | --- | --- | --- |
63
+ | `always` | Tiny entrypoint rules and source-of-truth governance config | Keep under strict token budget |
64
+ | `on-demand` | Domain docs and governance guides | Load only when task trigger matches |
65
+ | `evidence` | Runtime evidence and task artifacts | Summarize and reference by path |
66
+ | `archive` | Historical plans and old roadmap context | Do not load unless explicitly requested |
67
+ | `generated` | HTML reports, screenshots, graph outputs, generated artifacts | Keep manifest-only by default |
68
+
69
+ ## Progressive Governance
70
+
71
+ SCALE now has a baseline risk classifier. It keeps low-risk documentation work in `minimal` mode and escalates risky tasks to `standard`, `expanded`, or `critical`.
72
+
73
+ Examples:
74
+
75
+ | Signal | Mode |
76
+ | --- | --- |
77
+ | README typo | `minimal` |
78
+ | normal implementation task | `standard` |
79
+ | UI, browser, E2E, public interface, or cross-module work | `expanded` |
80
+ | auth, permission, secret, database, migration, production config, release, or destructive operation | `critical` |
81
+
82
+ This is not a replacement for verification. It only decides which governance behavior should activate.
83
+
84
+ ## Governance ROI
85
+
86
+ `scale governance roi` reports both benefit and overhead. Early ROI is estimated from context budget and risk signals. Later versions should replace estimates with measured eval data such as file reads saved, tool calls saved, fix iterations reduced, and human corrections avoided.
87
+