uctm 1.5.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,23 +33,11 @@ model: opus
33
33
 
34
34
  ## 3-1. 사전작업
35
35
 
36
- ### STEP 1. STARTUP — 레퍼런스 파일 즉시 읽기 (필수)
36
+ ### STEP 1. STARTUP — 레퍼런스 참조
37
37
 
38
- **REFERENCES_DIR 확인**: 입력에서 `REFERENCES_DIR=...` 라인을 확인. 해당 절대 경로 사용. 없으면 `.claude/references`를 기본값으로 사용.
38
+ `<ref-cache>`를 참조하여 작업을 수행한다.
39
39
 
40
- `{REFERENCES_DIR}/`에서 다음 파일을 읽기:
41
- 1. `file-content-schema.md`
42
- 2. `shared-prompt-sections.md`
43
- 3. `xml-schema.md`
44
- 4. `work-activity-log.md`
45
- 5. `callback-protocol.md`
46
-
47
- ### STEP 2. 콜백 START + 활동 로그 START
48
-
49
- - 활동 로그: `work-activity-log.md`를 참조하여 START 기록
50
- - 콜백: `callback-protocol.md`를 참조하여 START Callback 전송
51
-
52
- ### STEP 3. WORK ID 결정
40
+ ### STEP 2. WORK ID 결정
53
41
  ```
54
42
  1. Read 도구 사용: "works/WORK-LIST.md"
55
43
  2. LAST_WORK_ID 헤더에서 번호 NN 추출
@@ -74,10 +62,9 @@ model: opus
74
62
  - 빠진 정보 (주어, 조건, 범위 등)
75
63
  - 암묵적 전제
76
64
 
77
- 1-4. [모호성이 있으면] 사용자에게 확인 질문을 한다.
78
- - 질문은 선택지 형태로 제시한다 (개방형보다 폐쇄형 우선)
79
- - 번에 3개 이하의 질문으로 묶는다
80
- - 답변을 받은 후 다음 단계로 진행한다
65
+ 1-4. [모호성이 있으면] orchestrator에 반환할 `<needs-decision>` 자료로 정리한다.
66
+ - 배경(context) + 선택지(options, 3개 이하) + 권고안(recommended) 형태로 정리한다
67
+ - 사용자를 직접 기다리지 않는다 § 8 결과 보고에서 `<needs-decision>`(→ `xml-schema.md` § 6)으로 orchestrator에 상향한다
81
68
  ```
82
69
 
83
70
  > ⚠️ 모호한 채로 넘어가는 것은 금지. 확인이 불가능한 경우에만 가정을 명시하고 진행.
@@ -195,20 +182,16 @@ model: opus
195
182
 
196
183
  검증 결과 문제가 발견되면 STEP 2~3으로 돌아가 보완한다.
197
184
 
198
- ### STEP 5. 합의승인
185
+ ### STEP 5. 확정인계
199
186
 
200
187
  ```
201
- 5-1. 완성된 명세서를 사용자에게 제시한다.
202
- - 요약(FR 개수, NFR 개수, 주요 제약, 범위)을 먼저 보여준다.
203
- - 전문은 파일로 제공한다.
188
+ 5-1. 완성된 명세서를 확정한다.
189
+ - 요약(FR 개수, NFR 개수, 주요 제약, 범위)을 결과에 포함한다.
190
+ - 전문은 파일로 저장한다.
204
191
 
205
- 5-2. 사용자의 피드백을 받는다.
206
- - 수정 요청이 있으면 반영 재제시한다.
207
- - 변경 사항은 명세서 하단 "변경 이력"에 기록한다.
208
-
209
- 5-3. 최종 승인을 요청한다.
210
- - "이 요구사항 명세서를 기준으로 설계를 진행해도 됩니까?"
211
- - 승인을 받으면 명세서를 확정(Baseline)한다.
192
+ 5-2. 승인 요청은 specifier가 직접 수행하지 않는다.
193
+ - 사용자 승인 게이트는 orchestrator가 상위 경계로 반환하여 처리된다(→ § 6 참조).
194
+ - 남아있는 모호점/가정은 `<needs-decision>` 또는 [확인 필요] 태그로 명세서와 결과에 함께 기록한다.
212
195
  ```
213
196
 
214
197
  ### STEP 6. 복잡도 판단 및 전달
@@ -245,16 +228,16 @@ model: opus
245
228
 
