@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.
- package/README.en.md +17 -3
- package/README.md +107 -9
- package/dist/api/cli.js +988 -11
- package/dist/api/cli.js.map +1 -1
- package/dist/codegraph/CodeIntelligence.d.ts +135 -0
- package/dist/codegraph/CodeIntelligence.js +460 -0
- package/dist/codegraph/CodeIntelligence.js.map +1 -0
- package/dist/context/ContextBudget.d.ts +90 -0
- package/dist/context/ContextBudget.js +322 -0
- package/dist/context/ContextBudget.js.map +1 -0
- package/dist/eval/WorkflowEval.d.ts +161 -0
- package/dist/eval/WorkflowEval.js +379 -0
- package/dist/eval/WorkflowEval.js.map +1 -0
- package/dist/governance/GovernanceRoi.d.ts +25 -0
- package/dist/governance/GovernanceRoi.js +70 -0
- package/dist/governance/GovernanceRoi.js.map +1 -0
- package/dist/governance/ProgressiveGovernance.d.ts +22 -0
- package/dist/governance/ProgressiveGovernance.js +159 -0
- package/dist/governance/ProgressiveGovernance.js.map +1 -0
- package/dist/memory/MemoryBrain.d.ts +135 -0
- package/dist/memory/MemoryBrain.js +635 -0
- package/dist/memory/MemoryBrain.js.map +1 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +1 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/output/GovernanceDashboard.d.ts +57 -0
- package/dist/output/GovernanceDashboard.js +250 -0
- package/dist/output/GovernanceDashboard.js.map +1 -0
- package/dist/output/index.d.ts +2 -0
- package/dist/output/index.js +1 -0
- package/dist/output/index.js.map +1 -1
- package/dist/skills/SkillRadar.d.ts +83 -0
- package/dist/skills/SkillRadar.js +384 -0
- package/dist/skills/SkillRadar.js.map +1 -0
- package/dist/workflow/GovernanceTemplates.js +194 -194
- package/docs/CODE_INTELLIGENCE.md +138 -0
- package/docs/CONTEXT_BUDGET.md +87 -0
- package/docs/GOVERNANCE_DASHBOARD.md +69 -0
- package/docs/MEMORY_BRAIN.md +104 -0
- package/docs/README.md +16 -8
- package/docs/SKILL_RADAR.md +115 -0
- package/docs/WORKFLOW_EVAL.md +151 -0
- 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
|
+
|