@adityaaria/spark 6.0.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.
Files changed (91) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +20 -0
  3. package/.codex-plugin/plugin.json +48 -0
  4. package/.cursor-plugin/plugin.json +23 -0
  5. package/.kimi-plugin/plugin.json +38 -0
  6. package/.opencode/INSTALL.md +115 -0
  7. package/.opencode/plugins/spark.js +139 -0
  8. package/.pi/extensions/spark.ts +121 -0
  9. package/.version-bump.json +21 -0
  10. package/CLAUDE.md +115 -0
  11. package/CODE_OF_CONDUCT.md +128 -0
  12. package/GEMINI.md +2 -0
  13. package/LICENSE +21 -0
  14. package/README.md +282 -0
  15. package/RELEASE-NOTES.md +1299 -0
  16. package/assets/app-icon.png +0 -0
  17. package/assets/spark-small.svg +1 -0
  18. package/bin/spark.js +7 -0
  19. package/docs/README.kimi.md +94 -0
  20. package/docs/README.opencode.md +170 -0
  21. package/docs/porting-to-a-new-harness.md +830 -0
  22. package/gemini-extension.json +6 -0
  23. package/hooks/hooks-codex.json +16 -0
  24. package/hooks/hooks-cursor.json +10 -0
  25. package/hooks/hooks.json +16 -0
  26. package/hooks/run-hook.cmd +46 -0
  27. package/hooks/session-start +49 -0
  28. package/hooks/session-start-codex +26 -0
  29. package/package.json +52 -0
  30. package/skills/brainstorming/SKILL.md +159 -0
  31. package/skills/brainstorming/scripts/frame-template.html +213 -0
  32. package/skills/brainstorming/scripts/helper.js +167 -0
  33. package/skills/brainstorming/scripts/server.cjs +722 -0
  34. package/skills/brainstorming/scripts/start-server.sh +209 -0
  35. package/skills/brainstorming/scripts/stop-server.sh +120 -0
  36. package/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  37. package/skills/brainstorming/visual-companion.md +298 -0
  38. package/skills/dispatching-parallel-agents/SKILL.md +185 -0
  39. package/skills/executing-plans/SKILL.md +70 -0
  40. package/skills/finishing-a-development-branch/SKILL.md +241 -0
  41. package/skills/receiving-code-review/SKILL.md +213 -0
  42. package/skills/requesting-code-review/SKILL.md +103 -0
  43. package/skills/requesting-code-review/code-reviewer.md +172 -0
  44. package/skills/subagent-driven-development/SKILL.md +418 -0
  45. package/skills/subagent-driven-development/implementer-prompt.md +139 -0
  46. package/skills/subagent-driven-development/scripts/review-package +44 -0
  47. package/skills/subagent-driven-development/scripts/sdd-workspace +22 -0
  48. package/skills/subagent-driven-development/scripts/task-brief +40 -0
  49. package/skills/subagent-driven-development/task-reviewer-prompt.md +188 -0
  50. package/skills/systematic-debugging/CREATION-LOG.md +119 -0
  51. package/skills/systematic-debugging/SKILL.md +296 -0
  52. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  53. package/skills/systematic-debugging/condition-based-waiting.md +115 -0
  54. package/skills/systematic-debugging/defense-in-depth.md +122 -0
  55. package/skills/systematic-debugging/find-polluter.sh +63 -0
  56. package/skills/systematic-debugging/root-cause-tracing.md +169 -0
  57. package/skills/systematic-debugging/test-academic.md +14 -0
  58. package/skills/systematic-debugging/test-pressure-1.md +58 -0
  59. package/skills/systematic-debugging/test-pressure-2.md +68 -0
  60. package/skills/systematic-debugging/test-pressure-3.md +69 -0
  61. package/skills/test-driven-development/SKILL.md +371 -0
  62. package/skills/test-driven-development/testing-anti-patterns.md +299 -0
  63. package/skills/using-git-worktrees/SKILL.md +202 -0
  64. package/skills/using-spark/SKILL.md +121 -0
  65. package/skills/using-spark/references/antigravity-tools.md +96 -0
  66. package/skills/using-spark/references/claude-code-tools.md +50 -0
  67. package/skills/using-spark/references/codex-tools.md +72 -0
  68. package/skills/using-spark/references/copilot-tools.md +49 -0
  69. package/skills/using-spark/references/gemini-tools.md +63 -0
  70. package/skills/using-spark/references/pi-tools.md +28 -0
  71. package/skills/verification-before-completion/SKILL.md +139 -0
  72. package/skills/writing-plans/SKILL.md +174 -0
  73. package/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  74. package/skills/writing-skills/SKILL.md +689 -0
  75. package/skills/writing-skills/anthropic-best-practices.md +1150 -0
  76. package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  77. package/skills/writing-skills/graphviz-conventions.dot +172 -0
  78. package/skills/writing-skills/persuasion-principles.md +187 -0
  79. package/skills/writing-skills/render-graphs.js +168 -0
  80. package/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  81. package/src/cli/index.js +26 -0
  82. package/src/cli/install.js +47 -0
  83. package/src/cli/output.js +11 -0
  84. package/src/cli/parse-args.js +46 -0
  85. package/src/cli/prompt.js +10 -0
  86. package/src/installer/adapters/common.js +59 -0
  87. package/src/installer/adapters/extension-style.js +67 -0
  88. package/src/installer/adapters/shell-hook.js +57 -0
  89. package/src/installer/detect.js +168 -0
  90. package/src/installer/errors.js +7 -0
  91. package/src/installer/registry.js +35 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "spark-dev",