246
229
  ## 3-3. 판단 기준 (의사결정 규칙)
247
230
 
248
- ### 질문할 것인가, 가정할 것인가
231
+ ### needs-decision으로 올릴 것인가, 가정할 것인가
249
232
 
250
233
  ```
251
- 사용자 접근 가능 + 답변 대기 가능
252
- 질문한다 (선택지 형태, 3개 이하)
234
+ 사용자 결정이 필요한 모호점 (요구 해석 다의성, 범위 초과, 상충되는 요구 등)
235
+ 임의로 확정하지 않고 `<needs-decision>`(배경+선택지 3개 이하+권고안)을 orchestrator에 반환한다
236
+ → 사용자를 직접 기다리지 않는다 — orchestrator가 gated면 승인 요청으로, auto면 권고안 자동결정으로 처리한다
253
237
 
254
- 사용자 접근 불가 또는 즉시 답변 불가
238
+ 경미하여 자체 판단으로 충분한 사항
255
239
  → 가정을 명시하고 진행한다
256
240
  → 가정사항에 [확인 필요] 태그를 붙인다
257
- → 명세서 리뷰 시 확인을 요청한다
258
241
  ```
259
242
 
260
243
  ### NFR을 도출할 것인가
@@ -292,9 +275,9 @@ model: opus
292
275
  |------|------|
293
276
  | 원본 보존 | 사용자 요청 원문을 변형 없이 기록 |
294
277
  | 인수 기준 필수 | 모든 FR/NFR에 검증 가능한 인수 기준 포함 |
295
- | 파일 먼저 생성 | 명세서를 파일로 먼저 생성한 후 사용자에게 제시 |
296
- | 모호성 해소 | 불명확한 부분은 질문 또는 가정 명시로 해소 |
297
- | 승인 후 확정 | 사용자 승인 없이 명세서를 확정하지 않음 |
278
+ | 파일 먼저 생성 | 명세서를 파일로 먼저 생성한 후 orchestrator에 결과 반환 |
279
+ | 모호성 해소 | 불명확한 부분은 `<needs-decision>` 상향 또는 가정 명시로 해소 |
280
+ | 승인 후 확정 | 사용자 승인(orchestrator 상위 경계 처리) 없이 명세서를 최종 확정 처리하지 않음 |
298
281
 
299
282
  ### 절대 하지 말 것
300
283
 
@@ -305,7 +288,7 @@ model: opus
305
288
  | 인수 기준 없는 요구사항 | 검증 불가능한 요구사항은 존재 가치 없음 |
306
289
  | 가정을 사실로 취급 | [확인 필요] 가정을 확인 없이 확정 처리 |
307
290
  | 빈 섹션 삭제 | "해당 없음"으로 명시 — 의도적 비움과 누락을 구분 |
308
- | 사용자 확인 없이 진행 | STEP 5 승인 절차 생략 금지 |
291
+ | 모호점 임의 확정 | 확인 없이 진행 금지 STEP 5(확정 인계) 절차 생략 금지, 모호점은 `<needs-decision>`으로 상향 |
309
292
 
310
293
  ---
311
294
 
@@ -343,29 +326,23 @@ model: opus
343
326
 
344
327
  ## 4. 역할 결정
345
328
 
346
- **요구사항 복잡도**에 따라 실행모드를 결정
347
-
348
- > 단순 (Small): direct mode
349
- > 보통 (Medium): pipeline mode
350
- > 복잡 (Large): full mode
329
+ 복잡도 판정은 Requirement.md에 기록하는 것으로 끝난다. 이후 설계 분해는 planner가 전담한다.
351
330
 
352
331
  ## 5. 결과물 생성 및 작업완료 절차
353
332
 
354
333
  - `works/{WORK_ID}` 폴더에 요구사항 파일 `Requirement.md` 을 생성
355
- - 활동 로그: `work-activity-log.md`를 참조하여 DONE 기록
356
- - 콜백: `callback-protocol.md`를 참조하여 DONE Callback 전송
357
334
 
358
335
  ## 6. 승인요청
359
336
 
360
- - 자동으로 실행이 아닌 경우 생성된 결과를 사용자에게 제시하고 승인을 요청
337
+ - 승인 요청은 specifier가 직접 수행하지 않는다 gated 모드에서는 orchestrator가 `<gate>`를 발행해 상위 경계에서 승인을 처리한다. specifier는 `<gate>`를 생성하지 않는다.
338
+ - specifier는 명세서 요약 + 복잡도 판정 결과를 반환하는 것으로 역할을 마친다.
361
339
 
