@fitlab-ai/agent-infra 0.7.0 → 0.7.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.
- package/bin/cli.ts +1 -1
- package/dist/bin/cli.js +1 -1
- package/dist/lib/builtin-tuis.js +45 -0
- package/dist/lib/defaults.json +3 -0
- package/dist/lib/init.js +62 -23
- package/dist/lib/prompt.js +49 -1
- package/dist/lib/sandbox/commands/enter.js +1 -1
- package/dist/lib/sandbox/commands/list-running.js +58 -13
- package/dist/lib/sandbox/commands/rebuild.js +3 -11
- package/dist/lib/sandbox/commands/rm.js +2 -0
- package/dist/lib/sandbox/image-prune.js +18 -0
- package/dist/lib/sandbox/task-resolver.js +18 -0
- package/dist/lib/update.js +59 -18
- package/lib/builtin-tuis.ts +55 -0
- package/lib/defaults.json +3 -0
- package/lib/init.ts +87 -35
- package/lib/prompt.ts +54 -1
- package/lib/sandbox/commands/enter.ts +1 -1
- package/lib/sandbox/commands/list-running.ts +69 -16
- package/lib/sandbox/commands/rebuild.ts +3 -12
- package/lib/sandbox/commands/rm.ts +3 -0
- package/lib/sandbox/image-prune.ts +23 -0
- package/lib/sandbox/task-resolver.ts +23 -1
- package/lib/update.ts +71 -30
- package/package.json +1 -1
- package/templates/.agents/README.en.md +32 -0
- package/templates/.agents/README.zh-CN.md +32 -0
- package/templates/.agents/rules/task-short-id.en.md +141 -0
- package/templates/.agents/rules/task-short-id.zh-CN.md +124 -0
- package/templates/.agents/scripts/task-short-id.js +713 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/block-task/SKILL.en.md +12 -0
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +12 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +12 -0
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +12 -1
- package/templates/.agents/skills/check-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/close-codescan/SKILL.en.md +11 -0
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +11 -0
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +11 -0
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +11 -0
- package/templates/.agents/skills/code-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/commit/SKILL.en.md +4 -0
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +4 -0
- package/templates/.agents/skills/complete-task/SKILL.en.md +12 -0
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +12 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +4 -0
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -0
- package/templates/.agents/skills/create-task/SKILL.en.md +14 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/import-codescan/SKILL.en.md +14 -0
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +14 -0
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +14 -0
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +14 -0
- package/templates/.agents/skills/import-issue/SKILL.en.md +14 -0
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +14 -0
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/restore-task/SKILL.en.md +12 -0
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +12 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +4 -0
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/review-code/SKILL.en.md +4 -0
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/review-plan/SKILL.en.md +4 -0
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +112 -21
- package/templates/.agents/templates/task.en.md +1 -0
- package/templates/.agents/templates/task.zh-CN.md +1 -0
|
@@ -13,6 +13,10 @@ Import the specified Issue and create a task. Argument: issue number.
|
|
|
13
13
|
- Do not write or modify business code; import only
|
|
14
14
|
- After executing this skill, you **must** immediately update task status
|
|
15
15
|
|
|
16
|
+
## Task id short ref
|
|
17
|
+
|
|
18
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
19
|
+
|
|
16
20
|
## Execution Flow
|
|
17
21
|
|
|
18
22
|
### 1. Retrieve Issue Information
|
|
@@ -119,6 +123,14 @@ If task.md contains a valid `issue_number`, perform these sync actions (skip and
|
|
|
119
123
|
|
|
120
124
|
### 7. Verification Gate
|
|
121
125
|
|
|
126
|
+
**Allocate short id first** (writes `short_id` back to task.md and the registry entry; the validation gate will read it):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
node .agents/scripts/task-short-id.js alloc "$task_id"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
If this fails (non-zero exit), follow the message — archive some active tasks or raise `task.shortIdLength` — and do NOT continue.
|
|
133
|
+
|
|
122
134
|
Run the verification gate to confirm the task artifact and sync state are valid:
|
|
123
135
|
|
|
124
136
|
```bash
|
|
@@ -155,6 +167,8 @@ Next step - run requirements analysis:
|
|
|
155
167
|
- Codex CLI: $analyze-task {task-id}
|
|
156
168
|
```
|
|
157
169
|
|
|
170
|
+
|
|
171
|
+
|
|
158
172
|
## Completion Checklist
|
|
159
173
|
|
|
160
174
|
- [ ] Created the task file `.agents/workspace/active/{task-id}/task.md`
|
|
@@ -13,6 +13,10 @@ description: "从 Issue 导入并创建任务"
|
|
|
13
13
|
- 不要编写或修改业务代码。仅做导入
|
|
14
14
|
- 执行本技能后,你**必须**立即更新任务状态
|
|
15
15
|
|
|
16
|
+
## 任务入参短号别名
|
|
17
|
+
|
|
18
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
19
|
+
|
|
16
20
|
## 执行流程
|
|
17
21
|
|
|
18
22
|
### 1. 获取 Issue 信息
|
|
@@ -119,6 +123,14 @@ date "+%Y-%m-%d %H:%M:%S%:z"
|
|
|
119
123
|
|
|
120
124
|
### 7. 完成校验
|
|
121
125
|
|
|
126
|
+
**先调用短号分配**(保证 `short_id` 写回 task.md + 注册表 entry 已在;完成校验阶段会读取):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
node .agents/scripts/task-short-id.js alloc "$task_id"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
如失败(退出码非 0),按提示「归档若干任务」或「调高 task.shortIdLength」处理;不要继续执行后续步骤。
|
|
133
|
+
|
|
122
134
|
运行完成校验,确认任务产物和同步状态符合规范:
|
|
123
135
|
|
|
124
136
|
```bash
|
|
@@ -155,6 +167,8 @@ Issue #{number} 已导入。
|
|
|
155
167
|
- Codex CLI:$analyze-task {task-id}
|
|
156
168
|
```
|
|
157
169
|
|
|
170
|
+
|
|
171
|
+
|
|
158
172
|
## 完成检查清单
|
|
159
173
|
|
|
160
174
|
- [ ] 创建了任务文件 `.agents/workspace/active/{task-id}/task.md`
|
|
@@ -27,6 +27,10 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
27
27
|
|
|
28
28
|
Before the state check is complete, do not make external-state assertions such as "the code is unchanged", "tests passed", or "there are no other references", including in reasoning. This gate is only a structural floor; evidence pairing and authenticity still require the report template and review discipline.
|
|
29
29
|
|
|
30
|
+
## Task id short ref
|
|
31
|
+
|
|
32
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
33
|
+
|
|
30
34
|
## Steps
|
|
31
35
|
|
|
32
36
|
### 1. Verify Prerequisites
|
|
@@ -27,8 +27,11 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
27
27
|
|
|
28
28
|
状态核对完成前,禁止任何关于外部状态的断言(例如“代码没变”“测试已通过”“没有其他引用”),包括思考阶段。本门禁只提供结构下限;逐条证据配对和真实性仍需按报告模板与审查要求核对。
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## 任务入参短号别名
|
|
31
|
+
|
|
32
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
31
33
|
|
|
34
|
+
## 执行步骤
|
|
32
35
|
### 1. 验证前置条件
|
|
33
36
|
|
|
34
37
|
检查必要文件:
|
|
@@ -16,6 +16,10 @@ Restore local task workspace files from platform Issue comments that contain syn
|
|
|
16
16
|
|
|
17
17
|
Version stamp rule: when creating or updating `task.md` frontmatter, read `.agents/rules/version-stamp.md` first and write or refresh `agent_infra_version`.
|
|
18
18
|
|
|
19
|
+
## Task id short ref
|
|
20
|
+
|
|
21
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
22
|
+
|
|
19
23
|
## Steps
|
|
20
24
|
|
|
21
25
|
### 1. Verify Input and Environment
|
|
@@ -90,10 +94,18 @@ Update the restored `task.md`:
|
|
|
90
94
|
|
|
91
95
|
Append an Activity Log entry indicating the task was restored from the platform Issue.
|
|
92
96
|
|
|
97
|
+
**Re-allocate short id** (the task directory is back under `active/`; alloc a new `#N`, which may differ from the pre-archival value):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
node .agents/scripts/task-short-id.js alloc "$task_id"
|
|
101
|
+
```
|
|
102
|
+
|
|
93
103
|
### 7. Inform User
|
|
94
104
|
|
|
95
105
|
Report the restored task id, restored file count, and the active task directory.
|
|
96
106
|
|
|
107
|
+
|
|
108
|
+
|
|
97
109
|
## Completion Checklist
|
|
98
110
|
|
|
99
111
|
- [ ] Fetched Issue comments from the platform
|
|
@@ -16,8 +16,11 @@ description: "从平台 Issue 评论还原本地任务文件"
|
|
|
16
16
|
|
|
17
17
|
版本戳规则:创建或更新 `task.md` frontmatter 时,先读取 `.agents/rules/version-stamp.md`,并写入或刷新 `agent_infra_version`。
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## 任务入参短号别名
|
|
20
|
+
|
|
21
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
20
22
|
|
|
23
|
+
## 执行步骤
|
|
21
24
|
### 1. 验证输入与环境
|
|
22
25
|
|
|
23
26
|
检查:
|
|
@@ -90,10 +93,18 @@ date "+%Y-%m-%d %H:%M:%S%:z"
|
|
|
90
93
|
|
|
91
94
|
追加 Activity Log,说明任务已从平台 Issue 还原。
|
|
92
95
|
|
|
96
|
+
**重新分配短号**(已把任务目录写回 `active/`,需要在锁内重新 alloc;新短号可能与归档前不同):
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
node .agents/scripts/task-short-id.js alloc "$task_id"
|
|
100
|
+
```
|
|
101
|
+
|
|
93
102
|
### 7. 告知用户
|
|
94
103
|
|
|
95
104
|
报告已恢复的 task id、恢复文件数量和 active task 目录。
|
|
96
105
|
|
|
106
|
+
|
|
107
|
+
|
|
97
108
|
## 完成检查清单
|
|
98
109
|
|
|
99
110
|
- [ ] 已从平台获取 Issue 评论
|
|
@@ -26,6 +26,10 @@ ls -la .agents/workspace/active/{task-id}/
|
|
|
26
26
|
tail .agents/workspace/active/{task-id}/task.md
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## Task id short ref
|
|
30
|
+
|
|
31
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
32
|
+
|
|
29
33
|
## Steps
|
|
30
34
|
|
|
31
35
|
### 1. Verify Prerequisites
|
|
@@ -28,8 +28,11 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
28
28
|
|
|
29
29
|
状态核对完成前,禁止任何关于外部状态的断言。
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## 任务入参短号别名
|
|
32
|
+
|
|
33
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
32
34
|
|
|
35
|
+
## 执行步骤
|
|
33
36
|
### 1. 验证前置条件
|
|
34
37
|
|
|
35
38
|
要求存在:
|
|
@@ -36,6 +36,10 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
36
36
|
|
|
37
37
|
Before the state check is complete, do not make external-state assertions such as "the code is unchanged", "tests passed", or "there are no other references", including in reasoning. This gate is only a structural floor; evidence pairing and authenticity still require the report template and review discipline.
|
|
38
38
|
|
|
39
|
+
## Task id short ref
|
|
40
|
+
|
|
41
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
42
|
+
|
|
39
43
|
## Steps
|
|
40
44
|
|
|
41
45
|
### 1. Verify Prerequisites
|
|
@@ -36,8 +36,11 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
36
36
|
|
|
37
37
|
状态核对完成前,禁止任何关于外部状态的断言(例如“代码没变”“测试已通过”“没有其他引用”),包括思考阶段。本门禁只提供结构下限;逐条证据配对和真实性仍需按报告模板与审查要求核对。
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## 任务入参短号别名
|
|
40
|
+
|
|
41
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
40
42
|
|
|
43
|
+
## 执行步骤
|
|
41
44
|
### 1. 验证前置条件
|
|
42
45
|
|
|
43
46
|
要求存在:
|
|
@@ -26,6 +26,10 @@ ls -la .agents/workspace/active/{task-id}/
|
|
|
26
26
|
tail .agents/workspace/active/{task-id}/task.md
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## Task id short ref
|
|
30
|
+
|
|
31
|
+
> If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
|
|
32
|
+
|
|
29
33
|
## Steps
|
|
30
34
|
|
|
31
35
|
### 1. Verify Prerequisites
|
|
@@ -28,8 +28,11 @@ tail .agents/workspace/active/{task-id}/task.md
|
|
|
28
28
|
|
|
29
29
|
状态核对完成前,禁止任何关于外部状态的断言。
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## 任务入参短号别名
|
|
32
|
+
|
|
33
|
+
> 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
|
|
32
34
|
|
|
35
|
+
## 执行步骤
|
|
33
36
|
### 1. 验证前置条件
|
|
34
37
|
|
|
35
38
|
要求存在:
|
|
@@ -47,6 +47,7 @@ The script outputs JSON to stdout. Parse and record the report.
|
|
|
47
47
|
- `managed.written` / `managed.created`: updated / newly created managed files
|
|
48
48
|
- `managed.removed`: deleted managed files (including old paths removed during template migrations)
|
|
49
49
|
- `managed.skippedPlatform`: managed / merged entries skipped because they belong to a different platform
|
|
50
|
+
- `managed.skippedTUI`: managed / merged entries skipped because they are owned by a built-in TUI that is disabled in `tuis` (customTUI command files under the same path prefix are preserved)
|
|
50
51
|
- `merged.pending`: list of merged files for AI to process
|
|
51
52
|
- Each item has `target` (project-relative path) and `template` (template-root-relative path)
|
|
52
53
|
- `registryAdded`: newly added file registry entries
|
|
@@ -39,6 +39,7 @@ node .agents/skills/update-agent-infra/scripts/sync-templates.js
|
|
|
39
39
|
- `managed.written` / `managed.created`:已更新/新建的 managed 文件
|
|
40
40
|
- `managed.removed`:被删除的 managed 文件(包括模板迁移时移除的旧路径)
|
|
41
41
|
- `managed.skippedPlatform`:因归属其他平台而被跳过的 managed / merged 条目
|
|
42
|
+
- `managed.skippedTUI`:因 `tuis` 中未启用对应内建 TUI 而被跳过的 managed / merged 条目(落在同一路径前缀下的 customTUI 命令文件会被保留)
|
|
42
43
|
- `merged.pending`:需要 AI 处理的 merged 文件列表
|
|
43
44
|
- 每项包含 `target`(项目中的目标路径)和 `template`(模板根目录下的相对路径)
|
|
44
45
|
- `registryAdded`:新增的文件注册条目
|
|
@@ -42,6 +42,9 @@ const DEFAULTS = {
|
|
|
42
42
|
"disk": null
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
+
"task": {
|
|
46
|
+
"shortIdLength": 2
|
|
47
|
+
},
|
|
45
48
|
"labels": {
|
|
46
49
|
"in": {}
|
|
47
50
|
},
|
|
@@ -88,6 +91,39 @@ const PACKAGE_NAME = '@fitlab-ai/agent-infra';
|
|
|
88
91
|
const KNOWN_PLATFORMS = new Set(['github']);
|
|
89
92
|
const KNOWN_LANGUAGES = new Set(['en', 'zh-CN']);
|
|
90
93
|
|
|
94
|
+
// Single source of truth for built-in TUI ids and owned path prefixes.
|
|
95
|
+
// Keep in sync with lib/builtin-tuis.ts (enforced by tests/unit/scripts/sync-templates-consts.test.ts).
|
|
96
|
+
const BUILTIN_TUI_IDS = ['claude-code', 'codex', 'gemini-cli', 'opencode'];
|
|
97
|
+
const BUILTIN_TUI_OWNED_PATH_PREFIXES = {
|
|
98
|
+
'claude-code': ['.claude/'],
|
|
99
|
+
'codex': ['.codex/'],
|
|
100
|
+
'gemini-cli': ['.gemini/'],
|
|
101
|
+
'opencode': ['.opencode/']
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function resolveEnabledTUIs(value) {
|
|
105
|
+
// Missing field / null / non-array → full set (backward compat).
|
|
106
|
+
if (!Array.isArray(value)) return new Set(BUILTIN_TUI_IDS);
|
|
107
|
+
// Empty array is a meaningful user choice: no built-in TUI managed.
|
|
108
|
+
const set = new Set();
|
|
109
|
+
for (const v of value) {
|
|
110
|
+
if (typeof v === 'string' && BUILTIN_TUI_IDS.includes(v)) set.add(v);
|
|
111
|
+
}
|
|
112
|
+
return set;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isPathOwnedByDisabledTUI(rel, enabledSet) {
|
|
116
|
+
const normalized = String(rel || '').replace(/\\/g, '/').replace(/^\.\//, '');
|
|
117
|
+
for (const tui of BUILTIN_TUI_IDS) {
|
|
118
|
+
if (enabledSet.has(tui)) continue;
|
|
119
|
+
for (const prefix of BUILTIN_TUI_OWNED_PATH_PREFIXES[tui]) {
|
|
120
|
+
const trimmed = prefix.replace(/\/$/, '');
|
|
121
|
+
if (normalized === trimmed || normalized.startsWith(prefix)) return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
91
127
|
function norm(p) { return p.replace(/\\/g, '/'); }
|
|
92
128
|
|
|
93
129
|
function normDir(p) {
|
|
@@ -654,26 +690,32 @@ function learnAndGenerateCommands(projectRoot, customSkills, tool, templateSkill
|
|
|
654
690
|
}
|
|
655
691
|
}
|
|
656
692
|
|
|
657
|
-
function generateCustomCommands(projectRoot, customSkills, project, lang, report, customTUIs, templateSkillNames) {
|
|
693
|
+
function generateCustomCommands(projectRoot, customSkills, project, lang, report, customTUIs, templateSkillNames, enabledTUIs) {
|
|
658
694
|
for (const skill of customSkills) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
695
|
+
if (enabledTUIs.has('claude-code')) {
|
|
696
|
+
writeIfChanged(
|
|
697
|
+
projectRoot,
|
|
698
|
+
`.claude/commands/${skill.dirName}.md`,
|
|
699
|
+
generateClaudeCommand(skill, lang),
|
|
700
|
+
report.custom.commands
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
if (enabledTUIs.has('gemini-cli')) {
|
|
704
|
+
writeIfChanged(
|
|
705
|
+
projectRoot,
|
|
706
|
+
'.gemini/commands/' + project + '/' + skill.dirName + '.toml',
|
|
707
|
+
generateGeminiCommand(skill, lang),
|
|
708
|
+
report.custom.commands
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
if (enabledTUIs.has('opencode')) {
|
|
712
|
+
writeIfChanged(
|
|
713
|
+
projectRoot,
|
|
714
|
+
`.opencode/commands/${skill.dirName}.md`,
|
|
715
|
+
generateOpenCodeCommand(skill, lang),
|
|
716
|
+
report.custom.commands
|
|
717
|
+
);
|
|
718
|
+
}
|
|
677
719
|
}
|
|
678
720
|
|
|
679
721
|
const tools = Array.isArray(customTUIs) ? customTUIs : [];
|
|
@@ -969,6 +1011,7 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
969
1011
|
|
|
970
1012
|
const { project, org, language: lang = 'en' } = cfg;
|
|
971
1013
|
const platformType = cfg.platform?.type || DEFAULTS.platform.type;
|
|
1014
|
+
const enabledTUIs = resolveEnabledTUIs(cfg.tuis);
|
|
972
1015
|
const customTUIsConfig = Array.isArray(cfg.customTUIs) ? cfg.customTUIs : [];
|
|
973
1016
|
const vars = { project, org };
|
|
974
1017
|
const templateSkillNames = listTemplateSkillNames(templateRoot);
|
|
@@ -989,7 +1032,7 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
989
1032
|
errors: [],
|
|
990
1033
|
conflicts: []
|
|
991
1034
|
},
|
|
992
|
-
managed: { written: [], created: [], unchanged: [], skippedMerged: [], skippedPlatform: [], removed: [] },
|
|
1035
|
+
managed: { written: [], created: [], unchanged: [], skippedMerged: [], skippedPlatform: [], skippedTUI: [], removed: [] },
|
|
993
1036
|
custom: {
|
|
994
1037
|
detected: [],
|
|
995
1038
|
generated: [],
|
|
@@ -1016,10 +1059,12 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
1016
1059
|
const known = new Set([...managed, ...merged, ...ejected]);
|
|
1017
1060
|
for (const e of (DEFAULTS.files.managed || [])) {
|
|
1018
1061
|
if (isPathOwnedByOtherPlatform(e, platformType)) continue;
|
|
1062
|
+
if (isPathOwnedByDisabledTUI(e, enabledTUIs)) continue;
|
|
1019
1063
|
if (!known.has(e)) { managed.push(e); known.add(e); report.registryAdded.push({ entry: e, list: 'managed' }); }
|
|
1020
1064
|
}
|
|
1021
1065
|
for (const e of (DEFAULTS.files.merged || [])) {
|
|
1022
1066
|
if (isPathOwnedByOtherPlatform(e, platformType)) continue;
|
|
1067
|
+
if (isPathOwnedByDisabledTUI(e, enabledTUIs)) continue;
|
|
1023
1068
|
if (!known.has(e)) { merged.push(e); known.add(e); report.registryAdded.push({ entry: e, list: 'merged' }); }
|
|
1024
1069
|
}
|
|
1025
1070
|
|
|
@@ -1050,11 +1095,50 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
1050
1095
|
report.managed.removed.push(norm(path.relative(projectRoot, target)));
|
|
1051
1096
|
}
|
|
1052
1097
|
|
|
1098
|
+
// Cleanup files owned by disabled built-in TUIs. Iterates managed + merged
|
|
1099
|
+
// only (ejected entries are explicitly user-retained, see ejected loop below).
|
|
1100
|
+
//
|
|
1101
|
+
// Protection rule: only skip files registered as customTUI command targets
|
|
1102
|
+
// (e.g. a customTUI configured with dir=.codex/commands/ when codex is
|
|
1103
|
+
// disabled). Built-in TUI custom-skill commands like
|
|
1104
|
+
// .gemini/commands/<project>/<dirName>.toml are intentionally NOT protected
|
|
1105
|
+
// here so that disabling gemini-cli actually frees the gemini directory —
|
|
1106
|
+
// they will be regenerated only for still-enabled TUIs (see
|
|
1107
|
+
// generateCustomCommands).
|
|
1108
|
+
for (const entry of [...managed, ...merged]) {
|
|
1109
|
+
if (!isPathOwnedByDisabledTUI(entry, enabledTUIs)) continue;
|
|
1110
|
+
|
|
1111
|
+
if (entry.endsWith('/')) {
|
|
1112
|
+
const dir = path.join(projectRoot, entry);
|
|
1113
|
+
if (!fs.existsSync(dir)) continue;
|
|
1114
|
+
|
|
1115
|
+
for (const filePath of walkDir(dir)) {
|
|
1116
|
+
const relProj = norm(path.relative(projectRoot, filePath));
|
|
1117
|
+
if (customTUICommandTargets.has(relProj)) continue;
|
|
1118
|
+
fs.unlinkSync(filePath);
|
|
1119
|
+
report.managed.removed.push(relProj);
|
|
1120
|
+
}
|
|
1121
|
+
removeEmptyDirs(dir);
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
const target = path.join(projectRoot, renderPathname(entry, project));
|
|
1126
|
+
if (!fs.existsSync(target)) continue;
|
|
1127
|
+
const relProj = norm(path.relative(projectRoot, target));
|
|
1128
|
+
if (customTUICommandTargets.has(relProj)) continue;
|
|
1129
|
+
fs.unlinkSync(target);
|
|
1130
|
+
report.managed.removed.push(relProj);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1053
1133
|
for (const entry of managed) {
|
|
1054
1134
|
if (isPathOwnedByOtherPlatform(entry, platformType)) {
|
|
1055
1135
|
report.managed.skippedPlatform.push(entry);
|
|
1056
1136
|
continue;
|
|
1057
1137
|
}
|
|
1138
|
+
if (isPathOwnedByDisabledTUI(entry, enabledTUIs)) {
|
|
1139
|
+
report.managed.skippedTUI.push(entry);
|
|
1140
|
+
continue;
|
|
1141
|
+
}
|
|
1058
1142
|
|
|
1059
1143
|
const isDir = entry.endsWith('/');
|
|
1060
1144
|
let entryRels;
|
|
@@ -1140,7 +1224,7 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
1140
1224
|
|
|
1141
1225
|
const customSkills = detectCustomSkills(projectRoot, templateSkillNames);
|
|
1142
1226
|
report.custom.detected = customSkills.map((skill) => skill.dirName);
|
|
1143
|
-
generateCustomCommands(projectRoot, customSkills, project, lang, report, customTUIs, templateSkillNames);
|
|
1227
|
+
generateCustomCommands(projectRoot, customSkills, project, lang, report, customTUIs, templateSkillNames, enabledTUIs);
|
|
1144
1228
|
|
|
1145
1229
|
for (const entry of ejected) {
|
|
1146
1230
|
const dstFull = path.join(projectRoot, entry);
|
|
@@ -1148,6 +1232,9 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
1148
1232
|
report.ejected.skipped.push(entry);
|
|
1149
1233
|
continue;
|
|
1150
1234
|
}
|
|
1235
|
+
// Do not (re)create ejected files for disabled TUIs. Existing files are
|
|
1236
|
+
// never touched by sync (handled above); this guard only blocks creation.
|
|
1237
|
+
if (isPathOwnedByDisabledTUI(entry, enabledTUIs)) continue;
|
|
1151
1238
|
|
|
1152
1239
|
const selected = platformSelect(langSelect(entryVariantRels(entry, allSet, platformType), lang, allSet, project), platformType, project);
|
|
1153
1240
|
const target = norm(renderPathname(entry, project));
|
|
@@ -1168,6 +1255,10 @@ function syncTemplates(projectRoot, templateRootOverride) {
|
|
|
1168
1255
|
report.managed.skippedPlatform.push(entry);
|
|
1169
1256
|
continue;
|
|
1170
1257
|
}
|
|
1258
|
+
if (isPathOwnedByDisabledTUI(entry, enabledTUIs)) {
|
|
1259
|
+
report.managed.skippedTUI.push(entry);
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1171
1262
|
|
|
1172
1263
|
if (entry.includes('*')) {
|
|
1173
1264
|
const hits = allRels.filter(r => {
|
|
@@ -7,6 +7,7 @@ status: open # open | in-progress | review | blocked | complet
|
|
|
7
7
|
created_at: YYYY-MM-DDTHH:mm:ss±HH:MM
|
|
8
8
|
updated_at: YYYY-MM-DDTHH:mm:ss±HH:MM
|
|
9
9
|
agent_infra_version: v0.0.0 # Current agent-infra version; refreshed by workflow commands
|
|
10
|
+
short_id: # Allocated by create-task / import-* in active window; kept as historical value after archival
|
|
10
11
|
priority: # Optional Issue field: Urgent | High | Medium | Low
|
|
11
12
|
effort: # Optional Issue field: High | Medium | Low
|
|
12
13
|
start_date: # Optional Issue field for Feature: YYYY-MM-DD
|
|
@@ -7,6 +7,7 @@ status: open # open | in-progress | review | blocked | complet
|
|
|
7
7
|
created_at: YYYY-MM-DDTHH:mm:ss±HH:MM
|
|
8
8
|
updated_at: YYYY-MM-DDTHH:mm:ss±HH:MM
|
|
9
9
|
agent_infra_version: v0.0.0 # 当前 agent-infra 版本;由工作流命令刷新
|
|
10
|
+
short_id: # 由 create-task / import-* 在 active 期内写入;归档后保留历史值
|
|
10
11
|
priority: # 可选 Issue 字段:Urgent | High | Medium | Low
|
|
11
12
|
effort: # 可选 Issue 字段:High | Medium | Low
|
|
12
13
|
start_date: # Feature 可选 Issue 字段:YYYY-MM-DD
|