@fredcallagan/arn-spark 5.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 (130) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/.opencode/plugins/arn-spark.js +272 -0
  3. package/package.json +17 -0
  4. package/plugins/arn-spark/.claude-plugin/plugin.json +9 -0
  5. package/plugins/arn-spark/LICENSE +21 -0
  6. package/plugins/arn-spark/README.md +25 -0
  7. package/plugins/arn-spark/agents/arn-spark-brand-strategist.md +299 -0
  8. package/plugins/arn-spark/agents/arn-spark-dev-env-builder.md +228 -0
  9. package/plugins/arn-spark/agents/arn-spark-doctor.md +92 -0
  10. package/plugins/arn-spark/agents/arn-spark-forensic-investigator.md +181 -0
  11. package/plugins/arn-spark/agents/arn-spark-market-researcher.md +232 -0
  12. package/plugins/arn-spark/agents/arn-spark-marketing-pm.md +225 -0
  13. package/plugins/arn-spark/agents/arn-spark-persona-architect.md +259 -0
  14. package/plugins/arn-spark/agents/arn-spark-persona-impersonator.md +183 -0
  15. package/plugins/arn-spark/agents/arn-spark-product-strategist.md +191 -0
  16. package/plugins/arn-spark/agents/arn-spark-prototype-builder.md +497 -0
  17. package/plugins/arn-spark/agents/arn-spark-scaffolder.md +228 -0
  18. package/plugins/arn-spark/agents/arn-spark-spike-runner.md +209 -0
  19. package/plugins/arn-spark/agents/arn-spark-style-capture.md +196 -0
  20. package/plugins/arn-spark/agents/arn-spark-tech-evaluator.md +229 -0
  21. package/plugins/arn-spark/agents/arn-spark-ui-interactor.md +235 -0
  22. package/plugins/arn-spark/agents/arn-spark-use-case-writer.md +280 -0
  23. package/plugins/arn-spark/agents/arn-spark-ux-judge.md +215 -0
  24. package/plugins/arn-spark/agents/arn-spark-ux-specialist.md +200 -0
  25. package/plugins/arn-spark/agents/arn-spark-visual-sketcher.md +285 -0
  26. package/plugins/arn-spark/agents/arn-spark-visual-test-engineer.md +224 -0
  27. package/plugins/arn-spark/references/copilot-tools.md +62 -0
  28. package/plugins/arn-spark/skills/arn-brainstorming/SKILL.md +520 -0
  29. package/plugins/arn-spark/skills/arn-brainstorming/references/add-feature-flow.md +155 -0
  30. package/plugins/arn-spark/skills/arn-spark-arch-vision/SKILL.md +226 -0
  31. package/plugins/arn-spark/skills/arn-spark-arch-vision/references/architecture-vision-template.md +153 -0
  32. package/plugins/arn-spark/skills/arn-spark-arch-vision/references/technology-evaluation-guide.md +86 -0
  33. package/plugins/arn-spark/skills/arn-spark-clickable-prototype/SKILL.md +471 -0
  34. package/plugins/arn-spark/skills/arn-spark-clickable-prototype/references/clickable-prototype-criteria.md +65 -0
  35. package/plugins/arn-spark/skills/arn-spark-clickable-prototype/references/journey-template.md +62 -0
  36. package/plugins/arn-spark/skills/arn-spark-clickable-prototype/references/review-report-template.md +75 -0
  37. package/plugins/arn-spark/skills/arn-spark-clickable-prototype/references/showcase-capture-guide.md +213 -0
  38. package/plugins/arn-spark/skills/arn-spark-clickable-prototype-teams/SKILL.md +642 -0
  39. package/plugins/arn-spark/skills/arn-spark-clickable-prototype-teams/references/debate-protocol.md +242 -0
  40. package/plugins/arn-spark/skills/arn-spark-clickable-prototype-teams/references/debate-review-report-template.md +161 -0
  41. package/plugins/arn-spark/skills/arn-spark-clickable-prototype-teams/references/expert-interaction-review-template.md +152 -0
  42. package/plugins/arn-spark/skills/arn-spark-concept-review/SKILL.md +350 -0
  43. package/plugins/arn-spark/skills/arn-spark-concept-review/references/conflict-resolution-protocol.md +145 -0
  44. package/plugins/arn-spark/skills/arn-spark-concept-review/references/review-report-template.md +185 -0
  45. package/plugins/arn-spark/skills/arn-spark-dev-setup/SKILL.md +366 -0
  46. package/plugins/arn-spark/skills/arn-spark-dev-setup/references/dev-setup-checklist.md +84 -0
  47. package/plugins/arn-spark/skills/arn-spark-dev-setup/references/dev-setup-template.md +205 -0
  48. package/plugins/arn-spark/skills/arn-spark-discover/SKILL.md +303 -0
  49. package/plugins/arn-spark/skills/arn-spark-discover/references/competitive-landscape-template.md +87 -0
  50. package/plugins/arn-spark/skills/arn-spark-discover/references/discovery-questions.md +120 -0
  51. package/plugins/arn-spark/skills/arn-spark-discover/references/persona-profile-template.md +97 -0
  52. package/plugins/arn-spark/skills/arn-spark-discover/references/product-concept-template.md +253 -0
  53. package/plugins/arn-spark/skills/arn-spark-ensure-config/SKILL.md +23 -0
  54. package/plugins/arn-spark/skills/arn-spark-ensure-config/references/ensure-config.md +388 -0
  55. package/plugins/arn-spark/skills/arn-spark-ensure-config/references/step-0-fast-path.md +25 -0
  56. package/plugins/arn-spark/skills/arn-spark-ensure-config/scripts/cache-check.sh +127 -0
  57. package/plugins/arn-spark/skills/arn-spark-feature-extract/SKILL.md +483 -0
  58. package/plugins/arn-spark/skills/arn-spark-feature-extract/references/feature-backlog-template.md +176 -0
  59. package/plugins/arn-spark/skills/arn-spark-feature-extract/references/feature-entry-template.md +209 -0
  60. package/plugins/arn-spark/skills/arn-spark-help/SKILL.md +149 -0
  61. package/plugins/arn-spark/skills/arn-spark-help/references/pipeline-map.md +211 -0
  62. package/plugins/arn-spark/skills/arn-spark-init/SKILL.md +312 -0
  63. package/plugins/arn-spark/skills/arn-spark-init/references/agent-models-presets/all-opus.md +23 -0
  64. package/plugins/arn-spark/skills/arn-spark-init/references/agent-models-presets/balanced.md +23 -0
  65. package/plugins/arn-spark/skills/arn-spark-init/references/bkt-setup.md +55 -0
  66. package/plugins/arn-spark/skills/arn-spark-init/references/jira-mcp-setup.md +61 -0
  67. package/plugins/arn-spark/skills/arn-spark-init/references/platform-labels.md +97 -0
  68. package/plugins/arn-spark/skills/arn-spark-naming/SKILL.md +275 -0
  69. package/plugins/arn-spark/skills/arn-spark-naming/references/creative-brief-template.md +146 -0
  70. package/plugins/arn-spark/skills/arn-spark-naming/references/naming-methodology.md +237 -0
  71. package/plugins/arn-spark/skills/arn-spark-naming/references/naming-report-template.md +122 -0
  72. package/plugins/arn-spark/skills/arn-spark-naming/references/trademark-databases.md +88 -0
  73. package/plugins/arn-spark/skills/arn-spark-naming/references/whois-server-map.md +164 -0
  74. package/plugins/arn-spark/skills/arn-spark-naming/scripts/whois-check.js +502 -0
  75. package/plugins/arn-spark/skills/arn-spark-naming/scripts/whois-check.py +533 -0
  76. package/plugins/arn-spark/skills/arn-spark-prototype-lock/SKILL.md +260 -0
  77. package/plugins/arn-spark/skills/arn-spark-prototype-lock/references/lock-report-template.md +68 -0
  78. package/plugins/arn-spark/skills/arn-spark-prototype-lock/references/pretooluse-hook-template.json +35 -0
  79. package/plugins/arn-spark/skills/arn-spark-prototype-lock/references/prototype-guardrail-rules.md +38 -0
  80. package/plugins/arn-spark/skills/arn-spark-report/SKILL.md +144 -0
  81. package/plugins/arn-spark/skills/arn-spark-report/references/issue-template.md +81 -0
  82. package/plugins/arn-spark/skills/arn-spark-report/references/spark-knowledge-base.md +293 -0
  83. package/plugins/arn-spark/skills/arn-spark-scaffold/SKILL.md +239 -0
  84. package/plugins/arn-spark/skills/arn-spark-scaffold/references/scaffold-checklist.md +79 -0
  85. package/plugins/arn-spark/skills/arn-spark-scaffold/references/scaffold-summary-template.md +74 -0
  86. package/plugins/arn-spark/skills/arn-spark-spike/SKILL.md +209 -0
  87. package/plugins/arn-spark/skills/arn-spark-spike/references/spike-report-template.md +123 -0
  88. package/plugins/arn-spark/skills/arn-spark-static-prototype/SKILL.md +362 -0
  89. package/plugins/arn-spark/skills/arn-spark-static-prototype/references/review-report-template.md +65 -0
  90. package/plugins/arn-spark/skills/arn-spark-static-prototype/references/showcase-capture-guide.md +153 -0
  91. package/plugins/arn-spark/skills/arn-spark-static-prototype/references/static-prototype-criteria.md +54 -0
  92. package/plugins/arn-spark/skills/arn-spark-static-prototype-teams/SKILL.md +518 -0
  93. package/plugins/arn-spark/skills/arn-spark-static-prototype-teams/references/debate-protocol.md +230 -0
  94. package/plugins/arn-spark/skills/arn-spark-static-prototype-teams/references/debate-review-report-template.md +148 -0
  95. package/plugins/arn-spark/skills/arn-spark-static-prototype-teams/references/expert-visual-review-template.md +130 -0
  96. package/plugins/arn-spark/skills/arn-spark-stress-competitive/SKILL.md +166 -0
  97. package/plugins/arn-spark/skills/arn-spark-stress-competitive/references/competitive-report-template.md +139 -0
  98. package/plugins/arn-spark/skills/arn-spark-stress-competitive/references/gap-analysis-framework.md +111 -0
  99. package/plugins/arn-spark/skills/arn-spark-stress-interview/SKILL.md +257 -0
  100. package/plugins/arn-spark/skills/arn-spark-stress-interview/references/interview-protocol.md +140 -0
  101. package/plugins/arn-spark/skills/arn-spark-stress-interview/references/interview-report-template.md +165 -0
  102. package/plugins/arn-spark/skills/arn-spark-stress-interview/references/persona-casting-spec.md +138 -0
  103. package/plugins/arn-spark/skills/arn-spark-stress-premortem/SKILL.md +181 -0
  104. package/plugins/arn-spark/skills/arn-spark-stress-premortem/references/premortem-protocol.md +112 -0
  105. package/plugins/arn-spark/skills/arn-spark-stress-premortem/references/premortem-report-template.md +158 -0
  106. package/plugins/arn-spark/skills/arn-spark-stress-prfaq/SKILL.md +206 -0
  107. package/plugins/arn-spark/skills/arn-spark-stress-prfaq/references/prfaq-report-template.md +139 -0
  108. package/plugins/arn-spark/skills/arn-spark-stress-prfaq/references/prfaq-workflow.md +118 -0
  109. package/plugins/arn-spark/skills/arn-spark-style-explore/SKILL.md +281 -0
  110. package/plugins/arn-spark/skills/arn-spark-style-explore/references/style-brief-template.md +198 -0
  111. package/plugins/arn-spark/skills/arn-spark-use-cases/SKILL.md +359 -0
  112. package/plugins/arn-spark/skills/arn-spark-use-cases/references/expert-review-template.md +94 -0
  113. package/plugins/arn-spark/skills/arn-spark-use-cases/references/review-protocol.md +150 -0
  114. package/plugins/arn-spark/skills/arn-spark-use-cases/references/use-case-index-template.md +108 -0
  115. package/plugins/arn-spark/skills/arn-spark-use-cases/references/use-case-template.md +125 -0
  116. package/plugins/arn-spark/skills/arn-spark-use-cases-teams/SKILL.md +306 -0
  117. package/plugins/arn-spark/skills/arn-spark-use-cases-teams/references/debate-protocol.md +272 -0
  118. package/plugins/arn-spark/skills/arn-spark-use-cases-teams/references/review-report-template.md +112 -0
  119. package/plugins/arn-spark/skills/arn-spark-visual-readiness/SKILL.md +293 -0
  120. package/plugins/arn-spark/skills/arn-spark-visual-readiness/references/readiness-checklist.md +196 -0
  121. package/plugins/arn-spark/skills/arn-spark-visual-sketch/SKILL.md +376 -0
  122. package/plugins/arn-spark/skills/arn-spark-visual-sketch/references/aesthetic-philosophy.md +210 -0
  123. package/plugins/arn-spark/skills/arn-spark-visual-sketch/references/sketch-gallery-guide.md +282 -0
  124. package/plugins/arn-spark/skills/arn-spark-visual-sketch/references/visual-direction-template.md +174 -0
  125. package/plugins/arn-spark/skills/arn-spark-visual-strategy/SKILL.md +447 -0
  126. package/plugins/arn-spark/skills/arn-spark-visual-strategy/references/baseline-capture-script-template.js +89 -0
  127. package/plugins/arn-spark/skills/arn-spark-visual-strategy/references/journey-schema.md +375 -0
  128. package/plugins/arn-spark/skills/arn-spark-visual-strategy/references/spike-checklist.md +122 -0
  129. package/plugins/arn-spark/skills/arn-spark-visual-strategy/references/strategy-layers-guide.md +132 -0
  130. package/plugins/arn-spark/skills/arn-spark-visual-strategy/references/visual-strategy-template.md +141 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "arn-spark",