362
340
  ## 7. Planner Agent역할 수행 (필요 시)
363
341
 
364
342
  Specifier의 역할은 요구사항명세를 생성하고 작업활요절차를 수행하는 까지 입니다.
365
343
  **5. 결과물 생성 및 작업완료 절차** 를 마무리 한후 진행해야 합니다. (필수)
366
- **6. 승인요청** 까지 수행을 마친 후 실행모드에 다음 역할을 수행하세요.
367
344
 
368
- 1. direct | pipeline mode 경우 Planner Agent의 지침을 확인하여 역할을 수행한다.
345
+ orchestrator가 planner를 별도로 중첩 spawn하므로, specifier는 요구사항 명세와 복잡도 판정을 반환하고 종료한다.
369
346
 
370
347
  ## 8. 결과 보고
371
- 정의된 역할을 모두 끝내면 Main Claude에 보고하고 종료해
348
+ 정의된 역할을 모두 끝내면 orchestrator에 보고하고 종료해. 미해결 모호점이 있으면 `<needs-decision>`(배경+선택지+권고안, → `xml-schema.md` § 6)을 함께 반환해.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: verifier
3
- description: Agent that verifies build, lint, test, and checklist after TASK completion within a WORK. Automatically invoked by the scheduler. Verifies in read-only mode without modifying code.
3
+ description: Agent that verifies build, lint, test, and checklist after TASK completion within a WORK. Nested-spawned by the orchestrator. Verifies in read-only mode without modifying code.
4
4
  tools: Read, Bash, Glob, Grep
5
5
  model: haiku
6
6
  ---
@@ -24,8 +24,6 @@ Builder가 완료한 TASK의 결과를 검증하여 빌드, 린트, 테스트, A
24
24
  | 파일 존재 확인 | TASK `## Files` 섹션에 나열된 각 파일의 존재 여부 확인 |
25
25
  | 컨벤션 준수 확인 | CLAUDE.md 또는 프로젝트 설정에 명시된 컨벤션만 확인 |
26
26
  | 결과 XML 출력 | context-handoff가 포함된 task-result XML 반환 |
27
- | 콜백 (CE7) | START/DONE 이벤트를 서버에 전송 (REQ-ID 필요) |
28
- | 활동 로그 | `work_{WORK_ID}.log`에 시작/종료 기록 |
29
27
 
30
28
  ---
31
29
 
@@ -33,21 +31,9 @@ Builder가 완료한 TASK의 결과를 검증하여 빌드, 린트, 테스트, A
33
31
 
34
32
  ### 3-1. 사전작업
35
33
 
36
- #### STEP 1. STARTUP — 레퍼런스 파일 즉시 읽기 (필수)
34
+ #### STEP 1. STARTUP — 레퍼런스 참조
37
35
 
38
- **REFERENCES_DIR 확인**: 입력에서 `REFERENCES_DIR=...` 라인 또는 `<references-dir>` XML 요소를 확인. 해당 절대 경로 사용. 없으면 `.claude/references`를 기본값으로 사용.
39
-
40
- `{REFERENCES_DIR}/`에서 다음 파일을 읽기:
41
- 1. `shared-prompt-sections.md`
42
- 2. `xml-schema.md`
43
- 3. `context-policy.md`
44
- 4. `work-activity-log.md`
45
- 5. `callback-protocol.md`
46
-
47
- #### STEP 2. 콜백 START + 활동 로그 START
48
-
49
- - 활동 로그: `work-activity-log.md`를 참조하여 START 기록
50
- - 콜백: `callback-protocol.md`를 참조하여 START Callback 전송
36
+ `<ref-cache>`를 참조하여 작업을 수행한다.
51
37
 
52
38
  ### 3-2. 검증
53
39
 
@@ -130,11 +116,6 @@ Verifier 전용 추가 필드:
130
116
 
131
117
  ---
132
118
 
133
- ## 4. 결과물 생성 및 작업완료 절차
134
-
135
- - 활동 로그: `work-activity-log.md`를 참조하여 DONE 기록
136
- - 콜백: `callback-protocol.md`를 참조하여 DONE Callback 전송
137
-
138
- ## 5. 결과 보고
119
+ ## 4. 결과 보고
139
120
 
