@heart-of-gold/toolkit 0.1.24 → 0.1.30

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 (60) hide show
  1. package/.claude-plugin/marketplace.json +5 -5
  2. package/README.md +24 -9
  3. package/extensions/pi/architect.ts +23 -0
  4. package/extensions/pi/guided-workflows-core.js +147 -0
  5. package/extensions/pi/guided-workflows.ts +420 -0
  6. package/extensions/pi/index.ts +17 -0
  7. package/extensions/pi/share.ts +42 -0
  8. package/package.json +4 -1
  9. package/plugins/babel-fish/README.md +4 -1
  10. package/plugins/deep-thought/.claude-plugin/plugin.json +1 -1
  11. package/plugins/deep-thought/README.md +4 -1
  12. package/plugins/deep-thought/skills/expert-panel/SKILL.md +517 -0
  13. package/plugins/guide/README.md +11 -2
  14. package/plugins/guide/scripts/fetch-gmail.sh +88 -21
  15. package/plugins/marvin/.claude-plugin/plugin.json +1 -1
  16. package/plugins/marvin/README.md +23 -5
  17. package/plugins/marvin/skills/copy-editor/SKILL.md +300 -0
  18. package/plugins/marvin/skills/copy-editor/knowledge/ROLE.md +186 -0
  19. package/plugins/marvin/skills/copy-editor/knowledge/config-schema.md +166 -0
  20. package/plugins/marvin/skills/copy-editor/knowledge/language-profiles.md +138 -0
  21. package/plugins/marvin/skills/copy-editor/knowledge/lockfile-schema.md +259 -0
  22. package/plugins/marvin/skills/copy-editor/knowledge/output-contract.md +191 -0
  23. package/plugins/marvin/skills/copy-editor/knowledge/segmentation-prompt-v1.md +398 -0
  24. package/plugins/marvin/skills/copy-editor/knowledge/segmentation-prompt-v2.md +340 -0
  25. package/plugins/marvin/skills/copy-editor/knowledge/segmentation.md +165 -0
  26. package/plugins/marvin/skills/copy-editor/rules/czech.ts +482 -0
  27. package/plugins/marvin/skills/copy-editor/rules/english.ts +64 -0
  28. package/plugins/marvin/skills/copy-editor/rules/index.ts +29 -0
  29. package/plugins/marvin/skills/copy-editor/rules/types.ts +130 -0
  30. package/plugins/marvin/skills/copy-editor/scripts/copy-audit.ts +1527 -0
  31. package/plugins/marvin/skills/copy-editor/scripts/finding-filter.ts +51 -0
  32. package/plugins/marvin/skills/copy-editor/scripts/lockfile.ts +363 -0
  33. package/plugins/marvin/skills/copy-editor/scripts/self-test.ts +778 -0
  34. package/plugins/marvin/skills/redteam/SKILL.md +0 -22
  35. package/plugins/marvin/skills/share-html/SKILL.md +55 -0
  36. package/plugins/marvin/skills/share-html/scripts/healthcheck.sh +5 -0
  37. package/plugins/marvin/skills/share-html/scripts/publish.sh +101 -0
  38. package/plugins/marvin/skills/share-server-setup/SKILL.md +108 -0
  39. package/plugins/marvin/skills/share-server-setup/scripts/configure-existing-server.sh +38 -0
  40. package/plugins/marvin/skills/share-server-setup/scripts/configure-tailscale-viewer.sh +65 -0
  41. package/plugins/marvin/skills/share-server-setup/scripts/healthcheck.sh +44 -0
  42. package/plugins/marvin/skills/share-server-setup/scripts/install-launch-agent.sh +23 -0
  43. package/plugins/marvin/skills/share-server-setup/scripts/install-reference-server.sh +28 -0
  44. package/plugins/quellis/README.md +11 -2
  45. package/plugins/quellis/knowledge/coaching-frameworks.md +157 -14
  46. package/plugins/quellis/plugin.json +2 -1
  47. package/plugins/quellis/skills/coach/SKILL.md +269 -29
  48. package/plugins/quellis/skills/goal-checkin/SKILL.md +41 -11
  49. package/plugins/quellis/skills/goal-setting/SKILL.md +74 -30
  50. package/plugins/quellis/skills/reflect/SKILL.md +92 -20
  51. package/share-server/README.md +138 -0
  52. package/share-server/package.json +7 -0
  53. package/share-server/src/config.ts +65 -0
  54. package/share-server/src/index.ts +276 -0
  55. package/share-server/src/publish.ts +131 -0
  56. package/share-server/src/storage.ts +98 -0
  57. package/share-server/src/types.ts +39 -0
  58. package/share-server/src/viewer.ts +56 -0
  59. package/src/commands/share-server.ts +105 -0
  60. package/src/index.ts +3 -1
