@zhuan-ai/zhuanspec 2.2.1 → 2.2.3
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/dist/core/init.d.ts
CHANGED
|
@@ -50,9 +50,23 @@ export declare class InitCommand {
|
|
|
50
50
|
private fetchRemoteArchitectureContent;
|
|
51
51
|
private cloneRemoteArchitectureRepoToTemp;
|
|
52
52
|
private syncBusinessSpecTemplate;
|
|
53
|
+
private syncBusinessClaudeAssets;
|
|
54
|
+
private resolveBusinessDirectionRoot;
|
|
53
55
|
private findFirstDirectoryByName;
|
|
54
56
|
private findFirstTemplateSourceRoot;
|
|
55
57
|
private copyDirectoryContentsIfExists;
|
|
58
|
+
private resolveClaudeAssetSource;
|
|
59
|
+
private copyClaudeFileIfNeeded;
|
|
60
|
+
private copyClaudeDirectoryIfNeeded;
|
|
61
|
+
private copyClaudeDirectoryWithFallback;
|
|
62
|
+
private copyClaudeDirectoryFromSingleSource;
|
|
63
|
+
private directoryHasAtLeastOneFile;
|
|
64
|
+
private copyClaudeDirectoryByFileSystem;
|
|
65
|
+
private findGitRootForPath;
|
|
66
|
+
private safeRealpath;
|
|
67
|
+
private copyGitTrackedDirectoryFiles;
|
|
68
|
+
private mergeDirectoryWithoutOverwrite;
|
|
69
|
+
private describeClaudeAssetResult;
|
|
56
70
|
private writeTemplateFiles;
|
|
57
71
|
private configureAITools;
|
|
58
72
|
private configureRootAgentsStub;
|
package/dist/core/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import os from 'os';
|
|
3
|
-
import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, } from 'fs';
|
|
3
|
+
import { cpSync, existsSync, mkdirSync, mkdtempSync, realpathSync, writeFileSync, readdirSync, readFileSync, rmSync, } from 'fs';
|
|
4
4
|
import { createPrompt, isBackspaceKey, isDownKey, isEnterKey, isSpaceKey, isUpKey, useKeypress, usePagination, useState, } from '@inquirer/core';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import ora from 'ora';
|
|
@@ -339,6 +339,14 @@ export class InitCommand {
|
|
|
339
339
|
text: PALETTE.midGray(`未找到 ${this.businessDirection} 业务规范模板目录,保留默认模板`),
|
|
340
340
|
});
|
|
341
341
|
}
|
|
342
|
+
const claudeAssetSpinner = this.startSpinner(`正在同步 ${this.businessDirection} 业务 Claude 规范资产...`);
|
|
343
|
+
const claudeAssetResult = this.syncBusinessClaudeAssets(projectPath);
|
|
344
|
+
const claudeMdText = this.describeClaudeAssetResult('CLAUDE.md', claudeAssetResult.claudeMd);
|
|
345
|
+
const dotClaudeText = this.describeClaudeAssetResult('.claude', claudeAssetResult.dotClaude);
|
|
346
|
+
claudeAssetSpinner.stopAndPersist({
|
|
347
|
+
symbol: PALETTE.white('▌'),
|
|
348
|
+
text: PALETTE.white(`Claude 规范资产同步完成:${claudeMdText};${dotClaudeText}`),
|
|
349
|
+
});
|
|
342
350
|
}
|
|
343
351
|
// Success message
|
|
344
352
|
this.displaySuccessMessage(selectedTools, created, refreshed, skippedExisting, skipped, extendMode, rootStubStatus);
|
|
@@ -760,7 +768,7 @@ export class InitCommand {
|
|
|
760
768
|
}
|
|
761
769
|
try {
|
|
762
770
|
const specsRoot = path.join(tempDir, 'specs');
|
|
763
|
-
const businessRoot = this.
|
|
771
|
+
const businessRoot = this.resolveBusinessDirectionRoot(specsRoot);
|
|
764
772
|
if (!businessRoot) {
|
|
765
773
|
return { syncedSpecs: false, syncedChanges: false };
|
|
766
774
|
}
|
|
@@ -779,6 +787,53 @@ export class InitCommand {
|
|
|
779
787
|
rmSync(tempDir, { recursive: true, force: true });
|
|
780
788
|
}
|
|
781
789
|
}
|
|
790
|
+
syncBusinessClaudeAssets(projectPath) {
|
|
791
|
+
const fallbackResult = {
|
|
792
|
+
claudeMd: { source: 'none', status: 'missing' },
|
|
793
|
+
dotClaude: { source: 'none', status: 'missing' },
|
|
794
|
+
};
|
|
795
|
+
if (!this.businessDirection) {
|
|
796
|
+
return fallbackResult;
|
|
797
|
+
}
|
|
798
|
+
const tempDir = this.cloneRemoteArchitectureRepoToTemp();
|
|
799
|
+
if (!tempDir) {
|
|
800
|
+
return fallbackResult;
|
|
801
|
+
}
|
|
802
|
+
try {
|
|
803
|
+
const specsRoot = path.join(tempDir, 'specs');
|
|
804
|
+
const businessRoot = this.resolveBusinessDirectionRoot(specsRoot);
|
|
805
|
+
const commonClaudeRoot = path.join(specsRoot, 'common', 'claude');
|
|
806
|
+
const businessClaudeMd = businessRoot
|
|
807
|
+
? path.join(businessRoot, 'CLAUDE.md')
|
|
808
|
+
: null;
|
|
809
|
+
const commonClaudeMd = path.join(commonClaudeRoot, 'CLAUDE.md');
|
|
810
|
+
const resolvedClaudeMdSource = this.resolveClaudeAssetSource(businessClaudeMd, commonClaudeMd);
|
|
811
|
+
const businessDotClaude = businessRoot
|
|
812
|
+
? path.join(businessRoot, '.claude')
|
|
813
|
+
: null;
|
|
814
|
+
const commonDotClaude = path.join(commonClaudeRoot, '.claude');
|
|
815
|
+
return {
|
|
816
|
+
claudeMd: this.copyClaudeFileIfNeeded(resolvedClaudeMdSource, path.join(projectPath, 'CLAUDE.md')),
|
|
817
|
+
dotClaude: this.copyClaudeDirectoryWithFallback(businessDotClaude, commonDotClaude, path.join(projectPath, '.claude')),
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
catch {
|
|
821
|
+
return fallbackResult;
|
|
822
|
+
}
|
|
823
|
+
finally {
|
|
824
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
resolveBusinessDirectionRoot(specsRoot) {
|
|
828
|
+
if (!this.businessDirection) {
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
const directRoot = path.join(specsRoot, this.businessDirection);
|
|
832
|
+
if (existsSync(directRoot)) {
|
|
833
|
+
return directRoot;
|
|
834
|
+
}
|
|
835
|
+
return this.findFirstDirectoryByName(specsRoot, this.businessDirection);
|
|
836
|
+
}
|
|
782
837
|
findFirstDirectoryByName(searchRoot, targetName) {
|
|
783
838
|
if (!existsSync(searchRoot)) {
|
|
784
839
|
return null;
|
|
@@ -850,6 +905,197 @@ export class InitCommand {
|
|
|
850
905
|
}
|
|
851
906
|
return true;
|
|
852
907
|
}
|
|
908
|
+
resolveClaudeAssetSource(businessPath, commonPath) {
|
|
909
|
+
if (businessPath && existsSync(businessPath)) {
|
|
910
|
+
return { source: 'business', path: businessPath };
|
|
911
|
+
}
|
|
912
|
+
if (existsSync(commonPath)) {
|
|
913
|
+
return { source: 'common', path: commonPath };
|
|
914
|
+
}
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
copyClaudeFileIfNeeded(sourceAsset, targetPath) {
|
|
918
|
+
if (!sourceAsset) {
|
|
919
|
+
return { source: 'none', status: 'missing' };
|
|
920
|
+
}
|
|
921
|
+
if (existsSync(targetPath)) {
|
|
922
|
+
return { source: sourceAsset.source, status: 'kept-existing' };
|
|
923
|
+
}
|
|
924
|
+
cpSync(sourceAsset.path, targetPath, { force: false });
|
|
925
|
+
return { source: sourceAsset.source, status: 'copied' };
|
|
926
|
+
}
|
|
927
|
+
copyClaudeDirectoryIfNeeded(sourceAsset, targetPath) {
|
|
928
|
+
if (!sourceAsset) {
|
|
929
|
+
return { source: 'none', status: 'missing' };
|
|
930
|
+
}
|
|
931
|
+
if (!existsSync(sourceAsset.path)) {
|
|
932
|
+
return { source: sourceAsset.source, status: 'missing' };
|
|
933
|
+
}
|
|
934
|
+
const repoRoot = this.findGitRootForPath(sourceAsset.path);
|
|
935
|
+
if (!repoRoot) {
|
|
936
|
+
return this.copyClaudeDirectoryByFileSystem(sourceAsset, targetPath);
|
|
937
|
+
}
|
|
938
|
+
const canonicalRepoRoot = this.safeRealpath(repoRoot);
|
|
939
|
+
const canonicalSourcePath = this.safeRealpath(sourceAsset.path);
|
|
940
|
+
const relativeSourceDir = path
|
|
941
|
+
.relative(canonicalRepoRoot, canonicalSourcePath)
|
|
942
|
+
.split(path.sep)
|
|
943
|
+
.join('/');
|
|
944
|
+
if (relativeSourceDir.startsWith('..') ||
|
|
945
|
+
path.isAbsolute(relativeSourceDir)) {
|
|
946
|
+
return this.copyClaudeDirectoryByFileSystem(sourceAsset, targetPath);
|
|
947
|
+
}
|
|
948
|
+
const targetAlreadyExisted = existsSync(targetPath);
|
|
949
|
+
const copiedAny = this.copyGitTrackedDirectoryFiles(canonicalRepoRoot, relativeSourceDir, targetPath);
|
|
950
|
+
if (!copiedAny) {
|
|
951
|
+
return { source: sourceAsset.source, status: 'missing' };
|
|
952
|
+
}
|
|
953
|
+
return {
|
|
954
|
+
source: sourceAsset.source,
|
|
955
|
+
status: targetAlreadyExisted ? 'kept-existing' : 'copied',
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
copyClaudeDirectoryWithFallback(businessSourcePath, commonSourcePath, targetPath) {
|
|
959
|
+
const fromBusiness = this.copyClaudeDirectoryFromSingleSource(businessSourcePath, 'business', targetPath);
|
|
960
|
+
if (fromBusiness) {
|
|
961
|
+
return fromBusiness;
|
|
962
|
+
}
|
|
963
|
+
const fromCommon = this.copyClaudeDirectoryFromSingleSource(commonSourcePath, 'common', targetPath);
|
|
964
|
+
if (fromCommon) {
|
|
965
|
+
return fromCommon;
|
|
966
|
+
}
|
|
967
|
+
return { source: 'none', status: 'missing' };
|
|
968
|
+
}
|
|
969
|
+
copyClaudeDirectoryFromSingleSource(sourcePath, sourceLabel, targetPath) {
|
|
970
|
+
if (!sourcePath || !existsSync(sourcePath)) {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
if (!this.directoryHasAtLeastOneFile(sourcePath)) {
|
|
974
|
+
return null;
|
|
975
|
+
}
|
|
976
|
+
return this.copyClaudeDirectoryIfNeeded({ source: sourceLabel, path: sourcePath }, targetPath);
|
|
977
|
+
}
|
|
978
|
+
directoryHasAtLeastOneFile(dirPath) {
|
|
979
|
+
if (!existsSync(dirPath)) {
|
|
980
|
+
return false;
|
|
981
|
+
}
|
|
982
|
+
try {
|
|
983
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
984
|
+
for (const entry of entries) {
|
|
985
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
986
|
+
if (entry.isFile()) {
|
|
987
|
+
return true;
|
|
988
|
+
}
|
|
989
|
+
if (entry.isDirectory() && this.directoryHasAtLeastOneFile(fullPath)) {
|
|
990
|
+
return true;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
catch {
|
|
995
|
+
return false;
|
|
996
|
+
}
|
|
997
|
+
return false;
|
|
998
|
+
}
|
|
999
|
+
copyClaudeDirectoryByFileSystem(sourceAsset, targetPath) {
|
|
1000
|
+
if (!existsSync(targetPath)) {
|
|
1001
|
+
cpSync(sourceAsset.path, targetPath, { recursive: true, force: true });
|
|
1002
|
+
return { source: sourceAsset.source, status: 'copied' };
|
|
1003
|
+
}
|
|
1004
|
+
this.mergeDirectoryWithoutOverwrite(sourceAsset.path, targetPath);
|
|
1005
|
+
return { source: sourceAsset.source, status: 'kept-existing' };
|
|
1006
|
+
}
|
|
1007
|
+
findGitRootForPath(sourcePath) {
|
|
1008
|
+
try {
|
|
1009
|
+
const output = execSync('git rev-parse --show-toplevel', {
|
|
1010
|
+
encoding: 'utf-8',
|
|
1011
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
1012
|
+
cwd: sourcePath,
|
|
1013
|
+
});
|
|
1014
|
+
return output.trim() || null;
|
|
1015
|
+
}
|
|
1016
|
+
catch {
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
safeRealpath(targetPath) {
|
|
1021
|
+
try {
|
|
1022
|
+
return realpathSync(targetPath);
|
|
1023
|
+
}
|
|
1024
|
+
catch {
|
|
1025
|
+
return targetPath;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
copyGitTrackedDirectoryFiles(gitRoot, sourceDirRelativeToGitRoot, targetDir) {
|
|
1029
|
+
try {
|
|
1030
|
+
const sourcePrefix = sourceDirRelativeToGitRoot.endsWith('/')
|
|
1031
|
+
? sourceDirRelativeToGitRoot
|
|
1032
|
+
: `${sourceDirRelativeToGitRoot}/`;
|
|
1033
|
+
const output = execSync(`git ls-tree -r --name-only HEAD -- "${sourceDirRelativeToGitRoot}"`, {
|
|
1034
|
+
encoding: 'utf-8',
|
|
1035
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
1036
|
+
cwd: gitRoot,
|
|
1037
|
+
});
|
|
1038
|
+
const trackedFiles = output
|
|
1039
|
+
.split('\n')
|
|
1040
|
+
.map((line) => line.trim())
|
|
1041
|
+
.filter((line) => line.length > 0);
|
|
1042
|
+
if (trackedFiles.length === 0) {
|
|
1043
|
+
return false;
|
|
1044
|
+
}
|
|
1045
|
+
mkdirSync(targetDir, { recursive: true });
|
|
1046
|
+
trackedFiles.forEach((repoFilePath) => {
|
|
1047
|
+
const relativePath = repoFilePath.startsWith(sourcePrefix)
|
|
1048
|
+
? repoFilePath.slice(sourcePrefix.length)
|
|
1049
|
+
: path.basename(repoFilePath);
|
|
1050
|
+
const targetFilePath = path.join(targetDir, relativePath);
|
|
1051
|
+
if (existsSync(targetFilePath)) {
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
mkdirSync(path.dirname(targetFilePath), { recursive: true });
|
|
1055
|
+
const content = execSync(`git show HEAD:${repoFilePath}`, {
|
|
1056
|
+
encoding: 'buffer',
|
|
1057
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
1058
|
+
cwd: gitRoot,
|
|
1059
|
+
});
|
|
1060
|
+
writeFileSync(targetFilePath, content);
|
|
1061
|
+
});
|
|
1062
|
+
return true;
|
|
1063
|
+
}
|
|
1064
|
+
catch {
|
|
1065
|
+
return false;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
mergeDirectoryWithoutOverwrite(sourceDir, targetDir) {
|
|
1069
|
+
if (!existsSync(sourceDir) || !existsSync(targetDir)) {
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
const copyRecursive = (source, target) => {
|
|
1073
|
+
const entries = readdirSync(source, { withFileTypes: true });
|
|
1074
|
+
for (const entry of entries) {
|
|
1075
|
+
const sourceEntryPath = path.join(source, entry.name);
|
|
1076
|
+
const targetEntryPath = path.join(target, entry.name);
|
|
1077
|
+
if (entry.isDirectory()) {
|
|
1078
|
+
mkdirSync(targetEntryPath, { recursive: true });
|
|
1079
|
+
copyRecursive(sourceEntryPath, targetEntryPath);
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
if (!existsSync(targetEntryPath)) {
|
|
1083
|
+
cpSync(sourceEntryPath, targetEntryPath, { force: false });
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
copyRecursive(sourceDir, targetDir);
|
|
1088
|
+
}
|
|
1089
|
+
describeClaudeAssetResult(assetName, result) {
|
|
1090
|
+
if (result.status === 'missing') {
|
|
1091
|
+
return `${assetName} 未找到可用模板`;
|
|
1092
|
+
}
|
|
1093
|
+
const sourceText = result.source === 'business' ? '业务目录' : 'common/claude';
|
|
1094
|
+
if (result.status === 'kept-existing') {
|
|
1095
|
+
return `${assetName} 使用${sourceText}模板,目标已存在未覆盖`;
|
|
1096
|
+
}
|
|
1097
|
+
return `${assetName} 已从${sourceText}模板复制`;
|
|
1098
|
+
}
|
|
853
1099
|
async writeTemplateFiles(zhuanspecPath, config, skipExisting) {
|
|
854
1100
|
const context = {};
|
|
855
1101
|
const templates = TemplateManager.getTemplates(context);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const agentsRootStubTemplate = "# ZhuanSpec Instructions\n\nThese instructions are for AI assistants working in this project.\n\nAlways open `@/zhuanspec/AGENTS.md` when the request:\n- Mentions planning or proposals (words like proposal, spec, change, plan)\n- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work\n- Sounds ambiguous and you need the authoritative spec before coding\n\nUse `@/zhuanspec/AGENTS.md` to learn:\n- How to create and apply change proposals\n- Spec format and conventions\n- Project structure and guidelines\n\nKeep this managed block so 'zhuanspec update' can refresh the instructions.\n";
|
|
1
|
+
export declare const agentsRootStubTemplate = "# ZhuanSpec Instructions\n\nThese instructions are for AI assistants working in this project.\n\nAlways open `@/zhuanspec/AGENTS.md` when the request:\n- Mentions planning or proposals (words like proposal, spec, change, plan)\n- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work\n- Sounds ambiguous and you need the authoritative spec before coding\n\nUse `@/zhuanspec/AGENTS.md` to learn:\n- How to create and apply change proposals\n- Spec format and conventions\n- Project structure and guidelines\n\nKeep this managed block so 'zhuanspec update' can refresh the instructions.\n\n# Claude Instructions Bridge\n\nAlways open `@/CLAUDE.md` for this project and treat it as additional instruction context.\n\nWhen `AGENTS.md` and `CLAUDE.md` both define rules:\n- Follow higher-priority system/developer instructions first.\n- Then apply project rules from this `AGENTS.md`.\n- Then apply detailed conventions from `@/CLAUDE.md`.\n\nIf `@/CLAUDE.md` cannot be loaded, explicitly state that limitation before proceeding.\n";
|
|
2
2
|
//# sourceMappingURL=agents-root-stub.d.ts.map
|
|
@@ -13,5 +13,16 @@ Use \`@/zhuanspec/AGENTS.md\` to learn:
|
|
|
13
13
|
- Project structure and guidelines
|
|
14
14
|
|
|
15
15
|
Keep this managed block so 'zhuanspec update' can refresh the instructions.
|
|
16
|
+
|
|
17
|
+
# Claude Instructions Bridge
|
|
18
|
+
|
|
19
|
+
Always open \`@/CLAUDE.md\` for this project and treat it as additional instruction context.
|
|
20
|
+
|
|
21
|
+
When \`AGENTS.md\` and \`CLAUDE.md\` both define rules:
|
|
22
|
+
- Follow higher-priority system/developer instructions first.
|
|
23
|
+
- Then apply project rules from this \`AGENTS.md\`.
|
|
24
|
+
- Then apply detailed conventions from \`@/CLAUDE.md\`.
|
|
25
|
+
|
|
26
|
+
If \`@/CLAUDE.md\` cannot be loaded, explicitly state that limitation before proceeding.
|
|
16
27
|
`;
|
|
17
28
|
//# sourceMappingURL=agents-root-stub.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhuan-ai/zhuanspec",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "AI-native system for spec-driven development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zhuanspec",
|
|
@@ -38,6 +38,26 @@
|
|
|
38
38
|
"!dist/**/__tests__",
|
|
39
39
|
"!dist/**/*.map"
|
|
40
40
|
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"lint": "eslint src/",
|
|
43
|
+
"build": "node build.js",
|
|
44
|
+
"dev": "tsc --watch",
|
|
45
|
+
"dev:cli": "pnpm build && node bin/zhuanspec.js",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"test:ui": "vitest --ui",
|
|
49
|
+
"test:coverage": "vitest --coverage",
|
|
50
|
+
"test:postinstall": "node scripts/postinstall.js",
|
|
51
|
+
"prepare": "npm run build",
|
|
52
|
+
"prepublishOnly": "npm run build",
|
|
53
|
+
"postinstall": "node scripts/postinstall.js",
|
|
54
|
+
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
55
|
+
"diagnose:cursor": "node scripts/diagnose-cursor-commands.js",
|
|
56
|
+
"release": "pnpm run release:ci",
|
|
57
|
+
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
58
|
+
"release:local": "pnpm exec changeset version && pnpm run check:pack-version && pnpm exec changeset publish",
|
|
59
|
+
"changeset": "changeset"
|
|
60
|
+
},
|
|
41
61
|
"engines": {
|
|
42
62
|
"node": ">=20.19.0"
|
|
43
63
|
},
|
|
@@ -59,23 +79,5 @@
|
|
|
59
79
|
"ora": "^8.2.0",
|
|
60
80
|
"yaml": "^2.8.2",
|
|
61
81
|
"zod": "^4.0.17"
|
|
62
|
-
},
|
|
63
|
-
"scripts": {
|
|
64
|
-
"lint": "eslint src/",
|
|
65
|
-
"build": "node build.js",
|
|
66
|
-
"dev": "tsc --watch",
|
|
67
|
-
"dev:cli": "pnpm build && node bin/zhuanspec.js",
|
|
68
|
-
"test": "vitest run",
|
|
69
|
-
"test:watch": "vitest",
|
|
70
|
-
"test:ui": "vitest --ui",
|
|
71
|
-
"test:coverage": "vitest --coverage",
|
|
72
|
-
"test:postinstall": "node scripts/postinstall.js",
|
|
73
|
-
"postinstall": "node scripts/postinstall.js",
|
|
74
|
-
"check:pack-version": "node scripts/pack-version-check.mjs",
|
|
75
|
-
"diagnose:cursor": "node scripts/diagnose-cursor-commands.js",
|
|
76
|
-
"release": "pnpm run release:ci",
|
|
77
|
-
"release:ci": "pnpm run check:pack-version && pnpm exec changeset publish",
|
|
78
|
-
"release:local": "pnpm exec changeset version && pnpm run check:pack-version && pnpm exec changeset publish",
|
|
79
|
-
"changeset": "changeset"
|
|
80
82
|
}
|
|
81
|
-
}
|
|
83
|
+
}
|