@faviovazquez/deliberate 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BRAINSTORM.md +300 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/SKILL.md +365 -0
- package/agents/adversarial-strategist.md +96 -0
- package/agents/assumption-breaker.md +93 -0
- package/agents/bias-detector.md +95 -0
- package/agents/classifier.md +92 -0
- package/agents/emergence-reader.md +95 -0
- package/agents/first-principles.md +95 -0
- package/agents/formal-verifier.md +95 -0
- package/agents/incentive-mapper.md +95 -0
- package/agents/inverter.md +95 -0
- package/agents/pragmatic-builder.md +95 -0
- package/agents/reframer.md +95 -0
- package/agents/resilience-anchor.md +95 -0
- package/agents/risk-analyst.md +95 -0
- package/agents/specialists/design-lens.md +96 -0
- package/agents/specialists/ml-intuition.md +96 -0
- package/agents/specialists/safety-frontier.md +96 -0
- package/agents/systems-thinker.md +95 -0
- package/bin/cli.js +69 -0
- package/configs/defaults.yaml +54 -0
- package/configs/provider-model-slots.example.yaml +88 -0
- package/install.sh +210 -0
- package/package.json +54 -0
- package/scripts/detect-platform.sh +70 -0
- package/scripts/frame-template.html +517 -0
- package/scripts/helper.js +339 -0
- package/scripts/release.sh +131 -0
- package/scripts/start-server.sh +274 -0
- package/scripts/stop-server.sh +42 -0
- package/templates/brainstorm-output.md +60 -0
- package/templates/deliberation-output.md +64 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
// deliberate visual companion -- client-side helper
|
|
2
|
+
// Handles selection, event recording, and interactive features
|
|
3
|
+
|
|
4
|
+
(function() {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
var SERVER_URL = window.location.origin;
|
|
8
|
+
var selections = {};
|
|
9
|
+
var selectionCount = 0;
|
|
10
|
+
|
|
11
|
+
// Selection handling
|
|
12
|
+
window.toggleSelect = function(el) {
|
|
13
|
+
var container = el.closest('.options, .cards');
|
|
14
|
+
var isMultiSelect = container && container.hasAttribute('data-multiselect');
|
|
15
|
+
var choice = el.getAttribute('data-choice');
|
|
16
|
+
|
|
17
|
+
if (!isMultiSelect) {
|
|
18
|
+
// Single select: deselect all others in this container
|
|
19
|
+
var siblings = container ? container.querySelectorAll('.option, .card') : [];
|
|
20
|
+
for (var i = 0; i < siblings.length; i++) {
|
|
21
|
+
if (siblings[i] !== el) {
|
|
22
|
+
siblings[i].classList.remove('selected');
|
|
23
|
+
var sibChoice = siblings[i].getAttribute('data-choice');
|
|
24
|
+
if (sibChoice && selections[sibChoice]) {
|
|
25
|
+
delete selections[sibChoice];
|
|
26
|
+
selectionCount--;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Toggle this element
|
|
33
|
+
var isSelected = el.classList.toggle('selected');
|
|
34
|
+
|
|
35
|
+
if (isSelected) {
|
|
36
|
+
selections[choice] = true;
|
|
37
|
+
selectionCount++;
|
|
38
|
+
} else {
|
|
39
|
+
delete selections[choice];
|
|
40
|
+
selectionCount--;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Update selection bar
|
|
44
|
+
updateSelectionBar();
|
|
45
|
+
|
|
46
|
+
// Record event
|
|
47
|
+
recordEvent({
|
|
48
|
+
type: 'click',
|
|
49
|
+
choice: choice,
|
|
50
|
+
text: extractText(el),
|
|
51
|
+
selected: isSelected,
|
|
52
|
+
timestamp: Math.floor(Date.now() / 1000)
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function extractText(el) {
|
|
57
|
+
var h3 = el.querySelector('h3');
|
|
58
|
+
var p = el.querySelector('p');
|
|
59
|
+
var parts = [];
|
|
60
|
+
if (h3) parts.push(h3.textContent.trim());
|
|
61
|
+
if (p) parts.push(p.textContent.trim());
|
|
62
|
+
return parts.join(' - ') || el.textContent.trim().substring(0, 100);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function updateSelectionBar() {
|
|
66
|
+
var bar = document.getElementById('selection-bar');
|
|
67
|
+
var text = document.getElementById('selection-text');
|
|
68
|
+
if (!bar || !text) return;
|
|
69
|
+
|
|
70
|
+
if (selectionCount > 0) {
|
|
71
|
+
bar.classList.add('visible');
|
|
72
|
+
text.textContent = selectionCount + ' selected';
|
|
73
|
+
} else {
|
|
74
|
+
bar.classList.remove('visible');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function recordEvent(event) {
|
|
79
|
+
try {
|
|
80
|
+
var xhr = new XMLHttpRequest();
|
|
81
|
+
xhr.open('POST', SERVER_URL + '/events', true);
|
|
82
|
+
xhr.setRequestHeader('Content-Type', 'application/json');
|
|
83
|
+
xhr.send(JSON.stringify(event));
|
|
84
|
+
} catch (e) {
|
|
85
|
+
// Silent fail -- events are supplementary
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Tooltip system for Canvas visualizations
|
|
90
|
+
var tooltip = document.getElementById('tooltip');
|
|
91
|
+
|
|
92
|
+
window.showTooltip = function(x, y, content) {
|
|
93
|
+
if (!tooltip) return;
|
|
94
|
+
tooltip.innerHTML = content;
|
|
95
|
+
tooltip.style.left = (x + 12) + 'px';
|
|
96
|
+
tooltip.style.top = (y + 12) + 'px';
|
|
97
|
+
tooltip.classList.add('visible');
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
window.hideTooltip = function() {
|
|
101
|
+
if (!tooltip) return;
|
|
102
|
+
tooltip.classList.remove('visible');
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Auto-refresh: poll for new content every 2 seconds
|
|
106
|
+
var currentFile = '{{FILENAME}}';
|
|
107
|
+
var refreshInterval = setInterval(function() {
|
|
108
|
+
try {
|
|
109
|
+
var xhr = new XMLHttpRequest();
|
|
110
|
+
xhr.open('GET', SERVER_URL + '/status', true);
|
|
111
|
+
xhr.timeout = 2000;
|
|
112
|
+
xhr.onload = function() {
|
|
113
|
+
if (xhr.status === 200) {
|
|
114
|
+
var data = JSON.parse(xhr.responseText);
|
|
115
|
+
var statusEl = document.getElementById('status-text');
|
|
116
|
+
if (statusEl) statusEl.textContent = 'connected';
|
|
117
|
+
|
|
118
|
+
if (data.newest && data.newest !== currentFile) {
|
|
119
|
+
// New content available, reload
|
|
120
|
+
window.location.reload();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
xhr.onerror = function() {
|
|
125
|
+
var statusEl = document.getElementById('status-text');
|
|
126
|
+
if (statusEl) statusEl.textContent = 'disconnected';
|
|
127
|
+
};
|
|
128
|
+
xhr.ontimeout = function() {
|
|
129
|
+
var statusEl = document.getElementById('status-text');
|
|
130
|
+
if (statusEl) statusEl.textContent = 'reconnecting...';
|
|
131
|
+
};
|
|
132
|
+
xhr.send();
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// Silent fail
|
|
135
|
+
}
|
|
136
|
+
}, 2000);
|
|
137
|
+
|
|
138
|
+
// Utility: agent color lookup
|
|
139
|
+
window.AGENT_COLORS = {
|
|
140
|
+
'assumption-breaker': '#ff6b6b',
|
|
141
|
+
'first-principles': '#ff9f43',
|
|
142
|
+
'classifier': '#feca57',
|
|
143
|
+
'formal-verifier': '#48dbfb',
|
|
144
|
+
'bias-detector': '#a55eea',
|
|
145
|
+
'systems-thinker': '#0abde3',
|
|
146
|
+
'resilience-anchor': '#c8d6e5',
|
|
147
|
+
'adversarial-strategist': '#ee5a24',
|
|
148
|
+
'emergence-reader': '#686de0',
|
|
149
|
+
'incentive-mapper': '#b33939',
|
|
150
|
+
'pragmatic-builder': '#f6e58d',
|
|
151
|
+
'reframer': '#be2edd',
|
|
152
|
+
'risk-analyst': '#535c68',
|
|
153
|
+
'inverter': '#f9ca24',
|
|
154
|
+
'ml-intuition': '#6ab04c',
|
|
155
|
+
'safety-frontier': '#7ed6df',
|
|
156
|
+
'design-lens': '#dfe6e9'
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
window.getAgentColor = function(agentName) {
|
|
160
|
+
return window.AGENT_COLORS[agentName] || '#8b949e';
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Force-directed graph utilities for idea maps and agent position maps
|
|
164
|
+
window.ForceGraph = function(canvas, options) {
|
|
165
|
+
var ctx = canvas.getContext('2d');
|
|
166
|
+
var nodes = options.nodes || [];
|
|
167
|
+
var edges = options.edges || [];
|
|
168
|
+
var onHover = options.onHover || null;
|
|
169
|
+
var onClick = options.onClick || null;
|
|
170
|
+
var width = canvas.width;
|
|
171
|
+
var height = canvas.height;
|
|
172
|
+
var dpr = window.devicePixelRatio || 1;
|
|
173
|
+
|
|
174
|
+
// Set canvas for high DPI
|
|
175
|
+
canvas.width = width * dpr;
|
|
176
|
+
canvas.height = height * dpr;
|
|
177
|
+
canvas.style.width = width + 'px';
|
|
178
|
+
canvas.style.height = height + 'px';
|
|
179
|
+
ctx.scale(dpr, dpr);
|
|
180
|
+
|
|
181
|
+
// Initialize positions
|
|
182
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
183
|
+
if (nodes[i].x === undefined) nodes[i].x = width / 2 + (Math.random() - 0.5) * 200;
|
|
184
|
+
if (nodes[i].y === undefined) nodes[i].y = height / 2 + (Math.random() - 0.5) * 200;
|
|
185
|
+
nodes[i].vx = 0;
|
|
186
|
+
nodes[i].vy = 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function simulate() {
|
|
190
|
+
var k = 0.01; // spring constant
|
|
191
|
+
var repulsion = 5000;
|
|
192
|
+
var damping = 0.85;
|
|
193
|
+
var centerForce = 0.005;
|
|
194
|
+
|
|
195
|
+
// Repulsion between all nodes
|
|
196
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
197
|
+
for (var j = i + 1; j < nodes.length; j++) {
|
|
198
|
+
var dx = nodes[j].x - nodes[i].x;
|
|
199
|
+
var dy = nodes[j].y - nodes[i].y;
|
|
200
|
+
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
201
|
+
var force = repulsion / (dist * dist);
|
|
202
|
+
var fx = (dx / dist) * force;
|
|
203
|
+
var fy = (dy / dist) * force;
|
|
204
|
+
nodes[i].vx -= fx;
|
|
205
|
+
nodes[i].vy -= fy;
|
|
206
|
+
nodes[j].vx += fx;
|
|
207
|
+
nodes[j].vy += fy;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Attraction along edges
|
|
212
|
+
for (var e = 0; e < edges.length; e++) {
|
|
213
|
+
var src = edges[e].source;
|
|
214
|
+
var tgt = edges[e].target;
|
|
215
|
+
var dx = tgt.x - src.x;
|
|
216
|
+
var dy = tgt.y - src.y;
|
|
217
|
+
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
218
|
+
var force = k * (dist - 120);
|
|
219
|
+
var fx = (dx / dist) * force;
|
|
220
|
+
var fy = (dy / dist) * force;
|
|
221
|
+
src.vx += fx;
|
|
222
|
+
src.vy += fy;
|
|
223
|
+
tgt.vx -= fx;
|
|
224
|
+
tgt.vy -= fy;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Center gravity
|
|
228
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
229
|
+
nodes[i].vx += (width / 2 - nodes[i].x) * centerForce;
|
|
230
|
+
nodes[i].vy += (height / 2 - nodes[i].y) * centerForce;
|
|
231
|
+
nodes[i].vx *= damping;
|
|
232
|
+
nodes[i].vy *= damping;
|
|
233
|
+
nodes[i].x += nodes[i].vx;
|
|
234
|
+
nodes[i].y += nodes[i].vy;
|
|
235
|
+
|
|
236
|
+
// Bounds
|
|
237
|
+
var r = nodes[i].radius || 20;
|
|
238
|
+
nodes[i].x = Math.max(r, Math.min(width - r, nodes[i].x));
|
|
239
|
+
nodes[i].y = Math.max(r, Math.min(height - r, nodes[i].y));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function draw() {
|
|
244
|
+
ctx.clearRect(0, 0, width, height);
|
|
245
|
+
|
|
246
|
+
// Draw edges
|
|
247
|
+
for (var e = 0; e < edges.length; e++) {
|
|
248
|
+
var edge = edges[e];
|
|
249
|
+
ctx.beginPath();
|
|
250
|
+
ctx.moveTo(edge.source.x, edge.source.y);
|
|
251
|
+
ctx.lineTo(edge.target.x, edge.target.y);
|
|
252
|
+
ctx.strokeStyle = edge.color || 'rgba(139,148,158,0.3)';
|
|
253
|
+
ctx.lineWidth = edge.width || 1;
|
|
254
|
+
if (edge.dashed) ctx.setLineDash([6, 4]);
|
|
255
|
+
else ctx.setLineDash([]);
|
|
256
|
+
ctx.stroke();
|
|
257
|
+
ctx.setLineDash([]);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Draw nodes
|
|
261
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
262
|
+
var node = nodes[i];
|
|
263
|
+
var r = node.radius || 20;
|
|
264
|
+
|
|
265
|
+
ctx.beginPath();
|
|
266
|
+
ctx.arc(node.x, node.y, r, 0, Math.PI * 2);
|
|
267
|
+
ctx.fillStyle = node.color || '#8b949e';
|
|
268
|
+
ctx.globalAlpha = node.opacity || 0.9;
|
|
269
|
+
ctx.fill();
|
|
270
|
+
ctx.globalAlpha = 1;
|
|
271
|
+
|
|
272
|
+
if (node.selected) {
|
|
273
|
+
ctx.strokeStyle = '#58a6ff';
|
|
274
|
+
ctx.lineWidth = 3;
|
|
275
|
+
ctx.stroke();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Label
|
|
279
|
+
if (node.label) {
|
|
280
|
+
ctx.fillStyle = '#e6edf3';
|
|
281
|
+
ctx.font = (node.fontSize || 11) + 'px -apple-system, system-ui, sans-serif';
|
|
282
|
+
ctx.textAlign = 'center';
|
|
283
|
+
ctx.textBaseline = 'middle';
|
|
284
|
+
ctx.fillText(node.label, node.x, node.y + r + 14);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Mouse interaction
|
|
290
|
+
var hoveredNode = null;
|
|
291
|
+
|
|
292
|
+
canvas.addEventListener('mousemove', function(e) {
|
|
293
|
+
var rect = canvas.getBoundingClientRect();
|
|
294
|
+
var mx = e.clientX - rect.left;
|
|
295
|
+
var my = e.clientY - rect.top;
|
|
296
|
+
hoveredNode = null;
|
|
297
|
+
|
|
298
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
299
|
+
var dx = mx - nodes[i].x;
|
|
300
|
+
var dy = my - nodes[i].y;
|
|
301
|
+
var r = nodes[i].radius || 20;
|
|
302
|
+
if (dx * dx + dy * dy < r * r) {
|
|
303
|
+
hoveredNode = nodes[i];
|
|
304
|
+
canvas.style.cursor = 'pointer';
|
|
305
|
+
if (onHover) onHover(nodes[i], e.clientX, e.clientY);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
canvas.style.cursor = 'default';
|
|
310
|
+
hideTooltip();
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
canvas.addEventListener('click', function(e) {
|
|
314
|
+
if (hoveredNode && onClick) {
|
|
315
|
+
onClick(hoveredNode);
|
|
316
|
+
recordEvent({
|
|
317
|
+
type: 'node-click',
|
|
318
|
+
nodeId: hoveredNode.id,
|
|
319
|
+
nodeLabel: hoveredNode.label,
|
|
320
|
+
timestamp: Math.floor(Date.now() / 1000)
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Run simulation
|
|
326
|
+
var iterations = 100;
|
|
327
|
+
for (var step = 0; step < iterations; step++) {
|
|
328
|
+
simulate();
|
|
329
|
+
}
|
|
330
|
+
draw();
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
nodes: nodes,
|
|
334
|
+
edges: edges,
|
|
335
|
+
redraw: draw,
|
|
336
|
+
simulate: simulate
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
})();
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# deliberate -- Release script
|
|
5
|
+
# Usage: ./scripts/release.sh [patch|minor|major]
|
|
6
|
+
#
|
|
7
|
+
# This script:
|
|
8
|
+
# 1. Bumps the version in package.json
|
|
9
|
+
# 2. Updates CHANGELOG.md with the new version header
|
|
10
|
+
# 3. Commits the version bump
|
|
11
|
+
# 4. Creates a git tag
|
|
12
|
+
# 5. Pushes to origin with tags
|
|
13
|
+
# 6. Creates a GitHub release
|
|
14
|
+
# 7. Publishes to npm
|
|
15
|
+
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
17
|
+
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
18
|
+
BUMP_TYPE="${1:-patch}"
|
|
19
|
+
|
|
20
|
+
if [[ "$BUMP_TYPE" != "patch" && "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "major" ]]; then
|
|
21
|
+
echo "Usage: release.sh [patch|minor|major]"
|
|
22
|
+
echo " patch: 0.1.0 -> 0.1.1 (bug fixes)"
|
|
23
|
+
echo " minor: 0.1.0 -> 0.2.0 (new features, new agents)"
|
|
24
|
+
echo " major: 0.1.0 -> 1.0.0 (breaking changes)"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
cd "$ROOT_DIR"
|
|
29
|
+
|
|
30
|
+
# Pre-flight checks
|
|
31
|
+
echo "=== Pre-flight checks ==="
|
|
32
|
+
|
|
33
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
34
|
+
echo "ERROR: Working directory is not clean. Commit or stash changes first."
|
|
35
|
+
git status --short
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
40
|
+
echo "ERROR: GitHub CLI (gh) is required. Install: https://cli.github.com"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if ! command -v npm >/dev/null 2>&1; then
|
|
45
|
+
echo "ERROR: npm is required."
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
50
|
+
if [[ "$CURRENT_BRANCH" != "main" ]]; then
|
|
51
|
+
echo "WARNING: You are on branch '$CURRENT_BRANCH', not 'main'."
|
|
52
|
+
read -p "Continue? [y/N] " confirm
|
|
53
|
+
[[ "$confirm" == "y" || "$confirm" == "Y" ]] || exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Get current and new version
|
|
57
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
58
|
+
echo "Current version: $CURRENT_VERSION"
|
|
59
|
+
|
|
60
|
+
# Bump version (npm version updates package.json and creates git tag)
|
|
61
|
+
NEW_VERSION=$(npm version "$BUMP_TYPE" --no-git-tag-version | sed 's/^v//')
|
|
62
|
+
echo "New version: $NEW_VERSION"
|
|
63
|
+
|
|
64
|
+
# Update CHANGELOG.md
|
|
65
|
+
DATE=$(date +%Y-%m-%d)
|
|
66
|
+
CHANGELOG_ENTRY="## [$NEW_VERSION] - $DATE"
|
|
67
|
+
|
|
68
|
+
if grep -q "## \[Unreleased\]" CHANGELOG.md 2>/dev/null; then
|
|
69
|
+
# Replace [Unreleased] with the new version
|
|
70
|
+
sed -i "s/## \[Unreleased\]/$CHANGELOG_ENTRY/" CHANGELOG.md
|
|
71
|
+
else
|
|
72
|
+
# Insert new version header after the first ## line
|
|
73
|
+
sed -i "/^## \[/i\\
|
|
74
|
+
\\n$CHANGELOG_ENTRY\\n" CHANGELOG.md
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo ""
|
|
78
|
+
echo "=== CHANGELOG.md updated ==="
|
|
79
|
+
echo "Please review and add release notes to CHANGELOG.md before continuing."
|
|
80
|
+
echo "The new version header has been added. Add your changes under it."
|
|
81
|
+
echo ""
|
|
82
|
+
read -p "Open CHANGELOG.md for editing? [Y/n] " edit_changelog
|
|
83
|
+
if [[ "$edit_changelog" != "n" && "$edit_changelog" != "N" ]]; then
|
|
84
|
+
${EDITOR:-vi} CHANGELOG.md
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Commit and tag
|
|
88
|
+
echo ""
|
|
89
|
+
echo "=== Committing and tagging ==="
|
|
90
|
+
git add package.json CHANGELOG.md
|
|
91
|
+
git commit -m "release: v$NEW_VERSION"
|
|
92
|
+
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
|
|
93
|
+
|
|
94
|
+
# Push
|
|
95
|
+
echo ""
|
|
96
|
+
echo "=== Pushing to origin ==="
|
|
97
|
+
git push origin "$CURRENT_BRANCH"
|
|
98
|
+
git push origin "v$NEW_VERSION"
|
|
99
|
+
|
|
100
|
+
# Create GitHub release
|
|
101
|
+
echo ""
|
|
102
|
+
echo "=== Creating GitHub release ==="
|
|
103
|
+
|
|
104
|
+
# Extract changelog for this version
|
|
105
|
+
RELEASE_NOTES=$(awk "/^## \[$NEW_VERSION\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md)
|
|
106
|
+
|
|
107
|
+
if [[ -z "$RELEASE_NOTES" ]]; then
|
|
108
|
+
RELEASE_NOTES="Release v$NEW_VERSION"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
gh release create "v$NEW_VERSION" \
|
|
112
|
+
--title "v$NEW_VERSION" \
|
|
113
|
+
--notes "$RELEASE_NOTES"
|
|
114
|
+
|
|
115
|
+
# Publish to npm
|
|
116
|
+
echo ""
|
|
117
|
+
echo "=== Publishing to npm ==="
|
|
118
|
+
read -p "Publish to npm? [Y/n] " publish
|
|
119
|
+
if [[ "$publish" != "n" && "$publish" != "N" ]]; then
|
|
120
|
+
npm publish
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Published! Users can now run: npx deliberate"
|
|
123
|
+
else
|
|
124
|
+
echo "Skipped npm publish. Run 'npm publish' manually when ready."
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
echo ""
|
|
128
|
+
echo "=== Release v$NEW_VERSION complete ==="
|
|
129
|
+
echo " Git tag: v$NEW_VERSION"
|
|
130
|
+
echo " GitHub: https://github.com/FavioVazquez/deliberate/releases/tag/v$NEW_VERSION"
|
|
131
|
+
echo " npm: https://www.npmjs.com/package/deliberate"
|