deuk-agent-flow 5.0.2 → 5.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.ko.md +45 -0
  2. package/CHANGELOG.md +48 -0
  3. package/bundled/deuk-agent-flow.vsix +0 -0
  4. package/core-rules/AGENTS.md +5 -5
  5. package/package.json +20 -2
  6. package/scripts/bundle-vscode-vsix.ts +1 -1
  7. package/scripts/cli-args.ts +46 -1
  8. package/scripts/cli-context-commands.ts +35 -0
  9. package/scripts/cli-init-claude.ts +179 -0
  10. package/scripts/cli-init-commands.ts +21 -8
  11. package/scripts/cli-init-core.ts +89 -0
  12. package/scripts/cli-init-instructions.ts +489 -0
  13. package/scripts/cli-init-migrate.ts +504 -0
  14. package/scripts/cli-init-workspace.ts +63 -0
  15. package/scripts/cli-locales.ts +85 -0
  16. package/scripts/cli-skill-commands.ts +3 -1
  17. package/scripts/cli-ticket-commands.ts +68 -2
  18. package/scripts/cli-ticket-docmeta.ts +103 -0
  19. package/scripts/cli-ticket-document.ts +153 -0
  20. package/scripts/cli-ticket-evidence.ts +312 -0
  21. package/scripts/cli-ticket-home.ts +449 -0
  22. package/scripts/cli-ticket-index.ts +8 -0
  23. package/scripts/cli-ticket-scan.ts +102 -0
  24. package/scripts/cli-ticket-surface.ts +56 -0
  25. package/scripts/cli.ts +10 -1
  26. package/scripts/oss-prepack.js +32 -0
  27. package/scripts/out/scripts/bundle-vscode-vsix.js +68 -0
  28. package/scripts/out/scripts/bundle-vscode-vsix.js.map +1 -0
  29. package/scripts/out/scripts/cli-args.js +411 -0
  30. package/scripts/out/scripts/cli-args.js.map +1 -0
  31. package/scripts/out/scripts/cli-context-commands.js +31 -0
  32. package/scripts/out/scripts/cli-context-commands.js.map +1 -0
  33. package/scripts/out/scripts/cli-init-claude.js +176 -0
  34. package/scripts/out/scripts/cli-init-claude.js.map +1 -0
  35. package/scripts/out/scripts/cli-init-commands.js +98 -0
  36. package/scripts/out/scripts/cli-init-commands.js.map +1 -0
  37. package/scripts/out/scripts/cli-init-core.js +89 -0
  38. package/scripts/out/scripts/cli-init-core.js.map +1 -0
  39. package/scripts/out/scripts/cli-init-instructions.js +460 -0
  40. package/scripts/out/scripts/cli-init-instructions.js.map +1 -0
  41. package/scripts/out/scripts/cli-init-logic.js +41 -0
  42. package/scripts/out/scripts/cli-init-logic.js.map +1 -0
  43. package/scripts/out/scripts/cli-init-migrate.js +497 -0
  44. package/scripts/out/scripts/cli-init-migrate.js.map +1 -0
  45. package/scripts/out/scripts/cli-init-workspace.js +57 -0
  46. package/scripts/out/scripts/cli-init-workspace.js.map +1 -0
  47. package/scripts/out/scripts/cli-locales.js +83 -0
  48. package/scripts/out/scripts/cli-locales.js.map +1 -0
  49. package/scripts/out/scripts/cli-prompts.js +101 -0
  50. package/scripts/out/scripts/cli-prompts.js.map +1 -0
  51. package/scripts/out/scripts/cli-rule-compiler.js +121 -0
  52. package/scripts/out/scripts/cli-rule-compiler.js.map +1 -0
  53. package/scripts/out/scripts/cli-skill-commands.js +708 -0
  54. package/scripts/out/scripts/cli-skill-commands.js.map +1 -0
  55. package/scripts/out/scripts/cli-telemetry-commands.js +604 -0
  56. package/scripts/out/scripts/cli-telemetry-commands.js.map +1 -0
  57. package/scripts/out/scripts/cli-ticket-command-shared.js +2 -0
  58. package/scripts/out/scripts/cli-ticket-command-shared.js.map +1 -0
  59. package/scripts/out/scripts/cli-ticket-commands.js +3538 -0
  60. package/scripts/out/scripts/cli-ticket-commands.js.map +1 -0
  61. package/scripts/out/scripts/cli-ticket-docmeta.js +90 -0
  62. package/scripts/out/scripts/cli-ticket-docmeta.js.map +1 -0
  63. package/scripts/out/scripts/cli-ticket-document.js +121 -0
  64. package/scripts/out/scripts/cli-ticket-document.js.map +1 -0
  65. package/scripts/out/scripts/cli-ticket-evidence.js +286 -0
  66. package/scripts/out/scripts/cli-ticket-evidence.js.map +1 -0
  67. package/scripts/out/scripts/cli-ticket-home.js +440 -0
  68. package/scripts/out/scripts/cli-ticket-home.js.map +1 -0
  69. package/scripts/out/scripts/cli-ticket-index.js +280 -0
  70. package/scripts/out/scripts/cli-ticket-index.js.map +1 -0
  71. package/scripts/out/scripts/cli-ticket-migration.js +261 -0
  72. package/scripts/out/scripts/cli-ticket-migration.js.map +1 -0
  73. package/scripts/out/scripts/cli-ticket-parser.js +90 -0
  74. package/scripts/out/scripts/cli-ticket-parser.js.map +1 -0
  75. package/scripts/out/scripts/cli-ticket-scan.js +93 -0
  76. package/scripts/out/scripts/cli-ticket-scan.js.map +1 -0
  77. package/scripts/out/scripts/cli-ticket-surface.js +53 -0
  78. package/scripts/out/scripts/cli-ticket-surface.js.map +1 -0
  79. package/scripts/out/scripts/cli-usage-commands.js +310 -0
  80. package/scripts/out/scripts/cli-usage-commands.js.map +1 -0
  81. package/scripts/out/scripts/cli-utils.js +1544 -0
  82. package/scripts/out/scripts/cli-utils.js.map +1 -0
  83. package/scripts/out/scripts/cli.js +705 -0
  84. package/scripts/out/scripts/cli.js.map +1 -0
  85. package/scripts/out/scripts/lint-md.js +238 -0
  86. package/scripts/out/scripts/lint-md.js.map +1 -0
  87. package/scripts/out/scripts/lint-rules.js +193 -0
  88. package/scripts/out/scripts/lint-rules.js.map +1 -0
  89. package/scripts/out/scripts/merge-logic.js +38 -0
  90. package/scripts/out/scripts/merge-logic.js.map +1 -0
  91. package/scripts/out/scripts/plan-parser.js +52 -0
  92. package/scripts/out/scripts/plan-parser.js.map +1 -0
  93. package/scripts/out/scripts/ticket-machine.js +94 -0
  94. package/scripts/out/scripts/ticket-machine.js.map +1 -0
  95. package/scripts/out/scripts/ticket-workflow.js +498 -0
  96. package/scripts/out/scripts/ticket-workflow.js.map +1 -0
  97. package/scripts/ticket-machine.ts +99 -0
  98. package/scripts/ticket-workflow.ts +544 -0
  99. package/templates/skills/role-closer/SKILL.md +27 -0
  100. package/templates/skills/role-implementer/SKILL.md +30 -0
  101. package/templates/skills/role-planner/SKILL.md +29 -0
  102. package/templates/skills/role-qa-verifier/SKILL.md +30 -0
