magic-spec 1.4.0 β†’ 1.4.2

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/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.4.2] - 2026-03-01
9
+
10
+ ### Fixed
11
+
12
+ - **Localization**: Translated remaining Russian text in `README.md` Mermaid diagrams to English.
13
+
8
14
  ## [1.4.0] - 2026-03-01
9
15
 
10
16
  ### Added
package/README.md CHANGED
@@ -55,7 +55,7 @@ The engine enforces a rigorous, unskippable pipeline: **Idea β†’ Specification
55
55
 
56
56
  ```mermaid
57
57
  flowchart TB
58
- IDEA(["πŸ’‘ ИдСя"])
58
+ IDEA(["πŸ’‘ Idea"])
59
59
 
60
60
  subgraph BOX ["Magic Spec"]
61
61
  direction TB
@@ -75,7 +75,7 @@ flowchart TB
75
75
  TASKS --> RUN
76
76
  end
77
77
 
78
- CODE(["πŸš€ Код"])
78
+ CODE(["πŸš€ Code"])
79
79
 
80
80
  IDEA --> SPEC
81
81
  RUN --> CODE
@@ -65,5 +65,13 @@
65
65
  "CHANGELOG.md"
66
66
  ],
67
67
  "docsDir": "docs"
68
+ },
69
+ "tests": {
70
+ "sandboxDir": "installers/tests/sandbox",
71
+ "adaptersJson": "installers/adapters.json",
72
+ "pythonInstaller": "installers/python/magic_spec/__main__.py",
73
+ "nodeInstaller": "installers/node/index.js",
74
+ "testDir": "installers/tests",
75
+ "testPattern": "test_*.py"
68
76
  }
69
77
  }
@@ -116,6 +116,7 @@ const isInfo = args.includes('info');
116
116
  const isListEnvs = args.includes('--list-envs');
117
117
  const isEject = args.includes('--eject');
118
118
  const isFallbackMain = args.includes('--fallback-main');
119
+ const isLocal = args.includes('--local');
119
120
  const autoAccept = args.includes('--yes') || args.includes('-y');
120
121
 
121
122
  function parseCsvValues(raw) {
@@ -331,16 +332,20 @@ function runInfo() {
331
332
  }
332
333
  console.log(`Installed version : ${installedVersion} (.magic/.version)`);
333
334
 
334
- const magicrcFile = path.join(cwd, '.magicrc');
335
- let activeEnv = 'default (.agent/)';
336
- if (fs.existsSync(magicrcFile)) {
335
+ const ADAPTERS_PATH = path.join(__dirname, '..', 'adapters.json');
336
+ let activeEnvs = [];
337
+ if (fs.existsSync(ADAPTERS_PATH)) {
337
338
  try {
338
- const rc = JSON.parse(fs.readFileSync(magicrcFile, 'utf8'));
339
- if (rc.env) activeEnv = rc.env;
339
+ const adapters = JSON.parse(fs.readFileSync(ADAPTERS_PATH, 'utf8'));
340
+ activeEnvs = detectEnvironments(adapters);
340
341
  } catch (e) { }
341
342
  }
342
- console.log(`Active env : ${activeEnv}`);
343
343
 
344
+ if (activeEnvs.length === 0) {
345
+ console.log(`Active env : default (${AGENT_DIR}/)`);
346
+ } else {
347
+ console.log(`Active envs : ${activeEnvs.join(', ')}`);
348
+ }
344
349
  const enginePresent = fs.existsSync(path.join(cwd, ENGINE_DIR));
345
350
  console.log(`Engine : ${ENGINE_DIR}/ ${enginePresent ? 'βœ… present' : '❌ missing'}`);
346
351
 
@@ -431,18 +436,17 @@ async function runEject() {
431
436
  }
432
437
  }
433
438
 
434
- function detectEnvironment(adapters) {
439
+ function detectEnvironments(adapters) {
440
+ const detected = [];
435
441
  for (const env in adapters) {
436
442
  const marker = adapters[env].marker;
437
- if (marker && fs.existsSync(path.join(cwd, marker))) return env;
443
+ if (marker && fs.existsSync(path.join(cwd, marker))) {
444
+ detected.push(env);
445
+ }
438
446
  }
439
- return null;
447
+ return detected;
440
448
  }
441
449
 
442
- function saveMagicRc(config) {
443
- const magicrcFile = path.join(cwd, '.magicrc');
444
- fs.writeFileSync(magicrcFile, JSON.stringify(config, null, 2), 'utf8');
445
- }
446
450
 
447
451
  function getFileChecksum(filePath) {
448
452
  if (!fs.existsSync(filePath)) return null;
@@ -662,6 +666,7 @@ async function main() {
662
666
  console.log(" --env <adapter> Specify environment adapter");
663
667
  console.log(" --<adapter> Shortcut for --env <adapter> (e.g. --cursor)");
664
668
  console.log(" --update Update engine files only");
669
+ console.log(" --local Use local project files instead of GitHub");
665
670
  console.log(" --fallback-main Pull payload from main branch");
666
671
  console.log(" --yes, -y Auto-accept prompts");
667
672
  process.exit(0);
@@ -676,18 +681,16 @@ async function main() {
676
681
  const versionToFetch = isFallbackMain ? 'main' : version;
677
682
  let sourceRoot = null;
678
683
 
679
- // Load .magicrc
680
- let magicrc = {};
681
- const magicrcFile = path.join(cwd, '.magicrc');
682
- if (fs.existsSync(magicrcFile)) {
683
- try {
684
- magicrc = JSON.parse(fs.readFileSync(magicrcFile, 'utf8'));
685
- } catch (e) { }
684
+ if (isLocal) {
685
+ // In local mode, source root is the parent of 'installers' folder
686
+ sourceRoot = path.resolve(__dirname, '..', '..');
687
+ console.log(`🏠 Using local project files from: ${sourceRoot}`);
686
688
  }
687
689
 
688
690
  try {
689
- sourceRoot = await downloadPayload(versionToFetch);
690
-
691
+ if (!isLocal) {
692
+ sourceRoot = await downloadPayload(versionToFetch);
693
+ }
691
694
  let ADAPTERS = {};
692
695
  try {
693
696
  ADAPTERS = JSON.parse(fs.readFileSync(path.join(sourceRoot, 'installers', 'adapters.json'), 'utf8'));
@@ -706,29 +709,32 @@ async function main() {
706
709
  }
707
710
  }
708
711
 
709
- let selectedEnvResolved = null;
710
712
  if (envValues.length > 0) {
711
713
  selectedEnvResolved = envValues[0];
712
- } else if (magicrc.env && magicrc.env !== 'default') {
713
- selectedEnvResolved = magicrc.env;
714
- }
715
-
716
- if (!selectedEnvResolved && !isUpdate) {
717
- const detected = detectEnvironment(ADAPTERS);
718
- if (detected && ADAPTERS[detected] && (!magicrc.env || magicrc.env === 'default')) {
719
- const adapterName = ADAPTERS[detected].description || detected;
720
- console.log(`\nπŸ’‘ Detected ${adapterName} (${detected}/ directory found).`);
721
- let shouldAdopt = autoAccept;
722
- if (!shouldAdopt) {
723
- const answer = await askQuestion(` Install ${detected} adapter instead of default? (y/N): `);
724
- shouldAdopt = answer.toLowerCase() === 'y';
725
- }
726
- if (shouldAdopt) {
727
- selectedEnvResolved = detected;
714
+ }
715
+
716
+ if (envValues.length === 0 && !isUpdate) {
717
+ const detected = detectEnvironments(ADAPTERS);
718
+ if (detected.length > 0) {
719
+ // If only one detected, we can suggest it. If multiple, we need user choice or explicit flags.
720
+ if (detected.length === 1) {
721
+ const env = detected[0];
722
+ const adapterName = ADAPTERS[env].description || env;
723
+ console.log(`\nπŸ’‘ Detected ${adapterName} (${ADAPTERS[env].marker}/ directory found).`);
724
+ let shouldAdopt = autoAccept;
725
+ if (!shouldAdopt) {
726
+ const answer = await askQuestion(` Install ${env} adapter instead of default? (y/N): `);
727
+ shouldAdopt = answer.toLowerCase() === 'y';
728
+ }
729
+ if (shouldAdopt) {
730
+ selectedEnvResolved = env;
731
+ }
732
+ } else {
733
+ console.log(`\nπŸ’‘ Multiple environments detected: ${detected.join(', ')}`);
734
+ console.log(` Use --env <name> or --<name> to target specific one.`);
728
735
  }
729
736
  }
730
737
  }
731
-
732
738
  let conflictsToSkip = [];
733
739
  if (isUpdate) {
734
740
  const conflictResult = await handleConflicts(cwd);
@@ -842,16 +848,6 @@ async function main() {
842
848
  console.warn(`⚠️ Failed to write .magic/.version: ${vErr.message}`);
843
849
  }
844
850
 
845
- // 5. Update .magicrc - [T-2C02]
846
- try {
847
- const newConfig = {
848
- env: selectedEnvResolved || magicrc.env || 'default',
849
- version: version
850
- };
851
- saveMagicRc(newConfig);
852
- } catch (rcErr) {
853
- console.warn(`⚠️ Failed to update .magicrc: ${rcErr.message}`);
854
- }
855
851
 
856
852
  // 6. Save checksums - [T-2C03]
857
853
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magic-spec",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Magic Specification-Driven Development (SDD) Workflow",
5
5
  "author": "Oleg Alexandrov <alexandrovoleg.ru@gmail.com>",
6
6
  "license": "MIT",