@hongmaple0820/scale-engine 0.21.1 ā 0.23.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 +39 -13
- package/README.md +61 -31
- package/dist/api/cli.js +291 -4
- package/dist/api/cli.js.map +1 -1
- package/dist/api/doctor.d.ts +1 -0
- package/dist/api/doctor.js +83 -0
- package/dist/api/doctor.js.map +1 -1
- package/dist/artifact/types.d.ts +1 -1
- package/dist/artifact/types.js.map +1 -1
- package/dist/cli/phaseCommands.js +25 -6
- package/dist/cli/phaseCommands.js.map +1 -1
- package/dist/cli/runCommand.d.ts +39 -0
- package/dist/cli/runCommand.js +113 -0
- package/dist/cli/runCommand.js.map +1 -0
- package/dist/config/profiles.d.ts +52 -0
- package/dist/config/profiles.js +162 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/context/ContextBudget.d.ts +25 -1
- package/dist/context/ContextBudget.js +72 -7
- package/dist/context/ContextBudget.js.map +1 -1
- package/dist/context/ProjectAnatomy.d.ts +18 -0
- package/dist/context/ProjectAnatomy.js +287 -0
- package/dist/context/ProjectAnatomy.js.map +1 -0
- package/dist/dashboard/DashboardServer.d.ts +3 -0
- package/dist/dashboard/DashboardServer.js +114 -0
- package/dist/dashboard/DashboardServer.js.map +1 -1
- package/dist/hooks/BugPatternDetector.d.ts +36 -0
- package/dist/hooks/BugPatternDetector.js +207 -0
- package/dist/hooks/BugPatternDetector.js.map +1 -0
- package/dist/hooks/HookGeneratorEnhanced.js +301 -5
- package/dist/hooks/HookGeneratorEnhanced.js.map +1 -1
- package/dist/hooks/WorkflowHooksManager.js +24 -0
- package/dist/hooks/WorkflowHooksManager.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge/CerebrumManager.d.ts +25 -0
- package/dist/knowledge/CerebrumManager.js +127 -0
- package/dist/knowledge/CerebrumManager.js.map +1 -0
- package/dist/knowledge/SQLiteKnowledgeBase.d.ts +1 -0
- package/dist/knowledge/SQLiteKnowledgeBase.js +31 -3
- package/dist/knowledge/SQLiteKnowledgeBase.js.map +1 -1
- package/dist/knowledge/TfidfIndex.d.ts +50 -0
- package/dist/knowledge/TfidfIndex.js +177 -0
- package/dist/knowledge/TfidfIndex.js.map +1 -0
- package/dist/skills/SkillDiscovery.js +1 -1
- package/dist/skills/SkillDiscovery.js.map +1 -1
- package/dist/tools/CommandOutputCompressor.d.ts +28 -0
- package/dist/tools/CommandOutputCompressor.js +242 -0
- package/dist/tools/CommandOutputCompressor.js.map +1 -0
- package/dist/tools/CommandRunLedger.d.ts +77 -0
- package/dist/tools/CommandRunLedger.js +111 -0
- package/dist/tools/CommandRunLedger.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/workflow/EngineeringStandards.js +91 -2
- package/dist/workflow/EngineeringStandards.js.map +1 -1
- package/dist/workflow/GovernanceTemplatePacks.js +2 -2
- package/dist/workflow/GovernanceTemplates.js +90 -89
- package/dist/workflow/GovernanceTemplates.js.map +1 -1
- package/dist/workflow/TaskLevelDetector.d.ts +41 -0
- package/dist/workflow/TaskLevelDetector.js +219 -0
- package/dist/workflow/TaskLevelDetector.js.map +1 -0
- package/dist/workflow/WorkflowOrchestrator.d.ts +59 -0
- package/dist/workflow/WorkflowOrchestrator.js +326 -0
- package/dist/workflow/WorkflowOrchestrator.js.map +1 -0
- package/dist/workflow/WorkspaceLifecycle.d.ts +19 -1
- package/dist/workflow/WorkspaceLifecycle.js +119 -3
- package/dist/workflow/WorkspaceLifecycle.js.map +1 -1
- package/dist/workflow/WorkspaceTopology.d.ts +6 -0
- package/dist/workflow/WorkspaceTopology.js +17 -6
- package/dist/workflow/WorkspaceTopology.js.map +1 -1
- package/dist/workflow/gates/GateSystem.d.ts +23 -6
- package/dist/workflow/gates/GateSystem.js +114 -25
- package/dist/workflow/gates/GateSystem.js.map +1 -1
- package/dist/workflow/gates/MetaGovernanceGates.d.ts +70 -0
- package/dist/workflow/gates/MetaGovernanceGates.js +617 -0
- package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -0
- package/dist/workflow/types.d.ts +6 -1
- package/docs/GITLAB_FLOW.md +125 -0
- package/docs/README.md +3 -0
- package/docs/start/README.md +29 -3
- package/docs/start/artifact-lifecycle.md +326 -0
- package/docs/start/workflow-upgrade.md +150 -0
- package/image/wechat-public.jpg +0 -0
- package/image/wxPay.jpg +0 -0
- package/image/zfb.jpg +0 -0
- package/package.json +10 -8
package/dist/api/cli.js
CHANGED
|
@@ -11,7 +11,9 @@ import { BruteRetryDetector, PrematureDoneDetector, BlameShiftDetector } from '.
|
|
|
11
11
|
import { DangerousCommandDetector, SecretLeakDetector, RoleGateDetector, ScopeCreepDetector, BUILT_IN_ROLES } from '../guardrails/advancedDetectors.js';
|
|
12
12
|
import { SQLiteKnowledgeBase } from '../knowledge/SQLiteKnowledgeBase.js';
|
|
13
13
|
import { ContextBuilder } from '../context/ContextBuilder.js';
|
|
14
|
+
import { ProjectAnatomy } from '../context/ProjectAnatomy.js';
|
|
14
15
|
import { buildContextPack, doctorContextBudget, scanContextBudget, writeContextBudgetReport, } from '../context/ContextBudget.js';
|
|
16
|
+
import { CerebrumManager } from '../knowledge/CerebrumManager.js';
|
|
15
17
|
import { buildCodeGraphContext, createCodeGraphRoiReport, impactCodeGraph, inspectCodeIntelligence, queryCodeGraph, writeCodeIntelligenceConfig, } from '../codegraph/CodeIntelligence.js';
|
|
16
18
|
import { WorkflowEvalStore, compareWorkflowEvalRuns, renderWorkflowEvalReport, runWorkflowEvalSuite, } from '../eval/WorkflowEval.js';
|
|
17
19
|
import { FSMAgentBridge } from '../fsm/FSMAgentBridge.js';
|
|
@@ -36,6 +38,7 @@ import { ReviewStore } from '../workflow/ReviewStore.js';
|
|
|
36
38
|
import { WorkflowEngine } from '../workflow/WorkflowEngine.js';
|
|
37
39
|
import { resolveVerificationTargets, } from '../workflow/VerificationProfile.js';
|
|
38
40
|
import { writeGovernanceTemplates } from '../workflow/GovernanceTemplates.js';
|
|
41
|
+
import { getProfile as getConfigProfile, generateConfigForProfile, listProfiles as listConfigProfiles } from '../config/profiles.js';
|
|
39
42
|
import { computeGovernanceDrift } from '../workflow/GovernanceLock.js';
|
|
40
43
|
import { applyUpgradePlan, createThirdPartyUpdateReport, createUpgradeCheckReport, createUpgradePlanReport, rollbackLatestUpgrade, writeUpgradePlanHtml, } from '../workflow/UpgradeManager.js';
|
|
41
44
|
import { createGovernanceRoiReport } from '../governance/GovernanceRoi.js';
|
|
@@ -79,6 +82,19 @@ function governanceModeFromScenario(scenario) {
|
|
|
79
82
|
return 'minimal';
|
|
80
83
|
return 'standard';
|
|
81
84
|
}
|
|
85
|
+
function profileFromScenario(scenario) {
|
|
86
|
+
if (scenario === 'sandbox')
|
|
87
|
+
return 'minimal';
|
|
88
|
+
if (scenario === 'critical')
|
|
89
|
+
return 'advanced';
|
|
90
|
+
return 'standard';
|
|
91
|
+
}
|
|
92
|
+
function writeConfigYaml(projectDir, profileId, projectName, agents) {
|
|
93
|
+
const configPath = join(projectDir, '.scale', 'config.yaml');
|
|
94
|
+
const content = generateConfigForProfile(profileId, { name: projectName, agents });
|
|
95
|
+
writeFileSync(configPath, content, 'utf-8');
|
|
96
|
+
return configPath;
|
|
97
|
+
}
|
|
82
98
|
function ensureDir(dir) {
|
|
83
99
|
if (!existsSync(dir))
|
|
84
100
|
mkdirSync(dir, { recursive: true });
|
|
@@ -346,6 +362,60 @@ const gate = defineCommand({
|
|
|
346
362
|
subCommands: { 'pre-tool': gatePreTool, 'post-tool': gatePostTool, 'before-stop': gateBeforeStop },
|
|
347
363
|
});
|
|
348
364
|
// ============================================================================
|
|
365
|
+
// meta-governance ā å
ę²»ēéØē¦ (G9-G15)
|
|
366
|
+
// ============================================================================
|
|
367
|
+
const metaGovernance = defineCommand({
|
|
368
|
+
meta: { name: 'meta-governance', description: 'Run meta-governance gates (G9-G15) ā check if governance capabilities are actually used' },
|
|
369
|
+
args: {
|
|
370
|
+
'scale-dir': { type: 'string', default: '.scale' },
|
|
371
|
+
json: { type: 'boolean', default: false, description: 'Output as JSON' },
|
|
372
|
+
},
|
|
373
|
+
async run({ args }) {
|
|
374
|
+
const { eventBus } = getEngine();
|
|
375
|
+
const { GateSystem } = await import('../workflow/gates/GateSystem.js');
|
|
376
|
+
const gateSystem = new GateSystem(eventBus);
|
|
377
|
+
const results = await gateSystem.executeMetaGovernance(args['scale-dir']);
|
|
378
|
+
if (args.json) {
|
|
379
|
+
console.log(JSON.stringify(results, null, 2));
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const stageNames = {
|
|
383
|
+
G9: 'Knowledge Utilization',
|
|
384
|
+
G10: 'Evolution Effectiveness',
|
|
385
|
+
G11: 'Guardrail Effectiveness',
|
|
386
|
+
G12: 'Workflow Thoroughness',
|
|
387
|
+
G13: 'Multi-Agent Coordination',
|
|
388
|
+
G14: 'Skill Utilization',
|
|
389
|
+
G15: 'Self-Improvement',
|
|
390
|
+
};
|
|
391
|
+
let allPassed = true;
|
|
392
|
+
for (const result of results) {
|
|
393
|
+
const icon = result.passed ? 'ā
' : 'ā';
|
|
394
|
+
const name = stageNames[result.gate] ?? result.gate;
|
|
395
|
+
console.log(`${icon} ${result.gate} ${name}`);
|
|
396
|
+
if (result.evidence) {
|
|
397
|
+
for (const line of result.evidence.split('\n')) {
|
|
398
|
+
console.log(` ${line}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (!result.passed) {
|
|
402
|
+
allPassed = false;
|
|
403
|
+
for (const blocker of result.blockers) {
|
|
404
|
+
console.log(` ā ${blocker}`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
console.log();
|
|
408
|
+
}
|
|
409
|
+
if (!allPassed) {
|
|
410
|
+
console.log('ā Meta-governance check FAILED ā some capabilities are not being effectively used');
|
|
411
|
+
process.exit(1);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
console.log('ā
All meta-governance gates passed');
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
// ============================================================================
|
|
349
419
|
// artifact CRUD
|
|
350
420
|
// ============================================================================
|
|
351
421
|
const create = defineCommand({
|
|
@@ -1013,6 +1083,9 @@ const contextDoctor = defineCommand({
|
|
|
1013
1083
|
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1014
1084
|
'max-always': { type: 'string', description: 'Maximum Always-loaded estimated tokens' },
|
|
1015
1085
|
'max-task': { type: 'string', description: 'Maximum task context estimated tokens' },
|
|
1086
|
+
task: { type: 'string', description: 'Task text for a representative lazy context pack probe' },
|
|
1087
|
+
level: { type: 'string', default: 'M', description: 'Task level for the context pack probe' },
|
|
1088
|
+
files: { type: 'string', description: 'Comma-separated scoped files for the context pack probe' },
|
|
1016
1089
|
json: { type: 'boolean', default: false },
|
|
1017
1090
|
},
|
|
1018
1091
|
run({ args }) {
|
|
@@ -1023,6 +1096,9 @@ const contextDoctor = defineCommand({
|
|
|
1023
1096
|
scaleDir,
|
|
1024
1097
|
maxAlwaysTokens: parsePositiveIntArg(args['max-always'], '--max-always'),
|
|
1025
1098
|
maxTaskTokens: parsePositiveIntArg(args['max-task'], '--max-task'),
|
|
1099
|
+
task: args.task ? String(args.task) : undefined,
|
|
1100
|
+
level: String(args.level ?? 'M'),
|
|
1101
|
+
files: parseCommaList(args.files),
|
|
1026
1102
|
});
|
|
1027
1103
|
if (args.json) {
|
|
1028
1104
|
console.log(JSON.stringify(report, null, 2));
|
|
@@ -1038,9 +1114,55 @@ const contextDoctor = defineCommand({
|
|
|
1038
1114
|
process.exitCode = 1;
|
|
1039
1115
|
},
|
|
1040
1116
|
});
|
|
1117
|
+
const contextAnatomy = defineCommand({
|
|
1118
|
+
meta: { name: 'anatomy', description: 'Scan the project and generate .scale/anatomy.md for file-map context' },
|
|
1119
|
+
args: {
|
|
1120
|
+
dir: { type: 'string', default: PROJECT_DIR, description: 'Project directory' },
|
|
1121
|
+
'max-files': { type: 'string', description: 'Maximum files to include; defaults to 500' },
|
|
1122
|
+
exclude: { type: 'string', description: 'Comma-separated directory names to exclude' },
|
|
1123
|
+
write: { type: 'boolean', default: false, description: 'Write .scale/anatomy.md' },
|
|
1124
|
+
json: { type: 'boolean', default: false },
|
|
1125
|
+
},
|
|
1126
|
+
run({ args }) {
|
|
1127
|
+
const projectDir = resolve(String(args.dir ?? PROJECT_DIR));
|
|
1128
|
+
const scaleDir = resolveScaleDirForProject(projectDir);
|
|
1129
|
+
const maxFiles = parsePositiveIntArg(args['max-files'], '--max-files');
|
|
1130
|
+
const excludePatterns = parseCommaList(args.exclude);
|
|
1131
|
+
const anatomy = new ProjectAnatomy();
|
|
1132
|
+
const sections = anatomy.scan(projectDir, {
|
|
1133
|
+
maxFiles,
|
|
1134
|
+
excludePatterns: excludePatterns.length > 0 ? excludePatterns : undefined,
|
|
1135
|
+
});
|
|
1136
|
+
const content = anatomy.serialize(sections);
|
|
1137
|
+
const summary = [...sections.values()].reduce((acc, entries) => {
|
|
1138
|
+
acc.files += entries.length;
|
|
1139
|
+
acc.tokens += entries.reduce((sum, entry) => sum + entry.tokens, 0);
|
|
1140
|
+
return acc;
|
|
1141
|
+
}, { files: 0, tokens: 0 });
|
|
1142
|
+
const outputPath = join(scaleDir, 'anatomy.md');
|
|
1143
|
+
if (isTruthyFlag(args.write)) {
|
|
1144
|
+
ensureDir(scaleDir);
|
|
1145
|
+
writeFileSync(outputPath, content, 'utf-8');
|
|
1146
|
+
}
|
|
1147
|
+
if (args.json) {
|
|
1148
|
+
console.log(JSON.stringify({
|
|
1149
|
+
ok: true,
|
|
1150
|
+
projectDir,
|
|
1151
|
+
outputPath: isTruthyFlag(args.write) ? outputPath : undefined,
|
|
1152
|
+
summary,
|
|
1153
|
+
}, null, 2));
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
console.log('SCALE Project Anatomy');
|
|
1157
|
+
console.log(` Files: ${summary.files}`);
|
|
1158
|
+
console.log(` Estimated tokens: ${summary.tokens}`);
|
|
1159
|
+
if (isTruthyFlag(args.write))
|
|
1160
|
+
console.log(` Wrote: ${outputPath}`);
|
|
1161
|
+
},
|
|
1162
|
+
});
|
|
1041
1163
|
const context = defineCommand({
|
|
1042
1164
|
meta: { name: 'context', description: 'Context assembly' },
|
|
1043
|
-
subCommands: { build: contextBuild, status: contextStatus, inject: contextInject, glossary: contextGlossary, init: contextInit, grill: contextGrill, budget: contextBudget, pack: contextPack, doctor: contextDoctor },
|
|
1165
|
+
subCommands: { build: contextBuild, status: contextStatus, inject: contextInject, glossary: contextGlossary, init: contextInit, grill: contextGrill, budget: contextBudget, pack: contextPack, doctor: contextDoctor, anatomy: contextAnatomy },
|
|
1044
1166
|
});
|
|
1045
1167
|
// ============================================================================
|
|
1046
1168
|
// codegraph command - Adapter-first code intelligence
|
|
@@ -1722,9 +1844,14 @@ function printWorkspaceLifecycle(report) {
|
|
|
1722
1844
|
console.log(` Branch: ${report.root.branch ?? '(detached)'}`);
|
|
1723
1845
|
console.log(` Linked worktree: ${report.root.isLinkedWorktree ? 'yes' : 'no'}`);
|
|
1724
1846
|
console.log(` Root status: ${report.root.clean ? 'clean' : 'dirty'}`);
|
|
1847
|
+
console.log(` Branch policy: ${report.branchPolicy.mode} role=${report.branchPolicy.role} ship=${report.branchPolicy.shipAllowed ? 'allowed' : 'blocked'}`);
|
|
1848
|
+
console.log(` Integration: ${report.branchPolicy.integrationBranch}`);
|
|
1849
|
+
console.log(` Production: ${report.branchPolicy.productionBranch}`);
|
|
1725
1850
|
if (!report.root.clean) {
|
|
1726
1851
|
console.log(` staged=${report.root.staged} unstaged=${report.root.unstaged} untracked=${report.root.untracked}`);
|
|
1727
1852
|
}
|
|
1853
|
+
for (const blocker of report.branchPolicy.shipBlockers)
|
|
1854
|
+
console.log(` [SHIP BLOCKER] ${blocker}`);
|
|
1728
1855
|
if (report.childRepositories.length) {
|
|
1729
1856
|
console.log('\n Child repositories:');
|
|
1730
1857
|
for (const child of report.childRepositories) {
|
|
@@ -1767,6 +1894,7 @@ function printWorkspaceSummary(report) {
|
|
|
1767
1894
|
console.log(` Status: ${status}`);
|
|
1768
1895
|
console.log(` Topology: ${report.topology.topology}${report.topology.configured ? '' : ' (default)'}`);
|
|
1769
1896
|
console.log(` Root: ${rootStatus}`);
|
|
1897
|
+
console.log(` Branch: ${report.root.branch ?? '(detached)'} (${report.branchPolicy.role}, ship ${report.branchPolicy.shipAllowed ? 'allowed' : 'blocked'})`);
|
|
1770
1898
|
console.log(` Children: ${report.childRepositories.length} total, ${dirtyChildren.length} dirty, ${unpushedChildren.length} unpushed, ${noUpstreamChildren.length} no upstream`);
|
|
1771
1899
|
if (dirtyChildren.length > 0)
|
|
1772
1900
|
console.log(` Dirty child repositories: ${compactList(dirtyChildren)}`);
|
|
@@ -1882,6 +2010,7 @@ const workspaceFinish = defineCommand({
|
|
|
1882
2010
|
root: report.root,
|
|
1883
2011
|
childRepositories: report.childRepositories,
|
|
1884
2012
|
topology: report.topology,
|
|
2013
|
+
branchPolicy: report.branchPolicy,
|
|
1885
2014
|
finish: report.finish,
|
|
1886
2015
|
};
|
|
1887
2016
|
if (args.json) {
|
|
@@ -2223,6 +2352,7 @@ const init = defineCommand({
|
|
|
2223
2352
|
},
|
|
2224
2353
|
quick: { type: 'boolean', default: false, description: 'Quick start with auto-detection' },
|
|
2225
2354
|
interactive: { type: 'boolean', default: false, description: 'Interactive configuration mode with prompts' },
|
|
2355
|
+
profile: { type: 'string', default: '', description: 'Configuration profile (minimal/standard/advanced). Auto-mapped from scenario if not specified' },
|
|
2226
2356
|
'coverage-threshold': { type: 'string', default: '80', description: 'Coverage threshold (default 80%)' },
|
|
2227
2357
|
'retry-threshold': { type: 'string', default: '3', description: 'Brute retry threshold (default 3)' },
|
|
2228
2358
|
'block-severity': { type: 'string', default: 'CRITICAL', description: 'Block severity level (CRITICAL/HIGH/MEDIUM)' },
|
|
@@ -2285,7 +2415,11 @@ const init = defineCommand({
|
|
|
2285
2415
|
});
|
|
2286
2416
|
result.created.push(...governance.created);
|
|
2287
2417
|
result.skipped.push(...governance.skipped);
|
|
2288
|
-
|
|
2418
|
+
// Generate config.yaml from profile
|
|
2419
|
+
const profileId = args.profile || profileFromScenario(scenarioMode);
|
|
2420
|
+
const configPath = writeConfigYaml(args.dir, profileId, projectName, [agentType]);
|
|
2421
|
+
result.created.push(configPath);
|
|
2422
|
+
console.log(`\nā
SCALE Engine initialized for ${agentType} (interactive mode, profile: ${profileId})`);
|
|
2289
2423
|
console.log(`\nš Created:`);
|
|
2290
2424
|
for (const f of result.created)
|
|
2291
2425
|
console.log(` + ${f}`);
|
|
@@ -2298,8 +2432,10 @@ const init = defineCommand({
|
|
|
2298
2432
|
console.log(` Settings: ${result.settingsPath}`);
|
|
2299
2433
|
console.log(` Knowledge: ${result.knowledgeDocPath}`);
|
|
2300
2434
|
console.log(` Thresholds: ${thresholdsPath}`);
|
|
2435
|
+
console.log(` Config: ${configPath}`);
|
|
2301
2436
|
console.log(` Data dir: ${result.scaleDir}`);
|
|
2302
2437
|
console.log(` Scenario: ${scenarioMode}`);
|
|
2438
|
+
console.log(` Profile: ${profileId}`);
|
|
2303
2439
|
console.log(`\nš Next steps:`);
|
|
2304
2440
|
for (const step of governanceNextSteps())
|
|
2305
2441
|
console.log(` ā ${step}`);
|
|
@@ -2308,6 +2444,14 @@ const init = defineCommand({
|
|
|
2308
2444
|
// One-click quick start mode
|
|
2309
2445
|
if (!args.agent) {
|
|
2310
2446
|
const qsResult = await quickStart(args.dir, { governancePack: args['governance-pack'] });
|
|
2447
|
+
// Generate config.yaml from profile
|
|
2448
|
+
if (qsResult.success) {
|
|
2449
|
+
const profileId = args.profile || profileFromScenario(args.scenario);
|
|
2450
|
+
const projectName = args.dir.split(/[/\\]/).pop() || 'Project';
|
|
2451
|
+
const detectedAgent = qsResult.platform ? [qsResult.platform] : [];
|
|
2452
|
+
const configPath = writeConfigYaml(args.dir, profileId, projectName, detectedAgent);
|
|
2453
|
+
qsResult.created.push(configPath);
|
|
2454
|
+
}
|
|
2311
2455
|
if (args.json) {
|
|
2312
2456
|
const detection = qsResult.success ? undefined : detectPlatform(args.dir);
|
|
2313
2457
|
console.log(JSON.stringify({
|
|
@@ -2362,15 +2506,21 @@ const init = defineCommand({
|
|
|
2362
2506
|
});
|
|
2363
2507
|
result.created.push(...governance.created);
|
|
2364
2508
|
result.skipped.push(...governance.skipped);
|
|
2509
|
+
// Generate config.yaml from profile
|
|
2510
|
+
const profileId = args.profile || profileFromScenario(args.scenario);
|
|
2511
|
+
const configPath = writeConfigYaml(args.dir, profileId, projectName, [args.agent]);
|
|
2512
|
+
result.created.push(configPath);
|
|
2365
2513
|
if (args.json) {
|
|
2366
2514
|
console.log(JSON.stringify({
|
|
2367
2515
|
ok: true,
|
|
2368
2516
|
mode: args.quick ? 'quick-agent' : 'manual',
|
|
2369
2517
|
agent: args.agent,
|
|
2370
2518
|
scenario: args.scenario,
|
|
2519
|
+
profile: profileId,
|
|
2371
2520
|
governancePack: args['governance-pack'],
|
|
2372
2521
|
settingsPath: result.settingsPath,
|
|
2373
2522
|
knowledgeDocPath: result.knowledgeDocPath,
|
|
2523
|
+
configPath,
|
|
2374
2524
|
scaleDir: result.scaleDir,
|
|
2375
2525
|
created: result.created,
|
|
2376
2526
|
skipped: result.skipped,
|
|
@@ -2378,7 +2528,7 @@ const init = defineCommand({
|
|
|
2378
2528
|
}, null, 2));
|
|
2379
2529
|
return;
|
|
2380
2530
|
}
|
|
2381
|
-
console.log(`\nā
SCALE Engine initialized for ${args.agent} (scenario: ${args.scenario})`);
|
|
2531
|
+
console.log(`\nā
SCALE Engine initialized for ${args.agent} (scenario: ${args.scenario}, profile: ${profileId})`);
|
|
2382
2532
|
console.log(`\nš Created:`);
|
|
2383
2533
|
for (const f of result.created)
|
|
2384
2534
|
console.log(` + ${f}`);
|
|
@@ -2389,6 +2539,7 @@ const init = defineCommand({
|
|
|
2389
2539
|
}
|
|
2390
2540
|
console.log(`\nš§ Settings: ${result.settingsPath}`);
|
|
2391
2541
|
console.log(`\nš Knowledge: ${result.knowledgeDocPath}`);
|
|
2542
|
+
console.log(`\nš Config: ${configPath}`);
|
|
2392
2543
|
console.log(`\nš Data dir: ${result.scaleDir}`);
|
|
2393
2544
|
console.log(`\nš Next steps:`);
|
|
2394
2545
|
for (const step of governanceNextSteps())
|
|
@@ -2396,8 +2547,70 @@ const init = defineCommand({
|
|
|
2396
2547
|
},
|
|
2397
2548
|
});
|
|
2398
2549
|
// ============================================================================
|
|
2399
|
-
//
|
|
2550
|
+
// config command ā Configuration profile management
|
|
2400
2551
|
// ============================================================================
|
|
2552
|
+
const configProfile = defineCommand({
|
|
2553
|
+
meta: { name: 'profile', description: 'View or switch configuration profile' },
|
|
2554
|
+
args: {
|
|
2555
|
+
set: { type: 'string', default: '', description: 'Switch to profile (minimal/standard/advanced)' },
|
|
2556
|
+
list: { type: 'boolean', default: false, description: 'List all available profiles' },
|
|
2557
|
+
json: { type: 'boolean', default: false, description: 'Output as JSON' },
|
|
2558
|
+
},
|
|
2559
|
+
async run({ args }) {
|
|
2560
|
+
if (args.list) {
|
|
2561
|
+
const profiles = listConfigProfiles();
|
|
2562
|
+
if (args.json) {
|
|
2563
|
+
console.log(JSON.stringify(profiles, null, 2));
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
console.log('\nAvailable profiles:\n');
|
|
2567
|
+
for (const p of profiles) {
|
|
2568
|
+
console.log(` ${p.id.padEnd(12)} ${p.name} ā ${p.description}`);
|
|
2569
|
+
}
|
|
2570
|
+
console.log(`\nUse: scale config profile --set <id>`);
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
if (args.set) {
|
|
2574
|
+
const profile = getConfigProfile(args.set);
|
|
2575
|
+
if (profile.id !== args.set) {
|
|
2576
|
+
console.log(`\nā ļø Profile "${args.set}" not found. Available: minimal, standard, advanced`);
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2579
|
+
// Update config.yaml
|
|
2580
|
+
const configPath = join('.scale', 'config.yaml');
|
|
2581
|
+
const projectName = process.cwd().split(/[/\\]/).pop() || 'Project';
|
|
2582
|
+
const content = generateConfigForProfile(args.set, { name: projectName });
|
|
2583
|
+
ensureDir('.scale');
|
|
2584
|
+
writeFileSync(configPath, content, 'utf-8');
|
|
2585
|
+
console.log(`\nā
Profile switched to: ${profile.name}`);
|
|
2586
|
+
console.log(` ${profile.description}`);
|
|
2587
|
+
console.log(`\nš Config updated: ${configPath}`);
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
// Show current profile
|
|
2591
|
+
const configPath = join('.scale', 'config.yaml');
|
|
2592
|
+
if (!existsSync(configPath)) {
|
|
2593
|
+
console.log('\nā ļø No config.yaml found. Run: scale init');
|
|
2594
|
+
return;
|
|
2595
|
+
}
|
|
2596
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
2597
|
+
const match = content.match(/^profile:\s*(.+)$/m);
|
|
2598
|
+
const currentProfile = match?.[1]?.trim() || 'standard';
|
|
2599
|
+
const profile = getConfigProfile(currentProfile);
|
|
2600
|
+
if (args.json) {
|
|
2601
|
+
console.log(JSON.stringify({ profile: profile.id, name: profile.name, description: profile.description, sections: profile.sections }, null, 2));
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
console.log(`\nCurrent profile: ${profile.name} (${profile.id})`);
|
|
2605
|
+
console.log(` ${profile.description}`);
|
|
2606
|
+
console.log(`\nSections: ${profile.sections.join(', ')}`);
|
|
2607
|
+
console.log(`\nUse: scale config profile --set <id> to switch`);
|
|
2608
|
+
},
|
|
2609
|
+
});
|
|
2610
|
+
const config = defineCommand({
|
|
2611
|
+
meta: { name: 'config', description: 'Configuration management' },
|
|
2612
|
+
subCommands: { profile: configProfile },
|
|
2613
|
+
});
|
|
2401
2614
|
const governanceDiff = defineCommand({
|
|
2402
2615
|
meta: { name: 'diff', description: 'Check generated governance files for drift' },
|
|
2403
2616
|
args: {
|
|
@@ -3605,6 +3818,75 @@ const memoryDoctor = defineCommand({
|
|
|
3605
3818
|
process.exitCode = 1;
|
|
3606
3819
|
},
|
|
3607
3820
|
});
|
|
3821
|
+
const memoryCerebrum = defineCommand({
|
|
3822
|
+
meta: { name: 'cerebrum', description: 'Maintain .scale/cerebrum.md do-not-repeat rules and preferences' },
|
|
3823
|
+
args: {
|
|
3824
|
+
type: { type: 'string', description: 'Optional entry type: preference or do-not-repeat' },
|
|
3825
|
+
pattern: { type: 'string', description: 'Pattern for do-not-repeat entries' },
|
|
3826
|
+
description: { type: 'string', description: 'Entry description or preference text' },
|
|
3827
|
+
tags: { type: 'string', description: 'Comma-separated tags for preferences' },
|
|
3828
|
+
write: { type: 'boolean', default: false, description: 'Write .scale/cerebrum.md' },
|
|
3829
|
+
json: { type: 'boolean', default: false },
|
|
3830
|
+
},
|
|
3831
|
+
async run({ args }) {
|
|
3832
|
+
const { kb } = getEngine();
|
|
3833
|
+
const manager = new CerebrumManager(kb);
|
|
3834
|
+
const type = args.type ? String(args.type).toLowerCase() : '';
|
|
3835
|
+
let created;
|
|
3836
|
+
if (type) {
|
|
3837
|
+
if (type === 'do-not-repeat' || type === 'do_not_repeat' || type === 'dnr') {
|
|
3838
|
+
const pattern = String(args.pattern ?? '').trim();
|
|
3839
|
+
const description = String(args.description ?? '').trim();
|
|
3840
|
+
if (!pattern || !description) {
|
|
3841
|
+
console.error('memory cerebrum --type do-not-repeat requires --pattern and --description.');
|
|
3842
|
+
process.exit(1);
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
created = await manager.addDoNotRepeat(pattern, description);
|
|
3846
|
+
}
|
|
3847
|
+
else if (type === 'preference' || type === 'pref') {
|
|
3848
|
+
const description = String(args.description ?? args.pattern ?? '').trim();
|
|
3849
|
+
if (!description) {
|
|
3850
|
+
console.error('memory cerebrum --type preference requires --description.');
|
|
3851
|
+
process.exit(1);
|
|
3852
|
+
return;
|
|
3853
|
+
}
|
|
3854
|
+
created = await manager.addPreference(description, parseCommaList(args.tags));
|
|
3855
|
+
}
|
|
3856
|
+
else {
|
|
3857
|
+
console.error('memory cerebrum --type must be preference or do-not-repeat.');
|
|
3858
|
+
process.exit(1);
|
|
3859
|
+
return;
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
const entries = await manager.loadAll();
|
|
3863
|
+
const outputPath = join(SCALE_DIR, 'cerebrum.md');
|
|
3864
|
+
const shouldWrite = isTruthyFlag(args.write) || Boolean(created);
|
|
3865
|
+
if (shouldWrite) {
|
|
3866
|
+
ensureDir(SCALE_DIR);
|
|
3867
|
+
writeFileSync(outputPath, manager.toMarkdown(), 'utf-8');
|
|
3868
|
+
}
|
|
3869
|
+
const summary = {
|
|
3870
|
+
total: entries.length,
|
|
3871
|
+
doNotRepeat: entries.filter(entry => entry.type === 'do_not_repeat').length,
|
|
3872
|
+
preferences: entries.filter(entry => entry.type === 'preference').length,
|
|
3873
|
+
};
|
|
3874
|
+
if (args.json) {
|
|
3875
|
+
console.log(JSON.stringify({
|
|
3876
|
+
ok: true,
|
|
3877
|
+
outputPath: shouldWrite ? outputPath : undefined,
|
|
3878
|
+
created,
|
|
3879
|
+
summary,
|
|
3880
|
+
}, null, 2));
|
|
3881
|
+
return;
|
|
3882
|
+
}
|
|
3883
|
+
console.log('SCALE Cerebrum');
|
|
3884
|
+
console.log(` Do-not-repeat: ${summary.doNotRepeat}`);
|
|
3885
|
+
console.log(` Preferences: ${summary.preferences}`);
|
|
3886
|
+
if (shouldWrite)
|
|
3887
|
+
console.log(` Wrote: ${outputPath}`);
|
|
3888
|
+
},
|
|
3889
|
+
});
|
|
3608
3890
|
const memorySettle = defineCommand({
|
|
3609
3891
|
meta: { name: 'settle', description: 'Settle runtime evidence into a reviewable memory learning candidate' },
|
|
3610
3892
|
args: {
|
|
@@ -3869,6 +4151,7 @@ const memory = defineCommand({
|
|
|
3869
4151
|
subCommands: {
|
|
3870
4152
|
pack: memoryPack,
|
|
3871
4153
|
doctor: memoryDoctor,
|
|
4154
|
+
cerebrum: memoryCerebrum,
|
|
3872
4155
|
settle: memorySettle,
|
|
3873
4156
|
ingest: memoryIngest,
|
|
3874
4157
|
query: memoryQuery,
|
|
@@ -4748,6 +5031,7 @@ const team = defineCommand({
|
|
|
4748
5031
|
// Phase-Aligned Commands (v0.10.1) - agent-skills style
|
|
4749
5032
|
// ============================================================================
|
|
4750
5033
|
import * as phaseCommands from '../cli/phaseCommands.js';
|
|
5034
|
+
import { runCommand } from '../cli/runCommand.js';
|
|
4751
5035
|
import * as liteCommands from '../cli/liteCommands.js';
|
|
4752
5036
|
import * as vibeCommands from '../cli/vibeCommands.js';
|
|
4753
5037
|
const main = defineCommand({
|
|
@@ -4766,11 +5050,13 @@ const main = defineCommand({
|
|
|
4766
5050
|
verify: phaseCommands.phaseVerify,
|
|
4767
5051
|
review: phaseCommands.phaseReview,
|
|
4768
5052
|
ship: phaseCommands.phaseShip,
|
|
5053
|
+
run: runCommand,
|
|
4769
5054
|
// Original commands (preserved)
|
|
4770
5055
|
init,
|
|
4771
5056
|
doctor,
|
|
4772
5057
|
session,
|
|
4773
5058
|
gate,
|
|
5059
|
+
'meta-governance': metaGovernance,
|
|
4774
5060
|
create,
|
|
4775
5061
|
list,
|
|
4776
5062
|
show,
|
|
@@ -4807,6 +5093,7 @@ const main = defineCommand({
|
|
|
4807
5093
|
team,
|
|
4808
5094
|
'create-prd': createPRD,
|
|
4809
5095
|
'out-of-scope': outOfScope,
|
|
5096
|
+
config,
|
|
4810
5097
|
},
|
|
4811
5098
|
});
|
|
4812
5099
|
runMain(main);
|