3
+ "description": "Development marketplace for SPARK core skills library",
4
+ "owner": {
5
+ "name": "Jesse Vincent",
6
+ "email": "jesse@fsck.com"
7
+ },
8
+ "plugins": [
9
+ {
10
+ "name": "spark",
11
+ "description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
12
+ "version": "6.0.3",
13
+ "source": "./",
14
+ "author": {
15
+ "name": "Jesse Vincent",
16
+ "email": "jesse@fsck.com"
17
+ }
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "spark",
3
+ "description": "Core skills library for Claude Code: TDD, debugging, collaboration patterns, and proven techniques",
4
+ "version": "6.0.3",
5
+ "author": {
6
+ "name": "Jesse Vincent",
7
+ "email": "jesse@fsck.com"
8
+ },
9
+ "homepage": "https://github.com/adityaaria/SPARK",
10
+ "repository": "https://github.com/adityaaria/SPARK",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "skills",
14
+ "tdd",
15
+ "debugging",
16
+ "collaboration",
17
+ "best-practices",
18
+ "workflows"
19
+ ]
20
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "spark",
3
+ "version": "6.0.3",
4
+ "description": "An agentic skills framework & software development methodology that works: planning, TDD, debugging, and collaboration workflows.",
5
+ "author": {
6
+ "name": "Jesse Vincent",
7
+ "email": "jesse@fsck.com",
8
+ "url": "https://github.com/adityaaria"
9
+ },
10
+ "homepage": "https://github.com/adityaaria/SPARK",
11
+ "repository": "https://github.com/adityaaria/SPARK",
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "brainstorming",
15
+ "subagent-driven-development",
16
+ "skills",
17
+ "planning",
18
+ "tdd",
19
+ "debugging",
20
+ "code-review",
21
+ "workflow"
22
+ ],
23
+ "skills": "./skills/",
24
+ "hooks": "./hooks/hooks-codex.json",
25
+ "interface": {
26
+ "displayName": "SPARK",
27
+ "shortDescription": "Planning, TDD, debugging, and delivery workflows for coding agents",
28
+ "longDescription": "Use SPARK to guide agent work through brainstorming, implementation planning, test-driven development, systematic debugging, parallel execution, code review, and finish-the-branch workflows.",
29
+ "developerName": "Jesse Vincent",
30
+ "category": "Coding",
31
+ "capabilities": [
32
+ "Interactive",
33
+ "Read",
34
+ "Write"
35
+ ],
36
+ "defaultPrompt": [
37
+ "I've got an idea for something I'd like to build.",
38
+ "Let's add a feature to this project."
39
+ ],
40
+ "websiteURL": "https://github.com/adityaaria/SPARK",
41
+ "privacyPolicyURL": "https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement",
42
+ "termsOfServiceURL": "https://docs.github.com/en/site-policy/github-terms/github-terms-of-service",
43
+ "brandColor": "#F59E0B",
44
+ "composerIcon": "./assets/spark-small.svg",
45
+ "logo": "./assets/app-icon.png",
46
+ "screenshots": []
47
+ }
48
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "spark",
3
+ "displayName": "SPARK",
4
+ "description": "Core skills library: TDD, debugging, collaboration patterns, and proven techniques",
5
+ "version": "6.0.3",
6
+ "author": {
7
+ "name": "Jesse Vincent",
8
+ "email": "jesse@fsck.com"
9
+ },
10
+ "homepage": "https://github.com/adityaaria/SPARK",
11
+ "repository": "https://github.com/adityaaria/SPARK",
12
+ "license": "MIT",
13
+ "keywords": [
14
+ "skills",
15
+ "tdd",
16
+ "debugging",
17
+ "collaboration",
18
+ "best-practices",
19
+ "workflows"
20
+ ],
21
+ "skills": "./skills/",
22
+ "hooks": "./hooks/hooks-cursor.json"
23
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "spark",
3
+ "version": "6.0.3",
4
+ "description": "An agentic skills framework and software development methodology.",
5
+ "author": {
6
+ "name": "Jesse Vincent",
7
+ "email": "jesse@fsck.com"
8
+ },
9
+ "homepage": "https://github.com/adityaaria/SPARK",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "brainstorming",
13
+ "subagent-driven-development",
14
+ "skills",
15
+ "planning",
16
+ "tdd",
17
+ "debugging",
18
+ "code-review",
19
+ "workflow"
20
+ ],
21
+ "skills": "./skills/",
22
+ "sessionStart": {
23
+ "skill": "using-spark"
24
+ },
25
+ "skillInstructions": "Kimi Code tool mapping for SPARK skills:\n\n- When a SPARK skill says to ask the user, ask clarifying questions, ask one question at a time, present multiple-choice options, use the terminal for a question, or wait for the user's choice, call Kimi Code's `AskUserQuestion` tool. Do not render those choices as plain assistant text unless `AskUserQuestion` is unavailable or the session is in auto permission mode.\n- For `AskUserQuestion`, provide 1 question with 2-4 concrete options when possible. Put the recommended option first and suffix its label with `(Recommended)`.\n- When a SPARK skill refers to `TodoWrite`, use Kimi Code's `TodoList` tool.\n- When a SPARK skill says `Task tool (general-purpose)` or asks you to dispatch an implementer/reviewer subagent, use Kimi Code's `Agent` tool with a Kimi subagent type. Do not pass `general-purpose` as `subagent_type`.\n- For implementation, code review, spec review, quality review, and filled SPARK subagent prompt templates, call `Agent` with `subagent_type: \"coder\"`, paste the fully filled prompt into `prompt`, and provide a short `description`.\n- For read-only codebase exploration that would take several searches, use `Agent` with `subagent_type: \"explore\"`.\n- For read-only planning or architecture design, use `Agent` with `subagent_type: \"plan\"`.\n- Keep dependent SPARK subagent steps sequential. Use multiple `Agent` calls, or `run_in_background: true` only when the work is independent and background agents are available.\n- When a SPARK skill refers to the `Skill` tool, use Kimi Code's native `Skill` tool.\n- Use Kimi Code's `Read`, `Write`, `Edit`, `Bash`, `Grep`, `Glob`, `FetchURL`, `WebSearch`, and MCP tools by their actual exposed names.\n- When a skill asks to search file contents, use `Grep`; when it asks to find files by path or pattern, use `Glob`; when it asks to fetch a URL, use `FetchURL`; when it asks to search the web, use `WebSearch`.",
26
+ "interface": {
27
+ "displayName": "SPARK",
28
+ "shortDescription": "Planning, TDD, debugging, and delivery workflows for coding agents",
29
+ "longDescription": "Use SPARK to guide agent work through brainstorming, implementation planning, test-driven development, systematic debugging, parallel execution, code review, and finish-the-branch workflows.",
30
+ "developerName": "Jesse Vincent",
31
+ "capabilities": [
32
+ "Interactive",
33
+ "Read",
34
+ "Write"
35
+ ],
36
+ "websiteURL": "https://github.com/adityaaria/SPARK"
37
+ }
38
+ }
@@ -0,0 +1,115 @@
1
+ # Installing SPARK for OpenCode
2
+
3
+ ## Prerequisites
4
+
5
+ - [OpenCode.ai](https://opencode.ai) installed
6
+
7
+ ## Installation
8
+
9
+ Add spark to the `plugin` array in your `opencode.json` (global or project-level):
10
+
11
+ ```json
12
+ {
13
+ "plugin": ["spark@git+https://github.com/adityaaria/SPARK.git"]
14
+ }
15
+ ```
16
+
17
+ Restart OpenCode. The plugin installs through OpenCode's plugin manager and
18
+ registers all skills.
19
+
20
+ Verify by asking: "Tell me about your spark"
21
+
22
+ OpenCode uses its own plugin install. If you also use Claude Code, Codex, or
23
+ another harness, install SPARK separately for each one.
24
+
25
+ ## Migrating from the old symlink-based install
26
+
27
+ If you previously installed spark using `git clone` and symlinks, remove the old setup:
28
+
29
+ ```bash
30
+ # Remove old symlinks
31
+ rm -f ~/.config/opencode/plugins/spark.js
32
+ rm -rf ~/.config/opencode/skills/spark
33
+
34
+ # Optionally remove the cloned repo
35
+ rm -rf ~/.config/opencode/spark
36
+
37
+ # Remove skills.paths from opencode.json if you added one for spark
38
+ ```
39
+
40
+ Then follow the installation steps above.
41
+
42
+ ## Usage
43
+
44
+ Use OpenCode's native `skill` tool:
45
+
46
+ ```
47
+ use skill tool to list skills
48
+ use skill tool to load brainstorming
49
+ ```
50
+
51
+ ## Updating
52
+
53
+ OpenCode installs SPARK through a git-backed package spec. Some OpenCode
54
+ and Bun versions pin that resolved git dependency in a lockfile or cache, so a
55
+ restart may not pick up the newest SPARK commit. If updates do not appear,
56
+ clear OpenCode's package cache or reinstall the plugin.
57
+
58
+ To pin a specific version:
59
+
60
+ ```json
61
+ {
62
+ "plugin": ["spark@git+https://github.com/adityaaria/SPARK.git#v5.0.3"]
63
+ }
64
+ ```
65
+
66
+ ## Troubleshooting
67
+
68
+ ### Plugin not loading
69
+
70
+ 1. Check logs: `opencode run --print-logs "hello" 2>&1 | grep -i spark`
71
+ 2. Verify the plugin line in your `opencode.json`
72
+ 3. Make sure you're running a recent version of OpenCode
73
+
74
+ ### Windows install issues
75
+
76
+ Some Windows OpenCode builds have upstream installer issues with git-backed
77
+ plugin specs, including cache paths for `git+https` URLs and Bun not finding
78
+ `git.exe` even when it works in a normal terminal. If OpenCode cannot install
79
+ the plugin, try installing with system npm and pointing OpenCode at the local
80
+ package:
81
+
82
+ ```powershell
83
+ npm install spark@git+https://github.com/adityaaria/SPARK.git --prefix "$HOME\.config\opencode"
84
+ ```
85
+
86
+ Then use the installed package path in `opencode.json`:
87
+
88
+ ```json
89
+ {
90
+ "plugin": ["~/.config/opencode/node_modules/spark"]
91
+ }
92
+ ```
93
+
94
+ ### Skills not found
95
+
96
+ 1. Use `skill` tool to list what's discovered
97
+ 2. Check that the plugin is loading (see above)
98
+
99
+ ### Tool mapping
100
+
101
+ Skills speak in actions ("create a todo", "dispatch a subagent", "read a file"). On OpenCode these resolve to:
102
+
103
+ - "Create a todo" / "mark complete in todo list" → `todowrite`
104
+ - `Subagent (general-purpose):` template → `task` tool with `subagent_type: "general"` (or `"explore"` for codebase exploration)
105
+ - "Invoke a skill" → OpenCode's native `skill` tool
106
+ - "Read a file" → `read`
107
+ - "Create a file" / "edit a file" / "delete a file" → `apply_patch`
108
+ - "Run a shell command" → `bash`
109
+ - "Search file contents" / "find files by name" → `grep`, `glob`
110
+ - "Fetch a URL" → `webfetch`
111
+
112
+ ## Getting Help
113
+
114
+ - Report issues: https://github.com/adityaaria/SPARK/issues
115
+ - Full documentation: https://github.com/adityaaria/SPARK/blob/main/docs/README.opencode.md
@@ -0,0 +1,139 @@
1
+ /**
2
+ * SPARK plugin for OpenCode.ai
3
+ *
4
+ * Injects spark bootstrap context via message transform.
5
+ * Auto-registers skills directory via config hook (no symlinks needed).
6
+ */
7
+
8
+ import path from 'path';
9
+ import fs from 'fs';
10
+ import os from 'os';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+
15
+ // Simple frontmatter extraction (avoid dependency on skills-core for bootstrap)
16
+ const extractAndStripFrontmatter = (content) => {
17
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
18
+ if (!match) return { frontmatter: {}, content };
19
+
20
+ const frontmatterStr = match[1];
21
+ const body = match[2];
22
+ const frontmatter = {};
23
+
24
+ for (const line of frontmatterStr.split('\n')) {
25
+ const colonIdx = line.indexOf(':');
26
+ if (colonIdx > 0) {
27
+ const key = line.slice(0, colonIdx).trim();
28
+ const value = line.slice(colonIdx + 1).trim().replace(/^["']|["']$/g, '');
29
+ frontmatter[key] = value;
30
+ }
31
+ }
32
+
33
+ return { frontmatter, content: body };
34
+ };
35
+
36
+ // Normalize a path: trim whitespace, expand ~, resolve to absolute
37
+ const normalizePath = (p, homeDir) => {
38
+ if (!p || typeof p !== 'string') return null;
39
+ let normalized = p.trim();
40
+ if (!normalized) return null;
41
+ if (normalized.startsWith('~/')) {
42
+ normalized = path.join(homeDir, normalized.slice(2));
43
+ } else if (normalized === '~') {
44
+ normalized = homeDir;
45
+ }
46
+ return path.resolve(normalized);
47
+ };
48
+
49
+ // Module-level cache for bootstrap content.
50
+ // The SKILL.md file does not change during a session, so reading + parsing it
51
+ // once eliminates redundant fs.existsSync + fs.readFileSync + regex work on
52
+ // every agent step. See #1202 for the full analysis.
53
+ let _bootstrapCache = undefined; // undefined = not yet loaded, null = file missing
54
+
55
+ export const SPARKPlugin = async ({ client, directory }) => {
56
+ const homeDir = os.homedir();
57
+ const sparkSkillsDir = path.resolve(__dirname, '../../skills');
58
+ const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir);
59
+ const configDir = envConfigDir || path.join(homeDir, '.config/opencode');
60
+
61
+ // Helper to generate bootstrap content (cached after first call)
62
+ const getBootstrapContent = () => {
63
+ // Return cached result on subsequent calls
64
+ if (_bootstrapCache !== undefined) return _bootstrapCache;
65
+
66
+ // Try to load using-spark skill
67
+ const skillPath = path.join(sparkSkillsDir, 'using-spark', 'SKILL.md');
68
+ if (!fs.existsSync(skillPath)) {
69
+ _bootstrapCache = null;
70
+ return null;
71
+ }
72
+
73
+ const fullContent = fs.readFileSync(skillPath, 'utf8');
74
+ const { content } = extractAndStripFrontmatter(fullContent);
75
+
76
+ const toolMapping = `**Tool Mapping for OpenCode:**
77
+ When skills request actions, substitute OpenCode equivalents:
78
+ - Create or update todos → \`todowrite\`
79
+ - \`Subagent (general-purpose):\` → \`task\` with \`subagent_type: "general"\`
80
+ - Invoke a skill → OpenCode's native \`skill\` tool
81
+ - Read files → \`read\`
82
+ - Create, edit, or delete files → \`apply_patch\`
83
+ - Run shell commands → \`bash\`
84
+ - Search files → \`grep\`, \`glob\`
85
+ - Fetch a URL → \`webfetch\`
86
+
87
+ Use OpenCode's native \`skill\` tool to list and load skills.`;
88
+
89
+ _bootstrapCache = `<EXTREMELY_IMPORTANT>
90
+ You have spark.
91
+
92
+ **IMPORTANT: The using-spark skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load "using-spark" again - that would be redundant.**
93
+
94
+ ${content}
95
+
96
+ ${toolMapping}
97
+ </EXTREMELY_IMPORTANT>`;
98
+
99
+ return _bootstrapCache;
100
+ };
101
+
102
+ return {
103
+ // Inject skills path into live config so OpenCode discovers spark skills
104
+ // without requiring manual symlinks or config file edits.
105
+ // This works because Config.get() returns a cached singleton — modifications
106
+ // here are visible when skills are lazily discovered later.
107
+ config: async (config) => {
108
+ config.skills = config.skills || {};
109
+ config.skills.paths = config.skills.paths || [];
110
+ if (!config.skills.paths.includes(sparkSkillsDir)) {
111
+ config.skills.paths.push(sparkSkillsDir);
112
+ }
113
+ },
114
+
115
+ // Inject bootstrap into the first user message of each session.
116
+ // Using a user message instead of a system message avoids:
117
+ // 1. Token bloat from system messages repeated every turn (#750)
118
+ // 2. Multiple system messages breaking Qwen and other models (#894)
119
+ //
120
+ // The hook fires on every agent step (not just every turn) because
121
+ // opencode's prompt.ts reloads messages from DB each step. Fresh message
122
+ // arrays may need injection again, so getBootstrapContent() must not do
123
+ // repeated disk work.
124
+ 'experimental.chat.messages.transform': async (_input, output) => {
125
+ const bootstrap = getBootstrapContent();
126
+ if (!bootstrap || !output.messages.length) return;
127
+ const firstUser = output.messages.find(m => m.info.role === 'user');
128
+ if (!firstUser || !firstUser.parts.length) return;
129
+
130
+ // Guard: skip if first user message already contains bootstrap.
131
+ // This prevents double injection when OpenCode passes an already
132
+ // transformed in-memory message array through the hook again.
133
+ if (firstUser.parts.some(p => p.type === 'text' && p.text.includes('EXTREMELY_IMPORTANT'))) return;
134
+
135
+ const ref = firstUser.parts[0];
136
+ firstUser.parts.unshift({ ...ref, type: 'text', text: bootstrap });
137
+ }
138
+ };
139
+ };
@@ -0,0 +1,121 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
+
6
+ const EXTREMELY_IMPORTANT_MARKER = "<EXTREMELY_IMPORTANT>";
7
+ const BOOTSTRAP_MARKER = "spark:using-spark bootstrap for pi";
8
+
9
+ const extensionDir = dirname(fileURLToPath(import.meta.url));
10
+ const packageRoot = resolve(extensionDir, "../..");
11
+ const skillsDir = resolve(packageRoot, "skills");
12
+ const bootstrapSkillPath = resolve(skillsDir, "using-spark", "SKILL.md");
13
+
14
+ let cachedBootstrap: string | null | undefined;
15
+
16
+ export default function sparkPiExtension(pi: ExtensionAPI) {
17
+ let injectBootstrap = true;
18
+
19
+ pi.on("resources_discover", async () => ({
20
+ skillPaths: [skillsDir],
21
+ }));
22
+
23
+ pi.on("session_start", async () => {
24
+ injectBootstrap = true;
25
+ });
26
+
27
+ pi.on("session_compact", async () => {
28
+ injectBootstrap = true;
29
+ });
30
+
31
+ pi.on("agent_end", async () => {
32
+ injectBootstrap = false;
33
+ });
34
+
35
+ pi.on("context", async (event) => {
36
+ if (!injectBootstrap) return;
37
+ if (event.messages.some(messageContainsBootstrap)) return;
38
+
39
+ const bootstrap = getBootstrapContent();
40
+ if (!bootstrap) return;
41
+
42
+ const bootstrapMessage = {
43
+ role: "user" as const,
44
+ content: [{ type: "text" as const, text: bootstrap }],
45
+ timestamp: Date.now(),
46
+ };
47
+
48
+ const insertAt = firstNonCompactionSummaryIndex(event.messages);
49
+ return {
50
+ messages: [
51
+ ...event.messages.slice(0, insertAt),
52
+ bootstrapMessage,
53
+ ...event.messages.slice(insertAt),
54
+ ],
55
+ };
56
+ });
57
+ }
58
+
59
+ function getBootstrapContent(): string | null {
60
+ if (cachedBootstrap !== undefined) return cachedBootstrap;
61
+
62
+ try {
63
+ const skillContent = readFileSync(bootstrapSkillPath, "utf8");
64
+ const body = stripFrontmatter(skillContent);
65
+ cachedBootstrap = `${EXTREMELY_IMPORTANT_MARKER}
66
+ ${BOOTSTRAP_MARKER}
67
+
68
+ You have spark.
69
+
70
+ The using-spark skill content is included below and is already loaded for this Pi session. Follow it now. Do not try to load using-spark again.
71
+
72
+ ${body}
73
+
74
+ ${piToolMapping()}
75
+ </EXTREMELY_IMPORTANT>`;
76
+ return cachedBootstrap;
77
+ } catch {
78
+ cachedBootstrap = null;
79
+ return null;
80
+ }
81
+ }
82
+
83
+ function stripFrontmatter(content: string): string {
84
+ const match = content.match(/^---\n[\s\S]*?\n---\n([\s\S]*)$/);
85
+ return (match ? match[1] : content).trim();
86
+ }
87
+
88
+ function piToolMapping(): string {
89
+ return `## Pi tool mapping
90
+
91
+ Pi has native skills but does not expose Claude Code's \`Skill\` tool. When a SPARK instruction says to invoke a skill, use Pi's native skill system instead: load the relevant \`SKILL.md\` with \`read\` when the skill applies, or let a human invoke \`/skill:name\` explicitly.
92
+
93
+ Pi's built-in coding tools are lowercase: \`read\`, \`write\`, \`edit\`, \`bash\`, plus optional \`grep\`, \`find\`, and \`ls\`. Use those for the corresponding actions: read a file, create or edit files, run shell commands, search file contents, find files by name, and list directories.
94
+
95
+ Pi does not ship a standard subagent tool. If a subagent tool such as \`subagent\` from \`pi-subagents\` is available, use it for SPARK subagent workflows. If no subagent tool is available, do the work in this session or explain the missing capability instead of inventing \`Task\` calls.
96
+
97
+ Pi does not ship a standard task-list tool. If an installed todo/task tool is available, use it. Otherwise track work in plan files or a repo-local \`TODO.md\` when task tracking is needed. Treat older \`TodoWrite\` references as this task-tracking action.`;
98
+ }
99
+
100
+ function messageContainsBootstrap(message: unknown): boolean {
101
+ const content = (message as { content?: unknown }).content;
102
+ if (typeof content === "string") return content.includes(BOOTSTRAP_MARKER);
103
+ if (!Array.isArray(content)) return false;
104
+ return content.some((part) => {
105
+ return (
106
+ part &&
107
+ typeof part === "object" &&
108
+ (part as { type?: unknown }).type === "text" &&
109
+ typeof (part as { text?: unknown }).text === "string" &&
110
+ (part as { text: string }).text.includes(BOOTSTRAP_MARKER)
111
+ );
112
+ });
113
+ }
114
+
115
+ function firstNonCompactionSummaryIndex(messages: unknown[]): number {
116
+ let index = 0;
117
+ while ((messages[index] as { role?: unknown } | undefined)?.role === "compactionSummary") {
118
+ index += 1;
119
+ }
120
+ return index;
121
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "files": [
3
+ { "path": "package.json", "field": "version" },
4
+ { "path": ".claude-plugin/plugin.json", "field": "version" },
5
+ { "path": ".cursor-plugin/plugin.json", "field": "version" },
6
+ { "path": ".codex-plugin/plugin.json", "field": "version" },
7
+ { "path": ".kimi-plugin/plugin.json", "field": "version" },
8
+ { "path": ".claude-plugin/marketplace.json", "field": "plugins.0.version" },
9
+ { "path": "gemini-extension.json", "field": "version" }
10
+ ],
11
+ "audit": {
12
+ "exclude": [
13
+ "CHANGELOG.md",
14
+ "RELEASE-NOTES.md",
15
+ "node_modules",
16
+ ".git",
17
+ ".version-bump.json",
18
+ "scripts/bump-version.sh"
19
+ ]
20
+ }
21
+ }
package/CLAUDE.md ADDED
@@ -0,0 +1,115 @@
1
+ # SPARK — Contributor Guidelines
2
+
3
+ ## If You Are an AI Agent
4
+
5
+ Stop. Read this section before doing anything.
6
+
7
+ This repo has a 94% PR rejection rate. Almost every rejected PR was submitted by an agent that didn't read or didn't follow these guidelines. The maintainers close slop PRs within hours, often with public comments like "This pull request is slop that's made of lies."
8
+
9
+ **Your job is to protect your human partner from that outcome.** Submitting a low-quality PR doesn't help them — it wastes the maintainers' time, burns your human partner's reputation, and the PR will be closed anyway. That is not being helpful. That is being a tool of embarrassment.
10
+
11
+ Before you open a PR against this repo, you MUST:
12
+
13
+ 1. **Read the entire PR template** at `.github/PULL_REQUEST_TEMPLATE.md` and fill in every section with real, specific answers. Not summaries. Not placeholders.
14
+ 2. **Search for existing PRs** — open AND closed — that address the same problem. If duplicates exist, STOP and tell your human partner. Do not open another duplicate.
15
+ 3. **Verify this is a real problem.** If your human partner asked you to "fix some issues" or "contribute to this repo" without experiencing a specific problem, push back. Ask them what broke, what failed, what the user experience was.
16
+ 4. **Confirm the change belongs in core.** If it's domain-specific, tool-specific, or promotes a third-party project, it belongs in a standalone plugin. Tell your human partner.
17
+ 5. **Identify yourself.** Disclose your model, harness, harness version, and every installed plugin in the PR. Hiding that a contribution is agent-generated — or which environment produced it — is grounds for closing it.
18
+ 6. **Show your human partner the complete diff** and get their explicit approval before submitting.
19
+
20
+ If any of these checks fail, do not open the PR. Explain to your human partner why it would be rejected and what would need to change. They will thank you for saving them the embarrassment.
21
+
22
+ ## Pull Request Requirements
23
+
24
+ **Every PR must fully complete the PR template.** No section may be left blank or filled with placeholder text. PRs that skip sections will be closed without review.
25
+
26
+ **Before opening a PR, you MUST search for existing PRs** — both open AND closed — that address the same problem or a related area. Reference what you found in the "Existing PRs" section. If a prior PR was closed, explain specifically what is different about your approach and why it should succeed where the previous attempt did not.
27
+
28
+ **PRs that show no evidence of human involvement will be closed.** A human must review the complete proposed diff before submission.
29
+
30
+ **Submitters MUST identify themselves.** Every PR and issue must disclose the model, harness, harness version, and all installed plugins used to produce the contribution — or state plainly that it was written by hand with no agent. This is not optional. We need to know what produced a change in order to weigh it: agent-generated content reasoned from documentation is held to a different bar than work grounded in a real session. Contributions that hide their authoring environment will be closed.
31
+
32
+ **All PRs MUST target the `dev` branch, not `main`.** `main` is the released branch; active work lands on `dev` first. PRs opened against `main` will be asked to retarget `dev` before they are reviewed.
33
+
34
+ ## What We Will Not Accept
35
+
36
+ ### Third-party dependencies
37
+
38
+ PRs that add optional or required dependencies on third-party projects will not be accepted unless they are adding support for a new harness (e.g., a new IDE or CLI tool). SPARK is a zero-dependency plugin by design. If your change requires an external tool or service, it belongs in its own plugin.
39
+
40
+ ### "Compliance" changes to skills
41
+
42
+ Our internal skill philosophy differs from Anthropic's published guidance on writing skills. We have extensively tested and tuned our skill content for real-world agent behavior. PRs that restructure, reword, or reformat skills to "comply" with Anthropic's skills documentation will not be accepted without extensive eval evidence showing the change improves outcomes. The bar for modifying behavior-shaping content is very high.
43
+
44
+ ### Project-specific or personal configuration
45
+
46
+ Skills, hooks, or configuration that only benefit a specific project, team, domain, or workflow do not belong in core. Publish these as a separate plugin.
47
+
48
+ ### Bulk or spray-and-pray PRs
49
+
50
+ Do not trawl the issue tracker and open PRs for multiple issues in a single session. Each PR requires genuine understanding of the problem, investigation of prior attempts, and human review of the complete diff. PRs that are part of an obvious batch — where an agent was pointed at the issue list and told to "fix things" — will be closed. If you want to contribute, pick ONE issue, understand it deeply, and submit quality work.
51
+
52
+ ### Speculative or theoretical fixes
53
+
54
+ Every PR must solve a real problem that someone actually experienced. "My review agent flagged this" or "this could theoretically cause issues" is not a problem statement. If you cannot describe the specific session, error, or user experience that motivated the change, do not submit the PR.
55
+
56
+ ### Domain-specific skills
57
+
58
+ SPARK core contains general-purpose skills that benefit all users regardless of their project. Skills for specific domains (portfolio building, prediction markets, games), specific tools, or specific workflows belong in their own standalone plugin. Ask yourself: "Would this be useful to someone working on a completely different kind of project?" If not, publish it separately.
59
+
60
+ ### Fork-specific changes
61
+
62
+ If you maintain a fork with customizations, do not open PRs to sync your fork or push fork-specific changes upstream. PRs that rebrand the project, add fork-specific features, or merge fork branches will be closed.
63
+
64
+ ### Fabricated content
65
+
66
+ PRs containing invented claims, fabricated problem descriptions, or hallucinated functionality will be closed immediately. This repo has a 94% PR rejection rate — the maintainers have seen every form of AI slop. They will notice.
67
+
68
+ ### Bundled unrelated changes
69
+
70
+ PRs containing multiple unrelated changes will be closed. Split them into separate PRs.
71
+
72
+ ## New Harness Support
73
+
74
+ If your PR adds support for a new harness (IDE, CLI tool, agent runner), you MUST include a session transcript proving the integration works end-to-end.
75
+
76
+ A real integration loads the `using-spark` bootstrap at session start. The bootstrap is what causes skills to auto-trigger at the right moments. Without it, the skills are dead weight — present on disk but never invoked.
77
+
78
+ **The acceptance test.** Open a clean session in the new harness and send exactly this user message:
79
+
80
+ > Let's make a react todo list
81
+
82
+ A working integration auto-triggers the `brainstorming` skill before any code is written. Paste the complete transcript in the PR.
83
+
84
+ **These are not real integrations and will be closed:**
85
+
86
+ - Manually copying skill files into the harness
87
+ - Wrapping with `npx skills` or similar at-runtime shims
88
+ - Anything that requires the user to opt in to skills per-session
89
+ - Anything where `brainstorming` does not auto-trigger on the acceptance test above
90
+
91
+ If you are not sure whether your integration loads the bootstrap at session start, it does not.
92
+
93
+ ## Skill Changes Require Evaluation
94
+
95
+ Skills are not prose — they are code that shapes agent behavior. If you modify skill content:
96
+
97
+ - Use `spark:writing-skills` to develop and test changes
98
+ - Run adversarial pressure testing across multiple sessions
99
+ - Show before/after eval results in your PR
100
+ - Do not modify carefully-tuned content (Red Flags tables, rationalization lists, "human partner" language) without evidence the change is an improvement
101
+
102
+ ## Eval harness
103
+
104
+ Skill-behavior evals live in [spark-evals](https://github.com/prime-radiant-inc/spark-evals/), cloned into `evals/` — see `evals/README.md` for setup. Drill (the harness) drives real tmux sessions of Claude Code / Codex / Gemini CLI and judges skill compliance with an LLM verifier. Plugin-infrastructure tests still live at `tests/`.
105
+
106
+ ## Understand the Project Before Contributing
107
+
108
+ Before proposing changes to skill design, workflow philosophy, or architecture, read existing skills and understand the project's design decisions. SPARK has its own tested philosophy about skill design, agent behavior shaping, and terminology (e.g., "your human partner" is deliberate, not interchangeable with "the user"). Changes that rewrite the project's voice or restructure its approach without understanding why it exists will be rejected.
109
+
110
+ ## General
111
+
112
+ - Read `.github/PULL_REQUEST_TEMPLATE.md` before submitting
113
+ - One problem per PR
114
+ - Test on at least one harness and report results in the environment table
115
+ - Describe the problem you solved, not just what you changed