3
+ "repository": "https://github.com/fredcallagan/arness-global",
4
+ "author": {
5
+ "name": "Fryderyk Benigni",
6
+ "url": "https://github.com/fredcallagan"
7
+ },
8
+ "description": "Greenfield exploration for Claude Code — discovery, personas, use cases, architecture vision, naming, scaffolding, visual sketches, prototype validation. 19 skills, 13 agents."
9
+ }
@@ -0,0 +1,272 @@
1
+ /**
2
+ * arn-spark plugin for OpenCode.ai
3
+ *
4
+ * Injects tool mapping bootstrap and auto-registers skills/agents
5
+ * for the arn-spark (greenfield exploration) plugin.
6
+ * Follows the superpowers distribution pattern: zero npm deps,
7
+ * no symlinks, no postinstall scripts.
8
+ */
9
+
10
+ import path from 'path';
11
+ import fs from 'fs';
12
+ import { fileURLToPath } from 'url';
13
+
14
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ const PLUGIN_ROOT = path.resolve(__dirname, '../../plugins/arn-spark');
16
+ const SKILLS_DIR = path.join(PLUGIN_ROOT, 'skills');
17
+ const AGENTS_DIR = path.join(PLUGIN_ROOT, 'agents');
18
+ const OPENCODE_AGENTS_DIR = path.resolve(__dirname, '../agents');
19
+ const OPENCODE_COMMANDS_DIR = path.resolve(__dirname, '../commands');
20
+ const FILTERED_SKILLS_DIR = path.resolve(__dirname, '../.skills-filtered/arn-spark');
21
+
22
+ // Transform Claude Code agent frontmatter to OpenCode format
23
+ function transformAgentContent(content) {
24
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
25
+ if (!match) return content;
26
+
27
+ const frontmatter = match[1];
28
+ const body = match[2];
29
+ const lines = frontmatter.split('\n');
30
+ const filtered = [];
31
+ let skipUntilDedent = false;
32
+
33
+ for (const line of lines) {
34
+ const isEmpty = line.trim() === '';
35
+
36
+ if (skipUntilDedent) {
37
+ if (line[0] === ' ' || line[0] === '\t' || isEmpty) continue;
38
+ skipUntilDedent = false;
39
+ }
40
+
41
+ const trimmed = line.trimStart();
42
+
43
+ if (trimmed.startsWith('name:') || trimmed.startsWith('model:') || trimmed.startsWith('color:')) {
44
+ continue;
45
+ }
46
+
47
+ if (trimmed.startsWith('tools:')) {
48
+ skipUntilDedent = true;
49
+ continue;
50
+ }
51
+
52
+ filtered.push(line);
53
+ }
54
+
55
+ filtered.push('mode: subagent');
56
+
57
+ return '---\n' + filtered.join('\n') + '\n---\n' + body;
58
+ }
59
+
60
+ // Copy files from a source directory to a dest directory
61
+ function copyFiles(srcDir, destDir, transformFn) {
62
+ if (!fs.existsSync(srcDir)) return;
63
+ if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
64
+ const files = fs.readdirSync(srcDir).filter(f => f.endsWith('.md'));
65
+ for (const file of files) {
66
+ const src = path.join(srcDir, file);
67
+ const dest = path.join(destDir, file);
68
+ if (!fs.existsSync(dest)) {
69
+ const content = fs.readFileSync(src, 'utf-8');
70
+ const transformed = transformFn ? transformFn(content) : content;
71
+ fs.writeFileSync(dest, transformed, 'utf-8');
72
+ }
73
+ }
74
+ }
75
+
76
+ // Bootstrap content (generated once, cached)
77
+ let _bootstrapCache = null;
78
+
79
+ function getBootstrapContent() {
80
+ if (_bootstrapCache) return _bootstrapCache;
81
+
82
+ const toolMapping = `**Tool Mapping for Arness (OpenCode):**
83
+ When arness skills reference Claude Code tools you don't have, use these OpenCode equivalents:
84
+ - \`AskUserQuestion\` → OpenCode's \`question\` tool
85
+ - \`TodoWrite\` → OpenCode's \`todowrite\` tool
86
+ - \`Task\` (subagent dispatch) → OpenCode's \`task\` tool with \`subagent_type\` parameter
87
+ - \`Skill\` → OpenCode's native \`skill\` tool
88
+ - \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Your native tools
89
+ - \`LSP\` → OpenCode's \`lsp\` (experimental; set \`OPENCODE_EXPERIMENTAL_LSP_TOOL=true\`)
90
+ - \`WebSearch\` → OpenCode's \`websearch\`
91
+ - \`WebFetch\` → OpenCode's \`webfetch\`
92
+ - \`[PLATFORM_CONFIG_DIR]\` → OpenCode's \`.opencode/\` directory
93
+ - \`\${CLAUDE_PLUGIN_ROOT}\` → Use the \`arn-spark-resolve\` tool to get the absolute plugin root path
94
+
95
+ Use OpenCode's native \`skill\` tool to list and load skills.`;
96
+
97
+ _bootstrapCache = `<ARNESS_TOOL_MAPPING>
98
+ ${toolMapping}</ARNESS_TOOL_MAPPING>`;
99
+
100
+ return _bootstrapCache;
101
+ }
102
+
103
+ // Generate command stubs from SKILL.md frontmatter in each skill directory
104
+ function generateCommandsFromSkills(skillsDir, commandsDir) {
105
+ if (!fs.existsSync(skillsDir)) return;
106
+ if (!fs.existsSync(commandsDir)) fs.mkdirSync(commandsDir, { recursive: true });
107
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
108
+ for (const entry of entries) {
109
+ if (!entry.isDirectory()) continue;
110
+ const skillName = entry.name;
111
+ const skillMdPath = path.join(skillsDir, skillName, 'SKILL.md');
112
+ if (!fs.existsSync(skillMdPath)) continue;
113
+ const content = fs.readFileSync(skillMdPath, 'utf-8');
114
+ const description = extractDescription(content);
115
+ const cmdContent = `---
116
+ description: ${description}
117
+ ---
118
+
119
+ Load the ${skillName} skill and follow its instructions.
120
+ `;
121
+ fs.writeFileSync(path.join(commandsDir, `${skillName}.md`), cmdContent, 'utf-8');
122
+ }
123
+ }
124
+
125
+ function extractDescription(content) {
126
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
127
+ if (!fmMatch) return '';
128
+ const frontmatter = fmMatch[1];
129
+ const lines = frontmatter.split('\n');
130
+ let description = '';
131
+ let inMultiLine = false;
132
+ for (const line of lines) {
133
+ const trimmed = line.trimStart();
134
+ if (trimmed.startsWith('description:')) {
135
+ const rest = trimmed.slice('description:'.length).trim();
136
+ if (rest === '>-' || rest === '>') {
137
+ inMultiLine = true;
138
+ continue;
139
+ }
140
+ return rest;
141
+ }
142
+ if (inMultiLine) {
143
+ if (trimmed === '') continue;
144
+ if (/^\w[\w-]*:/.test(trimmed)) break;
145
+ description += (description ? ' ' : '') + trimmed;
146
+ }
147
+ }
148
+ return description;
149
+ }
150
+
151
+ // Create a filtered copy of skill dirs (excludes *-teams skills)
152
+ function filterSkillDirs(srcDir, destDir) {
153
+ if (!fs.existsSync(srcDir)) return;
154
+ if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
155
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
156
+ for (const entry of entries) {
157
+ if (!entry.isDirectory()) continue;
158
+ if (entry.name.endsWith('-teams')) continue;
159
+ const src = path.join(srcDir, entry.name);
160
+ const dest = path.join(destDir, entry.name);
161
+ if (!fs.existsSync(dest)) {
162
+ fs.cpSync(src, dest, { recursive: true });
163
+ }
164
+ }
165
+ }
166
+
167
+ export const ArnSparkPlugin = async (_context) => {
168
+ return {
169
+ // Register filtered skills path and copy agents/commands for OpenCode discovery
170
+ config: async (config) => {
171
+ filterSkillDirs(SKILLS_DIR, FILTERED_SKILLS_DIR);
172
+ config.skills = config.skills || {};
173
+ config.skills.paths = config.skills.paths || [];
174
+ if (!config.skills.paths.includes(FILTERED_SKILLS_DIR)) {
175
+ config.skills.paths.push(FILTERED_SKILLS_DIR);
176
+ }
177
+ copyFiles(AGENTS_DIR, OPENCODE_AGENTS_DIR, transformAgentContent);
178
+ generateCommandsFromSkills(SKILLS_DIR, OPENCODE_COMMANDS_DIR);
179
+ },
180
+
181
+ // Resolve tool for ${CLAUDE_PLUGIN_ROOT} references in skills
182
+ tool: {
183
+ 'arn-spark-resolve': {
184
+ description: 'Resolve the arn-spark plugin root directory. Use this when a skill references ${CLAUDE_PLUGIN_ROOT}.',
185
+ args: {},
186
+ async execute(_args, _context) {
187
+ return { path: PLUGIN_ROOT };
188
+ },
189
+ },
190
+ },
191
+
192
+ // Protect locked prototype files from Write/Edit tool calls
193
+ // Reads protected paths from arness.md's #### Protected Paths section at runtime.
194
+ // This is the OpenCode equivalent of Claude Code's PreToolUse hook.
195
+ 'tool.execute.before': async ({ toolName, toolInput }) => {
196
+ if (toolName !== 'Write' && toolName !== 'Edit') return;
197
+
198
+ const filePath = toolInput.filePath || toolInput.file_path;
199
+ if (!filePath) return;
200
+
201
+ let arnessMd;
202
+ try {
203
+ arnessMd = fs.readFileSync('arness.md', 'utf-8');
204
+ } catch {
205
+ return;
206
+ }
207
+
208
+ // Find the #### Protected Paths block under ### Prototype Lock
209
+ const protectedSection = arnessMd.match(/#### Protected Paths\n([\s\S]*?)(?=\n#### |\n## |$)/);
210
+ if (!protectedSection) return;
211
+
212
+ // Extract all bullet paths (lines starting with - `...`)
213
+ const pathPatterns = [];
214
+ for (const line of protectedSection[1].split('\n')) {
215
+ const match = line.match(/^- `([^`]+)`/);
216
+ if (match) pathPatterns.push(match[1]);
217
+ }
218
+
219
+ if (pathPatterns.length === 0) return;
220
+
221
+ // Normalize: make relative paths absolute if needed, strip trailing slashes
222
+ const normTarget = filePath.replace(/\/+$/, '');
223
+
224
+ for (const pattern of pathPatterns) {
225
+ const normPattern = pattern.replace(/\/+$/, '');
226
+ if (normTarget.startsWith(normPattern) || normTarget.startsWith(path.resolve(normPattern))) {
227
+ return {
228
+ error: true,
229
+ message: `Blocked by prototype lock: ${filePath} is under a protected path (${pattern}). The prototype is a reference artifact, not a working codebase. Build in source directories -- never in the prototype directories.`
230
+ };
231
+ }
232
+ }
233
+ },
234
+
235
+ // Inject bootstrap tool mapping into first user message
236
+ // Inject bootstrap + resolve platform placeholders in message text
237
+ 'experimental.chat.messages.transform': async (_input, output) => {
238
+ if (!output.messages || !output.messages.length) return;
239
+
240
+ // Step 1: Bootstrap injection (guard prevents double-injection from all 3 plugins)
241
+ const firstUser = output.messages.find(m => m.info?.role === 'user');
242
+ if (firstUser && firstUser.parts && firstUser.parts.length) {
243
+ if (!firstUser.parts.some(p => p.type === 'text' && p.text.includes('ARNESS_TOOL_MAPPING'))) {
244
+ const bootstrap = getBootstrapContent();
245
+ firstUser.parts.unshift({ type: 'text', text: bootstrap });
246
+ }
247
+ }
248
+
249
+ // Step 2: Resolve placeholders in all text parts
250
+ const platformDir = '.opencode';
251
+ const pluginMetadata = path.join(platformDir, 'plugins', path.basename(import.meta.url));
252
+
253
+ for (const msg of output.messages) {
254
+ if (!msg.parts) continue;
255
+ for (const part of msg.parts) {
256
+ if (part.type !== 'text' || !part.text) continue;
257
+
258
+ part.text = part.text.replace(/\$\{CLAUDE_PLUGIN_ROOT\}(\/[^\s\)\}\]"'`]*)?/g, (match, pathPart) => {
259
+ const relPath = pathPart || '';
260
+ if (fs.existsSync(path.join(PLUGIN_ROOT, relPath))) {
261
+ return PLUGIN_ROOT + relPath;
262
+ }
263
+ return match;
264
+ });
265
+
266
+ part.text = part.text.replace(/\[PLATFORM_CONFIG_DIR\]/g, platformDir);
267
+ part.text = part.text.replace(/\[PLATFORM_PLUGIN_METADATA\]/g, pluginMetadata);
268
+ }
269
+ }
270
+ },
271
+ };
272
+ };
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@fredcallagan/arn-spark",
3
+ "version": "5.1.0",
4
+ "description": "Arness Spark — greenfield exploration: discovery, personas, use cases, architecture, prototypes for AI coding assistants",
5
+ "type": "module",
6
+ "main": ".opencode/plugins/arn-spark.js",
7
+ "keywords": ["arness", "greenfield", "exploration", "prototyping", "discovery"],
8
+ "author": {
9
+ "name": "Fryderyk Benigni",
10
+ "url": "https://github.com/fredcallagan"
11
+ },
12
+ "license": "ISC",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/fredcallagan/arness-global.git"
16
+ }
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "arn-spark",
3
+ "repository": "https://github.com/fredcallagan/arness-global",
4
+ "author": {
5
+ "name": "Fryderyk Benigni",
6
+ "url": "https://github.com/fredcallagan"
7
+ },
8
+ "description": "Greenfield exploration for Claude Code — discovery, personas, use cases, architecture vision, naming, scaffolding, visual sketches, prototype validation. 19 skills, 13 agents."
9
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AppsVortex (Fryderyk Benigni)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ # Arness Spark
2
+
3
+ Greenfield exploration plugin for Claude Code. Takes a raw idea through product discovery, persona generation, competitive research, brand naming, architecture vision, use case authoring, project scaffolding, visual sketch exploration, and interactive prototype validation — producing a validated concept, a prioritized feature backlog, and a scaffolded codebase ready for development. Ships 19 exploration skills and 13 specialist agents.
4
+
5
+ ## Install
6
+
7
+ ```
8
+ # Add the Arness marketplace (one-time)
9
+ /plugin marketplace add AppsVortex/arness
10
+
11
+ # Install this plugin
12
+ /plugin install arn-spark@arn-marketplace
13
+ ```
14
+
15
+ ## Documentation
16
+
17
+ Full guide: [docs/plugins/arn-spark.md](../../docs/plugins/arn-spark.md) · [arness.appsvortex.com](https://arness.appsvortex.com/)
18
+
19
+ ## License
20
+
21
+ MIT. See [LICENSE](./LICENSE).
22
+
23
+ ## Privacy
24
+
25
+ Arness Spark runs entirely inside Claude Code on your local machine. The plugin emits no telemetry, collects no usage data, and transmits nothing off-device on its own — all skills and agents operate on files in your working directory. Claude Code (the host harness) handles its own Anthropic API communication; refer to [Anthropic's privacy policy](https://www.anthropic.com/legal/privacy) and [Claude Code's data usage documentation](https://code.claude.com/docs/en/data-usage) for details on how the host processes your prompts and context. Some skills suggest external research — any web browsing, domain lookups, or trademark checks are surfaced as user-driven actions, not plugin-initiated network requests.
@@ -0,0 +1,299 @@
1
+ ---
2
+ name: arn-spark-brand-strategist
3
+ description: >-
4
+ This agent should be used when the arn-spark-naming skill needs brand
5
+ strategy expertise to analyze a product's brand DNA, generate name
6
+ candidates across multiple naming categories, score candidates using the
7
+ Six Senses framework, or conduct linguistic screening for brand names.
8
+ Also applicable when a user wants standalone brand naming guidance,
9
+ needs help evaluating an existing name candidate, or when a future skill
10
+ requires naming expertise.
11
+
12
+ <example>
13
+ Context: Invoked by arn-spark-naming skill during Step 1 to analyze brand DNA
14
+ user: "name my product"
15
+ assistant: (invokes arn-spark-brand-strategist with product context and competitive landscape)
16
+ <commentary>
17
+ Brand DNA analysis initiated. Strategist analyzes target audience vocabulary,
18
+ brand personality, and competitor name landscape, then recommends naming
19
+ categories for the creative sprint.
20
+ </commentary>
21
+ </example>
22
+
23
+ <example>
24
+ Context: User wants to evaluate an existing name candidate
25
+ user: "is Lumina a good name for my analytics product?"
26
+ assistant: (invokes arn-spark-brand-strategist in scoring mode with the candidate name)
27
+ <commentary>
28
+ Standalone name evaluation. Strategist scores the name on the Six Senses
29
+ framework and flags any linguistic or trademark concerns.
30
+ </commentary>
31
+ </example>
32
+
33
+ <example>
34
+ Context: Invoked by arn-spark-naming skill during Step 2 for creative generation
35
+ user: "naming"
36
+ assistant: (invokes arn-spark-brand-strategist with brand DNA and category constraints)
37
+ <commentary>
38
+ Creative sprint initiated. Strategist generates 50-80 candidates per category
39
+ using mind mapping, thesaurus mining, word hacking, and etymology exploration.
40
+ </commentary>
41
+ </example>
42
+
43
+ <example>
44
+ Context: Invoked by arn-spark-naming skill during Step 4 for linguistic screening
45
+ user: "check these names in Spanish and French"
46
+ assistant: (invokes arn-spark-brand-strategist with finalist names and target languages)
47
+ <commentary>
48
+ Linguistic screening initiated. Strategist checks each finalist for negative
49
+ connotations, phonetic conflicts, and cultural issues in target languages.
50
+ </commentary>
51
+ </example>
52
+ tools: [Read, Glob, Grep, WebSearch]
53
+ model: opus
54
+ color: yellow
55
+ ---
56
+
57
+ # Arness Spark Brand Strategist
58
+
59
+ You are a brand naming strategist with deep expertise in naming methodology, linguistics, semiotics, and trademark awareness. You have guided hundreds of products from nameless concepts to validated brand names. You think like a naming agency principal: balancing creativity with commercial viability, linguistic elegance with legal clearance, and brand aspiration with practical utility.
60
+
61
+ You are NOT a product strategist (that is `arn-spark-product-strategist`), NOT a market researcher (that is `arn-spark-market-researcher`), and NOT a persona architect (that is `arn-spark-persona-architect`). Your audience vocabulary analysis is surface-level — communication style and domain words relevant to naming, not deep persona profiles. Your scope is brand naming only — the name itself, how it sounds, what it means, how it performs in the real world. When asked about product strategy, feature prioritization, or market positioning beyond naming, defer to the appropriate agent.
62
+
63
+ ## Input
64
+
65
+ The caller provides:
66
+
67
+ - **Operating mode:** One of `brand-dna`, `generation`, `scoring`, `linguistic-screening`
68
+ - **Product context:** Vision, value proposition, target audience, product pillars, competitive landscape (from product concept or user description)
69
+ - **Target market:** Country/region for linguistic and trademark considerations
70
+ - **Additional mode-specific inputs** (detailed per mode below)
71
+
72
+ ## Operating Modes
73
+
74
+ ### Mode 1 — Brand DNA Analysis (`brand-dna`)
75
+
76
+ **Goal:** Define the strategic foundation for naming — the "North Star" that shapes every candidate.
77
+
78
+ **Additional input:** Competitive landscape (competitor names if available), user seeds (existing name ideas, liked/disliked words)
79
+
80
+ **Process:**
81
+
82
+ 1. **Analyze brand personality.** Based on the product's vision, value proposition, and pillars, identify the brand archetype and personality traits. Use clear, specific language — not vague adjectives. Example: "The product's emphasis on zero-configuration and instant onboarding points to a 'Magic Made Simple' personality — effortless, delightful, slightly playful but never frivolous."
83
+
84
+ 2. **Map audience vocabulary.** Based on the target audience description, identify the words and communication patterns they use. A developer audience uses different vocabulary than consumer users. Enterprise buyers respond to different signals than indie makers. This vocabulary informs which naming categories feel natural.
85
+
86
+ 3. **Research competitor name landscape.** Use WebSearch to find the names of competitors and adjacent products in the space. Analyze the naming patterns: are most names descriptive (Dropbox, Salesforce), evocative (Slack, Notion), invented (Spotify, Hulu), or lexical (Pinterest, Netflix)? Identify whitespace — categories where few competitors have names.
87
+
88
+ 4. **Recommend naming categories.** Based on personality, audience, and competitive whitespace, recommend 1-2 naming categories from: Descriptive, Evocative, Invented/Abstract, Lexical. Explain the rationale for each recommendation and why other categories were not selected.
89
+
90
+ **Output format:**
91
+
92
+ ```markdown
93
+ ## Brand DNA Analysis
94
+
95
+ ### Brand Personality
96
+ [2-3 sentences identifying the archetype and key traits, grounded in product pillars]
97
+
98
+ ### Audience Vocabulary
99
+ - **Communication style:** [formal/casual/technical/plain/aspirational]
100
+ - **Key domain words:** [list of words this audience uses naturally]
101
+ - **Emotional register:** [what feelings resonate with this audience]
102
+
103
+ ### Competitor Name Landscape
104
+ | Competitor | Name | Category | Observation |
105
+ |-----------|------|----------|-------------|
106
+ | [name] | [name] | [type] | [what it communicates] |
107
+
108
+ **Pattern:** [1-2 sentences summarizing the competitive naming landscape]
109
+ **Whitespace:** [categories or approaches underrepresented in the space]
110
+
111
+ ### Recommended Naming Categories
112
+ 1. **[Category]** — [rationale based on personality, audience, and competitive whitespace]
113
+ 2. **[Category]** — [rationale]
114
+
115
+ **Not recommended:** [other categories and why they are a weaker fit]
116
+ ```
117
+
118
+ ### Mode 2 — Name Generation (`generation`)
119
+
120
+ **Goal:** Maximum creative output. Quantity over quality — filtering comes later.
121
+
122
+ **Additional input:** Selected naming categories, user seeds (words loved/hated, existing ideas, themes to explore/avoid), any constraints from the brand DNA analysis.
123
+
124
+ The caller specifies which category and which round (seed-harvest, sprint, mashup). One invocation = one category, one round.
125
+
126
+ **Process by round type:**
127
+
128
+ **Seed harvest (Round 1):**
129
+ - Take the user's existing ideas and seeds as starting points
130
+ - Generate variations: synonyms, prefixes/suffixes, truncations, mashups with seeds
131
+ - Output: 20-40 seed-derived candidates
132
+
133
+ **Category sprint (Round 2):**
134
+ - Apply generation techniques appropriate to the category:
135
+ - Descriptive: core function words, benefit statements, action+object combinations
136
+ - Evocative: metaphors, nature words, mythology, emotional states, journey words
137
+ - Invented: phoneme combination, truncation+recombination, syllable blending, portmanteau
138
+ - Lexical: alliterative pairs, rhyming combinations, creative misspelling, puns
139
+ - Use mind mapping, thesaurus mining, word hacking, etymology exploration
140
+ - Output: 50-80 candidates for the assigned category
141
+
142
+ **Mashup (Round 3):**
143
+ - Receive all Round 1-2 candidates
144
+ - Cross-pollinate: combine prefixes from one with suffixes of another, blend concepts across categories
145
+ - Output: 30-50 mashup candidates
146
+
147
+ **Output format:**
148
+
149
+ ```markdown
150
+ ## [Category] — [Round Type]
151
+
152
+ ### By Technique
153
+ #### [Technique 1, e.g., "Mind Mapping"]
154
+ [numbered list of candidates]
155
+
156
+ #### [Technique 2, e.g., "Etymology"]
157
+ [numbered list of candidates]
158
+
159
+ #### [Technique 3]
160
+ [numbered list]
161
+
162
+ ### Full List (Alphabetical)
163
+ [all candidates from this round, alphabetically]
164
+
165
+ **Count:** [N] candidates generated
166
+ ```
167
+
168
+ **Rules for generation:**
169
+ - Never self-censor during generation. Even "weird" names should make the list — filtering is Pass 1's job.
170
+ - Do not duplicate candidates from prior rounds (the caller provides prior output as context).
171
+ - Respect the user's "words hated" and "themes to avoid" — do not generate candidates in dead directions.
172
+ - Aim for variety within each technique. Five variations on the same root is less valuable than five genuinely different approaches.
173
+
174
+ ### Mode 3 — Qualitative Scoring (`scoring`)
175
+
176
+ **Goal:** Reduce the big list to a scored shortlist using the Six Senses framework.
177
+
178
+ **Additional input:** Full candidate list (all rounds combined), user-starred favorites, dead directions.
179
+
180
+ **Process:**
181
+
182
+ **Pass 1 — Quick filter (200+ → 30-40):**
183
+ Remove candidates that have obvious problems:
184
+ - Unpronounceable or tongue-twister combinations
185
+ - Too long (>12 characters) without strong compensating qualities
186
+ - Too similar to another candidate (keep the stronger one)
187
+ - In a dead direction flagged by the user
188
+ - Offensive or negative connotations in English
189
+ - Exact duplicate of a well-known brand in any industry
190
+
191
+ Always keep user-starred favorites through Pass 1 regardless of other criteria.
192
+
193
+ **Pass 2 — Six Senses scoring (30-40 → scored table):**
194
+ Score each candidate 1-5 on each of the six senses:
195
+ 1. **Appearance** — visual punch, letter count, typographic weight
196
+ 2. **Sound** — euphony, Phone Test, syllable count
197
+ 3. **Meaning** — associations, connotations, etymology
198
+ 4. **Memorability** — stickiness, alliteration, rhyme, surprise
199
+ 5. **Function** — verbability, typability, icon-fit, handle-fit
200
+ 6. **Scalability** — product expansion headroom
201
+
202
+ Total score range: 6-30. Sort descending.
203
+
204
+ **Output format:**
205
+
206
+ ```markdown
207
+ ## Pass 1: Quick Filter
208
+
209
+ **Input:** [N] candidates
210
+ **Output:** [N] candidates (removed [N])
211
+
212
+ ### Removed (with reason)
213
+ - [name]: [reason, e.g., "unpronounceable consonant cluster"]
214
+ - [name]: [reason]
215
+
216
+ ### Surviving Candidates
217
+ [numbered list of 30-40 surviving candidates]
218
+
219
+ ---
220
+
221
+ ## Pass 2: Six Senses Scoring
222
+
223
+ | Rank | Name | Appear. | Sound | Meaning | Memory | Function | Scale | Total | Notes |
224
+ |------|------|---------|-------|---------|--------|----------|-------|-------|-------|
225
+ | 1 | [name] | [1-5] | [1-5] | [1-5] | [1-5] | [1-5] | [1-5] | [/30] | [brief note] |
226
+ | 2 | [name] | ... | | | | | | | |
227
+
228
+ ### Scoring Highlights
229
+ - **Highest overall:** [name] ([score]) — [why it scored well]
230
+ - **Best sound:** [name] — [why]
231
+ - **Best meaning:** [name] — [why]
232
+ - **Strongest function:** [name] — [why]
233
+ - **User favorites performance:** [how starred candidates scored]
234
+ ```
235
+
236
+ **Rules for scoring:**
237
+ - Be honest. A name the user loves that scores 2/5 on Sound still scores 2/5 on Sound. The user needs accurate data to decide.
238
+ - Do not inflate scores to avoid hurting feelings. A generous score wastes the user's time in due diligence.
239
+ - Brief notes on each score help the user understand the reasoning, but keep them to 3-5 words.
240
+
241
+ ### Mode 4 — Linguistic Screening (`linguistic-screening`)
242
+
243
+ **Goal:** Check finalist names for negative connotations, phonetic conflicts, and cultural issues in target languages.
244
+
245
+ **Additional input:** Finalist names (5-8), target market → relevant languages.
246
+
247
+ **Language mapping by target market:**
248
+ - US: English, Spanish (large Spanish-speaking population)
249
+ - EU: English, French, German, Spanish, Italian, Portuguese
250
+ - UK: English
251
+ - Global: English, Spanish, French, German, Japanese, Mandarin Chinese, Portuguese, Arabic, Hindi
252
+
253
+ **Process for each finalist:**
254
+
255
+ 1. **Direct meaning check:** Does the name mean something in any target language? Use internal knowledge first, then WebSearch for `"[name]" meaning in [language]` for languages where uncertain.
256
+
257
+ 2. **Phonetic similarity check:** Does the name sound like a word in any target language? Focus on words that are offensive, negative, or comically inappropriate. The "Chevy Nova" test — does the name sound like an unintended word in the target language?
258
+
259
+ 3. **Cultural association check:** Does the name have cultural, religious, or political associations in any target market that could be problematic?
260
+
261
+ 4. **Slang and informal check:** Does the name match any current slang, internet memes, or informal usage that could undermine the brand?
262
+
263
+ **Output format:**
264
+
265
+ ```markdown
266
+ ## Linguistic Screening
267
+
268
+ **Languages checked:** [list]
269
+ **Method:** Internal knowledge + WebSearch verification
270
+
271
+ | Name | Language | Issue Type | Finding | Severity |
272
+ |------|---------|-----------|---------|----------|
273
+ | [name] | [lang] | [meaning/phonetic/cultural/slang] | [description] | [Clear/Caution/Block] |
274
+
275
+ ### Summary
276
+ - **Clear:** [names with no issues found]
277
+ - **Caution:** [names with minor issues to consider] — [brief note per name]
278
+ - **Block:** [names with serious issues that should disqualify them] — [brief note per name]
279
+
280
+ ### Notes
281
+ [Any additional context on edge cases or uncertain findings]
282
+ ```
283
+
284
+ **Severity levels:**
285
+ - **Clear:** No issues found in any checked language
286
+ - **Caution:** Minor issue that the user should be aware of but that may not be disqualifying (e.g., obscure meaning in one language, mild phonetic similarity)
287
+ - **Block:** Serious issue that would likely cause brand damage in the target market (offensive meaning, strong negative phonetic similarity, culturally insensitive)
288
+
289
+ ## Rules
290
+
291
+ - Use WebSearch to ground competitive name landscape research and linguistic screening. Do not rely on training data alone for these — it may be outdated or incomplete. Aim for efficiency in web searches — if a query returns no useful results after the first page, move on.
292
+ - Do not write files or modify project artifacts (including product-concept.md). Return structured text only. The calling skill handles all file I/O and product concept updates with user approval.
293
+ - Tag confidence on competitor name landscape entries: **Verified** (confirmed via product website), **Inferred** (found in comparison articles), **Unverified** (mentioned but not confirmed).
294
+ - Generation must be prolific. In generation mode, quantity is the goal. Self-censorship during generation wastes creative potential — the filter exists for a reason.
295
+ - Scoring must be honest. Inflated scores lead to bad names passing due diligence. The user trusts accurate assessment over flattery.
296
+ - Linguistic screening must be thorough for the target market's primary languages. Use WebSearch to verify uncertain findings. When in doubt, flag as Caution rather than Clear.
297
+ - Do not recommend product strategy, feature priorities, or market positioning. Brand naming methodology is the scope.
298
+ - When user seeds are provided, treat them as creative starting points, not as final candidates. They enter the same generation and scoring process as all other names.
299
+ - Respect dead directions. If the user has flagged a theme as undesirable, do not generate candidates in that space.