@design-ai/cli 4.61.0 → 4.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +30 -0
- package/README.ko.md +5 -5
- package/README.md +5 -5
- package/cli/lib/check.mjs +29 -0
- package/cli/lib/examples.mjs +2 -0
- package/cli/lib/pack.mjs +29 -1
- package/cli/lib/recall.mjs +2 -2
- package/cli/lib/route.mjs +26 -3
- package/cli/lib/search-ranked.mjs +31 -11
- package/docs/AI-LEARNING-PHASE2.md +11 -0
- package/docs/DOGFOOD-SDK-FINDINGS.md +56 -0
- package/docs/NEXT-SURFACE-DECISION.md +25 -0
- package/docs/ROADMAP.md +41 -1
- package/docs/SDK.md +6 -0
- package/docs/external-status.md +11 -11
- package/docs/integrations/agent-sdk-walkthrough.ko.md +219 -0
- package/docs/integrations/agent-sdk-walkthrough.md +219 -0
- package/examples/README.md +6 -0
- package/examples/flow-design-report-block.md +141 -0
- package/knowledge/COVERAGE.md +7 -5
- package/knowledge/patterns/trust-safety-moderation.md +107 -0
- package/package.json +1 -1
- package/tools/audit/integration-check.py +1 -0
- package/tools/audit/smoke_assertions.py +1 -0
package/docs/external-status.md
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
# External Publication Status
|
|
2
2
|
|
|
3
|
-
> Checked: 2026-07-
|
|
3
|
+
> Checked: 2026-07-06
|
|
4
4
|
> Scope: npm registry, GitHub Pages, Homebrew tap, VS Code Marketplace, Claude/Codex MCP
|
|
5
5
|
|
|
6
6
|
## Summary
|
|
7
7
|
|
|
8
|
-
npm is publicly published at `@design-ai/cli@4.
|
|
8
|
+
npm is publicly published at `@design-ai/cli@4.61.0` (npm dist-tag `latest` = `4.61.0`); publish run from tag `v4.61.0` succeeded with provenance and all pre-publish gates green. This release adds the ranked-search eval checkpoint (`search --eval-template` / `--eval`, with the Korean particle-form regression cases in the default template) — additive, so default `search` behavior is unchanged. The live `npm run registry:smoke` passes cleanly against published `@design-ai/cli@4.61.0` ("Registry smoke passed"), covering the retrieval surfaces (index/ranked/embeddings/recall) and route enrichment. GitHub Release `v4.61.0` is published, and the Homebrew tap formula points at the `v4.61.0` release source tarball with a verified SHA-256. The VS Code extension `sungjin.design-ai-vscode` remains published at `0.4.1`. GitHub Pages docs are publicly reachable.
|
|
9
9
|
|
|
10
10
|
## Results
|
|
11
11
|
|
|
12
12
|
| Surface | Checked target | Result | Evidence |
|
|
13
13
|
|---|---|---|---|
|
|
14
|
-
| npm registry | `@design-ai/cli` | Published latest is `4.
|
|
14
|
+
| npm registry | `@design-ai/cli` | Published latest is `4.61.0` (tag `v4.61.0`, provenance). Pre-publish packed-tarball smoke (incl. SDK import + `learn.remember` write) and live `npm run registry:smoke` both pass for `@design-ai/cli@4.61.0`. | `npm view @design-ai/cli version` → `4.61.0`; live registry smoke "Registry smoke passed" |
|
|
15
15
|
| GitHub Pages | `https://sungjin9288.github.io/design-ai/` | Published and reachable: HTTP `200`, design-ai MkDocs page rendered | `evidence/cli-logs/github-pages-status.log` |
|
|
16
|
-
| Homebrew tap | `Formula/design-ai.rb` | Formula pinned to `v4.
|
|
16
|
+
| Homebrew tap | `Formula/design-ai.rb` | Formula pinned to `v4.61.0` release source tarball with SHA-256 `7b391305b2afe756785b9ec71d7e359b1098dfae1e7d7faef460f20e219e166a` (recomputed from the published tag tarball) | `Formula/design-ai.rb` |
|
|
17
17
|
| VS Code Marketplace | `sungjin.design-ai-vscode` | Published: run `28431571256` published `v0.4.1`, and the Marketplace Gallery API returned visible version `0.4.1` on 2026-07-02. | `evidence/cli-logs/vscode-marketplace-status.log`, `evidence/cli-logs/vscode-marketplace-secret-status.log`, `evidence/cli-logs/vscode-extension-vsce-package.log`, `evidence/cli-logs/vscode-publish-workflow-status.log` |
|
|
18
|
-
| GitHub Release | `v4.
|
|
19
|
-
| MCP server | `@design-ai/cli@4.
|
|
18
|
+
| GitHub Release | `v4.61.0` | Published for tag `v4.61.0` at commit `5d8a21a` | `gh release view v4.61.0` |
|
|
19
|
+
| MCP server | `@design-ai/cli@4.61.0` / local clone | Public npm `design-ai-mcp` responds to initialize and tools/list with 10 tools; local Codex and Claude Code both report `design-ai` MCP as configured and connected. | `evidence/cli-logs/npm-registry-smoke.log`, `evidence/cli-logs/design-ai-mcp-client-status.log` |
|
|
20
20
|
|
|
21
21
|
## Interpretation
|
|
22
22
|
|
|
23
23
|
- The repository is locally release-ready based on `npm run release:check`.
|
|
24
24
|
- GitHub Pages docs can now be described as publicly deployed.
|
|
25
|
-
- Public npm install can now be described as published and smoke-tested at `4.
|
|
26
|
-
- Homebrew tap install can now be described as pinned to the `v4.
|
|
25
|
+
- Public npm install can now be described as published and smoke-tested at `4.61.0`.
|
|
26
|
+
- Homebrew tap install can now be described as pinned to the `v4.61.0` release tarball; full tap audit/install/test remains a maintainer-side verification step because this Homebrew version rejects path-based `brew audit Formula/...` calls.
|
|
27
27
|
- VS Code Marketplace can now be described as published and publicly reachable at version `0.4.1`.
|
|
28
28
|
- Claude Code and Codex can now be described as locally connected to the clone-backed `design-ai` MCP server, while public npm users can verify the published `design-ai-mcp` entrypoint from a clean working directory.
|
|
29
29
|
|
|
@@ -32,12 +32,12 @@ npm is publicly published at `@design-ai/cli@4.60.0` (npm dist-tag `latest` = `4
|
|
|
32
32
|
```bash
|
|
33
33
|
npm view @design-ai/cli version name time.modified dist-tags --json
|
|
34
34
|
curl -sS -L -o /tmp/design-ai-pages.html -w 'http_code=%{http_code}\nurl_effective=%{url_effective}\n' https://sungjin9288.github.io/design-ai/
|
|
35
|
-
curl -sL https://github.com/sungjin9288/design-ai/archive/refs/tags/v4.
|
|
35
|
+
curl -sL https://github.com/sungjin9288/design-ai/archive/refs/tags/v4.61.0.tar.gz | shasum -a 256
|
|
36
36
|
ruby -c Formula/design-ai.rb
|
|
37
37
|
brew style Formula/design-ai.rb
|
|
38
|
-
gh release view v4.
|
|
38
|
+
gh release view v4.61.0 --repo sungjin9288/design-ai --json tagName,isDraft,isPrerelease,publishedAt,name,url,assets
|
|
39
39
|
gh run view 28569283984 --repo sungjin9288/design-ai --json status,conclusion,name,url,createdAt,updatedAt
|
|
40
|
-
npm exec --yes --package=@design-ai/cli@4.
|
|
40
|
+
npm exec --yes --package=@design-ai/cli@4.61.0 -- design-ai-mcp
|
|
41
41
|
codex mcp get design-ai
|
|
42
42
|
claude mcp list
|
|
43
43
|
curl -sS -H 'Content-Type: application/json' \
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Agent SDK 워크스루
|
|
2
|
+
|
|
3
|
+
**프로그래밍 방식 Agent SDK** (`@design-ai/cli/sdk`) — 읽기 전용 함수들과 opt-in `learn.*` 로컬 쓰기 네임스페이스 — 로 design-ai를 완전히 구동하는 구체적이고 복사해서 바로 쓸 수 있는 워크스루예요. [`docs/integrations/sdk-walkthrough.md`](sdk-walkthrough.ko.md)(Anthropic/OpenAI SDK로 코퍼스 마크다운을 모델의 시스템 프롬프트에 임베드하는 방식)와는 다른 표면이에요. 이 문서는 여러분 자신의 Node.js 프로그램이나 에이전트 런타임에서 design-ai 자체의 결정적 함수 — `route`, `pack`, `check`, `learn.captureFromCheck` — 를 직접 호출하는 방법을 다뤄요. 전체 API 레퍼런스는 [`docs/SDK.md`](../SDK.md)를 참고하세요.
|
|
4
|
+
|
|
5
|
+
## 사전 준비
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @design-ai/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { route, pack, check, learn } from "@design-ai/cli/sdk";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`./sdk` 서브패스만 export돼요 — CLI 셸 실행도, MCP 서버도, 별도 코퍼스 클론도 필요 없어요. TypeScript 타입(`RouteResult`, `Pack`, `CheckReport`, `CaptureResult`, …)은 `tsconfig.json`에서 `moduleResolution: "node16"` / `"nodenext"` (또는 `"bundler"`)로 설정돼 있으면 `cli/sdk/index.d.ts`에서 자동으로 resolve돼요. 서브패스 `types` 조건이 이렇게 지켜져요.
|
|
16
|
+
|
|
17
|
+
## 설치
|
|
18
|
+
|
|
19
|
+
설정할 게 없어요. 8개 읽기 전용 함수(`route`, `prompt`, `pack`, `search`, `recall`, `check`, `routes`, `version`)는 디스크에 절대 쓰지 않아요. 유일한 쓰기 표면은 `learn` 네임스페이스(`learn.remember`, `learn.feedback`, `learn.captureFromCheck`)예요 — 모든 `learn.*` 호출은 로컬 학습 프로필에만, 그것도 명시적으로 호출했을 때만 써요. 아래 모든 워크스루가 하는 것처럼 `DESIGN_AI_LEARNING_FILE`을 임시 경로로 지정하면 언제든 이 쓰기를 실제 프로필 바깥에 격리할 수 있어요 — 그래서 아래 스크립트를 실행해도 `~/.design-ai/learning.json`은 전혀 건드리지 않아요.
|
|
20
|
+
|
|
21
|
+
## 워크스루 1: 브리프를 design-ai 라우트로 라우팅
|
|
22
|
+
|
|
23
|
+
**목표**: 작업 브리프에 대한 점수화된 라우트 추천을 받아서, 에이전트가 다음에 어떤 명령/스킬/지식을 써야 할지 알게 하기.
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { route } from "@design-ai/cli/sdk";
|
|
27
|
+
|
|
28
|
+
const brief =
|
|
29
|
+
"커뮤니티 앱의 게시물 신고 및 사용자 차단 플로우 설계 — " +
|
|
30
|
+
"신고 사유 선택, 처리 상태 안내, 차단 후 상호작용 차단 범위";
|
|
31
|
+
|
|
32
|
+
const routed = route(brief, { limit: 3, explain: true });
|
|
33
|
+
console.log(routed.map((r) => `[${r.confidence}] ${r.id} score=${r.score}`));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
[ '[low] design-from-brief score=1' ]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
이건 바로 이 브리프로 실제 dogfooding한 출력이에요 — 전체 실행 기록과 이 결과가 드러낸 라우트 테이블 갭은 [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md)를 참고하세요(F-1: 전용 flow-design 라우트가 아직 없어서 신고/차단 브리프가 `design-from-brief`로 폴백해요). `route()`는 낮은 confidence 매치여도 여전히 쓸 수 있는 추천을 반환해요 — 그래서 `pack()`으로 무조건 체이닝해도 안전해요.
|
|
41
|
+
|
|
42
|
+
## 워크스루 2: 바운드된 컨텍스트 번들 pack
|
|
43
|
+
|
|
44
|
+
**목표**: 같은 브리프를 아티팩트 작성 전에 에이전트가 읽어야 할 코퍼스 파일들의 바이트 상한 번들 + 바로 쓸 수 있는 프롬프트로 변환하기.
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { pack } from "@design-ai/cli/sdk";
|
|
48
|
+
|
|
49
|
+
const packed = pack(brief, {
|
|
50
|
+
routeId: routed[0].id,
|
|
51
|
+
withRecall: true,
|
|
52
|
+
recallLimit: 5,
|
|
53
|
+
maxBytes: 60000,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
console.log(packed.summary);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
{
|
|
61
|
+
totalFiles: 15,
|
|
62
|
+
includedFiles: 15,
|
|
63
|
+
truncatedFiles: 10,
|
|
64
|
+
missingFiles: 0,
|
|
65
|
+
usedBytes: 60000,
|
|
66
|
+
maxBytes: 60000,
|
|
67
|
+
remainingBytes: 0,
|
|
68
|
+
usedRatio: 1,
|
|
69
|
+
status: 'partial'
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`pack()`은 `maxBytes`를 절대 넘지 않아요 — 여기서는 예산을 정확히 채우고(60,000/60,000 바이트) `packed.warnings`에 어떤 파일이 잘렸는지 보고해요. 그래서 에이전트가 예산을 늘릴지, 잘린 파일의 나머지를 직접 읽을지 판단할 수 있어요. `packed.plan`은 `prompt()`가 반환할 것과 같은 바로 쓸 수 있는 프롬프트를 담고 있고, `packed.files`가 바운드된 번들 자체예요.
|
|
74
|
+
|
|
75
|
+
## 워크스루 3: 아티팩트 작성 (여기는 에이전트의 역할)
|
|
76
|
+
|
|
77
|
+
**목표**: SDK는 디자인 아티팩트를 쓰지 않아요 — 그건 LLM/에이전트의 역할이에요. `packed.plan`과 `packed.files`를 grounding으로 사용해요. 이 워크스루는 라이브 모델 호출 없이도 스크립트가 끝까지 실행되도록 짧은 샘플 아티팩트 문자열을 임베드해요. 실제 에이전트에서는 `SAMPLE_ARTIFACT`를 모델의 실제 마크다운 출력으로 교체하세요.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
// 실제 에이전트에서는 이 문자열이 모델의 응답이에요 — `packed.plan.prompt`와
|
|
81
|
+
// `packed.files`를 LLM 호출에 넣고 반환된 마크다운을 받아서 만들어요.
|
|
82
|
+
// 스크립트가 단독으로 실행되도록 여기서는 짧게 유지해요.
|
|
83
|
+
// flow-example.test.mjs에 같은 상수가 있어요 (이 워크스루와 lockstep —
|
|
84
|
+
// 거기 주석이 여기를 다시 가리켜요).
|
|
85
|
+
const SAMPLE_ARTIFACT = `# 게시물 신고 및 사용자 차단 플로우
|
|
86
|
+
|
|
87
|
+
Grounded in knowledge/patterns/ui-reasoning.md and knowledge/PRINCIPLES.md.
|
|
88
|
+
|
|
89
|
+
## 신고 플로우
|
|
90
|
+
1. 게시물 상세에서 "신고" 메뉴 선택 (keyboard: Tab으로 접근, Enter로 실행)
|
|
91
|
+
2. 신고 사유 목록에서 선택 (스팸, 욕설/혐오, 음란물, 사기, 기타) — 라디오 그룹, arrow key로 이동
|
|
92
|
+
3. 기타 선택 시 상세 사유 텍스트 입력 (최대 500자)
|
|
93
|
+
4. 제출 후 "신고가 접수되었습니다" 확인 화면 표시
|
|
94
|
+
5. 처리 상태: 접수 → 검토 중 → 조치 완료 (마이페이지 > 신고 내역에서 확인 가능)
|
|
95
|
+
|
|
96
|
+
## 차단 플로우
|
|
97
|
+
1. 사용자 프로필에서 "차단" 메뉴 선택
|
|
98
|
+
2. 확인 다이얼로그: "OO님을 차단하시겠어요?" — focus trap 적용, Escape로 취소
|
|
99
|
+
3. 차단 후 상호작용 범위: 서로의 게시물/댓글 비노출, DM 차단, 팔로우 자동 해제
|
|
100
|
+
4. 차단 사실은 상대방에게 통지되지 않음 (비통지 원칙)
|
|
101
|
+
|
|
102
|
+
## 반응형 동작
|
|
103
|
+
- Mobile: 전체 화면 시트로 신고 사유 목록 표시
|
|
104
|
+
- Desktop: 중앙 정렬 모달, 최대 너비 480px
|
|
105
|
+
- Tablet: mobile과 동일한 시트 레이아웃
|
|
106
|
+
|
|
107
|
+
## 접근성
|
|
108
|
+
- 신고 사유 목록: role="radiogroup", 각 항목 aria-checked
|
|
109
|
+
- 차단 확인 다이얼로그: focus-visible 스타일, aria-modal="true"
|
|
110
|
+
- Screen reader: 신고 접수 완료 시 aria-live="polite"로 상태 안내
|
|
111
|
+
- 대비: 경고/오류 텍스트는 최소 4.5:1 contrast ratio 확보 (WCAG AA)
|
|
112
|
+
|
|
113
|
+
## 하지 말아야 할 것 (Don't)
|
|
114
|
+
- Don't: 차단 시 상대방에게 알림을 보내지 마세요 (비통지 원칙 위반)
|
|
115
|
+
- Avoid: 신고 사유를 하나의 텍스트 필드로만 받는 방식 (분류 불가)
|
|
116
|
+
`;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 워크스루 4: 아티팩트 check
|
|
120
|
+
|
|
121
|
+
**목표**: 작성된 아티팩트를 grounding, 접근성, 반응형, 라우트별 요구사항 기준으로 점수화해서 배포 전에 확인하기.
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
import { check } from "@design-ai/cli/sdk";
|
|
125
|
+
|
|
126
|
+
const checked = check(SAMPLE_ARTIFACT, { routeId: routed[0].id });
|
|
127
|
+
console.log(`${checked.status} ${checked.score}`);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
warn 8/10
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`checked.results`가 체크별 세부 내역이에요 (여기서는 총 10개 체크: 8 pass, 2 warn, 0 fail). 하나는 `route-design-from-brief-design-system-foundation` — flow-design 아티팩트에 design-system-foundation 근거가 빠졌다고 보고하는 라우트별 체크로, 워크스루 1의 F-1 라우트 갭에서 정확히 예상되는 결과예요. 다른 하나는 `korean-context` — 이 짧은 샘플에 한국 시장 특화 고려가 빠졌다는 지적인데, 실제 dogfood의 더 긴 아티팩트는 이를 반영해서(정보통신망법 처리 기한 안내) 라우트 warn 하나만 남은 `warn 9/10`을 받았어요. `check()`도 `route`, `pack`처럼 아무것도 쓰지 않아요.
|
|
135
|
+
|
|
136
|
+
## 워크스루 5: check 결과를 로컬 학습으로 capture
|
|
137
|
+
|
|
138
|
+
**목표**: check의 non-pass 결과를 로컬 학습 프로필 엔트리로 전환하기 — 이 전체 플로우에서 유일한 쓰기이고, opt-in이며 명시적이에요.
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { learn } from "@design-ai/cli/sdk";
|
|
142
|
+
import { mkdtempSync } from "node:fs";
|
|
143
|
+
import { tmpdir } from "node:os";
|
|
144
|
+
import path from "node:path";
|
|
145
|
+
|
|
146
|
+
// DESIGN_AI_LEARNING_FILE을 임시 파일로 지정해서 실제 프로필
|
|
147
|
+
// (기본값 ~/.design-ai/learning.json)을 절대 건드리지 않아요.
|
|
148
|
+
const dir = mkdtempSync(path.join(tmpdir(), "design-ai-sdk-walkthrough-"));
|
|
149
|
+
process.env.DESIGN_AI_LEARNING_FILE = path.join(dir, "learning.json");
|
|
150
|
+
|
|
151
|
+
const captured = learn.captureFromCheck(SAMPLE_ARTIFACT, { routeId: routed[0].id });
|
|
152
|
+
console.log(`added ${captured.addedCount}, skipped ${captured.skippedCount}`);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
added 2, skipped 0
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
non-pass 결과 두 건(워크스루 4의 warn 둘)이 `process.env.DESIGN_AI_LEARNING_FILE`의 임시 프로필에 capture됐어요. 같은 아티팩트로 `captureFromCheck`를 다시 호출하면 아무것도 추가되지 않아요 — 모든 후보가 `duplicate-entry-text`로 skip되므로(두 번째 호출은 `added 0, skipped 2`), 변경 없는 아티팩트로 플로우를 재실행해도 프로필이 계속 커지지 않아요.
|
|
160
|
+
|
|
161
|
+
## 전체 스크립트
|
|
162
|
+
|
|
163
|
+
위 내용을 모두 하나의 실행 가능한 파일로 모으면:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
import { route, pack, check, learn } from "@design-ai/cli/sdk";
|
|
167
|
+
import { mkdtempSync } from "node:fs";
|
|
168
|
+
import { tmpdir } from "node:os";
|
|
169
|
+
import path from "node:path";
|
|
170
|
+
|
|
171
|
+
// 실제 프로필을 건드리지 않도록 학습 쓰기를 임시 파일로 지정.
|
|
172
|
+
const dir = mkdtempSync(path.join(tmpdir(), "design-ai-sdk-walkthrough-"));
|
|
173
|
+
process.env.DESIGN_AI_LEARNING_FILE = path.join(dir, "learning.json");
|
|
174
|
+
|
|
175
|
+
const brief =
|
|
176
|
+
"커뮤니티 앱의 게시물 신고 및 사용자 차단 플로우 설계 — " +
|
|
177
|
+
"신고 사유 선택, 처리 상태 안내, 차단 후 상호작용 차단 범위";
|
|
178
|
+
|
|
179
|
+
// 1. route — 브리프를 라우트 카탈로그에 점수화.
|
|
180
|
+
const routed = route(brief, { limit: 3, explain: true });
|
|
181
|
+
const routeId = routed[0].id;
|
|
182
|
+
console.log(routed.map((r) => `[${r.confidence}] ${r.id} score=${r.score}`));
|
|
183
|
+
|
|
184
|
+
// 2. pack — 바운드된 컨텍스트 번들 + 바로 쓸 수 있는 프롬프트.
|
|
185
|
+
const packed = pack(brief, { routeId, withRecall: true, recallLimit: 5, maxBytes: 60000 });
|
|
186
|
+
console.log(packed.summary);
|
|
187
|
+
|
|
188
|
+
// 3. author — LLM/에이전트가 packed.plan + packed.files를 grounding으로
|
|
189
|
+
// 삼아 여기서 아티팩트를 작성해요. 스크립트가 단독 실행되도록 짧은 샘플로
|
|
190
|
+
// 임베드. cli/sdk/flow-example.test.mjs와 lockstep 유지.
|
|
191
|
+
const SAMPLE_ARTIFACT = `# 게시물 신고 및 사용자 차단 플로우
|
|
192
|
+
...`; // 전체 텍스트는 위 워크스루 3 참고
|
|
193
|
+
|
|
194
|
+
// 4. check — 아티팩트 점수화.
|
|
195
|
+
const checked = check(SAMPLE_ARTIFACT, { routeId });
|
|
196
|
+
console.log(`${checked.status} ${checked.score}`);
|
|
197
|
+
|
|
198
|
+
// 5. learn.captureFromCheck — 유일한 쓰기, opt-in, 임시 프로필로.
|
|
199
|
+
const captured = learn.captureFromCheck(SAMPLE_ARTIFACT, { routeId });
|
|
200
|
+
console.log(`added ${captured.addedCount}, skipped ${captured.skippedCount}`);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
이 플로우는 이 워크스루를 작성하기 전에 실제로 end-to-end dogfooding됐어요 — 전체 실행 기록, 위 숫자들, 이 실행이 드러낸 코퍼스/라우트 갭은 [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md)를 참고하세요. 그 실행의 SDK 결론: 마찰 없음 — 위 플로우가 곧 이 워크스루예요.
|
|
204
|
+
|
|
205
|
+
## 읽기 전용 vs `learn.*` 쓰기 경계
|
|
206
|
+
|
|
207
|
+
- `route`, `prompt`, `pack`, `search`, `recall`, `check`, `routes`, `version` — 순수 읽기 전용. 파일 쓰기, 네트워크 호출, 학습 사용량 사이드카 쓰기가 전혀 없어요. `prompt`/`pack`의 `withLearning` 옵션을 설정해도 마찬가지예요 (이 옵션은 로컬 학습 프로필을 **읽기만** 해요).
|
|
208
|
+
- `learn.remember`, `learn.feedback`, `learn.captureFromCheck` — 유일한 쓰기 표면. `learn` 네임스페이스로 묶여 있어서 호출 지점에서 읽기/쓰기 경계가 눈에 보여요. 모든 `learn.*` 호출은 정확히 파일 하나 — `DESIGN_AI_LEARNING_FILE`(또는 기본 경로)의 로컬 학습 프로필 — 만 써요.
|
|
209
|
+
|
|
210
|
+
전체 함수별 레퍼런스(이 워크스루가 직접 다루지 않는 `search`, `recall`, `prompt`, `routes` 포함)는 [`docs/SDK.md`](../SDK.md)를 참고하세요.
|
|
211
|
+
|
|
212
|
+
## 다음
|
|
213
|
+
|
|
214
|
+
- [`docs/SDK.md`](../SDK.md) — 전체 Agent SDK 레퍼런스 (8개 읽기 전용 함수 + `learn.*`)
|
|
215
|
+
- [`docs/AGENT-SDK.md`](../AGENT-SDK.md) — 설계 근거와 단계별 계획
|
|
216
|
+
- [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md) — 이 워크스루의 근거가 된 실제 end-to-end 실행
|
|
217
|
+
- [`docs/integrations/sdk-walkthrough.ko.md`](sdk-walkthrough.ko.md) — Anthropic/OpenAI SDK 패턴 (코퍼스 마크다운을 시스템 프롬프트에 임베드, 이 문서와는 다른 표면)
|
|
218
|
+
|
|
219
|
+
이 플로우는 저장소 소스 체크아웃에 `node --test` 회귀 가드(`cli/sdk/flow-example.test.mjs`, npm 패키지에는 포함되지 않음)로도 있어서 `npm test` 때마다 실행돼요.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Agent SDK walkthrough
|
|
2
|
+
|
|
3
|
+
A concrete, copy-pastable walkthrough of driving design-ai entirely through the **programmatic Agent SDK** (`@design-ai/cli/sdk`) — the read-only verbs plus the opt-in `learn.*` local-write namespace. This is a different surface than [`docs/integrations/sdk-walkthrough.md`](sdk-walkthrough.md) (which embeds corpus Markdown into a model's system prompt via the Anthropic/OpenAI SDKs); this page is for driving design-ai's own deterministic functions — `route`, `pack`, `check`, `learn.captureFromCheck` — from your own Node.js program or agent runtime. See [`docs/SDK.md`](../SDK.md) for the full API reference.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @design-ai/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { route, pack, check, learn } from "@design-ai/cli/sdk";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Only the `./sdk` subpath is exported — no CLI shell-out, no MCP server, no separate corpus clone. TypeScript types (`RouteResult`, `Pack`, `CheckReport`, `CaptureResult`, …) resolve automatically from `cli/sdk/index.d.ts` as long as your `tsconfig.json` sets `moduleResolution: "node16"` / `"nodenext"` (or `"bundler"`), so the subpath `types` condition is honored.
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
Nothing to configure. The 8 read-only verbs (`route`, `prompt`, `pack`, `search`, `recall`, `check`, `routes`, `version`) never write to disk. The single write surface is the `learn` namespace (`learn.remember`, `learn.feedback`, `learn.captureFromCheck`) — every `learn.*` call writes only the local learning profile, and only when you call it. Point `DESIGN_AI_LEARNING_FILE` at a temp path any time you want to keep that write out of your real profile — which is what every walkthrough below does, so running these scripts never touches `~/.design-ai/learning.json`.
|
|
20
|
+
|
|
21
|
+
## Walkthrough 1: route a brief to a design-ai route
|
|
22
|
+
|
|
23
|
+
**Goal**: get a scored route recommendation for a task brief, so an agent knows which command/skills/knowledge to use next.
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { route } from "@design-ai/cli/sdk";
|
|
27
|
+
|
|
28
|
+
const brief =
|
|
29
|
+
"커뮤니티 앱의 게시물 신고 및 사용자 차단 플로우 설계 — " +
|
|
30
|
+
"신고 사유 선택, 처리 상태 안내, 차단 후 상호작용 차단 범위";
|
|
31
|
+
|
|
32
|
+
const routed = route(brief, { limit: 3, explain: true });
|
|
33
|
+
console.log(routed.map((r) => `[${r.confidence}] ${r.id} score=${r.score}`));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
[ '[low] design-from-brief score=1' ]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This is real output from dogfooding this exact brief — see [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md) for the full run and the route-table gap it surfaced (F-1: no dedicated flow-design route yet, so a report/block brief falls back to `design-from-brief`). `route()` still returns a usable recommendation — that's what makes it safe to chain into `pack()` unconditionally, even on a low-confidence match.
|
|
41
|
+
|
|
42
|
+
## Walkthrough 2: pack a bounded context bundle
|
|
43
|
+
|
|
44
|
+
**Goal**: turn the same brief into a ready-to-use prompt plus a byte-bounded bundle of the corpus files an agent should read before authoring the artifact.
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
import { pack } from "@design-ai/cli/sdk";
|
|
48
|
+
|
|
49
|
+
const packed = pack(brief, {
|
|
50
|
+
routeId: routed[0].id,
|
|
51
|
+
withRecall: true,
|
|
52
|
+
recallLimit: 5,
|
|
53
|
+
maxBytes: 60000,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
console.log(packed.summary);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
{
|
|
61
|
+
totalFiles: 15,
|
|
62
|
+
includedFiles: 15,
|
|
63
|
+
truncatedFiles: 10,
|
|
64
|
+
missingFiles: 0,
|
|
65
|
+
usedBytes: 60000,
|
|
66
|
+
maxBytes: 60000,
|
|
67
|
+
remainingBytes: 0,
|
|
68
|
+
usedRatio: 1,
|
|
69
|
+
status: 'partial'
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`pack()` never exceeds `maxBytes` — it fills the budget exactly (60,000/60,000 bytes here) and reports which files got truncated in `packed.warnings`, so an agent can decide whether to raise the budget or read a truncated file's remainder directly. `packed.plan` carries the same ready-to-use prompt `prompt()` would return; `packed.files` is the bounded bundle itself.
|
|
74
|
+
|
|
75
|
+
## Walkthrough 3: author the artifact (this is the agent's job)
|
|
76
|
+
|
|
77
|
+
**Goal**: the SDK does not write design artifacts — that's the LLM/agent's job, using `packed.plan` and `packed.files` as grounding. This walkthrough embeds a short sample artifact string so the script is runnable end-to-end without a live model call; in a real agent, replace `SAMPLE_ARTIFACT` with the model's actual Markdown output.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
// In a real agent, this string is the model's response — produced by
|
|
81
|
+
// feeding `packed.plan.prompt` and `packed.files` to your LLM call, then
|
|
82
|
+
// taking the Markdown it returns. Kept short here so the script runs
|
|
83
|
+
// standalone. See flow-example.test.mjs for the same constant (kept in
|
|
84
|
+
// lockstep with this walkthrough — the comment there points back here).
|
|
85
|
+
const SAMPLE_ARTIFACT = `# 게시물 신고 및 사용자 차단 플로우
|
|
86
|
+
|
|
87
|
+
Grounded in knowledge/patterns/ui-reasoning.md and knowledge/PRINCIPLES.md.
|
|
88
|
+
|
|
89
|
+
## 신고 플로우
|
|
90
|
+
1. 게시물 상세에서 "신고" 메뉴 선택 (keyboard: Tab으로 접근, Enter로 실행)
|
|
91
|
+
2. 신고 사유 목록에서 선택 (스팸, 욕설/혐오, 음란물, 사기, 기타) — 라디오 그룹, arrow key로 이동
|
|
92
|
+
3. 기타 선택 시 상세 사유 텍스트 입력 (최대 500자)
|
|
93
|
+
4. 제출 후 "신고가 접수되었습니다" 확인 화면 표시
|
|
94
|
+
5. 처리 상태: 접수 → 검토 중 → 조치 완료 (마이페이지 > 신고 내역에서 확인 가능)
|
|
95
|
+
|
|
96
|
+
## 차단 플로우
|
|
97
|
+
1. 사용자 프로필에서 "차단" 메뉴 선택
|
|
98
|
+
2. 확인 다이얼로그: "OO님을 차단하시겠어요?" — focus trap 적용, Escape로 취소
|
|
99
|
+
3. 차단 후 상호작용 범위: 서로의 게시물/댓글 비노출, DM 차단, 팔로우 자동 해제
|
|
100
|
+
4. 차단 사실은 상대방에게 통지되지 않음 (비통지 원칙)
|
|
101
|
+
|
|
102
|
+
## 반응형 동작
|
|
103
|
+
- Mobile: 전체 화면 시트로 신고 사유 목록 표시
|
|
104
|
+
- Desktop: 중앙 정렬 모달, 최대 너비 480px
|
|
105
|
+
- Tablet: mobile과 동일한 시트 레이아웃
|
|
106
|
+
|
|
107
|
+
## 접근성
|
|
108
|
+
- 신고 사유 목록: role="radiogroup", 각 항목 aria-checked
|
|
109
|
+
- 차단 확인 다이얼로그: focus-visible 스타일, aria-modal="true"
|
|
110
|
+
- Screen reader: 신고 접수 완료 시 aria-live="polite"로 상태 안내
|
|
111
|
+
- 대비: 경고/오류 텍스트는 최소 4.5:1 contrast ratio 확보 (WCAG AA)
|
|
112
|
+
|
|
113
|
+
## 하지 말아야 할 것 (Don't)
|
|
114
|
+
- Don't: 차단 시 상대방에게 알림을 보내지 마세요 (비통지 원칙 위반)
|
|
115
|
+
- Avoid: 신고 사유를 하나의 텍스트 필드로만 받는 방식 (분류 불가)
|
|
116
|
+
`;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Walkthrough 4: check the artifact
|
|
120
|
+
|
|
121
|
+
**Goal**: score the authored artifact for grounding, accessibility, responsive, and route-specific requirements before shipping it.
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
import { check } from "@design-ai/cli/sdk";
|
|
125
|
+
|
|
126
|
+
const checked = check(SAMPLE_ARTIFACT, { routeId: routed[0].id });
|
|
127
|
+
console.log(`${checked.status} ${checked.score}`);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
warn 8/10
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`checked.results` is the per-check breakdown (10 checks total here: 8 pass, 2 warns, 0 fail). One warn is `route-design-from-brief-design-system-foundation` — a route-specific check reporting that a flow-design artifact is missing design-system-foundation evidence, which is exactly what you'd expect from the F-1 route gap in walkthrough 1. The other, `korean-context`, flags that this short sample mentions no Korean-specific UX/market consideration — the fuller dogfooded artifact addressed it (정보통신망법 처리 기한 안내) and scored `warn 9/10` with only the route warn left. `check()` never writes anything; it's as read-only as `route` and `pack`.
|
|
135
|
+
|
|
136
|
+
## Walkthrough 5: capture check results into local learning
|
|
137
|
+
|
|
138
|
+
**Goal**: turn the check's non-pass results into local learning-profile entries — the one write in this whole flow, and it's opt-in and explicit.
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { learn } from "@design-ai/cli/sdk";
|
|
142
|
+
import { mkdtempSync } from "node:fs";
|
|
143
|
+
import { tmpdir } from "node:os";
|
|
144
|
+
import path from "node:path";
|
|
145
|
+
|
|
146
|
+
// Point DESIGN_AI_LEARNING_FILE at a temp file so this never touches your
|
|
147
|
+
// real profile (~/.design-ai/learning.json by default).
|
|
148
|
+
const dir = mkdtempSync(path.join(tmpdir(), "design-ai-sdk-walkthrough-"));
|
|
149
|
+
process.env.DESIGN_AI_LEARNING_FILE = path.join(dir, "learning.json");
|
|
150
|
+
|
|
151
|
+
const captured = learn.captureFromCheck(SAMPLE_ARTIFACT, { routeId: routed[0].id });
|
|
152
|
+
console.log(`added ${captured.addedCount}, skipped ${captured.skippedCount}`);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
added 2, skipped 0
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Both non-pass results (the two warns from walkthrough 4) got captured into the temp profile at `process.env.DESIGN_AI_LEARNING_FILE`. Calling `captureFromCheck` again with the same artifact adds nothing new — every candidate is skipped as `duplicate-entry-text` (`added 0, skipped 2` on the second call), so re-running the flow on an unchanged artifact never grows the profile.
|
|
160
|
+
|
|
161
|
+
## Full script
|
|
162
|
+
|
|
163
|
+
Everything above, assembled into one runnable file:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
import { route, pack, check, learn } from "@design-ai/cli/sdk";
|
|
167
|
+
import { mkdtempSync } from "node:fs";
|
|
168
|
+
import { tmpdir } from "node:os";
|
|
169
|
+
import path from "node:path";
|
|
170
|
+
|
|
171
|
+
// Never touch the real profile — point learning writes at a temp file.
|
|
172
|
+
const dir = mkdtempSync(path.join(tmpdir(), "design-ai-sdk-walkthrough-"));
|
|
173
|
+
process.env.DESIGN_AI_LEARNING_FILE = path.join(dir, "learning.json");
|
|
174
|
+
|
|
175
|
+
const brief =
|
|
176
|
+
"커뮤니티 앱의 게시물 신고 및 사용자 차단 플로우 설계 — " +
|
|
177
|
+
"신고 사유 선택, 처리 상태 안내, 차단 후 상호작용 차단 범위";
|
|
178
|
+
|
|
179
|
+
// 1. route — score the brief against the route catalog.
|
|
180
|
+
const routed = route(brief, { limit: 3, explain: true });
|
|
181
|
+
const routeId = routed[0].id;
|
|
182
|
+
console.log(routed.map((r) => `[${r.confidence}] ${r.id} score=${r.score}`));
|
|
183
|
+
|
|
184
|
+
// 2. pack — bounded context bundle + ready-to-use prompt.
|
|
185
|
+
const packed = pack(brief, { routeId, withRecall: true, recallLimit: 5, maxBytes: 60000 });
|
|
186
|
+
console.log(packed.summary);
|
|
187
|
+
|
|
188
|
+
// 3. author — the LLM/agent writes the artifact here, grounded in
|
|
189
|
+
// packed.plan + packed.files. Embedded as a short sample so this script
|
|
190
|
+
// runs standalone. Kept in lockstep with cli/sdk/flow-example.test.mjs.
|
|
191
|
+
const SAMPLE_ARTIFACT = `# 게시물 신고 및 사용자 차단 플로우
|
|
192
|
+
...`; // see Walkthrough 3 above for the full text
|
|
193
|
+
|
|
194
|
+
// 4. check — score the artifact.
|
|
195
|
+
const checked = check(SAMPLE_ARTIFACT, { routeId });
|
|
196
|
+
console.log(`${checked.status} ${checked.score}`);
|
|
197
|
+
|
|
198
|
+
// 5. learn.captureFromCheck — the one write, opt-in, into the temp profile.
|
|
199
|
+
const captured = learn.captureFromCheck(SAMPLE_ARTIFACT, { routeId });
|
|
200
|
+
console.log(`added ${captured.addedCount}, skipped ${captured.skippedCount}`);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
This exact flow was dogfooded end-to-end before this walkthrough was written — see [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md) for the full run, the numbers above, and the corpus/route gaps the run surfaced. The SDK verdict from that run: zero friction — the flow above is the walkthrough.
|
|
204
|
+
|
|
205
|
+
## Read-only vs `learn.*` write boundary
|
|
206
|
+
|
|
207
|
+
- `route`, `prompt`, `pack`, `search`, `recall`, `check`, `routes`, `version` — pure, read-only. No file writes, no network calls, no learning-usage sidecar writes, even when `prompt`/`pack`'s `withLearning` option is set (that option only **reads** the local learning profile).
|
|
208
|
+
- `learn.remember`, `learn.feedback`, `learn.captureFromCheck` — the only write surface, grouped under the `learn` namespace so the read/write boundary is visible at the call site. Every `learn.*` call writes exactly one file: the local learning profile at `DESIGN_AI_LEARNING_FILE` (or its default path).
|
|
209
|
+
|
|
210
|
+
See [`docs/SDK.md`](../SDK.md) for the full verb-by-verb reference, including `search`, `recall`, `prompt`, and `routes`, which this walkthrough doesn't exercise directly.
|
|
211
|
+
|
|
212
|
+
## Next
|
|
213
|
+
|
|
214
|
+
- [`docs/SDK.md`](../SDK.md) — full Agent SDK reference (all 8 read-only verbs + `learn.*`)
|
|
215
|
+
- [`docs/AGENT-SDK.md`](../AGENT-SDK.md) — design rationale and phased plan
|
|
216
|
+
- [`docs/DOGFOOD-SDK-FINDINGS.md`](../DOGFOOD-SDK-FINDINGS.md) — the real end-to-end run this walkthrough is based on
|
|
217
|
+
- [`docs/integrations/sdk-walkthrough.md`](sdk-walkthrough.md) — the Anthropic/OpenAI SDK pattern (embedding corpus Markdown in a system prompt, a different surface than this page)
|
|
218
|
+
|
|
219
|
+
This exact flow also has a `node --test` regression guard in the repo's source checkout (`cli/sdk/flow-example.test.mjs`, not shipped in the npm package) that runs on every `npm test`.
|
package/examples/README.md
CHANGED
|
@@ -235,6 +235,12 @@ Worked outputs from each skill — what "good" looks like. Use as reference when
|
|
|
235
235
|
| [report-example.md](report-example.md) | `ux-audit` | UX audit report — TL;DR pyramid, severity-aggregated findings, citations, code diffs, "things that work well". |
|
|
236
236
|
| [email-transactional-example.md](email-transactional-example.md) | `document-author` (email) | Korean fintech transactional email — preheader, receipt structure, bulletproof button, sender info per 정보통신망법. |
|
|
237
237
|
|
|
238
|
+
### Feature flow specs
|
|
239
|
+
|
|
240
|
+
| File | Skill | Demonstrates |
|
|
241
|
+
| --- | --- | --- |
|
|
242
|
+
| [flow-design-report-block.md](flow-design-report-block.md) | `ux-audit` / `design-critique` (`flow-design` route) | Report + block interaction flow. Entry points, step/state tables, edge/error paths, completion criteria, Korean 정보통신망법 제44조의2 임시조치 handling. |
|
|
243
|
+
|
|
238
244
|
### End-to-end deliverables
|
|
239
245
|
|
|
240
246
|
| File | Skill | Demonstrates |
|