ai-ops-cli 1.0.1 → 1.0.2
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/README.ko.md +25 -0
- package/README.md +59 -34
- package/data/context-layer/AGENTS.md +5 -4
- package/data/context-layer/docs/agent/rules/00-agent-baseline.md +47 -0
- package/data/packs/spec-lifecycle/docs/specs/README.ko.md +2 -0
- package/data/packs/spec-lifecycle/docs/specs/README.md +2 -0
- package/data/skills/README.ko.md +2 -0
- package/data/skills/README.md +2 -0
- package/data/subagents/README.ko.md +2 -0
- package/data/subagents/README.md +2 -0
- package/dist/bin/index.js +28 -27
- package/dist/bin/index.js.map +1 -1
- package/package.json +1 -1
- package/data/presets.yaml +0 -35
- package/data/rules/code-philosophy.yaml +0 -35
- package/data/rules/communication.yaml +0 -12
- package/data/rules/naming-convention.yaml +0 -10
- package/data/rules/plan-mode.yaml +0 -32
- package/data/rules/role-persona.yaml +0 -14
package/README.ko.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# ai-ops-cli
|
|
2
2
|
|
|
3
|
+
[English](./README.md)
|
|
4
|
+
|
|
3
5
|
`ai-ops-cli`는 프로젝트에 AI agent operating layer를 설치하고, 사용자 환경에 agent skills/subagents를 설치하는 CLI입니다.
|
|
4
6
|
|
|
5
7
|
이 문서는 현재 구현된 breaking model을 설명합니다. old rules + skills scaffolder 모델은 deprecated 문맥으로만 남깁니다.
|
|
@@ -36,6 +38,7 @@ Project repo:
|
|
|
36
38
|
AGENTS.md
|
|
37
39
|
GEMINI.md
|
|
38
40
|
CLAUDE.md
|
|
41
|
+
docs/agent/rules/00-agent-baseline.md
|
|
39
42
|
docs/agent/workflow.md
|
|
40
43
|
docs/agent/rules/routing-rules.md
|
|
41
44
|
docs/agent/rules/doc-update-rules.md
|
|
@@ -49,6 +52,8 @@ docs/docs-status.md
|
|
|
49
52
|
.ai-ops/context-layer.json
|
|
50
53
|
```
|
|
51
54
|
|
|
55
|
+
`docs/agent/rules/00-agent-baseline.md`는 기존 `role-persona`, `communication`, `code-philosophy`, `naming-convention`, `plan-mode`의 기본 의도를 새 operating layer 문서로 이관한 Active 규칙입니다. `AGENTS.md` 직후 먼저 읽습니다.
|
|
56
|
+
|
|
52
57
|
Global tool home:
|
|
53
58
|
|
|
54
59
|
```text
|
|
@@ -56,6 +61,26 @@ skills/*
|
|
|
56
61
|
subagents/*
|
|
57
62
|
```
|
|
58
63
|
|
|
64
|
+
## 수정 FAQ
|
|
65
|
+
|
|
66
|
+
### `ai-ops update`가 덮어쓰는 파일은 무엇인가요?
|
|
67
|
+
|
|
68
|
+
`AGENTS.md`, `GEMINI.md`, `CLAUDE.md`, `docs/agent/rules/*`, `docs/agent/checks/*`, `docs/agent/workflow.md`는 ai-ops managed 문서입니다. 이 파일의 `<!-- ai-ops:start -->`부터 `<!-- ai-ops:end -->`까지는 CLI 템플릿 영역이고, `ai-ops update` 때 현재 CLI 템플릿으로 다시 적용됩니다. 사용자가 이 영역을 직접 수정하면 다음 update에서 유지되지 않습니다.
|
|
69
|
+
|
|
70
|
+
`.ai-ops/manifest.json`과 `.ai-ops/context-layer.json`도 직접 편집 대상이 아닙니다. 각각 설치 상태와 문서 index를 기록하는 CLI 상태 파일입니다.
|
|
71
|
+
|
|
72
|
+
### 사용자가 직접 수정해야 하는 파일은 무엇인가요?
|
|
73
|
+
|
|
74
|
+
프로젝트 지식은 project-owned 문서에 적습니다. 기본 project-owned 문서는 `docs/agent/maps/codebase-map.md`, `docs/business/business-rules.md`, `docs/docs-status.md`입니다. `docs/agent/maps/codebase-map.md`와 `docs/business/business-rules.md`는 처음에는 Reserved 템플릿이지만, 프로젝트가 실제 내용을 채운 뒤에는 update가 자동으로 덮어쓰지 않습니다.
|
|
75
|
+
|
|
76
|
+
`docs/docs-status.md`는 project-owned 문서이지만 자유 메모장이 아니라 context-layer registry입니다. 문서 status/frontmatter를 바꿀 때 함께 맞추는 파일이며, update 과정에서 manifest와 실제 문서 frontmatter 기준으로 테이블이 정리될 수 있습니다.
|
|
77
|
+
|
|
78
|
+
### 프로젝트 고유 agent rule은 어디에 적나요?
|
|
79
|
+
|
|
80
|
+
현재 기본 layer에는 프로젝트 구조와 비즈니스 규칙을 담는 project-owned 문서가 있지만, 프로젝트별 agent 행동 규칙만을 위한 별도 Active 문서는 아직 first-class 템플릿으로 열려 있지 않습니다. 그래서 `AGENTS.md`의 managed 영역이나 tool adapter에 직접 규칙을 추가하는 방식은 update-safe한 계약이 아닙니다.
|
|
81
|
+
|
|
82
|
+
프로젝트별 agent rule을 안정적으로 지원하려면 `docs/agent/rules/project-rules.md` 같은 project-owned Active 문서를 추가하고, manifest/context-layer/docs-status가 함께 추적하도록 제품 계약을 확장하는 것이 다음 개선 후보입니다.
|
|
83
|
+
|
|
59
84
|
## 목표 CLI 표면
|
|
60
85
|
|
|
61
86
|
```text
|
package/README.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# ai-ops-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Korean](./README.ko.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`ai-ops-cli` installs an AI agent operating layer into a project and installs reusable agent skills/subagents into the user's global tool environment.
|
|
6
|
+
|
|
7
|
+
This document describes the currently implemented breaking model. The old rules + skills scaffolder model remains only as deprecated context.
|
|
6
8
|
|
|
7
9
|
## Current Breaking Model
|
|
8
10
|
|
|
9
11
|
```mermaid
|
|
10
12
|
flowchart TD
|
|
11
|
-
init["ai-ops init"] --> layer["
|
|
13
|
+
init["ai-ops init"] --> layer["Install project operating layer"]
|
|
12
14
|
layer --> entry["AGENTS.md canonical entrypoint"]
|
|
13
15
|
layer --> adapters["GEMINI.md / CLAUDE.md adapters"]
|
|
14
16
|
layer --> docs["docs/agent/* / docs/business/*"]
|
|
@@ -19,16 +21,16 @@ flowchart TD
|
|
|
19
21
|
pack["ai-ops pack ..."] --> docsSpecs["optional docs/specs/ pack"]
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
Core boundaries:
|
|
23
25
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- `AGENTS.md
|
|
27
|
-
- `GEMINI.md
|
|
28
|
-
- `docs/specs
|
|
29
|
-
-
|
|
26
|
+
- Project scope manages only operating-layer documents.
|
|
27
|
+
- Global scope manages only skills/subagents.
|
|
28
|
+
- `AGENTS.md` is the canonical entrypoint.
|
|
29
|
+
- `GEMINI.md` and `CLAUDE.md` are adapters that point tools back to `AGENTS.md`.
|
|
30
|
+
- `docs/specs/` is the optional pack location.
|
|
31
|
+
- Global asset commands require `AI_OPS_HOME` or `HOME`; they fail closed without cwd fallback when neither exists.
|
|
30
32
|
|
|
31
|
-
##
|
|
33
|
+
## Install Targets
|
|
32
34
|
|
|
33
35
|
Project repo:
|
|
34
36
|
|
|
@@ -36,6 +38,7 @@ Project repo:
|
|
|
36
38
|
AGENTS.md
|
|
37
39
|
GEMINI.md
|
|
38
40
|
CLAUDE.md
|
|
41
|
+
docs/agent/rules/00-agent-baseline.md
|
|
39
42
|
docs/agent/workflow.md
|
|
40
43
|
docs/agent/rules/routing-rules.md
|
|
41
44
|
docs/agent/rules/doc-update-rules.md
|
|
@@ -49,6 +52,8 @@ docs/docs-status.md
|
|
|
49
52
|
.ai-ops/context-layer.json
|
|
50
53
|
```
|
|
51
54
|
|
|
55
|
+
`docs/agent/rules/00-agent-baseline.md` is the Active rule that carries the original intent of the old `role-persona`, `communication`, `code-philosophy`, `naming-convention`, and `plan-mode` rules into the new operating layer. It is read immediately after `AGENTS.md`.
|
|
56
|
+
|
|
52
57
|
Global tool home:
|
|
53
58
|
|
|
54
59
|
```text
|
|
@@ -56,7 +61,27 @@ skills/*
|
|
|
56
61
|
subagents/*
|
|
57
62
|
```
|
|
58
63
|
|
|
59
|
-
##
|
|
64
|
+
## Editing FAQ
|
|
65
|
+
|
|
66
|
+
### What does `ai-ops update` overwrite?
|
|
67
|
+
|
|
68
|
+
`AGENTS.md`, `GEMINI.md`, `CLAUDE.md`, `docs/agent/rules/*`, `docs/agent/checks/*`, and `docs/agent/workflow.md` are ai-ops managed documents. In these files, the region from `<!-- ai-ops:start -->` through `<!-- ai-ops:end -->` is CLI template content. `ai-ops update` reapplies the current CLI template to that region. User edits inside that region are not preserved across update.
|
|
69
|
+
|
|
70
|
+
`.ai-ops/manifest.json` and `.ai-ops/context-layer.json` are also not direct-edit files. They are CLI state files for installation state and document indexing.
|
|
71
|
+
|
|
72
|
+
### Which files should users edit directly?
|
|
73
|
+
|
|
74
|
+
Project knowledge belongs in project-owned documents. The default project-owned documents are `docs/agent/maps/codebase-map.md`, `docs/business/business-rules.md`, and `docs/docs-status.md`. `docs/agent/maps/codebase-map.md` and `docs/business/business-rules.md` start as Reserved templates, but once the project fills them with real content, update does not automatically overwrite them.
|
|
75
|
+
|
|
76
|
+
`docs/docs-status.md` is project-owned, but it is not a free-form notebook. It is the context-layer registry. Update it together with document status/frontmatter changes; the update flow may also normalize its table from the manifest and current document frontmatter.
|
|
77
|
+
|
|
78
|
+
### Where should project-specific agent rules go?
|
|
79
|
+
|
|
80
|
+
The default layer currently has project-owned documents for project structure and business rules, but it does not yet provide a first-class Active template for project-specific agent behavior rules. Because of that, adding rules inside the managed region of `AGENTS.md` or inside a tool adapter is not an update-safe contract.
|
|
81
|
+
|
|
82
|
+
To support project-specific agent rules safely, the next product extension should add a project-owned Active document such as `docs/agent/rules/project-rules.md` and have the manifest, context-layer index, and docs-status table track it together.
|
|
83
|
+
|
|
84
|
+
## CLI Surface
|
|
60
85
|
|
|
61
86
|
```text
|
|
62
87
|
ai-ops [command]
|
|
@@ -72,9 +97,9 @@ Commands:
|
|
|
72
97
|
pack Manage optional project operating layer packs
|
|
73
98
|
```
|
|
74
99
|
|
|
75
|
-
`--tool
|
|
100
|
+
`--tool` remains because Codex, Claude Code, and Gemini CLI use different discovery locations and adapter files.
|
|
76
101
|
|
|
77
|
-
Skill lifecycle
|
|
102
|
+
Skill lifecycle commands:
|
|
78
103
|
|
|
79
104
|
```bash
|
|
80
105
|
ai-ops skill list
|
|
@@ -85,9 +110,9 @@ ai-ops skill update
|
|
|
85
110
|
ai-ops skill uninstall skill-load-check
|
|
86
111
|
```
|
|
87
112
|
|
|
88
|
-
`doc-impact-reviewer
|
|
113
|
+
`doc-impact-reviewer` is a manual task skill for checking operating-document impact near the end of work or before commit. Invoking `$doc-impact-reviewer` reads git status/diff and reports document update candidates as `required / recommended / not needed`. It does not edit documents, stage files, or commit before user approval.
|
|
89
114
|
|
|
90
|
-
Subagent lifecycle
|
|
115
|
+
Subagent lifecycle commands:
|
|
91
116
|
|
|
92
117
|
```bash
|
|
93
118
|
ai-ops subagent list
|
|
@@ -97,9 +122,9 @@ ai-ops subagent update
|
|
|
97
122
|
ai-ops subagent uninstall security-gate
|
|
98
123
|
```
|
|
99
124
|
|
|
100
|
-
|
|
125
|
+
Subagents are always installed into the global tool home. Codex uses `.codex/agents/<id>.toml`, Claude Code uses `.claude/agents/<id>.md`, Gemini CLI uses `.gemini/agents/<id>.md`, and state is recorded only in `.ai-ops/subagents-manifest.json`.
|
|
101
126
|
|
|
102
|
-
Pack lifecycle
|
|
127
|
+
Pack lifecycle commands:
|
|
103
128
|
|
|
104
129
|
```bash
|
|
105
130
|
ai-ops init --tool codex
|
|
@@ -110,14 +135,14 @@ ai-ops pack update spec-lifecycle
|
|
|
110
135
|
ai-ops pack uninstall spec-lifecycle
|
|
111
136
|
```
|
|
112
137
|
|
|
113
|
-
`spec-lifecycle` pack
|
|
138
|
+
The `spec-lifecycle` pack installs `docs/specs/README.md`, `docs/specs/README.ko.md`, `docs/specs/baseline/.gitkeep`, and `docs/specs/initial-build/.gitkeep`. Only Markdown documents are audited by the context-layer and `docs/docs-status.md`; `.gitkeep` files are tracked only as regular pack files in the manifest.
|
|
114
139
|
|
|
115
140
|
## Deprecated Old Model
|
|
116
141
|
|
|
117
|
-
|
|
142
|
+
The following behaviors may still appear in current code or older docs, but they are outside the new contract:
|
|
118
143
|
|
|
119
144
|
- preset-first init UX
|
|
120
|
-
- project
|
|
145
|
+
- project-scope skill installation
|
|
121
146
|
- `ai-ops skill install --project`
|
|
122
147
|
- project-installed skill metadata
|
|
123
148
|
- `.ai-ops-manifest.json`
|
|
@@ -125,26 +150,26 @@ ai-ops pack uninstall spec-lifecycle
|
|
|
125
150
|
- root `specs/`
|
|
126
151
|
- `ai-ops spec init`
|
|
127
152
|
|
|
128
|
-
|
|
153
|
+
Existing projects are not migrated automatically. Existing users should run `ai-ops uninstall` with the old CLI, then run `ai-ops init` again with the new major CLI.
|
|
129
154
|
|
|
130
155
|
## Old Model Command Notes
|
|
131
156
|
|
|
132
|
-
|
|
157
|
+
The command below remains only as a deprecated old-model example for historical project-scope skill installation. The current skill CLI is global-only and does not expose `--project`, `--global`, or `--scope` as public options.
|
|
133
158
|
|
|
134
159
|
```bash
|
|
135
160
|
ai-ops skill install skill-load-check --project --tool codex
|
|
136
161
|
```
|
|
137
162
|
|
|
138
|
-
Deprecated old
|
|
163
|
+
Deprecated old-model-only items:
|
|
139
164
|
|
|
140
|
-
- `--project
|
|
141
|
-
- `--global
|
|
142
|
-
- `spec init
|
|
143
|
-
- `.ai-ops-manifest.json
|
|
165
|
+
- `--project` was the old option for project-scope skill installation.
|
|
166
|
+
- `--global` and `--scope` were old options for directly selecting skill scope.
|
|
167
|
+
- `spec init` was the removed old command that created root `specs/`.
|
|
168
|
+
- `.ai-ops-manifest.json` was the old project manifest.
|
|
144
169
|
|
|
145
|
-
##
|
|
170
|
+
## Development
|
|
146
171
|
|
|
147
|
-
|
|
172
|
+
From the repository root:
|
|
148
173
|
|
|
149
174
|
```bash
|
|
150
175
|
npm install
|
|
@@ -153,18 +178,18 @@ npm run compile
|
|
|
153
178
|
npm test
|
|
154
179
|
```
|
|
155
180
|
|
|
156
|
-
CLI workspace
|
|
181
|
+
To check only the CLI workspace:
|
|
157
182
|
|
|
158
183
|
```bash
|
|
159
184
|
npm run build --workspace=apps/cli
|
|
160
185
|
npm run test --workspace=apps/cli
|
|
161
186
|
```
|
|
162
187
|
|
|
163
|
-
|
|
188
|
+
Use `npm run check` as the default validation for code and operating-document changes. For CLI release artifacts, run both `npm run build` and `npm run compile`.
|
|
164
189
|
|
|
165
|
-
Self-dogfood
|
|
190
|
+
Self-dogfood validation runs `npm run build`, applies `init --tool codex --tool gemini --tool claude-code` to this repo, then checks `diff`, `audit`, `update --force`, `uninstall --yes`, re-`init`, and re-`audit`. This repo does not install the `spec-lifecycle` pack during self-dogfood; `pack list` only verifies the `not installed` state.
|
|
166
191
|
|
|
167
|
-
##
|
|
192
|
+
## Related Docs
|
|
168
193
|
|
|
169
194
|
- [Master blueprint](../../docs/plan.md)
|
|
170
195
|
- [Implementation playbook](../../docs/implementation-playbook.md)
|
|
@@ -14,10 +14,11 @@ update_when:
|
|
|
14
14
|
## 읽기 순서
|
|
15
15
|
|
|
16
16
|
1. `AGENTS.md`
|
|
17
|
-
2. `docs/agent/
|
|
18
|
-
3. `docs/agent/
|
|
19
|
-
4.
|
|
20
|
-
5. `docs/
|
|
17
|
+
2. `docs/agent/rules/00-agent-baseline.md`
|
|
18
|
+
3. `docs/agent/workflow.md`
|
|
19
|
+
4. 나머지 `docs/agent/rules/*.md`
|
|
20
|
+
5. 작업 성격에 맞는 `docs/agent/checks/*.md`
|
|
21
|
+
6. `docs/docs-status.md`
|
|
21
22
|
|
|
22
23
|
## 문서 신뢰도
|
|
23
24
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: Active
|
|
3
|
+
layer: agent
|
|
4
|
+
owner: ai-ops
|
|
5
|
+
read_when:
|
|
6
|
+
- before_task
|
|
7
|
+
update_when:
|
|
8
|
+
- baseline_rule_changes
|
|
9
|
+
---
|
|
10
|
+
# Agent Baseline Rules
|
|
11
|
+
|
|
12
|
+
이 문서는 모든 작업 전에 먼저 적용할 기본 협업 규칙이다. 세부 routing, workflow, stop rule보다 앞서 읽고, 프로젝트별 Active 문서가 더 구체적인 판단 근거를 제공하면 그 문서를 우선한다.
|
|
13
|
+
|
|
14
|
+
## 협업 태도
|
|
15
|
+
|
|
16
|
+
- 사용자를 초보자로 낮춰 설명하지 않는다.
|
|
17
|
+
- 사용자는 senior developer라고 가정하되, 특정 도메인이나 패턴에 익숙하지 않을 수 있음을 고려한다.
|
|
18
|
+
- 패턴, 라이브러리, 아키텍처를 고를 때는 중요한 선택 이유를 짧게 설명한다.
|
|
19
|
+
- 아키텍처, edge case, 성능, 유지보수성을 우선해 판단한다.
|
|
20
|
+
|
|
21
|
+
## 커뮤니케이션
|
|
22
|
+
|
|
23
|
+
- "Certainly", "Of course", "Here is the code", "I understand", "Great question" 같은 filler phrase로 시작하지 않는다.
|
|
24
|
+
- 사용자가 명시적으로 영어를 요청하지 않는 한, 코드와 inline code comment를 제외한 응답은 한국어로 작성한다.
|
|
25
|
+
- 불확실한 내용은 단정하지 않고 확인 가능한 근거, 추론, 남은 리스크를 구분한다.
|
|
26
|
+
|
|
27
|
+
## 코드 철학
|
|
28
|
+
|
|
29
|
+
- clever하거나 opaque한 코드보다 의도가 드러나는 명시적인 코드를 우선한다.
|
|
30
|
+
- Rule of Three 이전에는 공통 abstraction을 서두르지 않는다.
|
|
31
|
+
- core business logic에는 side effect를 섞지 않고, functional core / imperative shell 구조를 선호한다.
|
|
32
|
+
- 상태 변경은 가능한 한 immutable update로 처리한다.
|
|
33
|
+
- 복잡한 business rule은 실패하는 테스트를 먼저 두고 구현한다.
|
|
34
|
+
- 파일 내부 선언은 types, constants, validators/guards, helper functions, main logic/exports 순서로 배치한다.
|
|
35
|
+
- 한 파일에 의미가 다른 그룹이 둘 이상 있으면 `// ----- types -----` 같은 section divider comment로 경계를 표시한다.
|
|
36
|
+
|
|
37
|
+
## 네이밍
|
|
38
|
+
|
|
39
|
+
- directory name은 kebab-case를 사용한다.
|
|
40
|
+
- 새 파일과 문서 이름은 역할이 드러나는 구체적인 이름을 사용한다.
|
|
41
|
+
|
|
42
|
+
## 계획과 다이어그램
|
|
43
|
+
|
|
44
|
+
- flow, sequence, state, structure를 설명할 때 긴 bullet list보다 Mermaid diagram을 우선 검토한다.
|
|
45
|
+
- UX/control flow와 decision tree는 `flowchart`, request/response와 service interaction은 `sequenceDiagram`, entity/schema relationship은 `erDiagram`, lifecycle/state transition은 `stateDiagram-v2`를 사용한다.
|
|
46
|
+
- Mermaid diagram은 fenced `mermaid` code block으로 작성한다.
|
|
47
|
+
- plan 문서를 저장할 때는 `YYYYMMDD_<topic>.md` 형식을 사용하고, topic은 kebab-case로 작성한다.
|
package/data/skills/README.ko.md
CHANGED
package/data/skills/README.md
CHANGED
package/data/subagents/README.md
CHANGED
package/dist/bin/index.js
CHANGED
|
@@ -491,7 +491,7 @@ import { join as join5 } from "path";
|
|
|
491
491
|
|
|
492
492
|
// src/core/source-hash.ts
|
|
493
493
|
import { createHash } from "crypto";
|
|
494
|
-
import {
|
|
494
|
+
import { readFileSync as readFileSync2, readdirSync as readdirSync2 } from "fs";
|
|
495
495
|
import { dirname, join as join4, resolve as resolve2 } from "path";
|
|
496
496
|
import { fileURLToPath } from "url";
|
|
497
497
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -788,7 +788,7 @@ var writeSubagentManifest = (manifestPath, manifest) => {
|
|
|
788
788
|
import { join as join9 } from "path";
|
|
789
789
|
|
|
790
790
|
// src/core/project-layer.ts
|
|
791
|
-
import { existsSync
|
|
791
|
+
import { existsSync, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync as readdirSync3, rmSync, writeFileSync as writeFileSync4 } from "fs";
|
|
792
792
|
import { dirname as dirname6, isAbsolute, join as join10, relative, resolve as resolve5 } from "path";
|
|
793
793
|
|
|
794
794
|
// src/core/paths.ts
|
|
@@ -808,6 +808,7 @@ var TEMPLATE_PATHS = [
|
|
|
808
808
|
"GEMINI.md",
|
|
809
809
|
"CLAUDE.md",
|
|
810
810
|
"docs/agent/workflow.md",
|
|
811
|
+
"docs/agent/rules/00-agent-baseline.md",
|
|
811
812
|
"docs/agent/rules/routing-rules.md",
|
|
812
813
|
"docs/agent/rules/doc-update-rules.md",
|
|
813
814
|
"docs/agent/rules/stop-rules.md",
|
|
@@ -958,7 +959,7 @@ var installManagedFiles = (basePath, specs, meta) => {
|
|
|
958
959
|
for (const spec of specs) {
|
|
959
960
|
const absolutePath = resolveProjectLayerFilePath(basePath, spec.path);
|
|
960
961
|
const wrappedContent = wrapWithSection(spec.content, meta);
|
|
961
|
-
if (!
|
|
962
|
+
if (!existsSync(absolutePath)) {
|
|
962
963
|
mkdirSync4(dirname6(absolutePath), { recursive: true });
|
|
963
964
|
writeFileSync4(absolutePath, wrappedContent + "\n", "utf-8");
|
|
964
965
|
written.push(spec.path);
|
|
@@ -990,7 +991,7 @@ var installProjectFiles = (params) => {
|
|
|
990
991
|
for (const spec of params.specs) {
|
|
991
992
|
const absolutePath = resolveProjectLayerFilePath(params.basePath, spec.path);
|
|
992
993
|
const previous = previousByPath.get(spec.path);
|
|
993
|
-
if (!
|
|
994
|
+
if (!existsSync(absolutePath)) {
|
|
994
995
|
mkdirSync4(dirname6(absolutePath), { recursive: true });
|
|
995
996
|
writeFileSync4(absolutePath, spec.content + "\n", "utf-8");
|
|
996
997
|
created.push(spec.path);
|
|
@@ -1218,7 +1219,7 @@ var issue = (level, code, message) => ({
|
|
|
1218
1219
|
var readDocumentSafely = (basePath, path) => {
|
|
1219
1220
|
try {
|
|
1220
1221
|
const absolutePath = resolveProjectLayerFilePath(basePath, path);
|
|
1221
|
-
if (!
|
|
1222
|
+
if (!existsSync(absolutePath)) {
|
|
1222
1223
|
return issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${path}`);
|
|
1223
1224
|
}
|
|
1224
1225
|
return parseProjectLayerDocument(path, readFileSync6(absolutePath, "utf-8"));
|
|
@@ -1312,7 +1313,7 @@ var diffProjectLayer = (basePath) => {
|
|
|
1312
1313
|
}
|
|
1313
1314
|
for (const file of manifest.managed_files) {
|
|
1314
1315
|
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
1315
|
-
if (!
|
|
1316
|
+
if (!existsSync(absolutePath)) {
|
|
1316
1317
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
1317
1318
|
continue;
|
|
1318
1319
|
}
|
|
@@ -1329,13 +1330,13 @@ var diffProjectLayer = (basePath) => {
|
|
|
1329
1330
|
}
|
|
1330
1331
|
}
|
|
1331
1332
|
for (const file of manifest.project_files) {
|
|
1332
|
-
if (!
|
|
1333
|
+
if (!existsSync(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
1333
1334
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
1334
1335
|
}
|
|
1335
1336
|
}
|
|
1336
1337
|
for (const pack of manifest.packs) {
|
|
1337
1338
|
for (const file of [...pack.documents, ...pack.files]) {
|
|
1338
|
-
if (!
|
|
1339
|
+
if (!existsSync(resolveProjectLayerFilePath(basePath, file.path))) {
|
|
1339
1340
|
issues.push(issue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
1340
1341
|
}
|
|
1341
1342
|
}
|
|
@@ -1372,7 +1373,7 @@ var auditProjectLayer = (basePath) => {
|
|
|
1372
1373
|
const contextPathSet = new Set(contextIndex?.documents.map((document) => document.path) ?? []);
|
|
1373
1374
|
const issues = [...diffReport.issues];
|
|
1374
1375
|
const docsStatusPath = resolveProjectLayerFilePath(basePath, "docs/docs-status.md");
|
|
1375
|
-
if (!
|
|
1376
|
+
if (!existsSync(docsStatusPath)) {
|
|
1376
1377
|
issues.push(issue("error", "missing-docs-status", "docs/docs-status.md\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
1377
1378
|
return { currentSourceHash: diffReport.currentSourceHash, issues };
|
|
1378
1379
|
}
|
|
@@ -1405,7 +1406,7 @@ var auditProjectLayer = (basePath) => {
|
|
|
1405
1406
|
};
|
|
1406
1407
|
function removeManagedProjectFile(basePath, relativePath) {
|
|
1407
1408
|
const absolutePath = resolveProjectLayerFilePath(basePath, relativePath);
|
|
1408
|
-
if (!
|
|
1409
|
+
if (!existsSync(absolutePath)) {
|
|
1409
1410
|
return { deleted: [], cleaned: [], preserved: [], notFound: [relativePath] };
|
|
1410
1411
|
}
|
|
1411
1412
|
const content = readFileSync6(absolutePath, "utf-8");
|
|
@@ -1422,7 +1423,7 @@ function removeManagedProjectFile(basePath, relativePath) {
|
|
|
1422
1423
|
}
|
|
1423
1424
|
var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
1424
1425
|
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
1425
|
-
if (!
|
|
1426
|
+
if (!existsSync(absolutePath)) {
|
|
1426
1427
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
1427
1428
|
}
|
|
1428
1429
|
const content = readFileSync6(absolutePath, "utf-8").trimEnd();
|
|
@@ -1435,7 +1436,7 @@ var removeCreateOnlyProjectFile = (basePath, file) => {
|
|
|
1435
1436
|
};
|
|
1436
1437
|
var removePackOwnedFile = (basePath, file) => {
|
|
1437
1438
|
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
1438
|
-
if (!
|
|
1439
|
+
if (!existsSync(absolutePath)) {
|
|
1439
1440
|
return { deleted: [], cleaned: [], preserved: [], notFound: [file.path] };
|
|
1440
1441
|
}
|
|
1441
1442
|
const currentHash = computeHash([readFileSync6(absolutePath, "utf-8").trimEnd()]);
|
|
@@ -1457,7 +1458,7 @@ var removeEmptyDirs = (basePath, relativePaths) => {
|
|
|
1457
1458
|
);
|
|
1458
1459
|
for (const dir of [...dirs, ".ai-ops"]) {
|
|
1459
1460
|
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
1460
|
-
if (!
|
|
1461
|
+
if (!existsSync(absoluteDir)) continue;
|
|
1461
1462
|
try {
|
|
1462
1463
|
if (readdirSync3(absoluteDir).length === 0) {
|
|
1463
1464
|
rmSync(absoluteDir, { recursive: true });
|
|
@@ -1482,7 +1483,7 @@ var uninstallProjectLayer = (basePath, manifest) => {
|
|
|
1482
1483
|
};
|
|
1483
1484
|
|
|
1484
1485
|
// src/core/pack.ts
|
|
1485
|
-
import { existsSync as
|
|
1486
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync5, readFileSync as readFileSync7, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
1486
1487
|
import { dirname as dirname7, isAbsolute as isAbsolute2, join as join11, relative as relative2, resolve as resolve6 } from "path";
|
|
1487
1488
|
var PACK_REGISTRY_FILENAME = "pack-registry.json";
|
|
1488
1489
|
var SPEC_LIFECYCLE_PACK_ID = "spec-lifecycle";
|
|
@@ -1603,7 +1604,7 @@ var applyPackSourceFiles = (params) => {
|
|
|
1603
1604
|
for (const file of sourceFiles) {
|
|
1604
1605
|
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
1605
1606
|
const previous = previousByPath.get(file.path);
|
|
1606
|
-
if (!
|
|
1607
|
+
if (!existsSync2(absolutePath)) {
|
|
1607
1608
|
writePackFile(params.basePath, file);
|
|
1608
1609
|
written.push(file.path);
|
|
1609
1610
|
continue;
|
|
@@ -1627,7 +1628,7 @@ var applyPackSourceFiles = (params) => {
|
|
|
1627
1628
|
continue;
|
|
1628
1629
|
}
|
|
1629
1630
|
const absolutePath = resolveProjectLayerFilePath(params.basePath, previous.path);
|
|
1630
|
-
if (!
|
|
1631
|
+
if (!existsSync2(absolutePath)) {
|
|
1631
1632
|
notFound.push(previous.path);
|
|
1632
1633
|
continue;
|
|
1633
1634
|
}
|
|
@@ -1646,7 +1647,7 @@ var removePackFiles = (basePath, record) => {
|
|
|
1646
1647
|
const notFound = [];
|
|
1647
1648
|
for (const file of [...record.documents, ...record.files]) {
|
|
1648
1649
|
const absolutePath = resolveProjectLayerFilePath(basePath, file.path);
|
|
1649
|
-
if (!
|
|
1650
|
+
if (!existsSync2(absolutePath)) {
|
|
1650
1651
|
notFound.push(file.path);
|
|
1651
1652
|
continue;
|
|
1652
1653
|
}
|
|
@@ -1665,7 +1666,7 @@ var removeEmptyDirs2 = (basePath, relativePaths) => {
|
|
|
1665
1666
|
);
|
|
1666
1667
|
for (const dir of dirs) {
|
|
1667
1668
|
const absoluteDir = resolveProjectLayerFilePath(basePath, dir);
|
|
1668
|
-
if (!
|
|
1669
|
+
if (!existsSync2(absoluteDir)) {
|
|
1669
1670
|
continue;
|
|
1670
1671
|
}
|
|
1671
1672
|
try {
|
|
@@ -1781,7 +1782,7 @@ var diffProjectLayerPack = (params) => {
|
|
|
1781
1782
|
}
|
|
1782
1783
|
for (const file of [...record.documents, ...record.files]) {
|
|
1783
1784
|
const absolutePath = resolveProjectLayerFilePath(params.basePath, file.path);
|
|
1784
|
-
if (!
|
|
1785
|
+
if (!existsSync2(absolutePath)) {
|
|
1785
1786
|
issues.push(packIssue("error", "missing-file", `\uD30C\uC77C \uC5C6\uC74C: ${file.path}`));
|
|
1786
1787
|
}
|
|
1787
1788
|
}
|
|
@@ -2080,13 +2081,13 @@ var findInstalledSkill = (installedSkills, skillId) => {
|
|
|
2080
2081
|
};
|
|
2081
2082
|
|
|
2082
2083
|
// src/lib/skill-install.ts
|
|
2083
|
-
import { existsSync as
|
|
2084
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
2084
2085
|
import { dirname as dirname8, resolve as resolve7 } from "path";
|
|
2085
2086
|
var installSkillPackages = (basePath, packages) => {
|
|
2086
2087
|
const writtenRoots = [];
|
|
2087
2088
|
for (const skillPackage of packages) {
|
|
2088
2089
|
const absRoot = resolve7(basePath, skillPackage.rootDir);
|
|
2089
|
-
if (
|
|
2090
|
+
if (existsSync3(absRoot)) {
|
|
2090
2091
|
rmSync3(absRoot, { recursive: true, force: true });
|
|
2091
2092
|
}
|
|
2092
2093
|
for (const file of skillPackage.files) {
|
|
@@ -2102,7 +2103,7 @@ var removeDirectories = (basePath, relativeDirs) => {
|
|
|
2102
2103
|
const removed = [];
|
|
2103
2104
|
for (const relativeDir of relativeDirs) {
|
|
2104
2105
|
const absPath = resolve7(basePath, relativeDir);
|
|
2105
|
-
if (!
|
|
2106
|
+
if (!existsSync3(absPath)) continue;
|
|
2106
2107
|
rmSync3(absPath, { recursive: true, force: true });
|
|
2107
2108
|
removed.push(relativeDir);
|
|
2108
2109
|
}
|
|
@@ -2281,10 +2282,10 @@ var skillUninstallCommand = async (skillId) => {
|
|
|
2281
2282
|
|
|
2282
2283
|
// src/commands/subagent.ts
|
|
2283
2284
|
import * as p8 from "@clack/prompts";
|
|
2284
|
-
import { existsSync as
|
|
2285
|
+
import { existsSync as existsSync5, rmSync as rmSync6 } from "fs";
|
|
2285
2286
|
|
|
2286
2287
|
// src/lib/subagent-install.ts
|
|
2287
|
-
import { existsSync as
|
|
2288
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync7, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
|
|
2288
2289
|
import { dirname as dirname9, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve8 } from "path";
|
|
2289
2290
|
var resolveInsideBasePath = (basePath, relativePath) => {
|
|
2290
2291
|
const absBasePath = resolve8(basePath);
|
|
@@ -2300,7 +2301,7 @@ var installSubagentPackages = (basePath, packages) => {
|
|
|
2300
2301
|
for (const subagentPackage of packages) {
|
|
2301
2302
|
for (const file of subagentPackage.files) {
|
|
2302
2303
|
const absPath = resolveInsideBasePath(basePath, file.relativePath);
|
|
2303
|
-
if (
|
|
2304
|
+
if (existsSync4(absPath)) {
|
|
2304
2305
|
rmSync5(absPath, { recursive: true, force: true });
|
|
2305
2306
|
}
|
|
2306
2307
|
mkdirSync7(dirname9(absPath), { recursive: true });
|
|
@@ -2314,7 +2315,7 @@ var removeSubagentFiles = (basePath, relativePaths) => {
|
|
|
2314
2315
|
const removed = [];
|
|
2315
2316
|
for (const relativePath of relativePaths) {
|
|
2316
2317
|
const absPath = resolveInsideBasePath(basePath, relativePath);
|
|
2317
|
-
if (!
|
|
2318
|
+
if (!existsSync4(absPath)) continue;
|
|
2318
2319
|
rmSync5(absPath, { recursive: true, force: true });
|
|
2319
2320
|
removed.push(relativePath);
|
|
2320
2321
|
}
|
|
@@ -2376,7 +2377,7 @@ var writeUserSubagentState = (params) => {
|
|
|
2376
2377
|
};
|
|
2377
2378
|
var readInstalledSubagents = (basePath) => readSubagentManifest(resolveSubagentManifestPath(basePath))?.subagents ?? [];
|
|
2378
2379
|
var warnMissingSkills = (requiredSkills) => {
|
|
2379
|
-
const missing = requiredSkills.filter((skill) => !
|
|
2380
|
+
const missing = requiredSkills.filter((skill) => !existsSync5(skill.path));
|
|
2380
2381
|
if (missing.length === 0) {
|
|
2381
2382
|
return;
|
|
2382
2383
|
}
|