@@ -9,31 +9,31 @@
9
9
  "name": "guide",
10
10
  "source": "./plugins/guide",
11
11
  "description": "The Hitchhiker's Guide — content creation suite with automated pipeline, daily briefs, and blog writing",
12
- "version": "0.1.0"
12
+ "version": "0.3.0"
13
13
  },
14
14
  {
15
15
  "name": "deep-thought",
16
16
  "source": "./plugins/deep-thought",
17
17
  "description": "The Answer Computer — reasoning tools for brainstorming, planning, and deep thinking",
18
- "version": "0.1.0"
18
+ "version": "0.2.2"
19
19
  },
20
20
  {
21
21
  "name": "marvin",
22
22
  "source": "./plugins/marvin",
23
23
  "description": "The Paranoid Android — quality tools for code review, knowledge compounding, and work execution",
24
- "version": "0.1.0"
24
+ "version": "0.3.0"
25
25
  },
26
26
  {
27
27
  "name": "babel-fish",
28
28
  "source": "./plugins/babel-fish",
29
29
  "description": "Universal Translator — media generation tools for audio, image, and video content",
30
- "version": "0.1.0"
30
+ "version": "0.2.0"
31
31
  },
32
32
  {
33
33
  "name": "quellis",
34
34
  "source": "./plugins/quellis",
35
35
  "description": "AI Coaching Companion — ICF methodology, powerful questions, goal-setting, and reflection",
36
- "version": "0.1.0"
36
+ "version": "0.3.0"
37
37
  }
38
38
  ]
39
39
  }
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Don't Panic.**
4
4
 