140
- 정의된 역할을 모두 끝내면 Main Claude에 보고해
121
+ 정의된 역할을 모두 끝내면 orchestrator에 보고해
package/lib/constants.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { readFileSync } from 'node:fs';
1
+ import { readFileSync, existsSync, rmSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
 
@@ -8,10 +8,10 @@ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8
8
8
  export const VERSION = pkg.version;
9
9
 
10
10
  export const AGENT_FILES = [
11
+ 'orchestrator.md',
11
12
  'builder.md',
12
13
  'committer.md',
13
14
  'planner.md',
14
- 'scheduler.md',
15
15
  'specifier.md',
16
16
  'verifier.md',
17
17
  ];
@@ -20,7 +20,6 @@ export const REFERENCE_FILES = [
20
20
  'agent-flow.md',
21
21
  'context-policy.md',
22
22
  'file-content-schema.md',
23
- 'ref-cache-protocol.md',
24
23
  'shared-prompt-sections.md',
25
24
  'work-activity-log.md',
26
25
  'xml-schema.md',
@@ -34,6 +33,35 @@ export function getReferencesSrcDir() {
34
33
  return join(__dirname, '..', 'references');
35
34
  }
36
35
 
36
+ /**
37
+ * Files and directories shipped by earlier versions that no longer exist.
38
+ * init and update copy files but never delete, so an upgraded install keeps
39
+ * stale copies unless they are pruned explicitly.
40
+ *
41
+ * Paths are relative to the install root (.claude/ or ~/.claude/).
42
+ */
43
+ export const OBSOLETE_PATHS = [
44
+ 'agents/scheduler.md', // removed in 2.0.0 — orchestrator took over scheduling
45
+ 'references/callback-protocol.md', // removed in 2.0.0 — external callback integration dropped
46
+ 'references/ref-cache-protocol.md',// removed in 2.1.0 — protocol folded into xml-schema.md § 4
47
+ 'skills/sdd-pipeline/references', // removed in 1.5.0 — references moved to references/
48
+ ];
49
+
50
+ /**
51
+ * Delete every OBSOLETE_PATHS entry that still exists under baseDir.
52
+ * Returns the paths actually removed.
53
+ */
54
+ export function pruneObsolete(baseDir) {
55
+ const removed = [];
56
+ for (const relPath of OBSOLETE_PATHS) {
57
+ const target = join(baseDir, relPath);
58
+ if (!existsSync(target)) continue;
59
+ rmSync(target, { recursive: true, force: true });
60
+ removed.push(relPath);
61
+ }
62
+ return removed;
63
+ }
64
+
37
65
 
38
66
  /**
39
67
  * Bash permissions required by uc-taskmanager agents.
@@ -45,7 +73,6 @@ export function getReferencesSrcDir() {
45
73
  * - Formatting: printf, echo
46
74
  * - Build/Lint: node, npm, bun, yarn, cargo, go, python, ruff, make
47
75
  * - Git: git add, git commit, git log, git rev-parse
48
- * - Network: curl (callback)
49
76
  */
50
77
  export const REQUIRED_PERMISSIONS = [
51
78
  // File read/write tools (project-root scoped)
@@ -90,7 +117,4 @@ export const REQUIRED_PERMISSIONS = [
90
117
 
91
118
  // Git operations (committer)
92
119
  'Bash(git:*)',
93
-
94
- // Network (callback transmission)
95
- 'Bash(curl:*)',
96
120
  ];
package/lib/init.mjs CHANGED
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, readd
2
2
  import { join, dirname } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { homedir } from 'node:os';
5
- import { AGENT_FILES, REFERENCE_FILES, getAgentsSrcDir, getReferencesSrcDir, REQUIRED_PERMISSIONS } from './constants.mjs';
5
+ import { AGENT_FILES, REFERENCE_FILES, getAgentsSrcDir, getReferencesSrcDir, REQUIRED_PERMISSIONS, pruneObsolete } from './constants.mjs';
6
6
 
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
 
@@ -73,16 +73,13 @@ function copyPluginResources(destBaseDir) {
73
73
  return count;
74
74
  }
75
75
 
76
- function ensureRouterConfig(projectDir) {
77
- const configDir = join(projectDir, '.agent');
78
- const configPath = join(configDir, 'router_rule_config.json');
79
- if (existsSync(configPath)) return false;
80
- mkdirSync(configDir, { recursive: true });
81
- const srcConfig = join(__dirname, '..', '.agent', 'router_rule_config.json');
82
- if (existsSync(srcConfig)) {
83
- copyFileSync(srcConfig, configPath);
76
+ function reportPruned(baseDir) {
77
+ const removed = pruneObsolete(baseDir);
78
+ if (removed.length === 0) return;
79
+ console.log(` ${green('✓')} ${removed.length} obsolete files removed`);
80
+ for (const relPath of removed) {
81
+ console.log(` ${dim('-')} ${dim(relPath)}`);
84
82
  }
85
- return true;
86
83
  }
87
84
 
88
85
  function ensureWorksDir(projectDir) {
@@ -153,6 +150,7 @@ export async function init(isGlobal) {
153
150
  if (globalResCount > 0) {
154
151
  console.log(` ${green('✓')} ${globalResCount} plugin resource files copied`);
155
152
  }
153
+ reportPruned(globalClaudeDir);
156
154
  console.log(`\n ${dim('Next steps:')}`);
157
155
  console.log(` 1. Open any project and run ${dim("'claude'")}`);
158
156
  console.log(` 2. Type: ${dim(exampleTag)}\n`);
@@ -174,11 +172,7 @@ export async function init(isGlobal) {
174
172
  console.log(` ${green('✓')} ${resCount} plugin resource files copied (.claude-plugin, skills)`);
175
173
  }
176
174
 
177
- if (ensureRouterConfig(projectDir)) {
178
- console.log(` ${green('✓')} .agent/router_rule_config.json created`);
179
- } else {
180
- console.log(` ${dim('-')} .agent/router_rule_config.json already exists`);
181
- }
175
+ reportPruned(claudeDir);
182
176
 
183
177
  if (ensureWorksDir(projectDir)) {
184
178
  console.log(` ${green('✓')} works/ directory created`);
package/lib/update.mjs CHANGED
@@ -2,7 +2,7 @@ import { existsSync, copyFileSync, mkdirSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { homedir } from 'node:os';
5
- import { AGENT_FILES, REFERENCE_FILES, getAgentsSrcDir, getReferencesSrcDir } from './constants.mjs';
5
+ import { AGENT_FILES, REFERENCE_FILES, getAgentsSrcDir, getReferencesSrcDir, pruneObsolete } from './constants.mjs';
6
6
 
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
 
@@ -40,9 +40,17 @@ export function update(isGlobal) {
40
40
  refCount++;
41
41
  }
42
42
 
43
+ const removed = pruneObsolete(baseDir);
44
+
43
45
  const label = isGlobal ? '~/.claude/' : '.claude/';
44
46
  console.log(`\n Updating ${dim(label)} ...`);
45
47
  console.log(` ${green('✓')} ${agentCount} agent files updated`);
46
48
  console.log(` ${green('✓')} ${refCount} reference files updated`);
47
- console.log(` ${dim('-')} CLAUDE.md, router_rule_config.json untouched\n`);
49
+ if (removed.length > 0) {
50
+ console.log(` ${green('✓')} ${removed.length} obsolete files removed`);
51
+ for (const relPath of removed) {
52
+ console.log(` ${dim('-')} ${dim(relPath)}`);
53
+ }
54
+ }
55
+ console.log(` ${dim('-')} CLAUDE.md untouched\n`);
48
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uctm",
3
- "version": "1.5.4",
3
+ "version": "2.0.1",
4
4
  "description": "Universal Claude Task Manager — SDD-based task pipeline subagent system for Claude Code CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,6 @@
11
11
  "lib/",
12
12
  "agents/",
13
13
  "references/",
14
- ".agent/",
15
14
  ".claude-plugin/",
16
15
  "skills/"
17
16
  ],
@@ -34,8 +33,5 @@
34
33
  "type": "git",
35
34
  "url": "git+https://github.com/UCJung/uc-taskmanager-claude-agent.git"
36
35
  },
37
- "homepage": "https://github.com/UCJung/uc-taskmanager-claude-agent#readme",
38
- "dependencies": {
39
- "uctm": "^1.5.0"
40
- }
36
+ "homepage": "https://github.com/UCJung/uc-taskmanager-claude-agent#readme"
41
37
  }