skillpp 0.1.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 (208) hide show
  1. package/COMPATIBILITY.md +58 -0
  2. package/LICENSE +21 -0
  3. package/README.md +307 -0
  4. package/README.zh-CN.md +307 -0
  5. package/SKILL.md +490 -0
  6. package/adapters/binance-ai.md +22 -0
  7. package/adapters/claude.md +21 -0
  8. package/adapters/gemini.md +26 -0
  9. package/adapters/gpt.md +28 -0
  10. package/adapters/kimi.md +26 -0
  11. package/adapters/mimo.md +22 -0
  12. package/adapters/openclaw.md +29 -0
  13. package/assets/skillpp-banner.png +0 -0
  14. package/package.json +59 -0
  15. package/pipelines.md +310 -0
  16. package/prompts/newbie-mode.md +48 -0
  17. package/prompts/router-prompt.md +32 -0
  18. package/prompts/universal-system-prompt.md +41 -0
  19. package/registry.md +209 -0
  20. package/rules.md +323 -0
  21. package/schemas/audit.schema.json +67 -0
  22. package/schemas/checkpoint.schema.json +86 -0
  23. package/schemas/handoff.schema.json +82 -0
  24. package/schemas/token.schema.json +36 -0
  25. package/scripts/compatibility-check.mjs +130 -0
  26. package/scripts/selftest.mjs +384 -0
  27. package/scripts/skillpp.mjs +448 -0
  28. package/scripts/validate-skillpp.mjs +140 -0
  29. package/skillpp.manifest.json +714 -0
  30. package/skills/audit-plus/SKILL.md +612 -0
  31. package/skills/binance/binance/CHANGELOG.md +112 -0
  32. package/skills/binance/binance/LICENSE.md +9 -0
  33. package/skills/binance/binance/SKILL.md +69 -0
  34. package/skills/binance/binance/references/algo.md +21 -0
  35. package/skills/binance/binance/references/alpha.md +9 -0
  36. package/skills/binance/binance/references/auth.md +32 -0
  37. package/skills/binance/binance/references/c2c.md +5 -0
  38. package/skills/binance/binance/references/convert.md +19 -0
  39. package/skills/binance/binance/references/copy-trading.md +6 -0
  40. package/skills/binance/binance/references/crypto-loan.md +27 -0
  41. package/skills/binance/binance/references/derivatives-options-streams.md +25 -0
  42. package/skills/binance/binance/references/derivatives-options.md +85 -0
  43. package/skills/binance/binance/references/derivatives-portfolio-margin-pro-streams.md +5 -0
  44. package/skills/binance/binance/references/derivatives-portfolio-margin-pro.md +34 -0
  45. package/skills/binance/binance/references/derivatives-portfolio-margin-streams.md +5 -0
  46. package/skills/binance/binance/references/derivatives-portfolio-margin.md +146 -0
  47. package/skills/binance/binance/references/dual-investment.md +15 -0
  48. package/skills/binance/binance/references/fiat.md +9 -0
  49. package/skills/binance/binance/references/futures-coin-streams.md +29 -0
  50. package/skills/binance/binance/references/futures-coin.md +109 -0
  51. package/skills/binance/binance/references/futures-usds-streams.md +35 -0
  52. package/skills/binance/binance/references/futures-usds.md +144 -0
  53. package/skills/binance/binance/references/gift-card.md +10 -0
  54. package/skills/binance/binance/references/margin-trading-streams.md +6 -0
  55. package/skills/binance/binance/references/margin-trading.md +101 -0
  56. package/skills/binance/binance/references/mining.md +17 -0
  57. package/skills/binance/binance/references/pay.md +5 -0
  58. package/skills/binance/binance/references/rebate.md +5 -0
  59. package/skills/binance/binance/references/simple-earn.md +56 -0
  60. package/skills/binance/binance/references/spot-streams.md +25 -0
  61. package/skills/binance/binance/references/spot.md +114 -0
  62. package/skills/binance/binance/references/staking.md +59 -0
  63. package/skills/binance/binance/references/sub-account.md +67 -0
  64. package/skills/binance/binance/references/vip-loan.md +27 -0
  65. package/skills/binance/binance/references/wallet.md +75 -0
  66. package/skills/binance/fiat/CHANGELOG.md +11 -0
  67. package/skills/binance/fiat/LICENSE.md +9 -0
  68. package/skills/binance/fiat/SKILL.md +169 -0
  69. package/skills/binance/fiat/references/authentication.md +126 -0
  70. package/skills/binance/fiat/references/sapi-endpoints.md +217 -0
  71. package/skills/binance/onchain-pay/.local.md.example +10 -0
  72. package/skills/binance/onchain-pay/CHANGELOG.md +20 -0
  73. package/skills/binance/onchain-pay/LICENSE.md +9 -0
  74. package/skills/binance/onchain-pay/SKILL.md +466 -0
  75. package/skills/binance/onchain-pay/references/authentication.md +92 -0
  76. package/skills/binance/onchain-pay/scripts/sign_and_call.sh +52 -0
  77. package/skills/binance/p2p/CHANGELOG.md +33 -0
  78. package/skills/binance/p2p/LICENSE.md +9 -0
  79. package/skills/binance/p2p/SKILL.md +1082 -0
  80. package/skills/binance/p2p/references/agent-sapi-api.md +795 -0
  81. package/skills/binance/p2p/references/authentication.md +100 -0
  82. package/skills/binance/payment/SKILL.md +824 -0
  83. package/skills/binance/payment/common.py +560 -0
  84. package/skills/binance/payment/payment_skill.py +86 -0
  85. package/skills/binance/payment/receive.py +109 -0
  86. package/skills/binance/payment/references/setup-guide.md +77 -0
  87. package/skills/binance/payment/requirements.txt +4 -0
  88. package/skills/binance/payment/send.py +952 -0
  89. package/skills/binance/payment/send_extension/__init__.py +43 -0
  90. package/skills/binance/payment/send_extension/base.py +48 -0
  91. package/skills/binance/payment/send_extension/c2c.py +193 -0
  92. package/skills/binance/payment/send_extension/pix.py +316 -0
  93. package/skills/binance/square-post/README.md +62 -0
  94. package/skills/binance/square-post/SKILL.md +171 -0
  95. package/skills/binance/square-post/scripts/lib.mjs +175 -0
  96. package/skills/binance/square-post/scripts/post-image.mjs +80 -0
  97. package/skills/binance/square-post/scripts/post-text.mjs +41 -0
  98. package/skills/binance/square-post/scripts/post-video.mjs +110 -0
  99. package/skills/binance/square-post/scripts/save-key.mjs +34 -0
  100. package/skills/binance-web3/binance-agentic-wallet/SKILL.md +150 -0
  101. package/skills/binance-web3/binance-agentic-wallet/references/authentication.md +136 -0
  102. package/skills/binance-web3/binance-agentic-wallet/references/limit-order.md +204 -0
  103. package/skills/binance-web3/binance-agentic-wallet/references/market-order.md +179 -0
  104. package/skills/binance-web3/binance-agentic-wallet/references/prediction.md +489 -0
  105. package/skills/binance-web3/binance-agentic-wallet/references/preflight.md +66 -0
  106. package/skills/binance-web3/binance-agentic-wallet/references/security.md +47 -0
  107. package/skills/binance-web3/binance-agentic-wallet/references/send.md +53 -0
  108. package/skills/binance-web3/binance-agentic-wallet/references/wallet-setting.md +86 -0
  109. package/skills/binance-web3/binance-agentic-wallet/references/wallet-view.md +312 -0
  110. package/skills/binance-web3/binance-agentic-wallet/references/x402-payment.md +259 -0
  111. package/skills/binance-web3/binance-tokenized-securities-info/SKILL.md +613 -0
  112. package/skills/binance-web3/crypto-market-rank/SKILL.md +91 -0
  113. package/skills/binance-web3/crypto-market-rank/references/cli.md +219 -0
  114. package/skills/binance-web3/crypto-market-rank/scripts/cli.mjs +149 -0
  115. package/skills/binance-web3/meme-rush/SKILL.md +72 -0
  116. package/skills/binance-web3/meme-rush/references/cli.md +158 -0
  117. package/skills/binance-web3/meme-rush/scripts/cli.mjs +101 -0
  118. package/skills/binance-web3/query-address-info/SKILL.md +61 -0
  119. package/skills/binance-web3/query-address-info/references/cli.md +56 -0
  120. package/skills/binance-web3/query-address-info/scripts/cli.mjs +132 -0
  121. package/skills/binance-web3/query-token-audit/SKILL.md +162 -0
  122. package/skills/binance-web3/query-token-info/SKILL.md +83 -0
  123. package/skills/binance-web3/query-token-info/references/cli.md +135 -0
  124. package/skills/binance-web3/query-token-info/scripts/cli.mjs +112 -0
  125. package/skills/binance-web3/trading-signal/SKILL.md +66 -0
  126. package/skills/binance-web3/trading-signal/references/cli.md +90 -0
  127. package/skills/binance-web3/trading-signal/scripts/cli.mjs +92 -0
  128. package/skills/four-meme/four-guard/API-Contract-TaxToken.md +277 -0
  129. package/skills/four-meme/four-guard/API-CreateToken.02-02-2026.md +285 -0
  130. package/skills/four-meme/four-guard/API-Documents.03-03-2026.md +789 -0
  131. package/skills/four-meme/four-guard/AgentIdentifier.abi +585 -0
  132. package/skills/four-meme/four-guard/README.md +21 -0
  133. package/skills/four-meme/four-guard/SKILL.md +31 -0
  134. package/skills/four-meme/four-guard/TaxToken.abi +969 -0
  135. package/skills/four-meme/four-guard/TokenIdentifierSample.js_ +81 -0
  136. package/skills/four-meme/four-guard/TokenIdentifierSample.sol +69 -0
  137. package/skills/four-meme/four-guard/TokenManager.lite.abi +836 -0
  138. package/skills/four-meme/four-guard/TokenManager2.lite.abi +2325 -0
  139. package/skills/four-meme/four-guard/TokenManagerHelper3.abi +999 -0
  140. package/skills/four-meme/four-guard/go.mod +36 -0
  141. package/skills/four-meme/four-guard/go.sum +127 -0
  142. package/skills/four-meme/four-guard/main.go +183 -0
  143. package/skills/four-meme/four-meme-ai/SKILL.md +31 -0
  144. package/skills/four-meme/four-meme-ai/references/agent-creator-and-wallets.md +87 -0
  145. package/skills/four-meme/four-meme-ai/references/api-create-token.md +55 -0
  146. package/skills/four-meme/four-meme-ai/references/contract-addresses.md +47 -0
  147. package/skills/four-meme/four-meme-ai/references/create-token-scripts.md +131 -0
  148. package/skills/four-meme/four-meme-ai/references/errors.md +29 -0
  149. package/skills/four-meme/four-meme-ai/references/event-listening.md +75 -0
  150. package/skills/four-meme/four-meme-ai/references/execute-trade.md +31 -0
  151. package/skills/four-meme/four-meme-ai/references/tax-token-query.md +38 -0
  152. package/skills/four-meme/four-meme-ai/references/token-query-api.md +44 -0
  153. package/skills/four-meme/four-meme-ai/references/token-tax-info.md +77 -0
  154. package/skills/four-meme/four-meme-ai/scripts/8004-balance.ts +52 -0
  155. package/skills/four-meme/four-meme-ai/scripts/8004-register.ts +108 -0
  156. package/skills/four-meme/four-meme-ai/scripts/create-token-api.ts +321 -0
  157. package/skills/four-meme/four-meme-ai/scripts/create-token-chain.ts +102 -0
  158. package/skills/four-meme/four-meme-ai/scripts/create-token-instant.ts +106 -0
  159. package/skills/four-meme/four-meme-ai/scripts/execute-buy.ts +198 -0
  160. package/skills/four-meme/four-meme-ai/scripts/execute-sell.ts +150 -0
  161. package/skills/four-meme/four-meme-ai/scripts/get-public-config.ts +25 -0
  162. package/skills/four-meme/four-meme-ai/scripts/get-recent-events.ts +76 -0
  163. package/skills/four-meme/four-meme-ai/scripts/get-tax-token-info.ts +69 -0
  164. package/skills/four-meme/four-meme-ai/scripts/get-token-info.ts +94 -0
  165. package/skills/four-meme/four-meme-ai/scripts/quote-buy.ts +85 -0
  166. package/skills/four-meme/four-meme-ai/scripts/quote-sell.ts +66 -0
  167. package/skills/four-meme/four-meme-ai/scripts/send-token.ts +98 -0
  168. package/skills/four-meme/four-meme-ai/scripts/token-get.ts +31 -0
  169. package/skills/four-meme/four-meme-ai/scripts/token-list.ts +134 -0
  170. package/skills/four-meme/four-meme-ai/scripts/token-rankings.ts +162 -0
  171. package/skills/four-meme/four-meme-ai/scripts/verify-events.ts +47 -0
  172. package/skills/four-meme/four-meme-integration/SKILL.md +374 -0
  173. package/skills/four-meme/four-meme-integration/references/agent-creator-and-wallets.md +87 -0
  174. package/skills/four-meme/four-meme-integration/references/api-create-token.md +55 -0
  175. package/skills/four-meme/four-meme-integration/references/contract-addresses.md +47 -0
  176. package/skills/four-meme/four-meme-integration/references/create-token-scripts.md +131 -0
  177. package/skills/four-meme/four-meme-integration/references/errors.md +29 -0
  178. package/skills/four-meme/four-meme-integration/references/event-listening.md +75 -0
  179. package/skills/four-meme/four-meme-integration/references/execute-trade.md +31 -0
  180. package/skills/four-meme/four-meme-integration/references/tax-token-query.md +38 -0
  181. package/skills/four-meme/four-meme-integration/references/token-query-api.md +44 -0
  182. package/skills/four-meme/four-meme-integration/references/token-tax-info.md +77 -0
  183. package/skills/four-meme/four-meme-integration/scripts/8004-balance.ts +52 -0
  184. package/skills/four-meme/four-meme-integration/scripts/8004-register.ts +108 -0
  185. package/skills/four-meme/four-meme-integration/scripts/create-token-api.ts +321 -0
  186. package/skills/four-meme/four-meme-integration/scripts/create-token-chain.ts +102 -0
  187. package/skills/four-meme/four-meme-integration/scripts/create-token-instant.ts +106 -0
  188. package/skills/four-meme/four-meme-integration/scripts/execute-buy.ts +198 -0
  189. package/skills/four-meme/four-meme-integration/scripts/execute-sell.ts +150 -0
  190. package/skills/four-meme/four-meme-integration/scripts/get-public-config.ts +25 -0
  191. package/skills/four-meme/four-meme-integration/scripts/get-recent-events.ts +76 -0
  192. package/skills/four-meme/four-meme-integration/scripts/get-tax-token-info.ts +69 -0
  193. package/skills/four-meme/four-meme-integration/scripts/get-token-info.ts +94 -0
  194. package/skills/four-meme/four-meme-integration/scripts/quote-buy.ts +85 -0
  195. package/skills/four-meme/four-meme-integration/scripts/quote-sell.ts +66 -0
  196. package/skills/four-meme/four-meme-integration/scripts/send-token.ts +98 -0
  197. package/skills/four-meme/four-meme-integration/scripts/token-get.ts +31 -0
  198. package/skills/four-meme/four-meme-integration/scripts/token-list.ts +134 -0
  199. package/skills/four-meme/four-meme-integration/scripts/token-rankings.ts +162 -0
  200. package/skills/four-meme/four-meme-integration/scripts/verify-events.ts +47 -0
  201. package/skills/skillpp/contract-profiler/SKILL.md +118 -0
  202. package/skills/skillpp/newbie-tutor/SKILL.md +85 -0
  203. package/skills/skillpp/opportunity-board/SKILL.md +87 -0
  204. package/skills/skillpp/risk-fusion/SKILL.md +146 -0
  205. package/skills/skillpp/scam-pattern-lab/SKILL.md +115 -0
  206. package/skills/skillpp/wallet-doctor/SKILL.md +119 -0
  207. package/skills/skillpp/watchtower/SKILL.md +72 -0
  208. package/tests/compatibility/v0.1.0.json +117 -0
