magic-spec 1.5.71 → 1.5.159
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 +183 -144
- package/LICENSE +201 -21
- package/README.md +326 -323
- package/installers/config.json +19 -2
- package/installers/node/index.js +72 -16
- package/package.json +2 -2
package/installers/config.json
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
"magic.spec",
|
|
17
17
|
"magic.task"
|
|
18
18
|
],
|
|
19
|
+
"devWorkflows": [
|
|
20
|
+
"magic.dev.simulate"
|
|
21
|
+
],
|
|
22
|
+
"devSkills": [
|
|
23
|
+
"magic.dev.simulate"
|
|
24
|
+
],
|
|
19
25
|
"magicFiles": [
|
|
20
26
|
"analyze.md",
|
|
21
27
|
"init.md",
|
|
@@ -31,11 +37,17 @@
|
|
|
31
37
|
"scripts/generate-checksums.js",
|
|
32
38
|
"scripts/generate-context.js",
|
|
33
39
|
"scripts/init.js",
|
|
40
|
+
"scripts/sync-skills.js",
|
|
34
41
|
"templates/plan.md",
|
|
35
42
|
"templates/retrospective.md",
|
|
36
43
|
"templates/spec.md",
|
|
37
44
|
"templates/tasks.md"
|
|
38
45
|
],
|
|
46
|
+
"devMagicFiles": [
|
|
47
|
+
"simulate.md",
|
|
48
|
+
"tests/engine.js",
|
|
49
|
+
"tests/suite.md"
|
|
50
|
+
],
|
|
39
51
|
"download": {
|
|
40
52
|
"timeoutMs": 10000,
|
|
41
53
|
"tempPrefix": "magic-spec-tmp-"
|
|
@@ -48,6 +60,7 @@
|
|
|
48
60
|
"targets": [
|
|
49
61
|
".magic",
|
|
50
62
|
".agents",
|
|
63
|
+
"skills",
|
|
51
64
|
"installers"
|
|
52
65
|
]
|
|
53
66
|
},
|
|
@@ -55,10 +68,14 @@
|
|
|
55
68
|
"versionFiles": [
|
|
56
69
|
"package.json",
|
|
57
70
|
"pyproject.toml",
|
|
58
|
-
"installers/python/magic_spec/__init__.py"
|
|
71
|
+
"installers/python/magic_spec/__init__.py",
|
|
72
|
+
".magic/.version",
|
|
73
|
+
".magic/.checksums"
|
|
59
74
|
],
|
|
60
75
|
"docsTargets": [
|
|
61
|
-
"CHANGELOG.md"
|
|
76
|
+
"CHANGELOG.md",
|
|
77
|
+
"README.md",
|
|
78
|
+
"docs/README.md"
|
|
62
79
|
]
|
|
63
80
|
},
|
|
64
81
|
"tests": {
|
package/installers/node/index.js
CHANGED
|
@@ -70,12 +70,16 @@ function loadInstallerConfig() {
|
|
|
70
70
|
const defaultExt = requireNonEmptyString(parsed.defaultExt, 'defaultExt');
|
|
71
71
|
const workflows = Array.isArray(parsed.workflows) ? parsed.workflows : null;
|
|
72
72
|
if (!workflows) {
|
|
73
|
-
failConfig("field 'workflows' must be
|
|
73
|
+
failConfig("field 'workflows' must be a non-empty array");
|
|
74
74
|
}
|
|
75
|
+
const devWorkflows = Array.isArray(parsed.devWorkflows) ? parsed.devWorkflows : [];
|
|
76
|
+
|
|
75
77
|
const magicFiles = Array.isArray(parsed.magicFiles) ? parsed.magicFiles : null;
|
|
76
78
|
if (!magicFiles) {
|
|
77
|
-
failConfig("field 'magicFiles' must be
|
|
79
|
+
failConfig("field 'magicFiles' must be a non-empty array");
|
|
78
80
|
}
|
|
81
|
+
const devMagicFiles = Array.isArray(parsed.devMagicFiles) ? parsed.devMagicFiles : [];
|
|
82
|
+
const devSkills = Array.isArray(parsed.devSkills) ? parsed.devSkills : [];
|
|
79
83
|
|
|
80
84
|
const designDir = requireNonEmptyString(parsed.designDir, 'designDir');
|
|
81
85
|
const versionFile = requireNonEmptyString(parsed.versionFile, 'versionFile');
|
|
@@ -95,7 +99,10 @@ function loadInstallerConfig() {
|
|
|
95
99
|
historyDir,
|
|
96
100
|
defaultExt,
|
|
97
101
|
workflows,
|
|
102
|
+
devWorkflows,
|
|
98
103
|
magicFiles,
|
|
104
|
+
devMagicFiles,
|
|
105
|
+
devSkills,
|
|
99
106
|
download: { timeoutMs, tempPrefix },
|
|
100
107
|
userAgent: { node: nodeUserAgent },
|
|
101
108
|
ejectTargets: parsed.eject.targets
|
|
@@ -109,8 +116,11 @@ const ENGINE_DIR = INSTALLER_CONFIG.engineDir;
|
|
|
109
116
|
const AGENT_DIR = INSTALLER_CONFIG.agentDir;
|
|
110
117
|
const WORKFLOWS_DIR = INSTALLER_CONFIG.workflowsDir;
|
|
111
118
|
const DEFAULT_EXT = INSTALLER_CONFIG.defaultExt;
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
let WORKFLOWS = [...INSTALLER_CONFIG.workflows];
|
|
120
|
+
let MAGIC_FILES = [...INSTALLER_CONFIG.magicFiles];
|
|
121
|
+
const DEV_WORKFLOWS = INSTALLER_CONFIG.devWorkflows;
|
|
122
|
+
const DEV_MAGIC_FILES = INSTALLER_CONFIG.devMagicFiles;
|
|
123
|
+
const DEV_SKILLS = INSTALLER_CONFIG.devSkills;
|
|
114
124
|
const DESIGN_DIR = INSTALLER_CONFIG.designDir;
|
|
115
125
|
const VERSION_FILE = INSTALLER_CONFIG.versionFile;
|
|
116
126
|
const CHECKSUMS_FILE = INSTALLER_CONFIG.checksumsFile;
|
|
@@ -130,6 +140,7 @@ const isListEnvs = args.includes('--list-envs');
|
|
|
130
140
|
const isEject = args.includes('--eject');
|
|
131
141
|
const isFallbackMain = args.includes('--fallback-main');
|
|
132
142
|
const isLocal = args.includes('--local');
|
|
143
|
+
const isDev = args.includes('--dev');
|
|
133
144
|
const autoAccept = args.includes('--yes') || args.includes('-y');
|
|
134
145
|
|
|
135
146
|
function parseCsvValues(raw) {
|
|
@@ -331,24 +342,16 @@ function installAdapter(sourceRoot, env, adapters, conflictsToSkip = []) {
|
|
|
331
342
|
}
|
|
332
343
|
|
|
333
344
|
function runDoctor() {
|
|
334
|
-
const
|
|
335
|
-
const checkScript = isWindows
|
|
336
|
-
? path.join(cwd, ENGINE_DIR, 'scripts', 'check-prerequisites.ps1')
|
|
337
|
-
: path.join(cwd, ENGINE_DIR, 'scripts', 'check-prerequisites.sh');
|
|
345
|
+
const checkScript = path.join(cwd, ENGINE_DIR, 'scripts', 'check-prerequisites.js');
|
|
338
346
|
|
|
339
347
|
if (!fs.existsSync(checkScript)) {
|
|
340
|
-
console.error('❌ Error: SDD engine not initialized. Run magic-spec first.');
|
|
348
|
+
console.error('❌ Error: SDD engine not initialized or check-prerequisites.js missing. Run magic-spec first.');
|
|
341
349
|
process.exit(1);
|
|
342
350
|
}
|
|
343
351
|
|
|
344
352
|
console.log(`🔍 ${PACKAGE_NAME} Doctor:`);
|
|
345
353
|
try {
|
|
346
|
-
|
|
347
|
-
if (isWindows) {
|
|
348
|
-
result = spawnSync('powershell.exe', ['-ExecutionPolicy', 'Bypass', '-File', checkScript, '-json'], { encoding: 'utf-8' });
|
|
349
|
-
} else {
|
|
350
|
-
result = spawnSync('bash', [checkScript, '--json'], { encoding: 'utf-8' });
|
|
351
|
-
}
|
|
354
|
+
const result = spawnSync('node', [checkScript, '--json'], { encoding: 'utf-8' });
|
|
352
355
|
|
|
353
356
|
if (result.error) {
|
|
354
357
|
console.error('❌ Failed to run doctor prerequisite check:', result.error.message);
|
|
@@ -763,6 +766,7 @@ async function main() {
|
|
|
763
766
|
console.log(" --env <adapter> Specify environment adapter");
|
|
764
767
|
console.log(" --<adapter> Shortcut for --env <adapter> (e.g. --cursor)");
|
|
765
768
|
console.log(" --update Update engine and adapter files");
|
|
769
|
+
console.log(" --dev Install development instruments (simulation, testing)");
|
|
766
770
|
console.log(" --local Use local project files instead of GitHub");
|
|
767
771
|
console.log(" --fallback-main Pull payload from main branch");
|
|
768
772
|
console.log(" --yes, -y Auto-accept prompts");
|
|
@@ -775,6 +779,13 @@ async function main() {
|
|
|
775
779
|
createBackup();
|
|
776
780
|
}
|
|
777
781
|
|
|
782
|
+
if (isDev) {
|
|
783
|
+
console.log("🛠️ Development instruments enabled.");
|
|
784
|
+
// Append dev workflows and engine files to the active set
|
|
785
|
+
WORKFLOWS = [...WORKFLOWS, ...DEV_WORKFLOWS];
|
|
786
|
+
MAGIC_FILES = [...MAGIC_FILES, ...DEV_MAGIC_FILES];
|
|
787
|
+
}
|
|
788
|
+
|
|
778
789
|
const versionToFetch = isFallbackMain ? 'main' : version;
|
|
779
790
|
let sourceRoot = null;
|
|
780
791
|
|
|
@@ -912,6 +923,39 @@ async function main() {
|
|
|
912
923
|
}
|
|
913
924
|
}
|
|
914
925
|
|
|
926
|
+
// If `--dev` is specified during update, ensure dev tools are present
|
|
927
|
+
if (isUpdate && isDev) {
|
|
928
|
+
const srcEng = path.join(sourceRoot, AGENT_DIR);
|
|
929
|
+
const destEng = path.join(cwd, AGENT_DIR);
|
|
930
|
+
|
|
931
|
+
// Sync dev workflows
|
|
932
|
+
const srcWfDir = path.join(srcEng, WORKFLOWS_DIR);
|
|
933
|
+
const destWfDir = path.join(destEng, WORKFLOWS_DIR);
|
|
934
|
+
if (fs.existsSync(srcWfDir)) {
|
|
935
|
+
fs.mkdirSync(destWfDir, { recursive: true });
|
|
936
|
+
for (const wf of DEV_WORKFLOWS) {
|
|
937
|
+
const file = wf + DEFAULT_EXT;
|
|
938
|
+
const sf = path.join(srcWfDir, file);
|
|
939
|
+
if (fs.existsSync(sf)) {
|
|
940
|
+
fs.copyFileSync(sf, path.join(destWfDir, file));
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// Sync dev skills
|
|
946
|
+
const srcSkillsDir = path.join(srcEng, 'skills');
|
|
947
|
+
const destSkillsDir = path.join(destEng, 'skills');
|
|
948
|
+
if (fs.existsSync(srcSkillsDir)) {
|
|
949
|
+
fs.mkdirSync(destSkillsDir, { recursive: true });
|
|
950
|
+
for (const sk of DEV_SKILLS) {
|
|
951
|
+
const ss = path.join(srcSkillsDir, sk);
|
|
952
|
+
if (fs.existsSync(ss) && fs.statSync(ss).isDirectory()) {
|
|
953
|
+
copyDir(ss, path.join(destSkillsDir, sk));
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
915
959
|
// 3. Init script
|
|
916
960
|
if (!isUpdate) {
|
|
917
961
|
const isWindows = process.platform === 'win32';
|
|
@@ -954,6 +998,18 @@ async function main() {
|
|
|
954
998
|
console.log(`✅ ${PACKAGE_NAME} updated successfully!`);
|
|
955
999
|
}
|
|
956
1000
|
|
|
1001
|
+
// 3.5. Sync Skill Wrappers
|
|
1002
|
+
const syncScript = path.join(cwd, ENGINE_DIR, 'scripts', 'sync-skills.js');
|
|
1003
|
+
if (fs.existsSync(syncScript)) {
|
|
1004
|
+
console.log('🔄 Projecting Workflows to Skill Wrappers...');
|
|
1005
|
+
const syncResult = spawnSync('node', [syncScript], { cwd });
|
|
1006
|
+
if (syncResult.error || syncResult.status !== 0) {
|
|
1007
|
+
console.warn(`⚠️ Skill synchronization failed: ${syncResult.stderr || syncResult.error?.message}`);
|
|
1008
|
+
} else {
|
|
1009
|
+
console.log('✅ Skills synchronized.');
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
|
|
957
1013
|
// 4. Write version file - [T-2B01]
|
|
958
1014
|
try {
|
|
959
1015
|
const versionFileDest = path.join(cwd, ENGINE_DIR, VERSION_FILE);
|
|
@@ -963,7 +1019,7 @@ async function main() {
|
|
|
963
1019
|
}
|
|
964
1020
|
|
|
965
1021
|
// 5. Auto-update .gitignore
|
|
966
|
-
const gitignoreEntries = [ENGINE_DIR];
|
|
1022
|
+
const gitignoreEntries = [ENGINE_DIR, 'skills'];
|
|
967
1023
|
if (envValues.length > 0) {
|
|
968
1024
|
for (const env of envValues) {
|
|
969
1025
|
const adapter = ADAPTERS[env];
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magic-spec",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.159",
|
|
4
4
|
"description": "Magic Specification-Driven Development (SDD) Workflow",
|
|
5
5
|
"author": "Oleg Alexandrov <alexandrovoleg.ru@gmail.com>",
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
7
|
"homepage": "https://github.com/teratron/magic-spec",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|