@hegemonart/get-design-done 1.24.0 → 1.24.1

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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Get Design Done — 5-stage agent-orchestrated design pipeline with 9 connections, handoff-first workflow, bidirectional Figma write-back, 22+ specialized agents, queryable knowledge layer (intel store, dependency analysis, learnings extraction), and a self-improvement loop (reflector, frontmatter + budget feedback, global-skills layer). v1.20.0 ships the SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream, and resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) for rate-limit + 429 + context-overflow recovery. Full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation (auto-tag + GitHub Release + release-time smoke test).",
8
- "version": "1.24.0"
8
+ "version": "1.24.1"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "get-design-done",
13
13
  "source": "./",
14
14
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), Claude Design handoff, bidirectional Figma write-back, and a queryable intel store (.design/intel/) for dependency and learnings queries. Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation. Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
15
- "version": "1.24.0",
15
+ "version": "1.24.1",
16
16
  "author": {
17
17
  "name": "hegemonart"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "get-design-done",
3
3
  "short_name": "gdd",
4
- "version": "1.24.0",
4
+ "version": "1.24.1",
5
5
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), handoff-first workflow via Claude Design bundles, bidirectional Figma write-back (annotations, Code Connect), queryable intel store (`.design/intel/`) for O(1) design surface lookups, and self-improvement loop (reflector agent, frontmatter + budget feedback, global-skills layer at `~/.claude/gdd/global-skills/`). Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings, reflect, apply-reflections. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows, lint + schema + frontmatter + stale-ref + shellcheck + gitleaks + injection-scan + blocking size-budget) and release automation (auto-tag + GitHub Release + release-time smoke test). Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
6
6
  "author": {
7
7
  "name": "hegemonart",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ All notable changes to get-design-done are documented here. Versions follow [sem
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.24.1] — 2026-04-25
8
+
9
+ CodeQL code-scanning cleanup — closes all 10 open alerts on `main` (1 error, 9 warnings). No behavior change for end users; security/quality patch on top of v1.24.0.
10
+
11
+ ### Fixed
12
+
13
+ - **`scripts/extract-changelog-section.cjs:31`** — `js/regex-injection` (error) + `js/incomplete-sanitization`. The CLI version arg was only escaping `.` before being interpolated into `new RegExp(...)`. Now escapes the full regex meta-char set `[.*+?^${}()|[\]\\]` via the same helper used elsewhere in the test suite.
14
+ - **`tests/mapper-schema.test.cjs:15`** — `js/incomplete-sanitization`. `extractSchemaKeys()` now uses the full meta-char escape on the slice-name input before constructing the heading regex.
15
+ - **`tests/skill-brief-mcp-migration.test.cjs:118`** — `js/identity-replacement`. The MCP-tool-presence check used `tool.replace(/_/g, '_')` (a no-op) inside `new RegExp(...)`. Replaced with a literal substring check (`assert.ok(fm.includes(tool))`) — MCP tool names are alphanumeric+underscore, so no regex is needed.
16
+ - **`.github/workflows/ci.yml`** — `actions/missing-workflow-permissions` (×6 jobs). Added a top-level `permissions: contents: read` block. Inherited by all 6 jobs (lint / validate / test / security / size-budget / e2e-headless). Gitleaks runs with `GITLEAKS_ENABLE_COMMENTS: false` so it does not require `pull-requests: write`.
17
+
18
+ ### Tests
19
+
20
+ - `tests/phase-24-baseline.test.cjs` — manifest-alignment assertions bumped to `1.24.1`.
21
+ - `tests/semver-compare.test.cjs` `OFF_CADENCE_VERSIONS` gains `1.24.1`.
22
+
23
+ ---
24
+
7
25
  ## [1.24.0] — 2026-04-25
8
26
 
9
27
  Phase 24 Multi-Runtime Installer milestone — `npx @hegemonart/get-design-done` with no flags now launches a polished interactive install session (`@clack/prompts`) that walks the user through a multi-select of all 14 supported AI coding runtimes plus a Global/Local radio. Scripted / CI installs continue to work via the existing flag surface unchanged. Strict superset over v1.23.5: any non-zero invocation still works exactly as before.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.24.0",
3
+ "version": "1.24.1",
4
4
  "description": "A Claude Code plugin for systematic design improvement",
5
5
  "author": "Hegemon",
6
6
  "homepage": "https://github.com/hegemonart/get-design-done",
@@ -28,7 +28,8 @@ if (!fs.existsSync(changelogPath)) {
28
28
 
29
29
  const body = fs.readFileSync(changelogPath, 'utf8').replace(/\r\n/g, '\n');
30
30
  const lines = body.split('\n');
31
- const headingRe = new RegExp(`^##\\s*\\[${version.replace(/\./g, '\\.')}\\]`);
31
+ const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
32
+ const headingRe = new RegExp(`^##\\s*\\[${escapedVersion}\\]`);
32
33
  const nextHeadingRe = /^##\s*\[/;
33
34
 
34
35
  let capture = false;
@@ -21,7 +21,7 @@
21
21
  const fs = require('node:fs');
22
22
  const path = require('node:path');
23
23
 
24
- const { acquire } = require('./lockfile.cjs');
24
+ const { acquire, renameWithRetry } = require('./lockfile.cjs');
25
25
 
26
26
  const STATE_PATH_REL = path.join('.design', 'iteration-budget.json');
27
27
  const DEFAULT_BUDGET = 50;
@@ -82,7 +82,7 @@ async function writeStateAtomic(state) {
82
82
  const merged = state.mergeFn ? state.mergeFn(latest || state.seed) : state.seed;
83
83
  const tmp = `${p}.tmp.${process.pid}.${Date.now()}`;
84
84
  fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n', 'utf8');
85
- fs.renameSync(tmp, p);
85
+ await renameWithRetry(tmp, p);
86
86
  return merged;
87
87
  } finally {
88
88
  await release();
@@ -76,9 +76,14 @@ async function acquire(path, opts) {
76
76
  if (existing === null) continue;
77
77
 
78
78
  const parsed = parseLock(existing);
79
- if (parsed === null || isStale(parsed, staleMs)) {
80
- // Clear stale/garbage lock; race-tolerant if it's already gone
81
- // we'll just get ENOENT, no-op.
79
+ // Only clear when we're confident the lock is stale: the payload
80
+ // parses AND the PID/age check says so. An unparseable payload is
81
+ // treated as fresh — on Windows, AV/indexer can transiently deny
82
+ // reads (EACCES/EPERM/EBUSY), and clearing under that condition
83
+ // would let two writers race and lose increments.
84
+ if (parsed !== null && isStale(parsed, staleMs)) {
85
+ // Clear stale lock; race-tolerant — if it's already gone we get
86
+ // ENOENT, no-op.
82
87
  try { fs.unlinkSync(lockPath); } catch { /* ignore */ }
83
88
  continue;
84
89
  }
@@ -174,4 +179,23 @@ function sleep(ms) {
174
179
  return new Promise((resolve) => setTimeout(resolve, ms));
175
180
  }
176
181
 
177
- module.exports = { acquire };
182
+ /**
183
+ * `fs.renameSync` wrapper that retries once on Windows EPERM/EBUSY/EACCES.
184
+ * AV scanners and the file-indexer can briefly hold a destination open
185
+ * after another process closed it, causing rename to fail even when the
186
+ * advisory lock is correctly held.
187
+ *
188
+ * Mirrors the inline retry in scripts/lib/gdd-state/index.ts mutate().
189
+ */
190
+ async function renameWithRetry(from, to) {
191
+ try {
192
+ fs.renameSync(from, to);
193
+ } catch (err) {
194
+ const code = err && typeof err === 'object' ? err.code : undefined;
195
+ if (code !== 'EPERM' && code !== 'EBUSY' && code !== 'EACCES') throw err;
196
+ await sleep(50);
197
+ fs.renameSync(from, to);
198
+ }
199
+ }
200
+
201
+ module.exports = { acquire, renameWithRetry };
@@ -30,7 +30,7 @@
30
30
  const fs = require('node:fs');
31
31
  const path = require('node:path');
32
32
 
33
- const { acquire } = require('./lockfile.cjs');
33
+ const { acquire, renameWithRetry } = require('./lockfile.cjs');
34
34
 
35
35
  const STATE_DIR_REL = path.join('.design', 'rate-limits');
36
36
  const LOCK_MAX_WAIT_MS = 3_000;
@@ -203,7 +203,7 @@ async function atomicWriteState(absPath, state) {
203
203
  try {
204
204
  const tmp = `${absPath}.tmp.${process.pid}.${Date.now()}`;
205
205
  fs.writeFileSync(tmp, JSON.stringify(state, null, 2) + '\n', 'utf8');
206
- fs.renameSync(tmp, absPath);
206
+ await renameWithRetry(tmp, absPath);
207
207
  } finally {
208
208
  await release();
209
209
  }