@bstage-sdk/cli 0.8.2 → 0.8.4

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/dist/MIGRATION.md CHANGED
@@ -51,6 +51,65 @@
51
51
 
52
52
  ---
53
53
 
54
+ ## → cli 0.8.4 · ai-toolkit 0.8.4
55
+
56
+ ### `bstage doctor`가 포털 배치 진단을 함께 본다 — `자동` · `선택`
57
+
58
+ **영향**
59
+
60
+ - 로그인(`bstage login`)·링크(`bstage link`)된 디렉터리에서 `bstage doctor`를 실행하는 모든 프로젝트. 로그인·링크가 없으면 지금과 같다(포털 진단 절만 "건너뜀"으로 표시).
61
+ - **종료 코드가 새로 생긴다.** 포털 진단에 `error` 심각도 항목이 하나라도 있으면 `bstage doctor`가 **1**로 끝난다. 예전엔 항상 0이었다. CI·스크립트에서 doctor의 종료 코드를 실패로 처리하고 있다면 확인한다(로컬 진단 결과는 여전히 종료 코드에 영향이 없다).
62
+ - 감지: `bstage doctor --json` 출력에 `portal` 필드가 있으면 이 버전 이상이다.
63
+
64
+ **변경 내용**
65
+
66
+ - 로컬 진단 뒤에 **"포털 진단"** 절이 붙는다. 이 레포(링크된 레포)의 배치마다 포털이 판정한 문제를 심각도(`✗` error · `!` warn · `·` info), 제목, 상세, 조치와 함께 보여 준다 — 스테이지 커스텀 페이지 꺼짐, 배치 게시 꺼짐, 게시된 빌드 없음, 게시 빌드의 APP ID·KEY 문제(만료·스코프·짝 불일치·앞뒤 공백), 다시 빌드하지 않은 환경변수, 반영하지 않은 새 성공 빌드, 최신 빌드 실패 등. 문제가 없으면 `✓ 문제 없음`이다.
67
+ - 배치는 30개까지(동시 4개) 진단한다. **`--placement <id|경로|슬롯 id>`**로 하나만 볼 수 있다(`bstage deploy --placement`와 같은 정확 일치). `--placement`를 줬는데 링크가 없으면 종료 코드 2, 토큰이 없으면 3이다.
68
+ - `--json`(stdout 객체 하나)에 **`portal`** 필드가 더해진다(기존 필드는 그대로): `{ status: 'ok'|'skipped'|'unsupported'|'error', reason?, hint?, omitted?, placements: [{ placementId, path, slotId, surface, findings: [{ id, severity, title, detail?, fix?, evidence? }], error? }] }`. `findings[].id`(예: `appkey.expired`, `placement.not_deployed`)는 바뀌지 않는 식별자라 스크립트·에이전트가 분기에 쓸 수 있다. 진단 요청이 실패한 배치는 `error`에 이유가 담기고 `status`는 `error`다.
69
+ - 포털 서버가 아직 진단을 지원하지 않으면(`status: 'unsupported'`) 그 절만 건너뛴다. CLI 토큰은 `read` 등급이면 된다.
70
+ - `bstage-deploy` 스킬: 배포 후 401이 나거나 페이지가 기대와 다르면 `bstage doctor --json`부터 실행해 `portal.placements[].findings`의 `id`·`fix`를 따르도록 안내한다.
71
+
72
+ **적용**
73
+
74
+ 1. (자동) CLI를 올리면 된다. 스킬 문구는 `npx @bstage-sdk/cli@latest ai update`로 갱신한다.
75
+ 2. (판단) CI에서 `bstage doctor`를 돌리고 있다면 새 종료 코드 1을 실패로 볼지 정한다. 로그인·링크가 없는 CI라면 영향이 없다.
76
+
77
+ ## → cli 0.8.3 · ai-toolkit 0.8.3
78
+
79
+ ### sandbox 포털 기본 주소가 공개 주소로 바뀌었다 — `자동`
80
+
81
+ **영향**
82
+
83
+ - sandbox 포털에 로그인·배포하는 모든 프로젝트. 할 일은 없다.
84
+ - 사외(파트너) 환경에서 `bstage login`이 `ENOTFOUND`로 실패하던 문제가 풀린다.
85
+
86
+ **변경 내용**
87
+
88
+ - sandbox 포털 기본 주소: 예전 사내망 전용 주소(사설 IP) → `bstage-portal.sandstage.in`(공개).
89
+ - 옛 주소로 저장된 `.bstage/project.json`·로그인 토큰·`BSTAGE_PORTAL_URL`·`--portal` 값은 새 주소로 바꿔 읽는다. 다시 `bstage link`·`bstage login` 하지 않아도 된다. 토큰 파일은 다음 로그인 때 새 주소 키로 합쳐진다.
90
+ - 스킴 없이 준 포털 주소(예: `BSTAGE_PORTAL_URL=bstage-portal.sandstage.in`)는 https로 본다. 예전에는 `Invalid URL`로 실패했다.
91
+
92
+ **적용**
93
+
94
+ 1. (자동) CLI를 올리면 된다. 옛 버전에서 사외 로그인이 필요하면 `npx bstage login --portal https://bstage-portal.sandstage.in` 또는 `BSTAGE_PORTAL_URL=https://bstage-portal.sandstage.in`(스킴 포함)을 쓴다.
95
+
96
+ ### 템플릿 `name`은 폴더명과 같을 필요가 없다(문서 정정) — `자동`
97
+
98
+ **영향**
99
+
100
+ - 코드·빌드 동작은 바뀌지 않는다. 문서만 바로잡았다.
101
+ - `AGENTS.md`와 `bstage-template` 스킬이 "`createTemplate`의 `name`은 폴더명과 동일해야 한다"고 안내했지만, 빌드는 그런 검사를 하지 않는다. 이 문구를 따라 페이지 폴더명을 `name`에 맞추느라 배포 경로가 의도와 달라질 수 있었다(예: `/todos`로 내보내려던 페이지가 `/garen-todos`로 나감).
102
+
103
+ **변경 내용**
104
+
105
+ - `name`은 Custom Element 태그명이다. 소문자로 시작하고 하이픈을 1개 이상 넣고 소문자·숫자·하이픈만 쓴다. 레포 안에서 템플릿마다 달라야 한다(`bstage build`가 검사).
106
+ - 배포 경로(페이지)와 슬롯 자리는 폴더 위치가 정한다(`src/pages/{경로}/`). 그래서 `name`은 폴더명과 같을 필요가 없다. 예: 폴더 `src/pages/todos` + `name: 'garen-todos'`.
107
+ - **AGENTS.md 관리 영역 v16**: 위 내용으로 템플릿 작성 절을 고쳤다. `bstage-template` 스킬도 같은 내용으로 고쳤다.
108
+
109
+ **적용**
110
+
111
+ 1. (자동) `npx @bstage-sdk/cli@latest ai update` — 스킬·`AGENTS.md` 관리 영역을 v16으로 갱신한다.
112
+
54
113
  ## → cli 0.7.0
55
114
 
56
115
  ### 페이지 배치를 CLI로 만든다 — `bstage placement create` — `자동` · `선택`
@@ -67,7 +67,10 @@ var TRANSLATION_CDN_BASE_KEY = "static/i18n";
67
67
  var TRANSLATION_CDN_BUCKET_PREFIX = "cdn.bstage.in/";
68
68
  var PORTAL_HOSTS = {
69
69
  real: "portal.bstage.in",
70
- sandbox: "bstage-portal.sandbox.bstage.systems"
70
+ sandbox: "bstage-portal.sandstage.in"
71
+ };
72
+ var LEGACY_PORTAL_HOSTS = {
73
+ "bstage-portal.sandbox.bstage.systems": "bstage-portal.sandstage.in"
71
74
  };
72
75
  var PORTAL_HOST_ENV_KEY = "VITE_BSTAGE_PORTAL_HOST";
73
76
  function getAuthHost(mode, phase, tenantId) {
@@ -2129,6 +2132,7 @@ export {
2129
2132
  TRANSLATION_CDN_BASE_KEY,
2130
2133
  TRANSLATION_CDN_BUCKET_PREFIX,
2131
2134
  PORTAL_HOSTS,
2135
+ LEGACY_PORTAL_HOSTS,
2132
2136
  PORTAL_HOST_ENV_KEY,
2133
2137
  resolveProjectTarget,
2134
2138
  appKeyEnvDefine,
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  APP_KEY_VAR,
4
4
  DEFAULT_TRANSLATION_TIER,
5
5
  LEGACY_APP_KEY_VAR,
6
+ LEGACY_PORTAL_HOSTS,
6
7
  LOGIN_PATH,
7
8
  PORTAL_HOSTS,
8
9
  PORTAL_HOST_ENV_KEY,
@@ -16,7 +17,7 @@ import {
16
17
  isPublicPhase,
17
18
  resolvePhase,
18
19
  resolveProjectTarget
19
- } from "./chunk-COUDGZIA.js";
20
+ } from "./chunk-MSXSJHUT.js";
20
21
 
21
22
  // src/index.ts
22
23
  import { readFileSync as readFileSync5 } from "fs";
@@ -155,6 +156,18 @@ var PortalClient = class {
155
156
  );
156
157
  return unwrap(body, "placements");
157
158
  }
