@arcships/morula-runtime 0.1.0-alpha.10 → 0.1.0-alpha.12
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/dist/index.js +571 -269
- package/dist/morula.js +9 -83
- package/dist/plugin/plugin.json +1 -1
- package/dist/plugin/skills/morula-cli/references/commands.md +4 -26
- package/dist/plugin/skills/morula-working-on-issues/SKILL.md +15 -12
- package/dist/plugin/skills/morula-working-on-issues/references/working-on-issues-source-map.md +2 -2
- package/package.json +1 -1
package/dist/morula.js
CHANGED
|
@@ -704,8 +704,8 @@ function page(ok, message) {
|
|
|
704
704
|
}
|
|
705
705
|
|
|
706
706
|
// ../morula-cli-core/dist/build-env.js
|
|
707
|
-
var BUILD_VERSION = "0.1.0-alpha.
|
|
708
|
-
var BUILD_ID = "
|
|
707
|
+
var BUILD_VERSION = "0.1.0-alpha.12";
|
|
708
|
+
var BUILD_ID = "20260922142838.0c791f70";
|
|
709
709
|
var BUILD_CONTEXTS = {
|
|
710
710
|
"local": "http://localhost:8080/api",
|
|
711
711
|
"test": "https://morula.basecastle.com/api",
|
|
@@ -880,24 +880,6 @@ var CiApi = class {
|
|
|
880
880
|
testReport(runId) {
|
|
881
881
|
return this.client.get(`/vcs/runs/${encodeURIComponent(requiredId2(runId, "run id"))}/test-report`);
|
|
882
882
|
}
|
|
883
|
-
/**
|
|
884
|
-
* 重跑整条流水线的失败 job(Phase 3;开放面 = 人 + 管家)。
|
|
885
|
-
*
|
|
886
|
-
* 只允许 failure / cancelled 的运行,其余状态服务端回 `CI_RETRY_NOT_ALLOWED`(不是 4xx)。
|
|
887
|
-
* **非幂等**:每次调用都会在平台上产生一次新的重跑,重复调用不会去重。
|
|
888
|
-
*/
|
|
889
|
-
retryRun(runId) {
|
|
890
|
-
return this.client.post(`/vcs/runs/${encodeURIComponent(requiredId2(runId, "run id"))}/retry`);
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
* 重跑单个 job(Phase 3;开放面 = 人 + 管家)。
|
|
894
|
-
*
|
|
895
|
-
* 服务端按 jobId 反查所属运行(`CI_JOB_NOT_FOUND` 覆盖「job 不存在」与「反查不到运行」两种情况);
|
|
896
|
-
* 状态门禁与 `retryRun` 相同。非幂等。
|
|
897
|
-
*/
|
|
898
|
-
retryJob(jobId) {
|
|
899
|
-
return this.client.post(`/vcs/jobs/${encodeURIComponent(requiredId2(jobId, "job id"))}/retry`);
|
|
900
|
-
}
|
|
901
883
|
};
|
|
902
884
|
function requiredId2(id, label) {
|
|
903
885
|
const normalized = id.trim();
|
|
@@ -2227,9 +2209,7 @@ async function ciCommand(context) {
|
|
|
2227
2209
|
return ciDeployments(context);
|
|
2228
2210
|
if (action === "test-report")
|
|
2229
2211
|
return ciTestReport(context);
|
|
2230
|
-
|
|
2231
|
-
return ciRetry(context);
|
|
2232
|
-
throw usage("usage: morula ci <status|log|deployments|test-report|retry>");
|
|
2212
|
+
throw usage("usage: morula ci <status|log|deployments|test-report>");
|
|
2233
2213
|
}
|
|
2234
2214
|
async function ciStatus(context) {
|
|
2235
2215
|
const { positionals, flags } = context.parsed;
|
|
@@ -2309,44 +2289,6 @@ async function ciTestReport(context) {
|
|
|
2309
2289
|
throw ciFailure(result);
|
|
2310
2290
|
return result;
|
|
2311
2291
|
}
|
|
2312
|
-
async function ciRetry(context) {
|
|
2313
|
-
const { positionals, flags } = context.parsed;
|
|
2314
|
-
rejectUnknownFlags(flags, ["space", "run", "job"]);
|
|
2315
|
-
const usageHint = "usage: morula ci retry --space <spaceId> [--run <runId>] [--job <jobId>]";
|
|
2316
|
-
if (positionals.length)
|
|
2317
|
-
throw usage(`\u91CD\u8DD1\u53EA\u5728\u7A7A\u95F4\u9762\u5F00\u653E\uFF1A\u8BF7\u7528 --space <spaceId>\uFF08\u4EFB\u52A1\u9762\u4E0D\u63D0\u4F9B retry\uFF09\u3002${usageHint}`);
|
|
2318
|
-
const runId = flagString(flags, "run");
|
|
2319
|
-
const jobId = flagString(flags, "job");
|
|
2320
|
-
if (runId && jobId)
|
|
2321
|
-
throw usage(`--run \u4E0E --job \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A\uFF08${usageHint}\uFF09`);
|
|
2322
|
-
const spaceId = flagString(flags, "space");
|
|
2323
|
-
if (!spaceId)
|
|
2324
|
-
throw usage(usageHint);
|
|
2325
|
-
if (jobId) {
|
|
2326
|
-
const result2 = await context.client.ci.retryJob(jobId);
|
|
2327
|
-
if (result2.ok === false)
|
|
2328
|
-
throw ciFailure(result2, "\u64CD\u4F5C");
|
|
2329
|
-
return result2;
|
|
2330
|
-
}
|
|
2331
|
-
let targetRunId = runId;
|
|
2332
|
-
if (!targetRunId) {
|
|
2333
|
-
const view = await context.client.ci.spaceView(spaceId, { failed: true });
|
|
2334
|
-
if (view.ok === false)
|
|
2335
|
-
throw ciFailure(view);
|
|
2336
|
-
targetRunId = view.runs[0]?.id;
|
|
2337
|
-
if (!targetRunId) {
|
|
2338
|
-
throw new CliError(
|
|
2339
|
-
"CI_RUN_NOT_FOUND",
|
|
2340
|
-
EXIT.NOT_FOUND,
|
|
2341
|
-
`\u7A7A\u95F4 ${spaceId} \u6CA1\u6709\u5931\u8D25\u7684\u6D41\u6C34\u7EBF\u8FD0\u884C\u53EF\u91CD\u8DD1\uFF08\u53EF\u5148\u7528 morula ci status --space ${spaceId} --failed \u786E\u8BA4\uFF09`
|
|
2342
|
-
);
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
const result = await context.client.ci.retryRun(targetRunId);
|
|
2346
|
-
if (result.ok === false)
|
|
2347
|
-
throw ciFailure(result, "\u64CD\u4F5C");
|
|
2348
|
-
return result;
|
|
2349
|
-
}
|
|
2350
2292
|
function resolveFace(context, usageHint) {
|
|
2351
2293
|
const taskId = context.parsed.positionals[0]?.trim();
|
|
2352
2294
|
const spaceId = flagString(context.parsed.flags, "space");
|
|
@@ -2356,16 +2298,14 @@ function resolveFace(context, usageHint) {
|
|
|
2356
2298
|
throw usage(usageHint);
|
|
2357
2299
|
return taskId ? { kind: "task", taskId } : { kind: "space", spaceId };
|
|
2358
2300
|
}
|
|
2359
|
-
function ciFailure(failure
|
|
2301
|
+
function ciFailure(failure) {
|
|
2360
2302
|
return new CliError(
|
|
2361
2303
|
failure.code,
|
|
2362
2304
|
exitForCiCode(failure.code),
|
|
2363
|
-
`CI
|
|
2305
|
+
`CI \u67E5\u8BE2\u5931\u8D25: ${failure.message || "\u672A\u77E5\u539F\u56E0"}\uFF08${failure.code}\uFF09`
|
|
2364
2306
|
);
|
|
2365
2307
|
}
|
|
2366
2308
|
function exitForCiCode(code) {
|
|
2367
|
-
if (code === "CI_RETRY_NOT_ALLOWED" || code === "CI_JOB_NOT_MANUAL")
|
|
2368
|
-
return EXIT.CONFLICT;
|
|
2369
2309
|
if (code === "CI_JOB_NOT_FOUND" || code === "CI_RUN_NOT_FOUND" || code === "TASK_NOT_FOUND" || code === "OBJECT_NOT_FOUND")
|
|
2370
2310
|
return EXIT.NOT_FOUND;
|
|
2371
2311
|
return EXIT.OTHER;
|
|
@@ -3285,7 +3225,7 @@ var SPEC = {
|
|
|
3285
3225
|
{ name: "name", type: "string", valueHint: "<branch>", description: "\u5206\u652F\u540D\uFF08\u5FC5\u586B\uFF09", required: true },
|
|
3286
3226
|
{ name: "repo", type: "string", valueHint: "<owner/name>", description: "\u6B21\u4ED3\u5E93\uFF08\u591A\u4ED3\u5E93\u4EFB\u52A1\u7684\u5206\u652F\u9010\u4ED3\u4E0A\u62A5\uFF09" }
|
|
3287
3227
|
],
|
|
3288
|
-
examples: ["morula task branch <taskId> --name <type>/<
|
|
3228
|
+
examples: ["morula task branch <taskId> --name <type>/<slug>"],
|
|
3289
3229
|
writes: "remote"
|
|
3290
3230
|
},
|
|
3291
3231
|
{
|
|
@@ -3847,7 +3787,7 @@ var SPEC = {
|
|
|
3847
3787
|
},
|
|
3848
3788
|
{
|
|
3849
3789
|
resource: "ci",
|
|
3850
|
-
summary: "CI/CD pipeline facts
|
|
3790
|
+
summary: "CI/CD pipeline facts (read-only): pipeline runs / job logs / deployments / failed test cases. Read faces share one command surface \u2014 task face `<taskId>` (AgentTask credential, self-check your MR pipeline) vs space face `--space <spaceId>` (steward/session credential, space-wide inspection); the two are mutually exclusive. Write operations (retry / play / trigger) were removed on 2026-09-22 (CI panel is read-only): operate pipelines directly in the VCS platform instead",
|
|
3851
3791
|
actions: [
|
|
3852
3792
|
{
|
|
3853
3793
|
action: "status",
|
|
@@ -3903,26 +3843,12 @@ var SPEC = {
|
|
|
3903
3843
|
writes: "none",
|
|
3904
3844
|
idempotent: true,
|
|
3905
3845
|
emits: ["ok", "runId", "report"]
|
|
3906
|
-
},
|
|
3907
|
-
{
|
|
3908
|
-
action: "retry",
|
|
3909
|
-
summary: "re-run a failed pipeline (Phase 3; space face ONLY \u2014 a positional <taskId> is a usage error, retry is not open to the task face; person + steward, and a steward must go through an elicitation confirm card). Omit both --run and --job to retry the newest FAILED run of the space (no failed run at all \u2192 CI_RUN_NOT_FOUND exit 3). Only failure/cancelled runs or jobs can be retried (CI_RETRY_NOT_ALLOWED exit 6). NOT idempotent: every call starts another platform re-run",
|
|
3910
|
-
flags: [
|
|
3911
|
-
{ name: "space", type: "string", valueHint: "<id>", description: "\u7A7A\u95F4 ID\uFF08\u5FC5\u586B\uFF1Bretry \u53EA\u6709\u7A7A\u95F4\u9762\uFF0C\u4EFB\u52A1\u9762\u4E0D\u5F00\u653E\uFF09", required: true },
|
|
3912
|
-
{ name: "run", type: "string", valueHint: "<runId>", description: "\u8981\u91CD\u8DD1\u7684\u8FD0\u884C ID\uFF08\u4E0E --job \u4E92\u65A5\uFF1B\u7F3A\u7701 = \u8BE5\u7A7A\u95F4\u6700\u65B0\u4E00\u6761\u5931\u8D25\u8FD0\u884C\uFF09" },
|
|
3913
|
-
{ name: "job", type: "string", valueHint: "<jobId>", description: "\u8981\u91CD\u8DD1\u7684\u5355\u4E2A job ID\uFF08\u4E0E --run \u4E92\u65A5\uFF1B\u6765\u81EA ci status \u7684 jobs[].id\uFF09" }
|
|
3914
|
-
],
|
|
3915
|
-
examples: ["morula ci retry --space <id>", "morula ci retry --space <id> --job <jobId>"],
|
|
3916
|
-
writes: "remote",
|
|
3917
|
-
idempotent: false,
|
|
3918
|
-
emits: ["ok", "action", "runId", "jobId", "externalId", "ref", "acceptedAt"]
|
|
3919
3846
|
}
|
|
3920
3847
|
],
|
|
3921
3848
|
notes: [
|
|
3922
3849
|
"\u4E24\u4E2A\u9762\uFF08\u4EFB\u52A1\u9762 <taskId> / \u7A7A\u95F4\u9762 --space <spaceId>\uFF09\u4E92\u65A5\uFF1A\u540C\u65F6\u7ED9 \u2192 usage error(2)\uFF0C\u90FD\u4E0D\u7ED9\u540C\u6837 usage error\u3002\u51ED\u8BC1\u4E0E\u4F5C\u7528\u57DF\u4E0D\u540C\uFF0C\u731C\u9519\u4F1A\u53D8\u6210\u9759\u9ED8\u8D8A\u6743\u6216\u9759\u9ED8\u5931\u8D25",
|
|
3923
|
-
"\u53EA\u8BFB\
|
|
3924
|
-
"\
|
|
3925
|
-
"\u670D\u52A1\u7AEF\u4E1A\u52A1\u5931\u8D25\u662F HTTP 200 + `{ ok:false, code, message }`\uFF1ACI_JOB_NOT_FOUND / CI_RUN_NOT_FOUND / TASK_NOT_FOUND / OBJECT_NOT_FOUND \u2192 exit 3\uFF1BCI_RETRY_NOT_ALLOWED / CI_JOB_NOT_MANUAL \u2192 exit 6\uFF1BCAPABILITY_UNSUPPORTED / NO_CONNECTION / \u5176\u4F59 \u2192 exit 1"
|
|
3850
|
+
"CI \u547D\u4EE4\u9762\u7EAF\u53EA\u8BFB\uFF08\u5199\u64CD\u4F5C\u5DF2\u79FB\u9664\uFF0C2026-09-22 \u5B9A\u6848\uFF09\uFF1Astatus / log / deployments / test-report \u5168\u90E8 writes: none\uFF1B\u91CD\u8DD1 / \u89E6\u53D1\u6D41\u6C34\u7EBF\u8BF7\u5728 VCS \u5E73\u53F0\uFF08GitLab/GitHub\uFF09\u4E0A\u76F4\u63A5\u64CD\u4F5C",
|
|
3851
|
+
"\u670D\u52A1\u7AEF\u4E1A\u52A1\u5931\u8D25\u662F HTTP 200 + `{ ok:false, code, message }`\uFF1ACI_JOB_NOT_FOUND / CI_RUN_NOT_FOUND / TASK_NOT_FOUND / OBJECT_NOT_FOUND \u2192 exit 3\uFF1BCAPABILITY_UNSUPPORTED / NO_CONNECTION / \u5176\u4F59 \u2192 exit 1"
|
|
3926
3852
|
]
|
|
3927
3853
|
},
|
|
3928
3854
|
{
|
package/dist/plugin/plugin.json
CHANGED
|
@@ -262,7 +262,7 @@ report the final branch name for an agent task (machine protocol; agent naming,
|
|
|
262
262
|
**示例**
|
|
263
263
|
|
|
264
264
|
```bash
|
|
265
|
-
morula task branch <taskId> --name <type>/<
|
|
265
|
+
morula task branch <taskId> --name <type>/<slug>
|
|
266
266
|
```
|
|
267
267
|
|
|
268
268
|
> `writes: remote` · `interactive: no` · `idempotent: no`
|
|
@@ -1401,12 +1401,11 @@ morula repo mr diff <taskId> --mr <iid>
|
|
|
1401
1401
|
|
|
1402
1402
|
## `morula ci`
|
|
1403
1403
|
|
|
1404
|
-
CI/CD pipeline facts
|
|
1404
|
+
CI/CD pipeline facts (read-only): pipeline runs / job logs / deployments / failed test cases. Read faces share one command surface — task face `<taskId>` (AgentTask credential, self-check your MR pipeline) vs space face `--space <spaceId>` (steward/session credential, space-wide inspection); the two are mutually exclusive. Write operations (retry / play / trigger) were removed on 2026-09-22 (CI panel is read-only): operate pipelines directly in the VCS platform instead
|
|
1405
1405
|
|
|
1406
1406
|
> 两个面(任务面 <taskId> / 空间面 --space <spaceId>)互斥:同时给 → usage error(2),都不给同样 usage error。凭证与作用域不同,猜错会变成静默越权或静默失败
|
|
1407
|
-
>
|
|
1408
|
-
>
|
|
1409
|
-
> 服务端业务失败是 HTTP 200 + `{ ok:false, code, message }`:CI_JOB_NOT_FOUND / CI_RUN_NOT_FOUND / TASK_NOT_FOUND / OBJECT_NOT_FOUND → exit 3;CI_RETRY_NOT_ALLOWED / CI_JOB_NOT_MANUAL → exit 6;CAPABILITY_UNSUPPORTED / NO_CONNECTION / 其余 → exit 1
|
|
1407
|
+
> CI 命令面纯只读(写操作已移除,2026-09-22 定案):status / log / deployments / test-report 全部 writes: none;重跑 / 触发流水线请在 VCS 平台(GitLab/GitHub)上直接操作
|
|
1408
|
+
> 服务端业务失败是 HTTP 200 + `{ ok:false, code, message }`:CI_JOB_NOT_FOUND / CI_RUN_NOT_FOUND / TASK_NOT_FOUND / OBJECT_NOT_FOUND → exit 3;CAPABILITY_UNSUPPORTED / NO_CONNECTION / 其余 → exit 1
|
|
1410
1409
|
|
|
1411
1410
|
### `morula ci status`
|
|
1412
1411
|
|
|
@@ -1504,27 +1503,6 @@ morula ci test-report <taskId>
|
|
|
1504
1503
|
|
|
1505
1504
|
> `writes: none` · `interactive: no` · `idempotent: yes` · `emits: ok, runId, report`
|
|
1506
1505
|
|
|
1507
|
-
### `morula ci retry`
|
|
1508
|
-
|
|
1509
|
-
**用法**:`morula ci retry [--space <id>] [--run <runId>] [--job <jobId>]`
|
|
1510
|
-
|
|
1511
|
-
re-run a failed pipeline (Phase 3; space face ONLY — a positional <taskId> is a usage error, retry is not open to the task face; person + steward, and a steward must go through an elicitation confirm card). Omit both --run and --job to retry the newest FAILED run of the space (no failed run at all → CI_RUN_NOT_FOUND exit 3). Only failure/cancelled runs or jobs can be retried (CI_RETRY_NOT_ALLOWED exit 6). NOT idempotent: every call starts another platform re-run
|
|
1512
|
-
|
|
1513
|
-
| Flag | 类型 | 必填 | 取值 | 默认 | 说明 |
|
|
1514
|
-
|---|---|---|---|---|---|
|
|
1515
|
-
| `--space <id>` | string | 是 | - | - | 空间 ID(必填;retry 只有空间面,任务面不开放) |
|
|
1516
|
-
| `--run <runId>` | string | - | - | - | 要重跑的运行 ID(与 --job 互斥;缺省 = 该空间最新一条失败运行) |
|
|
1517
|
-
| `--job <jobId>` | string | - | - | - | 要重跑的单个 job ID(与 --run 互斥;来自 ci status 的 jobs[].id) |
|
|
1518
|
-
|
|
1519
|
-
**示例**
|
|
1520
|
-
|
|
1521
|
-
```bash
|
|
1522
|
-
morula ci retry --space <id>
|
|
1523
|
-
morula ci retry --space <id> --job <jobId>
|
|
1524
|
-
```
|
|
1525
|
-
|
|
1526
|
-
> `writes: remote` · `interactive: no` · `idempotent: no` · `emits: ok, action, runId, jobId, externalId, ref, acceptedAt`
|
|
1527
|
-
|
|
1528
1506
|
<!-- hand:start ci -->
|
|
1529
1507
|
<!-- hand:end ci -->
|
|
1530
1508
|
|
|
@@ -68,33 +68,32 @@ allowed-tools: Bash(morula *), Bash(git *), Bash(gh *)
|
|
|
68
68
|
## 0.3 分支命名:由你(Agent)取名并上报
|
|
69
69
|
|
|
70
70
|
- **任务 ID 获取**:本任务的 AgentTask ID(UUID)在系统提示「基本信息」段(也是 `morula task get`(无参)返回的 `id`,`.agent_context/task-context.md` 开头亦有)。需要调用 `morula task branch` 时用它作为 taskId。
|
|
71
|
-
- **重要区分**:`morula task branch <taskId>` 的 taskId 用**本任务 UUID**(机器协议);但 **MR /
|
|
71
|
+
- **重要区分**:`morula task branch <taskId>` 的 taskId 用**本任务 UUID**(机器协议);但 **MR / PR 里的任务编号用对外编号 code**(如 `AGENT-958201`,用于服务端关联/关单)——**不要用 UUID 标记 MR**(UUID 关单只认业务对象,AgentTask 不会被识别,会导致 MR 关联失败)。
|
|
72
72
|
- **只有需要改代码并推分支的任务才取名**;纯问答/只读调研/本地起服务不建分支(见第 3 条决策树)。
|
|
73
73
|
- **先检查当前分支**:若仓库已有 feature 分支(同任务/同一改动闭环的后续轮次复用),**直接继续用当前分支,不要新建**(在仓库目录内执行):
|
|
74
74
|
```bash
|
|
75
75
|
cd <工作区根>/<仓库目录> && git branch --show-current # 若非空且非 main/master → 用这个分支继续改
|
|
76
76
|
```
|
|
77
77
|
- 若当前为 detached HEAD(首次执行),且任务确实要改代码:
|
|
78
|
-
1. 创建分支。分支名**严格由以下部分依次拼成,不多不少**:`<type>` + `/` +
|
|
78
|
+
1. 创建分支。分支名**严格由以下部分依次拼成,不多不少**:`<type>` + `/` + `<slug>`
|
|
79
79
|
- `<type>`:取下方「命名规范」清单里的一个(按任务性质选,如文档改动用 docs);
|
|
80
|
-
- `<本任务对外编号>`:见 0.2,**原样照抄**该编号到分支名里(大小写与内容都不改动,也不省略);
|
|
81
80
|
- `<slug>`:具体工作事情,小写、用 `-` 连接。
|
|
82
81
|
```bash
|
|
83
|
-
git switch -c <type
|
|
82
|
+
git switch -c <type>/<slug>
|
|
84
83
|
```
|
|
85
|
-
|
|
86
|
-
分支名**到 `<slug>` 为止就结束** ——
|
|
84
|
+
例:做 mention 相关的测试补全 → 分支名 `test/mention-tests`;修复登录 401 → `fix/login-401`
|
|
85
|
+
分支名**到 `<slug>` 为止就结束** —— slug 之后不再接任何内容。
|
|
87
86
|
2. **通过 CLI 把分支名上报服务端**(必须,服务端据此做 PR 关联/清理):
|
|
88
87
|
```bash
|
|
89
|
-
morula task branch <taskId> --name <type
|
|
88
|
+
morula task branch <taskId> --name <type>/<slug>
|
|
90
89
|
```
|
|
91
90
|
- **`morula task branch` 需要 `MORULA_RUNTIME_ID`**(daemon 注入的 env,用于校验你的归属)。若你的 exec 环境没有这个 env,**从主仓库目录内的 `.morula-worktree.json` 读取 `runtimeId` 字段**(完整路径 `<工作区根>/<仓库目录>/.morula-worktree.json`;工作区根下没有这个文件),用 `env MORULA_RUNTIME_ID=<该值> morula task branch ...` 或导出后再调用(不要从别处猜)。
|
|
92
91
|
- **命名规范**(分支名会出现在 PR、CI、历史里,必须规范):
|
|
93
92
|
- 前缀 type 选一:`feature`(新功能)、`fix`(缺陷修复)、`hotfix`(紧急/线上)、`docs`(文档)、`refactor`(重构)、`chore`(杂务)、`test`(测试)、`perf`(性能)、`style`(样式)、`build`(构建/依赖)、`ci`(CI)、`revert`(回滚);
|
|
94
|
-
- 任务编号 = 本任务的**对外编号**(见 0.2,如 `SPW299-30`),**原样大写**:服务端按 title/branch/body 扫描任务编号关联 MR,**匹配大小写敏感**(`[A-Z][A-Z0-9]{1,9}-数字`),写成小写会关联不到;
|
|
95
93
|
- slug = 具体工作事情,小写、用 `-` 连接(可用英文;**不要用中文**,中文分支名不被多数 CI/工具链支持);
|
|
96
|
-
-
|
|
97
|
-
- **分支名到 slug
|
|
94
|
+
- **只按本节规则拼,不要参考/模仿仓库里已有分支的命名**:历史分支是过往产物(可能含日期后缀、任务编号等旧形态),照着它们取名会沿用旧习惯;分支名完全由上面两段决定,与仓库现有分支无关;
|
|
95
|
+
- **分支名到 slug 就结束**:slug 之后**不再追加任何内容**——日期、时间戳、轮次号、随机串都不要;日期不表达语义,且会让「同一件事的后续轮次复用同分支」看起来像要新建分支;
|
|
96
|
+
- **分支名是全仓库共享的命名空间,撞名会被拒绝**:若 `morula task branch` / `morula repo mr create` 返回 `BRANCH_OWNED_BY_OTHER_TASK`(分支名已被其他任务占用),换一个更具体的 slug 重新取名、上报后再继续;
|
|
98
97
|
- **禁止**用 `main`/`master`,禁止以 `-` 开头/结尾,长度 ≤ 255。
|
|
99
98
|
- 如果你不改代码,**不要**创建分支,也不要调用 `morula task branch`。
|
|
100
99
|
|
|
@@ -109,6 +108,10 @@ allowed-tools: Bash(morula *), Bash(git *), Bash(gh *)
|
|
|
109
108
|
```
|
|
110
109
|
- 若 `git status` 显示工作目录有**不属于本任务**的改动(如误入其他任务 worktree),**立即停止并报告**,不要继续编辑。
|
|
111
110
|
- **不要在工作区根直接跑 git/gh**:工作区根不是 git 仓库(除仓库子目录外还有 `AGENTS.md`/`.agents/`/`.agent_context/`/`.morula/`),在根目录跑 git 只会报 `not a git repository`。`morula` CLI 反之可从工作区根**或其任意子目录**执行(它从 cwd 向上查找 `.morula/checkout.json` 凭据)。
|
|
111
|
+
- **工作区准备(全新检出,先补环境前置再跑构建/验收命令)**:
|
|
112
|
+
- 本工作区是全新检出,`node_modules` 不存在:先按仓库声明的包管理器安装依赖——有 `pnpm-lock.yaml` 用 `pnpm install`、`package-lock.json` 用 `npm ci`、`yarn.lock` 用 `yarn`;
|
|
113
|
+
- 仓库使用 Prisma 时(存在 `prisma/schema.prisma`)先 `npx prisma generate`,否则 `tsc` 会报大量与本次改动无关的错误;
|
|
114
|
+
- 验收/构建命令失败时,先区分「环境前置(依赖、生成物缺失)」与「自身改动」:环境前置先补齐再复跑,不要把环境报错当成本次改动的问题去修。
|
|
112
115
|
|
|
113
116
|
## 0.5 仓库与工作目录
|
|
114
117
|
|
|
@@ -249,8 +252,8 @@ morula task inbox --peek # 只看不取(确认有没有新意见,不标
|
|
|
249
252
|
|
|
250
253
|
## 2. PR 链接与关单意图是两套不同的契约
|
|
251
254
|
|
|
252
|
-
- **链接通道**:PR 的 title /
|
|
253
|
-
推荐写法:title 以「STR-101: 描述」开头,或
|
|
255
|
+
- **链接通道**:PR 的 title / body 中出现任务编号 → 服务端自动关联 PR 到任务。
|
|
256
|
+
推荐写法:title 以「STR-101: 描述」开头,或 body 写「Closes STR-101」(分支名不含任务编号,见 0.3;平台通道建的 MR 会自动把编号写进 title/body)。
|
|
254
257
|
- **关单通道**:只有 `Closes` / `Fixes` / `Resolves` 后**紧邻**任务编号(如「Closes STR-101」)→ 该 PR
|
|
255
258
|
merge 时服务端自动把任务流转到完成状态。title 前缀或 branch 引用只会关联 PR,不会在 merge 时关单。
|
|
256
259
|
- body 中松散的提及(如「Related to STR-101」)会被标记为纯引用,不展示在任务的 PR 列表中。
|
package/dist/plugin/skills/morula-working-on-issues/references/working-on-issues-source-map.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
| 契约 | 服务端实现 | 位置 |
|
|
7
7
|
|------|-----------|------|
|
|
8
|
-
| 任务 key 匹配(`SPW299-30`) | `VcsLinkService.TASK_KEY_RE`(扫描 title
|
|
8
|
+
| 任务 key 匹配(`SPW299-30`) | `VcsLinkService.TASK_KEY_RE`(扫描 title/branch/body;正则 `[A-Z][A-Z0-9]{1,9}-数字`,大小写敏感 → **MR title/body 中的编号须原样大写**;分支名已不含编号(契约 0.3 定案),编号由平台通道自动写入 title/body) | `src/modules/vcs-integration/link/vcs-link.service.ts:30,435` |
|
|
9
9
|
| Close intent 单独扫描(title/body,`Closes|Fixes|Resolves` 紧跟 key) | `CLOSE_INTENT_RE` | `vcs-link.service.ts:29` |
|
|
10
10
|
| reference-only 隐藏(松散 body 提及不入 PR 列表) | `resolveTargets` 与 closeIntent 分支 | `vcs-link.service.ts:60-80, 184-186` |
|
|
11
11
|
| merge 关单幂等 | merged → closeIntent 链接对应任务 | `vcs-link.service.ts:19-20`(文件头注释) |
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
| 契约 | 实现 | 位置 |
|
|
29
29
|
|------|------|------|
|
|
30
|
-
| 分支名由 Agent 取名并上报(格式 `<type
|
|
30
|
+
| 分支名由 Agent 取名并上报(格式 `<type>/<slug>`,见契约 0.3) | workContext 初始占位符 `morula/tmp-<random6>`;`morula task branch <id> --name <name> [--repo <owner/name>]` 更新(多仓库任务的次仓库带 `--repo`) | `buildPlaceholderBranchName`(`collaboration-logic.ts`)、`POST /agent-tasks/:id/branch`(`agent-task.controller.ts`)、`commands/task.ts`。**服务端不生成分支名**(曾有的 `buildBranchName` 编码旧规范,已删除) |
|
|
31
31
|
| 独立 worktree 创建(detached,不建占位分支) | `prepareWorktree`(`git worktree add --detach`) | `packages/runtime/src/daemon/worktree-manager.ts` |
|
|
32
32
|
| 复用检测(允许 agent 改名,禁主干) | marker 身份校验不含 branchName;detached 残留自动保全重建(未提交改动 → stash `morula-rescue <tag>`、未推送提交 → `refs/morula-rescue/<tag>`),保全失败/主干 → `WORKTREE_BRANCH_DRIFT` | `worktree-manager.ts`、`workspace-marker.ts` |
|
|
33
33
|
| 任务编号补齐兜底 | `ensurePullRequestTaskCode` | `packages/runtime/src/daemon/runner.ts` |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcships/morula-runtime",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.0-alpha.
|
|
4
|
+
"version": "0.1.0-alpha.12",
|
|
5
5
|
"description": "Device-level CLI for the Morula local agent runtime (daemon/portal/models/auth) and the Morula business CLI (morula), distributed via npm",
|
|
6
6
|
"bin": {
|
|
7
7
|
"morula-runtime": "./bin/morula-runtime.js",
|