deuk-agent-flow 4.0.36 → 4.2.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.
- package/CHANGELOG.ko.md +29 -0
- package/CHANGELOG.md +29 -0
- package/NOTICE.md +19 -0
- package/README.ko.md +2 -2
- package/README.md +2 -2
- package/core-rules/AGENTS.md +6 -4
- package/docs/npm-publish-guide.ko.md +70 -0
- package/docs/usage-guide.ko.md +2 -2
- package/package.json +18 -8
- package/scripts/cli-init-commands.mjs +53 -39
- package/scripts/cli-skill-commands.mjs +23 -12
- package/scripts/cli-ticket-command-shared.mjs +60 -0
- package/scripts/cli-ticket-commands.mjs +161 -114
- package/scripts/cli-ticket-index.mjs +41 -17
- package/scripts/cli-ticket-parser.mjs +4 -3
- package/scripts/cli.mjs +2 -1
- package/scripts/lint-rules.mjs +1 -0
- package/scripts/smoke-npm-docker.mjs +1 -1
- package/scripts/smoke-npm-local.mjs +1 -0
- package/templates/TICKET_TEMPLATE.ko.md +3 -3
- package/templates/TICKET_TEMPLATE.md +3 -3
- package/templates/project-pilot/CONFORMANCE_GATE_TEMPLATE.md +2 -0
- package/templates/project-pilot/DRIFT_CHECKLIST.md +8 -0
- package/templates/skills/project-pilot/SKILL.md +17 -7
- package/templates/skills/safe-refactor/SKILL.md +1 -1
- package/docs/badges/npm-downloads.json +0 -8
package/CHANGELOG.ko.md
CHANGED
|
@@ -10,7 +10,36 @@
|
|
|
10
10
|
|
|
11
11
|
### 수정됨 (Fixed)
|
|
12
12
|
|
|
13
|
+
- **ticket:** 티켓 템플릿의 APC 마커를 추가 설명문 없이 제목형으로 정리해, 에이전트가 마커 본문을 다음 줄에 쓰도록 유도했습니다.
|
|
14
|
+
- **ticket:** APC create 입력을 마커별로 자르지 않고 APC 섹션 전체 기준으로 검증해, 제목형·단독형·inline 마커 스타일 호환성을 유지했습니다.
|
|
15
|
+
- **rules:** `Ticket start` 링크가 이미 노출된 티켓은 완료 응답에서 같은 클릭 링크를 다시 내보내지 않도록 했습니다.
|
|
16
|
+
- **skills:** 공용 skill 요약과 ownership 문구에서 DeukAgentFlow 전용 표현을 제거해 소비자 표면을 일반화했습니다.
|
|
17
|
+
|
|
18
|
+
## [4.2.2] - 2026-05-10
|
|
19
|
+
|
|
20
|
+
### 수정됨 (Fixed)
|
|
21
|
+
|
|
22
|
+
- **release:** 버전 bump 시 `Unreleased`에 남은 항목이 유실되지 않도록 누적 릴리스 이월 처리를 보강했습니다.
|
|
23
|
+
|
|
24
|
+
## [4.2.1] - 2026-05-10
|
|
25
|
+
|
|
26
|
+
### 수정됨 (Fixed)
|
|
27
|
+
|
|
13
28
|
- **cli:** 티켓 탐색이 상위 워크스페이스를 상속하지 않고 현재 agent-rule 경계에서 멈추도록 수정했습니다.
|
|
29
|
+
- **ticket:** `status`, `guard`, `move`의 Phase 1 검증을 동일하게 적용해, 미완성 상태 티켓이 숨김 없이 걸러지도록 수정했습니다.
|
|
30
|
+
- **ticket:** `move` 단계에서 문자열 phase 값이 문자열 결합으로 오동작하는 것을 방지하기 위해 숫자 변환 후 산술 처리하도록 수정했습니다.
|
|
31
|
+
|
|
32
|
+
## [4.0.38] - 2026-05-10
|
|
33
|
+
|
|
34
|
+
### 수정됨 (Fixed)
|
|
35
|
+
|
|
36
|
+
- **rules:** 승인 대기 상태의 최종 응답도 compact `Ticket start` 표면을 반복하도록 강제해, 최종 승인 대기 문구만 남아 활성 티켓 링크가 숨겨지는 문제를 막았습니다.
|
|
37
|
+
|
|
38
|
+
## [4.0.37] - 2026-05-09
|
|
39
|
+
|
|
40
|
+
### 수정됨 (Fixed)
|
|
41
|
+
|
|
42
|
+
- **init:** init 성공 후 보이는 완료 피드백을 복구하고, 첫 사용 가이드로 ``이슈분석 티켓`이라고 해보세요.` 문구를 추가했습니다.
|
|
14
43
|
|
|
15
44
|
## [4.0.36] - 2026-05-09
|
|
16
45
|
|
package/CHANGELOG.md
CHANGED
|
@@ -10,7 +10,36 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
10
10
|
|
|
11
11
|
### Fixed
|
|
12
12
|
|
|
13
|
+
- **ticket:** prefer heading-style APC markers in ticket templates without extra explanatory prose, so agents keep marker bodies on following lines.
|
|
14
|
+
- **ticket:** validate APC create input from the whole APC section instead of slicing per marker, preserving compatibility with heading, bare, and inline marker styles.
|
|
15
|
+
- **rules:** avoid emitting a second clickable link for the same ticket in the completion reply after `Ticket start` was already exposed.
|
|
16
|
+
- **skills:** remove DeukAgentFlow-specific wording from shared skill summaries and ownership notes so consumer-facing templates stay generic.
|
|
17
|
+
|
|
18
|
+
## [4.2.2] - 2026-05-10
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **release:** keep release-context carry-over so version bumping does not drop `Unreleased` items.
|
|
23
|
+
|
|
24
|
+
## [4.2.1] - 2026-05-10
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
13
28
|
- **cli:** stop ticket discovery at the current agent-rule boundary instead of inheriting the parent workspace.
|
|
29
|
+
- **ticket:** enforce Phase 1 planning completeness in `status`, `guard`, and `move` checks to prevent silent Phase-1 bypass.
|
|
30
|
+
- **ticket:** coerce string phase values to numbers before phase transitions so moves can’t produce string-concatenation artifacts (for example, `"1" + 1 => "11"`).
|
|
31
|
+
|
|
32
|
+
## [4.0.38] - 2026-05-10
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **rules:** require approval-pending final answers to repeat the compact `Ticket start` surface, preventing final-only approval text from hiding the active ticket link.
|
|
37
|
+
|
|
38
|
+
## [4.0.37] - 2026-05-09
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **init:** restore a visible completion message after successful init and add the short first-use prompt guide ``이슈분석 티켓`이라고 해보세요.``
|
|
14
43
|
|
|
15
44
|
## [4.0.36] - 2026-05-09
|
|
16
45
|
|
package/NOTICE.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Deuk Agent Flow Notice
|
|
2
|
+
|
|
3
|
+
## v4.0.36 init hotfix
|
|
4
|
+
|
|
5
|
+
Interactive `deuk-agent-flow init` now asks only for the workspace purpose. The CLI infers document language, workflow mode, ticket sharing, agent pointer defaults, and MCP memory defaults from the project directory or safe private defaults.
|
|
6
|
+
|
|
7
|
+
The Deuk AgentContext MCP choice is hidden during first setup. MCP remains an optional companion setup that can be documented and configured separately.
|
|
8
|
+
|
|
9
|
+
This hotfix also avoids the post-choice stall that could leave setup incomplete after the user answered an init prompt.
|
|
10
|
+
|
|
11
|
+
Ticket creation/use surfaces must keep the clickable `Ticket start` line visible before asking for approval. Approval-only replies are treated as a hidden-ticket regression.
|
|
12
|
+
|
|
13
|
+
## v4.0.37 init completion feedback
|
|
14
|
+
|
|
15
|
+
Successful `init` now ends with a visible completion line and a short first-use prompt guide so terminal-first installs do not appear to finish silently.
|
|
16
|
+
|
|
17
|
+
## v4.0.38 approval-pending final answer guard
|
|
18
|
+
|
|
19
|
+
Approval-pending final answers must repeat the compact `Ticket start` surface. A final answer that only says approval is pending is treated as a hidden-ticket regression.
|
package/README.ko.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<br />
|
|
3
3
|
<img src="docs/assets/architecture-v3.png" width="800" alt="DeukAgentFlow Architecture" />
|
|
4
4
|
<br />
|
|
5
|
-
<h1>Deuk Agent Flow v4.0.
|
|
5
|
+
<h1>Deuk Agent Flow v4.0.38</h1>
|
|
6
6
|
<p>
|
|
7
7
|
<a href="https://www.npmjs.com/package/deuk-agent-flow"><img src="https://img.shields.io/npm/v/deuk-agent-flow.svg?label=deuk-flow" alt="deuk-flow npm version" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/deuk-agent-flow"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjoygram%2FDeukAgentFlow%2Fmaster%2Fdocs%2Fbadges%2Fnpm-downloads.json" alt="deuk-flow combined npm downloads" /></a>
|
|
@@ -66,7 +66,7 @@ Deuk Agent Flow
|
|
|
66
66
|
| 팀 기억 강화 | 완료된 작업이 검색 가능한 프로젝트 히스토리가 됨 |
|
|
67
67
|
|
|
68
68
|
> **현재 배포 기준:**
|
|
69
|
-
> v4.0.
|
|
69
|
+
> v4.0.38은 에이전트 기반 리포지토리에 배포해 사용할 수 있는 상태입니다. 대화형 `init`은 이제 workspace 용도만 묻고, 나머지 설정은 프로젝트 디렉터리 성격으로 추론하며, Deuk AgentContext MCP 선택지는 첫 설정에서 숨김 처리하고, 이전의 다중 질문/먹통 완료 실패를 피합니다. 이제 설치가 끝나면 완료 피드백과 짧은 첫 사용 가이드도 다시 보입니다. 티켓 생성/사용 뒤에도 승인 요청 전과 승인 대기 최종 응답에서 클릭 가능한 `Ticket start` 줄이 계속 보이도록 했습니다. 현재는 **OpenAI Codex**와 **GitHub Copilot** 환경에서 가장 안정적으로 동작합니다. Cursor, Windsurf, Claude Code도 포인터 구조로 지원하지만, 워크스페이스별 검증을 권장합니다. Deuk AgentContext MCP는 선택형 기억 계층이며, MCP 서버 등록은 `init`에 딸려 들어가지 않고 별도로 설정합니다.
|
|
70
70
|
> **아키텍처 기반:**
|
|
71
71
|
> 거대하고 무거운 레거시 `.cursorrules` 방식을 공식적으로 폐기했습니다. v3.0은 `AGENTS.md`를 단일 진실 공급원으로 사용하는 **Hub-Spoke 모델**을 도입하여, IDE별 규칙은 얇은 진입점 포인터 역할만 수행합니다.
|
|
72
72
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<br />
|
|
3
3
|
<img src="docs/assets/architecture-v3.png" width="800" alt="DeukAgentFlow Architecture" />
|
|
4
4
|
<br />
|
|
5
|
-
<h1>Deuk Agent Flow v4.0.
|
|
5
|
+
<h1>Deuk Agent Flow v4.0.38</h1>
|
|
6
6
|
<p>
|
|
7
7
|
<a href="https://www.npmjs.com/package/deuk-agent-flow"><img src="https://img.shields.io/npm/v/deuk-agent-flow.svg?label=deuk-flow" alt="deuk-flow npm version" /></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/deuk-agent-flow"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fjoygram%2FDeukAgentFlow%2Fmaster%2Fdocs%2Fbadges%2Fnpm-downloads.json" alt="deuk-flow combined npm downloads" /></a>
|
|
@@ -66,7 +66,7 @@ Repo-owned work
|
|
|
66
66
|
| Better team memory | Completed work becomes searchable project history |
|
|
67
67
|
|
|
68
68
|
> **Current readiness:**
|
|
69
|
-
> v4.0.
|
|
69
|
+
> v4.0.38 is deployment-ready for agent-driven repositories. Interactive `init` now asks only the workspace purpose, infers the remaining setup from the project directory, hides the Deuk AgentContext MCP choice during first setup, completes without the earlier multi-prompt stall, and ends with a visible completion line plus a short first-use prompt guide. Ticket creation/use also keeps the clickable `Ticket start` line visible before approval is requested, including approval-pending final answers. It is currently most reliable in **OpenAI Codex** and **GitHub Copilot** workflows. Cursor, Windsurf, and Claude Code remain supported through pointer-style integration, but they should be validated per workspace before rollout. Deuk AgentContext MCP is an optional memory layer; MCP server registration is separate from `init`.
|
|
70
70
|
> **Architecture foundation:**
|
|
71
71
|
> We have officially deprecated monolithic `.cursorrules`. v3.0 introduces the **Hub-Spoke model** where `AGENTS.md` is the single source of truth, and IDE-specific rules act as thin entry-point pointers.
|
|
72
72
|
|
package/core-rules/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
version:
|
|
3
|
-
changelog: "
|
|
2
|
+
version: 76
|
|
3
|
+
changelog: "v76: Route ticket reuse through CLI topic/id resolution and block duplicate create after archived path misses."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Agent Rules
|
|
@@ -40,6 +40,7 @@ changelog: "v72: Clarify that external progress-update pressure is satisfied onl
|
|
|
40
40
|
- Ticket-start exposure contract: after selecting or creating the active ticket, relay exactly one clickable `Ticket start: [<id>](/absolute/path/to/ticket.md)` line as the first visible assistant line, a short scope/planned-change summary, and any compact `Guard topic: <id>` line; tool/CLI output alone does not count, and `file://`, truncated, non-clickable, hidden, or folded tool-result links must be converted without changing the id.
|
|
41
41
|
- Approval-pending contract: stop if approval is pending, make the first visible assistant line exactly the clickable `Ticket start: [<id>](/absolute/path/to/ticket.md)` line, then print `조용히 작업` and keep the guard topic visible; do not put acknowledgements, explanations, command echoes, approval-only text such as `승인 바랍니다`, or status text before or instead of it. This keeps the active ticket visible even when earlier tool results are folded, hidden, or compacted. This blocks unapproved work, not concise answers to explicit user-requested output or direct questions about workflow state.
|
|
42
42
|
- Hidden-ticket regression guard: if the latest visible chat line after ticket creation/use is only an approval request or a generic permission prompt, treat the ticket as not exposed. Immediately repeat the clickable `Ticket start` line and compact scope before waiting for approval.
|
|
43
|
+
- Approval-pending final-answer guard: when approval is still pending, the final answer must repeat the compact approval-pending surface instead of saying only `승인 대기 중이에요`, `승인 바랍니다`, or another approval-only sentence. The final answer's first visible line must still be the clickable `Ticket start` line, followed by `조용히 작업` and `Guard topic: <id>`.
|
|
43
44
|
- Commentary surface map: treat `ticket_start_pending`, `approval_pending`, `approved_execution`, `command_running`, `search_running`, `user-complaint reply`, `requirement_change_pending`, and `final_answer` as separate output surfaces. Each surface must follow its own compact contract; a fix on one surface does not authorize spillover on another.
|
|
44
45
|
- Execution feedback contract: non-final chatter is capped at one word and must be short TDW state only (`ticket`, `approval`, `guard`, `context`, `verify`); do not repeat the same state or narrate routine reads, edits, formatting, lint retries, validation progress, or "almost done" status.
|
|
45
46
|
- Running-surface contract: `approved_execution`, `command_running`, and `search_running` all use the same low-token rule. Unless the user explicitly requested live narration or a blocker must be surfaced, output must stay empty or one-word TDW state only; command/search progress does not create a separate narration allowance.
|
|
@@ -49,7 +50,7 @@ changelog: "v72: Clarify that external progress-update pressure is satisfied onl
|
|
|
49
50
|
- Default execution mode is no progress commentary. After approval, do not emit step-by-step status, planning narration, repo-state narration, or commit narration in chat unless the user explicitly asked for live narration or a blocker/user decision must be surfaced.
|
|
50
51
|
- Keep chat compact; do not mirror ticket prose in screen output.
|
|
51
52
|
- Final answers must be short but complete enough to answer the user.
|
|
52
|
-
- After task completion, prefer: result, verification status, ticket
|
|
53
|
+
- After task completion, prefer: result, verification status, ticket reference, then one short line saying which ticket section to read for details. If a clickable `Ticket start` link for the same ticket was already exposed in the visible conversation, do not emit a second clickable link for that ticket in the final answer; refer to the ticket id in plain text or say the archived ticket was updated. If any important area is unverified, say that explicitly instead of sounding complete.
|
|
53
54
|
- Do not cite approval-pending silence as a reason to withhold a concise explanation that the user explicitly requested. Explain the state, separate rule text from agent interpretation, and keep the answer narrow.
|
|
54
55
|
- When the user complains about verbosity, chatter, progress reports, or over-explaining, reply with a short acknowledgment plus the concrete fix or scope change. Do not switch into meta labeling, terminology lessons, or general explanation unless the user explicitly asks what the term means.
|
|
55
56
|
- If the user asks for `짧게`, `매우 짧게`, `한 줄로`, or `간단히`, prioritize a one-sentence or bullet-only answer and omit background unless the user asks for it or a blocker requires it.
|
|
@@ -67,7 +68,7 @@ changelog: "v72: Clarify that external progress-update pressure is satisfied onl
|
|
|
67
68
|
Use this recipe directly. Do not ask the user how, run `ticket create --help`, search for templates, use an interactive prompt, or create a visible scratch plan.
|
|
68
69
|
|
|
69
70
|
1. Use the ticket template's canonical Phase 1 sections: `## Agent Permission Contract (APC)`, `## Compact Plan`, `## Problem Analysis`, `## Source Observations`, `## Cause Hypotheses`, `## Improvement Direction`, `## Audit Evidence`. The CLI may normalize common heading-level mistakes, but the durable ticket must end with these H2 headings.
|
|
70
|
-
2. Under `Agent Permission Contract (APC)`,
|
|
71
|
+
2. Under `Agent Permission Contract (APC)`, use heading-style APC markers exactly as `### [BOUNDARY]`, `### [CONTRACT]`, and `### [PATCH PLAN]`; write each marker's body on the following lines, never on the same line as the marker.
|
|
71
72
|
3. Run this exact stdin command:
|
|
72
73
|
|
|
73
74
|
```bash
|
|
@@ -98,6 +99,7 @@ When the user asks for AgentFlow skill status or connected skills, use `deuk-age
|
|
|
98
99
|
|
|
99
100
|
Use the mentioned ticket directly. For investigation/regression/why questions, create the ticket first and stop after Phase 1. Do not use `deuk-agent-flow ticket list` for discovery.
|
|
100
101
|
For bug/regression/why or direct change requests, the first repo action after rules load is `deuk-agent-flow ticket create` or `deuk-agent-flow ticket use`. Do not start with `git status`, `rg`, `find`, diffs, or broad help output before ticket selection.
|
|
102
|
+
When a ticket id/topic is known, never infer its active file path or probe `.deuk-agent/tickets/sub` directly; use `deuk-agent-flow ticket status --topic <id>` or `deuk-agent-flow ticket use --topic <id>` so closed/archived locations resolve through the index. A missing guessed path is not evidence that a new ticket is needed.
|
|
101
103
|
|
|
102
104
|
## 3. Phase Contract
|
|
103
105
|
At each phase, ask available tooling for one complete requirement bundle and follow it exactly. Minimum bundle:
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# DeukAgentFlow npm 배포 가이드
|
|
2
|
+
|
|
3
|
+
`deuk-agent-flow`가 본패키지이고 `deuk-agent-rule`은 호환용 alias 패키지다.
|
|
4
|
+
|
|
5
|
+
## 배포 전 확인
|
|
6
|
+
|
|
7
|
+
1. `package.json`의 `repository`, `bugs`, `homepage`가 현재 Git 저장소 URL을 가리키는지 확인한다.
|
|
8
|
+
2. `packages/deuk-agent-rule/package.json`의 version과 `deuk-agent-flow` dependency가 root version과 같은지 확인한다.
|
|
9
|
+
3. 다운로드 배지는 `deuk-agent-flow`를 canonical package로 두고 `deuk-agent-rule`을 alias contribution으로 합산한다.
|
|
10
|
+
|
|
11
|
+
## 검증 순서
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm test
|
|
15
|
+
npm run smoke:npm:local
|
|
16
|
+
npm run publish:dry
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Docker가 가능한 환경에서는 추가로 실행한다.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run smoke:npm:docker
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Windows에서는 다음 명령으로 `.cmd` shim 생성까지 확인한다.
|
|
26
|
+
|
|
27
|
+
```bat
|
|
28
|
+
node scripts\smoke-npm-local.mjs
|
|
29
|
+
where deuk-agent-flow
|
|
30
|
+
where deuk-agent-rule
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 실제 배포
|
|
34
|
+
|
|
35
|
+
root에서 실행한다.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm run publish
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
이 명령은 다음 순서로 동작한다.
|
|
42
|
+
|
|
43
|
+
1. `deuk-agent-rule` alias package metadata를 root package 기준으로 동기화한다.
|
|
44
|
+
2. `npm test`를 실행한다.
|
|
45
|
+
3. local npm install smoke를 실행한다.
|
|
46
|
+
4. `deuk-agent-flow`를 먼저 publish한다.
|
|
47
|
+
5. `deuk-agent-rule` alias package를 publish한다.
|
|
48
|
+
|
|
49
|
+
이미 같은 버전의 `deuk-agent-flow`가 올라갔고 alias만 다시 올려야 하면 다음 명령을 사용한다.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm run publish:bootstrap
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 배포 후 확인
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm view deuk-agent-flow version
|
|
59
|
+
npm view deuk-agent-rule version
|
|
60
|
+
npm install -g deuk-agent-flow
|
|
61
|
+
deuk-agent-flow --help
|
|
62
|
+
npm install -g deuk-agent-rule
|
|
63
|
+
deuk-agent-rule --help
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
다운로드 배지는 필요하면 갱신한다.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm run badge:downloads
|
|
70
|
+
```
|
package/docs/usage-guide.ko.md
CHANGED
|
@@ -164,7 +164,7 @@ git diff -- .deuk-agent/tickets/INDEX.archive.*.json
|
|
|
164
164
|
|
|
165
165
|
스킬은 전체 workflow를 대체하지 않는 짧은 행동 playbook입니다. DeukAgentFlow에서는 티켓/APC/Phase Gate가 계속 상위 권한이고, 스킬은 특정 실패 패턴에서 에이전트의 움직임만 더 날카롭게 만듭니다.
|
|
166
166
|
|
|
167
|
-
`init
|
|
167
|
+
`init`은 first-party 스킬 원본을 프로젝트 안으로 복제하지 않습니다. 스킬 원본은 DeukAgentFlow 패키지의 `templates/skills/`가 SSoT입니다.
|
|
168
168
|
|
|
169
169
|
기본 추천 장착:
|
|
170
170
|
|
|
@@ -201,7 +201,7 @@ deuk-agent-flow skill expose --platform claude
|
|
|
201
201
|
deuk-agent-flow skill expose --platform cursor
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
-
`skill add`는
|
|
204
|
+
`skill add`/`skill expose`는 스킬 사용 경로를 열지만, `init`은 로컬 스킬 템플릿 복제본을 만들거나 보존하지 않습니다.
|
|
205
205
|
|
|
206
206
|
---
|
|
207
207
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deuk-agent-flow",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.7",
|
|
4
4
|
"description": "Keep AI coding work from vanishing between chats: repo-owned tickets, scope, verification, and memory for AGENTS.md-powered agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents-md",
|
|
@@ -22,19 +22,17 @@
|
|
|
22
22
|
"license": "Apache-2.0",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "
|
|
25
|
+
"url": "https://github.com/joygram/DeukAgentFlow.git"
|
|
26
26
|
},
|
|
27
27
|
"bugs": {
|
|
28
28
|
"url": "https://github.com/joygram/DeukAgentFlow/issues"
|
|
29
29
|
},
|
|
30
30
|
"homepage": "https://github.com/joygram/DeukAgentFlow#readme",
|
|
31
31
|
"files": [
|
|
32
|
-
"LICENSE",
|
|
33
32
|
"bin/**/*",
|
|
34
33
|
"core-rules/**/*",
|
|
35
34
|
"docs/architecture.md",
|
|
36
35
|
"docs/architecture.ko.md",
|
|
37
|
-
"docs/badges/**/*",
|
|
38
36
|
"docs/how-it-works.md",
|
|
39
37
|
"docs/how-it-works.ko.md",
|
|
40
38
|
"docs/principles.md",
|
|
@@ -42,6 +40,7 @@
|
|
|
42
40
|
"docs/npm-publish-guide.ko.md",
|
|
43
41
|
"docs/usage-guide.ko.md",
|
|
44
42
|
"docs/assets/**/*",
|
|
43
|
+
"NOTICE.md",
|
|
45
44
|
"templates/**/*",
|
|
46
45
|
"scripts/cli.mjs",
|
|
47
46
|
"scripts/cli-args.mjs",
|
|
@@ -52,6 +51,7 @@
|
|
|
52
51
|
"scripts/cli-rule-compiler.mjs",
|
|
53
52
|
"scripts/cli-skill-commands.mjs",
|
|
54
53
|
"scripts/cli-telemetry-commands.mjs",
|
|
54
|
+
"scripts/cli-ticket-command-shared.mjs",
|
|
55
55
|
"scripts/cli-ticket-commands.mjs",
|
|
56
56
|
"scripts/cli-ticket-index.mjs",
|
|
57
57
|
"scripts/cli-ticket-migration.mjs",
|
|
@@ -71,13 +71,20 @@
|
|
|
71
71
|
"CHANGELOG.ko.md"
|
|
72
72
|
],
|
|
73
73
|
"scripts": {
|
|
74
|
+
"bump": "commit-and-tag-version",
|
|
75
|
+
"bump:patch": "commit-and-tag-version -r patch",
|
|
76
|
+
"bump:minor": "commit-and-tag-version -r minor",
|
|
77
|
+
"bump:major": "commit-and-tag-version -r major",
|
|
78
|
+
"merge:dry": "node scripts/cli.mjs merge --dry-run --cwd .. --agents skip",
|
|
74
79
|
"lint:md": "node scripts/lint-md.mjs",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
80
|
+
"test": "node --test scripts/tests/*.test.mjs",
|
|
81
|
+
"sync:oss": "node scripts/sync-oss.mjs",
|
|
82
|
+
"publish": "node scripts/publish-dual-npm.mjs",
|
|
83
|
+
"publish:dry": "node scripts/publish-dual-npm.mjs --dry-run",
|
|
77
84
|
"smoke:npm:local": "node scripts/smoke-npm-local.mjs",
|
|
78
85
|
"smoke:npm:docker": "node scripts/smoke-npm-docker.mjs",
|
|
79
|
-
"publish:bootstrap": "node scripts/publish-dual-npm.mjs --alias-only
|
|
80
|
-
"publish:bootstrap:dry": "node scripts/publish-dual-npm.mjs --alias-only --dry-run
|
|
86
|
+
"publish:bootstrap": "node scripts/publish-dual-npm.mjs --alias-only",
|
|
87
|
+
"publish:bootstrap:dry": "node scripts/publish-dual-npm.mjs --alias-only --dry-run",
|
|
81
88
|
"badge:downloads": "node scripts/update-download-badge.mjs"
|
|
82
89
|
},
|
|
83
90
|
"engines": {
|
|
@@ -89,6 +96,9 @@
|
|
|
89
96
|
"deuk-agent-rule": "./bin/deuk-agent-rule.js",
|
|
90
97
|
"deukagentrule": "./bin/deuk-agent-rule.js"
|
|
91
98
|
},
|
|
99
|
+
"devDependencies": {
|
|
100
|
+
"commit-and-tag-version": "^12.7.1"
|
|
101
|
+
},
|
|
92
102
|
"dependencies": {
|
|
93
103
|
"ejs": "^5.0.2",
|
|
94
104
|
"yaml": "^2.8.3"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join, dirname, basename, relative } from "path";
|
|
2
2
|
import { homedir } from "os";
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, unlinkSync, rmSync, renameSync, statSync,
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, unlinkSync, rmSync, renameSync, statSync, symlinkSync, chmodSync } from "fs";
|
|
4
4
|
|
|
5
5
|
import { ensureTicketDirAndGitignore } from "./cli-init-logic.mjs";
|
|
6
6
|
import { normalizeTicketPaths } from "./cli-ticket-migration.mjs";
|
|
@@ -44,6 +44,29 @@ const SOURCE_MODE_COMMANDS = [
|
|
|
44
44
|
["deuk-agent-rule", "deuk-agent-rule.js"],
|
|
45
45
|
["deukagentrule", "deuk-agent-rule.js"]
|
|
46
46
|
];
|
|
47
|
+
const CANONICAL_INIT_CLEANUP_PATHS = {
|
|
48
|
+
runtimeTemplateCopies: [join(AGENT_ROOT_DIR, "templates"), LEGACY_TEMPLATE_DIR],
|
|
49
|
+
localSkillCopies: [
|
|
50
|
+
join(AGENT_ROOT_DIR, "skill-templates"),
|
|
51
|
+
join(AGENT_ROOT_DIR, "skills"),
|
|
52
|
+
join(AGENT_ROOT_DIR, "skills.json"),
|
|
53
|
+
join(".claude", "skills"),
|
|
54
|
+
join(".cursor", "rules", "deuk-agent-skills.mdc")
|
|
55
|
+
],
|
|
56
|
+
duplicateRuleCopies: [join(AGENT_ROOT_DIR, "rules"), join(".cursor", "rules", "deuk-agent-rule-multi-ai-workflow.mdc")],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function removeLegacyPaths(cwd, dryRun, paths, label) {
|
|
60
|
+
let removed = 0;
|
|
61
|
+
for (const relPath of paths) {
|
|
62
|
+
const target = join(cwd, relPath);
|
|
63
|
+
if (!existsSync(target)) continue;
|
|
64
|
+
if (!dryRun) rmSync(target, { recursive: true, force: true });
|
|
65
|
+
console.log(`[CLEANUP] removed ${label}: ${toRepoRelativePath(cwd, target)}`);
|
|
66
|
+
removed += 1;
|
|
67
|
+
}
|
|
68
|
+
return removed;
|
|
69
|
+
}
|
|
47
70
|
|
|
48
71
|
function pathEntries(pathEnv = process.env.PATH || "", platform = process.platform) {
|
|
49
72
|
return String(pathEnv || "").split(platform === "win32" ? ";" : ":").filter(Boolean);
|
|
@@ -813,8 +836,10 @@ function canonicalizeAgentRootLayout(cwd, dryRun) {
|
|
|
813
836
|
console.log(`[CLEANUP] removed runtime template copy: ${toRepoRelativePath(cwd, runtimeTemplates)}`);
|
|
814
837
|
}
|
|
815
838
|
|
|
816
|
-
|
|
817
|
-
|
|
839
|
+
removeLocalSkillCopies(cwd, dryRun);
|
|
840
|
+
|
|
841
|
+
const allowedDirs = new Set(["docs", "knowledge", "tickets"]);
|
|
842
|
+
const allowedFiles = new Set(["config.json", "telemetry.jsonl", "usage.json"]);
|
|
818
843
|
|
|
819
844
|
for (const entry of sortedDirEntries(agentRoot, { withFileTypes: true })) {
|
|
820
845
|
const sourceAbs = join(agentRoot, entry.name);
|
|
@@ -1334,27 +1359,11 @@ function canonicalizeRecursiveInitSurfaces(cwd, bundleRoot, dryRun) {
|
|
|
1334
1359
|
}
|
|
1335
1360
|
|
|
1336
1361
|
function removeRuntimeTemplateCopies(cwd, dryRun) {
|
|
1337
|
-
|
|
1338
|
-
const legacyTemplates = join(cwd, LEGACY_TEMPLATE_DIR);
|
|
1339
|
-
for (const target of [runtimeTemplates, legacyTemplates]) {
|
|
1340
|
-
if (!existsSync(target)) continue;
|
|
1341
|
-
if (!dryRun) rmSync(target, { recursive: true, force: true });
|
|
1342
|
-
console.log(`[CLEANUP] removed runtime template copy: ${toRepoRelativePath(cwd, target)}`);
|
|
1343
|
-
}
|
|
1362
|
+
removeLegacyPaths(cwd, dryRun, CANONICAL_INIT_CLEANUP_PATHS.runtimeTemplateCopies, "runtime template copy");
|
|
1344
1363
|
}
|
|
1345
1364
|
|
|
1346
|
-
function
|
|
1347
|
-
|
|
1348
|
-
const skillSourceDir = join(bundleRoot, "templates", "skills");
|
|
1349
|
-
if (!existsSync(skillSourceDir)) return;
|
|
1350
|
-
|
|
1351
|
-
if (!dryRun) {
|
|
1352
|
-
mkdirSync(skillDestDir, { recursive: true });
|
|
1353
|
-
cpSync(skillSourceDir, skillDestDir, { recursive: true });
|
|
1354
|
-
console.log(`[SYNC] skill templates synced to ${toRepoRelativePath(cwd, skillDestDir)}`);
|
|
1355
|
-
return;
|
|
1356
|
-
}
|
|
1357
|
-
console.log(`[SYNC] skill templates synced to ${toRepoRelativePath(cwd, skillDestDir)} (dry-run mode)`);
|
|
1365
|
+
function removeLocalSkillCopies(cwd, dryRun) {
|
|
1366
|
+
removeLegacyPaths(cwd, dryRun, CANONICAL_INIT_CLEANUP_PATHS.localSkillCopies, "local skill copy");
|
|
1358
1367
|
}
|
|
1359
1368
|
|
|
1360
1369
|
function canonicalizeLegacyDeukAgentText(content, bundleRoot) {
|
|
@@ -1520,6 +1529,18 @@ function migrateMissingFrontmatter(cwd, dryRun) {
|
|
|
1520
1529
|
}
|
|
1521
1530
|
}
|
|
1522
1531
|
|
|
1532
|
+
function runInitArchiveNormalizationPasses(cwd, dryRun) {
|
|
1533
|
+
const passes = [
|
|
1534
|
+
() => canonicalizeTicketArchivePath(cwd, dryRun),
|
|
1535
|
+
() => canonicalizeDocsArchiveBuckets(cwd, dryRun),
|
|
1536
|
+
() => enforceCanonicalAgentLayout(cwd, dryRun),
|
|
1537
|
+
() => mergeSeparatedDocsIntoTickets(cwd, dryRun),
|
|
1538
|
+
() => canonicalizeTicketArchivePath(cwd, dryRun),
|
|
1539
|
+
() => enforceCanonicalAgentLayout(cwd, dryRun),
|
|
1540
|
+
];
|
|
1541
|
+
for (const pass of passes) pass();
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1523
1544
|
export function buildGlobalCodexInstructions() {
|
|
1524
1545
|
return `---
|
|
1525
1546
|
|
|
@@ -1563,7 +1584,7 @@ This pointer is a thin bootstrap, not a second workflow contract.
|
|
|
1563
1584
|
2. Then read local \`PROJECT_RULE.md\` and internally identify applicable DC-* rules.
|
|
1564
1585
|
3. After the core hub is loaded, \`core-rules/AGENTS.md\` is the DeukAgentFlow SSoT for TDW, RAG, silence, scope, and verification.
|
|
1565
1586
|
|
|
1566
|
-
Do not print pointer/core metadata, version, DC-* lists, progress commentary, or interim summaries. When approval is pending, make the first visible assistant line exactly the clickable \`Ticket start: [<id>](/absolute/path/to/ticket.md)\` line; never leave only an approval request such as \`승인 바랍니다\` visible after ticket creation/use. Before the final answer, only the single required ticket-start line, blockers, explicit user-requested output, or explicit command results may appear. During approved_execution, command_running, or search_running, stay silent unless the user explicitly asks for live narration or a blocker/user decision must be surfaced.
|
|
1587
|
+
Do not print pointer/core metadata, version, DC-* lists, progress commentary, or interim summaries. When approval is pending, make the first visible assistant line exactly the clickable \`Ticket start: [<id>](/absolute/path/to/ticket.md)\` line, including in the final answer if approval is still pending; never leave only an approval request such as \`승인 바랍니다\` or \`승인 대기 중이에요\` visible after ticket creation/use. Before the final answer, only the single required ticket-start line, blockers, explicit user-requested output, or explicit command results may appear. During approved_execution, command_running, or search_running, stay silent unless the user explicitly asks for live narration or a blocker/user decision must be surfaced.
|
|
1567
1588
|
`;
|
|
1568
1589
|
|
|
1569
1590
|
if (spoke.format === "mdc") {
|
|
@@ -1621,16 +1642,7 @@ function removeDuplicateRuleCopies(cwd, dryRun) {
|
|
|
1621
1642
|
// Note: AGENTS.md is now the Antigravity spoke target — do NOT delete it here.
|
|
1622
1643
|
// CLAUDE.md/GEMINI.md legacy cleanup is handled by deploySpokePointers (spoke.legacy field).
|
|
1623
1644
|
// .gemini is the Antigravity platform directory — preserve it.
|
|
1624
|
-
|
|
1625
|
-
join(cwd, AGENT_ROOT_DIR, "rules"),
|
|
1626
|
-
join(cwd, ".cursor", "rules", "deuk-agent-rule-multi-ai-workflow.mdc"),
|
|
1627
|
-
];
|
|
1628
|
-
|
|
1629
|
-
for (const p of duplicatePaths) {
|
|
1630
|
-
if (!existsSync(p)) continue;
|
|
1631
|
-
if (!dryRun) rmSync(p, { recursive: true, force: true });
|
|
1632
|
-
console.log(`[CLEANUP] removed legacy/duplicate: ${toRepoRelativePath(cwd, p)}`);
|
|
1633
|
-
}
|
|
1645
|
+
removeLegacyPaths(cwd, dryRun, CANONICAL_INIT_CLEANUP_PATHS.duplicateRuleCopies, "legacy/duplicate");
|
|
1634
1646
|
}
|
|
1635
1647
|
|
|
1636
1648
|
export async function runInit(opts, bundleRoot) {
|
|
@@ -1684,6 +1696,11 @@ export async function runInit(opts, bundleRoot) {
|
|
|
1684
1696
|
}
|
|
1685
1697
|
}
|
|
1686
1698
|
|
|
1699
|
+
export function formatInitCompletionMessage(cwd, dryRun = false) {
|
|
1700
|
+
const label = dryRun ? "Dry-run complete" : "Init complete";
|
|
1701
|
+
return `[DONE] ${label} for ${basename(cwd)}. Rules and pointers are ready. \`이슈분석 티켓\`이라고 해보세요.`;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1687
1704
|
async function initSingleWorkspace(subCwd, opts, bundleRoot, selectedTools) {
|
|
1688
1705
|
console.log(`\nInitializing ${basename(subCwd)}...`);
|
|
1689
1706
|
|
|
@@ -1700,10 +1717,7 @@ async function initSingleWorkspace(subCwd, opts, bundleRoot, selectedTools) {
|
|
|
1700
1717
|
migrateMissingFrontmatter(subCwd, opts.dryRun);
|
|
1701
1718
|
|
|
1702
1719
|
// 2.6. Deterministic archive/docs normalization
|
|
1703
|
-
|
|
1704
|
-
canonicalizeDocsArchiveBuckets(subCwd, opts.dryRun);
|
|
1705
|
-
enforceCanonicalAgentLayout(subCwd, opts.dryRun);
|
|
1706
|
-
mergeSeparatedDocsIntoTickets(subCwd, opts.dryRun);
|
|
1720
|
+
runInitArchiveNormalizationPasses(subCwd, opts.dryRun);
|
|
1707
1721
|
if (!opts.dryRun) {
|
|
1708
1722
|
const rebuiltIndex = rebuildTicketIndexFromTopicFilesIfNeeded(subCwd, { force: true });
|
|
1709
1723
|
writeTicketIndexJson(subCwd, rebuiltIndex, { force: true });
|
|
@@ -1725,7 +1739,7 @@ async function initSingleWorkspace(subCwd, opts, bundleRoot, selectedTools) {
|
|
|
1725
1739
|
|
|
1726
1740
|
// 5. Runtime template cleanup; package templates/ is the SSoT.
|
|
1727
1741
|
removeRuntimeTemplateCopies(subCwd, opts.dryRun);
|
|
1728
|
-
|
|
1742
|
+
removeLocalSkillCopies(subCwd, opts.dryRun);
|
|
1729
1743
|
canonicalizeGeneratedCommandReferences(subCwd, bundleRoot, opts.dryRun);
|
|
1730
1744
|
canonicalizeRecursiveInitSurfaces(subCwd, bundleRoot, opts.dryRun);
|
|
1731
1745
|
}
|
|
@@ -1741,5 +1755,5 @@ export function runMerge(opts, bundleRoot) {
|
|
|
1741
1755
|
}
|
|
1742
1756
|
|
|
1743
1757
|
removeRuntimeTemplateCopies(opts.cwd, opts.dryRun);
|
|
1744
|
-
|
|
1758
|
+
removeLocalSkillCopies(opts.cwd, opts.dryRun);
|
|
1745
1759
|
}
|
|
@@ -6,17 +6,29 @@ import { AGENT_ROOT_DIR } from "./cli-utils.mjs";
|
|
|
6
6
|
const SKILL_IDS = ["safe-refactor", "generated-file-guard", "context-recall", "project-pilot"];
|
|
7
7
|
const SKILL_ROOT = "templates/skills";
|
|
8
8
|
const CONFIG_FILE = `${AGENT_ROOT_DIR}/skills.json`;
|
|
9
|
-
const REPO_SKILL_TEMPLATE_ROOT = `${AGENT_ROOT_DIR}/skill-templates`;
|
|
10
9
|
const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
+
const SKILL_PATHS = {
|
|
11
|
+
installedRoot: join(AGENT_ROOT_DIR, "skills"),
|
|
12
|
+
templateRoot: SKILL_ROOT,
|
|
13
|
+
claudeRoot: join(".claude", "skills"),
|
|
14
|
+
cursorPointer: join(".cursor", "rules", "deuk-agent-skills.mdc"),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function safeReadJson(absPath, fallback = null) {
|
|
18
|
+
if (!existsSync(absPath)) return fallback;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(absPath, "utf8"));
|
|
21
|
+
} catch {
|
|
22
|
+
return fallback;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
function repoSkillPath(cwd, id) {
|
|
13
|
-
return join(cwd,
|
|
27
|
+
return join(cwd, SKILL_PATHS.installedRoot, id, "SKILL.md");
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
function sourceSkillPath(cwd, id) {
|
|
17
|
-
const
|
|
18
|
-
if (existsSync(localTemplate)) return localTemplate;
|
|
19
|
-
const repoTemplate = join(cwd, SKILL_ROOT, id, "SKILL.md");
|
|
31
|
+
const repoTemplate = join(cwd, SKILL_PATHS.templateRoot, id, "SKILL.md");
|
|
20
32
|
if (existsSync(repoTemplate)) return repoTemplate;
|
|
21
33
|
return join(PACKAGE_ROOT, SKILL_ROOT, id, "SKILL.md");
|
|
22
34
|
}
|
|
@@ -29,18 +41,17 @@ function loadSkillSource(cwd, id) {
|
|
|
29
41
|
|
|
30
42
|
function loadSkillConfig(cwd) {
|
|
31
43
|
const path = join(cwd, CONFIG_FILE);
|
|
32
|
-
|
|
33
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
44
|
+
return safeReadJson(path, { version: 1, installed: [], exposed: {} });
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
function detectExposedPlatforms(cwd, id) {
|
|
37
48
|
const platforms = [];
|
|
38
|
-
const claudePath = join(cwd,
|
|
49
|
+
const claudePath = join(cwd, SKILL_PATHS.claudeRoot, id, "SKILL.md");
|
|
39
50
|
if (existsSync(claudePath)) {
|
|
40
51
|
platforms.push("claude");
|
|
41
52
|
}
|
|
42
53
|
|
|
43
|
-
const cursorPath = join(cwd,
|
|
54
|
+
const cursorPath = join(cwd, SKILL_PATHS.cursorPointer);
|
|
44
55
|
if (existsSync(cursorPath)) {
|
|
45
56
|
try {
|
|
46
57
|
const body = readFileSync(cursorPath, "utf8");
|
|
@@ -101,7 +112,7 @@ export function addSkill(opts = {}) {
|
|
|
101
112
|
function exposeClaude(cwd, ids, dryRun) {
|
|
102
113
|
for (const id of ids) {
|
|
103
114
|
const body = readFileSync(repoSkillPath(cwd, id), "utf8");
|
|
104
|
-
const target = join(cwd,
|
|
115
|
+
const target = join(cwd, SKILL_PATHS.claudeRoot, id, "SKILL.md");
|
|
105
116
|
if (!dryRun) {
|
|
106
117
|
mkdirSync(dirname(target), { recursive: true });
|
|
107
118
|
writeFileSync(target, body, "utf8");
|
|
@@ -110,7 +121,7 @@ function exposeClaude(cwd, ids, dryRun) {
|
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
function exposeCursor(cwd, ids, dryRun) {
|
|
113
|
-
const target = join(cwd,
|
|
124
|
+
const target = join(cwd, SKILL_PATHS.cursorPointer);
|
|
114
125
|
const body = [
|
|
115
126
|
"---",
|
|
116
127
|
"description: \"DeukAgentFlow skill pointers\"",
|
|
@@ -153,7 +164,7 @@ export function exposeSkills(opts = {}) {
|
|
|
153
164
|
|
|
154
165
|
export function lintSkills(cwd = process.cwd()) {
|
|
155
166
|
const paths = [];
|
|
156
|
-
for (const root of [join(cwd, SKILL_ROOT), join(cwd,
|
|
167
|
+
for (const root of [join(cwd, SKILL_ROOT), join(cwd, SKILL_PATHS.installedRoot)]) {
|
|
157
168
|
if (!existsSync(root)) continue;
|
|
158
169
|
for (const id of readdirSync(root)) {
|
|
159
170
|
const path = join(root, id, "SKILL.md");
|