@chem-x/starter-kit 26.9.21-227 → 26.9.21-34

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 (47) hide show
  1. package/cli/audit/autofix.js +2 -17
  2. package/cli/audit.js +0 -3
  3. package/cli/commands/cmd-audit.js +3 -43
  4. package/cli/commands/cmd-router.js +1 -13
  5. package/cli/generator-templates/archetypes/index.js +4 -34
  6. package/cli/generator-templates/controller.js +1 -1
  7. package/cli/generator-templates/react.js +1 -1
  8. package/cli/generator-templates/svelte.js +1 -1
  9. package/cli/generator-templates/types.js +2 -2
  10. package/cli/generator-templates/vue.js +1 -1
  11. package/cli/generator-templates.js +0 -1
  12. package/cli/generator-templates.spec.js +0 -5
  13. package/cli/generator.js +7 -94
  14. package/cli/index.js +2 -5
  15. package/cli/mcp/antigravity.js +2 -3
  16. package/cli/mcp/manifests.js +1 -1
  17. package/cli/mcp/tools-search.js +1 -7
  18. package/cli/mcp/tools.js +0 -23
  19. package/cli/mutators.js +23 -10
  20. package/cli/project-detector.js +0 -47
  21. package/cli/ui-e2e-verification.spec.js +1 -3
  22. package/cli/ui-filetree.spec.js +5 -5
  23. package/cli/ui-html.js +34 -26
  24. package/cli/ui-kanban.spec.js +12 -12
  25. package/cli/ui-styles.js +81 -195
  26. package/cli/ui-vbulletin.spec.js +13 -12
  27. package/cli/ui.spec.js +4 -6
  28. package/package.json +1 -1
  29. package/cli/audit/clone-detector.js +0 -64
  30. package/cli/audit/clone-detector.spec.js +0 -46
  31. package/cli/audit/reporter-clones.js +0 -33
  32. package/cli/audit/reporter-hotspot-graph.js +0 -34
  33. package/cli/audit-stages.spec.js +0 -30
  34. package/cli/exploder.js +0 -258
  35. package/cli/exploder.spec.js +0 -99
  36. package/cli/generator-compact.spec.js +0 -104
  37. package/cli/generator-templates/archetypes/minimal-archetypes.js +0 -131
  38. package/cli/generator-templates/archetypes/vector-matcher.js +0 -50
  39. package/cli/generator-templates/archetypes/vector-matcher.spec.js +0 -25
  40. package/cli/generator-templates/compact.js +0 -130
  41. package/cli/search-queries-hotspot-graph.js +0 -65
  42. package/cli/search-queries-hotspot-graph.spec.js +0 -66
  43. package/cli/search-queries-similar.js +0 -84
  44. package/cli/search-queries-similar.spec.js +0 -43
  45. package/cli/trend.js +0 -84
  46. package/cli/trend.spec.js +0 -51
  47. package/cli/ui-index.html +0 -659
@@ -63,9 +63,7 @@ export const autofixContent = (content, options = {}) => {
63
63
  }
64
64
 
65
65
  // 3. AI lazy placeholder comment removal
