@iodes/releasekit 0.1.0 → 0.1.2
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/LICENSE +21 -21
- package/README.md +306 -110
- package/dist/cli.js +7 -5
- package/dist/content.d.ts +8 -0
- package/dist/content.js +5 -3
- package/dist/export.js +4 -3
- package/dist/git.d.ts +17 -6
- package/dist/git.js +9 -9
- package/dist/images.d.ts +14 -5
- package/dist/images.js +32 -8
- package/dist/model.d.ts +29 -19
- package/dist/model.js +27 -8
- package/dist/project.d.ts +1 -2
- package/dist/project.js +7 -12
- package/dist/prompts.d.ts +2 -2
- package/dist/prompts.js +24 -16
- package/dist/schema-export.js +9 -2
- package/dist/validate.js +10 -12
- package/examples/README.md +34 -14
- package/examples/backup-encryption/README.md +19 -0
- package/examples/backup-encryption/dark.png +0 -0
- package/examples/backup-encryption/dark.prompt.md +52 -0
- package/examples/backup-encryption/dimensions-edit.prompt.md +7 -0
- package/examples/backup-encryption/flat-render-requests.md +15 -0
- package/examples/backup-encryption/light.png +0 -0
- package/examples/backup-encryption/light.prompt.md +52 -0
- package/examples/backup-encryption/pair-review.md +18 -0
- package/examples/backup-encryption/scene.yaml +31 -0
- package/examples/connected-route/README.md +23 -0
- package/examples/connected-route/dark.png +0 -0
- package/examples/connected-route/dark.prompt.md +58 -0
- package/examples/connected-route/light.png +0 -0
- package/examples/connected-route/light.prompt.md +58 -0
- package/examples/connected-route/pair-review.md +22 -0
- package/examples/connected-route/render-requests.md +171 -0
- package/examples/connected-route/scene.yaml +59 -0
- package/examples/feature-briefs.yaml +96 -89
- package/examples/location-preferences/README.md +18 -0
- package/examples/location-preferences/dark.png +0 -0
- package/examples/location-preferences/dark.prompt.md +52 -0
- package/examples/location-preferences/light.png +0 -0
- package/examples/location-preferences/light.prompt.md +52 -0
- package/examples/location-preferences/pair-review.md +17 -0
- package/examples/location-preferences/scene.yaml +26 -0
- package/examples/provided-media/README.md +15 -0
- package/examples/provided-media/scene.yaml +22 -0
- package/examples/queue-action/README.md +15 -15
- package/examples/queue-action/alignment-edit.prompt.md +8 -8
- package/examples/queue-action/dark.prompt.md +58 -58
- package/examples/queue-action/light.prompt.md +58 -58
- package/examples/queue-action/pair-review.md +33 -33
- package/examples/queue-action/scene.yaml +41 -41
- package/examples/release-notes.en-US.json +56 -56
- package/examples/release-notes.ko-KR.json +56 -56
- package/examples/storage-breakdown/README.md +18 -0
- package/examples/storage-breakdown/dark.png +0 -0
- package/examples/storage-breakdown/dark.prompt.md +52 -0
- package/examples/storage-breakdown/light.png +0 -0
- package/examples/storage-breakdown/light.prompt.md +52 -0
- package/examples/storage-breakdown/pair-review.md +18 -0
- package/examples/storage-breakdown/scene.yaml +28 -0
- package/examples/tablet-reading/README.md +18 -0
- package/examples/tablet-reading/content-edit.prompt.md +7 -0
- package/examples/tablet-reading/dark.png +0 -0
- package/examples/tablet-reading/dark.prompt.md +52 -0
- package/examples/tablet-reading/light.png +0 -0
- package/examples/tablet-reading/light.prompt.md +52 -0
- package/examples/tablet-reading/pair-review.md +18 -0
- package/examples/tablet-reading/scene.yaml +29 -0
- package/kit/references/composition-recipes.md +89 -73
- package/kit/references/format.md +27 -24
- package/kit/references/media-sources.md +34 -0
- package/kit/references/theme-pairing.md +55 -53
- package/kit/references/visual-language.md +73 -69
- package/kit/references/workflow.md +90 -24
- package/kit/references/writing.md +27 -27
- package/kit/skills/releasekit-draft/SKILL.md +12 -10
- package/kit/skills/releasekit-image/SKILL.md +20 -16
- package/kit/skills/releasekit-review/SKILL.md +16 -12
- package/kit/skills/releasekit-translate/SKILL.md +14 -10
- package/package.json +54 -52
- package/schemas/bundle.schema.json +26 -1
- package/schemas/visual.schema.json +42 -0
- package/schemas/evidence.schema.json +0 -96
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 SO, HYEONSEOP
|
|
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.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SO, HYEONSEOP
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,110 +1,306 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
releasekit
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<h1>ReleaseKit</h1>
|
|
4
|
+
|
|
5
|
+
<p><strong>Turn Git changes into visual release notes.</strong></p>
|
|
6
|
+
<p>Written with your coding agent. Versioned with your product.</p>
|
|
7
|
+
|
|
8
|
+
<p>
|
|
9
|
+
<a href="https://www.npmjs.com/package/@iodes/releasekit"><img src="https://img.shields.io/npm/v/@iodes/releasekit?color=4678ED" alt="npm version"></a>
|
|
10
|
+
<a href="https://github.com/iodes/ReleaseKit/actions/workflows/check.yml"><img src="https://github.com/iodes/ReleaseKit/actions/workflows/check.yml/badge.svg" alt="Check workflow status"></a>
|
|
11
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-4678ED" alt="License: MIT"></a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<p>
|
|
15
|
+
<a href="#quick-start">Quick start</a> ·
|
|
16
|
+
<a href="#workflow">Workflow</a> ·
|
|
17
|
+
<a href="examples/README.md">Examples</a> ·
|
|
18
|
+
<a href="#documentation">Documentation</a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
ReleaseKit pairs a deterministic CLI with portable agent skills. Your agent writes the notes and selects or creates images; the CLI collects Git evidence, prepares image requests, validates content, and exports JSON with local assets.
|
|
24
|
+
|
|
25
|
+
| Dark | Light |
|
|
26
|
+
| :---: | :---: |
|
|
27
|
+
|  |  |
|
|
28
|
+
|
|
29
|
+
*One scene brief, two theme variants. Fictional feature illustrations. [Browse the composition gallery →](examples/README.md#composition-gallery)*
|
|
30
|
+
|
|
31
|
+
## Why ReleaseKit?
|
|
32
|
+
|
|
33
|
+
- **Grounded in Git.** Draft from tags or commits, pin the evidence, and keep each release's changes together.
|
|
34
|
+
- **Works with your agent.** Use portable skills for Codex, Claude Code, and Cursor, plus the image tools already available to you.
|
|
35
|
+
- **Visuals for your feature.** Generate flat explanations in dark and light, or reuse an approved screenshot, photo, or content image across both viewer themes.
|
|
36
|
+
- **Content you own.** Keep Markdown, translations, and images in your repository. Export JSON and local assets for your product to display.
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
Requires **Git** and **Node.js 22.12+**.
|
|
41
|
+
|
|
42
|
+
### 1. Install
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npm install -g @iodes/releasekit
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Set up your product
|
|
49
|
+
|
|
50
|
+
Run inside your product's Git repository:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
releasekit init --tools codex,claude,cursor --themes both
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Choose the tools you use: `codex`, `claude`, `cursor`, or a comma-separated list. Then edit `releasekit/config.yaml` to set your product name, source language, locales, and visual settings. Setup prints the skill invocation hints for each tool.
|
|
57
|
+
|
|
58
|
+
### 3. Ask your agent
|
|
59
|
+
|
|
60
|
+
Start with the installed `releasekit-draft` skill. Example conversation with an image tool available:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
You: Use releasekit-draft to draft 1.4.0 from v1.3.0 to v1.4.0.
|
|
64
|
+
AI: Which language should the original notes use, and which
|
|
65
|
+
translations would you like? Current settings: Korean original,
|
|
66
|
+
English translation. A single language is also fine.
|
|
67
|
+
You: Korean original and English translation.
|
|
68
|
+
AI: Created releasekit/releases/1.4.0/
|
|
69
|
+
✓ Pinned the Git range and collected change evidence
|
|
70
|
+
✓ Wrote release notes in ko-KR and en-US
|
|
71
|
+
Next: prepare the images required by these notes.
|
|
72
|
+
Choose: Prepare images (recommended), Review copy, or Stop for now.
|
|
73
|
+
|
|
74
|
+
You: Prepare images.
|
|
75
|
+
AI: ✓ Generated dark/light explanations from shared scene briefs
|
|
76
|
+
✓ Reviewed and imported both variants for each generated graphic
|
|
77
|
+
The product-detail image is pending; I need an approved capture
|
|
78
|
+
or photo. Next: provide that image, or review the completed copy
|
|
79
|
+
while it is pending.
|
|
80
|
+
|
|
81
|
+
You: Use ./approved-capture.png for the product-detail note.
|
|
82
|
+
AI: ✓ Reviewed and imported it once for both viewer themes
|
|
83
|
+
Next: review and finalize 1.4.0, then export the release bundle.
|
|
84
|
+
|
|
85
|
+
You: Review and finalize 1.4.0, then export up to three releases
|
|
86
|
+
in English to ./release-output.
|
|
87
|
+
AI: ✓ Validated notes, translations, and images
|
|
88
|
+
✓ Marked release 1.4.0 ready
|
|
89
|
+
Exported release-output/
|
|
90
|
+
├── release-notes.json ← Notes grouped by release
|
|
91
|
+
└── assets/ ← Theme variants and shared supplied images
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The draft skill asks for the original language and optional translations before preparing or writing notes. Choices already supplied in the conversation are reused. The selection is saved for that release; future project defaults change only when requested.
|
|
95
|
+
|
|
96
|
+
Invoke the skill with `$releasekit-draft` in Codex, `/releasekit-draft` in Claude Code, or the skill picker in Cursor. The agent runs the CLI, generates flat explanations, and requests approved source images when the actual product or content must be shown.
|
|
97
|
+
|
|
98
|
+
## Workflow
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
Git range → Release draft → Notes + images + translations → Validate → Export
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Skill | Purpose |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `releasekit-draft` | Create or revise notes from a Git range. |
|
|
107
|
+
| `releasekit-image` | Plan, generate or request, review, and import images. |
|
|
108
|
+
| `releasekit-translate` | Translate notes and track source freshness. |
|
|
109
|
+
| `releasekit-review` | Review content, evidence, images, and release readiness. |
|
|
110
|
+
|
|
111
|
+
All four skills use the agent's native question picker when clarification is needed and the tool is available, with free-text input for another answer; otherwise they ask in chat. This covers language choices, image references, translation scope or terminology, and unresolved review/export choices. Existing decisions are reused, so a clear request proceeds without extra questions. Image uploads are requested through the conversation's attachment flow.
|
|
112
|
+
|
|
113
|
+
After each stage, the agent reports what is complete and recommends the next useful task based on the release's current state. Choose a suggested action or describe another direction to continue in the same conversation; you can also stop for now. If you already requested the remaining work, the agent continues without asking again. Completed steps are skipped, and missing images or translations stay visible until resolved.
|
|
114
|
+
|
|
115
|
+
The agent handles editorial work, media selection, and image generation where appropriate. The CLI handles files, evidence, validation, and export. Finalizing a release marks local content ready; committing, publishing, and displaying it remain separate steps.
|
|
116
|
+
|
|
117
|
+
<details>
|
|
118
|
+
<summary><strong>Step-by-step CLI workflow</strong></summary>
|
|
119
|
+
|
|
120
|
+
Replace the sample version, Git refs, and note ID with your own. If release `1.3.0` already exists in ReleaseKit, add `--previous 1.3.0` to link its history.
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
releasekit prepare 1.4.0 --from v1.3.0 --to v1.4.0
|
|
124
|
+
releasekit note add 1.4.0 queue-action
|
|
125
|
+
|
|
126
|
+
# Fill the notes, evidence references, and visual brief.
|
|
127
|
+
# Choose an archetype and set scene.source to generated for this example.
|
|
128
|
+
releasekit image plan 1.4.0
|
|
129
|
+
|
|
130
|
+
# Generate and review the dark image with your agent or an external tool.
|
|
131
|
+
releasekit image import 1.4.0 queue-action --theme dark --file ./selected-dark.png
|
|
132
|
+
|
|
133
|
+
# Plan again to use the accepted dark image as a composition reference.
|
|
134
|
+
releasekit image plan 1.4.0
|
|
135
|
+
# Generate and review the matching light image, then import it.
|
|
136
|
+
releasekit image import 1.4.0 queue-action --theme light --file ./selected-light.png
|
|
137
|
+
|
|
138
|
+
# Review the completed translation before marking it current.
|
|
139
|
+
releasekit translation mark 1.4.0 queue-action --locale en-US
|
|
140
|
+
releasekit validate 1.4.0
|
|
141
|
+
releasekit finalize 1.4.0
|
|
142
|
+
releasekit export --current 1.4.0 --limit 3 --locale ko-KR --out ./release-output
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- Preparing creates only `release.yaml` with pinned Git boundaries. The agent reads commit history and relevant file diffs from Git as needed.
|
|
146
|
+
- Use `--from-root` for an explicitly requested full-history first release.
|
|
147
|
+
- `--to` defaults to `HEAD`; `--previous` can supply the comparison start.
|
|
148
|
+
- Edit existing drafts in place. `prepare` never overwrites them.
|
|
149
|
+
- Use `note add --no-image` for an intentionally text-only note.
|
|
150
|
+
- Add `--json` for structured results or `--cwd` to select a project directory.
|
|
151
|
+
- Export to a new directory; an existing destination is never overwritten.
|
|
152
|
+
|
|
153
|
+
See the [agent workflow](kit/references/workflow.md) for ancestry rules and continuing existing releases.
|
|
154
|
+
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
<details>
|
|
158
|
+
<summary><strong>Updating installed skills</strong></summary>
|
|
159
|
+
|
|
160
|
+
After installing a newer package version, run `releasekit update` in your product repository. It refreshes managed files, preserves user edits, and reports conflicts.
|
|
161
|
+
|
|
162
|
+
Codex and Cursor share `.agents/skills` to avoid duplicate discovery. Claude Code uses `.claude/skills`.
|
|
163
|
+
|
|
164
|
+
</details>
|
|
165
|
+
|
|
166
|
+
## Image themes
|
|
167
|
+
|
|
168
|
+
**Generated graphics default to dark and light.** Paired variants share one scene brief, preserving geometry, feature meaning, and semantic colors while presentation surfaces adapt. Images are shared across locales.
|
|
169
|
+
|
|
170
|
+
Choose `scene.source` in each note's visual brief before planning:
|
|
171
|
+
|
|
172
|
+
| Source | Use for | Theme handling |
|
|
173
|
+
| --- | --- | --- |
|
|
174
|
+
| `generated` | Flat glyphs, interface explanations, diagrams, and data graphics supported by the feature. | Separate images for the configured dark/light themes. |
|
|
175
|
+
| `provided` | Approved screenshots, photographs, or content artwork. Required for `object-detail` and `editorial-scene`. | One unchanged `shared` asset, or distinct genuine theme captures. |
|
|
176
|
+
|
|
177
|
+
Choose a single theme during setup with `--themes dark` or `--themes light`, or edit this field in the generated configuration while keeping the other visual settings:
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# releasekit/config.yaml
|
|
181
|
+
visuals:
|
|
182
|
+
themes: both # both | dark | light
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`releasekit image plan <version>` reports pending and reusable assets, with separate `generationRequests` and `providedRequests` counts. It reuses current imports and never calls a model API. Single-theme exports contain one real asset and an explicit fallback.
|
|
186
|
+
|
|
187
|
+
Requests with `action: generate` include a prompt for the agent or an external tool. Requests with `action: provide` have `promptFile: null` and identify the needed source. Missing supplied media stays pending and blocks finalization; the agent can continue independent writing and translation work.
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary><strong>Importing one supplied image for both themes</strong></summary>
|
|
191
|
+
|
|
192
|
+
Complete the note's visual brief with `scene.source: provided`. This example uses the note ID `product-detail`:
|
|
193
|
+
|
|
194
|
+
```sh
|
|
195
|
+
releasekit image plan 1.4.0
|
|
196
|
+
|
|
197
|
+
# Once an approved capture or photo is available, inspect it and import.
|
|
198
|
+
releasekit image import 1.4.0 product-detail --theme shared --file ./approved-capture.png
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The CLI keeps the original bytes, dimensions, and colors. One `shared` asset serves both viewer themes without generating or duplicating another file.
|
|
202
|
+
|
|
203
|
+
If genuine dark/light captures exist, import them with `--theme dark` and `--theme light` instead. A note must use either `shared` or themed entries; remove the previous variant entries when switching. A missing configured capture remains a supplied-image request.
|
|
204
|
+
|
|
205
|
+
Follow the current image plan even if older prompt files remain. See the [supplied-media example](examples/provided-media/README.md) and [media source guide](kit/references/media-sources.md) for pending inputs and older briefs.
|
|
206
|
+
|
|
207
|
+
</details>
|
|
208
|
+
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Applying changed settings to an existing draft</strong></summary>
|
|
211
|
+
|
|
212
|
+
Releases capture the project's visual settings when prepared. To apply updated defaults:
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
releasekit image plan 1.4.0 --sync-config
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
This preserves selected files and schedules only newly required or stale variants. Reopen ready content first by setting `status: draft` and `contentHash: null` in its `release.yaml`.
|
|
219
|
+
|
|
220
|
+
</details>
|
|
221
|
+
|
|
222
|
+
## Content and export
|
|
223
|
+
|
|
224
|
+
Everything lives alongside your product:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
releasekit/
|
|
228
|
+
├── config.yaml
|
|
229
|
+
└── releases/
|
|
230
|
+
└── 1.4.0/
|
|
231
|
+
├── release.yaml # Metadata, note order, previous release
|
|
232
|
+
├── notes/ # Markdown for each locale
|
|
233
|
+
├── visuals/ # Scene briefs, media sources, and variants
|
|
234
|
+
├── prompts/ # Prompts for pending generated variants
|
|
235
|
+
└── assets/ # Selected raster images
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Releases store the comparison start and end SHAs in `release.yaml`, with relevant paths or commits attached to individual notes. They do not save a full patch or a separate changed-file index. Draft validation reads the pinned Git range; finalized releases can be validated and exported without Git history.
|
|
239
|
+
|
|
240
|
+
Export follows explicit `previous` links, keeping each version's notes in a separate group. The default limit is **three releases, including the current one**. Similar notes in different versions remain separate.
|
|
241
|
+
|
|
242
|
+
The bundle contains display data and relative assets. Git evidence, prompts, and private source paths stay out of the export. Consumers safely render `bodyMarkdown` and select `image.variants[theme]`, falling back to `image.variants[image.fallbackTheme]` when needed. Text-only notes have `image: null`.
|
|
243
|
+
|
|
244
|
+
`fallbackTheme` can be `dark`, `light`, or `shared`. A shared-image export contains one `image.variants.shared` entry with `fallbackTheme: shared`; the same consumer lookup displays it in either viewer theme. Preserve the supplied image's original appearance when displaying it.
|
|
245
|
+
|
|
246
|
+
Translations track source fingerprints, and finalized releases record content fingerprints to detect later edits. See the [file contract](kit/references/format.md) and [JSON schemas](schemas) for the full structure.
|
|
247
|
+
|
|
248
|
+
## Documentation
|
|
249
|
+
|
|
250
|
+
| Guide | What it covers |
|
|
251
|
+
| --- | --- |
|
|
252
|
+
| [Agent workflow](kit/references/workflow.md) | Git boundaries, drafts, review, and export. |
|
|
253
|
+
| [Writing and translation](kit/references/writing.md) | Product copy, evidence, and locale freshness. |
|
|
254
|
+
| [Visual language](kit/references/visual-language.md) | Composition, hierarchy, materials, and acceptance checks. |
|
|
255
|
+
| [Choosing generated or supplied media](kit/references/media-sources.md) | Source selection, pending captures, and shared assets. |
|
|
256
|
+
| [Composition recipes](kit/references/composition-recipes.md) | Eight presentation categories matched to the feature and its source. |
|
|
257
|
+
| [Theme pairs and cost](kit/references/theme-pairing.md) | Shared geometry, single-theme policies, and reuse. |
|
|
258
|
+
| [File contract](kit/references/format.md) · [JSON schemas](schemas) | Authoring files and the public export format. |
|
|
259
|
+
| [Worked examples](examples/README.md) | Paired illustrations, supplied-image workflow, independent briefs, and three-release bundles. |
|
|
260
|
+
|
|
261
|
+
Visual guidance uses independent, brand-neutral descriptions. Each illustration should communicate the actual feature through its own scene. Worked examples demonstrate the process; each note gets its own composition.
|
|
262
|
+
|
|
263
|
+
The built-in guidance covers source selection, a scene contract, semantic palette roles, theme-pair invariants, text rules, cost-aware reuse, and visual acceptance checks. Generated icons are compact flat monochrome glyphs. Physical details and content previews use supplied images rather than invented 3D objects or decorative scenes.
|
|
264
|
+
|
|
265
|
+
## Development
|
|
266
|
+
|
|
267
|
+
Use **Node.js 24** for development. From a local checkout:
|
|
268
|
+
|
|
269
|
+
```sh
|
|
270
|
+
npm ci
|
|
271
|
+
npm run check
|
|
272
|
+
npm test
|
|
273
|
+
npm run build
|
|
274
|
+
npm pack --dry-run
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
CI runs on Windows and Linux with Node.js 22 and 24. Tests cover Git ranges, release history, image integrity, theme policies, supplied media and shared assets, translation freshness, finalization, installation conflicts, and CLI behavior.
|
|
278
|
+
|
|
279
|
+
<details>
|
|
280
|
+
<summary><strong>Install from a local checkout</strong></summary>
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
npm pack
|
|
284
|
+
npm install -g ./iodes-releasekit-0.1.0.tgz
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Use the tarball filename printed by `npm pack` if the package version differs. Packing builds the package automatically.
|
|
288
|
+
|
|
289
|
+
</details>
|
|
290
|
+
|
|
291
|
+
<details>
|
|
292
|
+
<summary><strong>Publishing this package</strong></summary>
|
|
293
|
+
|
|
294
|
+
The [Publish workflow](.github/workflows/publish.yml) runs manually on a `release/x.y.z` branch. The branch selects the major/minor release line and starting patch; all three components must be numeric with no leading zeros.
|
|
295
|
+
|
|
296
|
+
Once the workflow exists on the default and release branches, open **Actions → Publish → Run workflow** and select the release branch. It pins the selected commit and calculates the next available patch from both Git tags and npm versions. For `release/0.1.0`, publishing starts at `0.1.0` if unused, then advances past the highest existing patch to `0.1.1`, `0.1.2`, and so on. A newer major/minor line blocks older lines, and registry errors stop the workflow.
|
|
297
|
+
|
|
298
|
+
The runner restores dependencies and updates the package and lockfile with `npm version --no-git-tag-version`; no version-bump commit is needed. The CLI reads that package version for `--version`. After checks, tests, build, and package preview pass, the workflow creates a new tag and publishes through the npm trusted publisher configured for `publish.yml`.
|
|
299
|
+
|
|
300
|
+
Existing tags are never moved. Every run calculates a fresh version, even for the same commit. If an earlier attempt already created a tag or published a package, rerunning advances to the next patch. Tag pushes do not start publishing.
|
|
301
|
+
|
|
302
|
+
</details>
|
|
303
|
+
|
|
304
|
+
## License
|
|
305
|
+
|
|
306
|
+
[MIT](LICENSE) © 2026 SO, HYEONSEOP.
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { Command, Option } from 'commander';
|
|
4
5
|
import { Project, prepare } from './project.js';
|
|
5
6
|
import { initProject, installSkills } from './install.js';
|
|
@@ -7,9 +8,10 @@ import { addNote, markTranslation, syncImagePolicy } from './content.js';
|
|
|
7
8
|
import { planImages, importImage } from './images.js';
|
|
8
9
|
import { validate, finalize } from './validate.js';
|
|
9
10
|
import { exportBundle } from './export.js';
|
|
10
|
-
import { configSchema, noteMetaSchema,
|
|
11
|
+
import { configSchema, noteMetaSchema, assetVariant } from './model.js';
|
|
12
|
+
const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
11
13
|
const program = new Command();
|
|
12
|
-
program.name('releasekit').description('Git-based visual release content and agent skills').version(
|
|
14
|
+
program.name('releasekit').description('Git-based visual release content and agent skills').version(version)
|
|
13
15
|
.option('--cwd <directory>', 'project working directory', process.cwd())
|
|
14
16
|
.option('--json', 'print machine-readable results');
|
|
15
17
|
const project = () => Project.find(path.resolve(program.opts().cwd));
|
|
@@ -44,7 +46,7 @@ note.command('add <version> <id>').description('Scaffold a note and its locale f
|
|
|
44
46
|
emit({ version, note: id, status: 'draft' });
|
|
45
47
|
});
|
|
46
48
|
const images = program.command('image').description('Plan themed illustrations and register selected files');
|
|
47
|
-
images.command('plan <version>').description('
|
|
49
|
+
images.command('plan <version>').description('Plan generation or supplied-image requests without calling a model')
|
|
48
50
|
.option('--sync-config', 'apply current project image settings to this draft')
|
|
49
51
|
.action(async (version, options) => {
|
|
50
52
|
const instance = project();
|
|
@@ -53,9 +55,9 @@ images.command('plan <version>').description('Write pending prompts and report a
|
|
|
53
55
|
emit(await planImages(instance, version));
|
|
54
56
|
});
|
|
55
57
|
images.command('import <version> <note>').description('Import a selected raster variant')
|
|
56
|
-
.addOption(new Option('--theme <theme>', 'variant to register').choices(['dark', 'light']).makeOptionMandatory())
|
|
58
|
+
.addOption(new Option('--theme <theme>', 'variant to register; shared is for supplied images').choices(['dark', 'light', 'shared']).makeOptionMandatory())
|
|
57
59
|
.requiredOption('--file <file>', 'selected local PNG, JPEG, or WebP')
|
|
58
|
-
.action(async (version, id, options) => emit(await importImage(project(), version, id,
|
|
60
|
+
.action(async (version, id, options) => emit(await importImage(project(), version, id, assetVariant.parse(options.theme), path.resolve(program.opts().cwd, options.file))));
|
|
59
61
|
const translation = program.command('translation').description('Track source freshness for reviewed translations');
|
|
60
62
|
translation.command('mark <version> <note>').description('Mark an already reviewed translation current')
|
|
61
63
|
.requiredOption('--locale <locale>', 'translation language code')
|
package/dist/content.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare function readVisual(project: Project, version: string, id: string
|
|
|
7
7
|
schemaVersion: 1;
|
|
8
8
|
scene: {
|
|
9
9
|
archetype: "data-view" | "device-view" | "editorial-scene" | "icon-tile" | "object-detail" | "spatial-view" | "symbol-pair" | "ui-detail";
|
|
10
|
+
source?: "generated" | "provided" | undefined;
|
|
10
11
|
subject: string;
|
|
11
12
|
message: string;
|
|
12
13
|
focus: string;
|
|
@@ -33,6 +34,13 @@ export declare function readVisual(project: Project, version: string, id: string
|
|
|
33
34
|
width: number;
|
|
34
35
|
height: number;
|
|
35
36
|
} | undefined;
|
|
37
|
+
shared?: {
|
|
38
|
+
file: string;
|
|
39
|
+
sha256: string;
|
|
40
|
+
sceneHash: string;
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
} | undefined;
|
|
36
44
|
};
|
|
37
45
|
}>;
|
|
38
46
|
export declare function checkReferenceFiles(project: Project, references: string[]): Promise<void>;
|
package/dist/content.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
|
-
import { locale, noteMetaSchema, visualSchema } from './model.js';
|
|
2
|
+
import { locale, noteMetaSchema, visualSchema, imageSource } from './model.js';
|
|
3
3
|
import { identifier, writeYaml, writeNote, readNote, noteHash, exists, readYaml } from './files.js';
|
|
4
4
|
import { Project, editable } from './project.js';
|
|
5
5
|
export async function addNote(project, version, id, category, image) {
|
|
@@ -16,7 +16,7 @@ export async function addNote(project, version, id, category, image) {
|
|
|
16
16
|
if (image) {
|
|
17
17
|
await writeYaml(await project.releaseFile(version, `visuals/${id}.yaml`), {
|
|
18
18
|
schemaVersion: 1,
|
|
19
|
-
scene: { archetype: '', subject: '', message: '', focus: '', composition: '', context: '', elements: [], preserve: [], avoid: [], text: [], references: [] },
|
|
19
|
+
scene: { archetype: '', source: '', subject: '', message: '', focus: '', composition: '', context: '', elements: [], preserve: [], avoid: [], text: [], references: [] },
|
|
20
20
|
variants: {},
|
|
21
21
|
});
|
|
22
22
|
}
|
|
@@ -52,7 +52,9 @@ export async function syncImagePolicy(project, version) {
|
|
|
52
52
|
await project.save(release);
|
|
53
53
|
}
|
|
54
54
|
export async function readVisual(project, version, id) {
|
|
55
|
-
|
|
55
|
+
const visual = await readYaml(await project.releaseFile(version, `visuals/${identifier(id)}.yaml`), visualSchema);
|
|
56
|
+
imageSource(visual.scene);
|
|
57
|
+
return visual;
|
|
56
58
|
}
|
|
57
59
|
export async function checkReferenceFiles(project, references) {
|
|
58
60
|
const { within } = await import('./files.js');
|
package/dist/export.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Project } from './project.js';
|
|
4
|
-
import { bundleSchema,
|
|
4
|
+
import { bundleSchema, activeVariants, locale } from './model.js';
|
|
5
5
|
import { validate } from './validate.js';
|
|
6
6
|
import { exists, readNote, write } from './files.js';
|
|
7
7
|
import { readVisual } from './content.js';
|
|
@@ -25,8 +25,9 @@ export async function exportBundle(project, current, options) {
|
|
|
25
25
|
const exported = { id: note.id, category: note.category, title: text.title, bodyMarkdown: text.body, image: null };
|
|
26
26
|
if (note.image) {
|
|
27
27
|
const visual = await readVisual(project, release.version, note.id);
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const variants = activeVariants(visual, release.visuals);
|
|
29
|
+
exported.image = { alt: text.alt, fallbackTheme: variants[0], variants: {} };
|
|
30
|
+
for (const variant of variants) {
|
|
30
31
|
const asset = visual.variants[variant];
|
|
31
32
|
const relative = `assets/${release.version}/${path.posix.basename(asset.file)}`;
|
|
32
33
|
exported.image.variants[variant] = { src: relative, width: asset.width, height: asset.height };
|
package/dist/git.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Release } from './model.js';
|
|
2
|
+
interface GitChanges {
|
|
3
|
+
source: Release['source'];
|
|
4
|
+
commits: Array<{
|
|
5
|
+
sha: string;
|
|
6
|
+
subject: string;
|
|
7
|
+
}>;
|
|
8
|
+
files: Array<{
|
|
9
|
+
status: string;
|
|
10
|
+
path: string;
|
|
11
|
+
oldPath?: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
2
14
|
export declare function git(cwd: string, args: string[], input?: string): string;
|
|
3
15
|
export declare function repoRoot(cwd: string): string;
|
|
4
16
|
export declare function resolveCommit(root: string, ref: string): string;
|
|
5
17
|
export declare function isAncestor(root: string, base: string, head: string): boolean;
|
|
6
|
-
export declare function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
export declare function checkPrevious(root: string, previous: Release, evidence: Evidence): void;
|
|
18
|
+
export declare function resolveRange(root: string, from: string | null, to: string): Release['source'];
|
|
19
|
+
export declare function collect(root: string, from: string | null, to: string): GitChanges;
|
|
20
|
+
export declare function checkPrevious(root: string, previous: Release, source: Release['source']): void;
|
|
21
|
+
export {};
|