@arcships/morula-runtime 0.1.0-alpha.1 → 0.1.0-alpha.10

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.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "morula-cli",
3
+ "version": "0.1.0-alpha.10",
4
+ "description": "Use Morula CLI task management from DimCode.",
5
+ "interface": {
6
+ "displayName": "Morula CLI",
7
+ "shortDescription": "Operate Morula task management from DimCode."
8
+ },
9
+ "skills": "./skills"
10
+ }
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: morula-cli
3
+ description: 使用 Morula CLI 管理任务、空间、成员、评论与自动化报告。当用户要求操作 Morula 任务系统或产出自动化报告时使用。
4
+ ---
5
+
6
+ # Morula CLI
7
+
8
+ ## 能力速查
9
+
10
+ | 操作 | 命令 | 风险 | 审批 |
11
+ |------|------|------|------|
12
+ | 查任务 | `morula task list [flags]`(`--mine` 仅我负责) | `read_only` | 自动 |
13
+ | 任务详情 | `morula task get <id>` | `read_only` | 自动 |
14
+ | 创建任务 | `morula task create --space <id> --title "标题" [flags]` | `write_internal` | **需确认** |
15
+ | 更新任务 | `morula task update <id> [flags]` | `write_internal` | **需确认** |
16
+ | 删除任务 | `morula task delete <id>` | `destructive` | **需预演+确认** (硬删除) |
17
+ | 查空间 | `morula space list [flags]` | `read_only` | 自动 |
18
+ | 空间详情 | `morula space get <id>` | `read_only` | 自动 |
19
+ | 查成员 | `morula space-member list --space <id>` | `read_only` | 自动 |
20
+ | 添加成员 | `morula space-member add --space <id> --principal <id> [--role <admin|member>]` | `identity_access` | **需确认** |
21
+ | 移除成员 | `morula space-member remove <member-id>` | `identity_access` | **需确认** |
22
+ | 查看评论 | `morula comment list --object <id>` | `read_only` | 自动 |
23
+ | 添加评论 | `morula comment add --object <id> --content "内容"` | `write_internal` | **需确认** |
24
+ | 删除评论 | `morula comment delete <id>` | `destructive` | **需预演+确认** (硬删除) |
25
+ | 产出报告 | `morula report create --title "标题" --content-file <path>` | `write_internal` | 自动(见下方「何时产出报告」) |
26
+ | 查看报告 | `morula report list --autopilot <id>` / `morula report get <id>` | `read_only` | 自动 |
27
+ | 上传文件 | `morula attachment upload <file> --object <id>`(挂任务)/ `--comment <id>`(挂评论) | `write_internal` | **需确认** |
28
+
29
+ 完整参数见 [commands.md](references/commands.md)。
30
+
31
+ ## 何时产出报告(`morula report create`)
32
+
33
+ 报告是**归属于某个自动化**的产出域(正文为 Markdown),人从该自动化的卡片「报告」入口查看——不进任务看板、不占任务编号、也不写进评论。判据:
34
+
35
+ - **该产出**:一次执行得出的**结论型重内容**——扫描/巡检结果、审查结论、分析摘要、对比清单、需要留档的建议。产出后可另用 `morula task create` 建任务跟进。
36
+ - **不该产出**:过程性进度、寒暄、需要人立刻拍板的一句话(短信息走评论/收件箱,只有重内容进报告域);终端输出用户看不到,需要留档的结论必须落到报告或评论。
37
+ - 一次执行可产 0..N 份,份数由 agent 判断;长报告先写进文件再用 `--content-file <path>`(超长正文不要塞进 `--content` 命令行)。
38
+ - `--autopilot` 仅在**没有执行上下文**时才需要显式传:在 agent 任务里省略,服务端按当前任务反查所属自动化并自动绑定 `runId`;若服务端返回「当前执行上下文未关联自动化」,才补 `--autopilot <id>`。
39
+
40
+ ## 审批规则
41
+
42
+ | 风险等级 | Agent 行为 |
43
+ |---------|-----------|
44
+ | `read_only` | 直接在终端执行,结果格式化展示 |
45
+ | `write_internal` | 向用户确认"即将创建/更新 [资源名],确认?",用户同意后执行 |
46
+ | `destructive` | 先 `get <id>` 展示将被删除的资源详情 → 用户确认 → 执行,不可自动重试 |
47
+
48
+ ## 操作前收集
49
+
50
+ | 操作 | 必需信息 | 获取方式 |
51
+ |------|---------|---------|
52
+ | 创建任务 | `spaceId`, `title` | `space list` 获取 spaceId;用户提供 title |
53
+ | 更新任务 | `taskId` | `task list` 获取目标 taskId |
54
+ | 删除任务 | `taskId` | `task list` 获取 → `task get <id>` 确认标题/空间后删除 |
55
+ | 管理成员 | `spaceId`, `principalId` | `space-member list --space <id>` 获取 |
56
+ | 管理评论 | `objectId`, `content` | `task get <id>` 获取 objectId;用户提供内容 |
57
+ | 产出报告 | `title`, 正文 | 标题与正文来自本次执行的结论;长正文先写文件再 `--content-file <path>` |
58
+
59
+ ## 验证操作成功
60
+
61
+ | 操作 | 验证方法 |
62
+ |------|---------|
63
+ | create | 返回 JSON 含 `id` + `code`(如 TASK-042) |
64
+ | update | JSON 返回更新后的字段值,确认与输入一致 |
65
+ | delete | 退出码 0;再次 `get <id>` 应返回退出码 3(404) |
66
+ | login | `auth status` 应返回 `"loggedIn": true` |
67
+
68
+ ## 数据量控制
69
+
70
+ - 列表命令默认 `--page-size 10`(后端 REST 默认值),单次向用户展示不超过 20 条
71
+ - 用户要求"全部"时自动翻页,每页最多 100000 条(后端 REST 上限)
72
+ - 超过 100 条结果 → 摘要展示前 5 条 + "共 X 条,建议缩小筛选范围"
73
+ - 注意:`--page-size` 的"每页最多 50 条"限制仅存在于服务端 Agent 的 `search_objects` 工具(MCP 通道),CLI 走 REST 不受此限
74
+
75
+ ## 幂等性
76
+
77
+ | 命令 | 重试策略 |
78
+ |------|---------|
79
+ | `list` / `get` / `status` | ✅ 安全重试 |
80
+ | `create` | ⚠️ 重试可能重复创建;401/5xx 时先检查是否已创建成功再决定 |
81
+ | `update` | ✅ 安全重试(覆盖更新) |
82
+ | `delete` | ⚠️ 退出码 3(404)= 已删除,非错误 |
83
+
84
+ ## 操作约束
85
+
86
+ ### 必须遵守
87
+ 1. **先 list 再操作** — 不要猜测或编造 UUID,必须从 `list` 结果中获取
88
+ 2. **修改前确认** — `write_internal` 操作必须经用户确认
89
+ 3. **检查返回值** — 退出码非 0 时读 stderr 的 JSON,按退出码语义处理
90
+ 4. **不展示原始 JSON** — 提取关键字段(title/id/priority/state)格式化呈现
91
+
92
+ ### 常见错误
93
+ - ❌ 用 `--priority p0` → 合法值只有 `low medium high urgent`
94
+ - ❌ 同时传 `--mine` 与 `--assignee` → 互斥,二选一
95
+ - ❌ 不检查 auth status 直接 create → 先 `morula auth status`
96
+ - ❌ 对 401 反复重试同一条命令 → 应 `morula auth login` 重新认证
97
+ - ❌ 传无效枚举值 → 先查 [commands.md](references/commands.md) 确认合法值
98
+ - ❌ 在 create 时传 `--sort-order` → 仅 update 支持
99
+
100
+ ## 结果呈现
101
+
102
+ ### 列表结果 → 表格摘要
103
+ 提取 `id`、`title`、`priority`、状态名(嵌套 `state.name`)、负责人名(嵌套 `assignee.displayName`)以表格展示。有分页时提示"第 X 页,共 Y 条"。列表响应中没有顶层 `stateName`/`assigneeName` 字段。
104
+
105
+ ### 单条详情 → 字段列表
106
+ 提取关键字段以 key: value 对展示。不要展示完整 JSON。
107
+
108
+ ### 错误 → 翻译退出码
109
+
110
+ Agent 看到非零退出码时,应从 stderr 提取 JSON 中的 `code` 和 `message` 字段,按以下规则处理:
111
+
112
+ - 退出码 2(`USAGE` / `BAD_REQUEST`)→ 参数格式或值不正确。检查命令语法,对照 [commands.md](references/commands.md) 修正参数后重试。常见原因:传了不支持的枚举值(如 `--priority p0`)、日期格式错误(应 ISO 8601)。
113
+ - 退出码 3(`NOT_FOUND`)→ 请求的资源(空间/任务/成员/评论)不存在。用对应的 `list` 命令重新查询可用 ID,确认 ID 未被删除或拼写错误。
114
+ - 退出码 4(`UNAUTHENTICATED`)→ Token 过期或未登录。执行 `morula auth login --env prod` 重新认证。不要在未认证状态下反复重试业务命令。
115
+ - 退出码 5(`FORBIDDEN`)→ 当前用户对该空间/资源无操作权限。检查用户是否为空间成员、角色权限是否足够(如需要 admin 才能移除成员)。
116
+ - 退出码 6(`CONFLICT`)→ 资源状态冲突(如并发修改、重复创建)。用 `get` 重新查询最新数据,确认当前状态后再决定是否重试。避免盲目重写。
117
+ - 退出码 7(`UPSTREAM` / `NETWORK` / `TIMEOUT` / `RATE_LIMITED`)→ 网络超时、服务端 5xx 错误或频率限制。指数退避重试(1s → 2s → 4s),最多 3 次。如持续失败,告知用户稍后再试。
118
+ - 退出码 137(`CRASH`)→ CLI 进程被操作系统 SIGKILL 强制终止,无 stdout/stderr 输出(包装脚本会尝试注入诊断信息)。详见下方「退出码 137 诊断」章节。
119
+
120
+ ## 退出码 137 诊断
121
+
122
+ 当 morula CLI 返回退出码 137(SIGKILL)时,表明进程被操作系统强制终止,无 stderr 输出。常见于 macOS。
123
+
124
+ **原因**:macOS arm64 对可执行文件有严格的代码签名验证。如果 CLI 二进制(Bun 单文件产物或旧 SEA)签名无效或被破坏(`EXC_CRASH (Code Signature Invalid)`),内核会在启动时直接 SIGKILL。
125
+
126
+ **诊断步骤**:
127
+ 1. 检查二进制签名状态:
128
+ ```bash
129
+ codesign -dvvv "$(dirname $(which morula))/../skills/morula-cli/scripts/morula" 2>&1
130
+ ```
131
+ 2. 检查系统崩溃日志:打开 Console.app → Crash Reports,搜索 `morula`
132
+ 3. 确认 macOS 版本:`sw_vers`
133
+
134
+ **修复方式**(用户侧):
135
+ ```bash
136
+ BIN="$(dirname $(which morula))/../skills/morula-cli/scripts/morula"
137
+ xattr -cr "$BIN"
138
+ codesign --force --deep --sign - "$BIN"
139
+ ```
140
+
141
+ **Agent 回退策略**:如果 CLI 持续返回 137 且无法修复,Agent 应回退到直接调用 Morula REST API(`POST /objects`、`GET /spaces` 等),通过 HTTP 完成操作。注意:API 直调时需显式传递 `descriptionFormat` 字段(通过内容自动检测设置)。
142
+
143
+ ## Step 0: 使用插件命令
144
+
145
+ 插件安装后,宿主会将 `bin/` 加入 `PATH`。始终直接使用:
146
+
147
+ ```bash
148
+ morula --help # 打印所有命令与参数(JSON)
149
+ morula --version # 输出版本号 JSON
150
+ ```
151
+
152
+ 所有成功结果默认以 JSON 输出到 stdout,错误以 JSON 输出到 stderr。不要添加 `--json`。
153
+
154
+ ## Step 1: 检查认证
155
+
156
+ ```bash
157
+ morula auth status
158
+ ```
159
+
160
+ 如未登录或任何命令以退出码 `4` 返回,进入 Step 2。不要要求用户提供、复制或粘贴 Token。
161
+
162
+ ## Step 2: SkyDoor SSO 登录
163
+
164
+ ```bash
165
+ morula auth login --env prod
166
+ ```
167
+
168
+ 该命令会打开浏览器,通过 PKCE + loopback 完成登录。浏览器步骤需要用户操作;等待用户完成后再继续。登录凭据存于 `~/.morula-cli/config.yaml`(0600)。
169
+
170
+ ## Step 3: 执行业务命令
171
+
172
+ 先用列表命令发现稳定 ID,再读取或修改资源。修改前确认用户意图,不要猜测空间、任务、状态或负责人 ID。
173
+
174
+ 常用命令:
175
+
176
+ ```bash
177
+ morula space list
178
+ morula space get <space-id>
179
+ morula task list --space <space-id> --page 1 --page-size 20
180
+ morula task get <task-id>
181
+ morula task create --space <space-id> --title "标题" --priority medium
182
+ morula task update <task-id> --state <state-id> --assignee <principal-id>
183
+ ```
184
+
185
+ 字段读写(自定义字段):
186
+
187
+ ```bash
188
+ # 自定义字段(字段模板里的 select 等字段)
189
+ morula task list --space <space-id> --field plane_module=定制服务 # 按自定义字段值筛选(等值)
190
+ morula task get <task-id> # 详情附带 fieldValues
191
+ morula task create --space <space-id> --title "标题" --field plane_module=定制服务 # 创建后写入自定义字段值
192
+ ```
193
+
194
+ - `--field` 格式为 `key=value`:key 为字段模板里的 fieldKey(也接受字段名),list 筛选需配合 `--space` 解析字段模板。
195
+ - `list` 默认返回字段值(includeFieldValues)。
196
+
197
+ 我的任务(用户问"我有哪些任务"时使用):
198
+
199
+ ```bash
200
+ morula task list --mine # 仅当前用户负责的任务(自动解析,无需传 --assignee)
201
+ ```
202
+
203
+ 完整参数见 [commands.md](references/commands.md),认证和错误处理见 [authentication.md](references/authentication.md)。
204
+
205
+ ## 退出码
206
+
207
+ | 退出码 | stderr `code` | 含义 | Agent 处理 |
208
+ |--------|--------------|------|-----------|
209
+ | `0` | — | 成功,stdout 为 JSON 结果 | 提取字段格式化展示 |
210
+ | `1` | `ERROR` | 未分类的内部错误 | 读取 `message` 告知用户,记录上下文后重新评估 |
211
+ | `2` | `USAGE` / `BAD_REQUEST` | 参数格式或值不正确 | 检查命令语法和参数值,对照 [commands.md](references/commands.md) 修正后重试 |
212
+ | `3` | `NOT_FOUND` | 资源(空间/任务/成员/评论)不存在 | 用 `list` 重新查询可用 ID,确认 ID 未被删除或输入错误 |
213
+ | `4` | `UNAUTHENTICATED` | Token 过期或未登录 | 执行 `morula auth login --env prod` 重新认证 |
214
+ | `5` | `FORBIDDEN` | 无操作权限 | 检查用户角色和空间权限;如需提权,告知用户联系管理员 |
215
+ | `6` | `CONFLICT` | 资源状态冲突(并发修改/重复创建) | 用 `get` 重新查询最新状态后谨慎重试,避免盲目覆盖 |
216
+ | `7` | `UPSTREAM` / `NETWORK` / `TIMEOUT` / `RATE_LIMITED` | 网络超时、服务端 5xx 或限频 | 指数退避重试(1s→2s→4s),最多 3 次;持续失败则告知用户稍后再试 |
217
+ | `137` | `CRASH` | 进程被 SIGKILL 强制终止(macOS 代码签名验证失败) | 见下方「退出码 137 诊断」章节;无法修复时回退到直接调用 REST API |
@@ -0,0 +1,21 @@
1
+ # 认证与配置
2
+
3
+ > CLI-SPLIT-001:业务 CLI(`morula`)与全局运行时 CLI(`morula-runtime`,`@arcships/morula-runtime`)**共享同一认证配置**(`~/.morula-cli/config.yaml`)。设备首次登录推荐用 `morula-runtime auth login`(引导命令以 morula-runtime 开头);业务命令登录也可直接用 `morula auth login`。两者任一登录成功后,两个 CLI 均可使用。
4
+
5
+ `morula auth login` 使用 OAuth2 PKCE S256:CLI 在 `127.0.0.1` 随机端口监听一次性回调,生成 verifier/challenge/state,通过 morula-server 代理 SkyDoor SSO,最后交换 180 天有效的 Morula JWT。
6
+
7
+ 配置路径默认是 `~/.morula-cli/config.yaml`,目录权限 0700、文件权限 0600。支持多个 context:
8
+
9
+ ```yaml
10
+ currentContext: test
11
+ contexts:
12
+ test:
13
+ url: https://morula.basecastle.com/api
14
+ token: <redacted>
15
+ ```
16
+
17
+ 地址优先级:`--url` > `MORULA_API_URL` > 保存 context > 内建环境。Token 优先级:`--token` > `MORULA_TOKEN` > 与目标地址绑定的保存 context。
18
+
19
+ 当前构建 target 为 `production`,默认 context 为 `prod`(https://morula.fazhiplus.com/api)。 若覆盖目标地址,保存的 Token 不会自动发送,必须显式传入 Token。
20
+
21
+ 安全规则:不得显示、记录或提交配置中的 token;不得要求用户在聊天中粘贴 token。401 对应退出码 4,应重新运行浏览器登录。