159
+ /**
160
+ * `GET .../placements/{id}/diagnosis` — 배치 하나가 "왜 기대대로 안 뜨는가"를 서버가 판정한 결과.
161
+ * 이 경로가 없는 구버전 서버는 404(CLI 토큰이면 등급 허용 목록 403)로 답한다 — 해석은 호출자 몫이다.
162
+ * `findings`가 빠진 응답도 빈 배열로 맞춰 호출자가 분기하지 않게 한다.
163
+ */
164
+ async getPlacementDiagnosis(org, space, placementId) {
165
+ const d = await this.json(
166
+ "GET",
167
+ `${this.stage(org, space)}/placements/${enc(placementId)}/diagnosis`
168
+ );
169
+ return { ...d, findings: d.findings ?? [] };
170
+ }
158
171
  /**
159
172
  * `expectedLiveBuildId`는 CAS(compare-and-swap) — 서버 측 live 빌드와 다르면 409.
160
173
  * 응답은 배치 전체가 아니라 `{id, liveBuildId}`만 온다(포털 핸들러 그대로).
@@ -2211,7 +2224,10 @@ import { dirname as dirname5, join as join7 } from "path";
2211
2224
  import { loadEnv as loadEnv2 } from "vite";
2212
2225
  var LOCAL_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
2213
2226
  function normalizePortalUrl(url) {
2214
- const u = new URL(url);
2227
+ const raw = url.trim();
2228
+ const u = new URL(/^[a-z][a-z0-9+.-]*:\/\//i.test(raw) ? raw : `https://${raw}`);
2229
+ const current = LEGACY_PORTAL_HOSTS[u.hostname];
2230
+ if (current) u.hostname = current;
2215
2231
  if (u.protocol !== "https:" && !(u.protocol === "http:" && LOCAL_HOSTS.has(u.hostname))) {
2216
2232
  fail(
2217
2233
  ExitCode.PRECONDITION,
@@ -2345,14 +2361,32 @@ function sanitize(tokens) {
2345
2361
  });
2346
2362
  return Object.fromEntries(buckets.filter(([, bucket]) => Object.keys(bucket).length > 0));
2347
2363
  }
2364
+ function canonicalPortalKey(portal) {
2365
+ try {
2366
+ return normalizePortalUrl(portal);
2367
+ } catch {
2368
+ return portal;
2369
+ }
2370
+ }
2371
+ function mergeByCanonicalPortal(tokens) {
2372
+ return Object.entries(tokens).reduce((acc, [portal, bucket]) => {
2373
+ const key = canonicalPortalKey(portal);
2374
+ const existing = acc[key] ?? {};
2375
+ const merged = key === portal ? { ...existing, ...bucket } : { ...bucket, ...existing };
2376
+ return { ...acc, [key]: merged };
2377
+ }, {});
2378
+ }
2348
2379
  function migrate(raw) {
2349
2380
  if (!raw || typeof raw !== "object") return { version: 2, tokens: {} };
2350
2381
  const obj = raw;
2351
2382
  if (obj.version === 2 && obj.tokens && typeof obj.tokens === "object") {
2352
- return { version: 2, tokens: sanitize(obj.tokens) };
2383
+ return {
2384
+ version: 2,
2385
+ tokens: mergeByCanonicalPortal(sanitize(obj.tokens))
2386
+ };
2353
2387
  }
2354
2388
  const tokens = Object.entries(obj).filter(([, v]) => isEntry(v)).map(([portal, v]) => [portal, { [UNKNOWN_ORG]: v }]);
2355
- return { version: 2, tokens: Object.fromEntries(tokens) };
2389
+ return { version: 2, tokens: mergeByCanonicalPortal(Object.fromEntries(tokens)) };
2356
2390
  }
2357
2391
  async function readCredentialFile(env2) {
2358
2392
  try {
@@ -4416,6 +4450,122 @@ async function i18nPullCommand(options) {
4416
4450
  console.log(pc15.dim(" \uC0DD\uC131 \uD30C\uC77C\uC744 \uD55C \uBC88 import\uD558\uBA74 useBstageTranslations().t() \uD0A4\uAC00 \uC881\uD600\uC9D1\uB2C8\uB2E4."));
4417
4451
  }
4418
4452
 
4453
+ // src/commands/doctor/portal.ts
4454
+ var MAX_DIAGNOSED_PLACEMENTS = 30;
4455
+ var DIAGNOSIS_CONCURRENCY = 4;
4456
+ function portalHasErrorFinding(p5) {
4457
+ return (p5?.placements ?? []).some((row) => row.findings.some((f) => f.severity === "error"));
4458
+ }
4459
+ async function diagnosePortal(opts, deps = {}) {
4460
+ const explicit = Boolean(opts.placement);
4461
+ const ctx = await openContext(deps, explicit);
4462
+ if (!("client" in ctx)) return ctx;
4463
+ const { client, link } = ctx;
4464
+ let all;
4465
+ try {
4466
+ all = await client.listPlacements(link.organizationId, link.spaceId, link.surface);
4467
+ } catch (err) {
4468
+ return {
4469
+ status: "error",
4470
+ reason: `\uBC30\uCE58 \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${describeError(err)}`,
4471
+ placements: []
4472
+ };
4473
+ }
4474
+ const targets = explicit ? requireTargets(all, link.repoId, opts.placement) : selectPlacements(all, link.repoId);
4475
+ if (targets.length === 0) {
4476
+ return {
4477
+ status: "ok",
4478
+ reason: "\uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
4479
+ hint: "bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984>",
4480
+ placements: []
4481
+ };
4482
+ }
4483
+ const picked = targets.slice(0, MAX_DIAGNOSED_PLACEMENTS);
4484
+ const omitted = targets.length - picked.length;
4485
+ const outcomes = await mapLimit(picked, DIAGNOSIS_CONCURRENCY, (p5) => diagnoseOne(ctx, p5));
4486
+ if (outcomes.every((o) => o.unsupported)) {
4487
+ return {
4488
+ status: "unsupported",
4489
+ reason: "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uBC30\uCE58 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
4490
+ placements: []
4491
+ };
4492
+ }
4493
+ const placements = outcomes.map((o) => o.row);
4494
+ return {
4495
+ status: placements.some((r) => r.error !== void 0) ? "error" : "ok",
4496
+ placements,
4497
+ ...omitted > 0 ? { omitted } : {}
4498
+ };
4499
+ }
4500
+ async function openContext(deps, explicit) {
4501
+ const cwd = deps.cwd ?? process.cwd();
4502
+ const env2 = deps.env ?? process.env;
4503
+ const hasLink = await loadLink(cwd, env2) !== null;
4504
+ try {
4505
+ return await resolveContext({ cwd, env: env2, fetch: deps.fetch });
4506
+ } catch (err) {
4507
+ if (explicit) throw err;
4508
+ const reason = scrub(err instanceof Error ? err.message : String(err));
4509
+ const isAuth = err instanceof CliExit && err.code === ExitCode.AUTH;
4510
+ const hint = isAuth ? "bstage login" : hasLink ? void 0 : "bstage link";
4511
+ return { status: "skipped", reason, ...hint ? { hint } : {}, placements: [] };
4512
+ }
4513
+ }
4514
+ async function diagnoseOne(ctx, p5) {
4515
+ const base = {
4516
+ placementId: p5.id,
4517
+ path: p5.path ?? "",
4518
+ slotId: p5.slotId ?? "",
4519
+ surface: p5.surface
4520
+ };
4521
+ try {
4522
+ const d = await ctx.client.getPlacementDiagnosis(
4523
+ ctx.link.organizationId,
4524
+ ctx.link.spaceId,
4525
+ p5.id
4526
+ );
4527
+ return {
4528
+ row: {
4529
+ ...base,
4530
+ path: d.path || base.path,
4531
+ slotId: d.slotId || base.slotId,
4532
+ surface: d.surface ?? base.surface,
4533
+ findings: d.findings
4534
+ },
4535
+ unsupported: false
4536
+ };
4537
+ } catch (err) {
4538
+ return {
4539
+ row: { ...base, findings: [], error: describeError(err) },
4540
+ unsupported: isUnsupported(err)
4541
+ };
4542
+ }
4543
+ }
4544
+ var PLACEMENT_NOT_FOUND = "\uBC30\uCE58\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4";
4545
+ function isUnsupported(err) {
4546
+ if (!(err instanceof PortalError)) return false;
4547
+ if (err.status === 404) return !err.message.includes(PLACEMENT_NOT_FOUND);
4548
+ return err.status === 403 && err.message.includes("\uD1A0\uD070 \uB4F1\uAE09\uC73C\uB85C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294");
4549
+ }
4550
+ function describeError(err) {
4551
+ if (err instanceof PortalError && err.status > 0) {
4552
+ return scrub(`${err.message} (HTTP ${err.status})`);
4553
+ }
4554
+ return scrub(err instanceof Error ? err.message : String(err));
4555
+ }
4556
+ async function mapLimit(items, limit, fn) {
4557
+ const results = new Array(items.length);
4558
+ let next = 0;
4559
+ const worker = async () => {
4560
+ while (next < items.length) {
4561
+ const i = next++;
4562
+ results[i] = await fn(items[i]);
4563
+ }
4564
+ };
4565
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
4566
+ return results;
4567
+ }
4568
+
4419
4569
  // src/commands/doctor/report.ts
4420
4570
  import { readFile as readFile9 } from "fs/promises";
4421
4571
  import { join as join15 } from "path";
@@ -4817,18 +4967,93 @@ async function fetchLatestVersion2(packageName) {
4817
4967
  }
4818
4968
 
4819
4969
  // src/commands/doctor/render.ts
4970
+ import pc17 from "picocolors";
4971
+
4972
+ // src/commands/doctor/renderPortal.ts
4820
4973
  import pc16 from "picocolors";
4974
+ var MARKERS = {
4975
+ error: pc16.red("\u2717"),
4976
+ warn: pc16.yellow("!"),
4977
+ info: pc16.dim("\xB7")
4978
+ };
4979
+ function clean(s) {
4980
+ return (s ?? "").replace(/\t/g, " ").replace(/[\p{Cc}\p{Cf}\p{Co}\p{Cs}\p{Zl}\p{Zp}\p{Variation_Selector}\u00ad\u180e]/gu, "");
4981
+ }
4982
+ function marker(severity) {
4983
+ return MARKERS[severity] ?? pc16.dim("\xB7");
4984
+ }
4985
+ function portalNeedsWork(p5) {
4986
+ return p5 !== void 0 && (p5.status === "error" || portalHasErrorFinding(p5));
4987
+ }
4988
+ function hintSuffix(reason, hint) {
4989
+ return hint && !(reason ?? "").includes(hint) ? ` (\uD560 \uC77C: ${hint})` : "";
4990
+ }
4991
+ function formatFinding(f) {
4992
+ const lines = [` ${marker(f.severity)} ${clean(f.title)} ${pc16.dim(`[${clean(f.id)}]`)}`];
4993
+ if (f.detail) lines.push(pc16.dim(` ${clean(f.detail)}`));
4994
+ if (f.fix) lines.push(pc16.dim(` \uC870\uCE58: ${clean(f.fix)}`));
4995
+ return lines;
4996
+ }
4997
+ function formatPlacement(row) {
4998
+ const label = clean(row.path || row.slotId || row.placementId);
4999
+ const lines = [` ${pc16.bold(label)}`];
5000
+ if (row.error !== void 0) {
5001
+ lines.push(` ${pc16.red("\u2717")} \uC9C4\uB2E8\uC744 \uBC1B\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${clean(row.error)}`);
5002
+ } else if (row.findings.length === 0) {
5003
+ lines.push(` ${pc16.green("\u2713")} \uBB38\uC81C \uC5C6\uC74C`);
5004
+ } else {
5005
+ lines.push(...row.findings.flatMap(formatFinding));
5006
+ }
5007
+ return lines;
5008
+ }
5009
+ function formatPortal(p5) {
5010
+ const lines = [pc16.bold("\uD3EC\uD138 \uC9C4\uB2E8")];
5011
+ if (p5.status === "skipped") {
5012
+ lines.push(
5013
+ pc16.dim(
5014
+ ` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uB85C\uADF8\uC778\xB7\uB9C1\uD06C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
5015
+ )
5016
+ );
5017
+ } else if (p5.status === "unsupported") {
5018
+ lines.push(
5019
+ pc16.dim(` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."}`)
5020
+ );
5021
+ } else if (p5.placements.length === 0) {
5022
+ lines.push(
5023
+ p5.status === "error" ? pc16.red(` \u2717 ${clean(p5.reason) || "\uD3EC\uD138 \uC9C4\uB2E8\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."}`) : pc16.dim(
5024
+ ` ${clean(p5.reason) || "\uC9C4\uB2E8\uD560 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
5025
+ )
5026
+ );
5027
+ } else {
5028
+ lines.push(...p5.placements.flatMap(formatPlacement));
5029
+ }
5030
+ if (p5.omitted) {
5031
+ lines.push(
5032
+ pc16.dim(
5033
+ ` (\uBC30\uCE58\uAC00 \uB9CE\uC544 ${p5.omitted}\uAC1C\uB294 \uC9C4\uB2E8\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 bstage doctor --placement <\uACBD\uB85C|\uC2AC\uB86F id>\uB85C \uB530\uB85C \uBCF4\uC138\uC694.)`
5034
+ )
5035
+ );
5036
+ }
5037
+ return lines;
5038
+ }
5039
+ function printPortal(p5) {
5040
+ if (!p5) return;
5041
+ for (const line of formatPortal(p5)) console.log(line);
5042
+ console.log("");
5043
+ }
5044
+
5045
+ // src/commands/doctor/render.ts
4821
5046
  function printVersions(r) {
4822
- console.log(pc16.bold("\u{1F4E6} SDK \uBC84\uC804"));
5047
+ console.log(pc17.bold("\u{1F4E6} SDK \uBC84\uC804"));
4823
5048
  if (!r.latestChecked) {
4824
- console.log(pc16.dim(" \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uAC74\uB108\uB6F0\uC5B4 \uC124\uCE58 \uBC84\uC804\uB9CC \uD45C\uC2DC\uD569\uB2C8\uB2E4."));
5049
+ console.log(pc17.dim(" \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uAC74\uB108\uB6F0\uC5B4 \uC124\uCE58 \uBC84\uC804\uB9CC \uD45C\uC2DC\uD569\uB2C8\uB2E4."));
4825
5050
  }
4826
5051
  const nameWidth = Math.max(12, ...r.versions.map((v) => v.pkg.replace("@bstage-sdk/", "").length));
4827
5052
  for (const v of r.versions) {
4828
5053
  const name = v.pkg.replace("@bstage-sdk/", "").padEnd(nameWidth);
4829
5054
  const inst = v.installed ?? "?";
4830
5055
  if (v.latest && v.installed) {
4831
- const arrow = v.outdated ? pc16.yellow(`\u2192 ${v.latest} (\uB4A4\uCC98\uC9D0)`) : pc16.green("(\uCD5C\uC2E0)");
5056
+ const arrow = v.outdated ? pc17.yellow(`\u2192 ${v.latest} (\uB4A4\uCC98\uC9D0)`) : pc17.green("(\uCD5C\uC2E0)");
4832
5057
  console.log(` ${name} ${inst.padEnd(8)} ${arrow}`);
4833
5058
  } else {
4834
5059
  console.log(` ${name} ${inst}`);
@@ -4837,89 +5062,89 @@ function printVersions(r) {
4837
5062
  console.log("");
4838
5063
  }
4839
5064
  function printFiles(r) {
4840
- console.log(pc16.bold("\u{1F4C1} init \uAE30\uBCF8 \uD30C\uC77C (\uCC38\uACE0)"));
5065
+ console.log(pc17.bold("\u{1F4C1} init \uAE30\uBCF8 \uD30C\uC77C (\uCC38\uACE0)"));
4841
5066
  const absent = r.files.filter((f) => !f.present);
4842
5067
  if (absent.length === 0) {
4843
- console.log(pc16.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
5068
+ console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
4844
5069
  } else {
4845
- console.log(pc16.dim(" init \uAE30\uBCF8\uAC12\uACFC\uC758 \uCC28\uC774\uC77C \uBFD0 \u2014 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB2E4\uB974\uAC8C \uCC98\uB9AC \uC911\uC774\uBA74 \uBB34\uC2DC\uD558\uC138\uC694."));
5070
+ console.log(pc17.dim(" init \uAE30\uBCF8\uAC12\uACFC\uC758 \uCC28\uC774\uC77C \uBFD0 \u2014 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB2E4\uB974\uAC8C \uCC98\uB9AC \uC911\uC774\uBA74 \uBB34\uC2DC\uD558\uC138\uC694."));
4846
5071
  for (const f of r.files) {
4847
- if (f.present) console.log(` ${pc16.green("\u2713")} ${f.path}`);
4848
- else console.log(` ${pc16.dim("\xB7")} ${f.path.padEnd(20)} ${pc16.dim(`\uC5C6\uC74C (${f.note})`)}`);
5072
+ if (f.present) console.log(` ${pc17.green("\u2713")} ${f.path}`);
5073
+ else console.log(` ${pc17.dim("\xB7")} ${f.path.padEnd(20)} ${pc17.dim(`\uC5C6\uC74C (${f.note})`)}`);
4849
5074
  }
4850
5075
  }
4851
5076
  console.log("");
4852
5077
  }
4853
5078
  function printLayout(r) {
4854
- console.log(pc16.bold("\u{1F5C2} \uD15C\uD50C\uB9BF \uB514\uB809\uD1A0\uB9AC"));
5079
+ console.log(pc17.bold("\u{1F5C2} \uD15C\uD50C\uB9BF \uB514\uB809\uD1A0\uB9AC"));
4855
5080
  if (r.layout.legacyPresent) {
4856
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("src/templates/ \uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 (\uC61B \uAD6C\uC870)")}`);
4857
- console.log(pc16.dim(" \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C \uACBD\uB85C\uAC00 \uD3F4\uB354 \uAD6C\uC870\uB97C \uB530\uB77C\uAC00\uB3C4\uB85D \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4."));
4858
- console.log(pc16.dim(" \uD398\uC774\uC9C0 \u2192 src/pages/{\uACBD\uB85C}/ \xB7 \uC704\uC82F \u2192 src/slots/{\uC544\uBB34\uC774\uB984}/"));
5081
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("src/templates/ \uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 (\uC61B \uAD6C\uC870)")}`);
5082
+ console.log(pc17.dim(" \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C \uACBD\uB85C\uAC00 \uD3F4\uB354 \uAD6C\uC870\uB97C \uB530\uB77C\uAC00\uB3C4\uB85D \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4."));
5083
+ console.log(pc17.dim(" \uD398\uC774\uC9C0 \u2192 src/pages/{\uACBD\uB85C}/ \xB7 \uC704\uC82F \u2192 src/slots/{\uC544\uBB34\uC774\uB984}/"));
4859
5084
  if (r.layout.legacyTemplates.length > 0) {
4860
- console.log(pc16.dim(` \uC62E\uACA8\uC57C \uD560 \uD15C\uD50C\uB9BF: ${r.layout.legacyTemplates.join(", ")}`));
5085
+ console.log(pc17.dim(` \uC62E\uACA8\uC57C \uD560 \uD15C\uD50C\uB9BF: ${r.layout.legacyTemplates.join(", ")}`));
4861
5086
  }
4862
- console.log(pc16.dim(' \uBCC0\uD658: \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C "bstage \uB9C8\uC774\uADF8\uB808\uC774\uC158" \uC694\uCCAD'));
5087
+ console.log(pc17.dim(' \uBCC0\uD658: \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C "bstage \uB9C8\uC774\uADF8\uB808\uC774\uC158" \uC694\uCCAD'));
4863
5088
  } else if (!r.layout.pagesPresent && !r.layout.slotsPresent) {
4864
- console.log(` ${pc16.dim("\xB7")} src/pages/ \xB7 src/slots/ \uB458 \uB2E4 \uC5C6\uC74C`);
5089
+ console.log(` ${pc17.dim("\xB7")} src/pages/ \xB7 src/slots/ \uB458 \uB2E4 \uC5C6\uC74C`);
4865
5090
  } else {
4866
- console.log(pc16.green(" \u2713 src/pages/ \xB7 src/slots/ \uAD6C\uC870"));
5091
+ console.log(pc17.green(" \u2713 src/pages/ \xB7 src/slots/ \uAD6C\uC870"));
4867
5092
  }
4868
5093
  console.log("");
4869
5094
  }
4870
5095
  function printPnpmWorkspace(r) {
4871
5096
  if (!r.pnpmWorkspace.relevant) return;
4872
- console.log(pc16.bold("\u{1F4E6} pnpm workspace \uC124\uC815"));
5097
+ console.log(pc17.bold("\u{1F4E6} pnpm workspace \uC124\uC815"));
4873
5098
  if (r.pnpmWorkspace.allowBuildsDeclared) {
4874
- console.log(pc16.green(" \u2713 pnpm-workspace.yaml\uC5D0 allowBuilds \uC120\uC5B8\uB428"));
5099
+ console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 allowBuilds \uC120\uC5B8\uB428"));
4875
5100
  } else {
4876
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("pnpm-workspace.yaml\uC5D0 allowBuilds \uC5C6\uC74C")}`);
5101
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 allowBuilds \uC5C6\uC74C")}`);
4877
5102
  console.log(
4878
- pc16.dim(" pnpm\uC740 \uC758\uC874\uC131 build script\uB97C \uAE30\uBCF8 \uCC28\uB2E8\uD558\uACE0, pnpm 11\uC740 \uADF8\uAC83\uC744 \uC5D0\uB7EC\uB85C \uB0B8\uB2E4")
5103
+ pc17.dim(" pnpm\uC740 \uC758\uC874\uC131 build script\uB97C \uAE30\uBCF8 \uCC28\uB2E8\uD558\uACE0, pnpm 11\uC740 \uADF8\uAC83\uC744 \uC5D0\uB7EC\uB85C \uB0B8\uB2E4")
4879
5104
  );
4880
5105
  console.log(
4881
- pc16.dim(" \u2192 `pnpm install`\uC774 ERR_PNPM_IGNORED_BUILDS\uB85C \uC2E4\uD328\uD558\uACE0 `pnpm dev`\uB3C4 \uC8FD\uB294\uB2E4")
5106
+ pc17.dim(" \u2192 `pnpm install`\uC774 ERR_PNPM_IGNORED_BUILDS\uB85C \uC2E4\uD328\uD558\uACE0 `pnpm dev`\uB3C4 \uC8FD\uB294\uB2E4")
4882
5107
  );
4883
- console.log(pc16.dim(" \uCD94\uAC00: pnpm-workspace.yaml\uC5D0 `allowBuilds:` + `esbuild: true`"));
4884
- console.log(pc16.dim(" \uB610\uB294 `pnpm approve-builds`\uB85C \uB300\uD654\uC2DD \uC120\uD0DD"));
5108
+ console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml\uC5D0 `allowBuilds:` + `esbuild: true`"));
5109
+ console.log(pc17.dim(" \uB610\uB294 `pnpm approve-builds`\uB85C \uB300\uD654\uC2DD \uC120\uD0DD"));
4885
5110
  }
4886
5111
  if (r.pnpmWorkspace.filePresent && !r.pnpmWorkspace.packagesDeclared) {
4887
- console.log(` ${pc16.yellow("\u2192")} ${pc16.yellow("pnpm-workspace.yaml\uC5D0 packages \uC5C6\uC74C")}`);
4888
- console.log(pc16.dim(" pnpm 9\uB294 \uC774 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 workspace \uB8E8\uD2B8\uB85C \uBCF4\uACE0 packages\uB97C \uC694\uAD6C\uD55C\uB2E4"));
4889
- console.log(pc16.dim(" \u2192 pnpm 9\uC5D0\uC11C `ERROR packages field missing or empty`\uB85C \uC8FD\uB294\uB2E4"));
4890
- console.log(pc16.dim(" \uCD94\uAC00: pnpm-workspace.yaml \uB9E8 \uC704\uC5D0 `packages:` + `- '.'`"));
5112
+ console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 packages \uC5C6\uC74C")}`);
5113
+ console.log(pc17.dim(" pnpm 9\uB294 \uC774 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 workspace \uB8E8\uD2B8\uB85C \uBCF4\uACE0 packages\uB97C \uC694\uAD6C\uD55C\uB2E4"));
5114
+ console.log(pc17.dim(" \u2192 pnpm 9\uC5D0\uC11C `ERROR packages field missing or empty`\uB85C \uC8FD\uB294\uB2E4"));
5115
+ console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml \uB9E8 \uC704\uC5D0 `packages:` + `- '.'`"));
4891
5116
  } else if (r.pnpmWorkspace.packagesDeclared) {
4892
- console.log(pc16.green(" \u2713 pnpm-workspace.yaml\uC5D0 packages \uC120\uC5B8\uB428"));
5117
+ console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 packages \uC120\uC5B8\uB428"));
4893
5118
  }
4894
5119
  console.log("");
4895
5120
  }
4896
5121
  function printScriptRow(sc) {
4897
5122
  if (sc.actual === null) {
4898
- console.log(` ${pc16.yellow("\u2192")} ${sc.name} ${pc16.yellow("\uC5C6\uC74C")}`);
5123
+ console.log(` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uC5C6\uC74C")}`);
4899
5124
  } else {
4900
5125
  console.log(
4901
- ` ${pc16.yellow("\u2192")} ${sc.name} ${pc16.yellow("\uB2E4\uB984")} ${pc16.dim(`\u2014 \uD604\uC7AC \`${sc.actual}\``)}`
5126
+ ` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uB2E4\uB984")} ${pc17.dim(`\u2014 \uD604\uC7AC \`${sc.actual}\``)}`
4902
5127
  );
4903
5128
  if (sc.actual.includes("--noEmit") && !sc.actual.includes("-p ")) {
4904
5129
  console.log(
4905
- pc16.dim(
5130
+ pc17.dim(
4906
5131
  " \uC8FC\uC758: solution-style tsconfig\uC5D0\uC11C `tsc --noEmit`\uC740 \uC544\uBB34 \uD30C\uC77C\uB3C4 \uAC80\uC0AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
4907
5132
  )
4908
5133
  );
4909
5134
  }
4910
5135
  }
4911
- console.log(pc16.dim(` ${sc.why}`));
4912
- console.log(pc16.dim(` \uAD8C\uC7A5: "${sc.name}": "${sc.expected}"`));
5136
+ console.log(pc17.dim(` ${sc.why}`));
5137
+ console.log(pc17.dim(` \uAD8C\uC7A5: "${sc.name}": "${sc.expected}"`));
4913
5138
  }
4914
5139
  function printScripts(r) {
4915
- console.log(pc16.bold("\u{1F6E0} package.json \uC2A4\uD06C\uB9BD\uD2B8"));
5140
+ console.log(pc17.bold("\u{1F6E0} package.json \uC2A4\uD06C\uB9BD\uD2B8"));
4916
5141
  const scriptIssues = r.scripts.filter((sc) => sc.actual !== sc.expected);
4917
5142
  if (scriptIssues.length === 0) {
4918
- console.log(pc16.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
5143
+ console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
4919
5144
  } else {
4920
5145
  for (const sc of r.scripts) {
4921
5146
  if (sc.actual === sc.expected) {
4922
- console.log(` ${pc16.green("\u2713")} ${sc.name}`);
5147
+ console.log(` ${pc17.green("\u2713")} ${sc.name}`);
4923
5148
  continue;
4924
5149
  }
4925
5150
  printScriptRow(sc);
@@ -4929,76 +5154,76 @@ function printScripts(r) {
4929
5154
  }
4930
5155
  function printLiquid(r) {
4931
5156
  if (r.liquid === null) return;
4932
- console.log(pc16.bold("\u{1F4A7} liquid \uAC80\uC99D"));
5157
+ console.log(pc17.bold("\u{1F4A7} liquid \uAC80\uC99D"));
4933
5158
  const errors = r.liquid.issues.filter((i) => i.level === "error");
4934
5159
  const warns = r.liquid.issues.filter((i) => i.level === "warn");
4935
5160
  if (errors.length === 0 && warns.length === 0) {
4936
- console.log(pc16.green(" \u2713 \uADDC\uC57D\xB7\uBB38\uBC95 \uC774\uC0C1 \uC5C6\uC74C"));
5161
+ console.log(pc17.green(" \u2713 \uADDC\uC57D\xB7\uBB38\uBC95 \uC774\uC0C1 \uC5C6\uC74C"));
4937
5162
  }
4938
- for (const i of errors) console.log(` ${pc16.red("\u2717")} ${i.path} ${pc16.red(i.message)}`);
4939
- for (const i of warns) console.log(` ${pc16.yellow("\u26A0")} ${i.path} ${pc16.dim(i.message)}`);
5163
+ for (const i of errors) console.log(` ${pc17.red("\u2717")} ${i.path} ${pc17.red(i.message)}`);
5164
+ for (const i of warns) console.log(` ${pc17.yellow("\u26A0")} ${i.path} ${pc17.dim(i.message)}`);
4940
5165
  if (errors.length > 0) {
4941
5166
  console.log(
4942
- pc16.dim(" \uACE0\uCE5C \uB4A4 `bstage build`\uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 \u2014 \uD3EC\uD138 \uBE4C\uB4DC\uB3C4 \uAC19\uC740 \uAC80\uC0AC\uB97C \uD569\uB2C8\uB2E4.")
5167
+ pc17.dim(" \uACE0\uCE5C \uB4A4 `bstage build`\uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 \u2014 \uD3EC\uD138 \uBE4C\uB4DC\uB3C4 \uAC19\uC740 \uAC80\uC0AC\uB97C \uD569\uB2C8\uB2E4.")
4943
5168
  );
4944
5169
  }
4945
5170
  console.log("");
4946
5171
  }
4947
5172
  function printRecommendedDeps(r) {
4948
5173
  if (r.recommendedDeps.length === 0) return;
4949
- console.log(pc16.bold("\u{1F9F1} \uAD8C\uC7A5 \uC758\uC874\uC131"));
5174
+ console.log(pc17.bold("\u{1F9F1} \uAD8C\uC7A5 \uC758\uC874\uC131"));
4950
5175
  if (r.recommendedDeps.every((d) => d.declared)) {
4951
- console.log(pc16.green(" \u2713 \uBAA8\uB450 \uC120\uC5B8\uB428"));
5176
+ console.log(pc17.green(" \u2713 \uBAA8\uB450 \uC120\uC5B8\uB428"));
4952
5177
  } else {
4953
5178
  for (const d of r.recommendedDeps) {
4954
5179
  if (d.declared) {
4955
- console.log(` ${pc16.green("\u2713")} ${d.pkg}`);
5180
+ console.log(` ${pc17.green("\u2713")} ${d.pkg}`);
4956
5181
  continue;
4957
5182
  }
4958
- console.log(` ${pc16.yellow("\u2192")} ${d.pkg} ${pc16.yellow("\uBBF8\uC120\uC5B8")} ${pc16.dim(`\u2014 ${d.note}`)}`);
4959
- console.log(pc16.dim(` ${d.why}`));
4960
- console.log(pc16.dim(` \uCD94\uAC00: npm i ${d.pkg} (\uD504\uB85C\uC81D\uD2B8 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB85C)`));
5183
+ console.log(` ${pc17.yellow("\u2192")} ${d.pkg} ${pc17.yellow("\uBBF8\uC120\uC5B8")} ${pc17.dim(`\u2014 ${d.note}`)}`);
5184
+ console.log(pc17.dim(` ${d.why}`));
5185
+ console.log(pc17.dim(` \uCD94\uAC00: npm i ${d.pkg} (\uD504\uB85C\uC81D\uD2B8 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB85C)`));
4961
5186
  }
4962
5187
  }
4963
5188
  console.log("");
4964
5189
  }
4965
5190
  function printMigrations(r) {
4966
- console.log(pc16.bold("\u{1F4D6} \uC801\uC6A9 \uAC00\uB2A5\uD55C \uB9C8\uC774\uADF8\uB808\uC774\uC158"));
5191
+ console.log(pc17.bold("\u{1F4D6} \uC801\uC6A9 \uAC00\uB2A5\uD55C \uB9C8\uC774\uADF8\uB808\uC774\uC158"));
4967
5192
  if (r.migrations.length === 0) {
4968
- console.log(pc16.dim(" \uD574\uB2F9 \uD56D\uBAA9 \uC5C6\uC74C."));
5193
+ console.log(pc17.dim(" \uD574\uB2F9 \uD56D\uBAA9 \uC5C6\uC74C."));
4969
5194
  } else {
4970
5195
  for (const m of r.migrations) {
4971
- console.log(` ${pc16.cyan(`\u2192 ${m.label}`)}`);
5196
+ console.log(` ${pc17.cyan(`\u2192 ${m.label}`)}`);
4972
5197
  for (const item of m.items) console.log(` \u2022 ${item}`);
4973
5198
  }
4974
5199
  }
4975
5200
  console.log("");
4976
5201
  }
4977
5202
  function printAgentsMd(r) {
4978
- console.log(pc16.bold("\u{1F4DD} AGENTS.md"));
5203
+ console.log(pc17.bold("\u{1F4DD} AGENTS.md"));
4979
5204
  switch (r.agentsMd.status) {
4980
5205
  case "ok":
4981
- console.log(pc16.green(" \u2713 \uAD00\uB9AC \uC601\uC5ED \uCD5C\uC2E0"));
5206
+ console.log(pc17.green(" \u2713 \uAD00\uB9AC \uC601\uC5ED \uCD5C\uC2E0"));
4982
5207
  break;
4983
5208
  case "missing":
4984
- console.log(pc16.dim(" \xB7 \uD30C\uC77C \uC5C6\uC74C \u2014 bstage \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74 init/\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC73C\uB85C \uC0DD\uC131\uD558\uC138\uC694."));
5209
+ console.log(pc17.dim(" \xB7 \uD30C\uC77C \uC5C6\uC74C \u2014 bstage \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74 init/\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC73C\uB85C \uC0DD\uC131\uD558\uC138\uC694."));
4985
5210
  break;
4986
5211
  case "stale":
4987
5212
  if (r.agentsMd.downgrade) {
4988
5213
  console.log(
4989
- pc16.yellow(" ! \uAD00\uB9AC \uC601\uC5ED\uC774 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804") + pc16.dim(
5214
+ pc17.yellow(" ! \uAD00\uB9AC \uC601\uC5ED\uC774 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804") + pc17.dim(
4990
5215
  " \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uAC31\uC2E0\uD558\uBA74 \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uC544\uAC11\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
4991
5216
  )
4992
5217
  );
4993
5218
  break;
4994
5219
  }
4995
5220
  console.log(
4996
- pc16.yellow(" \u2192 \uAD00\uB9AC \uC601\uC5ED\uC774 \uC624\uB798\uB428") + pc16.dim(" \u2014 `bstage ai update`\uB85C \uAC31\uC2E0(\uC790\uC720 \uC601\uC5ED\uC740 \uBCF4\uC874).")
5221
+ pc17.yellow(" \u2192 \uAD00\uB9AC \uC601\uC5ED\uC774 \uC624\uB798\uB428") + pc17.dim(" \u2014 `bstage ai update`\uB85C \uAC31\uC2E0(\uC790\uC720 \uC601\uC5ED\uC740 \uBCF4\uC874).")
4997
5222
  );
4998
5223
  break;
4999
5224
  case "legacy":
5000
5225
  console.log(
5001
- pc16.yellow(" \u2192 \uB808\uAC70\uC2DC \uD3EC\uB9F7(\uAD00\uB9AC \uC601\uC5ED \uB9C8\uCEE4 \uC5C6\uC74C)") + pc16.dim(
5226
+ pc17.yellow(" \u2192 \uB808\uAC70\uC2DC \uD3EC\uB9F7(\uAD00\uB9AC \uC601\uC5ED \uB9C8\uCEE4 \uC5C6\uC74C)") + pc17.dim(
5002
5227
  " \u2014 `bstage ai install`\uB85C \uC2A4\uD0AC\uC744 \uBA3C\uC800 \uC124\uCE58\uD55C \uB4A4, `bstage-migrate` \uC2A4\uD0AC\uB85C reconcile(SDK \uC601\uC5ED \uAD50\uCCB4 + \uC0AC\uC6A9\uC790 \uB0B4\uC6A9 \uBCF4\uC874)."
5003
5228
  )
5004
5229
  );
@@ -5007,29 +5232,29 @@ function printAgentsMd(r) {
5007
5232
  console.log("");
5008
5233
  }
5009
5234
  function printSkills(r) {
5010
- console.log(pc16.bold("\u{1F9E9} \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC (.claude/skills/)"));
5235
+ console.log(pc17.bold("\u{1F9E9} \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC (.claude/skills/)"));
5011
5236
  const skillsNeedWork = r.skills.filter((s) => s.status !== "ok");
5012
5237
  if (r.skillsSkipped) {
5013
5238
  console.log(
5014
- pc16.yellow(" ! sdk\uC640 liquid\uAC00 \uC11E\uC5EC \uC788\uC5B4 \uC2A4\uD0AC \uAC80\uC0AC\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 \uD558\uB098\uB9CC \uB0A8\uACA8 \uC8FC\uC138\uC694.")
5239
+ pc17.yellow(" ! sdk\uC640 liquid\uAC00 \uC11E\uC5EC \uC788\uC5B4 \uC2A4\uD0AC \uAC80\uC0AC\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 \uD558\uB098\uB9CC \uB0A8\uACA8 \uC8FC\uC138\uC694.")
5015
5240
  );
5016
5241
  } else if (skillsNeedWork.length === 0) {
5017
- console.log(pc16.green(" \u2713 \uBAA8\uB4E0 \uC2A4\uD0AC \uCD5C\uC2E0"));
5242
+ console.log(pc17.green(" \u2713 \uBAA8\uB4E0 \uC2A4\uD0AC \uCD5C\uC2E0"));
5018
5243
  } else {
5019
5244
  for (const s of r.skills) {
5020
- if (s.status === "ok") console.log(` ${pc16.green("\u2713")} ${s.name}`);
5245
+ if (s.status === "ok") console.log(` ${pc17.green("\u2713")} ${s.name}`);
5021
5246
  else if (s.status === "missing")
5022
- console.log(` ${pc16.yellow("\u2192")} ${s.name.padEnd(16)} ${pc16.yellow("\uBBF8\uC124\uCE58")}`);
5247
+ console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uBBF8\uC124\uCE58")}`);
5023
5248
  else if (s.status === "newer")
5024
5249
  console.log(
5025
- ` ${pc16.yellow("!")} ${s.name.padEnd(16)} ${pc16.yellow("\uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804")}` + pc16.dim(
5250
+ ` ${pc17.yellow("!")} ${s.name.padEnd(16)} ${pc17.yellow("\uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804")}` + pc17.dim(
5026
5251
  " \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uB9BD\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
5027
5252
  )
5028
5253
  );
5029
- else console.log(` ${pc16.yellow("\u2192")} ${s.name.padEnd(16)} ${pc16.yellow("\uAD6C\uBC84\uC804/\uC218\uC815\uB428")}`);
5254
+ else console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uAD6C\uBC84\uC804/\uC218\uC815\uB428")}`);
5030
5255
  }
5031
5256
  console.log(
5032
- pc16.dim(
5257
+ pc17.dim(
5033
5258
  " \uC544\uB798\uC5D0\uC11C \uC790\uB3D9 \uB3D9\uAE30\uD654\uD569\uB2C8\uB2E4 \u2014 bstage-* \uC2A4\uD0AC\uB9CC \uB36E\uC5B4\uC4F0\uBA70, \uADF8 \uC678 \uC0AC\uC6A9\uC790 \uC2A4\uD0AC\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
5034
5259
  )
5035
5260
  );
@@ -5039,36 +5264,43 @@ function printSkills(r) {
5039
5264
  function printNextSteps(r) {
5040
5265
  const agentsNeedsWork = r.agentsMd.status === "legacy" || r.agentsMd.status === "stale";
5041
5266
  const liquidBroken = (r.liquid?.issues ?? []).some((i) => i.level === "error");
5042
- const hasWork = r.versions.some((v) => v.outdated) || r.migrations.length > 0 || agentsNeedsWork || liquidBroken;
5267
+ const portalBroken = portalNeedsWork(r.portal);
5268
+ const migrationWork = r.versions.some((v) => v.outdated) || r.migrations.length > 0 || agentsNeedsWork || liquidBroken;
5269
+ const hasWork = migrationWork || portalBroken;
5270
+ if (portalBroken) {
5271
+ console.log(pc17.yellow("\uC704 \uD3EC\uD138 \uC9C4\uB2E8 \uD56D\uBAA9\uC744 \uBA3C\uC800 \uD574\uACB0\uD558\uC138\uC694 \u2014 \uAC01 \uD56D\uBAA9\uC758 \uC870\uCE58\uB97C \uB530\uB974\uBA74 \uB429\uB2C8\uB2E4."));
5272
+ }
5043
5273
  if (liquidBroken) {
5044
5274
  console.log(
5045
- pc16.yellow("\uC704 liquid \uAC80\uC99D \uC624\uB958\uB97C \uBA3C\uC800 \uACE0\uCE58\uC138\uC694 \u2014 \uADF8\uB300\uB85C push\uD558\uBA74 \uD3EC\uD138 \uBE4C\uB4DC\uAC00 \uB9C9\uD799\uB2C8\uB2E4.")
5275
+ pc17.yellow("\uC704 liquid \uAC80\uC99D \uC624\uB958\uB97C \uBA3C\uC800 \uACE0\uCE58\uC138\uC694 \u2014 \uADF8\uB300\uB85C push\uD558\uBA74 \uD3EC\uD138 \uBE4C\uB4DC\uAC00 \uB9C9\uD799\uB2C8\uB2E4.")
5046
5276
  );
5047
5277
  }
5048
- if (hasWork) {
5278
+ if (migrationWork) {
5049
5279
  console.log(
5050
- pc16.dim(
5280
+ pc17.dim(
5051
5281
  "\uB2E4\uC74C \uB2E8\uACC4: \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC2A4\uD0AC\uC744 \uC2E4\uD589\uD574 \uC704 \uD56D\uBAA9\uC744 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uB9DE\uCDB0 \uC801\uC6A9\uD558\uC138\uC694.\n \uC0C1\uC138 \uAC00\uC774\uB4DC: SDK \uBB38\uC11C\uC758 MIGRATION.md (\uC704 \uD56D\uBAA9\uBCC4 \uC801\uC6A9 \uC808\uCC28)"
5052
5282
  )
5053
5283
  );
5054
- } else {
5055
- console.log(pc16.green("\u2713 \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4."));
5284
+ } else if (!hasWork) {
5285
+ console.log(pc17.green("\u2713 \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4."));
5056
5286
  if (r.files.some((f) => !f.present)) {
5057
- console.log(pc16.dim(" (\uC704 init \uAE30\uBCF8 \uD30C\uC77C \uCC28\uC774\uB294 \uC120\uD0DD \uC0AC\uD56D\uC785\uB2C8\uB2E4.)"));
5287
+ console.log(pc17.dim(" (\uC704 init \uAE30\uBCF8 \uD30C\uC77C \uCC28\uC774\uB294 \uC120\uD0DD \uC0AC\uD56D\uC785\uB2C8\uB2E4.)"));
5058
5288
  }
5059
5289
  if (r.recommendedDeps.some((d) => !d.declared)) {
5060
- console.log(pc16.dim(" (\uC704 \uAD8C\uC7A5 \uC758\uC874\uC131\uC740 \uBC84\uC804\uACFC \uBB34\uAD00\uD569\uB2C8\uB2E4 \u2014 \uC4F8 \uAC70\uBA74 \uB530\uB85C \uCD94\uAC00\uD558\uC138\uC694.)"));
5290
+ console.log(pc17.dim(" (\uC704 \uAD8C\uC7A5 \uC758\uC874\uC131\uC740 \uBC84\uC804\uACFC \uBB34\uAD00\uD569\uB2C8\uB2E4 \u2014 \uC4F8 \uAC70\uBA74 \uB530\uB85C \uCD94\uAC00\uD558\uC138\uC694.)"));
5061
5291
  }
5062
5292
  }
5063
5293
  console.log("");
5064
5294
  }
5065
5295
  function printReport(r) {
5066
5296
  console.log("");
5067
- console.log(`${pc16.cyan(pc16.bold("bstage doctor"))} ${pc16.dim(`\u2014 ${r.project ?? "(\uC774\uB984 \uC5C6\uC74C)"}`)}`);
5297
+ console.log(`${pc17.cyan(pc17.bold("bstage doctor"))} ${pc17.dim(`\u2014 ${r.project ?? "(\uC774\uB984 \uC5C6\uC74C)"}`)}`);
5068
5298
  console.log("");
5069
5299
  if (!r.isBstageProject) {
5070
- console.log(pc16.yellow("\uC774 \uB514\uB809\uD1A0\uB9AC\uB294 bstage \uD15C\uD50C\uB9BF \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC2B5\uB2C8\uB2E4."));
5071
- console.log(pc16.dim(" package.json\uC5D0 @bstage-sdk/* \uC758\uC874\uC131\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
5300
+ console.log(pc17.yellow("\uC774 \uB514\uB809\uD1A0\uB9AC\uB294 bstage \uD15C\uD50C\uB9BF \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC2B5\uB2C8\uB2E4."));
5301
+ console.log(pc17.dim(" package.json\uC5D0 @bstage-sdk/* \uC758\uC874\uC131\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
5302
+ console.log("");
5303
+ printPortal(r.portal);
5072
5304
  return;
5073
5305
  }
5074
5306
  printVersions(r);
@@ -5081,15 +5313,24 @@ function printReport(r) {
5081
5313
  printMigrations(r);
5082
5314
  printAgentsMd(r);
5083
5315
  printSkills(r);
5316
+ printPortal(r.portal);
5084
5317
  printNextSteps(r);
5085
5318
  }
5086
5319
 
5087
5320
  // src/commands/doctor.ts
5088
- async function doctorCommand(options) {
5089
- const root = process.cwd();
5090
- const report2 = await diagnose2(root);
5321
+ async function doctorCommand(options, deps = {}) {
5322
+ const root = deps.cwd ?? process.cwd();
5323
+ const [local, portal] = await Promise.all([
5324
+ diagnose2(root),
5325
+ diagnosePortal(
5326
+ { placement: options.placement },
5327
+ { cwd: root, env: deps.env, fetch: deps.fetch }
5328
+ )
5329
+ ]);
5330
+ const report2 = { ...local, portal };
5331
+ if (portalHasErrorFinding(portal)) process.exitCode = ExitCode.FAILURE;
5091
5332
  if (options.json) {
5092
- console.log(JSON.stringify(report2, null, 2));
5333
+ printJson(report2);
5093
5334
  return;
5094
5335
  }
5095
5336
  printReport(report2);
@@ -5098,7 +5339,7 @@ async function doctorCommand(options) {
5098
5339
 
5099
5340
  // src/commands/link.ts
5100
5341
  import * as p4 from "@clack/prompts";
5101
- import pc17 from "picocolors";
5342
+ import pc18 from "picocolors";
5102
5343
  var clackSelect = async (message, items) => {
5103
5344
  const options = items.map((i) => ({
5104
5345
  value: i.value,
@@ -5210,15 +5451,15 @@ function printLinked(link, repoLabel, repoFromOrigin, json) {
5210
5451
  return;
5211
5452
  }
5212
5453
  if (repoFromOrigin) {
5213
- console.log(pc17.dim(` git origin(${repoLabel})\uACFC \uC77C\uCE58\uD558\uB294 \uB808\uD3EC\uB97C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4.`));
5454
+ console.log(pc18.dim(` git origin(${repoLabel})\uACFC \uC77C\uCE58\uD558\uB294 \uB808\uD3EC\uB97C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4.`));
5214
5455
  }
5215
5456
  console.log(
5216
- pc17.green(
5457
+ pc18.green(
5217
5458
  `\u2713 \uC5F0\uACB0\uD588\uC2B5\uB2C8\uB2E4: ${link.organizationId} / ${link.spaceId} / ${repoLabel} [${link.surface}]`
5218
5459
  )
5219
5460
  );
5220
5461
  console.log(
5221
- pc17.dim(
5462
+ pc18.dim(
5222
5463
  " .bstage/project.json \uC5D0 \uC800\uC7A5 (gitignore \uB300\uC0C1). CI\uC5D0\uC11C\uB294 BSTAGE_ORG\xB7BSTAGE_SPACE\xB7BSTAGE_REPO\xB7BSTAGE_SURFACE\xB7BSTAGE_PORTAL_URL \uD658\uACBD\uBCC0\uC218\uB97C \uC4F0\uC138\uC694."
5223
5464
  )
5224
5465
  );
@@ -5273,7 +5514,7 @@ async function linkCommand(options, deps = {}) {
5273
5514
  }
5274
5515
 
5275
5516
  // src/commands/list.ts
5276
- import pc18 from "picocolors";
5517
+ import pc19 from "picocolors";
5277
5518
 
5278
5519
  // src/portal/buildRepo.ts
5279
5520
  function buildMatchesRepo(b, repo) {
@@ -5305,10 +5546,10 @@ function artifactKinds(build) {
5305
5546
  function renderList(placements, builds, repo) {
5306
5547
  const mine = placements.filter((p5) => p5.stageRepoId === repo.id);
5307
5548
  const lines = [];
5308
- lines.push(pc18.bold("\uBC30\uCE58"));
5549
+ lines.push(pc19.bold("\uBC30\uCE58"));
5309
5550
  if (mine.length === 0) {
5310
5551
  lines.push(
5311
- pc18.yellow(
5552
+ pc19.yellow(
5312
5553
  " \uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. bstage placement create \uB85C \uD398\uC774\uC9C0 \uBC30\uCE58\uB97C \uBA3C\uC800 \uB9CC\uB4DC\uC138\uC694."
5313
5554
  )
5314
5555
  );
@@ -5327,10 +5568,10 @@ function renderList(placements, builds, repo) {
5327
5568
  );
5328
5569
  }
5329
5570
  lines.push("");
5330
- lines.push(pc18.bold("\uCD5C\uADFC \uBE4C\uB4DC"));
5571
+ lines.push(pc19.bold("\uCD5C\uADFC \uBE4C\uB4DC"));
5331
5572
  const recent = builds.filter((b) => buildMatchesRepo(b, repo));
5332
5573
  lines.push(
5333
- recent.length === 0 ? pc18.dim(" \uBE4C\uB4DC \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.") : table([
5574
+ recent.length === 0 ? pc19.dim(" \uBE4C\uB4DC \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.") : table([
5334
5575
  ["\uBE4C\uB4DC", "\uC0C1\uD0DC", "\uC885\uB958", "\uCEE4\uBC0B", "\uC694\uCCAD \uC2DC\uAC01"],
5335
5576
  ...recent.map((b) => [
5336
5577
  b.id,
@@ -5344,7 +5585,7 @@ function renderList(placements, builds, repo) {
5344
5585
  if (mine.length === 0) {
5345
5586
  lines.push("");
5346
5587
  lines.push(
5347
- pc18.yellow(
5588
+ pc19.yellow(
5348
5589
  "\uC774 \uB808\uD3EC\uC5D0 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C: bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984> [--path /\uACBD\uB85C] \u2192 bstage deploy. \uC704\uC82F(\uC2AC\uB86F) \uBC30\uCE58\uB294 \uD3EC\uD138 \uD654\uBA74(\uC2A4\uD14C\uC774\uC9C0 > \uD398\uC774\uC9C0 > \uC0C8 \uD398\uC774\uC9C0)\uC5D0\uC11C \uB9CC\uB4ED\uB2C8\uB2E4. (bstage-deploy \uC2A4\uD0AC \uCC38\uC870)"
5349
5590
  )
5350
5591
  );
@@ -5370,12 +5611,12 @@ async function listCommand(options, deps = {}) {
5370
5611
  printJson({ link, placements: mine, builds: myBuilds });
5371
5612
  return;
5372
5613
  }
5373
- out(pc18.dim(`${link.organizationId} / ${link.spaceId} [${link.surface}]`));
5614
+ out(pc19.dim(`${link.organizationId} / ${link.spaceId} [${link.surface}]`));
5374
5615
  out(renderList(placements, builds, repo));
5375
5616
  }
5376
5617
 
5377
5618
  // src/commands/logs.ts
5378
- import pc19 from "picocolors";
5619
+ import pc20 from "picocolors";
5379
5620
  function statusLine(build) {
5380
5621
  return `[bstage] \uBE4C\uB4DC ${build.id} \xB7 ${build.status}${build.failureReason ? ` \xB7 ${build.failureReason}` : ""}`;
5381
5622
  }
@@ -5389,7 +5630,7 @@ async function latestBuildId(ctx) {
5389
5630
  return latest.id;
5390
5631
  }
5391
5632
  function logSink(json) {
5392
- return json ? (delta) => void process.stderr.write(pc19.dim(delta)) : (delta) => void process.stdout.write(delta);
5633
+ return json ? (delta) => void process.stderr.write(pc20.dim(delta)) : (delta) => void process.stdout.write(delta);
5393
5634
  }
5394
5635
  async function logsCommand(buildId, options, deps = {}) {
5395
5636
  const out = deps.out ?? ((s) => void process.stdout.write(s));
@@ -5413,17 +5654,17 @@ async function report(client, org, space, id, build, options, out, following) {
5413
5654
  return;
5414
5655
  }
5415
5656
  if (following) {
5416
- console.error(pc19.dim(`
5657
+ console.error(pc20.dim(`
5417
5658
  ${statusLine(build)}`));
5418
5659
  return;
5419
5660
  }
5420
5661
  const log3 = await client.getBuildLog(org, space, id);
5421
5662
  out(log3.endsWith("\n") ? log3 : log3 + "\n");
5422
- console.error(pc19.dim(statusLine(build)));
5663
+ console.error(pc20.dim(statusLine(build)));
5423
5664
  }
5424
5665
 
5425
5666
  // src/commands/placement.ts
5426
- import pc20 from "picocolors";
5667
+ import pc21 from "picocolors";
5427
5668
 
5428
5669
  // src/portal/pagePlacement.ts
5429
5670
  function normalizePagePath(raw) {
@@ -5494,7 +5735,7 @@ async function ensureBuildWithArtifact(ctx, repo, template, options, deps) {
5494
5735
  const latest = options.build ? void 0 : latestSucceeded(await ctx.client.listBuilds(org, space, RECENT_BUILDS), repo);
5495
5736
  const found = latest && resolvePageArtifact(latest, template, surface);
5496
5737
  if (latest && found) return { build: latest, artifact: found };
5497
- if (!options.json) console.error(pc20.dim(`[bstage] ${buildReason(latest, options)}`));
5738
+ if (!options.json) console.error(pc21.dim(`[bstage] ${buildReason(latest, options)}`));
5498
5739
  if (!options.skipGitCheck) await precheckGit(deps, repo.defaultBranch);
5499
5740
  const created = await createAndAnnounceBuild(ctx, options.json);
5500
5741
  const done = await waitForCompletedBuild(ctx, deps, created, options.json);
@@ -5525,9 +5766,9 @@ function reportExisting(owner, resolved, repoId, options, out) {
5525
5766
  return;
5526
5767
  }
5527
5768
  out(
5528
- `${pc20.green("\u2713")} ${label} \uC5D0 \uC774 \uB808\uD3EC\uC758 '${resolved.artifact.name}' \uBC30\uCE58\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4 (${owner.id}).`
5769
+ `${pc21.green("\u2713")} ${label} \uC5D0 \uC774 \uB808\uD3EC\uC758 '${resolved.artifact.name}' \uBC30\uCE58\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4 (${owner.id}).`
5529
5770
  );
5530
- out(pc20.dim(` \uB2E4\uC74C: ${nextCommand(label)}`));
5771
+ out(pc21.dim(` \uB2E4\uC74C: ${nextCommand(label)}`));
5531
5772
  return;
5532
5773
  }
5533
5774
  const who = `\uBC30\uCE58 ${owner.id}, \uC0B0\uCD9C\uBB3C ${owner.artifact ?? "-"}${owner.stageRepoId === repoId ? "" : ", \uB2E4\uB978 \uB808\uD3EC"}`;
@@ -5601,9 +5842,9 @@ function reportCreated(created, resolved, options, out) {
5601
5842
  return;
5602
5843
  }
5603
5844
  out(
5604
- `${pc20.green("\u2713")} \uBC30\uCE58\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${label} \u2190 ${resolved.artifact.name} (${created.id}, \uBE4C\uB4DC ${resolved.build.id} \xB7 ${shortSha(resolved.build.commitSha)})`
5845
+ `${pc21.green("\u2713")} \uBC30\uCE58\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${label} \u2190 ${resolved.artifact.name} (${created.id}, \uBE4C\uB4DC ${resolved.build.id} \xB7 ${shortSha(resolved.build.commitSha)})`
5605
5846
  );
5606
- out(pc20.dim(` \uC544\uC9C1 \uB77C\uC774\uBE0C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uB2E4\uC74C: ${nextCommand(label)}`));
5847
+ out(pc21.dim(` \uC544\uC9C1 \uB77C\uC774\uBE0C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uB2E4\uC74C: ${nextCommand(label)}`));
5607
5848
  }
5608
5849
  async function placementCreateCommand(options, deps = {}) {
5609
5850
  if (options.json && !options.yes) {
@@ -5656,7 +5897,7 @@ async function placementCreateCommand(options, deps = {}) {
5656
5897
 
5657
5898
  // src/commands/login.ts
5658
5899
  import { hostname as osHostname } from "os";
5659
- import pc21 from "picocolors";
5900
+ import pc22 from "picocolors";
5660
5901
 
5661
5902
  // src/portal/openBrowser.ts
5662
5903
  import { execFile as execFile2 } from "child_process";
@@ -5724,7 +5965,7 @@ async function loginWithToken(portalUrl, token, options, deps, env2) {
5724
5965
  return;
5725
5966
  }
5726
5967
  console.log(
5727
- pc21.green(`\u2713 ${portalUrl} \uC5D0 ${me.user.email} \uB85C \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4 (\uC870\uC9C1 ${organizationId}).`)
5968
+ pc22.green(`\u2713 ${portalUrl} \uC5D0 ${me.user.email} \uB85C \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4 (\uC870\uC9C1 ${organizationId}).`)
5728
5969
  );
5729
5970
  }
5730
5971
  function nextIntervalOnSlowDown(interval, retryAfterSec) {
@@ -5735,11 +5976,11 @@ function printDeviceCodePrompt(userCode, verificationUriComplete, expiresIn) {
5735
5976
  console.log("");
5736
5977
  console.log(` \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC544\uB798 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uACE0 \uC2B9\uC778\uD558\uC138\uC694.`);
5737
5978
  console.log("");
5738
- console.log(` \uCF54\uB4DC ${pc21.bold(userCode)}`);
5739
- console.log(` \uC8FC\uC18C ${pc21.underline(verificationUriComplete)}`);
5979
+ console.log(` \uCF54\uB4DC ${pc22.bold(userCode)}`);
5980
+ console.log(` \uC8FC\uC18C ${pc22.underline(verificationUriComplete)}`);
5740
5981
  console.log("");
5741
5982
  console.log(
5742
- pc21.dim(
5983
+ pc22.dim(
5743
5984
  ` \uD130\uBBF8\uB110\uC758 \uCF54\uB4DC\uC640 \uBE0C\uB77C\uC6B0\uC800\uC758 \uCF54\uB4DC\uAC00 \uAC19\uC740\uC9C0 \uAF2D \uD655\uC778\uD558\uC138\uC694. ${Math.round(expiresIn / 60)}\uBD84 \uC548\uC5D0 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC73C\uBA74 \uB9CC\uB8CC\uB429\uB2C8\uB2E4.`
5744
5985
  )
5745
5986
  );
@@ -5780,7 +6021,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
5780
6021
  if (!sameOrigin(portalUrl, verificationUriComplete)) {
5781
6022
  if (!options.json) {
5782
6023
  console.log(
5783
- pc21.yellow(
6024
+ pc22.yellow(
5784
6025
  " \uC2B9\uC778 \uC8FC\uC18C\uAC00 \uD3EC\uD138\uACFC \uB2E4\uB978 \uC0AC\uC774\uD2B8\uC785\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uC8FC\uC18C\uB97C \uD655\uC778\uD55C \uB4A4 \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."
5785
6026
  )
5786
6027
  );
@@ -5789,7 +6030,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
5789
6030
  }
5790
6031
  const opened = await (deps.openBrowser ?? openBrowser)(verificationUriComplete);
5791
6032
  if (!opened && !options.json) {
5792
- console.log(pc21.dim(" \uBE0C\uB77C\uC6B0\uC800\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."));
6033
+ console.log(pc22.dim(" \uBE0C\uB77C\uC6B0\uC800\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."));
5793
6034
  }
5794
6035
  }
5795
6036
  function sameOrigin(a, b) {
@@ -5854,13 +6095,13 @@ function reportIssued(portalUrl, issued, organizationId, json) {
5854
6095
  });
5855
6096
  return;
5856
6097
  }
5857
- console.log(pc21.green(`\u2713 ${portalUrl} \uC5D0 \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4.`));
6098
+ console.log(pc22.green(`\u2713 ${portalUrl} \uC5D0 \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4.`));
5858
6099
  console.log(
5859
- pc21.dim(
6100
+ pc22.dim(
5860
6101
  ` \uC870\uC9C1 ${orgLabel(organizationId ?? UNKNOWN_ORG)} \xB7 \uD1A0\uD070 ${issued.prefix}\u2026 \xB7 \uB4F1\uAE09 ${issued.permission} \xB7 ${scopeLabel(issued.allSpaces, issued.spaceIds)} \xB7 \uB9CC\uB8CC ${issued.expiresAt.slice(0, 10)}`
5861
6102
  )
5862
6103
  );
5863
- console.log(pc21.dim(" \uB2E4\uC74C: \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C bstage link"));
6104
+ console.log(pc22.dim(" \uB2E4\uC74C: \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C bstage link"));
5864
6105
  }
5865
6106
  async function loginCommand(options, deps = {}) {
5866
6107
  const env2 = deps.env ?? process.env;
@@ -5877,7 +6118,7 @@ async function loginCommand(options, deps = {}) {
5877
6118
  }
5878
6119
 
5879
6120
  // src/commands/logout.ts
5880
- import pc22 from "picocolors";
6121
+ import pc23 from "picocolors";
5881
6122
  async function logoutCommand(options, deps = {}) {
5882
6123
  const cwd = deps.cwd ?? process.cwd();
5883
6124
  const env2 = deps.env ?? process.env;
@@ -5891,16 +6132,16 @@ async function logoutCommand(options, deps = {}) {
5891
6132
  const removed = await deleteCredential(portalUrl, options.org, env2);
5892
6133
  if (removed.length === 0) {
5893
6134
  const scope = options.org ? `\uC870\uC9C1 ${options.org} \uC758 ` : "";
5894
- console.log(pc22.yellow(`${portalUrl} \uC5D0 \uC800\uC7A5\uB41C ${scope}\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`));
6135
+ console.log(pc23.yellow(`${portalUrl} \uC5D0 \uC800\uC7A5\uB41C ${scope}\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`));
5895
6136
  } else {
5896
6137
  const orgs = removed.map(orgLabel).join(", ");
5897
- console.log(pc22.green(`\u2713 ${portalUrl} \uC790\uACA9\uC99D\uBA85\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC870\uC9C1 ${orgs}`));
6138
+ console.log(pc23.green(`\u2713 ${portalUrl} \uC790\uACA9\uC99D\uBA85\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC870\uC9C1 ${orgs}`));
5898
6139
  }
5899
- console.log(pc22.dim(" \uD3EC\uD138 \uD654\uBA74\uC5D0\uC11C \uD1A0\uD070 \uC790\uCCB4\uB97C \uD3D0\uAE30\uD558\uBA74 \uB2E4\uB978 \uAE30\uAE30\uC5D0\uC11C\uB3C4 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4."));
6140
+ console.log(pc23.dim(" \uD3EC\uD138 \uD654\uBA74\uC5D0\uC11C \uD1A0\uD070 \uC790\uCCB4\uB97C \uD3D0\uAE30\uD558\uBA74 \uB2E4\uB978 \uAE30\uAE30\uC5D0\uC11C\uB3C4 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4."));
5900
6141
  }
5901
6142
 
5902
6143
  // src/commands/publish.ts
5903
- import pc23 from "picocolors";
6144
+ import pc24 from "picocolors";
5904
6145
  function parseOnOff(v) {
5905
6146
  const s = v.toLowerCase();
5906
6147
  if (s === "on") return true;
@@ -5939,13 +6180,13 @@ async function togglePlacement(ctx, p5, enabled) {
5939
6180
  }
5940
6181
  function printResults2(results, enabled, out) {
5941
6182
  for (const r of results) {
5942
- const mark = r.status === "failed" ? pc23.red("\u2717") : r.status === "conflict" ? pc23.yellow("!") : pc23.green("\u2713");
6183
+ const mark = r.status === "failed" ? pc24.red("\u2717") : r.status === "conflict" ? pc24.yellow("!") : pc24.green("\u2713");
5943
6184
  const stateLabel = r.status === "unchanged" ? "\uBCC0\uACBD \uC5C6\uC74C" : `\uAC8C\uC2DC ${r.enabled ? "on" : "off"}`;
5944
- const suffix = r.message && r.status !== "unchanged" ? pc23.dim(` ${r.message}`) : "";
6185
+ const suffix = r.message && r.status !== "unchanged" ? pc24.dim(` ${r.message}`) : "";
5945
6186
  out(`${mark} ${r.label} ${stateLabel}${suffix}`);
5946
6187
  }
5947
6188
  if (!enabled) {
5948
- out(pc23.dim(" \uB77C\uC774\uBE0C \uBC84\uC804 \uD3EC\uC778\uD130\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uCF1C\uBA74 \uAC19\uC740 \uBE4C\uB4DC\uAC00 \uC989\uC2DC \uC11C\uBE59\uB429\uB2C8\uB2E4."));
6189
+ out(pc24.dim(" \uB77C\uC774\uBE0C \uBC84\uC804 \uD3EC\uC778\uD130\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uCF1C\uBA74 \uAC19\uC740 \uBE4C\uB4DC\uAC00 \uC989\uC2DC \uC11C\uBE59\uB429\uB2C8\uB2E4."));
5949
6190
  }
5950
6191
  }
5951
6192
  function reportOutcome2(results, options, enabled, out) {
@@ -5985,7 +6226,7 @@ async function publishCommand(state, options, deps = {}) {
5985
6226
  }
5986
6227
 
5987
6228
  // src/commands/rollback.ts
5988
- import pc24 from "picocolors";
6229
+ import pc25 from "picocolors";
5989
6230
  function pickRollbackTarget(builds, repo, currentLive) {
5990
6231
  const ok = builds.filter((b) => buildMatchesRepo(b, repo) && b.status === "SUCCEEDED").sort((a, b) => a.requestedAt < b.requestedAt ? 1 : -1);
5991
6232
  if (!currentLive) return ok[0] ?? null;
@@ -6070,16 +6311,16 @@ async function rollbackCommand(buildId, options, deps = {}) {
6070
6311
  reportOutcome(results, options, out);
6071
6312
  if (!options.json) {
6072
6313
  out(
6073
- pc24.dim(" \uB418\uB3CC\uB9B0 \uB4A4\uC5D0\uB3C4 \uCD5C\uC2E0 \uBE4C\uB4DC\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2014 bstage deploy \uB85C \uB2E4\uC2DC \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.")
6314
+ pc25.dim(" \uB418\uB3CC\uB9B0 \uB4A4\uC5D0\uB3C4 \uCD5C\uC2E0 \uBE4C\uB4DC\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2014 bstage deploy \uB85C \uB2E4\uC2DC \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.")
6074
6315
  );
6075
6316
  }
6076
6317
  }
6077
6318
 
6078
6319
  // src/commands/skills.ts
6079
- import pc25 from "picocolors";
6320
+ import pc26 from "picocolors";
6080
6321
  async function skillsInstallCommand(options) {
6081
6322
  console.warn(
6082
- pc25.yellow(
6323
+ pc26.yellow(
6083
6324
  "bstage skills install\uC740 bstage ai install\uB85C \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C \uB9B4\uB9AC\uC988\uC5D0\uC11C \uC81C\uAC70\uB429\uB2C8\uB2E4."
6084
6325
  )
6085
6326
  );
@@ -6089,7 +6330,7 @@ async function skillsInstallCommand(options) {
6089
6330
  // src/commands/docs.ts
6090
6331
  import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
6091
6332
  import { join as join16 } from "path";
6092
- import pc26 from "picocolors";
6333
+ import pc27 from "picocolors";
6093
6334
  var DOC_ORDER = [
6094
6335
  ["GETTING_STARTED.md", "\uBE60\uB978 \uC2DC\uC791 \uAC00\uC774\uB4DC"],
6095
6336
  ["API_REFERENCE.md", "createTemplate, hooks, BstageClient, PlatformBridge API"],
@@ -6109,10 +6350,10 @@ var CORE_DOCS_SEGMENTS = ["node_modules", "@bstage-sdk", "core", "docs"];
6109
6350
  async function docsCommand() {
6110
6351
  const docsDir = join16(process.cwd(), ...CORE_DOCS_SEGMENTS);
6111
6352
  if (!existsSync8(docsDir)) {
6112
- console.log(pc26.yellow("SDK \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
6113
- console.log(pc26.dim(" @bstage-sdk/core\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 (npm install \uD6C4 \uC7AC\uC2DC\uB3C4)."));
6353
+ console.log(pc27.yellow("SDK \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
6354
+ console.log(pc27.dim(" @bstage-sdk/core\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 (npm install \uD6C4 \uC7AC\uC2DC\uB3C4)."));
6114
6355
  console.log(
6115
- pc26.dim(
6356
+ pc27.dim(
6116
6357
  " SDK \uC758\uC874\uC774 \uC5C6\uB294 \uB808\uD3EC\uC5D0\uB294 \uC774 \uACBD\uB85C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 liquid \uADDC\uC57D\xB7\uB370\uC774\uD130\uB294 bstage-liquid \uC2A4\uD0AC\uC744 \uBCF4\uC138\uC694."
6117
6358
  )
6118
6359
  );
@@ -6124,24 +6365,24 @@ async function docsCommand() {
6124
6365
  const known = new Set(DOC_ORDER.map(([f]) => f));
6125
6366
  const extras = [...present].filter((f) => !known.has(f)).sort();
6126
6367
  console.log("");
6127
- console.log(pc26.bold("bstage SDK \uBB38\uC11C"));
6128
- console.log(pc26.dim(` ${docsDir}`));
6368
+ console.log(pc27.bold("bstage SDK \uBB38\uC11C"));
6369
+ console.log(pc27.dim(` ${docsDir}`));
6129
6370
  console.log("");
6130
6371
  for (const [file3, desc] of ordered) {
6131
- console.log(` ${pc26.cyan(file3.padEnd(22))} ${pc26.dim(desc)}`);
6372
+ console.log(` ${pc27.cyan(file3.padEnd(22))} ${pc27.dim(desc)}`);
6132
6373
  }
6133
6374
  for (const file3 of extras) {
6134
- console.log(` ${pc26.cyan(file3.padEnd(22))}`);
6375
+ console.log(` ${pc27.cyan(file3.padEnd(22))}`);
6135
6376
  }
6136
6377
  console.log("");
6137
6378
  console.log(
6138
- pc26.dim("\uD30C\uC77C\uC744 \uC5F4\uC5B4 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uD655\uC778\uD558\uC138\uC694. \uCEE4\uB9E8\uB4DC \uB3C4\uC6C0\uB9D0\uC740 `bstage <command> --help`.")
6379
+ pc27.dim("\uD30C\uC77C\uC744 \uC5F4\uC5B4 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uD655\uC778\uD558\uC138\uC694. \uCEE4\uB9E8\uB4DC \uB3C4\uC6C0\uB9D0\uC740 `bstage <command> --help`.")
6139
6380
  );
6140
6381
  console.log("");
6141
6382
  }
6142
6383
 
6143
6384
  // src/commands/whoami.ts
6144
- import pc27 from "picocolors";
6385
+ import pc28 from "picocolors";
6145
6386
  function jsonEntry(c, active) {
6146
6387
  return {
6147
6388
  organizationId: c.organizationId,
@@ -6155,21 +6396,21 @@ function jsonEntry(c, active) {
6155
6396
  }
6156
6397
  function printCredentials(stored, activeOrg) {
6157
6398
  if (stored.length === 0) return;
6158
- console.log(pc27.dim("\uC800\uC7A5\uB41C \uD1A0\uD070"));
6399
+ console.log(pc28.dim("\uC800\uC7A5\uB41C \uD1A0\uD070"));
6159
6400
  const rows = stored.map((c) => [
6160
6401
  ` \uC870\uC9C1 ${orgLabel(c.organizationId)}`,
6161
6402
  `\uB4F1\uAE09 ${c.permission ?? "-"}`,
6162
6403
  scopeLabel(c.allSpaces, c.spaceIds),
6163
6404
  `\uB9CC\uB8CC ${c.expiresAt ? c.expiresAt.slice(0, 10) : "-"}`,
6164
- c.organizationId === activeOrg ? pc27.dim("(\uC0AC\uC6A9 \uC911)") : ""
6405
+ c.organizationId === activeOrg ? pc28.dim("(\uC0AC\uC6A9 \uC911)") : ""
6165
6406
  ]);
6166
6407
  console.log(table(rows));
6167
6408
  }
6168
6409
  function printMe(me, portalUrl) {
6169
- console.log(`${pc27.bold(me.user.email)} ${pc27.dim(portalUrl)}`);
6410
+ console.log(`${pc28.bold(me.user.email)} ${pc28.dim(portalUrl)}`);
6170
6411
  for (const m of me.memberships) {
6171
6412
  const stages = Object.entries(m.stageRoles ?? {}).map(([s, r]) => `${s}:${r}`).join(", ");
6172
- console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${pc27.dim(stages)}`);
6413
+ console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${pc28.dim(stages)}`);
6173
6414
  }
6174
6415
  }
6175
6416
  async function whoamiCommand(options, deps = {}) {
@@ -6225,10 +6466,10 @@ function reportStoredOnly(portalUrl, stored, json) {
6225
6466
  });
6226
6467
  return;
6227
6468
  }
6228
- console.log(pc27.dim(portalUrl));
6469
+ console.log(pc28.dim(portalUrl));
6229
6470
  printCredentials(stored);
6230
6471
  console.log(
6231
- pc27.yellow(" \uC5EC\uB7EC \uC870\uC9C1\uC758 \uD1A0\uD070\uC774 \uC788\uC2B5\uB2C8\uB2E4 \u2014 --org <id> \uB85C \uC870\uC9C1\uC744 \uC9C0\uC815\uD558\uBA74 \uACC4\uC815 \uC815\uBCF4\uB3C4 \uBD05\uB2C8\uB2E4.")
6472
+ pc28.yellow(" \uC5EC\uB7EC \uC870\uC9C1\uC758 \uD1A0\uD070\uC774 \uC788\uC2B5\uB2C8\uB2E4 \u2014 --org <id> \uB85C \uC870\uC9C1\uC744 \uC9C0\uC815\uD558\uBA74 \uACC4\uC815 \uC815\uBCF4\uB3C4 \uBD05\uB2C8\uB2E4.")
6232
6473
  );
6233
6474
  }
6234
6475
 
@@ -6248,8 +6489,11 @@ program.command("build").description(
6248
6489
  ).option("--json", "\uAC80\uC99D \uACB0\uACFC\xB7\uC0B0\uCD9C\uBB3C \uC694\uC57D\uC744 JSON\uC73C\uB85C \uCD9C\uB825 (liquid\xB7\uD63C\uD569 \uB808\uD3EC)").action((options) => buildCommand(options));
6249
6490
  program.command("docs").description("\uC124\uCE58\uB41C SDK \uBB38\uC11C \uBAA9\uB85D\xB7\uACBD\uB85C \uCD9C\uB825").action(docsCommand);
6250
6491
  program.command("doctor").description(
6251
- "SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
6252
- ).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").action(doctorCommand);
6492
+ "SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 + \uD3EC\uD138 \uBC30\uCE58 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
6493
+ ).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").option(
6494
+ "--placement <target>",
6495
+ "\uD3EC\uD138 \uC9C4\uB2E8\uC744 \uBC30\uCE58 \uD558\uB098\uB85C \uC881\uD798 (id\xB7\uACBD\uB85C\xB7\uC2AC\uB86F id). \uB9C1\uD06C\xB7\uB85C\uADF8\uC778\uC774 \uC5C6\uC73C\uBA74 \uC885\uB8CC \uCF54\uB4DC 2\xB73"
6496
+ ).action((o) => runCommand(() => doctorCommand(o)));
6253
6497
  program.command("dev").description("\uC778\uC99D \uD504\uB85D\uC2DC \uD3EC\uD568 \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)").option("-p, --port <port>", "Dev server port", "5173").option(
6254
6498
  "--phase <phase>",
6255
6499
  "Target phase (dev, qa, real, sandbox). \uC0DD\uB7B5 \uC2DC .env\uC758 VITE_BSTAGE_PHASE, \uADF8\uAC83\uB3C4 \uC5C6\uC73C\uBA74 sandbox"
@@ -6304,6 +6548,8 @@ program.addHelpText(
6304
6548
  $ bstage dev \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (\uC778\uC99D \uD504\uB85D\uC2DC \xB7 liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)
6305
6549
  $ bstage build IIFE \uBC88\uB4E4 \uBE4C\uB4DC (dist/{\uACBD\uB85C} \xB7 dist/{\uC2AC\uB86F})
6306
6550
  $ bstage doctor SDK \uBC84\uC804\xB7\uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8
6551
+ $ bstage doctor --placement /me
6552
+ \uBC30\uCE58 \uD558\uB098\uB9CC \uD3EC\uD138 \uC9C4\uB2E8 (\uAC8C\uC2DC\xB7\uBE4C\uB4DC\xB7\uC571 \uD0A4 \uBB38\uC81C\uC640 \uC870\uCE58)
6307
6553
  $ bstage ai install \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC\xB7AGENTS.md \uC124\uCE58/\uCD5C\uC2E0\uD654 (+ \uC2DC\uD06C\uB9BF \uAC00\uB4DC)
6308
6554
  $ bstage ai doctor \uC5D0\uC774\uC804\uD2B8 \uC790\uC0B0 \uCD5C\uC2E0 \uC5EC\uBD80 \uC9C4\uB2E8
6309
6555
  $ bstage i18n pull \uD50C\uB7AB\uD3FC \uBC88\uC5ED \uBC1B\uAE30 + \uD0C0\uC785 \uC0DD\uC131
@@ -3,7 +3,7 @@ import {
3
3
  appKeyEnvDefine,
4
4
  bstageDevPlugin,
5
5
  createViteConfig
6
- } from "../chunk-COUDGZIA.js";
6
+ } from "../chunk-MSXSJHUT.js";
7
7
  export {
8
8
  appKeyEnvAliasPlugin,
9
9
  appKeyEnvDefine,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bstage-sdk/cli",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "bstage SDK CLI — build b.stage templates",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -32,14 +32,14 @@
32
32
  "liquidjs": "^10.24.0",
33
33
  "picocolors": "^1.1.1",
34
34
  "vite": "^7.0.0",
35
- "@bstage-sdk/ai-toolkit": "0.8.2",
36
- "@bstage-sdk/core": "0.8.2"
35
+ "@bstage-sdk/ai-toolkit": "0.8.4",
36
+ "@bstage-sdk/core": "0.8.4"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^25.5.0",
40
40
  "tsup": "^8.0.0",
41
41
  "typescript": "^5.5.0",
42
- "@bstage-sdk/design": "0.8.2"
42
+ "@bstage-sdk/design": "0.8.4"
43
43
  },
44
44
  "license": "MIT",
45
45
  "scripts": {