@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.
Files changed (89) hide show
  1. package/README.en.md +39 -13
  2. package/README.md +61 -31
  3. package/dist/api/cli.js +291 -4
  4. package/dist/api/cli.js.map +1 -1
  5. package/dist/api/doctor.d.ts +1 -0
  6. package/dist/api/doctor.js +83 -0
  7. package/dist/api/doctor.js.map +1 -1
  8. package/dist/artifact/types.d.ts +1 -1
  9. package/dist/artifact/types.js.map +1 -1
  10. package/dist/cli/phaseCommands.js +25 -6
  11. package/dist/cli/phaseCommands.js.map +1 -1
  12. package/dist/cli/runCommand.d.ts +39 -0
  13. package/dist/cli/runCommand.js +113 -0
  14. package/dist/cli/runCommand.js.map +1 -0
  15. package/dist/config/profiles.d.ts +52 -0
  16. package/dist/config/profiles.js +162 -0
  17. package/dist/config/profiles.js.map +1 -0
  18. package/dist/context/ContextBudget.d.ts +25 -1
  19. package/dist/context/ContextBudget.js +72 -7
  20. package/dist/context/ContextBudget.js.map +1 -1
  21. package/dist/context/ProjectAnatomy.d.ts +18 -0
  22. package/dist/context/ProjectAnatomy.js +287 -0
  23. package/dist/context/ProjectAnatomy.js.map +1 -0
  24. package/dist/dashboard/DashboardServer.d.ts +3 -0
  25. package/dist/dashboard/DashboardServer.js +114 -0
  26. package/dist/dashboard/DashboardServer.js.map +1 -1
  27. package/dist/hooks/BugPatternDetector.d.ts +36 -0
  28. package/dist/hooks/BugPatternDetector.js +207 -0
  29. package/dist/hooks/BugPatternDetector.js.map +1 -0
  30. package/dist/hooks/HookGeneratorEnhanced.js +301 -5
  31. package/dist/hooks/HookGeneratorEnhanced.js.map +1 -1
  32. package/dist/hooks/WorkflowHooksManager.js +24 -0
  33. package/dist/hooks/WorkflowHooksManager.js.map +1 -1
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.js +2 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/knowledge/CerebrumManager.d.ts +25 -0
  38. package/dist/knowledge/CerebrumManager.js +127 -0
  39. package/dist/knowledge/CerebrumManager.js.map +1 -0
  40. package/dist/knowledge/SQLiteKnowledgeBase.d.ts +1 -0
  41. package/dist/knowledge/SQLiteKnowledgeBase.js +31 -3
  42. package/dist/knowledge/SQLiteKnowledgeBase.js.map +1 -1
  43. package/dist/knowledge/TfidfIndex.d.ts +50 -0
  44. package/dist/knowledge/TfidfIndex.js +177 -0
  45. package/dist/knowledge/TfidfIndex.js.map +1 -0
  46. package/dist/skills/SkillDiscovery.js +1 -1
  47. package/dist/skills/SkillDiscovery.js.map +1 -1
  48. package/dist/tools/CommandOutputCompressor.d.ts +28 -0
  49. package/dist/tools/CommandOutputCompressor.js +242 -0
  50. package/dist/tools/CommandOutputCompressor.js.map +1 -0
  51. package/dist/tools/CommandRunLedger.d.ts +77 -0
  52. package/dist/tools/CommandRunLedger.js +111 -0
  53. package/dist/tools/CommandRunLedger.js.map +1 -0
  54. package/dist/tools/index.d.ts +2 -0
  55. package/dist/tools/index.js +2 -0
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/workflow/EngineeringStandards.js +91 -2
  58. package/dist/workflow/EngineeringStandards.js.map +1 -1
  59. package/dist/workflow/GovernanceTemplatePacks.js +2 -2
  60. package/dist/workflow/GovernanceTemplates.js +90 -89
  61. package/dist/workflow/GovernanceTemplates.js.map +1 -1
  62. package/dist/workflow/TaskLevelDetector.d.ts +41 -0
  63. package/dist/workflow/TaskLevelDetector.js +219 -0
  64. package/dist/workflow/TaskLevelDetector.js.map +1 -0
  65. package/dist/workflow/WorkflowOrchestrator.d.ts +59 -0
  66. package/dist/workflow/WorkflowOrchestrator.js +326 -0
  67. package/dist/workflow/WorkflowOrchestrator.js.map +1 -0
  68. package/dist/workflow/WorkspaceLifecycle.d.ts +19 -1
  69. package/dist/workflow/WorkspaceLifecycle.js +119 -3
  70. package/dist/workflow/WorkspaceLifecycle.js.map +1 -1
  71. package/dist/workflow/WorkspaceTopology.d.ts +6 -0
  72. package/dist/workflow/WorkspaceTopology.js +17 -6
  73. package/dist/workflow/WorkspaceTopology.js.map +1 -1
  74. package/dist/workflow/gates/GateSystem.d.ts +23 -6
  75. package/dist/workflow/gates/GateSystem.js +114 -25
  76. package/dist/workflow/gates/GateSystem.js.map +1 -1
  77. package/dist/workflow/gates/MetaGovernanceGates.d.ts +70 -0
  78. package/dist/workflow/gates/MetaGovernanceGates.js +617 -0
  79. package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -0
  80. package/dist/workflow/types.d.ts +6 -1
  81. package/docs/GITLAB_FLOW.md +125 -0
  82. package/docs/README.md +3 -0
  83. package/docs/start/README.md +29 -3
  84. package/docs/start/artifact-lifecycle.md +326 -0
  85. package/docs/start/workflow-upgrade.md +150 -0
  86. package/image/wechat-public.jpg +0 -0
  87. package/image/wxPay.jpg +0 -0
  88. package/image/zfb.jpg +0 -0
  89. 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
- console.log(`\nāœ… SCALE Engine initialized for ${agentType} (interactive mode)`);
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
- // governance command — Generated governance asset tooling
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);