@design-ai/cli 4.55.0 → 4.56.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.
Files changed (52) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +39 -0
  3. package/README.ko.md +7 -7
  4. package/README.md +9 -9
  5. package/cli/lib/mcp-server.mjs +208 -10
  6. package/cli/lib/site-analysis.mjs +297 -0
  7. package/cli/lib/site-args.mjs +433 -0
  8. package/cli/lib/site-bundle-build.mjs +127 -0
  9. package/cli/lib/site-bundle-check.mjs +454 -0
  10. package/cli/lib/site-bundle-commands.mjs +95 -0
  11. package/cli/lib/site-bundle-compare.mjs +157 -0
  12. package/cli/lib/site-bundle-contract.mjs +79 -0
  13. package/cli/lib/site-bundle-files.mjs +87 -0
  14. package/cli/lib/site-bundle-handoff-runbook-actions.mjs +113 -0
  15. package/cli/lib/site-bundle-handoff-runbook-evidence-fields.mjs +164 -0
  16. package/cli/lib/site-bundle-handoff-runbook-evidence.mjs +334 -0
  17. package/cli/lib/site-bundle-handoff-runbook-format.mjs +31 -0
  18. package/cli/lib/site-bundle-handoff-runbook-stage-metadata.mjs +84 -0
  19. package/cli/lib/site-bundle-handoff-runbook.mjs +1331 -0
  20. package/cli/lib/site-bundle-handoff-summary.mjs +183 -0
  21. package/cli/lib/site-bundle-handoff.mjs +271 -0
  22. package/cli/lib/site-bundle-readme.mjs +98 -0
  23. package/cli/lib/site-bundle-repair-report.mjs +143 -0
  24. package/cli/lib/site-bundle-repair.mjs +68 -0
  25. package/cli/lib/site-content.mjs +399 -0
  26. package/cli/lib/site-evidence.mjs +35 -0
  27. package/cli/lib/site-mcp-commands.mjs +28 -0
  28. package/cli/lib/site-mcp-probes.mjs +159 -0
  29. package/cli/lib/site-mcp-readiness.mjs +157 -0
  30. package/cli/lib/site-mcp-report.mjs +324 -0
  31. package/cli/lib/site-next-actions.mjs +333 -0
  32. package/cli/lib/site-options.mjs +104 -0
  33. package/cli/lib/site-prompts.mjs +332 -0
  34. package/cli/lib/site-starter.mjs +153 -0
  35. package/cli/lib/site-strings.mjs +23 -0
  36. package/cli/lib/site-tasks.mjs +93 -0
  37. package/cli/lib/site-workflow-graph.mjs +309 -0
  38. package/cli/lib/site-workspace.mjs +492 -0
  39. package/cli/lib/site.mjs +108 -6617
  40. package/docs/DISTRIBUTION.ko.md +35 -6
  41. package/docs/DISTRIBUTION.md +35 -8
  42. package/docs/RELEASE-CHECKLIST.md +20 -3
  43. package/docs/ROADMAP.md +2179 -0
  44. package/docs/external-status.md +22 -7
  45. package/docs/integrations/design-ai-mcp-server.md +32 -0
  46. package/docs/integrations/vscode-walkthrough.ko.md +3 -3
  47. package/docs/integrations/vscode-walkthrough.md +3 -3
  48. package/docs/site-overrides/main.html +1 -1
  49. package/package.json +1 -1
  50. package/tools/audit/package-smoke.py +106 -0
  51. package/tools/audit/registry-smoke.py +378 -10
  52. package/tools/audit/smoke_assertions.py +83 -22
@@ -14,6 +14,7 @@ from doctor_assertions import EXPECTED_DOCTOR_PASS_LABELS, assert_doctor_report_
14
14
 
15
15
  ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
16
16
  ROOT = Path(__file__).resolve().parents[2]
17
+ PACKAGE_JSON = ROOT / "package.json"
17
18
  PLUGIN_MANIFEST = ROOT / ".claude-plugin" / "plugin.json"