66
- const hasLazyTruncation = TRUNCATION_REGEX.test(line);
67
- const isLazyTruncationEligible = !shouldDropLine && shouldFix('AI_SLOP_LAZY_PLACEHOLDER');
68
- if (isLazyTruncationEligible && hasLazyTruncation) {
66
+ if (!shouldDropLine && shouldFix('AI_SLOP_LAZY_PLACEHOLDER') && TRUNCATION_REGEX.test(line)) {
69
67
  fixes.push({
70
68
  line: lineNumber,
71
69
  rule: 'AI_SLOP_LAZY_PLACEHOLDER',
@@ -74,9 +72,7 @@ export const autofixContent = (content, options = {}) => {
74
72
  shouldDropLine = true;
75
73
  }
76
74
 
77
- const hasEmDash = line.includes('\u2014');
78
- const isEmDashEligible = !shouldDropLine && shouldFix('TYPOGRAPHY_EM_DASH');
79
- if (isEmDashEligible && hasEmDash) {
75
+ if (!shouldDropLine && shouldFix('TYPOGRAPHY_EM_DASH') && line.includes('\u2014')) {
80
76
  line = line.replace(/\u2014/g, '-');
81
77
  fixes.push({
82
78
  line: lineNumber,
@@ -85,17 +81,6 @@ export const autofixContent = (content, options = {}) => {
85
81
  });
86
82
  }
87
83
 
88
- const hasTimeoutMacro = /setTimeout\([^,]+,\s*0\)/.test(line);
89
- const isTimeoutEligible = !shouldDropLine && shouldFix('MACRO_TASK_OVER_MICRO_TASK');
90
- if (isTimeoutEligible && hasTimeoutMacro) {
91
- line = line.replace(/setTimeout\(([^,]+),\s*0\)/g, 'queueMicrotask($1)');
92
- fixes.push({
93
- line: lineNumber,
94
- rule: 'MACRO_TASK_OVER_MICRO_TASK',
95
- action: 'Replaced setTimeout(fn, 0) with queueMicrotask(fn)'
96
- });
97
- }
98
-
99
84
  if (!shouldDropLine) {
100
85
  resultLines.push(line);
101
86
  }
package/cli/audit.js CHANGED
@@ -226,11 +226,8 @@ export const runAudit = (targetDir = 'src', options = {}) => {
226
226
  const patterns = patternRegistry.resolveHarmonizationCandidates(hotspots);
227
227
  const roadmap = buildRemediationRoadmap({ hotspots, violations, patterns });
228
228
 
229
- const stage = options.stage || (options.relax ? 'draft' : 'strict');
230
-
231
229
  const report = {
232
230
  targetDir,
233
- stage,
234
231
  options,
235
232
  scannedFiles,
236
233
  totalViolations: violations.length,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cmd-audit.js: Audit command orchestrator.
2
+ * cmd-audit.js — Audit command orchestrator.
3
3
  * Single responsibility: run the full AST audit pipeline given CLI args.
4
4
  * Extracted from cli/index.js per Directive 1.A (Monolith Decomposition).
5
5
  */
@@ -47,19 +47,6 @@ export const runAudit = async (customDir, isCli, rawArgs, loadProjectConfig) =>
47
47
  const isPromptOnFail = rawArgs.includes('--prompt-on-fail');
48
48
  const isCopyPrompt = rawArgs.includes('--copy-prompt');
49
49
 
50
- const stageFlag = rawArgs.find((arg) => arg.startsWith('--stage='));
51
- let stage = 'strict';
52
- if (stageFlag) {
53
- stage = stageFlag.split('=')[1];
54
- } else if (rawArgs.includes('--relax') || rawArgs.includes('--draft')) {
55
- stage = 'draft';
56
- } else if (isStrict) {
57
- stage = 'strict';
58
- } else if (projectConfig.stage) {
59
- stage = projectConfig.stage;
60
- }
61
- const isDraft = stage === 'draft';
62
-
63
50
  const dirFlag = rawArgs.find((arg) => arg.startsWith('--dir='));
64
51
  const outputFlag = rawArgs.find((arg) => arg.startsWith('--output=') || arg.startsWith('-o='));
65
52
  const outputFile = outputFlag ? outputFlag.split('=')[1] : null;
@@ -101,7 +88,7 @@ export const runAudit = async (customDir, isCli, rawArgs, loadProjectConfig) =>
101
88
  fileList = preflight.fileList;
102
89
  }
103
90
 
104
- const auditOptions = { outputFile, model, costPerMillion, fast: isFast, fileList, stage };
91
+ const auditOptions = { outputFile, model, costPerMillion, fast: isFast, fileList };
105
92
  const report = executeAstAudit(targetDir, auditOptions);
106
93
  saveAuditSnapshot(report);
107
94
  const syncRes = syncSearchIndex(targetDir, process.cwd());
@@ -115,35 +102,9 @@ export const runAudit = async (customDir, isCli, rawArgs, loadProjectConfig) =>
115
102
  process.stdout.write(`\x1b[32m✔\x1b[0m Auto-triage generated ${createdTasks.length} team task(s) from audit violations.\n`);
116
103
  }
117
104
  }
118
- if (rawArgs.includes('--clones')) {
119
- const { detectSemanticClones } = await import('../audit/clone-detector.js');
120
- const { formatCloneReport } = await import('../audit/reporter-clones.js');
121
- const cloneThresholdArg = rawArgs.find((a) => a.startsWith('--clone-threshold='));
122
- const threshold = cloneThresholdArg ? parseFloat(cloneThresholdArg.split('=')[1]) : 0.85;
123
- const clones = detectSemanticClones(syncRes.db, { threshold });
124
- if (isJson) {
125
- report.clones = clones;
126
- } else {
127
- process.stdout.write(formatCloneReport(clones));
128
- }
129
- }
130
- if (rawArgs.includes('--hotspot-graph')) {
131
- const { calculateCascadingHotspotGraph } = await import('../search-queries-hotspot-graph.js');
132
- const { formatHotspotGraphReport } = await import('../audit/reporter-hotspot-graph.js');
133
- const limitArg = rawArgs.find((a) => a.startsWith('--limit='));
134
- const limit = limitArg ? parseInt(limitArg.split('=')[1], 10) : 10;
135
- const graph = calculateCascadingHotspotGraph(syncRes.db, { limit });
136
- if (isJson) {
137
- report.hotspotGraph = graph;
138
- } else {
139
- process.stdout.write(formatHotspotGraphReport(graph));
140
- }
141
- }
142
105
  }
143
106
 
144
107
  // Stage 1: Atomic failure predicates
145
- const isCriticalViolation = (v) => v.severity === 'CRITICAL';
146
- const hasCritical = report.violations.some(isCriticalViolation);
147
108
  const isSevereViolation = (v) => v.severity === 'CRITICAL' || v.severity === 'HIGH';
148
109
  const hasCriticalOrHigh = report.violations.some(isSevereViolation);
149
110
  const hasViolations = report.violations.length > 0;
@@ -155,8 +116,7 @@ export const runAudit = async (customDir, isCli, rawArgs, loadProjectConfig) =>
155
116
  const isDefaultFail = !hasThreshold && !isStrict && hasCriticalOrHigh;
156
117
 
157
118
  // Stage 2: Unified failure decision
158
- const hasStandardFailure = evaluateAuditFailure([isStrictFail, isDefaultFail, isGradeFail, isScoreFail]);
159
- const hasFailingViolations = isDraft ? hasCritical : hasStandardFailure;
119
+ const hasFailingViolations = evaluateAuditFailure([isStrictFail, isDefaultFail, isGradeFail, isScoreFail]);
160
120
 
161
121
  if (isJson) {
162
122
  process.stdout.write(JSON.stringify(report, null, 2) + '\n');
@@ -1,5 +1,5 @@
1
1
  /**
2
- * cmd-router.js: CLI command dispatch table.
2
+ * cmd-router.js — CLI command dispatch table.
3
3
  * Single responsibility: map first-arg tokens to their lazy-loaded command handlers.
4
4
  * Extracted from cli/index.js per Directive 1.A (Monolith Decomposition).
5
5
  */
@@ -67,12 +67,6 @@ export const dispatchCommand = async (firstArg, rawArgs, runAudit, getPackageVer
67
67
  await runAudit(posDir, true);
68
68
  break;
69
69
  }
70
- case 'trend':
71
- case 'trends': {
72
- const { runTrend } = await import('../trend.js');
73
- runTrend(rawArgs.slice(1), process.cwd());
74
- break;
75
- }
76
70
  case 'init': {
77
71
  const { runInit } = await import('../scaffold.js');
78
72
  await runInit(rawArgs[1] || 'src/chemical-x', rawArgs, runAudit);
@@ -113,12 +107,6 @@ export const dispatchCommand = async (firstArg, rawArgs, runAudit, getPackageVer
113
107
  await runMutatorCli(rawArgs, true);
114
108
  break;
115
109
  }
116
- case 'explode':
117
- case 'unpack': {
118
- const { runExplodeCli } = await import('../exploder.js');
119
- await runExplodeCli(rawArgs.slice(1), true);
120
- break;
121
- }
122
110
  case 'add': {
123
111
  if (['prop', 'state', 'action'].includes(rawArgs[1])) {
124
112
  const { runMutatorCli } = await import('../mutators.js');
@@ -7,10 +7,6 @@ import { INPUT_ARCHETYPES } from './input-archetypes.js';
7
7
  import { LAYOUT_ARCHETYPES } from './layout-archetypes.js';
8
8
  import { DOMAIN_ARCHETYPES } from './domain-archetypes.js';
9
9
  import { STATUS_ARCHETYPES } from './status-archetypes.js';
10
- import { MINIMAL_ARCHETYPES } from './minimal-archetypes.js';
11
- import { matchArchetypeByVector } from './vector-matcher.js';
12
-
13
- export { matchArchetypeByVector };
14
10
 
15
11
  export const ALL_ARCHETYPES = [
16
12
  ...COLLECTION_ARCHETYPES,
@@ -20,24 +16,7 @@ export const ALL_ARCHETYPES = [
20
16
  ...STATUS_ARCHETYPES
21
17
  ];
22
18
 
23
- export const EXTENDED_ARCHETYPES = [
24
- ...MINIMAL_ARCHETYPES,
25
- ...ALL_ARCHETYPES
26
- ];
27
-
28
- const isPartialMatch = (token, kw) => {
29
- const isMinLength = token.length >= 3;
30
- const isAffixMatch = token.startsWith(kw) || kw.startsWith(token);
31
- return isMinLength && isAffixMatch;
32
- };
33
-
34
- export const resolveArchetype = (slug = '', description = '', explicitTemplate = '') => {
35
- if (explicitTemplate) {
36
- const templateNorm = String(explicitTemplate).toLowerCase().trim();
37
- const exactMatch = EXTENDED_ARCHETYPES.find((a) => a.id === templateNorm || a.keywords.includes(templateNorm));
38
- if (exactMatch) return exactMatch;
39
- }
40
-
19
+ export const resolveArchetype = (slug = '', description = '') => {
41
20
  const normalized = String(slug).toLowerCase().replace(/^(m-|a-|o-|t-|v-|use-)/, '');
42
21
  const slugTokens = normalized.split(/[-_]/).filter(Boolean);
43
22
  const descTokens = String(description)
@@ -61,7 +40,7 @@ export const resolveArchetype = (slug = '', description = '', explicitTemplate =
61
40
  for (const kw of archetype.keywords) {
62
41
  if (token === kw) {
63
42
  score += 12;
64
- } else if (isPartialMatch(token, kw)) {
43
+ } else if (token.length >= 3 && (token.startsWith(kw) || kw.startsWith(token))) {
65
44
  score += 8;
66
45
  }
67
46
  }
@@ -74,7 +53,7 @@ export const resolveArchetype = (slug = '', description = '', explicitTemplate =
74
53
  for (const kw of archetype.keywords) {
75
54
  if (token === kw) {
76
55
  score += 7;
77
- } else if (isPartialMatch(token, kw)) {
56
+ } else if (token.length >= 3 && (token.startsWith(kw) || kw.startsWith(token))) {
78
57
  score += 4;
79
58
  }
80
59
  }
@@ -86,19 +65,10 @@ export const resolveArchetype = (slug = '', description = '', explicitTemplate =
86
65
  }
87
66
  }
88
67
 
89
- const hasKeywordWinner = Boolean(bestArchetype && highestScore > 0);
90
- if (hasKeywordWinner) {
68
+ if (bestArchetype && highestScore > 0) {
91
69
  return bestArchetype;
92
70
  }
93
71
 
94
- const hasDescription = Boolean(description && String(description).trim());
95
- if (hasDescription) {
96
- const vectorMatch = matchArchetypeByVector(description, 0.3);
97
- if (vectorMatch) {
98
- return vectorMatch.archetype;
99
- }
100
- }
101
-
102
72
  // Fallback to State Boundary (Archetype #22 in LAYOUT_ARCHETYPES)
103
73
  return LAYOUT_ARCHETYPES.find((a) => a.id === 'state-boundary') || ALL_ARCHETYPES[0];
104
74
  };
@@ -3,7 +3,7 @@ import { convertReactControllerToVue, convertReactControllerToSvelte } from './c
3
3
 
4
4
  export const buildController = (name, pascalName, options = {}) => {
5
5
  const fw = options.framework ? options.framework.toLowerCase() : 'react';
6
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
6
+ const archetype = resolveArchetype(name, options.description || options.desc);
7
7
 
8
8
  if (archetype && typeof archetype.buildController === 'function') {
9
9
  const rawReactController = archetype.buildController(name, pascalName);
@@ -3,7 +3,7 @@ import { resolveArchetype } from './archetypes/index.js';
3
3
  export const buildReactComponent = (name, pascalName, options = {}) => {
4
4
  const atomsPackage = options.atomsPackage || null;
5
5
  const hasController = options.hasController !== false;
6
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
6
+ const archetype = resolveArchetype(name, options.description || options.desc);
7
7
 
8
8
  const atomImport = atomsPackage ? `import { AtomButton } from '${atomsPackage}';\n` : '';
9
9
  const controllerImport = hasController
@@ -3,7 +3,7 @@ import { resolveArchetype } from './archetypes/index.js';
3
3
  export const buildSvelteComponent = (name, pascalName, options = {}) => {
4
4
  const atomsPackage = options.atomsPackage || null;
5
5
  const hasController = options.hasController !== false;
6
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
6
+ const archetype = resolveArchetype(name, options.description || options.desc);
7
7
  const atomImport = atomsPackage ? `import { AtomButton } from '${atomsPackage}';\n` : '';
8
8
 
9
9
  const controllerImport = hasController
@@ -1,7 +1,7 @@
1
1
  import { resolveArchetype } from './archetypes/index.js';
2
2
 
3
3
  export const buildPropsType = (name, pascalName, options = {}) => {
4
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
4
+ const archetype = resolveArchetype(name, options.description || options.desc);
5
5
  if (archetype && typeof archetype.buildProps === 'function') {
6
6
  const rawProps = archetype.buildProps(name, pascalName);
7
7
  if (!rawProps.includes(`${pascalName}Emits`)) {
@@ -28,7 +28,7 @@ export interface ${pascalName}Emits {
28
28
  };
29
29
 
30
30
  export const buildStateType = (name, pascalName, options = {}) => {
31
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
31
+ const archetype = resolveArchetype(name, options.description || options.desc);
32
32
  if (archetype && typeof archetype.buildState === 'function') {
33
33
  return archetype.buildState(name, pascalName);
34
34
  }
@@ -3,7 +3,7 @@ import { resolveArchetype } from './archetypes/index.js';
3
3
  export const buildVueComponent = (name, pascalName, options = {}) => {
4
4
  const atomsPackage = options.atomsPackage || null;
5
5
  const hasController = options.hasController !== false;
6
- const archetype = resolveArchetype(name, options.description || options.desc, options.template || options.archetype);
6
+ const archetype = resolveArchetype(name, options.description || options.desc);
7
7
 
8
8
  const controllerImport = hasController
9
9
  ? `import { use${pascalName}Controller } from './${name}.controller';\n`
@@ -27,4 +27,3 @@ export {
27
27
  buildViewIndex,
28
28
  buildViewSpec
29
29
  } from './generator-templates/views.js';
30
- export { buildCompactCapsule } from './generator-templates/compact.js';
@@ -180,8 +180,3 @@ test('archetypes: resolveArchetype matches from description keywords', () => {
180
180
  const cart = resolveArchetype('m-box', 'shopping cart checkout billing payment');
181
181
  assert.equal(cart.id, 'cart-billing');
182
182
  });
183
-
184
- test('archetypes: resolveArchetype matches from semantic vector embeddings on unknown slugs', () => {
185
- const chat = resolveArchetype('m-quantum-nexus', 'live chat messages conversation thread');
186
- assert.equal(chat.id, 'chat-messaging');
187
- });
package/cli/generator.js CHANGED
@@ -5,7 +5,6 @@ import { checkOrPromptEvaluation } from './license.js';
5
5
  import {
6
6
  toPascalCase,
7
7
  toCamelCase,
8
- resolveArchetype,
9
8
  buildReactComponent,
10
9
  buildVueComponent,
11
10
  buildSvelteComponent,
@@ -26,10 +25,9 @@ import {
26
25
  buildSvelteView,
27
26
  buildViewParamsType,
28
27
  buildViewIndex,
29
- buildViewSpec,
30
- buildCompactCapsule
28
+ buildViewSpec
31
29
  } from './generator-templates.js';
32
- import { detectFramework, resolveFramework, detectTierBaseDir, detectInstalledFamily, detectTestRunner, detectStylingStack } from './project-detector.js';
30
+ import { detectFramework, resolveFramework, detectTierBaseDir, detectInstalledFamily, detectTestRunner } from './project-detector.js';
33
31
 
34
32
  const TIERS = [
35
33
  { prefix: 'm-', tier: 'molecule', label: '1. m- Molecule (Self-contained feature block < 100 lines - Recommended)' },
@@ -84,20 +82,11 @@ export const createCapsuleFiles = ({
84
82
  cwd = process.cwd(),
85
83
  desc = '',
86
84
  description = '',
87
- template = null,
88
- templateArg = null,
89
- css = null,
90
- compact = false,
91
- flat = false,
92
85
  dryRun = false
93
86
  }) => {
94
87
  const capsuleDesc = desc || description || '';
95
88
  const cleanName = (name || 'user-avatar').trim().toLowerCase();
96
89
  const selectedTier = resolveSelectedTier(tier, cleanName);
97
- const explicitTemplate = template || templateArg || null;
98
- const isCompact = Boolean(compact || flat);
99
- const styling = detectStylingStack(cwd);
100
- const wantsNoScss = css === 'none' || css === 'tailwind' || (styling.hasTailwind && css !== 'scss');
101
90
 
102
91
  const resolvedFrameworkId = resolveFramework({ frameworkArg: framework, cwd });
103
92
  const selectedFramework = FRAMEWORKS.find(
@@ -123,56 +112,6 @@ export const createCapsuleFiles = ({
123
112
  const detectedDir = detectTierBaseDir(selectedTier.tier, cwd);
124
113
  const parentDir = targetParent || detectedDir;
125
114
  const resolvedParent = path.resolve(cwd, parentDir || '.');
126
-
127
- const isHookOrView = selectedTier.tier === 'hook' || selectedTier.tier === 'view';
128
- const canUseCompact = isCompact && !isHookOrView;
129
- if (canUseCompact) {
130
- const compFile = `${capsuleName}.${selectedFramework.ext}`;
131
- const targetFilePath = path.resolve(resolvedParent, compFile);
132
-
133
- if (!dryRun && fs.existsSync(targetFilePath)) {
134
- throw new Error(`File ${compFile} already exists at ${targetFilePath}.`);
135
- }
136
-
137
- const archetype = resolveArchetype(capsuleName, capsuleDesc, explicitTemplate);
138
- const installedFamily = detectInstalledFamily(cwd);
139
- const compactContent = buildCompactCapsule({
140
- capsuleName,
141
- pascalName,
142
- framework: selectedFramework.id,
143
- archetype,
144
- atomsPackage: installedFamily.atomsPackage
145
- });
146
-
147
- const filesCreated = [compFile];
148
- const previews = [{ file: compFile, lines: compactContent.split('\n').length }];
149
-
150
- if (!dryRun) {
151
- if (!fs.existsSync(resolvedParent)) {
152
- fs.mkdirSync(resolvedParent, { recursive: true });
153
- }
154
- fs.writeFileSync(targetFilePath, compactContent, 'utf-8');
155
- }
156
-
157
- const relTargetDir = path.relative(cwd, targetFilePath);
158
-
159
- return {
160
- success: true,
161
- compact: true,
162
- dryRun: Boolean(dryRun),
163
- capsuleName,
164
- pascalName,
165
- framework: selectedFramework.id,
166
- tier: selectedTier.tier,
167
- targetDir: targetFilePath,
168
- relativeDir: relTargetDir,
169
- directory: relTargetDir,
170
- files: filesCreated,
171
- filesCreated,
172
- previews
173
- };
174
- }
175
-
176
115
  const targetDir = path.resolve(resolvedParent, capsuleName);
177
116
  const runner = detectTestRunner(targetDir || cwd);
178
117
 
@@ -231,26 +170,24 @@ export const createCapsuleFiles = ({
231
170
  atomsPackage: installedFamily.atomsPackage,
232
171
  hasController,
233
172
  description: capsuleDesc,
234
- framework: selectedFramework.id,
235
- template: explicitTemplate
173
+ framework: selectedFramework.id
236
174
  };
237
175
 
238
176
  recordFile(compFile, path.join(targetDir, compFile), selectedFramework.compBuilder(capsuleName, pascalName, templateOpts));
239
177
  recordFile('index.ts', path.join(targetDir, 'index.ts'), buildIndex(capsuleName, pascalName, selectedFramework.ext, hasController));
240
178
  recordFile(specFile, path.join(targetDir, specFile), buildComponentSpec(capsuleName, pascalName, hasController, runner));
241
179
 
242
- const domainOpts = { description: capsuleDesc, framework: selectedFramework.id, template: explicitTemplate };
243
- recordFile('types/props.d.ts', path.join(typesDir, 'props.d.ts'), buildPropsType(capsuleName, pascalName, domainOpts));
244
- recordFile('types/state.d.ts', path.join(typesDir, 'state.d.ts'), buildStateType(capsuleName, pascalName, domainOpts));
180
+ recordFile('types/props.d.ts', path.join(typesDir, 'props.d.ts'), buildPropsType(capsuleName, pascalName, { description: capsuleDesc, framework: selectedFramework.id }));
181
+ recordFile('types/state.d.ts', path.join(typesDir, 'state.d.ts'), buildStateType(capsuleName, pascalName, { description: capsuleDesc, framework: selectedFramework.id }));
245
182
  recordFile('types/index.ts', path.join(typesDir, 'index.ts'), buildTypesIndex(['props', 'state']));
246
183
  recordFile('types.d.ts', path.join(targetDir, 'types.d.ts'), "export * from './types/index';\n");
247
184
 
248
185
  if (hasController) {
249
186
  const controllerFile = `${capsuleName}.controller.ts`;
250
- recordFile(controllerFile, path.join(targetDir, controllerFile), buildController(capsuleName, pascalName, domainOpts));
187
+ recordFile(controllerFile, path.join(targetDir, controllerFile), buildController(capsuleName, pascalName, { description: capsuleDesc, framework: selectedFramework.id }));
251
188
  }
252
189
 
253
- if (!isLean && !wantsNoScss) {
190
+ if (!isLean) {
254
191
  const scssFile = `_${capsuleName}.scss`;
255
192
  recordFile(scssFile, path.join(targetDir, scssFile), buildScss(capsuleName));
256
193
  }
@@ -357,27 +294,6 @@ export const runGenerateWizard = async (rawArgs = []) => {
357
294
  .replace(/^--(desc|description|prompt)=/, '');
358
295
  const isDryRun = rawArgs.includes('--dry-run') || rawArgs.includes('-n');
359
296
 
360
- const isBareOrMinimal = rawArgs.includes('--bare') || rawArgs.includes('--minimal');
361
- const templateFlagMatch = (rawArgs.find((a) => a.startsWith('--template=')) || '').split('=')[1];
362
- let templateArg = templateFlagMatch || null;
363
- if (!templateArg && isBareOrMinimal) {
364
- templateArg = 'minimal';
365
- } else if (!templateArg && rawArgs.includes('--controls')) {
366
- templateArg = 'controls';
367
- } else if (!templateArg && rawArgs.includes('--canvas')) {
368
- templateArg = 'canvas';
369
- }
370
-
371
- const cssFlagMatch = (rawArgs.find((a) => a.startsWith('--css=')) || '').split('=')[1];
372
- let cssArg = cssFlagMatch || null;
373
- if (!cssArg && rawArgs.includes('--no-scss')) {
374
- cssArg = 'none';
375
- }
376
-
377
- const hasCompactFlag = rawArgs.includes('--compact');
378
- const hasFlatFlag = rawArgs.includes('--flat');
379
- const isCompact = hasCompactFlag || hasFlatFlag;
380
-
381
297
  if (!rawName && !isYes) {
382
298
  rawName = useGum
383
299
  ? gumInput('Capsule feature name (e.g. user-avatar, spark-kpi, auth-status):', 'user-avatar')
@@ -455,9 +371,6 @@ export const runGenerateWizard = async (rawArgs = []) => {
455
371
  isLean,
456
372
  cwd: process.cwd(),
457
373
  desc: descArg,
458
- template: templateArg,
459
- css: cssArg,
460
- compact: isCompact,
461
374
  dryRun: isDryRun
462
375
  });
463
376
  } catch (err) {
package/cli/index.js CHANGED
@@ -67,12 +67,11 @@ export const patchFile = async (...a) => (await import('./patcher.js')).pa
67
67
  export const runWriterCli = async (...a) => (await import('./patcher.js')).runWriterCli(...a);
68
68
  export const writeFile = async (...a) => (await import('./patcher.js')).writeFile(...a);
69
69
  export const runTeamCli = async (...a) => (await import('./team/index.js')).runTeamCli(...a);
70
- export const runTrend = async (...a) => (await import('./trend.js')).runTrend(...a);
71
70
  export const runPillarsWizard = async (...a) => (await import('./pillars-wizard.js')).runPillarsWizard(...a);
72
71
  export { handleError, withErrorCatcher, publishIssue };
73
72
 
74
73
  // ---------------------------------------------------------------------------
75
- // Allowed commands guard (exits early before any heavy import)
74
+ // Allowed commands guard (exits early — before any heavy import)
76
75
  // ---------------------------------------------------------------------------
77
76
 
78
77
  export const ALLOWED_COMMANDS = new Set([
@@ -81,9 +80,7 @@ export const ALLOWED_COMMANDS = new Set([
81
80
  'patch', 'edit',
82
81
  'write',
83
82
  'generate', 'g', 'gen', 'capsule', 'add',
84
- 'explode', 'unpack',
85
83
  'audit',
86
- 'trend', 'trends',
87
84
  'verify', 'check:all',
88
85
  'team', 'swarm', 'feed',
89
86
  'pillars', 'rules', 'config:pillars',
@@ -103,7 +100,7 @@ export const ALLOWED_COMMANDS = new Set([
103
100
  ]);
104
101
 
105
102
  // ---------------------------------------------------------------------------
106
- // main: thin orchestrator; real dispatch lives in cmd-router.js
103
+ // main — thin orchestrator; real dispatch lives in cmd-router.js
107
104
  // ---------------------------------------------------------------------------
108
105
 
109
106
  const main = async () => {
@@ -8,9 +8,8 @@ export const buildMcpInstructions = () => {
8
8
  '# Chemical X Protocol: Master MCP Gateway Guide (chemical-x / chemx)',
9
9
  '',
10
10
  'MASTER TOOL: "chemx" (chemical-x / chemx)',
11
- 'Provides all Chemical X operations through a single tool. This avoids requiring',
12
- 'separate approval for each sub-operation in MCP clients that gate tool access per-tool.',
13
- 'Pass the desired operation via the action parameter; see action: \'help\' for the full list.',
11
+ 'Recommended gateway tool for all Chemical X operations. Dispatches all sub-operations',
12
+ 'through a single tool for token efficiency and single-point authorization.',
14
13
  '',
15
14
  '1. TESTING, BUILDS & VERIFICATION:',
16
15
  ' - chemx({ action: "test" }) or chemx({ command: "test" })',
@@ -5,7 +5,7 @@
5
5
 
6
6
  export const MASTER_MCP_TOOL = {
7
7
  name: 'chemx',
8
- description: "Provides all Chemical X operations (search, generate, patch, audit, verify, team) through a single tool. This avoids requiring separate approval for each sub-operation in MCP clients that gate tool access per-tool. Pass the desired operation via the action parameter; see action: 'help' for the full list.",
8
+ description: 'Chemical X Protocol Master Gateway: provides all Chemical X operations (test, build, verify, typecheck, audit, read, patch, write, check, q, team, autofix, generate, patterns, issue) through a single unified tool. Recommended for token efficiency and single-point authorization.',
9
9
  inputSchema: {
10
10
  type: 'object',
11
11
  properties: {
@@ -11,7 +11,6 @@ import {
11
11
  querySemanticIndex,
12
12
  queryHybridIndex
13
13
  } from '../search-queries.js';
14
- import { findSimilarSymbols } from '../search-queries-similar.js';
15
14
  import { readTokenOptimized } from '../reader.js';
16
15
  import { patchFile, writeFile } from '../patcher.js';
17
16
  import { toColumnar } from '../columnar.js';
@@ -186,12 +185,7 @@ export const handleChemxRead = (args = {}, cwd = process.cwd()) => {
186
185
  const blast = calculateBlastRadius(db, args.symbol || targetPath);
187
186
  if (args.symbol) {
188
187
  const refs = findSymbolReferences(db, args.symbol);
189
- const similar = findSimilarSymbols(db, args.symbol, 3);
190
- const hasSimilar = similar.length > 0;
191
- const simSuffix = hasSimilar
192
- ? ` Similar symbols: ${similar.map((s) => `${s.name} (${Math.round(s.similarity * 100)}%)`).join(', ')}.`
193
- : '';
194
- connectionCard = `\n// Connections for ${args.symbol}: referenced by ${refs.length} file(s) [${refs.slice(0, 3).map((r) => path.basename(r.importerPath)).join(', ')}]. Blast Radius: ${blast.totalImpactCount} affected file(s) across ${blast.depth} hops (${blast.impactedTests.length} tests).${simSuffix}`;
188
+ connectionCard = `\n// Connections for ${args.symbol}: referenced by ${refs.length} file(s) [${refs.slice(0, 3).map((r) => path.basename(r.importerPath)).join(', ')}]. Blast Radius: ${blast.totalImpactCount} affected file(s) across ${blast.depth} hops (${blast.impactedTests.length} tests).`;
195
189
  } else {
196
190
  const deps = findFileDependencies(db, targetPath);
197
191
  const dependents = findFileDependents(db, targetPath);
package/cli/mcp/tools.js CHANGED
@@ -15,8 +15,6 @@ import { runBuildAudit } from '../build.js';
15
15
  import { runAutofix } from '../audit/autofix.js';
16
16
  import { runTypecheckAudit, runTestAudit, runProjectVerify } from '../verify.js';
17
17
  import { syncSearchIndex, syncViolationsIndex, recordAuditSnapshot } from '../search.js';
18
- import { openIndexDb } from '../search-schema.js';
19
- import { fetchScoreTrends, formatTrendReport, renderSparkline } from '../trend.js';
20
18
  import { MCP_TOOLS, ALL_MCP_TOOLS } from './manifests.js';
21
19
  import {
22
20
  resolveTargetCwd,
@@ -288,24 +286,6 @@ const handleChemxVerify = async (args = {}, cwd = process.cwd()) => {
288
286
  });
289
287
  };
290
288
 
291
- const handleChemxTrend = async (args = {}, cwd = process.cwd()) => {
292
- const targetCwd = resolveTargetCwd(args.cwd || cwd);
293
- const db = openIndexDb(targetCwd);
294
- const limit = args.limit || 10;
295
- const snapshots = fetchScoreTrends(db, limit);
296
- if (args.json) {
297
- const scores = snapshots.map((s) => s.score);
298
- return {
299
- count: snapshots.length,
300
- sparkline: renderSparkline(scores),
301
- latestScore: snapshots.length ? snapshots[snapshots.length - 1].score : null,
302
- delta: snapshots.length >= 2 ? snapshots[snapshots.length - 1].score - snapshots[0].score : 0,
303
- snapshots
304
- };
305
- }
306
- return formatTrendReport(snapshots);
307
- };
308
-
309
289
  const handleChemx = async (args = {}, cwd = process.cwd()) => {
310
290
  let action = args.action;
311
291
  let params = args.params || {};
@@ -351,14 +331,11 @@ const handleChemx = async (args = {}, cwd = process.cwd()) => {
351
331
  } else if (subCmd === 'autofix') {
352
332
  action = 'autofix';
353
333
  params = { path: parts[1] || 'src', ...params };
354
- } else if (subCmd === 'trend' || subCmd === 'trends') {
355
- action = 'trend';
356
334
  }
357
335
  }
358
336
 
359
337
  const DISPATCHER = {
360
338
  audit: handleAudit,
361
- trend: handleChemxTrend,
362
339
  build: handleAuditBuild,
363
340
  verify: handleChemxVerify,
364
341
  typecheck: handleChemxTypecheck,