@heart-of-gold/toolkit 0.1.35 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +7 -4
- package/package.json +1 -1
- package/plugins/babel-fish/.claude-plugin/plugin.json +1 -1
- package/plugins/babel-fish/skills/visualize/SKILL.md +190 -20
- package/plugins/babel-fish/skills/visualize/scripts/agent-artifact-template.html +169 -0
- package/plugins/babel-fish/skills/visualize/scripts/new-authored-artifact.js +20 -0
- package/plugins/babel-fish/skills/visualize/scripts/new-authored-artifact.sh +14 -0
- package/plugins/babel-fish/skills/visualize/scripts/publish-authored-html.js +87 -0
- package/plugins/babel-fish/skills/visualize/scripts/publish-authored-html.sh +93 -0
- package/plugins/deep-thought/.claude-plugin/plugin.json +1 -1
- package/plugins/marvin/.claude-plugin/plugin.json +1 -1
- package/src/commands/install.ts +17 -1
|
@@ -15,19 +15,19 @@
|
|
|
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.2.
|
|
18
|
+
"version": "0.2.7"
|
|
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.3.
|
|
24
|
+
"version": "0.3.7"
|
|
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.2.
|
|
30
|
+
"version": "0.2.5"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"name": "quellis",
|
package/README.md
CHANGED
|
@@ -26,13 +26,16 @@ bunx @heart-of-gold/toolkit install --to opencode
|
|
|
26
26
|
|
|
27
27
|
### Pi Coding Agent
|
|
28
28
|
```bash
|
|
29
|
-
#
|
|
30
|
-
bunx @heart-of-gold/toolkit install --to pi
|
|
31
|
-
|
|
32
|
-
# Or install the package directly in Pi to get skills + pi-native extensions
|
|
29
|
+
# Option A: install the package directly in Pi to get skills + pi-native extensions
|
|
33
30
|
pi install npm:@heart-of-gold/toolkit
|
|
31
|
+
|
|
32
|
+
# Option B: install shared skills only into Pi's native skill directory
|
|
33
|
+
bunx @heart-of-gold/toolkit install --to pi
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
**Important:** choose one Pi install path or the other.
|
|
37
|
+
Do **not** use both the Pi package install and `install --to pi` at the same time, or Pi will report duplicate skill collisions on reload.
|
|
38
|
+
|
|
36
39
|
Pi also discovers skills from the shared `~/.agents/skills/` location, so installs done with the OpenCode target are usable from Pi too.
|
|
37
40
|
|
|
38
41
|
When installed as a Pi package, Heart of Gold exposes Pi-native extension commands for the flagship workflows:
|
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ Translating structured text into spatial understanding. The job is not to "turn
|
|
|
21
21
|
Create one clear, polished, shareable visual artifact that:
|
|
22
22
|
- matches the user's actual need
|
|
23
23
|
- feels intentionally designed, not markdown restyled in boxes
|
|
24
|
+
- is authored deliberately by the coding agent whenever possible
|
|
24
25
|
- summarizes before detailing
|
|
25
26
|
- uses browser HTML as the primary medium for substantial artifacts
|
|
26
27
|
- falls back to terminal rendering only when that is the better fit
|
|
@@ -34,12 +35,16 @@ Create one clear, polished, shareable visual artifact that:
|
|
|
34
35
|
|
|
35
36
|
Do **not** mirror the source document structure one-to-one unless the user explicitly wants a document view.
|
|
36
37
|
|
|
38
|
+
The coding agent should be the **author** of the visual artifact.
|
|
39
|
+
The renderer is a **finisher/fallback**, not the brain.
|
|
40
|
+
|
|
37
41
|
Instead:
|
|
38
42
|
1. understand the source
|
|
39
43
|
2. decide what the artifact is trying to communicate
|
|
40
44
|
3. choose the visual form that best serves that goal
|
|
41
|
-
4.
|
|
42
|
-
5.
|
|
45
|
+
4. author the HTML artifact directly when practical
|
|
46
|
+
5. use toolkit renderers only as helpers or fallback paths
|
|
47
|
+
6. keep raw/source detail secondary or collapsible when possible
|
|
43
48
|
|
|
44
49
|
HTML should feel like:
|
|
45
50
|
- a dashboard
|
|
@@ -115,6 +120,26 @@ Apply these defaults unless the user asks for something else:
|
|
|
115
120
|
See also:
|
|
116
121
|
- `docs/architecture/visualize-design-rules.md`
|
|
117
122
|
|
|
123
|
+
## Writing Tone
|
|
124
|
+
|
|
125
|
+
Write artifact copy like a strong product/design-systems editor:
|
|
126
|
+
- concise
|
|
127
|
+
- confident
|
|
128
|
+
- specific
|
|
129
|
+
- implementation-aware
|
|
130
|
+
- high signal-to-noise
|
|
131
|
+
|
|
132
|
+
Prefer lines like:
|
|
133
|
+
- `One code change, bounded migration risk`
|
|
134
|
+
- `Three priority tiers, one direction`
|
|
135
|
+
- `Deferred — tracked, not scheduled`
|
|
136
|
+
|
|
137
|
+
Avoid:
|
|
138
|
+
- fluffy marketing copy
|
|
139
|
+
- generic AI hype
|
|
140
|
+
- long throat-clearing intros
|
|
141
|
+
- repeating the source document verbatim
|
|
142
|
+
|
|
118
143
|
## Rules: Do
|
|
119
144
|
|
|
120
145
|
- Decide the communication goal before choosing the renderer.
|
|
@@ -125,6 +150,7 @@ See also:
|
|
|
125
150
|
- Use `roadmap` or richer execution-oriented views for plans when that improves understanding.
|
|
126
151
|
- Use `architecture` views for system/design-heavy documents.
|
|
127
152
|
- Keep raw source detail available, but secondary.
|
|
153
|
+
- Make section labels do real editorial work: `Scope at a glance`, `Why this shape`, `What could go wrong`, `Deferred — tracked, not scheduled`.
|
|
128
154
|
- Briefly explain why you chose the visualization mode when sharing the result.
|
|
129
155
|
|
|
130
156
|
## Rules: Don't
|
|
@@ -136,6 +162,8 @@ See also:
|
|
|
136
162
|
- Do not use flashy gradients, glass, shadows, or color noise unless they clearly improve hierarchy.
|
|
137
163
|
- Do not silently guess when the visualization choice is materially ambiguous.
|
|
138
164
|
- Do not create multiple competing artifacts unless the user explicitly asks for comparison.
|
|
165
|
+
- Do not preserve source heading order if a clearer narrative order exists.
|
|
166
|
+
- Do not expose every extracted detail at the same visual weight.
|
|
139
167
|
|
|
140
168
|
## Expected Behavior
|
|
141
169
|
|
|
@@ -150,8 +178,9 @@ When invoked, behave like a visual editor, not a format converter.
|
|
|
150
178
|
- UI/product visualization
|
|
151
179
|
3. Choose the best artifact family.
|
|
152
180
|
4. If uncertain, ask one concise question.
|
|
153
|
-
5.
|
|
154
|
-
6.
|
|
181
|
+
5. Prefer **agent-authored HTML** when browser rendering will help and the artifact needs real design judgment.
|
|
182
|
+
6. Use toolkit renderers as a fallback when a quick structured artifact is sufficient.
|
|
183
|
+
7. Fall back to terminal rendering when browser/share is unavailable or explicitly not wanted.
|
|
155
184
|
|
|
156
185
|
If the user says "you decide," choose the clearest non-gimmicky artifact, not the fanciest one.
|
|
157
186
|
|
|
@@ -189,12 +218,15 @@ If the user does not care or says "you decide," choose the safest useful mode:
|
|
|
189
218
|
- use `architecture` for clearly system-design-heavy docs
|
|
190
219
|
- use `mindmap` only when the artifact is genuinely concise and branchy
|
|
191
220
|
|
|
192
|
-
## Renderers
|
|
221
|
+
## Authoring & Renderers
|
|
193
222
|
|
|
194
|
-
|
|
195
|
-
-
|
|
223
|
+
Preferred implementation order:
|
|
224
|
+
- **Agent-authored HTML** — primary path for high-quality shareable artifacts
|
|
225
|
+
- `scripts/smart-render.js` — fallback renderer when the agent wants a quick scaffold or safe structured default
|
|
196
226
|
- `scripts/render-mindmap/index.js` — specialized mind-map renderer for branchy content
|
|
197
227
|
|
|
228
|
+
The key rule: if the artifact needs real design judgment, the coding agent should author the HTML directly instead of delegating the whole job to a parser.
|
|
229
|
+
|
|
198
230
|
**Locations:**
|
|
199
231
|
- `scripts/smart-render.js`
|
|
200
232
|
- `scripts/render-mindmap/index.js`
|
|
@@ -220,6 +252,31 @@ fi
|
|
|
220
252
|
|
|
221
253
|
## Usage
|
|
222
254
|
|
|
255
|
+
### Preferred: agent-authored HTML
|
|
256
|
+
|
|
257
|
+
When quality matters more than speed, start from the shared authored-artifact template, write the HTML directly, then publish it.
|
|
258
|
+
|
|
259
|
+
**Cross-platform preferred path:** use the Node helpers first. They work better across macOS, Linux, Windows, Codex, Claude Code, and Pi than shell-specific one-liners.
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# 1. Print a fresh temp HTML path based on the shared template
|
|
263
|
+
node /absolute/path/to/new-authored-artifact.js
|
|
264
|
+
|
|
265
|
+
# 2. After editing the file, publish it
|
|
266
|
+
node /absolute/path/to/publish-authored-html.js --url-only /tmp/path/from-step-1/artifact.html
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Shell fallback:** if Node helper usage is awkward in a specific harness, the `.sh` helpers are still available.
|
|
270
|
+
|
|
271
|
+
Template and helper files:
|
|
272
|
+
- `scripts/agent-artifact-template.html`
|
|
273
|
+
- `scripts/new-authored-artifact.js`
|
|
274
|
+
- `scripts/publish-authored-html.js`
|
|
275
|
+
- `scripts/new-authored-artifact.sh`
|
|
276
|
+
- `scripts/publish-authored-html.sh`
|
|
277
|
+
|
|
278
|
+
### Fallback: toolkit renderer
|
|
279
|
+
|
|
223
280
|
```bash
|
|
224
281
|
# Generate a safe default HTML visualization for a markdown file
|
|
225
282
|
node "$SCRIPT" path/to/file.md --out /tmp/view.html
|
|
@@ -236,7 +293,29 @@ node "$(dirname "$SCRIPT")/render-mindmap/index.js" --html /tmp/map.html path/to
|
|
|
236
293
|
|
|
237
294
|
## HTML Share Flow
|
|
238
295
|
|
|
239
|
-
|
|
296
|
+
### Preferred share flow: publish agent-authored HTML
|
|
297
|
+
|
|
298
|
+
Use this when the artifact needs stronger design judgment than the fallback renderer can provide.
|
|
299
|
+
|
|
300
|
+
1. Create the scaffold with a standalone cross-platform command:
|
|
301
|
+
```bash
|
|
302
|
+
node /absolute/path/to/new-authored-artifact.js
|
|
303
|
+
```
|
|
304
|
+
2. Read the printed temp path from stdout.
|
|
305
|
+
3. Author the HTML artifact directly into that file.
|
|
306
|
+
4. Publish it with a standalone cross-platform command:
|
|
307
|
+
```bash
|
|
308
|
+
node /absolute/path/to/publish-authored-html.js --url-only /tmp/your-artifact.html
|
|
309
|
+
```
|
|
310
|
+
5. Read the returned URL from stdout.
|
|
311
|
+
6. Return that URL to the user as the primary result.
|
|
312
|
+
7. Briefly explain what was published and why this visual form was chosen.
|
|
313
|
+
|
|
314
|
+
Shell helpers remain available as a fallback if a harness prefers `bash`.
|
|
315
|
+
|
|
316
|
+
### Fallback share flow: render then publish
|
|
317
|
+
|
|
318
|
+
Use the helper script when the user wants a browser URL and the fallback renderer is sufficient:
|
|
240
319
|
|
|
241
320
|
```bash
|
|
242
321
|
bash scripts/render-and-share.sh path/to/file.md
|
|
@@ -249,18 +328,6 @@ This script:
|
|
|
249
328
|
4. publishes the artifact to the configured local share server
|
|
250
329
|
5. prints the publish result so you can return the URL
|
|
251
330
|
|
|
252
|
-
### Recommended share flow
|
|
253
|
-
|
|
254
|
-
1. Verify or assume the input markdown is ready.
|
|
255
|
-
2. Choose the mode from context.
|
|
256
|
-
3. Run:
|
|
257
|
-
```bash
|
|
258
|
-
bash scripts/render-and-share.sh --mode <chosen-mode> --url-only [file]
|
|
259
|
-
```
|
|
260
|
-
4. Read the returned URL from stdout.
|
|
261
|
-
5. Return that URL to the user as the primary result.
|
|
262
|
-
6. Briefly explain what was published and why this mode was chosen.
|
|
263
|
-
|
|
264
331
|
If publishing fails because the share server is not configured, say so clearly and fall back to terminal rendering unless the user wants to stop and run `share-server-setup` first.
|
|
265
332
|
|
|
266
333
|
## Terminal Rendering
|
|
@@ -289,6 +356,34 @@ Many harness bash panels truncate long output and wrap wide content, breaking al
|
|
|
289
356
|
|
|
290
357
|
The default mode is vertical layout — boxes on main branches, compact leaves, about 40 chars wide.
|
|
291
358
|
|
|
359
|
+
## Agent-Authored HTML Workflow
|
|
360
|
+
|
|
361
|
+
When authoring HTML directly, follow this sequence:
|
|
362
|
+
|
|
363
|
+
1. Read the source and decide the artifact family.
|
|
364
|
+
2. Decide the audience and the first question the page should answer.
|
|
365
|
+
3. Create the scaffold with `new-authored-artifact.js` or `new-authored-artifact.sh`.
|
|
366
|
+
4. Draft the page in three layers:
|
|
367
|
+
- **summary layer** — what matters first
|
|
368
|
+
- **decision / execution layer** — the main story
|
|
369
|
+
- **source layer** — appendix, evidence, or raw detail
|
|
370
|
+
5. Replace the template content with a real designed artifact.
|
|
371
|
+
6. Keep source detail secondary.
|
|
372
|
+
7. Publish with `publish-authored-html.js` or `publish-authored-html.sh`.
|
|
373
|
+
|
|
374
|
+
Harness note:
|
|
375
|
+
- prefer separate commands over complex one-liners
|
|
376
|
+
- prefer the Node helpers for cross-platform behavior
|
|
377
|
+
- avoid assuming `mktemp /tmp/name-XXXXXX.html` works on every shell; use the provided helper instead
|
|
378
|
+
- if a harness only supports shell comfortably, use the `.sh` helpers as fallback
|
|
379
|
+
|
|
380
|
+
For plans specifically:
|
|
381
|
+
- do not dump the full task prose into the primary lanes
|
|
382
|
+
- summarize workstreams into short cards or task tiles
|
|
383
|
+
- show dependencies, risks, and acceptance separately
|
|
384
|
+
- keep raw markdown only in an appendix or disclosure block
|
|
385
|
+
- compress long task descriptions into one-sentence operational summaries first
|
|
386
|
+
|
|
292
387
|
## Required Output Structure
|
|
293
388
|
|
|
294
389
|
For substantial HTML artifacts, prefer this structure:
|
|
@@ -319,6 +414,53 @@ For substantial HTML artifacts, prefer this structure:
|
|
|
319
414
|
- what happens next
|
|
320
415
|
- supporting source detail below
|
|
321
416
|
|
|
417
|
+
## Expected Behavior by Artifact Family
|
|
418
|
+
|
|
419
|
+
### Plan / roadmap artifacts
|
|
420
|
+
Must usually include:
|
|
421
|
+
- a top-line mission
|
|
422
|
+
- scope or execution stats
|
|
423
|
+
- grouped workstreams or phases
|
|
424
|
+
- key decisions / rationale
|
|
425
|
+
- explicit risks / acceptance posture
|
|
426
|
+
- deferred or out-of-scope work if relevant
|
|
427
|
+
|
|
428
|
+
### Architecture artifacts
|
|
429
|
+
Must usually include:
|
|
430
|
+
- system framing
|
|
431
|
+
- major components / boundaries
|
|
432
|
+
- integration or dependency context
|
|
433
|
+
- key tradeoffs / decisions
|
|
434
|
+
- assumptions / risks
|
|
435
|
+
|
|
436
|
+
### Explainers
|
|
437
|
+
Must usually include:
|
|
438
|
+
- what this is
|
|
439
|
+
- why it matters
|
|
440
|
+
- the recommendation or conclusion
|
|
441
|
+
- supporting evidence
|
|
442
|
+
- what happens next
|
|
443
|
+
|
|
444
|
+
## Recommended Authoring Moves
|
|
445
|
+
|
|
446
|
+
When the artifact still feels too markdown-like, do one or more of these:
|
|
447
|
+
- replace raw section names with editorial section labels
|
|
448
|
+
- compress paragraphs into 1–3 sentence summary cards
|
|
449
|
+
- convert repeated prose into chips, bullets, metrics, or compact lists
|
|
450
|
+
- surface one key takeaway per section before the detail
|
|
451
|
+
- split `what / why / risk / next` into separate visual units
|
|
452
|
+
- move citations, raw notes, and source text into a secondary appendix
|
|
453
|
+
|
|
454
|
+
## Guideline Authoring Workflow
|
|
455
|
+
|
|
456
|
+
1. Restate the artifact purpose in one sentence.
|
|
457
|
+
2. Decide the audience and primary question.
|
|
458
|
+
3. Choose the artifact family and page shape.
|
|
459
|
+
4. Extract only what is needed for the summary layer.
|
|
460
|
+
5. Build the main body around grouped visual units, not source sections.
|
|
461
|
+
6. Add source appendix or evidence only after the main page works.
|
|
462
|
+
7. Run the quality gates before publishing.
|
|
463
|
+
|
|
322
464
|
## Quality Gates
|
|
323
465
|
|
|
324
466
|
Before returning a shared HTML result, check mentally:
|
|
@@ -330,9 +472,37 @@ Before returning a shared HTML result, check mentally:
|
|
|
330
472
|
- Is the chosen mode actually appropriate for the content?
|
|
331
473
|
- If this is a plan, does it foreground execution rather than document order?
|
|
332
474
|
- If this is a brainstorm, is it actually branch-shaped enough for a mind map?
|
|
475
|
+
- Do the section titles help scanning?
|
|
476
|
+
- Is secondary detail actually secondary?
|
|
333
477
|
|
|
334
478
|
If the answer to several of these is no, reconsider the mode or ask the user.
|
|
335
479
|
|
|
480
|
+
## Pattern Examples
|
|
481
|
+
|
|
482
|
+
### Good plan framing
|
|
483
|
+
- `Scope at a glance`
|
|
484
|
+
- `Three priority tiers, one direction`
|
|
485
|
+
- `What could go wrong`
|
|
486
|
+
- `Deferred — tracked, not scheduled`
|
|
487
|
+
|
|
488
|
+
### Good risk cards
|
|
489
|
+
- short risk title
|
|
490
|
+
- severity or posture badge
|
|
491
|
+
- one-sentence mitigation
|
|
492
|
+
- accepted vs mitigated distinction when relevant
|
|
493
|
+
|
|
494
|
+
### Good summary stats
|
|
495
|
+
- workstreams
|
|
496
|
+
- tasks
|
|
497
|
+
- code edits
|
|
498
|
+
- new files
|
|
499
|
+
- doctrine docs touched
|
|
500
|
+
|
|
501
|
+
### Good appendix behavior
|
|
502
|
+
- source plan path
|
|
503
|
+
- cited references
|
|
504
|
+
- raw plan or evidence hidden behind disclosure
|
|
505
|
+
|
|
336
506
|
## Input Formats
|
|
337
507
|
|
|
338
508
|
### Markdown (primary)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Heart of Gold Visual Artifact</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #09111f;
|
|
10
|
+
--bg-2: #0f1a31;
|
|
11
|
+
--panel: rgba(255,255,255,0.06);
|
|
12
|
+
--panel-soft: rgba(255,255,255,0.04);
|
|
13
|
+
--text: #eef2ff;
|
|
14
|
+
--muted: #b8c0d9;
|
|
15
|
+
--muted-2: #91a1c2;
|
|
16
|
+
--border: rgba(255,255,255,0.11);
|
|
17
|
+
--accent: #7c9cff;
|
|
18
|
+
--accent-2: #80e0d0;
|
|
19
|
+
--success: #86efac;
|
|
20
|
+
--warn: #fbbf24;
|
|
21
|
+
--danger: #fca5a5;
|
|
22
|
+
--shadow: 0 24px 80px rgba(0,0,0,0.34);
|
|
23
|
+
--radius-xl: 28px;
|
|
24
|
+
--radius-lg: 20px;
|
|
25
|
+
--radius-md: 16px;
|
|
26
|
+
}
|
|
27
|
+
* { box-sizing: border-box; }
|
|
28
|
+
html, body { margin: 0; padding: 0; }
|
|
29
|
+
html { color-scheme: dark; }
|
|
30
|
+
body {
|
|
31
|
+
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
32
|
+
line-height: 1.55;
|
|
33
|
+
color: var(--text);
|
|
34
|
+
background:
|
|
35
|
+
radial-gradient(circle at top left, rgba(124,156,255,0.18), transparent 32%),
|
|
36
|
+
radial-gradient(circle at top right, rgba(128,224,208,0.12), transparent 24%),
|
|
37
|
+
linear-gradient(180deg, var(--bg-2) 0%, var(--bg) 100%);
|
|
38
|
+
}
|
|
39
|
+
main { max-width: 1480px; margin: 0 auto; padding: 36px 22px 84px; }
|
|
40
|
+
.hero, .section, .rail-card, .card, .stat, .chip, .callout {
|
|
41
|
+
border: 1px solid var(--border);
|
|
42
|
+
box-shadow: var(--shadow);
|
|
43
|
+
backdrop-filter: blur(14px);
|
|
44
|
+
}
|
|
45
|
+
.hero, .section, .rail-card { background: var(--panel); }
|
|
46
|
+
.hero {
|
|
47
|
+
padding: 28px;
|
|
48
|
+
border-radius: 32px;
|
|
49
|
+
margin-bottom: 24px;
|
|
50
|
+
display: grid;
|
|
51
|
+
gap: 16px;
|
|
52
|
+
}
|
|
53
|
+
.eyebrow {
|
|
54
|
+
color: var(--accent-2);
|
|
55
|
+
text-transform: uppercase;
|
|
56
|
+
letter-spacing: 0.16em;
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
font-weight: 700;
|
|
59
|
+
}
|
|
60
|
+
h1 { margin: 0; font-size: clamp(34px, 4vw, 62px); line-height: 1.02; text-wrap: balance; }
|
|
61
|
+
h2 { margin: 0 0 12px; font-size: clamp(22px, 2vw, 32px); text-wrap: balance; }
|
|
62
|
+
h3 { margin: 0 0 10px; font-size: 18px; }
|
|
63
|
+
p { margin: 0; color: var(--muted); }
|
|
64
|
+
.hero p { max-width: 78ch; font-size: 17px; }
|
|
65
|
+
.page { display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 320px); gap: 24px; align-items: start; }
|
|
66
|
+
.rail { position: sticky; top: 16px; display: grid; gap: 16px; }
|
|
67
|
+
.rail-card, .section { padding: 22px; border-radius: var(--radius-xl); }
|
|
68
|
+
.section { margin-bottom: 20px; }
|
|
69
|
+
.grid-2, .grid-3, .grid-4, .lane-grid { display: grid; gap: 16px; }
|
|
70
|
+
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
71
|
+
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
72
|
+
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
73
|
+
.lane-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
|
|
74
|
+
.card, .stat, .lane, .callout {
|
|
75
|
+
padding: 18px;
|
|
76
|
+
border-radius: var(--radius-md);
|
|
77
|
+
background: var(--panel-soft);
|
|
78
|
+
}
|
|
79
|
+
.label {
|
|
80
|
+
color: var(--accent-2);
|
|
81
|
+
text-transform: uppercase;
|
|
82
|
+
letter-spacing: 0.11em;
|
|
83
|
+
font-size: 12px;
|
|
84
|
+
margin-bottom: 8px;
|
|
85
|
+
}
|
|
86
|
+
.stat .value { font-size: 28px; font-weight: 700; color: var(--text); margin-top: 6px; }
|
|
87
|
+
.stat .hint { color: var(--muted-2); font-size: 13px; margin-top: 6px; }
|
|
88
|
+
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
|
|
89
|
+
.chip {
|
|
90
|
+
display: inline-flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: 999px;
|
|
91
|
+
background: rgba(255,255,255,0.05); color: var(--muted-2); font-size: 12px;
|
|
92
|
+
}
|
|
93
|
+
.chip.good { color: #c7ffd7; }
|
|
94
|
+
.chip.warn { color: #ffd88d; }
|
|
95
|
+
.chip.danger { color: #ffd1d1; }
|
|
96
|
+
details { margin-top: 12px; }
|
|
97
|
+
summary { cursor: pointer; font-weight: 600; }
|
|
98
|
+
.raw {
|
|
99
|
+
margin-top: 12px; padding: 14px; border-radius: 14px; border: 1px solid var(--border);
|
|
100
|
+
background: rgba(0,0,0,0.22); color: #d8e1fb; white-space: pre-wrap;
|
|
101
|
+
font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
102
|
+
}
|
|
103
|
+
a { color: #dce6ff; }
|
|
104
|
+
ul { margin: 0; padding-left: 18px; color: var(--muted); }
|
|
105
|
+
@media (max-width: 1080px) {
|
|
106
|
+
.page { grid-template-columns: 1fr; }
|
|
107
|
+
.rail { position: static; }
|
|
108
|
+
.grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
109
|
+
}
|
|
110
|
+
@media (max-width: 720px) {
|
|
111
|
+
main { padding: 20px 14px 60px; }
|
|
112
|
+
.hero, .section, .rail-card { padding: 18px; }
|
|
113
|
+
.grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
116
|
+
</head>
|
|
117
|
+
<body>
|
|
118
|
+
<main>
|
|
119
|
+
<section class="hero">
|
|
120
|
+
<div class="eyebrow">Artifact Family</div>
|
|
121
|
+
<h1>Title</h1>
|
|
122
|
+
<p>One-line framing that explains what this artifact is, why it matters, and how to read it.</p>
|
|
123
|
+
<div class="chip-row">
|
|
124
|
+
<span class="chip">Mode</span>
|
|
125
|
+
<span class="chip">Audience</span>
|
|
126
|
+
<span class="chip">Purpose</span>
|
|
127
|
+
</div>
|
|
128
|
+
</section>
|
|
129
|
+
|
|
130
|
+
<div class="page">
|
|
131
|
+
<section>
|
|
132
|
+
<section class="section">
|
|
133
|
+
<div class="label">Summary</div>
|
|
134
|
+
<h2>Start With the Story</h2>
|
|
135
|
+
<div class="grid-4">
|
|
136
|
+
<div class="stat"><div class="label">Stat</div><div class="value">4</div><div class="hint">What this number means</div></div>
|
|
137
|
+
<div class="stat"><div class="label">Stat</div><div class="value">18</div><div class="hint">What this number means</div></div>
|
|
138
|
+
<div class="stat"><div class="label">Stat</div><div class="value">11</div><div class="hint">What this number means</div></div>
|
|
139
|
+
<div class="stat"><div class="label">Stat</div><div class="value">2</div><div class="hint">What this number means</div></div>
|
|
140
|
+
</div>
|
|
141
|
+
</section>
|
|
142
|
+
|
|
143
|
+
<section class="section">
|
|
144
|
+
<div class="label">Main Body</div>
|
|
145
|
+
<h2>Transform the Source</h2>
|
|
146
|
+
<div class="grid-2">
|
|
147
|
+
<div class="card">
|
|
148
|
+
<div class="label">Use cards</div>
|
|
149
|
+
<p>Summaries, priorities, risks, decisions, and recommendations should be grouped into visual units rather than dumped as prose.</p>
|
|
150
|
+
</div>
|
|
151
|
+
<div class="card">
|
|
152
|
+
<div class="label">Use disclosure</div>
|
|
153
|
+
<p>Keep raw source detail secondary. Put it behind details/summary or a source appendix.</p>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</section>
|
|
157
|
+
</section>
|
|
158
|
+
|
|
159
|
+
<aside class="rail">
|
|
160
|
+
<section class="rail-card">
|
|
161
|
+
<div class="label">Rail</div>
|
|
162
|
+
<h3>Keep It Focused</h3>
|
|
163
|
+
<p>Use the right rail for compact metadata, jump links, or decision context — not for a massive table of contents.</p>
|
|
164
|
+
</section>
|
|
165
|
+
</aside>
|
|
166
|
+
</div>
|
|
167
|
+
</main>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { copyFileSync, mkdirSync, mkdtempSync } from 'node:fs';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { tmpdir } from 'node:os';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const templatePath = join(__dirname, 'agent-artifact-template.html');
|
|
10
|
+
const providedPath = process.argv[2] ? resolve(process.argv[2]) : null;
|
|
11
|
+
|
|
12
|
+
const outPath = (() => {
|
|
13
|
+
if (providedPath) return providedPath;
|
|
14
|
+
const tempDir = mkdtempSync(join(tmpdir(), 'hog-visualize-artifact-'));
|
|
15
|
+
return join(tempDir, 'artifact.html');
|
|
16
|
+
})();
|
|
17
|
+
|
|
18
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
19
|
+
copyFileSync(templatePath, outPath);
|
|
20
|
+
process.stdout.write(`${outPath}\n`);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
TEMPLATE="$SCRIPT_DIR/agent-artifact-template.html"
|
|
6
|
+
OUT_PATH="${1:-}"
|
|
7
|
+
|
|
8
|
+
if [[ -z "$OUT_PATH" ]]; then
|
|
9
|
+
TEMP_BASE="$(mktemp /tmp/hog-visualize-artifact-XXXXXX)"
|
|
10
|
+
OUT_PATH="${TEMP_BASE}.html"
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
cp "$TEMPLATE" "$OUT_PATH"
|
|
14
|
+
printf '%s\n' "$OUT_PATH"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { basename, resolve } from 'node:path';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
|
|
7
|
+
function fail(code, message, status = 1) {
|
|
8
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: { code, message } })}\n`);
|
|
9
|
+
process.exit(status);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function parseArgs(argv) {
|
|
13
|
+
const opts = {
|
|
14
|
+
htmlPath: null,
|
|
15
|
+
configPath: resolve(homedir(), '.agent-share', 'config.json'),
|
|
16
|
+
slug: '',
|
|
17
|
+
title: '',
|
|
18
|
+
alias: '',
|
|
19
|
+
urlOnly: false,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23
|
+
const arg = argv[i];
|
|
24
|
+
if (arg === '--config' && i + 1 < argv.length) opts.configPath = resolve(argv[++i]);
|
|
25
|
+
else if (arg === '--slug' && i + 1 < argv.length) opts.slug = argv[++i];
|
|
26
|
+
else if (arg === '--title' && i + 1 < argv.length) opts.title = argv[++i];
|
|
27
|
+
else if (arg === '--alias' && i + 1 < argv.length) opts.alias = argv[++i];
|
|
28
|
+
else if (arg === '--url-only') opts.urlOnly = true;
|
|
29
|
+
else if (arg === '--help') {
|
|
30
|
+
process.stdout.write('Usage: publish-authored-html.js <html-file> [--config PATH] [--slug STEM] [--title TITLE] [--alias ALIAS] [--url-only]\n');
|
|
31
|
+
process.exit(0);
|
|
32
|
+
} else if (!arg.startsWith('-') && !opts.htmlPath) {
|
|
33
|
+
opts.htmlPath = resolve(arg);
|
|
34
|
+
} else {
|
|
35
|
+
fail('INVALID_ARGS', `Unknown or misplaced argument: ${arg}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return opts;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function main() {
|
|
43
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
44
|
+
|
|
45
|
+
if (!opts.htmlPath) fail('MISSING_PATH', 'HTML file path is required.');
|
|
46
|
+
if (!existsSync(opts.configPath)) fail('MISSING_CONFIG', 'Share server config not found. Run share-server-setup first.');
|
|
47
|
+
if (!existsSync(opts.htmlPath)) fail('MISSING_PATH', `HTML file does not exist: ${opts.htmlPath}`);
|
|
48
|
+
if (!opts.htmlPath.toLowerCase().endsWith('.html')) fail('UNSUPPORTED_ARTIFACT', 'Only .html files are supported for authored artifact publishing.');
|
|
49
|
+
|
|
50
|
+
const cfg = JSON.parse(readFileSync(opts.configPath, 'utf8'));
|
|
51
|
+
const apiUrl = String(cfg?.server?.apiUrl || '').replace(/\/$/, '');
|
|
52
|
+
if (!apiUrl) fail('INVALID_CONFIG', 'share server apiUrl missing from config.');
|
|
53
|
+
|
|
54
|
+
const htmlBuffer = readFileSync(opts.htmlPath);
|
|
55
|
+
const form = new FormData();
|
|
56
|
+
form.append('artifact', new Blob([htmlBuffer], { type: 'text/html' }), basename(opts.htmlPath));
|
|
57
|
+
form.append('artifactType', 'html-file');
|
|
58
|
+
if (opts.slug) form.append('slug', opts.slug);
|
|
59
|
+
if (opts.title) form.append('title', opts.title);
|
|
60
|
+
if (opts.alias) form.append('alias', opts.alias);
|
|
61
|
+
|
|
62
|
+
const response = await fetch(`${apiUrl}/publish`, { method: 'POST', body: form });
|
|
63
|
+
const text = await response.text();
|
|
64
|
+
|
|
65
|
+
let payload;
|
|
66
|
+
try {
|
|
67
|
+
payload = JSON.parse(text);
|
|
68
|
+
} catch {
|
|
69
|
+
fail('INVALID_RESPONSE', `Share server returned non-JSON response: ${text}`, 1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!response.ok || payload?.ok === false) {
|
|
73
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (opts.urlOnly) {
|
|
78
|
+
process.stdout.write(`${payload.url || payload.viewerUrl || ''}\n`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
main().catch((error) => {
|
|
86
|
+
fail('PUBLISH_FAILED', error instanceof Error ? error.message : String(error));
|
|
87
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
HTML_PATH=""
|
|
6
|
+
SLUG=""
|
|
7
|
+
TITLE=""
|
|
8
|
+
ALIAS=""
|
|
9
|
+
URL_ONLY=0
|
|
10
|
+
|
|
11
|
+
usage() {
|
|
12
|
+
cat <<'EOF'
|
|
13
|
+
Usage: publish-authored-html.sh <html-file> [--slug STEM] [--title TITLE] [--alias ALIAS] [--url-only]
|
|
14
|
+
|
|
15
|
+
Publish an already-authored HTML artifact via share-html.
|
|
16
|
+
Use this when the coding agent wrote the HTML directly and only needs the share pipeline.
|
|
17
|
+
EOF
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
while [[ $# -gt 0 ]]; do
|
|
21
|
+
case "$1" in
|
|
22
|
+
--slug) SLUG="$2"; shift 2 ;;
|
|
23
|
+
--title) TITLE="$2"; shift 2 ;;
|
|
24
|
+
--alias) ALIAS="$2"; shift 2 ;;
|
|
25
|
+
--url-only) URL_ONLY=1; shift ;;
|
|
26
|
+
--help) usage; exit 0 ;;
|
|
27
|
+
--*) echo "Unknown argument: $1" >&2; exit 1 ;;
|
|
28
|
+
*)
|
|
29
|
+
if [[ -z "$HTML_PATH" ]]; then
|
|
30
|
+
HTML_PATH="$1"
|
|
31
|
+
shift
|
|
32
|
+
else
|
|
33
|
+
echo "Unexpected positional argument: $1" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
;;
|
|
37
|
+
esac
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
if [[ -z "$HTML_PATH" ]]; then
|
|
41
|
+
usage >&2
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [[ ! -f "$HTML_PATH" ]]; then
|
|
46
|
+
echo "HTML file does not exist: $HTML_PATH" >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
find_share_publish_script() {
|
|
51
|
+
local candidates=(
|
|
52
|
+
"$SCRIPT_DIR/../../share-html/scripts/publish.sh"
|
|
53
|
+
"$SCRIPT_DIR/../../../marvin/skills/share-html/scripts/publish.sh"
|
|
54
|
+
"$SCRIPT_DIR/../../../../marvin/skills/share-html/scripts/publish.sh"
|
|
55
|
+
"$HOME/.agents/skills/share-html/scripts/publish.sh"
|
|
56
|
+
"$HOME/.pi/agent/skills/share-html/scripts/publish.sh"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
for candidate in "${candidates[@]}"; do
|
|
60
|
+
if [[ -f "$candidate" ]]; then
|
|
61
|
+
printf '%s\n' "$candidate"
|
|
62
|
+
return 0
|
|
63
|
+
fi
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
find "$(cd "$SCRIPT_DIR/../../../../.." && pwd)" -path '*/share-html/scripts/publish.sh' 2>/dev/null | head -1
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
PUBLISH_SCRIPT="$(find_share_publish_script)"
|
|
70
|
+
if [[ -z "$PUBLISH_SCRIPT" || ! -f "$PUBLISH_SCRIPT" ]]; then
|
|
71
|
+
echo '{"ok":false,"error":{"code":"MISSING_SHARE_HTML","message":"Could not find share-html publish.sh. Install the share-html skill first."}}'
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
CMD=(bash "$PUBLISH_SCRIPT" "$HTML_PATH")
|
|
76
|
+
if [[ -n "$SLUG" ]]; then CMD+=(--slug "$SLUG"); fi
|
|
77
|
+
if [[ -n "$TITLE" ]]; then CMD+=(--title "$TITLE"); fi
|
|
78
|
+
if [[ -n "$ALIAS" ]]; then CMD+=(--alias "$ALIAS"); fi
|
|
79
|
+
|
|
80
|
+
PUBLISH_JSON="$(${CMD[@]})"
|
|
81
|
+
|
|
82
|
+
if [[ "$URL_ONLY" -eq 1 ]]; then
|
|
83
|
+
python3 - <<'PY' "$PUBLISH_JSON"
|
|
84
|
+
import json, sys
|
|
85
|
+
payload = json.loads(sys.argv[1])
|
|
86
|
+
if not payload.get("ok", True):
|
|
87
|
+
print(json.dumps(payload))
|
|
88
|
+
raise SystemExit(1)
|
|
89
|
+
print(payload.get("url") or payload.get("viewerUrl") or "")
|
|
90
|
+
PY
|
|
91
|
+
else
|
|
92
|
+
printf '%s\n' "$PUBLISH_JSON"
|
|
93
|
+
fi
|
package/src/commands/install.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { defineCommand } from "citty";
|
|
2
2
|
import { loadAllPlugins, loadPlugin } from "../parsers/claude";
|
|
3
3
|
import { targets } from "../targets/index";
|
|
4
|
-
import { resolve } from "path";
|
|
4
|
+
import { resolve, join } from "path";
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
|
+
import { execSync } from "child_process";
|
|
5
7
|
|
|
6
8
|
export const installCommand = defineCommand({
|
|
7
9
|
meta: {
|
|
@@ -27,6 +29,20 @@ export const installCommand = defineCommand({
|
|
|
27
29
|
},
|
|
28
30
|
async run({ args }) {
|
|
29
31
|
const targetName = args.to;
|
|
32
|
+
|
|
33
|
+
if (targetName === "pi") {
|
|
34
|
+
try {
|
|
35
|
+
const npmRoot = execSync("npm root -g", { encoding: "utf8" }).trim();
|
|
36
|
+
const packagePath = join(npmRoot, "@heart-of-gold", "toolkit", "package.json");
|
|
37
|
+
if (existsSync(packagePath)) {
|
|
38
|
+
console.warn("Warning: @heart-of-gold/toolkit is already installed as a Pi package.");
|
|
39
|
+
console.warn("Using 'install --to pi' as well will create duplicate Pi skill collisions on reload.");
|
|
40
|
+
console.warn("Prefer one Pi install path: either 'pi install npm:@heart-of-gold/toolkit' or 'bunx @heart-of-gold/toolkit install --to pi'.\n");
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// ignore detection failures and proceed normally
|
|
44
|
+
}
|
|
45
|
+
}
|
|
30
46
|
const target = targets[targetName];
|
|
31
47
|
if (!target) {
|
|
32
48
|
const available = Object.keys(targets).join(", ");
|