@@ -0,0 +1,448 @@
1
+ #!/usr/bin/env node
2
+ // skillpp.mjs - Skill++ Unified Executor v0.1
3
+ // Usage: node scripts/skillpp.mjs <command> '<input>'
4
+ //
5
+ // Commands:
6
+ // parse Parse input only (no execution)
7
+ // analyze Full token analysis (P_TOKEN_ANALYSIS)
8
+ // scan Chain opportunity scan (P_CHAIN_SCAN)
9
+ // audit Deep contract audit (P_DEEP_AUDIT)
10
+ // wallet Wallet portfolio analysis (P_WALLET_XRAY)
11
+ // signals Smart money signals (P_SMART_MONEY)
12
+
13
+ import { existsSync, readFileSync, readdirSync } from 'fs';
14
+ import { join, resolve, dirname } from 'path';
15
+ import { fileURLToPath } from 'url';
16
+ import { spawnSync } from 'child_process';
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const ROOT = resolve(__dirname, '..');
20
+ const MANIFEST = JSON.parse(readFileSync(join(ROOT, 'skillpp.manifest.json'), 'utf-8'));
21
+
22
+ // Config
23
+ const CMD_PIPELINE_MAP = {
24
+ analyze: 'P_TOKEN_ANALYSIS',
25
+ scan: 'P_CHAIN_SCAN',
26
+ trade: 'P_TRADE_SAFETY',
27
+ audit: 'P_DEEP_AUDIT',
28
+ wallet: 'P_WALLET_XRAY',
29
+ signals: 'P_SMART_MONEY',
30
+ create: 'P_FOURMEME_CREATE',
31
+ };
32
+ const DRY_RUN = process.argv.includes('--dry-run');
33
+ const SHOW_PATHS = process.argv.includes('--show-paths');
34
+
35
+ // Input Parser
36
+ function parseInput(raw) {
37
+ const result = { raw, type: 'unknown' };
38
+ const value = raw.trim();
39
+ const chainAliases = {
40
+ bsc: { chain: 'BSC', chainId: '56' },
41
+ bnb: { chain: 'BSC', chainId: '56' },
42
+ ethereum: { chain: 'Ethereum', chainId: '1' },
43
+ eth: { chain: 'Ethereum', chainId: '1' },
44
+ base: { chain: 'Base', chainId: '8453' },
45
+ polygon: { chain: 'Polygon', chainId: '137' },
46
+ matic: { chain: 'Polygon', chainId: '137' },
47
+ solana: { chain: 'Solana', chainId: 'CT_501' },
48
+ sol: { chain: 'Solana', chainId: 'CT_501' },
49
+ };
50
+ const explorerPatterns = [
51
+ { regex: /bscscan\.com\/address\/(0x[a-fA-F0-9]{40})/, chain: 'BSC', chainId: '56' },
52
+ { regex: /etherscan\.io\/address\/(0x[a-fA-F0-9]{40})/, chain: 'Ethereum', chainId: '1' },
53
+ { regex: /basescan\.org\/address\/(0x[a-fA-F0-9]{40})/, chain: 'Base', chainId: '8453' },
54
+ { regex: /polygonscan\.com\/address\/(0x[a-fA-F0-9]{40})/, chain: 'Polygon', chainId: '137' },
55
+ ];
56
+ for (const p of explorerPatterns) {
57
+ const m = raw.match(p.regex);
58
+ if (m) { result.type = 'explorer_url'; result.chain = p.chain; result.chainId = p.chainId; result.contractAddress = m[1]; result.sourceAvailable = raw.includes('#code'); return result; }
59
+ }
60
+ const alias = chainAliases[value.toLowerCase()];
61
+ if (alias) { result.type = 'chain_id'; result.chain = alias.chain; result.chainId = alias.chainId; return result; }
62
+ if (/^(1|56|8453|137|43114|42161|10|CT_501)$/.test(value)) { result.type = 'chain_id'; result.chainId = value; return result; }
63
+ const addrMatch = raw.match(/(0x[a-fA-F0-9]{40})/);
64
+ if (addrMatch) { result.type = 'address'; result.contractAddress = addrMatch[1]; return result; }
65
+ if (/^[A-Za-z][A-Za-z0-9]{1,10}$/.test(value)) { result.type = 'token_symbol'; result.tokenSymbol = value; return result; }
66
+ if (/\b(contract|pragma solidity|function)\b/.test(raw)) { result.type = 'source_code'; return result; }
67
+ result.type = 'intent';
68
+ return result;
69
+ }
70
+
71
+ // Checkpoint Engine
72
+ // Design: checkpoints pause execution with structured JSON.
73
+ // - BLOCKING checkpoints -> exit(10), AI must present to user, wait for confirmation
74
+ // - ADVISORY checkpoints -> inform only, continue execution
75
+ // - Resume support is intentionally explicit; blocking checkpoints stop execution until implemented
76
+ function emitCheckpoint(id, data) {
77
+ const def = MANIFEST.checkpoints?.find(c => c.id === id);
78
+ const output = {
79
+ checkpoint: id,
80
+ securityLevel: def?.securityLevel || 'ADVISORY',
81
+ canBypass: def?.canBypass !== false,
82
+ timestamp: Math.floor(Date.now() / 1000),
83
+ data,
84
+ action: def?.securityLevel === 'BLOCKING' ? 'STOP_AND_WAIT' : 'INFORM',
85
+ };
86
+ console.log(`\n[CHECKPOINT: ${id}] (${output.securityLevel})`);
87
+ console.log(JSON.stringify(output, null, 2));
88
+ if (output.securityLevel === 'BLOCKING' && !DRY_RUN) {
89
+ console.log(`\nExecution paused. AI must present this to user and wait for confirmation.`);
90
+ process.exit(10); // exit code 10 = checkpoint reached
91
+ }
92
+ }
93
+
94
+ // CLI Runner
95
+ function runSkillCLI(skillName, command, paramsJson) {
96
+ const skill = MANIFEST.skills.find(s => s.name === skillName);
97
+ if (!skill) return { error: `skill not found: ${skillName}` };
98
+ if (!skill.execCommand) return { error: `no execCommand for: ${skillName}`, skill: skillName };
99
+
100
+ // Text-only skills (no CLI)
101
+ if (skill.execCommand.startsWith('AI ') || skill.execCommand.startsWith('curl') || skill.execCommand.startsWith('read-only')) {
102
+ return { note: `manual execution: ${skill.execCommand}`, skill: skillName };
103
+ }
104
+
105
+ // Node CLI skills
106
+ if (skill.execCommand.startsWith('node ')) {
107
+ const scriptRel = skill.execCommand.replace('node ', '');
108
+ const scriptPath = join(ROOT, scriptRel);
109
+ if (!existsSync(scriptPath)) return { error: `script not found: ${scriptPath}`, skill: skillName };
110
+
111
+ if (DRY_RUN) return { note: `[DRY-RUN] node ${scriptRel} ${command}`, skill: skillName };
112
+
113
+ const args = paramsJson ? [scriptPath, command, paramsJson] : [scriptPath, command];
114
+ const child = spawnSync(process.execPath, args, {
115
+ encoding: 'utf-8',
116
+ timeout: 15000,
117
+ windowsHide: true,
118
+ });
119
+
120
+ if (child.error) {
121
+ return { error: child.error.message, skill: skillName, exitCode: child.status ?? 1 };
122
+ }
123
+
124
+ const stdout = (child.stdout || '').trim();
125
+ const stderr = (child.stderr || '').trim();
126
+ if (child.status !== 0) {
127
+ return { error: stderr || stdout || `exit ${child.status}`, skill: skillName, exitCode: child.status };
128
+ }
129
+
130
+ try { return JSON.parse(stdout); } catch { return { raw: stdout, skill: skillName }; }
131
+ }
132
+
133
+ return { note: `manual: ${skill.execCommand}`, skill: skillName };
134
+ }
135
+
136
+ function commandExists(dep) {
137
+ const checker = process.platform === 'win32'
138
+ ? { file: 'where.exe', args: [dep] }
139
+ : { file: 'which', args: [dep] };
140
+ const result = spawnSync(checker.file, checker.args, { stdio: 'pipe', windowsHide: true });
141
+ return result.status === 0;
142
+ }
143
+
144
+ function listDirFiles(relDir, suffix = '') {
145
+ const abs = join(ROOT, relDir);
146
+ if (!existsSync(abs)) return [];
147
+ return readdirSync(abs, { withFileTypes: true })
148
+ .filter(entry => entry.isFile() && (!suffix || entry.name.endsWith(suffix)))
149
+ .map(entry => entry.name)
150
+ .sort();
151
+ }
152
+
153
+ function pathCheck(relPath) {
154
+ const abs = join(ROOT, relPath);
155
+ const check = { path: relPath, exists: existsSync(abs) };
156
+ if (SHOW_PATHS) check.absolutePath = abs;
157
+ return check;
158
+ }
159
+
160
+ function externalCommandForSkill(skill) {
161
+ if (skill.execCommand === 'baw') return 'baw';
162
+ if (skill.execCommand === 'binance-cli') return 'binance-cli';
163
+ if (skill.execCommand === 'npx fourmeme') return 'fourmeme';
164
+ if (skill.execCommand?.startsWith('python3 ')) return process.platform === 'win32' ? 'python' : 'python3';
165
+ return null;
166
+ }
167
+
168
+ function runtimeDependencyForSkill(skill, dep) {
169
+ const externalCommand = externalCommandForSkill(skill);
170
+ if (externalCommand) return externalCommand;
171
+ return dep;
172
+ }
173
+
174
+ function runDoctor() {
175
+ const adapters = listDirFiles('adapters', '.md');
176
+ const prompts = listDirFiles('prompts', '.md');
177
+ const schemas = listDirFiles('schemas', '.json');
178
+ const externalCli = {};
179
+
180
+ for (const skill of MANIFEST.skills) {
181
+ const command = externalCommandForSkill(skill);
182
+ if (!command) continue;
183
+ externalCli[command] = {
184
+ available: commandExists(command),
185
+ skill: skill.name,
186
+ execCommand: skill.execCommand,
187
+ installCmd: skill.installCmd || 'install manually',
188
+ requiredForWriteOps: !skill.readOnly,
189
+ };
190
+ }
191
+
192
+ const output = {
193
+ command: 'doctor',
194
+ status: 'ok',
195
+ packageRoot: SHOW_PATHS ? ROOT : '<redacted>',
196
+ privacy: SHOW_PATHS
197
+ ? 'absolute paths shown because --show-paths was provided'
198
+ : 'absolute local paths redacted; run with --show-paths only in a private local session',
199
+ checks: {
200
+ manifest: pathCheck('skillpp.manifest.json'),
201
+ skillsDir: pathCheck('skills'),
202
+ scriptsDir: pathCheck('scripts'),
203
+ adaptersDir: pathCheck('adapters'),
204
+ promptsDir: pathCheck('prompts'),
205
+ schemasDir: pathCheck('schemas'),
206
+ rootSkill: pathCheck('SKILL.md'),
207
+ },
208
+ counts: {
209
+ skills: MANIFEST.skills.length,
210
+ pipelines: MANIFEST.pipelines.length,
211
+ checkpoints: MANIFEST.checkpoints?.length || 0,
212
+ adapters: adapters.length,
213
+ prompts: prompts.length,
214
+ schemas: schemas.length,
215
+ },
216
+ adapters,
217
+ prompts,
218
+ externalCli,
219
+ guidance: [
220
+ 'Use relative paths from this report unless the user explicitly provides local paths.',
221
+ 'Do not ask for machine-specific workspace paths in public issues or shared logs.',
222
+ 'Missing external write CLIs are warnings until wallet, exchange, or Four.meme write operations are requested.',
223
+ ],
224
+ };
225
+
226
+ console.log(JSON.stringify(output, null, 2));
227
+ }
228
+
229
+ function listSkills() {
230
+ const output = {
231
+ command: 'skills',
232
+ count: MANIFEST.skills.length,
233
+ skills: MANIFEST.skills.map(skill => ({
234
+ name: skill.name,
235
+ group: skill.group,
236
+ path: skill.path,
237
+ entry: skill.entry,
238
+ readOnly: skill.readOnly,
239
+ needsCheckpoint: skill.needsCheckpoint,
240
+ execCommand: skill.execCommand,
241
+ })),
242
+ };
243
+ console.log(JSON.stringify(output, null, 2));
244
+ }
245
+
246
+ // Pipeline Executor
247
+ function executePipeline(pipelineId, parsed) {
248
+ const pipeline = MANIFEST.pipelines.find(p => p.id === pipelineId);
249
+ if (!pipeline) return { error: `pipeline not found: ${pipelineId}` };
250
+
251
+ // Default chainId for bare addresses (BSC)
252
+ const chainId = parsed.chainId || '56';
253
+ const addr = parsed.contractAddress; // unified address field
254
+
255
+ console.log(`\nPipeline: ${pipeline.name} (${pipelineId})`);
256
+ console.log(` Steps: ${pipeline.skills.join(' -> ')}`);
257
+
258
+ const results = {};
259
+
260
+ for (const [idx, skillName] of pipeline.skills.entries()) {
261
+ console.log(`\n-- Step ${idx + 1}: ${skillName} --`);
262
+
263
+ let result;
264
+ switch (skillName) {
265
+ case 'query-token-info':
266
+ if (pipelineId === 'P_DEEP_AUDIT' && parsed.type === 'source_code' && !addr) {
267
+ result = { note: 'skipped: source-code audit has no token address for token metadata lookup' };
268
+ } else {
269
+ result = runSkillCLI('query-token-info', 'search',
270
+ JSON.stringify({ keyword: addr || parsed.tokenSymbol || parsed.raw, chainIds: chainId }));
271
+ }
272
+ break;
273
+ case 'query-token-audit':
274
+ // Some pipelines discover token addresses inside previous results; the AI layer expands those.
275
+ if (pipelineId === 'P_WALLET_XRAY') {
276
+ result = { note: 'deferred: will audit each token from positions (not wallet address itself)' };
277
+ } else if (pipelineId === 'P_SMART_MONEY' && !addr) {
278
+ result = { note: 'deferred: will audit token addresses extracted from smart-money signals' };
279
+ } else if (addr) {
280
+ result = { note: 'step entered: curl POST audit API (pending AI execution)', contractAddress: addr, chainId };
281
+ } else {
282
+ result = { note: 'skipped: no address available' };
283
+ }
284
+ break;
285
+ case 'trading-signal':
286
+ result = runSkillCLI('trading-signal', 'smart-money',
287
+ JSON.stringify({ chainId, page: 1, pageSize: 10 }));
288
+ break;
289
+ case 'meme-rush':
290
+ if (pipelineId === 'P_CHAIN_SCAN') {
291
+ result = {
292
+ 'meme-rush': runSkillCLI('meme-rush', 'meme-rush',
293
+ JSON.stringify({ chainId, rankType: 10, limit: 10 })),
294
+ 'topic-rush': runSkillCLI('meme-rush', 'topic-rush',
295
+ JSON.stringify({ chainId, rankType: 10, sort: 10 })),
296
+ };
297
+ } else {
298
+ result = runSkillCLI('meme-rush', 'meme-rush',
299
+ JSON.stringify({ chainId, rankType: 10, limit: 10 }));
300
+ }
301
+ break;
302
+ case 'crypto-market-rank':
303
+ if (pipelineId === 'P_CHAIN_SCAN') {
304
+ result = {
305
+ 'token-rank': runSkillCLI('crypto-market-rank', 'token-rank',
306
+ JSON.stringify({ chainId, rankType: 10, page: 1, size: 10 })),
307
+ 'smart-money-inflow': runSkillCLI('crypto-market-rank', 'smart-money-inflow',
308
+ JSON.stringify({ chainId, period: '24h', page: 1, size: 10 })),
309
+ };
310
+ } else {
311
+ result = runSkillCLI('crypto-market-rank', 'token-rank',
312
+ JSON.stringify({ chainId, rankType: 10, page: 1, size: 10 }));
313
+ }
314
+ break;
315
+ case 'audit-plus':
316
+ case 'contract-profiler':
317
+ case 'risk-fusion':
318
+ case 'wallet-doctor':
319
+ case 'newbie-tutor':
320
+ case 'opportunity-board':
321
+ result = { note: `text-based skill, AI executes by reading ${skillName}/SKILL.md`, skill: skillName };
322
+ break;
323
+ case 'query-address-info':
324
+ if (addr) {
325
+ result = runSkillCLI('query-address-info', 'positions',
326
+ JSON.stringify({ address: addr, chainId, offset: 0 }));
327
+ } else {
328
+ result = { note: 'skipped: no wallet address' };
329
+ }
330
+ break;
331
+ case 'four-meme-integration':
332
+ result = { note: 'requires PRIVATE_KEY + user confirmation, manual execution only' };
333
+ break;
334
+ default:
335
+ result = { note: `no executor mapping for: ${skillName}` };
336
+ }
337
+
338
+ results[skillName] = result;
339
+ if (result?.error) {
340
+ console.error(` FAIL ${skillName}: ${result.error}`);
341
+ } else if (result?.note) {
342
+ console.log(` NOTE ${skillName}: ${result.note}`);
343
+ } else {
344
+ console.log(` PASS ${skillName}: success`);
345
+ }
346
+ }
347
+
348
+ // Checkpoints
349
+ if (pipeline.checkpoints.length > 0) {
350
+ console.log(`\n-- Checkpoints --`);
351
+ for (const cpId of pipeline.checkpoints) {
352
+ emitCheckpoint(cpId, { pipeline: pipelineId, results: Object.keys(results) });
353
+ }
354
+ }
355
+
356
+ return results;
357
+ }
358
+
359
+ // Main
360
+ async function main() {
361
+ const args = process.argv.slice(2).filter(a => a !== '--dry-run' && a !== '--show-paths');
362
+ const [command, inputStr] = args;
363
+
364
+ if (!command || command === '--help' || command === '-h') {
365
+ console.log(`Skill++ Executor v0.1
366
+ Usage: node scripts/skillpp.mjs <command> '<input>' [--dry-run]
367
+
368
+ Commands:
369
+ parse "<input>" Parse only (no execution)
370
+ analyze "<address|url>" P_TOKEN_ANALYSIS
371
+ scan "<chainId>" P_CHAIN_SCAN
372
+ trade "<address|url>" P_TRADE_SAFETY
373
+ audit "<address|url>" P_DEEP_AUDIT
374
+ wallet "<address>" P_WALLET_XRAY
375
+ signals "<chainId>" P_SMART_MONEY
376
+ create "<intent>" P_FOURMEME_CREATE
377
+ doctor Check package root, manifest, skills, and external CLIs
378
+ skills List registered skills from the manifest
379
+
380
+ Flags:
381
+ --dry-run Show execution plan without running
382
+ --show-paths Include absolute local paths in doctor output
383
+ `);
384
+ process.exit(0);
385
+ }
386
+
387
+ if (command === 'doctor') {
388
+ runDoctor();
389
+ process.exit(0);
390
+ }
391
+
392
+ if (command === 'skills') {
393
+ listSkills();
394
+ process.exit(0);
395
+ }
396
+
397
+ // Parse input
398
+ const parsed = parseInput(inputStr || '');
399
+ console.log(JSON.stringify({ command, parsed }, null, 2));
400
+
401
+ if (command === 'parse') process.exit(0);
402
+
403
+ // Route: command takes priority over parsed input type
404
+ const pipelineId = CMD_PIPELINE_MAP[command];
405
+ if (!pipelineId) {
406
+ console.error(`Unknown command: ${command}. Use --help for usage.`);
407
+ process.exit(1);
408
+ }
409
+
410
+ if (DRY_RUN) console.log('\nDRY RUN MODE - no real API calls\n');
411
+
412
+ // Check deps
413
+ const pipeline = MANIFEST.pipelines.find(p => p.id === pipelineId);
414
+ const issues = [];
415
+ for (const sn of pipeline.skills) {
416
+ const skill = MANIFEST.skills.find(s => s.name === sn);
417
+ if (!skill) continue;
418
+ for (const dep of skill.deps || []) {
419
+ if (dep === 'node' || dep === 'curl') continue;
420
+ const runtimeDep = runtimeDependencyForSkill(skill, dep);
421
+ if (!commandExists(runtimeDep)) {
422
+ issues.push({ skill: sn, dep: runtimeDep, package: dep, installCmd: skill.installCmd || 'manual install' });
423
+ }
424
+ }
425
+ }
426
+ if (issues.length > 0) {
427
+ console.log('\nMissing dependencies:');
428
+ issues.forEach(i => console.log(` ${i.skill}: ${i.dep} -> ${i.installCmd}`));
429
+ }
430
+
431
+ // Execute
432
+ const results = executePipeline(pipelineId, parsed);
433
+
434
+ // Build handoff
435
+ const handoff = {
436
+ _meta: { pipeline: pipelineId, timestamp: Math.floor(Date.now() / 1000), source: 'skillpp-executor' },
437
+ input: { raw: inputStr || '', type: parsed.type, chainId: parseInput(inputStr || '').chainId || '56', address: parseInput(inputStr || '').contractAddress },
438
+ results,
439
+ nextActions: [
440
+ { action: 'Deep audit contract', pipeline: 'P_DEEP_AUDIT', condition: 'if source code available' },
441
+ { action: 'Check smart money', pipeline: 'P_SMART_MONEY' },
442
+ { action: 'View wallet holdings', pipeline: 'P_WALLET_XRAY', condition: 'if wallet address provided' },
443
+ ],
444
+ };
445
+ console.log(`\nHandoff:\n${JSON.stringify(handoff, null, 2)}`);
446
+ }
447
+
448
+ await main();
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ // skillpp-validate.mjs - Skill++ manifest and schema validator
3
+ // Usage: node scripts/validate-skillpp.mjs [--strict]
4
+ // Exits 0 on pass, 1 on warnings, 2 on errors.
5
+
6
+ import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
7
+ import { join, resolve, dirname } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ const ROOT = resolve(__dirname, '..');
12
+ const STRICT = process.argv.includes('--strict');
13
+
14
+ let errors = 0;
15
+ let warnings = 0;
16
+
17
+ function err(msg) { console.error(`FAIL ${msg}`); errors++; }
18
+ function warn(msg) { console.warn(`WARN ${msg}`); warnings++; }
19
+ function ok(msg) { console.log(`PASS ${msg}`); }
20
+
21
+ // 1. Check manifest exists and is valid JSON
22
+ console.log('\n-- Manifest --');
23
+ const manifestPath = join(ROOT, 'skillpp.manifest.json');
24
+ if (!existsSync(manifestPath)) {
25
+ err('skillpp.manifest.json not found');
26
+ } else {
27
+ try {
28
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
29
+ ok(`manifest valid JSON (${manifest.skills.length} skills, ${manifest.pipelines.length} pipelines)`);
30
+
31
+ // Check each skill path exists
32
+ for (const skill of manifest.skills) {
33
+ const skillPath = join(ROOT, skill.path, skill.entry);
34
+ if (!existsSync(skillPath)) {
35
+ err(`skill path not found: ${skill.path}${skill.entry}`);
36
+ }
37
+ }
38
+ } catch (e) {
39
+ err(`manifest parse error: ${e.message}`);
40
+ }
41
+ }
42
+
43
+ // 2. Check all SKILL.md files for BOM and frontmatter
44
+ console.log('\n-- SKILL.md Checks --');
45
+ function walkDir(dir) {
46
+ const files = [];
47
+ try {
48
+ for (const entry of readdirSync(dir)) {
49
+ const full = join(dir, entry);
50
+ if (entry.startsWith('.') || entry === 'node_modules') continue;
51
+ try {
52
+ if (statSync(full).isDirectory()) {
53
+ files.push(...walkDir(full));
54
+ } else if (entry === 'SKILL.md') {
55
+ files.push(full);
56
+ }
57
+ } catch {}
58
+ }
59
+ } catch {}
60
+ return files;
61
+ }
62
+
63
+ const skillFiles = walkDir(join(ROOT, 'skills'));
64
+ // Also check root SKILL.md
65
+ if (existsSync(join(ROOT, 'SKILL.md'))) {
66
+ skillFiles.push(join(ROOT, 'SKILL.md'));
67
+ }
68
+
69
+ for (const f of skillFiles) {
70
+ const rel = f.replace(ROOT, '').replace(/\\/g, '/');
71
+ try {
72
+ const raw = readFileSync(f);
73
+ let buf = raw;
74
+ if (raw[0] === 0xEF && raw[1] === 0xBB && raw[2] === 0xBF) {
75
+ buf = raw.subarray(3);
76
+ err(`BOM detected: ${rel}`);
77
+ }
78
+ const text = buf.toString('utf-8');
79
+
80
+ // Frontmatter check
81
+ const fm = /^---\s*\n([\s\S]*?)\n---/.exec(text);
82
+ if (!fm) {
83
+ err(`no frontmatter: ${rel}`);
84
+ } else {
85
+ const frontmatter = fm[1];
86
+ const hasName = /^name:\s*\S/m.test(frontmatter);
87
+ const hasDesc = /^description:\s*\S/m.test(frontmatter);
88
+
89
+ if (!hasName) err(`missing 'name' in frontmatter: ${rel}`);
90
+ if (!hasDesc) err(`missing 'description' in frontmatter: ${rel}`);
91
+
92
+ // Non-standard fields (official spec allows: name/description/license/allowed-tools/metadata)
93
+ const nonStandard = ['version', 'category', 'capabilities', 'trigger'];
94
+ for (const field of nonStandard) {
95
+ if (new RegExp(`^${field}:`, 'm').test(frontmatter)) {
96
+ if (STRICT) {
97
+ err(`non-standard field '${field}' in frontmatter: ${rel}`);
98
+ } else {
99
+ warn(`non-standard field '${field}' in frontmatter: ${rel} (use --strict to error)`);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ } catch (e) {
105
+ err(`read error ${rel}: ${e.message}`);
106
+ }
107
+ }
108
+ ok(`${skillFiles.length} SKILL.md files checked`);
109
+
110
+ // 3. Check schemas directory
111
+ console.log('\n-- Schemas --');
112
+ const schemasDir = join(ROOT, 'schemas');
113
+ const requiredSchemas = ['handoff.schema.json', 'token.schema.json', 'audit.schema.json', 'checkpoint.schema.json'];
114
+ for (const s of requiredSchemas) {
115
+ const sp = join(schemasDir, s);
116
+ if (!existsSync(sp)) {
117
+ err(`schema missing: ${s}`);
118
+ } else {
119
+ try {
120
+ JSON.parse(readFileSync(sp, 'utf-8'));
121
+ ok(`${s} valid`);
122
+ } catch (e) {
123
+ err(`${s} invalid JSON: ${e.message}`);
124
+ }
125
+ }
126
+ }
127
+
128
+ // 4. Summary
129
+ console.log(`\n-- Result --`);
130
+ console.log(`Errors: ${errors}, Warnings: ${warnings}`);
131
+ if (errors > 0) {
132
+ console.log('STATUS: FAIL');
133
+ process.exit(2);
134
+ } else if (warnings > 0) {
135
+ console.log('STATUS: PASS WITH WARNINGS');
136
+ process.exit(1);
137
+ } else {
138
+ console.log('STATUS: PASS');
139
+ process.exit(0);
140
+ }