18
19
  PLUGIN_INVENTORY_SECTIONS = (
19
20
  ("skills", "skill"),
@@ -21,6 +22,7 @@ PLUGIN_INVENTORY_SECTIONS = (
21
22
  ("agents", "agent"),
22
23
  )
23
24
  OUTPUT_FORCE_OVERWRITE_SENTINEL = "__design-ai-smoke-force-overwrite-sentinel__"
25
+ EXPECTED_MCP_INVALID_ARGUMENT_MESSAGE = "design_ai_search.limit must be an integer"
24
26
 
25
27
 
26
28
  def load_plugin_manifest() -> dict[str, object]:
@@ -30,11 +32,70 @@ def load_plugin_manifest() -> dict[str, object]:
30
32
  raise SystemExit(f"failed to load plugin manifest for smoke assertions: {PLUGIN_MANIFEST}") from error
31
33
 
32
34
 
35
+ def load_package_json() -> dict[str, object]:
36
+ try:
37
+ return json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
38
+ except (OSError, json.JSONDecodeError) as error:
39
+ raise SystemExit(f"failed to load package metadata for smoke assertions: {PACKAGE_JSON}") from error
40
+
41
+
33
42
  def count_manifest_section(manifest: dict[str, object], section: str) -> int:
34
43
  items = manifest.get(section)
35
44
  return len(items) if isinstance(items, list) else 0
36
45
 
37
46
 
47
+ EXPECTED_RELEASE_VERSION = str(load_package_json().get("version", ""))
48
+
49
+
50
+ def mcp_smoke_input() -> str:
51
+ messages = [
52
+ {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-11-25"}},
53
+ {"jsonrpc": "2.0", "method": "notifications/initialized"},
54
+ {"jsonrpc": "2.0", "id": 2, "method": "tools/list"},
55
+ {
56
+ "jsonrpc": "2.0",
57
+ "id": 3,
58
+ "method": "tools/call",
59
+ "params": {
60
+ "name": "design_ai_search",
61
+ "arguments": {"query": "Pretendard", "limit": "10"},
62
+ },
63
+ },
64
+ ]
65
+ return "".join(f"{json.dumps(message, separators=(',', ':'))}\n" for message in messages)
66
+
67
+
68
+ def assert_design_ai_mcp_protocol_responses(responses: list[object], *, context: str, cmd: list[str]) -> None:
69
+ by_id = {
70
+ response.get("id"): response
71
+ for response in responses
72
+ if isinstance(response, dict) and "id" in response
73
+ }
74
+ init = by_id.get(1)
75
+ tools = by_id.get(2)
76
+ invalid_call = by_id.get(3)
77
+
78
+ if not (isinstance(init, dict) and init.get("result", {}).get("serverInfo", {}).get("name") == "design-ai"):
79
+ raise SystemExit(f"{context}: MCP initialize response missing design-ai serverInfo")
80
+
81
+ tool_names = [
82
+ item.get("name")
83
+ for item in tools.get("result", {}).get("tools", [])
84
+ ] if isinstance(tools, dict) else []
85
+ if "design_ai_route" not in tool_names or "design_ai_search" not in tool_names:
86
+ raise SystemExit(f"{context}: MCP tools/list response missing design-ai tools")
87
+
88
+ invalid_error = invalid_call.get("error", {}) if isinstance(invalid_call, dict) else {}
89
+ invalid_text = str(invalid_error.get("message", "")) if isinstance(invalid_error, dict) else ""
90
+ if not (
91
+ isinstance(invalid_call, dict)
92
+ and isinstance(invalid_error, dict)
93
+ and invalid_error.get("code") == -32602
94
+ and EXPECTED_MCP_INVALID_ARGUMENT_MESSAGE in invalid_text
95
+ ):
96
+ raise SystemExit(f"{context}: MCP invalid argument response did not preserve invalid params validation")
97
+
98
+
38
99
  def format_inventory_count(count: int, singular: str) -> str:
39
100
  return f"{count} {singular}{'' if count == 1 else 's'}"
40
101
 
@@ -327,7 +388,7 @@ EXPECTED_MAIN_HELP_FRAGMENTS = (
327
388
  EXPECTED_VERSION_FRAGMENTS = (
328
389
  "design-ai CLI:",
329
390
  "Plugin / corpus:",
330
- "4.55.0",
391
+ EXPECTED_RELEASE_VERSION,
331
392
  "Source:",
332
393
  )
333
394
  EXPECTED_INSTALL_OUTPUT_FRAGMENTS = (
@@ -367,7 +428,7 @@ EXPECTED_DOCTOR_STRICT_OUTPUT_FRAGMENTS = (
367
428
  "Target:",
368
429
  "Prefix:",
369
430
  "Source layout: complete",
370
- "Version alignment: 4.55.0",
431
+ f"Version alignment: {EXPECTED_RELEASE_VERSION}",
371
432
  "Manifest paths: 41 referenced artifact(s) exist",
372
433
  "Node runtime:",
373
434
  "Python runtime:",
@@ -1508,7 +1569,7 @@ def passing_list_catalog_output(kind: str = "skills") -> str:
1508
1569
  "",
1509
1570
  " design-ai catalog",
1510
1571
  "",
1511
- "Plugin: design-ai v4.55.0",
1572
+ f"Plugin: design-ai v{EXPECTED_RELEASE_VERSION}",
1512
1573
  "",
1513
1574
  "",
1514
1575
  f"{kind} ({len(items)})",
@@ -1540,7 +1601,7 @@ def passing_list_catalog_json(kind: str = "skills") -> str:
1540
1601
  return json.dumps(
1541
1602
  {
1542
1603
  "name": "design-ai",
1543
- "version": "4.55.0",
1604
+ "version": EXPECTED_RELEASE_VERSION,
1544
1605
  "kind": kind,
1545
1606
  "sections": [
1546
1607
  {
@@ -1961,7 +2022,7 @@ def passing_examples_human_output() -> str:
1961
2022
  def passing_route_json() -> str:
1962
2023
  return json.dumps({
1963
2024
  "brief": EXPECTED_ROUTE_BRIEF,
1964
- "version": "4.55.0",
2025
+ "version": EXPECTED_RELEASE_VERSION,
1965
2026
  "routes": [
1966
2027
  {
1967
2028
  "id": EXPECTED_ROUTE_ID,
@@ -2035,7 +2096,7 @@ def passing_route_explain_human_output() -> str:
2035
2096
  f" {EXPECTED_ROUTE_BRIEF}",
2036
2097
  "",
2037
2098
  "Source: /tmp/design-ai",
2038
- "Corpus version: 4.55.0",
2099
+ f"Corpus version: {EXPECTED_RELEASE_VERSION}",
2039
2100
  "",
2040
2101
  f"1. {EXPECTED_ROUTE_LABEL} (high, score {len(EXPECTED_ROUTE_MATCHED_KEYWORDS)})",
2041
2102
  f" id: {EXPECTED_ROUTE_ID}",
@@ -2124,7 +2185,7 @@ def passing_route_catalog_json() -> str:
2124
2185
  routes.append(route)
2125
2186
 
2126
2187
  return json.dumps({
2127
- "version": "4.55.0",
2188
+ "version": EXPECTED_RELEASE_VERSION,
2128
2189
  "routes": routes,
2129
2190
  })
2130
2191
 
@@ -2132,7 +2193,7 @@ def passing_route_catalog_json() -> str:
2132
2193
  def passing_prompt_payload() -> dict:
2133
2194
  return {
2134
2195
  "brief": EXPECTED_ROUTE_BRIEF,
2135
- "version": "4.55.0",
2196
+ "version": EXPECTED_RELEASE_VERSION,
2136
2197
  "route": {
2137
2198
  "id": EXPECTED_ROUTE_ID,
2138
2199
  "label": EXPECTED_ROUTE_LABEL,
@@ -2237,7 +2298,7 @@ def passing_prompt_markdown_output() -> str:
2237
2298
  f" {EXPECTED_ROUTE_BRIEF}",
2238
2299
  "",
2239
2300
  "Source: /tmp/design",
2240
- "Corpus version: 4.55.0",
2301
+ f"Corpus version: {EXPECTED_RELEASE_VERSION}",
2241
2302
  "",
2242
2303
  "# design-ai task prompt",
2243
2304
  f"Task: {EXPECTED_ROUTE_BRIEF}",
@@ -2263,7 +2324,7 @@ def passing_prompt_markdown_output() -> str:
2263
2324
  def passing_pack_json() -> str:
2264
2325
  return json.dumps({
2265
2326
  "brief": EXPECTED_ROUTE_BRIEF,
2266
- "version": "4.55.0",
2327
+ "version": EXPECTED_RELEASE_VERSION,
2267
2328
  "maxBytes": EXPECTED_PACK_MAX_BYTES,
2268
2329
  "usedBytes": EXPECTED_PACK_MAX_BYTES,
2269
2330
  "summary": {
@@ -2311,7 +2372,7 @@ def passing_pack_markdown_output() -> str:
2311
2372
  f" {EXPECTED_ROUTE_BRIEF}",
2312
2373
  "",
2313
2374
  "Source: /tmp/design",
2314
- "Corpus version: 4.55.0",
2375
+ f"Corpus version: {EXPECTED_RELEASE_VERSION}",
2315
2376
  f"Context: partial, {EXPECTED_PACK_MAX_BYTES}/{EXPECTED_PACK_MAX_BYTES} bytes, 2 warnings",
2316
2377
  "",
2317
2378
  "# design-ai prompt pack",
@@ -4181,8 +4242,8 @@ def passing_main_help_output() -> str:
4181
4242
 
4182
4243
  def passing_version_output() -> str:
4183
4244
  return "\n".join([
4184
- "design-ai CLI: 4.55.0",
4185
- "Plugin / corpus: 4.55.0",
4245
+ f"design-ai CLI: {EXPECTED_RELEASE_VERSION}",
4246
+ f"Plugin / corpus: {EXPECTED_RELEASE_VERSION}",
4186
4247
  "Source: /tmp/design-ai",
4187
4248
  "",
4188
4249
  ])
@@ -4195,8 +4256,8 @@ def passing_version_json() -> str:
4195
4256
  "sourceRoot": "/tmp/design-ai",
4196
4257
  },
4197
4258
  "versions": {
4198
- "cli": "4.55.0",
4199
- "plugin": "4.55.0",
4259
+ "cli": EXPECTED_RELEASE_VERSION,
4260
+ "plugin": EXPECTED_RELEASE_VERSION,
4200
4261
  "aligned": True,
4201
4262
  },
4202
4263
  },
@@ -4213,7 +4274,7 @@ def passing_workspace_json() -> str:
4213
4274
  "root": "/tmp/project",
4214
4275
  "sourceRoot": "/tmp/design-ai",
4215
4276
  "packageName": "@design-ai/cli",
4216
- "version": "4.55.0",
4277
+ "version": EXPECTED_RELEASE_VERSION,
4217
4278
  },
4218
4279
  "git": {
4219
4280
  "isRepo": False,
@@ -4267,7 +4328,7 @@ def passing_workspace_json() -> str:
4267
4328
  "learningRestoreBackups": None,
4268
4329
  "release": {
4269
4330
  "packageName": "@design-ai/cli",
4270
- "version": "4.55.0",
4331
+ "version": EXPECTED_RELEASE_VERSION,
4271
4332
  "scripts": {
4272
4333
  "test": "node --test cli/lib/*.test.mjs",
4273
4334
  "audit:strict": "python3 -B tools/audit/run-all.py --strict",
@@ -5568,7 +5629,7 @@ def passing_doctor_strict_output() -> str:
5568
5629
  "ℹ Prefix: smoke-design-",
5569
5630
  "",
5570
5631
  "✓ Source layout: complete at /tmp/design-ai",
5571
- "✓ Version alignment: 4.55.0",
5632
+ f"✓ Version alignment: {EXPECTED_RELEASE_VERSION}",
5572
5633
  "✓ Manifest paths: 41 referenced artifact(s) exist",
5573
5634
  "✓ Node runtime: v24.13.1",
5574
5635
  "✓ Python runtime: Python 3.12.12",
@@ -5593,7 +5654,7 @@ def passing_install_output() -> str:
5593
5654
  return "\n".join([
5594
5655
  "",
5595
5656
  " design-ai installer",
5596
- " v4.55.0",
5657
+ f" v{EXPECTED_RELEASE_VERSION}",
5597
5658
  "",
5598
5659
  "Source: /tmp/design-ai",
5599
5660
  "Target: /tmp/claude-home",
@@ -6022,7 +6083,7 @@ def assert_workspace_json(raw: str, *, context: str, cmd: list[str]) -> None:
6022
6083
  )
6023
6084
  if workspace_context.get("packageName") != "@design-ai/cli":
6024
6085
  raise SystemExit(f"workspace JSON after {context} packageName differs from expected package")
6025
- if workspace_context.get("version") != "4.55.0":
6086
+ if workspace_context.get("version") != EXPECTED_RELEASE_VERSION:
6026
6087
  raise SystemExit(f"workspace JSON after {context} version differs from expected release version")
6027
6088
  for key in ("cwd", "root", "sourceRoot"):
6028
6089
  if not isinstance(workspace_context.get(key), str) or not workspace_context[key]:
@@ -6355,7 +6416,7 @@ def assert_workspace_json(raw: str, *, context: str, cmd: list[str]) -> None:
6355
6416
  context=context,
6356
6417
  command_label="workspace JSON",
6357
6418
  )
6358
- if release.get("packageName") != "@design-ai/cli" or release.get("version") != "4.55.0":
6419
+ if release.get("packageName") != "@design-ai/cli" or release.get("version") != EXPECTED_RELEASE_VERSION:
6359
6420
  raise SystemExit(f"workspace JSON after {context} release package metadata differs from expected values")
6360
6421
  if not isinstance(release.get("scripts"), dict):
6361
6422
  raise SystemExit(f"workspace JSON after {context} release scripts is not an object")
@@ -10780,7 +10841,7 @@ def run_self_test() -> None:
10780
10841
  )
10781
10842
  expect_self_test_failure(
10782
10843
  lambda: assert_version_json(
10783
- passing_version_json().replace('"plugin": "4.55.0"', '"plugin": "unknown"'),
10844
+ passing_version_json().replace(f'"plugin": "{EXPECTED_RELEASE_VERSION}"', '"plugin": "unknown"'),
10784
10845
  context=context,
10785
10846
  cmd=[*version_cmd, "--json"],
10786
10847
  ),