5
- 29 skills for AI coding agents. Five plugins. Works with **Claude Code, Codex, OpenCode, Pi**, and any tool supporting the [agentskills.io](https://agentskills.io) standard. Named after *The Hitchhiker's Guide to the Galaxy* because the universe is absurd and your tools should at least have personality.
5
+ 30 skills for AI coding agents. Five plugins. Works with **Claude Code, Codex, OpenCode, Pi**, and any tool supporting the [agentskills.io](https://agentskills.io) standard. Named after *The Hitchhiker's Guide to the Galaxy* because the universe is absurd and your tools should at least have personality.
6
6
 
7
7
  ## Installation
8
8
 
@@ -38,8 +38,15 @@ Pi also discovers skills from the shared `~/.agents/skills/` location, so instal
38
38
  When installed as a Pi package, Heart of Gold exposes Pi-native extension commands for the flagship workflows:
39
39
  - `/deep-thought-brainstorm` — start a brainstorm (collaborative discovery)
40
40
  - `/deep-thought-plan` — start planning (research and produce a plan document)
41
+ - `/deep-thought-architect` — turn brainstorm decisions into stories and architecture docs
42
+ - `/share` — publish an HTML file or static site directory through the portable `share-html` skill
43
+ - `/share-server-setup` — set up or adopt the local share server through the portable `share-server-setup` skill
41
44
  - `/marvin-work` — start executing a plan (with always-on safety guardrails)
42
45
 
46
+ Pi package installs also include a Pi-only guided workflow enhancer for supported Heart of Gold skills. For `brainstorm`, `plan`, and `architect`, when the assistant asks a high-confidence structured question, Pi can upgrade it into a custom interactive TUI and feed the answer back into the same workflow. Shared skills remain plain-text portable in every other harness.
47
+
48
+ For extension debugging, Pi also exposes `/deep-thought-guided-debug` to toggle notices explaining when a guided prompt was extracted, skipped, dismissed, or answered.
49
+
43
50
  The skills themselves enforce their own boundaries (read-only for brainstorm/plan, safe commands for work) via `allowed-tools` and prompt constraints — no manual mode switching needed.
44
51
 
45
52
  The work extension also provides always-on guardrails that protect `.env`, `.git/`, and `node_modules/` from edits, block `git add .` and destructive `rm`, and require confirmation for `git push` / `npm publish`.
@@ -90,15 +97,18 @@ The unglamorous work that compounds.
90
97
 
91
98
  Execute plans task by task with tests after every change. Quick-review code with an emphasis on simplicity — catch YAGNI violations, premature abstractions, and code that solves problems that don't exist yet. Document solutions so the next person doesn't waste time re-discovering what you already figured out.
92
99
 
93
- 6 skills · 2 agents · 3 knowledge files
100
+ 9 skills · 2 agents · 3 knowledge files
94
101
 
95
102
  ```
96
- /marvin:work # execute plans — implement, test, commit, ship
97
- /marvin:quick-review # fast opinionated quality pass (simplicity, tests, correctness)
98
- /marvin:compound # document solved problems for future reference
99
- /marvin:redteam # adversarial review — find weaknesses, expose with failing tests
100
- /marvin:scaffold # prepare project structure, configs, dependencies
101
- /marvin:test-writer # write failing tests from user stories
103
+ /marvin:work # execute plans — implement, test, commit, ship
104
+ /marvin:quick-review # fast opinionated quality pass (simplicity, tests, correctness)
105
+ /marvin:compound # document solved problems for future reference
106
+ /marvin:redteam # adversarial review — find weaknesses, expose with failing tests
107
+ /marvin:scaffold # prepare project structure, configs, dependencies
108
+ /marvin:test-writer # write failing tests from user stories
109
+ /marvin:copy-editor # two-layer copy editor (typography audit + LLM judgment)
110
+ /marvin:share-server-setup # set up local artifact sharing infrastructure
111
+ /marvin:share-html # publish HTML/static output to a browser URL
102
112
  ```
103
113
 
104
114
  ### [Guide](plugins/guide/) — The Hitchhiker's Guide
@@ -172,6 +182,10 @@ bunx @heart-of-gold/toolkit list deep-thought
172
182
 
173
183
  # Show supported targets
174
184
  bunx @heart-of-gold/toolkit targets
185
+
186
+ # Manage the local share server reference implementation
187
+ bunx @heart-of-gold/toolkit share-server health
188
+ bunx @heart-of-gold/toolkit share-server install
175
189
  ```
176
190
 
177
191
  ## Release Safety
@@ -192,10 +206,11 @@ npm run check:compat
192
206
 
193
207
  - **Codex/OpenCode/Pi**: Bun runtime (for `bunx`)
194
208
  - **Claude Code**: No additional requirements
195
- - **Guide plugin**: Python 3.10+, `feedparser`, `pyyaml`, `jq`, `curl`
209
+ - **Guide plugin**: Python 3.10+, `feedparser`, `pyyaml`, `jq`, `curl`, `zip`
196
210
  - **Babel Fish audio**: ElevenLabs API key
197
211
  - **Babel Fish image**: OpenRouter API key
198
212
  - **iMessage delivery**: macOS (optional)
213
+ - **Private tailnet viewer exposure**: Tailscale CLI (optional)
199
214
 
200
215
  ## Acknowledgments
201
216
 
@@ -0,0 +1,23 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+
3
+ export default function architectExtension(pi: ExtensionAPI) {
4
+ pi.registerCommand("deep-thought-architect", {
5
+ description: "Start architect — turn brainstorm decisions into stories and architecture docs",
6
+ handler: async (args, ctx) => {
7
+ const source =
8
+ args.trim() || (ctx.hasUI ? (await ctx.ui.editor("Architect input (feature or brainstorm path)", ""))?.trim() : undefined);
9
+ if (!source) {
10
+ ctx.ui.notify("Usage: /deep-thought-architect <feature or brainstorm path>", "info");
11
+ return;
12
+ }
13
+
14
+ const prompt = `/skill:architect ${source}`;
15
+ if (ctx.isIdle()) {
16
+ pi.sendUserMessage(prompt);
17
+ } else {
18
+ pi.sendUserMessage(prompt, { deliverAs: "followUp" });
19
+ ctx.ui.notify("Architect queued as follow-up", "info");
20
+ }
21
+ },
22
+ });
23
+ }
@@ -0,0 +1,147 @@
1
+ export const WORKFLOW_PATTERNS = [
2
+ { workflow: "brainstorm", pattern: /^\/(?:skill:brainstorm|brainstorm|deep-thought:brainstorm|deep-thought-brainstorm)\b/i },
3
+ { workflow: "plan", pattern: /^\/(?:skill:plan|plan|deep-thought:plan|deep-thought-plan)\b/i },
4
+ { workflow: "architect", pattern: /^\/(?:skill:architect|architect|deep-thought:architect|deep-thought-architect)\b/i },
5
+ ];
6
+
7
+ export const RESET_COMMAND_PATTERN =
8
+ /^\/(?!(?:skill:brainstorm|brainstorm|deep-thought:brainstorm|deep-thought-brainstorm|skill:plan|plan|deep-thought:plan|deep-thought-plan|skill:architect|architect|deep-thought:architect|deep-thought-architect)\b)\S+/i;
9
+
10
+ export function normalizeInline(text) {
11
+ return String(text)
12
+ .replace(/\*\*(.*?)\*\*/g, "$1")
13
+ .replace(/__(.*?)__/g, "$1")
14
+ .replace(/`([^`]+)`/g, "$1")
15
+ .replace(/\s+/g, " ")
16
+ .trim();
17
+ }
18
+
19
+ export function detectWorkflow(text) {
20
+ const trimmed = String(text).trim();
21
+ for (const { workflow, pattern } of WORKFLOW_PATTERNS) {
22
+ if (pattern.test(trimmed)) return workflow;
23
+ }
24
+ return undefined;
25
+ }
26
+
27
+ export function parseExtractionEnvelope(text) {
28
+ try {
29
+ let json = String(text).trim();
30
+ const codeBlock = json.match(/```(?:json)?\s*([\s\S]*?)```/i);
31
+ if (codeBlock) json = codeBlock[1].trim();
32
+ const parsed = JSON.parse(json);
33
+ if (!parsed || typeof parsed !== "object" || typeof parsed.kind !== "string") return null;
34
+ if (parsed.kind === "none") return parsed;
35
+ if (parsed.kind !== "single_choice" && parsed.kind !== "text") return null;
36
+ if (typeof parsed.question !== "string" || parsed.question.trim() === "") return null;
37
+ if (parsed.kind === "single_choice") {
38
+ if (!Array.isArray(parsed.options) || parsed.options.length < 2 || parsed.options.length > 5) return null;
39
+ }
40
+ return parsed;
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+
46
+ function splitQuestionAndContext(lines, optionStartIndex) {
47
+ const prior = lines.slice(0, optionStartIndex).map((line) => normalizeInline(line)).filter(Boolean);
48
+ if (prior.length === 0) return { question: "Choose an option" };
49
+
50
+ let question = prior[prior.length - 1];
51
+ let contextLines = prior.slice(0, -1);
52
+
53
+ for (let i = prior.length - 1; i >= 0; i--) {
54
+ const line = prior[i];
55
+ if (line.endsWith("?") || line.endsWith(":")) {
56
+ question = line.replace(/:$/, "");
57
+ contextLines = prior.slice(Math.max(0, i - 2), i);
58
+ break;
59
+ }
60
+ }
61
+
62
+ return { question, context: contextLines.join(" ").trim() || undefined };
63
+ }
64
+
65
+ export function heuristicExtractOptions(text) {
66
+ const lines = String(text).split(/\r?\n/);
67
+ const options = [];
68
+ let optionStartIndex = -1;
69
+
70
+ for (let i = 0; i < lines.length; i++) {
71
+ const line = lines[i].trim();
72
+ const match = line.match(/^(\d+\.|[-*])\s+(.*)$/);
73
+ if (!match) {
74
+ if (options.length > 0) break;
75
+ continue;
76
+ }
77
+ if (optionStartIndex === -1) optionStartIndex = i;
78
+ const body = normalizeInline(match[2]);
79
+ const parts = body.split(/\s+[—-]\s+/);
80
+ const label = parts[0]?.trim();
81
+ const description = parts.slice(1).join(" — ").trim() || undefined;
82
+ if (!label) break;
83
+ options.push({ label, description });
84
+ }
85
+
86
+ if (optionStartIndex === -1 || options.length < 2 || options.length > 5) return null;
87
+ const { question, context } = splitQuestionAndContext(lines, optionStartIndex);
88
+ return { kind: "single_choice", question, context, options, confidence: "medium" };
89
+ }
90
+
91
+ export function heuristicExtractText(text) {
92
+ const lines = String(text)
93
+ .split(/\r?\n/)
94
+ .map((line) => normalizeInline(line))
95
+ .filter(Boolean);
96
+
97
+ for (let i = lines.length - 1; i >= 0; i--) {
98
+ const line = lines[i];
99
+ if (!line.endsWith("?")) continue;
100
+ if (/^(if|when|otherwise|for example)\b/i.test(line)) continue;
101
+ return {
102
+ kind: "text",
103
+ question: line,
104
+ context: lines.slice(Math.max(0, i - 2), i).join(" ").trim() || undefined,
105
+ confidence: "low",
106
+ };
107
+ }
108
+
109
+ return null;
110
+ }
111
+
112
+ export function heuristicExtractPrompt(text) {
113
+ return heuristicExtractOptions(text) ?? heuristicExtractText(text) ?? { kind: "none", reason: "no clear prompt", confidence: "low" };
114
+ }
115
+
116
+ export function coerceExtractedPrompt(workflow, extracted) {
117
+ if (!extracted || extracted.kind === "none") return null;
118
+ if (extracted.confidence === "low") return null;
119
+
120
+ if (extracted.kind === "single_choice") {
121
+ const options = (extracted.options ?? [])
122
+ .filter((option) => option && typeof option.label === "string" && option.label.trim() !== "")
123
+ .map((option) => ({
124
+ label: normalizeInline(option.label),
125
+ description: option.description ? normalizeInline(option.description) : undefined,
126
+ }));
127
+ if (options.length < 2 || options.length > 5) return null;
128
+ return {
129
+ kind: "single_choice",
130
+ workflow,
131
+ question: normalizeInline(extracted.question),
132
+ context: extracted.context ? normalizeInline(extracted.context) : undefined,
133
+ options,
134
+ answerInstruction: extracted.answerInstruction ? normalizeInline(extracted.answerInstruction) : undefined,
135
+ confidence: extracted.confidence,
136
+ };
137
+ }
138
+
139
+ return {
140
+ kind: "text",
141
+ workflow,
142
+ question: normalizeInline(extracted.question),
143
+ context: extracted.context ? normalizeInline(extracted.context) : undefined,
144
+ answerInstruction: extracted.answerInstruction ? normalizeInline(extracted.answerInstruction) : undefined,
145
+ confidence: extracted.confidence,
146
+ };
147
+ }