@programinglive/dev-workflow-mcp-server 1.13.3 → 1.13.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@programinglive/dev-workflow-mcp-server",
3
- "version": "1.13.3",
3
+ "version": "1.13.5",
4
4
  "description": "MCP server to enforce development workflow discipline",
5
5
  "homepage": "https://devworkflow.programinglive.com/",
6
6
  "mcpName": "io.github.programinglive/dev-workflow-mcp-server",
@@ -158,6 +158,52 @@ function loadPackageJson(cwd = process.cwd()) {
158
158
  }
159
159
  }
160
160
 
161
+ /**
162
+ * Memastikan package.json berisi versi semver yang sah SETELAH rilis berjalan.
163
+ *
164
+ * MENGAPA ADA
165
+ * -----------
166
+ * 30 Oktober 2026 `perform_release` menulis `"version": null` ke package.json
167
+ * dan membuat tag `vnull`, lalu mem-push keduanya. Penyebabnya argumen
168
+ * `--release-as` terkirim dua kali sehingga `semver.inc()` mengembalikan null.
169
+ *
170
+ * `SEMVER_REGEX` sudah ada saat itu, tetapi hanya dipakai memvalidasi tipe
171
+ * rilis MASUKAN. Hasil rilis tidak pernah diperiksa, jadi kerusakan baru
172
+ * terlihat setelah tag keluar dari mesin.
173
+ *
174
+ * Fungsi ini menutup celah itu: standard-version dianggap belum berhasil
175
+ * sebelum package.json terbukti berisi semver yang sah.
176
+ */
177
+ function verifyReleaseVersion({ cwd = process.cwd(), readFileSync = fs.readFileSync } = {}) {
178
+ const packageJsonPath = path.join(cwd, 'package.json');
179
+
180
+ let contents;
181
+ try {
182
+ contents = readFileSync(packageJsonPath, 'utf8');
183
+ } catch (error) {
184
+ throw new Error(`Tidak bisa membaca ${packageJsonPath}; hasil rilis tidak dapat diverifikasi.`);
185
+ }
186
+
187
+ let parsed;
188
+ try {
189
+ parsed = JSON.parse(contents);
190
+ } catch (error) {
191
+ throw new Error(`${packageJsonPath} bukan JSON yang sah setelah rilis; hasilnya tidak dapat diverifikasi.`);
192
+ }
193
+
194
+ const version = parsed?.version;
195
+
196
+ if (typeof version !== 'string' || !SEMVER_REGEX.test(version.trim())) {
197
+ throw new Error(
198
+ `Rilis gagal: package.json berisi version ${JSON.stringify(version)}, bukan semver yang sah. ` +
199
+ 'Tag tidak boleh di-push. Periksa argumen --release-as, lalu pulihkan dengan ' +
200
+ `"git tag -d v${String(version)}" dan "git reset --hard HEAD~1" bila perlu.`
201
+ );
202
+ }
203
+
204
+ return version.trim();
205
+ }
206
+
161
207
  function detectPackageManager({ env = process.env, cwd = process.cwd() } = {}) {
162
208
  const userAgent = env.npm_config_user_agent || '';
163
209
  if (userAgent.startsWith('pnpm/')) return 'pnpm';
@@ -249,6 +295,18 @@ function runRelease({
249
295
  return { ...releaseResult, status: releaseResult?.status || 1 };
250
296
  }
251
297
 
298
+ // Rilis hanya dianggap berhasil setelah package.json terbukti berisi semver
299
+ // yang sah. Tanpa pemeriksaan ini, `version: null` dan tag `vnull` lolos
300
+ // sampai di-push (kejadian 30 Oktober 2026).
301
+ let releasedVersion;
302
+ try {
303
+ releasedVersion = verifyReleaseVersion({ cwd });
304
+ } catch (error) {
305
+ safeLog('error', error.message);
306
+ return { status: 1, error };
307
+ }
308
+ safeLog('info', `✅ Released ${releasedVersion}`);
309
+
252
310
  const releaseNotesPath = dependencies.releaseNotesPath || path.join('docs', 'release-notes', 'RELEASE_NOTES.md');
253
311
  const updateNotes = dependencies.updateReleaseNotes || ((options = {}) => updateReleaseNotes({ rootDir: cwd, ...options }));
254
312
 
@@ -284,6 +342,7 @@ module.exports = {
284
342
  getNpmRunArgument,
285
343
  buildStandardVersionArgs,
286
344
  loadPackageJson,
345
+ verifyReleaseVersion,
287
346
  detectPackageManager,
288
347
  runProjectTests,
289
348
  runRelease,