@@ -0,0 +1,280 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, renameSync } from "fs";
2
+ import { basename } from "path";
3
+ import { TICKET_INDEX_FILENAME, requireNonEmptySlug, detectConsumerTicketDir, computeTicketPath, normalizeTicketGroup, writeFileLF, makePath, resolveWorkspaceContext } from "./cli-utils.js";
4
+ import { collectTicketEntriesFromTopicFiles } from "./cli-ticket-scan.js";
5
+ const ARCHIVE_INDEX_MONTH_RE = /^INDEX\.archive\.(\d{4}-\d{2})\.json$/;
6
+ const ARCHIVE_INDEX_LEGACY_RE = /^INDEX\.archive\.json$/;
7
+ function parseNextTicketSequence(value) {
8
+ const raw = Number(value);
9
+ if (!Number.isInteger(raw) || raw < 1)
10
+ return null;
11
+ return raw;
12
+ }
13
+ function maxTicketNumberFromEntries(entries = []) {
14
+ const newRe = /^([0-9]{3,4})-/;
15
+ let max = 0;
16
+ for (const e of (entries || [])) {
17
+ const id = String(e.id || '');
18
+ const m = id.match(newRe);
19
+ if (m) {
20
+ const n = parseInt(m[1], 10);
21
+ if (n > max)
22
+ max = n;
23
+ }
24
+ }
25
+ return max;
26
+ }
27
+ function normalizeNextTicketSequence(nextTicketSequence, entries = []) {
28
+ const fallbackNum = maxTicketNumberFromEntries(entries);
29
+ const fallbackNext = fallbackNum < 9999 ? (fallbackNum + 1) : fallbackNum;
30
+ const parsed = parseNextTicketSequence(nextTicketSequence);
31
+ if (parsed === null)
32
+ return fallbackNext || 1;
33
+ return Math.max(parsed, fallbackNext || 1);
34
+ }
35
+ function writeJsonFileAtomically(absPath, data) {
36
+ const serialized = JSON.stringify(data, null, 2) + "\n";
37
+ const tmpPath = `${absPath}.tmp-${process.pid}-${Date.now()}`;
38
+ writeFileLF(tmpPath, serialized);
39
+ try {
40
+ renameSync(tmpPath, absPath);
41
+ }
42
+ catch (err) {
43
+ // POSIX rename(2)은 대상을 원자적으로 덮어쓰지만, Windows renameSync는 대상이
44
+ // 이미 있으면 EEXIST/EPERM으로 throw한다. 그 경우 대상을 먼저 지우고 재시도하고,
45
+ // 그래도 실패하면 직접 덮어쓰기로 폴백한다. 어느 경로든 tmp는 남기지 않는다.
46
+ try {
47
+ if (existsSync(absPath)) {
48
+ unlinkSync(absPath);
49
+ renameSync(tmpPath, absPath);
50
+ }
51
+ else {
52
+ throw err;
53
+ }
54
+ }
55
+ catch {
56
+ writeFileLF(absPath, serialized);
57
+ if (existsSync(tmpPath)) {
58
+ try {
59
+ unlinkSync(tmpPath);
60
+ }
61
+ catch { /* best-effort cleanup */ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ function listArchiveIndexFiles(dir) {
67
+ if (!existsSync(dir))
68
+ return [];
69
+ return readdirSync(dir, { withFileTypes: true })
70
+ .filter(ent => ent.isFile())
71
+ .map(ent => makePath(dir, ent.name))
72
+ .filter(abs => ARCHIVE_INDEX_LEGACY_RE.test(basename(abs)) || ARCHIVE_INDEX_MONTH_RE.test(basename(abs)))
73
+ .sort((a, b) => {
74
+ const aBase = basename(a);
75
+ const bBase = basename(b);
76
+ const aMatch = aBase.match(ARCHIVE_INDEX_MONTH_RE);
77
+ const bMatch = bBase.match(ARCHIVE_INDEX_MONTH_RE);
78
+ if (aMatch && !bMatch)
79
+ return 1;
80
+ if (!aMatch && bMatch)
81
+ return -1;
82
+ if (!aMatch && !bMatch)
83
+ return aBase.localeCompare(bBase);
84
+ return aMatch[1].localeCompare(bMatch[1]);
85
+ });
86
+ }
87
+ function parseIndexFile(absPath) {
88
+ if (!existsSync(absPath)) {
89
+ return { version: 1, updatedAt: null, nextTicketSequence: 1, entries: [] };
90
+ }
91
+ try {
92
+ const j = JSON.parse(readFileSync(absPath, "utf8"));
93
+ const entries = Array.isArray(j.entries) ? j.entries.map(e => {
94
+ const entry = { ...e, status: e.status || "open", group: normalizeTicketGroup(e.group, "sub") };
95
+ entry.path = computeTicketPath(entry);
96
+ return entry;
97
+ }) : [];
98
+ // activeTicketId/activeTickets are no longer read from INDEX.json — focus is
99
+ // owned solely by the marker file. Any legacy fields on disk are ignored.
100
+ return {
101
+ version: j.version || 1,
102
+ updatedAt: j.updatedAt ?? null,
103
+ nextTicketSequence: parseNextTicketSequence(j.nextTicketSequence),
104
+ entries
105
+ };
106
+ }
107
+ catch (err) {
108
+ console.error(`[ERROR] Failed to parse ${basename(absPath)} at ${absPath}:`, err.message);
109
+ return { version: 1, updatedAt: null, nextTicketSequence: 1, entries: [], _corrupt: true };
110
+ }
111
+ }
112
+ function getWorkspaceKey(cwd) {
113
+ return resolveWorkspaceContext(cwd).breadcrumb;
114
+ }
115
+ function getWorkspaceSlug(cwd) {
116
+ const key = getWorkspaceKey(cwd);
117
+ return key.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'default';
118
+ }
119
+ function splitEntriesForStorage(entries = []) {
120
+ const activeEntries = [];
121
+ const archiveEntries = [];
122
+ for (const entry of entries) {
123
+ const status = String(entry?.status || "open").toLowerCase();
124
+ const phase = Number(entry?.phase || 1);
125
+ if ((status === "open" || status === "active") && phase < 4 && !entry?.archiveYearMonth) {
126
+ activeEntries.push(entry);
127
+ }
128
+ else {
129
+ archiveEntries.push(entry);
130
+ }
131
+ }
132
+ return { activeEntries, archiveEntries };
133
+ }
134
+ export function readTicketIndexJson(cwd) {
135
+ const dir = detectConsumerTicketDir(cwd);
136
+ if (!dir)
137
+ return { version: 1, updatedAt: null, entries: [] };
138
+ const mainPath = makePath(dir, TICKET_INDEX_FILENAME);
139
+ const main = parseIndexFile(mainPath);
140
+ // The pointer file no longer stores entries — the ticket list is derived from
141
+ // the .md files (single source of truth). Scan them here so every consumer of
142
+ // readTicketIndexJson still sees a populated entry list.
143
+ const entries = collectTicketEntriesFromTopicFiles(cwd).map(entry => {
144
+ const next = { ...entry, status: entry.status || "open", group: normalizeTicketGroup(entry.group, "sub") };
145
+ next.path = computeTicketPath(next);
146
+ return next;
147
+ });
148
+ // #685: LangGraph 모델 — state(현재 노드)는 .md 프론트매터(phase/status)가 유일 SSOT.
149
+ // sessionId/쿠키/claim 폴백 레이어는 전면 제거됨. 현재 노드(activeTicketId)는 디스크의
150
+ // .md 스캔 결과에서 결정적으로 도출한다: live = (open/active) AND phase<4.
151
+ // 여러 개 live면 가장 진행된 노드(phase 높은 것, 동률이면 최신 createdAt)가 현재 노드.
152
+ // 값이 없으면 폴백이 아니라 "현재 노드 없음(null) = START 진입점"이다.
153
+ const liveEntries = entries.filter(e => {
154
+ const status = String(e.status || "open").toLowerCase();
155
+ return (status === "open" || status === "active") && Number(e.phase || 1) < 4 && !e.archiveYearMonth;
156
+ });
157
+ const sortedLive = [...liveEntries].sort((a, b) => {
158
+ const phaseDiff = Number(b.phase || 1) - Number(a.phase || 1);
159
+ if (phaseDiff !== 0)
160
+ return phaseDiff;
161
+ return String(b.createdAt || "").localeCompare(String(a.createdAt || ""));
162
+ });
163
+ const activeTicketId = sortedLive.length > 0 ? sortedLive[0].id : null;
164
+ return {
165
+ version: main.version || 1,
166
+ updatedAt: main.updatedAt ?? null,
167
+ activeTicketId,
168
+ liveTicketIds: sortedLive.map(e => e.id),
169
+ nextTicketSequence: normalizeNextTicketSequence(main.nextTicketSequence, entries),
170
+ entries,
171
+ _corrupt: Boolean(main._corrupt)
172
+ };
173
+ }
174
+ export function writeTicketIndexJson(cwd, indexJson, opts = {}) {
175
+ if (indexJson._corrupt && !opts.force) {
176
+ console.error(`[ABORT] Refusing to overwrite potentially corrupt ${TICKET_INDEX_FILENAME}. Use --force to override.`);
177
+ return;
178
+ }
179
+ const dir = detectConsumerTicketDir(cwd, { createIfMissing: true });
180
+ // #776: dir이 null이면(워크스페이스 마커 미존재 등) 조용히 mkdirSync(null)로 throw하던
181
+ // 것을 막는다. 정상 흐름에선 init이 마커를 먼저 민팅하므로 여기 도달 시 dir은 non-null.
182
+ // 그래도 도달하면 ticket index는 .md에서 재도출 가능한 얇은 포인터일 뿐이라, 명확히
183
+ // 알리고 skip한다(치명적 throw로 상위 init 전체를 위장 실패시키지 않는다).
184
+ if (!dir) {
185
+ console.warn(`[TICKET-INDEX] skipped: no ticket dir resolved for ${cwd} (workspace marker missing?)`);
186
+ return;
187
+ }
188
+ const p = makePath(dir, TICKET_INDEX_FILENAME);
189
+ if (opts.dryRun)
190
+ return;
191
+ mkdirSync(dir, { recursive: true });
192
+ // The pointer file is a THIN focus-state file. The ticket list itself is
193
+ // derived from .md files (the single source of truth), so we never persist
194
+ // entries or per-month archive index files. We keep only the two facts that
195
+ // cannot be re-derived from .md alone: the focus pointer (activeTicketId) and
196
+ // the monotonically increasing next ticket number (nextTicketSequence).
197
+ const entries = Array.isArray(indexJson.entries) ? indexJson.entries : [];
198
+ const currentDiskState = parseIndexFile(p);
199
+ // nextTicketSequence must never go backwards: max of the stored pointer and
200
+ // (highest known ticket number across ALL entries, active or archived) + 1.
201
+ const callerNextSequence = normalizeNextTicketSequence(indexJson.nextTicketSequence, entries);
202
+ const diskNextSequence = normalizeNextTicketSequence(currentDiskState.nextTicketSequence, entries);
203
+ const nextTicketSequence = Math.max(callerNextSequence, diskNextSequence);
204
+ const out = {
205
+ version: indexJson.version || 1,
206
+ updatedAt: indexJson.updatedAt || new Date().toISOString(),
207
+ // activeTickets is deliberately omitted to prevent centralized contention
208
+ nextTicketSequence
209
+ };
210
+ writeJsonFileAtomically(p, out);
211
+ // Remove any legacy per-month archive index files — entries are no longer
212
+ // persisted, so these stale duplicates must not linger.
213
+ for (const filePath of listArchiveIndexFiles(dir)) {
214
+ unlinkSync(filePath);
215
+ }
216
+ }
217
+ // #675: Claims ticketId for the current session using cookie touch file.
218
+ // Pass ticketId=null to release.
219
+ export function setActiveTicketMarker(cwd, ticketId, opts = {}) {
220
+ // #685: LangGraph 모델 — 현재 노드는 .md phase가 SSOT다. 노드 위치를 쿠키/마커에
221
+ // 별도 저장하지 않는다(폴백 레이어 전면 제거). 이 함수는 하위 호환을 위한 no-op이며,
222
+ // 노드 이동은 ticket move가 .md phase를 갱신하는 것으로만 일어난다.
223
+ return;
224
+ }
225
+ // #685: getHostnameSlug 제거 — 티켓 ID에서 hostname suffix를 뺐으므로 불필요(언니 지시).
226
+ // #685: claim/actor/세션 마커 레이어 전면 제거 — LangGraph 모델에서 현재 노드는 .md
227
+ // phase가 SSOT이고 단일 사용자 환경이라 "누가 티켓을 잡았나" 추적이 불필요하다.
228
+ // resolveActor/readClaim/writeClaim/releaseClaim/isClaimStale/migrateLegacyActiveMarkers
229
+ // (전부 sessionId 쿠키 폴백 의존)와 CLAIM_STALE_MS를 삭제했다.
230
+ export function computeNextTicketNumber(indexState) {
231
+ const maybeEntries = Array.isArray(indexState) ? indexState : indexState?.entries;
232
+ const parsedNext = normalizeNextTicketSequence(indexState?.nextTicketSequence, maybeEntries);
233
+ return { num: parsedNext };
234
+ }
235
+ export function generateTicketId(titleSlug, indexState) {
236
+ // #685: 티켓 ID의 hostname suffix(-joy-deep 등) 제거 — 단일 환경이라 호스트 구분이
237
+ // 무의미하다(언니 지시). ID는 {num}-{slug}로만 구성한다.
238
+ const slug = requireNonEmptySlug(titleSlug, "ticket title");
239
+ const match = slug.match(/^(\d{3,4})-(.*)/);
240
+ const idSlug = match ? requireNonEmptySlug(match[2], "ticket title") : slug;
241
+ if (/^\d{3,4}$/.test(idSlug)) {
242
+ throw new Error("[VALIDATION FAILED] ticket title must include a non-numeric slug; ticket numbers are assigned by INDEX nextTicketSequence.");
243
+ }
244
+ const { num } = computeNextTicketNumber(indexState);
245
+ const numStr = String(num).padStart(3, '0');
246
+ const finalSlug = idSlug.slice(0, 32);
247
+ return `${numStr}-${finalSlug}`;
248
+ }
249
+ export function syncActiveTicketId(cwd, opts = {}) {
250
+ // #685: LangGraph 모델 — 현재 노드는 .md phase가 SSOT라 마커 동기화가 불필요하다.
251
+ // 이 함수는 이제 레거시 포인터 파일(LATEST.md/ACTIVE_TICKET.*) 정리만 담당한다.
252
+ const ticketDir = detectConsumerTicketDir(cwd);
253
+ if (!ticketDir)
254
+ return;
255
+ if (opts.dryRun)
256
+ return;
257
+ const legacyLatestPath = makePath(ticketDir, "LATEST.md");
258
+ const pointerPathMd = makePath(ticketDir, "ACTIVE_TICKET.md");
259
+ const pointerPathJson = makePath(ticketDir, "ACTIVE_TICKET.json");
260
+ for (const p of [legacyLatestPath, pointerPathMd, pointerPathJson]) {
261
+ if (existsSync(p)) {
262
+ unlinkSync(p);
263
+ }
264
+ }
265
+ }
266
+ export async function syncToPipeline(url, data) {
267
+ try {
268
+ const response = await fetch(url, {
269
+ method: "POST",
270
+ headers: { "Content-Type": "application/json" },
271
+ body: JSON.stringify(data),
272
+ signal: AbortSignal?.timeout ? AbortSignal.timeout(3000) : undefined
273
+ });
274
+ return response.ok;
275
+ }
276
+ catch (err) {
277
+ return false;
278
+ }
279
+ }
280
+ //# sourceMappingURL=cli-ticket-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-ticket-index.js","sourceRoot":"","sources":["../../cli-ticket-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,261 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, copyFileSync, renameSync } from "fs";
2
+ import { basename, dirname } from "path";
3
+ import { toRepoRelativePath, TICKET_SUBDIR, TICKET_LIST_FILENAME, parseFrontMatter, findFileRecursively, detectConsumerTicketDir, makePath } from "./cli-utils.js";
4
+ import { readTicketIndexJson, syncActiveTicketId, writeTicketIndexJson } from "./cli-ticket-index.js";
5
+ import { collectTicketMarkdownFiles, rebuildTicketIndexFromTopicFilesIfNeeded } from "./cli-ticket-parser.js";
6
+ import { splitTicketDocMetaSection } from "./cli-ticket-docmeta.js";
7
+ import { writeTicketDocument } from "./cli-ticket-document.js";
8
+ // ─── Summary Extraction ─────────────────────────────────────────────────────
9
+ /**
10
+ * Extracts a concise summary from ticket body content for legacy tickets.
11
+ * Strategy: combine title + scope/background + top tasks into 1-2 lines.
12
+ * Handles 3 legacy formats:
13
+ * - Old format: 🎯 Scope Bounds, 📁 Files to Modify
14
+ * - Mid format: ## Background, ## Analysis, ## Tasks
15
+ * - New format: ## Target Module, ## APC (already has summary usually)
16
+ */
17
+ export function extractSummary(meta, content) {
18
+ const title = meta.title || "";
19
+ const lines = content.split("\n");
20
+ // Collect section contents by known header patterns
21
+ const sections = {};
22
+ let currentSection = null;
23
+ for (const line of lines) {
24
+ const trimmed = line.trim();
25
+ // Match ## headers (with or without emoji prefix)
26
+ const headerMatch = trimmed.match(/^##\s+(?:[\u{1F3AF}\u{1F4C1}\u{1F3D7}\u{1F6D1}\u{1F504}\u{2705}\s]*)?(.+)$/u);
27
+ if (headerMatch) {
28
+ currentSection = headerMatch[1].trim().toLowerCase();
29
+ sections[currentSection] = [];
30
+ continue;
31
+ }
32
+ // Match # title
33
+ if (trimmed.startsWith("# ") && !currentSection) {
34
+ continue; // skip title line
35
+ }
36
+ if (currentSection && trimmed && !trimmed.startsWith(">") && !trimmed.startsWith("<!--")) {
37
+ sections[currentSection].push(trimmed);
38
+ }
39
+ }
40
+ // Priority: scope/background > analysis > tasks
41
+ let contextLine = "";
42
+ // Try scope bounds (old format)
43
+ const scopeKeys = Object.keys(sections).filter(k => k.includes("scope") || k.includes("target") || k.includes("background"));
44
+ for (const key of scopeKeys) {
45
+ const scopeLines = (sections[key] || [])
46
+ .filter(l => !l.startsWith("- **Context") && !l.startsWith("["))
47
+ .map(l => l.replace(/^[-*]\s*\*\*[^*]+:\*\*\s*/, "").replace(/`/g, ""))
48
+ .filter(l => l.length > 5 && l.length < 200);
49
+ if (scopeLines.length > 0) {
50
+ contextLine = scopeLines[0];
51
+ break;
52
+ }
53
+ }
54
+ // Try analysis section if no scope found
55
+ if (!contextLine) {
56
+ const analysisKeys = Object.keys(sections).filter(k => k.includes("analysis") || k.includes("design") || k.includes("decisions"));
57
+ for (const key of analysisKeys) {
58
+ const analysisLines = (sections[key] || [])
59
+ .filter(l => l.length > 10 && l.length < 200 && !l.startsWith("|"))
60
+ .map(l => l.replace(/^[-*]\s*/, ""));
61
+ if (analysisLines.length > 0) {
62
+ contextLine = analysisLines[0];
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ // Collect task summary (first 3 task items)
68
+ const taskKeys = Object.keys(sections).filter(k => k.includes("task") || k.includes("phased") || k.includes("execution steps"));
69
+ let taskItems = [];
70
+ for (const key of taskKeys) {
71
+ taskItems = (sections[key] || [])
72
+ .filter(l => /^-\s*\[[ x]\]/.test(l) || /^\d+\.\s*\[/.test(l))
73
+ .map(l => l.replace(/^[-*\d.]+\s*\[[ x]\]\s*/, "").replace(/\[Phase\s*\d+[>]\s*/i, "").replace(/]/g, "").trim())
74
+ .filter(l => l.length > 3)
75
+ .slice(0, 3);
76
+ if (taskItems.length > 0)
77
+ break;
78
+ }
79
+ // Build summary
80
+ const parts = [];
81
+ if (contextLine) {
82
+ parts.push(contextLine.length > 120 ? contextLine.substring(0, 117) + "..." : contextLine);
83
+ }
84
+ if (taskItems.length > 0) {
85
+ parts.push(`주요 작업: ${taskItems.join(", ")}`);
86
+ }
87
+ if (parts.length === 0) {
88
+ // Fallback: use title itself as summary
89
+ return title || null;
90
+ }
91
+ const summary = parts.join(". ").substring(0, 300);
92
+ return summary || null;
93
+ }
94
+ // ─── CAUTION Block / Target Module Injection ─────────────────────────────────
95
+ const CAUTION_BLOCK = `> **[CAUTION FOR AI AGENTS]**
96
+ > 1. Restrict all analysis, file creation, and modifications to the declared **Target Module** below.
97
+ > 2. Read the files listed in **Context Files** before doing ANY code generation.
98
+ > 3. DO NOT leak configuration, logic, or dependencies from other modules.
99
+
100
+ ## Target Module
101
+ - **Target:** [Fill in the target module/submodule path]
102
+ - **Context Files:** [List architecture docs or key files to read first]`;
103
+ /**
104
+ * Ensures the CAUTION block and Target Module section exist after the title.
105
+ * Returns modified content or null if no change needed.
106
+ */
107
+ export function ensureCautionBlock(content) {
108
+ // Already has Target Module or the new-format CAUTION
109
+ if (content.includes("## Target Module"))
110
+ return null;
111
+ // Also skip if it already has the old-format scope bounds (don't duplicate)
112
+ const hasOldScope = /## [\u{1F3AF}]?\s*Scope Bounds/u.test(content);
113
+ if (hasOldScope)
114
+ return null;
115
+ // Find the # title line and insert after it
116
+ const titleMatch = content.match(/^(# .+)\n/m);
117
+ if (!titleMatch)
118
+ return null;
119
+ const titleEnd = content.indexOf(titleMatch[0]) + titleMatch[0].length;
120
+ const before = content.substring(0, titleEnd);
121
+ let after = content.substring(titleEnd);
122
+ // Skip if CAUTION already exists (old variant)
123
+ if (after.includes("[CAUTION FOR AI AGENTS]"))
124
+ return null;
125
+ return before + "\n" + CAUTION_BLOCK + "\n" + after;
126
+ }
127
+ // ─── Main Migration ─────────────────────────────────────────────────────────
128
+ export function performUpgradeMigration(cwd, opts = {}) {
129
+ const root = detectConsumerTicketDir(cwd, { createIfMissing: true });
130
+ const files = collectTicketMarkdownFiles(root).filter(p => {
131
+ const base = basename(p);
132
+ return base !== "LATEST.md" && base !== TICKET_LIST_FILENAME && base !== "ACTIVE_TICKET.md";
133
+ });
134
+ console.log(`[UPGRADE] Scanning ${files.length} tickets for V2 migration...`);
135
+ let upgraded = 0;
136
+ let summaryAdded = 0;
137
+ let cautionAdded = 0;
138
+ for (const abs of files) {
139
+ const rel = toRepoRelativePath(cwd, abs);
140
+ const body = readFileSync(abs, "utf8");
141
+ const { meta, content } = parseFrontMatter(body);
142
+ let dirty = false;
143
+ let modifiedContent = content;
144
+ const isAlreadyInArchive = rel.includes("/archive/");
145
+ // 1. Summary enrichment for legacy tickets
146
+ if (!meta.summary) {
147
+ const generated = extractSummary(meta, content);
148
+ if (generated) {
149
+ meta.summary = generated;
150
+ dirty = true;
151
+ summaryAdded++;
152
+ }
153
+ }
154
+ // 2. CAUTION / Target Module injection
155
+ const cautionResult = ensureCautionBlock(modifiedContent);
156
+ if (cautionResult !== null) {
157
+ modifiedContent = cautionResult;
158
+ dirty = true;
159
+ cautionAdded++;
160
+ }
161
+ // 3. Archive placement fix (existing logic)
162
+ if (meta.status === "archived" && !isAlreadyInArchive && !opts.dryRun) {
163
+ const finalAbs = moveFileToArchive(cwd, abs, meta.group || basename(dirname(abs)));
164
+ const ticketDocMeta = splitTicketDocMetaSection(modifiedContent);
165
+ writeTicketDocument(finalAbs, { meta, content: ticketDocMeta.body, docmeta: ticketDocMeta.docmeta });
166
+ upgraded++;
167
+ console.log(`[OK] Upgraded + archived: ${toRepoRelativePath(cwd, finalAbs)}`);
168
+ continue;
169
+ }
170
+ if (dirty) {
171
+ if (opts.dryRun) {
172
+ const changes = [];
173
+ if (!parseFrontMatter(body).meta.summary && meta.summary)
174
+ changes.push("summary");
175
+ if (cautionResult !== null)
176
+ changes.push("caution+targetModule");
177
+ console.log(`[DRY-RUN] Would upgrade: ${rel} (+${changes.join(", ")})`);
178
+ }
179
+ else {
180
+ const ticketDocMeta = splitTicketDocMetaSection(modifiedContent);
181
+ writeTicketDocument(abs, { meta, content: ticketDocMeta.body, docmeta: ticketDocMeta.docmeta });
182
+ upgraded++;
183
+ }
184
+ }
185
+ }
186
+ console.log(`[UPGRADE] Results: ${upgraded} upgraded, ${summaryAdded} summaries added, ${cautionAdded} caution blocks added`);
187
+ if (!opts.dryRun) {
188
+ rebuildTicketIndexFromTopicFilesIfNeeded(cwd, { ...opts, force: true });
189
+ syncActiveTicketId(cwd);
190
+ }
191
+ return upgraded;
192
+ }
193
+ // #727: performDefragmentation 제거 — 홈 uuid 스토어의 티켓을 meta.submodule 기준으로
194
+ // 서브모듈 .deuk/tickets 로 역이동(cwd write)시켜 홈 일원화(#622)를 되돌리던 코드였다.
195
+ // normalizeTicketPaths 주석('티켓은 홈에 산다, cwd로 끌어내면 안 됨')과 정면 모순이라
196
+ // 함수와 호출(upgrade 흐름)을 통째로 제거. 티켓은 홈에만 산다.
197
+ // ─── Utilities ──────────────────────────────────────────────────────────────
198
+ export function moveFileToArchive(cwd, abs, group) {
199
+ const ticketDir = detectConsumerTicketDir(cwd);
200
+ const archiveBase = makePath(ticketDir, "archive");
201
+ const targetSubDir = (basename(ticketDir) === TICKET_SUBDIR || !group) ? "sub" : group;
202
+ const targetDir = makePath(archiveBase, targetSubDir);
203
+ mkdirSync(targetDir, { recursive: true });
204
+ const finalAbs = makePath(targetDir, basename(abs));
205
+ if (finalAbs !== abs) {
206
+ if (existsSync(finalAbs)) {
207
+ unlinkSync(abs);
208
+ }
209
+ else {
210
+ writeFileSync(finalAbs, readFileSync(abs, "utf8"), "utf8");
211
+ unlinkSync(abs);
212
+ }
213
+ }
214
+ return finalAbs;
215
+ }
216
+ export function normalizeTicketPaths(cwd, opts = {}) {
217
+ const index = readTicketIndexJson(cwd);
218
+ const ticketDir = detectConsumerTicketDir(cwd);
219
+ const entries = index.entries || [];
220
+ let modified = false;
221
+ for (const entry of entries) {
222
+ if (!entry.path)
223
+ continue;
224
+ // #622/#623: 티켓 .md는 cwd(워크스페이스 git 트리)가 아니라 홈 ticketDir에 산다.
225
+ // 정상 위치는 makePath(ticketDir, entry.path)이다. entry.path를 cwd 기준으로 해석해
226
+ // 그쪽으로 옮기면, 홈에 멀쩡히 있던 .md를 워크스페이스로 끌어내 홈 디렉토리를 비우고
227
+ // (그 순간 rebuild 스캔이 entries=0을 보고 active claim을 고아로 오인해 삭제한다).
228
+ // 따라서 파일이 이미 ticketDir 하위에 있으면 그게 올바른 위치이므로 이동하지 않는다.
229
+ const canonicalAbs = makePath(ticketDir, entry.path);
230
+ if (existsSync(canonicalAbs))
231
+ continue;
232
+ const currentAbs = makePath(cwd, entry.path);
233
+ if (!existsSync(currentAbs)) {
234
+ const fileName = basename(entry.path);
235
+ const found = findFileRecursively(ticketDir, fileName);
236
+ if (found) {
237
+ // 발견된 파일이 이미 홈 ticketDir 하위면 정상 위치 — 워크스페이스로 옮기지 않는다.
238
+ const destAbs = canonicalAbs;
239
+ if (found !== destAbs) {
240
+ mkdirSync(dirname(destAbs), { recursive: true });
241
+ try {
242
+ renameSync(found, destAbs);
243
+ }
244
+ catch {
245
+ copyFileSync(found, destAbs);
246
+ unlinkSync(found);
247
+ }
248
+ modified = true;
249
+ }
250
+ }
251
+ }
252
+ }
253
+ if (modified) {
254
+ index.updatedAt = new Date().toISOString();
255
+ writeTicketIndexJson(cwd, index);
256
+ if (!opts.silent)
257
+ console.log(`[NORMALIZE] Corrected stale paths in ${basename(cwd)}/INDEX.json`);
258
+ }
259
+ return modified;
260
+ }
261
+ //# sourceMappingURL=cli-ticket-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-ticket-migration.js","sourceRoot":"","sources":["../../cli-ticket-migration.ts"],"names":[],"mappings":"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"}