oasis_test 0.1.61 → 0.1.63
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 +815 -304
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,6 +34,197 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
mod
|
|
35
35
|
));
|
|
36
36
|
|
|
37
|
+
// ../core/src/content-type-handler.ts
|
|
38
|
+
function deliverableSubmit(ctx) {
|
|
39
|
+
const id = ctx.artifactId;
|
|
40
|
+
if (ctx.action === "integrate") {
|
|
41
|
+
return `- \`oasis integrate ${id} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2014\u2014 **\u6536\u53E3\u4E13\u7528**\uFF1A\u628A\u4F60\u5728 deliverable/ \u5408\u6210\u7684\u6574\u5408\u7248\u843D\u4E3A\u65B0 head\uFF08\u7CFB\u7EDF\u5185\u90E8\u4F1A\u628A\u961F\u5217\u91CC\u5176\u4F59\u5F85\u843D\u7248\u672C\u4E00\u5E76\u5E76\u8FDB\u6765\uFF09\u3002**\u7EDD\u4E0D\u8981\u7528 propose / advance \u4EA4\u96C6\u6210**\uFF08\u90A3\u4F1A\u628A\u96C6\u6210\u5F53\u6210\u53C8\u4E00\u4E2A\u5E76\u5217\u7248\u672C\u3001\u843D\u9519\u7248\u672C\uFF09\u3002`;
|
|
42
|
+
}
|
|
43
|
+
if (ctx.isPart) {
|
|
44
|
+
return `- \`oasis propose ${id} --part <\u4F60\u7684\u90E8\u4EF6> --file <\u6587\u4EF6> --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u4EA7\u51FA\u3002\`--part\` \u5FC5\u987B\u662F\u5206\u914D\u7ED9\u4F60\u7684\u90A3\u4E2A\u90E8\u4EF6\u540D\uFF1B\`--file\` \u6307\u5411\u4F60\u5199\u597D\u7684\u5185\u5BB9\u6587\u4EF6\uFF08\u90E8\u4EF6\u662F\u72EC\u7ACB\u788E\u7247\uFF0C\u5199\u4F60\u81EA\u5DF1\u7684\uFF09\uFF1B\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u505A\u4E86\u5565\u3002\u4EA7\u5B8C\u5373\u53EF\u6536\u5DE5\uFF0C\u96C6\u6210\u7531 owner \u505A\u3002`;
|
|
45
|
+
}
|
|
46
|
+
return `- \`oasis propose ${id} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4EA7\u7269\u7684\u65B0\u4E00\u7248\u3002\`--from-dir\` \u6307\u5411\u4F60\u7F16\u8F91\u540E\u7684 deliverable/\uFF08\u7CFB\u7EDF\u636E\u76EE\u5F55\u7B97\u8FD9\u7248\u3001\u5E76\u548C\u4E0A\u4E00\u7248 diff\uFF09\uFF1B\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u6539\u4E86\u5565\uFF08\u7ED9\u8BC4\u5BA1/\u540E\u4EBA\u770B\uFF0C\u4E0D\u7528\u50CF git commit \u90A3\u4E48\u7EC6\uFF09\u3002`;
|
|
47
|
+
}
|
|
48
|
+
function handlerFor(repos, contentType) {
|
|
49
|
+
if (repos?.some((r) => r.remote)) return codeHandler;
|
|
50
|
+
if (contentType === "media") return mediaHandler;
|
|
51
|
+
return textHandler;
|
|
52
|
+
}
|
|
53
|
+
function handlerForType(contentType) {
|
|
54
|
+
if (contentType === void 0) return void 0;
|
|
55
|
+
if (contentType === "code") return codeHandler;
|
|
56
|
+
if (contentType === "media") return mediaHandler;
|
|
57
|
+
return textHandler;
|
|
58
|
+
}
|
|
59
|
+
var slug, textHandler, codeHandler, mediaHandler;
|
|
60
|
+
var init_content_type_handler = __esm({
|
|
61
|
+
"../core/src/content-type-handler.ts"() {
|
|
62
|
+
"use strict";
|
|
63
|
+
slug = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
64
|
+
textHandler = {
|
|
65
|
+
produceInstructions(ctx) {
|
|
66
|
+
const { artifactId } = ctx;
|
|
67
|
+
if (ctx.part !== void 0) {
|
|
68
|
+
return [
|
|
69
|
+
`\u628A\u4F60\u8FD9\u4E2A\u90E8\u4EF6 \`${ctx.part}\` \u7684\u5B8C\u6574\u5185\u5BB9\u5199\u8FDB\u672C\u5730\u6587\u4EF6\uFF0C\u7136\u540E**\u53EA\u6267\u884C\u8FD9\u4E00\u6B65**\uFF1A`,
|
|
70
|
+
`\`oasis propose ${artifactId} --file <\u6587\u4EF6> --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\`\u3002`,
|
|
71
|
+
`**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D\u8981 advance\u3001\u4E0D\u8981 conclude**\u3002\u7B49\u6240\u6709\u5144\u5F1F\u90E8\u4EF6\u90FD\u4EA7\u51FA\u540E\uFF0C\u7CFB\u7EDF\u4F1A\u628A\u5404\u90E8\u4EF6\u96C6\u6210\u6210\u4E00\u7248\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`,
|
|
72
|
+
``,
|
|
73
|
+
`> \u26A0 \u5927\u6587\u4EF6\u52A1\u5FC5**\u589E\u91CF\u5199**\uFF08Write \u9AA8\u67B6 \u2192 Edit \u5206\u6B21\u8FFD\u52A0\uFF09\uFF0C\u522B\u4E00\u6B21\u6027\u5410\u6574\u4E2A\u5927\u6587\u4EF6\uFF08\u6709\u8F93\u51FA token \u4E0A\u9650\uFF09\u3002`
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
if (ctx.unionInto !== void 0) {
|
|
77
|
+
return [
|
|
78
|
+
`\u4F60\u4EA7\u51FA\u7684\u662F**\u6574\u4F53\u4EA4\u4ED8\u7269\u7684\u4E00\u4E2A\u6A21\u5757**\uFF0C\u4F1A\u88AB\u673A\u68B0\u5E76\u5165 \`${ctx.unionInto}\`\uFF08\u6309\u6587\u4EF6\u540D\u5408\u5E76\uFF09\u3002`,
|
|
79
|
+
`\u628A\u4F60\u8D1F\u8D23\u7684\u6587\u4EF6\u5199\u8FDB\u4E00\u4E2A**\u76EE\u5F55**\uFF08\u6587\u4EF6\u540D\u5373\u5B83\u5728\u6700\u7EC8\u4EA4\u4ED8\u7269\u91CC\u7684\u8DEF\u5F84\uFF0C\u5982 \`combat.js\`\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
80
|
+
`\`oasis propose ${artifactId} --from-dir <\u76EE\u5F55> --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\` \u2192 \`oasis conclude ${artifactId}\`\u3002`,
|
|
81
|
+
`**\u53EA\u5199\u4F60\u8FD9\u4E2A\u6A21\u5757\u7684\u6587\u4EF6\uFF0C\u4E0D\u8981\u78B0\u522B\u7684\u6A21\u5757\u7684\u6587\u4EF6**\uFF08\u540C\u540D\u4F1A\u8986\u76D6\u522B\u4EBA\u7684\uFF09\u3002\u4E25\u683C\u9075\u5B88\u4E0A\u6E38 tech-design \u7EA6\u5B9A\u7684\u63A5\u53E3/\u5168\u5C40\u547D\u540D\uFF0C\u6A21\u5757\u95F4\u624D\u80FD\u62FC\u5F97\u8D77\u6765\u3002`,
|
|
82
|
+
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
return [
|
|
86
|
+
ctx.hasHead ? `\u4F60\u7684\u4EA4\u4ED8\u7269\u5728 \`./deliverable/\` \u2014\u2014 \u91CC\u9762\u5DF2\u662F**\u5F53\u524D\u7248\u672C\u7684\u5B8C\u6574\u5185\u5BB9**\uFF0C\u76F4\u63A5\u5728\u5B83\u4E0A\u9762\u589E\u5220\u6539\u3002` : `\u4F60\u7684\u4EA4\u4ED8\u7269\u76EE\u5F55\u662F \`./deliverable/\`\uFF08\u5F53\u524D\u4E3A\u7A7A\u2014\u2014\u8FD9\u662F\u5168\u65B0\u4EA7\u7269\uFF0C\u5728\u5176\u4E2D\u4EA7\u51FA\u9996\u7248\u5185\u5BB9\uFF09\u3002`,
|
|
87
|
+
`- \u6700\u7EC8\u4EA7\u7269\u53EA\u653E \`deliverable/\`\uFF1B\u4E34\u65F6\u6587\u4EF6\uFF08\u8349\u7A3F/\u811A\u672C/\u5B9E\u9A8C\uFF09\u653E\u5230**\u522B\u5904**\uFF0C\u522B\u7559\u5728 \`deliverable/\` \u91CC\u3002`,
|
|
88
|
+
`- \u6539\u597D\u540E\u6574\u76EE\u5F55\u63D0\u4EA4\uFF1A\`oasis propose ${artifactId} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\``,
|
|
89
|
+
` \u2192 \u7CFB\u7EDF\u81EA\u52A8\u843D\u5730\u4E3A\u65B0\u7248\u672C\uFF08**\u65E0\u9700 advance**\uFF09\uFF1B\u6574\u4E2A\u4EA4\u4ED8\u7269**\u771F\u6B63\u5B8C\u6574**\u4E86\u518D \`oasis conclude ${artifactId}\`\u3002`,
|
|
90
|
+
...ctx.hasHead ? [`\uFF08\`deliverable/\` \u672C\u5C31\u662F head \u7684\u5B8C\u6574\u526F\u672C\u2014\u2014\u4F60\u4EA4\u7684\u4E00\u5B9A\u662F\u5B8C\u6574\u7248\uFF0C\u4E0D\u4F1A\u4E22\u5DF2\u6709\u5185\u5BB9\u3002\uFF09`] : [],
|
|
91
|
+
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
92
|
+
];
|
|
93
|
+
},
|
|
94
|
+
integrateInstructions(ctx) {
|
|
95
|
+
const parts = ctx.queuedPartLabels.map((p2) => `\`${p2}\``).join("\u3001") || "\uFF08\u961F\u5217\u4E3A\u7A7A\uFF09";
|
|
96
|
+
return [
|
|
97
|
+
`\u5404\u90E8\u4EF6\u4ECE**\u5171\u540C\u7956\u5148 H** \u5206\u5934\u4EA7\u51FA\u3001\u5404\u6539\u5404\u5757\uFF1A\u6BCF\u6761\u5185\u5BB9\u5728 \`parts/<\u540D>/CONTENT.md\`\uFF08\u6216\u5176\u5C55\u5F00\u6587\u4EF6\uFF09\u91CC\uFF08${parts}\uFF09\uFF0CH \u7684\u5185\u5BB9\u5728 \`deliverable/\`\uFF08\u4ECE\u96F6\u5206\u89E3\u5219\u4E3A\u7A7A\uFF09\u3002`,
|
|
98
|
+
`\u628A\u5B83\u4EEC\u5408\u6210\u4E00\u4E2A\u5B8C\u6574\u7684\u6574\u5408\u7248**\u5C31\u5730\u5199\u8FDB \`deliverable/\`**\u2014\u2014**\u4EE5 H \u4E3A\u5E95**\u3001\u628A\u5404\u90E8\u4EF6\u6539\u52A8**\u5168\u5E76\u8FDB\u6765**\uFF08\u5355\u6587\u4EF6 \`deliverable/CONTENT.md\`\uFF0C\u591A\u6587\u4EF6\u94FA\u6210\u591A\u4E2A\u6587\u4EF6\uFF1B\u5927\u6587\u4EF6\u589E\u91CF\u5199\uFF1AWrite \u9AA8\u67B6 \u2192 Edit \u8FFD\u52A0\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
99
|
+
`\`oasis integrate ${ctx.artifactId} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${ctx.artifactId}\`\u3002`,
|
|
100
|
+
``,
|
|
101
|
+
`**\u5FE0\u5B9E\u5408\u5E76\u3001\u522B\u4E22\u4EFB\u4F55\u90E8\u4EF6**\uFF1B\u63A5\u53E3/\u547D\u540D\u5BF9\u4E0D\u9F50\u5C31\u6309\u4E0A\u6E38\u89C4\u683C\u6821\u6B63\uFF0C\u8BA9 N \u4E2A\u90E8\u4EF6\u62FC\u6210\u4E00\u4E2A\u81EA\u6D3D\u6574\u4F53\u3002`
|
|
102
|
+
];
|
|
103
|
+
},
|
|
104
|
+
submitInstruction: deliverableSubmit,
|
|
105
|
+
collectionStrategy: { kind: "inline" },
|
|
106
|
+
mergeMode: "oasis-queue"
|
|
107
|
+
};
|
|
108
|
+
codeHandler = {
|
|
109
|
+
produceInstructions(ctx) {
|
|
110
|
+
const { artifactId } = ctx;
|
|
111
|
+
const repos = ctx.repos ?? [];
|
|
112
|
+
const r0 = repos[0];
|
|
113
|
+
if (ctx.part !== void 0) {
|
|
114
|
+
const work = `feat/${slug(artifactId)}__${slug(ctx.part)}`;
|
|
115
|
+
const feat2 = `feat/${slug(artifactId)}`;
|
|
116
|
+
const dev = r0?.develop ?? "develop";
|
|
117
|
+
return [
|
|
118
|
+
`\u4F60\u4EA7\u51FA\u7684\u662F\u9879\u76EE **${ctx.projectName ?? "?"}** \u7684\u4EE3\u7801\u3001\u4E14\u53EA\u662F\u90E8\u4EF6 \`${ctx.part}\`\u2014\u2014\u5185\u5BB9\u6D3B\u5728 git \u91CC\u3002\u4F60**\u53EA\u7BA1\u4EA7\u51FA\u4F60\u8FD9\u5757\u3001push \u4F60\u81EA\u5DF1\u7684\u5DE5\u4F5C\u5206\u652F**\uFF1B\`oasis propose\` \u65F6**\u7CFB\u7EDF\u4F1A\u628A\u5B83\u5E72\u51C0\u5408\u8FDB\u5DE5\u5355\u5206\u652F \`${feat2}\`**\uFF08\u4E0D\u7528\u4F60\u624B\u52A8\u5408\u3001\u4E5F\u4E0D\u7528\u7B49 owner \u5408\uFF09\u3002`,
|
|
119
|
+
`1. \`git clone ${r0?.remote ?? "<remote>"} repos/${r0?.id ?? "<id>"}\` \u2192 \`cd repos/${r0?.id ?? "<id>"}\` \u2192 \u4ECE\u4E3B\u5E72\u8D77\u4F60\u7684\u5DE5\u4F5C\u5206\u652F\uFF1A\`git checkout ${dev} && git checkout -b ${work}\``,
|
|
120
|
+
`2. \u5B9E\u73B0\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u6539\u52A8\uFF08\u4E25\u5B88\u4E0A\u6E38\u63A5\u53E3\u7EA6\u5B9A\uFF09\u3001\u81EA\u67E5\u80FD\u6784\u5EFA/\u80FD\u8DD1\u3001\`git commit\``,
|
|
121
|
+
`3. **\u53EA\u63A8\u4F60\u81EA\u5DF1\u7684\u5DE5\u4F5C\u5206\u652F**\uFF1A\`git push -u origin ${work}\`\uFF08**\u522B\u78B0 \`${feat2}\`**\u2014\u2014\u5408\u5E76\u4EA4\u7ED9\u7CFB\u7EDF\uFF09`,
|
|
122
|
+
`4. \u56DE\u62A5\uFF1A\`oasis propose ${artifactId} --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD>"\`\uFF08\u7CFB\u7EDF\u628A \`${work}\` \u5E72\u51C0\u5408\u8FDB \`${feat2}\` \u518D\u6536\u96C6\uFF1B**\u82E5\u4E0E \`${feat2}\` \u51B2\u7A81\u4F1A\u5F53\u573A\u6253\u56DE**\u2014\u2014\u6309\u63D0\u793A \`git fetch && git rebase origin/${feat2}\` \u89E3\u5B8C\u51B2\u7A81\u3001\`git push -f origin ${work}\` \u540E\u91CD\u65B0 propose\uFF09`,
|
|
123
|
+
`**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D conclude**\u3002\u5404\u90E8\u4EF6\u90FD\u5E76\u5B8C\u540E\u7531 owner \u9A8C\u6574\u4F53\u6536\u53E3\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
const feat = `feat/${slug(artifactId)}`;
|
|
127
|
+
if (ctx.isFinalize) {
|
|
128
|
+
const r02 = repos[0];
|
|
129
|
+
return [
|
|
130
|
+
`\u4F60\u662F **${ctx.projectName ?? "?"}** \u4EE3\u7801\u4EA4\u4ED8\u7269\u7684 owner\uFF0C\u6765**\u6536\u53E3**\uFF1A\u5404\u90E8\u4EF6\u5DF2\u5404\u81EA\u5E76\u5165**\u5DE5\u5355\u5206\u652F \`${feat}\`**\uFF08\u6BCF\u4E2A part \u5E72\u5B8C\u81EA\u5DF1 merge \u8FDB\u6765\u3001\u89E3\u4E86\u5404\u81EA\u51B2\u7A81\uFF09\u3002\u4F60**\u4E0D\u7528\u518D\u9010\u6761\u5408\u5E76**\uFF0C\u53EA\u9A8C\u6574\u4F53 + \u6536\u53E3\uFF1A`,
|
|
131
|
+
`1. \`git clone ${r02?.remote ?? "<remote>"} repos/${r02?.id ?? "<id>"}\` \u2192 \`cd repos/${r02?.id ?? "<id>"} && git fetch && git checkout ${feat}\`\uFF08**\u662F\u5DF2\u5B58\u5728\u7684\u5DE5\u5355\u5206\u652F\u3001\u542B\u5404\u90E8\u4EF6\u5168\u90E8\u6539\u52A8**\uFF0C\u4E0D\u662F\u4ECE\u4E3B\u5E72\u65B0\u5EFA\uFF09\u3002\u591A\u4ED3\u5219\u5BF9\u6BCF\u4E2A\u78B0\u8FC7\u7684\u4ED3\u540C\u6837 checkout \`${feat}\`\u3002`,
|
|
132
|
+
`2. **\u9A8C\u6574\u4F53\u80FD\u6784\u5EFA / \u80FD\u8DD1**\uFF08\u8FD9\u624D\u662F\u4F60 owner \u7684\u5224\u65AD\u6D3B\uFF09\uFF1B\u6709\u6B8B\u7559\u95EE\u9898\uFF08\u63A5\u53E3\u6CA1\u5BF9\u9F50 / \u6784\u5EFA\u5931\u8D25 / \u90E8\u4EF6\u8854\u63A5\u5904\u8981\u6536\u5C3E\uFF09\u2192 \u5C31\u5730\u4FEE\u3001\`git commit\`\u3001\`git push origin ${feat}\`\u3002`,
|
|
133
|
+
`3. \`oasis propose ${artifactId} --reason "<\u6536\u53E3\u8BF4\u660E>"\`\uFF08\u7CFB\u7EDF\u4ECE\u5404\u4ED3 \`${feat}\` \u6536\u5168 {\u4ED3\u5E93\u2192\u63D0\u4EA4} = \u5168\u90E8\u4EF6\u6574\u5408\u6001\uFF09\u2192 \`oasis conclude ${artifactId}\`\uFF08conclude \u540E\u9010\u4ED3 gated \u5408\u8FDB\u4E3B\u5E72\uFF09\u3002`,
|
|
134
|
+
``,
|
|
135
|
+
`**\u4F60\u8FD9\u7EA7\u662F\u628A\u5173\u6574\u4F53\u81EA\u6D3D + \u6536\u53E3\u6210\u4EA4\u4ED8\u7248\uFF0C\u4E0D\u662F\u91CD\u65B0\u5B9E\u73B0**\u2014\u2014\u5404\u90E8\u4EF6\u7684\u5B9E\u73B0\u5DF2\u5728\u5B83\u4EEC\u5404\u81EA\u6536\u5C3E\u65F6\u5E76\u8FDB \`${feat}\` \u4E86\u3002**\u522B\u7528 \`oasis integrate\`**\uFF1A\u4EE3\u7801\u6536\u53E3\u5C31\u8D70 \`propose\`\uFF08git-native\uFF09\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
const repoLines = repos.map((r) => ` - \`${r.id}\`\uFF1A${r.remote ?? "<remote>"}\uFF08\u4E3B\u5E72 \`${r.develop}\`\uFF09`);
|
|
139
|
+
const short = (s2) => s2.slice(0, 12);
|
|
140
|
+
const versionLine = (() => {
|
|
141
|
+
if (!(ctx.hasHead && ctx.headExternalRef)) return [];
|
|
142
|
+
const ref2 = ctx.headExternalRef;
|
|
143
|
+
if (ref2.trim().startsWith("{")) {
|
|
144
|
+
try {
|
|
145
|
+
const m2 = JSON.parse(ref2);
|
|
146
|
+
const parts = Object.entries(m2).map(([id, sha2]) => `\`${id}\` @ \`${short(sha2)}\``);
|
|
147
|
+
return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u5404\u4ED3\u4E3B\u5E72\uFF09\uFF1A${parts.join("\uFF0C")}\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
|
|
148
|
+
} catch {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u4E3B\u5E72\uFF09\uFF1A\`${repos[0]?.id ?? "<\u4E3B\u4ED3>"}\` @ \`${short(ref2)}\`\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
|
|
152
|
+
})();
|
|
153
|
+
return [
|
|
154
|
+
`\u4F60\u4EA7\u51FA\u7684\u662F\u9879\u76EE **${ctx.projectName ?? "?"}** \u7684\u4EE3\u7801\u2014\u2014**\u5185\u5BB9\u76F4\u63A5\u6D3B\u5728 git \u4ED3\u5E93\u91CC**\uFF0C\u4F60\u50CF\u5F00\u53D1\u8005\u4E00\u6837\u5728 git \u91CC\u5E72\uFF0C\u4EA7\u7269\u4E0D\u8FDB Oasis \u6863\u6848\u67DC\u3002`,
|
|
155
|
+
``,
|
|
156
|
+
`\u672C\u9879\u76EE\u7684\u4EE3\u7801\u4ED3\u5E93\uFF08\u4F1E\u4ED3\uFF0C\u672C\u673A\u51ED\u8BC1\u5DF2\u914D\u597D\uFF1B**\u53EA\u52A8\u4F60\u9700\u8981\u6539\u7684\uFF0C\u4E0D\u78B0\u7684\u4E0D\u7528 clone**\uFF09\uFF1A`,
|
|
157
|
+
...repoLines,
|
|
158
|
+
`> \u636E\u4F60\u7684**\u4E0A\u6E38\u8F93\u5165**\u5224\u65AD\u672C\u5DE5\u5355\u8BE5\u843D\u5728**\u54EA\u4E2A**\u4ED3\uFF0C\u518D\u5BF9\u7167\u4E0A\u9762\u9879\u76EE\u73B0\u6709\u7684\u4ED3\uFF1A\u9700\u8981\u7684\u4ED3**\u5728\u6E05\u5355\u91CC** \u2192 \u53EA\u5728\u90A3\u4E2A\u4ED3\u91CC\u5E72\uFF1B**\u4E0D\u5728**\uFF08\u9879\u76EE\u6709\u522B\u7684\u4ED3\u3001\u4F46\u6CA1\u6709\u4F60\u9700\u8981\u7684\u90A3\u4E2A\uFF09\u2192 \u522B\u51D1\u5408\u7528\u522B\u7684\u4ED3\uFF0C\u7528 \`oasis gap ${artifactId} --desc "<\u7F3A\u54EA\u4E2A\u4ED3\u53CA\u7528\u9014>"\` \u62A5\u7F3A\u53E3\u3002`,
|
|
159
|
+
...versionLine,
|
|
160
|
+
``,
|
|
161
|
+
`### \u5DE5\u4F5C\u6D41\u7A0B\uFF08git-native\uFF0C\u4F1E\u4ED3\uFF09`,
|
|
162
|
+
`1. \u5BF9**\u6BCF\u4E2A\u4F60\u8981\u6539\u7684\u4ED3\u5E93**\uFF1A\`git clone <remote> repos/<id>\` \u2192 \`cd repos/<id> && git checkout <\u4E3B\u5E72> && git checkout -b ${feat}\``,
|
|
163
|
+
`2. \u57FA\u4E8E \`inputs/\`\uFF08\u4E0A\u6E38\u89C4\u683C\uFF09\u5B9E\u73B0\u6539\u52A8\u2014\u2014clone \u4E0B\u6765\u7684\u4E3B\u5E72\u5DF2\u542B\u6B64\u524D\u5DF2\u5E76\u5165\u7684\u4EE3\u7801\uFF0C**\u5728\u5B83\u4E4B\u4E0A\u6539**`,
|
|
164
|
+
`3. \u6BCF\u4E2A\u6539\u8FC7\u7684\u4ED3\u5E93\uFF1A\u81EA\u67E5\uFF08\u8BED\u6CD5/\u6784\u5EFA/\u80FD\u8DD1\uFF09\uFF0C\`git commit\`\uFF0C\`git push -u origin ${feat}\``,
|
|
165
|
+
`4. \u56DE\u62A5 Oasis\uFF1A\`oasis propose ${artifactId} --reason "<\u4E00\u53E5\u8BDD>"\` \u2192 \`oasis conclude ${artifactId}\``,
|
|
166
|
+
` **\u4E0D\u7528\u62A5 commit sha**\u2014\u2014\u7CFB\u7EDF\u4F1A\u53BB\u5404\u4ED3\u5E93\u7684 \`${feat}\` \u5206\u652F\u81EA\u52A8\u6536\u96C6\u4F60\u7684\u63D0\u4EA4\uFF0C\u62FC\u6210 {\u4ED3\u5E93\u2192\u63D0\u4EA4} \u6E05\u5355\uFF1B\u6CA1\u78B0\u7684\u4ED3\u5E93\uFF08\`${feat}\` \u65E0\u65B0\u63D0\u4EA4\uFF09\u4E0D\u8BA1\u5165\u3002`,
|
|
167
|
+
``,
|
|
168
|
+
`**\u4E0D\u8981\u63A8\u4E3B\u5E72\u3001\u4E0D\u8981\u81EA\u5DF1\u5408\u5E76**\u2014\u2014\u96C6\u6210\u7531\u7CFB\u7EDF\u5728 conclude \u540E\u9010\u4ED3\u628A\u5173\u5408\u5E76\u3002\u7248\u672C\u5386\u53F2 diff \u4F60\u81EA\u5DF1 \`git log -p\` \u5373\u53EF\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
169
|
+
];
|
|
170
|
+
},
|
|
171
|
+
integrateInstructions(ctx) {
|
|
172
|
+
const { artifactId } = ctx;
|
|
173
|
+
const r0 = ctx.repos?.[0];
|
|
174
|
+
const feat = `feat/${slug(artifactId)}`;
|
|
175
|
+
return [
|
|
176
|
+
`\u8FD9\u662F\u4EE3\u7801\u2014\u2014\u5404\u90E8\u4EF6**\u5DF2\u81EA\u884C\u5E76\u5165\u5DE5\u5355\u5206\u652F \`${feat}\`**\uFF08\u6BCF\u4E2A part \u5E72\u5B8C\u81EA\u5DF1 merge \u8FDB\u6765\u3001\u89E3\u4E86\u5404\u81EA\u7684\u51B2\u7A81\uFF09\u3002\u4F60 owner **\u4E0D\u7528\u518D\u9010\u6761\u5408\u5E76**\uFF0C\u53EA\u9A8C\u6574\u4F53 + \u6536\u53E3\uFF1A`,
|
|
177
|
+
`1. \`git clone ${r0?.remote ?? "<remote>"} repos/${r0?.id ?? "<id>"}\` \u2192 \`git checkout ${feat}\`\uFF0C**\u9A8C\u6574\u4F53\u80FD\u6784\u5EFA/\u80FD\u8DD1**\uFF08\u8FD9\u624D\u662F\u4F60 owner \u7684\u5224\u65AD\u6D3B\uFF09\u3002`,
|
|
178
|
+
`2. \u82E5\u6709\u6B8B\u7559\u95EE\u9898\uFF08\u63A5\u53E3\u6CA1\u5BF9\u9F50\u3001\u6784\u5EFA\u5931\u8D25\u3001\u90E8\u4EF6\u8854\u63A5\u5904\u8981\u6536\u5C3E\uFF09\u2192 \u5C31\u5730\u4FEE\u3001\`git commit\`\u3001\`git push origin ${feat}\`\u3002`,
|
|
179
|
+
`3. \`oasis integrate ${artifactId} --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${artifactId}\`\uFF08\u7CFB\u7EDF\u4ECE \`${feat}\` \u6536\u96C6\u6574\u5408\u7248\uFF1Bconclude \u540E\u9010\u4ED3\u540C\u6B65\u8FDB develop\uFF09\u3002`,
|
|
180
|
+
``,
|
|
181
|
+
`**\u4F60\u8FD9\u7EA7\u662F\u628A\u5173\u6574\u4F53\u81EA\u6D3D\u3001\u4E0D\u662F\u91CD\u65B0\u5408\u5E76**\u2014\u2014\u5408\u5E76\u5DF2\u7ECF\u5728\u5404\u90E8\u4EF6\u6536\u5C3E\u65F6\u5404\u81EA\u505A\u5B8C\u4E86\u3002`
|
|
182
|
+
];
|
|
183
|
+
},
|
|
184
|
+
submitInstruction(ctx) {
|
|
185
|
+
const id = ctx.artifactId;
|
|
186
|
+
if (ctx.action === "integrate") {
|
|
187
|
+
return `- \`oasis integrate ${id} --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2014\u2014 **\u6536\u53E3\u4E13\u7528**\uFF1A\u628A\u5DE5\u5355\u5206\u652F\u7684\u6574\u5408\u7248\u843D\u4E3A R\\*\uFF08\u7CFB\u7EDF\u4ECE git \u6536\u96C6\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002**\u7EDD\u4E0D\u8981\u7528 propose/advance \u4EA4\u96C6\u6210**\u3002`;
|
|
188
|
+
}
|
|
189
|
+
if (ctx.isPart) {
|
|
190
|
+
return `- \`oasis propose ${id} --part <\u4F60\u7684\u90E8\u4EF6> --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u4EA7\u51FA\uFF08\u4EE3\u7801\uFF1A\u4F60 push \u4F60\u7684\u5DE5\u4F5C\u5206\u652F\uFF0C\u7CFB\u7EDF\u628A\u5B83\u5E72\u51C0\u5408\u8FDB\u5DE5\u5355\u5206\u652F\u518D\u6536\u96C6\uFF1B\u51B2\u7A81\u4F1A\u6253\u56DE\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002\`--part\` \u5FC5\u987B\u662F\u5206\u914D\u7ED9\u4F60\u7684\u90E8\u4EF6\u540D\u3002\u4EA7\u5B8C\u5373\u53EF\u6536\u5DE5\u3002`;
|
|
191
|
+
}
|
|
192
|
+
return `- \`oasis propose ${id} --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4EA7\u7269\u7684\u65B0\u4E00\u7248\uFF08\u4EE3\u7801\uFF1A\u4F60\u5DF2 push \u5230\u5DE5\u5355\u5206\u652F\uFF0C\u7CFB\u7EDF\u4ECE\u5404\u4ED3\u6536\u96C6 {\u4ED3\u5E93\u2192\u63D0\u4EA4}\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u6539\u4E86\u5565\u3002`;
|
|
193
|
+
},
|
|
194
|
+
collectionStrategy: { kind: "external-git" },
|
|
195
|
+
mergeMode: "external-ff"
|
|
196
|
+
// Phase B:code git-native——part 直接 FF、owner produce 收口(见 §9.1/§9.5)
|
|
197
|
+
};
|
|
198
|
+
mediaHandler = {
|
|
199
|
+
produceInstructions(ctx) {
|
|
200
|
+
const { artifactId } = ctx;
|
|
201
|
+
if (ctx.part !== void 0) {
|
|
202
|
+
return [
|
|
203
|
+
`\u4F60\u4EA7\u51FA\u7684\u662F**\u5A92\u4F53**\u4EA4\u4ED8\u7269\u7684\u4E00\u4E2A\u90E8\u4EF6 \`${ctx.part}\`\uFF08\u89C6\u9891/\u97F3\u9891/\u56FE\u7B49\uFF09\u3002\u628A\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u6210\u54C1\u6587\u4EF6\u5199\u8FDB\u672C\u5730\uFF0C\u7136\u540E**\u53EA\u8FD9\u4E00\u6B65**\uFF1A`,
|
|
204
|
+
`\`oasis propose ${artifactId} --file <\u6210\u54C1\u6587\u4EF6> --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD>"\`\u3002**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D conclude**\uFF0C\u7B49\u5404\u90E8\u4EF6\u9F50\u4E86 owner \u6536\u53E3\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
205
|
+
];
|
|
206
|
+
}
|
|
207
|
+
return [
|
|
208
|
+
ctx.hasHead ? `\u4F60\u7684\u4EA4\u4ED8\u7269\u5728 \`./deliverable/\`\uFF08\u5A92\u4F53\u6210\u54C1\uFF1A\u89C6\u9891/\u97F3\u9891/\u56FE\u7B49\uFF09\u2014\u2014\u5728\u5B83\u57FA\u7840\u4E0A\u66F4\u65B0/\u66FF\u6362\u3002` : `\u4F60\u7684\u4EA4\u4ED8\u7269\u76EE\u5F55\u662F \`./deliverable/\`\uFF08\u5F53\u524D\u4E3A\u7A7A\u2014\u2014\u4EA7\u51FA\u9996\u7248\u6210\u54C1\uFF09\u3002`,
|
|
209
|
+
`\u628A**\u6E32\u67D3/\u5BFC\u51FA\u597D\u7684\u6210\u54C1\u6587\u4EF6**\u653E\u8FDB \`deliverable/\`\uFF08\u6309\u4EA4\u4ED8\u8981\u6C42\u7684\u683C\u5F0F\uFF0C\u5982 mp4/wav/png\uFF1B\u5927\u4E8C\u8FDB\u5236\u76F4\u63A5\u653E\uFF0C\u522B\u585E\u8FDB\u6587\u672C\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
210
|
+
`\`oasis propose ${artifactId} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\` \u2192 \u6574\u4F53\u5B8C\u6574\u4E86\u518D \`oasis conclude ${artifactId}\`\u3002`,
|
|
211
|
+
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\uFF08\u811A\u672C/\u5206\u955C/\u7D20\u6750\u6CA1\u5C31\u7EEA\uFF09\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
212
|
+
];
|
|
213
|
+
},
|
|
214
|
+
integrateInstructions(ctx) {
|
|
215
|
+
const parts = ctx.queuedPartLabels.map((p2) => `\`${p2}\``).join("\u3001") || "\uFF08\u961F\u5217\u4E3A\u7A7A\uFF09";
|
|
216
|
+
return [
|
|
217
|
+
`\u5404\u90E8\u4EF6\u7684\u6210\u54C1\u5728 \`parts/<\u540D>/\`\uFF08${parts}\uFF09\u3002\u628A\u5B83\u4EEC\u6C47\u6210**\u6700\u7EC8\u6210\u54C1**\u653E\u8FDB \`deliverable/\`\uFF08\u6309\u4EA4\u4ED8\u683C\u5F0F\u3001\u987A\u5E8F/\u62FC\u63A5\u6B63\u786E\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
218
|
+
`\`oasis integrate ${ctx.artifactId} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${ctx.artifactId}\`\u3002**\u522B\u4E22\u4EFB\u4F55\u90E8\u4EF6**\u3002`
|
|
219
|
+
];
|
|
220
|
+
},
|
|
221
|
+
submitInstruction: deliverableSubmit,
|
|
222
|
+
collectionStrategy: { kind: "inline" },
|
|
223
|
+
mergeMode: "oasis-queue"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
37
228
|
// ../core/src/read-model.ts
|
|
38
229
|
function emptyReadModel() {
|
|
39
230
|
return {
|
|
@@ -78,6 +269,7 @@ function fold(model, op) {
|
|
|
78
269
|
workspace: p2.workspace,
|
|
79
270
|
persistence: p2.persistence ?? "temp",
|
|
80
271
|
createdVia: p2.createdVia,
|
|
272
|
+
...p2.isFinalOutput !== void 0 ? { isFinalOutput: p2.isFinalOutput } : {},
|
|
81
273
|
...p2.title !== void 0 ? { title: p2.title } : {},
|
|
82
274
|
...p2.description !== void 0 ? { description: p2.description } : {},
|
|
83
275
|
...p2.docType !== void 0 ? { docType: p2.docType } : {},
|
|
@@ -944,10 +1136,38 @@ function computeCascadeActions(model, schema) {
|
|
|
944
1136
|
}
|
|
945
1137
|
return out;
|
|
946
1138
|
}
|
|
1139
|
+
function advanceableHead(model, schema, id) {
|
|
1140
|
+
if (lifecycleOf(model, id) !== "active") return null;
|
|
1141
|
+
const head = queueOf(model, id)[0];
|
|
1142
|
+
if (!head) return null;
|
|
1143
|
+
if (isStale(model, head)) return null;
|
|
1144
|
+
if (pendingConcludeAttempt(model, id)) return null;
|
|
1145
|
+
const artifact = model.artifacts.get(id);
|
|
1146
|
+
const typeDef = schema.get(artifact.type);
|
|
1147
|
+
const isExternalFF = handlerForType(typeDef?.contentType)?.mergeMode === "external-ff";
|
|
1148
|
+
const eagerFF = head.part === void 0 || (artifact.parts ?? []).length <= 1 || isExternalFF;
|
|
1149
|
+
if (!eagerFF) return null;
|
|
1150
|
+
const proposerIsAgent = head.author.startsWith("actor:agent:");
|
|
1151
|
+
const requiresHumanReview = proposerIsAgent && (head.resolves !== void 0 ? head.resolves.some((annId) => {
|
|
1152
|
+
const a = model.annotations.get(annId);
|
|
1153
|
+
return a !== void 0 && isHumanChangeRequest(a);
|
|
1154
|
+
}) : hasOpenHumanChangeRequest(model, id));
|
|
1155
|
+
if (requiresHumanReview) return null;
|
|
1156
|
+
return head;
|
|
1157
|
+
}
|
|
1158
|
+
function computeAdvanceableRevisions(model, schema) {
|
|
1159
|
+
const out = [];
|
|
1160
|
+
for (const a of model.artifacts.values()) {
|
|
1161
|
+
const rev = advanceableHead(model, schema, a.id);
|
|
1162
|
+
if (rev) out.push({ artifactId: a.id, revisionId: rev.id });
|
|
1163
|
+
}
|
|
1164
|
+
return out;
|
|
1165
|
+
}
|
|
947
1166
|
var CorruptLogError, STRUCTURAL_OP_KINDS, ROUND_LIMIT_MARKER, PENDING_ROLE_PREFIX, PENDING_UNASSIGNED;
|
|
948
1167
|
var init_read_model = __esm({
|
|
949
1168
|
"../core/src/read-model.ts"() {
|
|
950
1169
|
"use strict";
|
|
1170
|
+
init_content_type_handler();
|
|
951
1171
|
CorruptLogError = class extends Error {
|
|
952
1172
|
name = "CorruptLogError";
|
|
953
1173
|
constructor(op, detail) {
|
|
@@ -1036,197 +1256,6 @@ var init_content_handler = __esm({
|
|
|
1036
1256
|
}
|
|
1037
1257
|
});
|
|
1038
1258
|
|
|
1039
|
-
// ../core/src/content-type-handler.ts
|
|
1040
|
-
function deliverableSubmit(ctx) {
|
|
1041
|
-
const id = ctx.artifactId;
|
|
1042
|
-
if (ctx.action === "integrate") {
|
|
1043
|
-
return `- \`oasis integrate ${id} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2014\u2014 **\u6536\u53E3\u4E13\u7528**\uFF1A\u628A\u4F60\u5728 deliverable/ \u5408\u6210\u7684\u6574\u5408\u7248\u843D\u4E3A\u65B0 head\uFF08\u7CFB\u7EDF\u5185\u90E8\u4F1A\u628A\u961F\u5217\u91CC\u5176\u4F59\u5F85\u843D\u7248\u672C\u4E00\u5E76\u5E76\u8FDB\u6765\uFF09\u3002**\u7EDD\u4E0D\u8981\u7528 propose / advance \u4EA4\u96C6\u6210**\uFF08\u90A3\u4F1A\u628A\u96C6\u6210\u5F53\u6210\u53C8\u4E00\u4E2A\u5E76\u5217\u7248\u672C\u3001\u843D\u9519\u7248\u672C\uFF09\u3002`;
|
|
1044
|
-
}
|
|
1045
|
-
if (ctx.isPart) {
|
|
1046
|
-
return `- \`oasis propose ${id} --part <\u4F60\u7684\u90E8\u4EF6> --file <\u6587\u4EF6> --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u4EA7\u51FA\u3002\`--part\` \u5FC5\u987B\u662F\u5206\u914D\u7ED9\u4F60\u7684\u90A3\u4E2A\u90E8\u4EF6\u540D\uFF1B\`--file\` \u6307\u5411\u4F60\u5199\u597D\u7684\u5185\u5BB9\u6587\u4EF6\uFF08\u90E8\u4EF6\u662F\u72EC\u7ACB\u788E\u7247\uFF0C\u5199\u4F60\u81EA\u5DF1\u7684\uFF09\uFF1B\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u505A\u4E86\u5565\u3002\u4EA7\u5B8C\u5373\u53EF\u6536\u5DE5\uFF0C\u96C6\u6210\u7531 owner \u505A\u3002`;
|
|
1047
|
-
}
|
|
1048
|
-
return `- \`oasis propose ${id} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4EA7\u7269\u7684\u65B0\u4E00\u7248\u3002\`--from-dir\` \u6307\u5411\u4F60\u7F16\u8F91\u540E\u7684 deliverable/\uFF08\u7CFB\u7EDF\u636E\u76EE\u5F55\u7B97\u8FD9\u7248\u3001\u5E76\u548C\u4E0A\u4E00\u7248 diff\uFF09\uFF1B\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u6539\u4E86\u5565\uFF08\u7ED9\u8BC4\u5BA1/\u540E\u4EBA\u770B\uFF0C\u4E0D\u7528\u50CF git commit \u90A3\u4E48\u7EC6\uFF09\u3002`;
|
|
1049
|
-
}
|
|
1050
|
-
function handlerFor(repos, contentType) {
|
|
1051
|
-
if (repos?.some((r) => r.remote)) return codeHandler;
|
|
1052
|
-
if (contentType === "media") return mediaHandler;
|
|
1053
|
-
return textHandler;
|
|
1054
|
-
}
|
|
1055
|
-
function handlerForType(contentType) {
|
|
1056
|
-
if (contentType === void 0) return void 0;
|
|
1057
|
-
if (contentType === "code") return codeHandler;
|
|
1058
|
-
if (contentType === "media") return mediaHandler;
|
|
1059
|
-
return textHandler;
|
|
1060
|
-
}
|
|
1061
|
-
var slug, textHandler, codeHandler, mediaHandler;
|
|
1062
|
-
var init_content_type_handler = __esm({
|
|
1063
|
-
"../core/src/content-type-handler.ts"() {
|
|
1064
|
-
"use strict";
|
|
1065
|
-
slug = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
1066
|
-
textHandler = {
|
|
1067
|
-
produceInstructions(ctx) {
|
|
1068
|
-
const { artifactId } = ctx;
|
|
1069
|
-
if (ctx.part !== void 0) {
|
|
1070
|
-
return [
|
|
1071
|
-
`\u628A\u4F60\u8FD9\u4E2A\u90E8\u4EF6 \`${ctx.part}\` \u7684\u5B8C\u6574\u5185\u5BB9\u5199\u8FDB\u672C\u5730\u6587\u4EF6\uFF0C\u7136\u540E**\u53EA\u6267\u884C\u8FD9\u4E00\u6B65**\uFF1A`,
|
|
1072
|
-
`\`oasis propose ${artifactId} --file <\u6587\u4EF6> --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\`\u3002`,
|
|
1073
|
-
`**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D\u8981 advance\u3001\u4E0D\u8981 conclude**\u3002\u7B49\u6240\u6709\u5144\u5F1F\u90E8\u4EF6\u90FD\u4EA7\u51FA\u540E\uFF0C\u7CFB\u7EDF\u4F1A\u628A\u5404\u90E8\u4EF6\u96C6\u6210\u6210\u4E00\u7248\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`,
|
|
1074
|
-
``,
|
|
1075
|
-
`> \u26A0 \u5927\u6587\u4EF6\u52A1\u5FC5**\u589E\u91CF\u5199**\uFF08Write \u9AA8\u67B6 \u2192 Edit \u5206\u6B21\u8FFD\u52A0\uFF09\uFF0C\u522B\u4E00\u6B21\u6027\u5410\u6574\u4E2A\u5927\u6587\u4EF6\uFF08\u6709\u8F93\u51FA token \u4E0A\u9650\uFF09\u3002`
|
|
1076
|
-
];
|
|
1077
|
-
}
|
|
1078
|
-
if (ctx.unionInto !== void 0) {
|
|
1079
|
-
return [
|
|
1080
|
-
`\u4F60\u4EA7\u51FA\u7684\u662F**\u6574\u4F53\u4EA4\u4ED8\u7269\u7684\u4E00\u4E2A\u6A21\u5757**\uFF0C\u4F1A\u88AB\u673A\u68B0\u5E76\u5165 \`${ctx.unionInto}\`\uFF08\u6309\u6587\u4EF6\u540D\u5408\u5E76\uFF09\u3002`,
|
|
1081
|
-
`\u628A\u4F60\u8D1F\u8D23\u7684\u6587\u4EF6\u5199\u8FDB\u4E00\u4E2A**\u76EE\u5F55**\uFF08\u6587\u4EF6\u540D\u5373\u5B83\u5728\u6700\u7EC8\u4EA4\u4ED8\u7269\u91CC\u7684\u8DEF\u5F84\uFF0C\u5982 \`combat.js\`\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
1082
|
-
`\`oasis propose ${artifactId} --from-dir <\u76EE\u5F55> --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\` \u2192 \`oasis conclude ${artifactId}\`\u3002`,
|
|
1083
|
-
`**\u53EA\u5199\u4F60\u8FD9\u4E2A\u6A21\u5757\u7684\u6587\u4EF6\uFF0C\u4E0D\u8981\u78B0\u522B\u7684\u6A21\u5757\u7684\u6587\u4EF6**\uFF08\u540C\u540D\u4F1A\u8986\u76D6\u522B\u4EBA\u7684\uFF09\u3002\u4E25\u683C\u9075\u5B88\u4E0A\u6E38 tech-design \u7EA6\u5B9A\u7684\u63A5\u53E3/\u5168\u5C40\u547D\u540D\uFF0C\u6A21\u5757\u95F4\u624D\u80FD\u62FC\u5F97\u8D77\u6765\u3002`,
|
|
1084
|
-
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1085
|
-
];
|
|
1086
|
-
}
|
|
1087
|
-
return [
|
|
1088
|
-
ctx.hasHead ? `\u4F60\u7684\u4EA4\u4ED8\u7269\u5728 \`./deliverable/\` \u2014\u2014 \u91CC\u9762\u5DF2\u662F**\u5F53\u524D\u7248\u672C\u7684\u5B8C\u6574\u5185\u5BB9**\uFF0C\u76F4\u63A5\u5728\u5B83\u4E0A\u9762\u589E\u5220\u6539\u3002` : `\u4F60\u7684\u4EA4\u4ED8\u7269\u76EE\u5F55\u662F \`./deliverable/\`\uFF08\u5F53\u524D\u4E3A\u7A7A\u2014\u2014\u8FD9\u662F\u5168\u65B0\u4EA7\u7269\uFF0C\u5728\u5176\u4E2D\u4EA7\u51FA\u9996\u7248\u5185\u5BB9\uFF09\u3002`,
|
|
1089
|
-
`- \u6700\u7EC8\u4EA7\u7269\u53EA\u653E \`deliverable/\`\uFF1B\u4E34\u65F6\u6587\u4EF6\uFF08\u8349\u7A3F/\u811A\u672C/\u5B9E\u9A8C\uFF09\u653E\u5230**\u522B\u5904**\uFF0C\u522B\u7559\u5728 \`deliverable/\` \u91CC\u3002`,
|
|
1090
|
-
`- \u6539\u597D\u540E\u6574\u76EE\u5F55\u63D0\u4EA4\uFF1A\`oasis propose ${artifactId} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\``,
|
|
1091
|
-
` \u2192 \u7CFB\u7EDF\u81EA\u52A8\u843D\u5730\u4E3A\u65B0\u7248\u672C\uFF08**\u65E0\u9700 advance**\uFF09\uFF1B\u6574\u4E2A\u4EA4\u4ED8\u7269**\u771F\u6B63\u5B8C\u6574**\u4E86\u518D \`oasis conclude ${artifactId}\`\u3002`,
|
|
1092
|
-
...ctx.hasHead ? [`\uFF08\`deliverable/\` \u672C\u5C31\u662F head \u7684\u5B8C\u6574\u526F\u672C\u2014\u2014\u4F60\u4EA4\u7684\u4E00\u5B9A\u662F\u5B8C\u6574\u7248\uFF0C\u4E0D\u4F1A\u4E22\u5DF2\u6709\u5185\u5BB9\u3002\uFF09`] : [],
|
|
1093
|
-
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1094
|
-
];
|
|
1095
|
-
},
|
|
1096
|
-
integrateInstructions(ctx) {
|
|
1097
|
-
const parts = ctx.queuedPartLabels.map((p2) => `\`${p2}\``).join("\u3001") || "\uFF08\u961F\u5217\u4E3A\u7A7A\uFF09";
|
|
1098
|
-
return [
|
|
1099
|
-
`\u5404\u90E8\u4EF6\u4ECE**\u5171\u540C\u7956\u5148 H** \u5206\u5934\u4EA7\u51FA\u3001\u5404\u6539\u5404\u5757\uFF1A\u6BCF\u6761\u5185\u5BB9\u5728 \`parts/<\u540D>/CONTENT.md\`\uFF08\u6216\u5176\u5C55\u5F00\u6587\u4EF6\uFF09\u91CC\uFF08${parts}\uFF09\uFF0CH \u7684\u5185\u5BB9\u5728 \`deliverable/\`\uFF08\u4ECE\u96F6\u5206\u89E3\u5219\u4E3A\u7A7A\uFF09\u3002`,
|
|
1100
|
-
`\u628A\u5B83\u4EEC\u5408\u6210\u4E00\u4E2A\u5B8C\u6574\u7684\u6574\u5408\u7248**\u5C31\u5730\u5199\u8FDB \`deliverable/\`**\u2014\u2014**\u4EE5 H \u4E3A\u5E95**\u3001\u628A\u5404\u90E8\u4EF6\u6539\u52A8**\u5168\u5E76\u8FDB\u6765**\uFF08\u5355\u6587\u4EF6 \`deliverable/CONTENT.md\`\uFF0C\u591A\u6587\u4EF6\u94FA\u6210\u591A\u4E2A\u6587\u4EF6\uFF1B\u5927\u6587\u4EF6\u589E\u91CF\u5199\uFF1AWrite \u9AA8\u67B6 \u2192 Edit \u8FFD\u52A0\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
1101
|
-
`\`oasis integrate ${ctx.artifactId} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${ctx.artifactId}\`\u3002`,
|
|
1102
|
-
``,
|
|
1103
|
-
`**\u5FE0\u5B9E\u5408\u5E76\u3001\u522B\u4E22\u4EFB\u4F55\u90E8\u4EF6**\uFF1B\u63A5\u53E3/\u547D\u540D\u5BF9\u4E0D\u9F50\u5C31\u6309\u4E0A\u6E38\u89C4\u683C\u6821\u6B63\uFF0C\u8BA9 N \u4E2A\u90E8\u4EF6\u62FC\u6210\u4E00\u4E2A\u81EA\u6D3D\u6574\u4F53\u3002`
|
|
1104
|
-
];
|
|
1105
|
-
},
|
|
1106
|
-
submitInstruction: deliverableSubmit,
|
|
1107
|
-
collectionStrategy: { kind: "inline" },
|
|
1108
|
-
mergeMode: "oasis-queue"
|
|
1109
|
-
};
|
|
1110
|
-
codeHandler = {
|
|
1111
|
-
produceInstructions(ctx) {
|
|
1112
|
-
const { artifactId } = ctx;
|
|
1113
|
-
const repos = ctx.repos ?? [];
|
|
1114
|
-
const r0 = repos[0];
|
|
1115
|
-
if (ctx.part !== void 0) {
|
|
1116
|
-
const work = `feat/${slug(artifactId)}__${slug(ctx.part)}`;
|
|
1117
|
-
const feat2 = `feat/${slug(artifactId)}`;
|
|
1118
|
-
const dev = r0?.develop ?? "develop";
|
|
1119
|
-
return [
|
|
1120
|
-
`\u4F60\u4EA7\u51FA\u7684\u662F\u9879\u76EE **${ctx.projectName ?? "?"}** \u7684\u4EE3\u7801\u3001\u4E14\u53EA\u662F\u90E8\u4EF6 \`${ctx.part}\`\u2014\u2014\u5185\u5BB9\u6D3B\u5728 git \u91CC\u3002\u4F60**\u53EA\u7BA1\u4EA7\u51FA\u4F60\u8FD9\u5757\u3001push \u4F60\u81EA\u5DF1\u7684\u5DE5\u4F5C\u5206\u652F**\uFF1B\`oasis propose\` \u65F6**\u7CFB\u7EDF\u4F1A\u628A\u5B83\u5E72\u51C0\u5408\u8FDB\u5DE5\u5355\u5206\u652F \`${feat2}\`**\uFF08\u4E0D\u7528\u4F60\u624B\u52A8\u5408\u3001\u4E5F\u4E0D\u7528\u7B49 owner \u5408\uFF09\u3002`,
|
|
1121
|
-
`1. \`git clone ${r0?.remote ?? "<remote>"} repos/${r0?.id ?? "<id>"}\` \u2192 \`cd repos/${r0?.id ?? "<id>"}\` \u2192 \u4ECE\u4E3B\u5E72\u8D77\u4F60\u7684\u5DE5\u4F5C\u5206\u652F\uFF1A\`git checkout ${dev} && git checkout -b ${work}\``,
|
|
1122
|
-
`2. \u5B9E\u73B0\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u6539\u52A8\uFF08\u4E25\u5B88\u4E0A\u6E38\u63A5\u53E3\u7EA6\u5B9A\uFF09\u3001\u81EA\u67E5\u80FD\u6784\u5EFA/\u80FD\u8DD1\u3001\`git commit\``,
|
|
1123
|
-
`3. **\u53EA\u63A8\u4F60\u81EA\u5DF1\u7684\u5DE5\u4F5C\u5206\u652F**\uFF1A\`git push -u origin ${work}\`\uFF08**\u522B\u78B0 \`${feat2}\`**\u2014\u2014\u5408\u5E76\u4EA4\u7ED9\u7CFB\u7EDF\uFF09`,
|
|
1124
|
-
`4. \u56DE\u62A5\uFF1A\`oasis propose ${artifactId} --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD>"\`\uFF08\u7CFB\u7EDF\u628A \`${work}\` \u5E72\u51C0\u5408\u8FDB \`${feat2}\` \u518D\u6536\u96C6\uFF1B**\u82E5\u4E0E \`${feat2}\` \u51B2\u7A81\u4F1A\u5F53\u573A\u6253\u56DE**\u2014\u2014\u6309\u63D0\u793A \`git fetch && git rebase origin/${feat2}\` \u89E3\u5B8C\u51B2\u7A81\u3001\`git push -f origin ${work}\` \u540E\u91CD\u65B0 propose\uFF09`,
|
|
1125
|
-
`**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D conclude**\u3002\u5404\u90E8\u4EF6\u90FD\u5E76\u5B8C\u540E\u7531 owner \u9A8C\u6574\u4F53\u6536\u53E3\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1126
|
-
];
|
|
1127
|
-
}
|
|
1128
|
-
const feat = `feat/${slug(artifactId)}`;
|
|
1129
|
-
if (ctx.isFinalize) {
|
|
1130
|
-
const r02 = repos[0];
|
|
1131
|
-
return [
|
|
1132
|
-
`\u4F60\u662F **${ctx.projectName ?? "?"}** \u4EE3\u7801\u4EA4\u4ED8\u7269\u7684 owner\uFF0C\u6765**\u6536\u53E3**\uFF1A\u5404\u90E8\u4EF6\u5DF2\u5404\u81EA\u5E76\u5165**\u5DE5\u5355\u5206\u652F \`${feat}\`**\uFF08\u6BCF\u4E2A part \u5E72\u5B8C\u81EA\u5DF1 merge \u8FDB\u6765\u3001\u89E3\u4E86\u5404\u81EA\u51B2\u7A81\uFF09\u3002\u4F60**\u4E0D\u7528\u518D\u9010\u6761\u5408\u5E76**\uFF0C\u53EA\u9A8C\u6574\u4F53 + \u6536\u53E3\uFF1A`,
|
|
1133
|
-
`1. \`git clone ${r02?.remote ?? "<remote>"} repos/${r02?.id ?? "<id>"}\` \u2192 \`cd repos/${r02?.id ?? "<id>"} && git fetch && git checkout ${feat}\`\uFF08**\u662F\u5DF2\u5B58\u5728\u7684\u5DE5\u5355\u5206\u652F\u3001\u542B\u5404\u90E8\u4EF6\u5168\u90E8\u6539\u52A8**\uFF0C\u4E0D\u662F\u4ECE\u4E3B\u5E72\u65B0\u5EFA\uFF09\u3002\u591A\u4ED3\u5219\u5BF9\u6BCF\u4E2A\u78B0\u8FC7\u7684\u4ED3\u540C\u6837 checkout \`${feat}\`\u3002`,
|
|
1134
|
-
`2. **\u9A8C\u6574\u4F53\u80FD\u6784\u5EFA / \u80FD\u8DD1**\uFF08\u8FD9\u624D\u662F\u4F60 owner \u7684\u5224\u65AD\u6D3B\uFF09\uFF1B\u6709\u6B8B\u7559\u95EE\u9898\uFF08\u63A5\u53E3\u6CA1\u5BF9\u9F50 / \u6784\u5EFA\u5931\u8D25 / \u90E8\u4EF6\u8854\u63A5\u5904\u8981\u6536\u5C3E\uFF09\u2192 \u5C31\u5730\u4FEE\u3001\`git commit\`\u3001\`git push origin ${feat}\`\u3002`,
|
|
1135
|
-
`3. \`oasis propose ${artifactId} --reason "<\u6536\u53E3\u8BF4\u660E>"\`\uFF08\u7CFB\u7EDF\u4ECE\u5404\u4ED3 \`${feat}\` \u6536\u5168 {\u4ED3\u5E93\u2192\u63D0\u4EA4} = \u5168\u90E8\u4EF6\u6574\u5408\u6001\uFF09\u2192 \`oasis conclude ${artifactId}\`\uFF08conclude \u540E\u9010\u4ED3 gated \u5408\u8FDB\u4E3B\u5E72\uFF09\u3002`,
|
|
1136
|
-
``,
|
|
1137
|
-
`**\u4F60\u8FD9\u7EA7\u662F\u628A\u5173\u6574\u4F53\u81EA\u6D3D + \u6536\u53E3\u6210\u4EA4\u4ED8\u7248\uFF0C\u4E0D\u662F\u91CD\u65B0\u5B9E\u73B0**\u2014\u2014\u5404\u90E8\u4EF6\u7684\u5B9E\u73B0\u5DF2\u5728\u5B83\u4EEC\u5404\u81EA\u6536\u5C3E\u65F6\u5E76\u8FDB \`${feat}\` \u4E86\u3002**\u522B\u7528 \`oasis integrate\`**\uFF1A\u4EE3\u7801\u6536\u53E3\u5C31\u8D70 \`propose\`\uFF08git-native\uFF09\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1138
|
-
];
|
|
1139
|
-
}
|
|
1140
|
-
const repoLines = repos.map((r) => ` - \`${r.id}\`\uFF1A${r.remote ?? "<remote>"}\uFF08\u4E3B\u5E72 \`${r.develop}\`\uFF09`);
|
|
1141
|
-
const short = (s2) => s2.slice(0, 12);
|
|
1142
|
-
const versionLine = (() => {
|
|
1143
|
-
if (!(ctx.hasHead && ctx.headExternalRef)) return [];
|
|
1144
|
-
const ref2 = ctx.headExternalRef;
|
|
1145
|
-
if (ref2.trim().startsWith("{")) {
|
|
1146
|
-
try {
|
|
1147
|
-
const m2 = JSON.parse(ref2);
|
|
1148
|
-
const parts = Object.entries(m2).map(([id, sha2]) => `\`${id}\` @ \`${short(sha2)}\``);
|
|
1149
|
-
return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u5404\u4ED3\u4E3B\u5E72\uFF09\uFF1A${parts.join("\uFF0C")}\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
|
|
1150
|
-
} catch {
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u4E3B\u5E72\uFF09\uFF1A\`${repos[0]?.id ?? "<\u4E3B\u4ED3>"}\` @ \`${short(ref2)}\`\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
|
|
1154
|
-
})();
|
|
1155
|
-
return [
|
|
1156
|
-
`\u4F60\u4EA7\u51FA\u7684\u662F\u9879\u76EE **${ctx.projectName ?? "?"}** \u7684\u4EE3\u7801\u2014\u2014**\u5185\u5BB9\u76F4\u63A5\u6D3B\u5728 git \u4ED3\u5E93\u91CC**\uFF0C\u4F60\u50CF\u5F00\u53D1\u8005\u4E00\u6837\u5728 git \u91CC\u5E72\uFF0C\u4EA7\u7269\u4E0D\u8FDB Oasis \u6863\u6848\u67DC\u3002`,
|
|
1157
|
-
``,
|
|
1158
|
-
`\u672C\u9879\u76EE\u7684\u4EE3\u7801\u4ED3\u5E93\uFF08\u4F1E\u4ED3\uFF0C\u672C\u673A\u51ED\u8BC1\u5DF2\u914D\u597D\uFF1B**\u53EA\u52A8\u4F60\u9700\u8981\u6539\u7684\uFF0C\u4E0D\u78B0\u7684\u4E0D\u7528 clone**\uFF09\uFF1A`,
|
|
1159
|
-
...repoLines,
|
|
1160
|
-
`> \u636E\u4F60\u7684**\u4E0A\u6E38\u8F93\u5165**\u5224\u65AD\u672C\u5DE5\u5355\u8BE5\u843D\u5728**\u54EA\u4E2A**\u4ED3\uFF0C\u518D\u5BF9\u7167\u4E0A\u9762\u9879\u76EE\u73B0\u6709\u7684\u4ED3\uFF1A\u9700\u8981\u7684\u4ED3**\u5728\u6E05\u5355\u91CC** \u2192 \u53EA\u5728\u90A3\u4E2A\u4ED3\u91CC\u5E72\uFF1B**\u4E0D\u5728**\uFF08\u9879\u76EE\u6709\u522B\u7684\u4ED3\u3001\u4F46\u6CA1\u6709\u4F60\u9700\u8981\u7684\u90A3\u4E2A\uFF09\u2192 \u522B\u51D1\u5408\u7528\u522B\u7684\u4ED3\uFF0C\u7528 \`oasis gap ${artifactId} --desc "<\u7F3A\u54EA\u4E2A\u4ED3\u53CA\u7528\u9014>"\` \u62A5\u7F3A\u53E3\u3002`,
|
|
1161
|
-
...versionLine,
|
|
1162
|
-
``,
|
|
1163
|
-
`### \u5DE5\u4F5C\u6D41\u7A0B\uFF08git-native\uFF0C\u4F1E\u4ED3\uFF09`,
|
|
1164
|
-
`1. \u5BF9**\u6BCF\u4E2A\u4F60\u8981\u6539\u7684\u4ED3\u5E93**\uFF1A\`git clone <remote> repos/<id>\` \u2192 \`cd repos/<id> && git checkout <\u4E3B\u5E72> && git checkout -b ${feat}\``,
|
|
1165
|
-
`2. \u57FA\u4E8E \`inputs/\`\uFF08\u4E0A\u6E38\u89C4\u683C\uFF09\u5B9E\u73B0\u6539\u52A8\u2014\u2014clone \u4E0B\u6765\u7684\u4E3B\u5E72\u5DF2\u542B\u6B64\u524D\u5DF2\u5E76\u5165\u7684\u4EE3\u7801\uFF0C**\u5728\u5B83\u4E4B\u4E0A\u6539**`,
|
|
1166
|
-
`3. \u6BCF\u4E2A\u6539\u8FC7\u7684\u4ED3\u5E93\uFF1A\u81EA\u67E5\uFF08\u8BED\u6CD5/\u6784\u5EFA/\u80FD\u8DD1\uFF09\uFF0C\`git commit\`\uFF0C\`git push -u origin ${feat}\``,
|
|
1167
|
-
`4. \u56DE\u62A5 Oasis\uFF1A\`oasis propose ${artifactId} --reason "<\u4E00\u53E5\u8BDD>"\` \u2192 \`oasis conclude ${artifactId}\``,
|
|
1168
|
-
` **\u4E0D\u7528\u62A5 commit sha**\u2014\u2014\u7CFB\u7EDF\u4F1A\u53BB\u5404\u4ED3\u5E93\u7684 \`${feat}\` \u5206\u652F\u81EA\u52A8\u6536\u96C6\u4F60\u7684\u63D0\u4EA4\uFF0C\u62FC\u6210 {\u4ED3\u5E93\u2192\u63D0\u4EA4} \u6E05\u5355\uFF1B\u6CA1\u78B0\u7684\u4ED3\u5E93\uFF08\`${feat}\` \u65E0\u65B0\u63D0\u4EA4\uFF09\u4E0D\u8BA1\u5165\u3002`,
|
|
1169
|
-
``,
|
|
1170
|
-
`**\u4E0D\u8981\u63A8\u4E3B\u5E72\u3001\u4E0D\u8981\u81EA\u5DF1\u5408\u5E76**\u2014\u2014\u96C6\u6210\u7531\u7CFB\u7EDF\u5728 conclude \u540E\u9010\u4ED3\u628A\u5173\u5408\u5E76\u3002\u7248\u672C\u5386\u53F2 diff \u4F60\u81EA\u5DF1 \`git log -p\` \u5373\u53EF\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1171
|
-
];
|
|
1172
|
-
},
|
|
1173
|
-
integrateInstructions(ctx) {
|
|
1174
|
-
const { artifactId } = ctx;
|
|
1175
|
-
const r0 = ctx.repos?.[0];
|
|
1176
|
-
const feat = `feat/${slug(artifactId)}`;
|
|
1177
|
-
return [
|
|
1178
|
-
`\u8FD9\u662F\u4EE3\u7801\u2014\u2014\u5404\u90E8\u4EF6**\u5DF2\u81EA\u884C\u5E76\u5165\u5DE5\u5355\u5206\u652F \`${feat}\`**\uFF08\u6BCF\u4E2A part \u5E72\u5B8C\u81EA\u5DF1 merge \u8FDB\u6765\u3001\u89E3\u4E86\u5404\u81EA\u7684\u51B2\u7A81\uFF09\u3002\u4F60 owner **\u4E0D\u7528\u518D\u9010\u6761\u5408\u5E76**\uFF0C\u53EA\u9A8C\u6574\u4F53 + \u6536\u53E3\uFF1A`,
|
|
1179
|
-
`1. \`git clone ${r0?.remote ?? "<remote>"} repos/${r0?.id ?? "<id>"}\` \u2192 \`git checkout ${feat}\`\uFF0C**\u9A8C\u6574\u4F53\u80FD\u6784\u5EFA/\u80FD\u8DD1**\uFF08\u8FD9\u624D\u662F\u4F60 owner \u7684\u5224\u65AD\u6D3B\uFF09\u3002`,
|
|
1180
|
-
`2. \u82E5\u6709\u6B8B\u7559\u95EE\u9898\uFF08\u63A5\u53E3\u6CA1\u5BF9\u9F50\u3001\u6784\u5EFA\u5931\u8D25\u3001\u90E8\u4EF6\u8854\u63A5\u5904\u8981\u6536\u5C3E\uFF09\u2192 \u5C31\u5730\u4FEE\u3001\`git commit\`\u3001\`git push origin ${feat}\`\u3002`,
|
|
1181
|
-
`3. \`oasis integrate ${artifactId} --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${artifactId}\`\uFF08\u7CFB\u7EDF\u4ECE \`${feat}\` \u6536\u96C6\u6574\u5408\u7248\uFF1Bconclude \u540E\u9010\u4ED3\u540C\u6B65\u8FDB develop\uFF09\u3002`,
|
|
1182
|
-
``,
|
|
1183
|
-
`**\u4F60\u8FD9\u7EA7\u662F\u628A\u5173\u6574\u4F53\u81EA\u6D3D\u3001\u4E0D\u662F\u91CD\u65B0\u5408\u5E76**\u2014\u2014\u5408\u5E76\u5DF2\u7ECF\u5728\u5404\u90E8\u4EF6\u6536\u5C3E\u65F6\u5404\u81EA\u505A\u5B8C\u4E86\u3002`
|
|
1184
|
-
];
|
|
1185
|
-
},
|
|
1186
|
-
submitInstruction(ctx) {
|
|
1187
|
-
const id = ctx.artifactId;
|
|
1188
|
-
if (ctx.action === "integrate") {
|
|
1189
|
-
return `- \`oasis integrate ${id} --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2014\u2014 **\u6536\u53E3\u4E13\u7528**\uFF1A\u628A\u5DE5\u5355\u5206\u652F\u7684\u6574\u5408\u7248\u843D\u4E3A R\\*\uFF08\u7CFB\u7EDF\u4ECE git \u6536\u96C6\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002**\u7EDD\u4E0D\u8981\u7528 propose/advance \u4EA4\u96C6\u6210**\u3002`;
|
|
1190
|
-
}
|
|
1191
|
-
if (ctx.isPart) {
|
|
1192
|
-
return `- \`oasis propose ${id} --part <\u4F60\u7684\u90E8\u4EF6> --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u4EA7\u51FA\uFF08\u4EE3\u7801\uFF1A\u4F60 push \u4F60\u7684\u5DE5\u4F5C\u5206\u652F\uFF0C\u7CFB\u7EDF\u628A\u5B83\u5E72\u51C0\u5408\u8FDB\u5DE5\u5355\u5206\u652F\u518D\u6536\u96C6\uFF1B\u51B2\u7A81\u4F1A\u6253\u56DE\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002\`--part\` \u5FC5\u987B\u662F\u5206\u914D\u7ED9\u4F60\u7684\u90E8\u4EF6\u540D\u3002\u4EA7\u5B8C\u5373\u53EF\u6536\u5DE5\u3002`;
|
|
1193
|
-
}
|
|
1194
|
-
return `- \`oasis propose ${id} --reason "<\u4E00\u53E5\u8BDD>"\` \u2014\u2014 \u63D0\u4EA4\u4EA7\u7269\u7684\u65B0\u4E00\u7248\uFF08\u4EE3\u7801\uFF1A\u4F60\u5DF2 push \u5230\u5DE5\u5355\u5206\u652F\uFF0C\u7CFB\u7EDF\u4ECE\u5404\u4ED3\u6536\u96C6 {\u4ED3\u5E93\u2192\u63D0\u4EA4}\uFF1B\u89C1\u300C\u600E\u4E48\u63D0\u4EA4\u300D\uFF09\u3002\`--reason\` \u4E00\u53E5\u8BDD\u8BF4\u6E05\u6539\u4E86\u5565\u3002`;
|
|
1195
|
-
},
|
|
1196
|
-
collectionStrategy: { kind: "external-git" },
|
|
1197
|
-
mergeMode: "external-ff"
|
|
1198
|
-
// Phase B:code git-native——part 直接 FF、owner produce 收口(见 §9.1/§9.5)
|
|
1199
|
-
};
|
|
1200
|
-
mediaHandler = {
|
|
1201
|
-
produceInstructions(ctx) {
|
|
1202
|
-
const { artifactId } = ctx;
|
|
1203
|
-
if (ctx.part !== void 0) {
|
|
1204
|
-
return [
|
|
1205
|
-
`\u4F60\u4EA7\u51FA\u7684\u662F**\u5A92\u4F53**\u4EA4\u4ED8\u7269\u7684\u4E00\u4E2A\u90E8\u4EF6 \`${ctx.part}\`\uFF08\u89C6\u9891/\u97F3\u9891/\u56FE\u7B49\uFF09\u3002\u628A\u4F60\u8FD9\u4E2A\u90E8\u4EF6\u7684\u6210\u54C1\u6587\u4EF6\u5199\u8FDB\u672C\u5730\uFF0C\u7136\u540E**\u53EA\u8FD9\u4E00\u6B65**\uFF1A`,
|
|
1206
|
-
`\`oasis propose ${artifactId} --file <\u6210\u54C1\u6587\u4EF6> --part ${ctx.part} --reason "<\u4E00\u53E5\u8BDD>"\`\u3002**\u5230\u6B64\u4E3A\u6B62\u2014\u2014\u4E0D conclude**\uFF0C\u7B49\u5404\u90E8\u4EF6\u9F50\u4E86 owner \u6536\u53E3\u3002**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1207
|
-
];
|
|
1208
|
-
}
|
|
1209
|
-
return [
|
|
1210
|
-
ctx.hasHead ? `\u4F60\u7684\u4EA4\u4ED8\u7269\u5728 \`./deliverable/\`\uFF08\u5A92\u4F53\u6210\u54C1\uFF1A\u89C6\u9891/\u97F3\u9891/\u56FE\u7B49\uFF09\u2014\u2014\u5728\u5B83\u57FA\u7840\u4E0A\u66F4\u65B0/\u66FF\u6362\u3002` : `\u4F60\u7684\u4EA4\u4ED8\u7269\u76EE\u5F55\u662F \`./deliverable/\`\uFF08\u5F53\u524D\u4E3A\u7A7A\u2014\u2014\u4EA7\u51FA\u9996\u7248\u6210\u54C1\uFF09\u3002`,
|
|
1211
|
-
`\u628A**\u6E32\u67D3/\u5BFC\u51FA\u597D\u7684\u6210\u54C1\u6587\u4EF6**\u653E\u8FDB \`deliverable/\`\uFF08\u6309\u4EA4\u4ED8\u8981\u6C42\u7684\u683C\u5F0F\uFF0C\u5982 mp4/wav/png\uFF1B\u5927\u4E8C\u8FDB\u5236\u76F4\u63A5\u653E\uFF0C\u522B\u585E\u8FDB\u6587\u672C\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
1212
|
-
`\`oasis propose ${artifactId} --from-dir deliverable/ --reason "<\u4E00\u53E5\u8BDD\u7406\u7531>"\` \u2192 \u6574\u4F53\u5B8C\u6574\u4E86\u518D \`oasis conclude ${artifactId}\`\u3002`,
|
|
1213
|
-
`**\u522B\u7F16\u9020\uFF1B\u7F3A\u524D\u7F6E\uFF08\u811A\u672C/\u5206\u955C/\u7D20\u6750\u6CA1\u5C31\u7EEA\uFF09\u6309\u751F\u4EA7\u8005\u5B88\u5219\u8D70 oasis gap**\u3002`
|
|
1214
|
-
];
|
|
1215
|
-
},
|
|
1216
|
-
integrateInstructions(ctx) {
|
|
1217
|
-
const parts = ctx.queuedPartLabels.map((p2) => `\`${p2}\``).join("\u3001") || "\uFF08\u961F\u5217\u4E3A\u7A7A\uFF09";
|
|
1218
|
-
return [
|
|
1219
|
-
`\u5404\u90E8\u4EF6\u7684\u6210\u54C1\u5728 \`parts/<\u540D>/\`\uFF08${parts}\uFF09\u3002\u628A\u5B83\u4EEC\u6C47\u6210**\u6700\u7EC8\u6210\u54C1**\u653E\u8FDB \`deliverable/\`\uFF08\u6309\u4EA4\u4ED8\u683C\u5F0F\u3001\u987A\u5E8F/\u62FC\u63A5\u6B63\u786E\uFF09\uFF0C\u7136\u540E\uFF1A`,
|
|
1220
|
-
`\`oasis integrate ${ctx.artifactId} --from-dir deliverable/ --reason "<\u96C6\u6210\u8BF4\u660E>"\` \u2192 \`oasis conclude ${ctx.artifactId}\`\u3002**\u522B\u4E22\u4EFB\u4F55\u90E8\u4EF6**\u3002`
|
|
1221
|
-
];
|
|
1222
|
-
},
|
|
1223
|
-
submitInstruction: deliverableSubmit,
|
|
1224
|
-
collectionStrategy: { kind: "inline" },
|
|
1225
|
-
mergeMode: "oasis-queue"
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
});
|
|
1229
|
-
|
|
1230
1259
|
// ../core/src/diff.ts
|
|
1231
1260
|
function lineDiff(oldText, newText, capLines = 60) {
|
|
1232
1261
|
const a = oldText.split("\n");
|
|
@@ -1344,9 +1373,11 @@ var init_op_payloads = __esm({
|
|
|
1344
1373
|
});
|
|
1345
1374
|
|
|
1346
1375
|
// ../contract/src/artifact.ts
|
|
1376
|
+
var DELIVERY_SUMMARY_ARTIFACT_TYPE;
|
|
1347
1377
|
var init_artifact = __esm({
|
|
1348
1378
|
"../contract/src/artifact.ts"() {
|
|
1349
1379
|
"use strict";
|
|
1380
|
+
DELIVERY_SUMMARY_ARTIFACT_TYPE = "delivery-summary";
|
|
1350
1381
|
}
|
|
1351
1382
|
});
|
|
1352
1383
|
|
|
@@ -2044,6 +2075,7 @@ var init_kernel = __esm({
|
|
|
2044
2075
|
// §6.1/§6.3:工作流节点(auto/prereq/seed)默认 persistent;随手 scratch 默认 temp
|
|
2045
2076
|
persistence: args.persistence ?? (createdVia === "manual-spawn" ? "temp" : "persistent"),
|
|
2046
2077
|
createdVia,
|
|
2078
|
+
...args.isFinalOutput !== void 0 ? { isFinalOutput: args.isFinalOutput } : {},
|
|
2047
2079
|
inputs,
|
|
2048
2080
|
...args.title !== void 0 ? { title: args.title } : {},
|
|
2049
2081
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
@@ -2069,7 +2101,8 @@ var init_kernel = __esm({
|
|
|
2069
2101
|
}
|
|
2070
2102
|
/** routing 兜底(pending → 实派)与改派 */
|
|
2071
2103
|
async assignOwner(args) {
|
|
2072
|
-
this.artifactOrThrow(args.artifactId);
|
|
2104
|
+
const artifact = this.artifactOrThrow(args.artifactId);
|
|
2105
|
+
this.assertDeliverySummaryStructureMutable([artifact.id], args.actor, "\u6539\u6D3E\u8D1F\u8D23\u4EBA");
|
|
2073
2106
|
const payload = { owner: args.owner };
|
|
2074
2107
|
await this.commit(args.artifactId, args.actor, "assign_owner", args.artifactId, payload);
|
|
2075
2108
|
}
|
|
@@ -2232,6 +2265,28 @@ var init_kernel = __esm({
|
|
|
2232
2265
|
landed.push(head);
|
|
2233
2266
|
}
|
|
2234
2267
|
}
|
|
2268
|
+
/**
|
|
2269
|
+
* 冻结孤儿自愈(ADR 0069):把「本该自动落地却撞冻结没落」的 fresh 队首补落地。
|
|
2270
|
+
* 每落一条都对 **live model** 重算 `advanceableHead`(staleness 用落完上一条后的**新** head)——
|
|
2271
|
+
* 链式(Z.base=刚落的 X)顺序落完;竞争(Z.base=旧 head)落第一条后转 stale 自动停,不盲连落。
|
|
2272
|
+
* 尽力而为:撞显式冻结(`this.frozen`,纯投影看不见)或落地异常即停,留下次解冻 / serve 60s 循环兜底。
|
|
2273
|
+
* 钩子(`submitReview` 评审解冻后)与 serve 政策循环共用此方法。actor 记为 `actor:system`(系统协调动作)。
|
|
2274
|
+
*/
|
|
2275
|
+
async advanceOrphans(artifactId) {
|
|
2276
|
+
const landed = [];
|
|
2277
|
+
for (; ; ) {
|
|
2278
|
+
if (this.frozen.has(artifactId)) break;
|
|
2279
|
+
const rev = advanceableHead(this.model, this.schema, artifactId);
|
|
2280
|
+
if (!rev) break;
|
|
2281
|
+
try {
|
|
2282
|
+
await this.landHead(artifactId, SYSTEM_ACTOR, rev);
|
|
2283
|
+
landed.push(rev);
|
|
2284
|
+
} catch {
|
|
2285
|
+
break;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
return landed;
|
|
2289
|
+
}
|
|
2235
2290
|
/**
|
|
2236
2291
|
* group-commit(spec §5.5):队首 stale + 检查贵 + 多条竞争 → owner 把**整队 drain** 进一次集成。
|
|
2237
2292
|
* batch = 全部排队项(含排在 stale 队首之后的 fresh 项——严格 FIFO 下它们反正动不了,
|
|
@@ -2441,6 +2496,7 @@ var init_kernel = __esm({
|
|
|
2441
2496
|
await this.commit(args.artifactId, args.actor, "submit_review", attempt.head, payload, void 0, args.hand);
|
|
2442
2497
|
const status = attemptStatus(this.model, attempt);
|
|
2443
2498
|
if (status === "satisfied") await this.fireTriggers(args.artifactId);
|
|
2499
|
+
if (status !== "pending") await this.advanceOrphans(args.artifactId);
|
|
2444
2500
|
return { status };
|
|
2445
2501
|
}
|
|
2446
2502
|
async fireTriggers(artifactId) {
|
|
@@ -2757,6 +2813,7 @@ var init_kernel = __esm({
|
|
|
2757
2813
|
this.ensureActive(args.artifactId);
|
|
2758
2814
|
const artifact = this.artifactOrThrow(args.artifactId);
|
|
2759
2815
|
this.artifactOrThrow(args.to);
|
|
2816
|
+
this.assertDeliverySummaryStructureMutable([args.artifactId, args.to], args.actor, "\u4FEE\u6539\u8FDE\u7EBF");
|
|
2760
2817
|
if (args.to === args.artifactId) throw new KernelError("\u4E0D\u80FD\u4F9D\u8D56\u81EA\u5DF1");
|
|
2761
2818
|
if (artifact.inputs.some((e) => e.to === args.to)) {
|
|
2762
2819
|
throw new KernelError(`\u4F9D\u8D56\u8FB9\u5DF2\u5B58\u5728: ${args.artifactId} \u2192 ${args.to}`);
|
|
@@ -2829,7 +2886,7 @@ var init_kernel = __esm({
|
|
|
2829
2886
|
const keep = args.preserveEdgesAmong;
|
|
2830
2887
|
for (const edge of this.edgesTouching(args.artifactId)) {
|
|
2831
2888
|
if (keep?.has(edge.artifactId) && keep.has(edge.to)) continue;
|
|
2832
|
-
await this.
|
|
2889
|
+
await this.unlinkInputUnchecked({ artifactId: edge.artifactId, to: edge.to, actor: args.actor });
|
|
2833
2890
|
}
|
|
2834
2891
|
}
|
|
2835
2892
|
const payload = {
|
|
@@ -2924,6 +2981,11 @@ var init_kernel = __esm({
|
|
|
2924
2981
|
}
|
|
2925
2982
|
/** 治理断边(§11.3/§11.6:边即可见性拓扑——产线用法应经 Intervention 获得 preview) */
|
|
2926
2983
|
async unlinkInput(args) {
|
|
2984
|
+
this.assertDeliverySummaryStructureMutable([args.artifactId, args.to], args.actor, "\u4FEE\u6539\u8FDE\u7EBF");
|
|
2985
|
+
await this.unlinkInputUnchecked(args);
|
|
2986
|
+
}
|
|
2987
|
+
/** cancel 级联仍须能机械断边;这条内部路径保留原调用者审计身份,但不开放给人工命令。 */
|
|
2988
|
+
async unlinkInputUnchecked(args) {
|
|
2927
2989
|
this.ensureActive(args.artifactId);
|
|
2928
2990
|
const artifact = this.artifactOrThrow(args.artifactId);
|
|
2929
2991
|
if (!artifact.inputs.some((e) => e.to === args.to)) {
|
|
@@ -2932,6 +2994,25 @@ var init_kernel = __esm({
|
|
|
2932
2994
|
const payload = { to: args.to };
|
|
2933
2995
|
await this.commit(args.artifactId, args.actor, "unlink_input", args.artifactId, payload);
|
|
2934
2996
|
}
|
|
2997
|
+
assertDeliverySummaryStructureMutable(ids, actor, action) {
|
|
2998
|
+
if (actor === SYSTEM_ACTOR) return;
|
|
2999
|
+
const summary = ids.map((id) => this.model.artifacts.get(id)).find((a) => a?.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
3000
|
+
if (!summary) return;
|
|
3001
|
+
throw new KernelError(
|
|
3002
|
+
`\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u4EBA\u5DE5${action}\uFF08${summary.id}\uFF09\u3002\u8BF7\u4FEE\u6539\u5176\u5B83\u4E1A\u52A1\u8282\u70B9\u5E76\u91CD\u65B0\u89C4\u5212\u672B\u7AEF\u95ED\u73AF\u3002`
|
|
3003
|
+
);
|
|
3004
|
+
}
|
|
3005
|
+
/** 已落图的交付汇总只允许系统改结构;建单 plan 中首次原子 spawn 不受影响。 */
|
|
3006
|
+
assertDeliverySummaryIntervention(plan, actor) {
|
|
3007
|
+
if (actor === SYSTEM_ACTOR) return;
|
|
3008
|
+
for (const op of plan.ops) {
|
|
3009
|
+
if (op.action === "edit" || op.action === "assign") {
|
|
3010
|
+
this.assertDeliverySummaryStructureMutable([op.artifactId], actor, op.action === "edit" ? "\u7F16\u8F91\u8282\u70B9\u5B9A\u4E49" : "\u6539\u6D3E\u8D1F\u8D23\u4EBA");
|
|
3011
|
+
} else if (op.action === "link" || op.action === "unlink") {
|
|
3012
|
+
this.assertDeliverySummaryStructureMutable([op.artifactId, op.to], actor, "\u4FEE\u6539\u8FDE\u7EBF");
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
2935
3016
|
// ── Intervention(§11.7):结构变更的原子单位 ────────────────────────────
|
|
2936
3017
|
/**
|
|
2937
3018
|
* 预检(②终态校验 + ③advisory + ④爆炸半径)。preview 白送:
|
|
@@ -3127,6 +3208,7 @@ ${res.candidates.map((c) => ` - ${c.type}:${c.title ?? "(\u65E0title)"} \u2192
|
|
|
3127
3208
|
*/
|
|
3128
3209
|
async applyIntervention(plan, baseSeqs, actor) {
|
|
3129
3210
|
plan = this.resolveInterventionRefs(plan);
|
|
3211
|
+
this.assertDeliverySummaryIntervention(plan, actor);
|
|
3130
3212
|
const { changeClass, nonMonotonicOps } = classifyIntervention(plan);
|
|
3131
3213
|
if (changeClass === "C" && !isHumanActor(actor)) {
|
|
3132
3214
|
throw new KernelError(
|
|
@@ -3226,6 +3308,7 @@ ${res.candidates.map((c) => ` - ${c.type}:${c.title ?? "(\u65E0title)"} \u2192
|
|
|
3226
3308
|
workspace: op.workspace ?? "ws:default",
|
|
3227
3309
|
persistence: "persistent",
|
|
3228
3310
|
createdVia: isPrereqFill(spawnId) ? "prereq" : "manual-spawn",
|
|
3311
|
+
...op.isFinalOutput !== void 0 ? { isFinalOutput: op.isFinalOutput } : {},
|
|
3229
3312
|
...op.title !== void 0 ? { title: op.title } : {},
|
|
3230
3313
|
...op.description !== void 0 ? { description: op.description } : {},
|
|
3231
3314
|
...op.docType !== void 0 ? { docType: op.docType } : {},
|
|
@@ -3371,9 +3454,9 @@ ${res.candidates.map((c) => ` - ${c.type}:${c.title ?? "(\u65E0title)"} \u2192
|
|
|
3371
3454
|
/** sealed = 不再接受变更(§7.1);annotation / reject 不在此列(结案后补注与清理仍允许) */
|
|
3372
3455
|
ensureActive(artifactId) {
|
|
3373
3456
|
const lifecycle = lifecycleOf(this.model, artifactId);
|
|
3374
|
-
if (lifecycle
|
|
3375
|
-
|
|
3376
|
-
}
|
|
3457
|
+
if (lifecycle === "active") return;
|
|
3458
|
+
const why = lifecycle === "sealed:frozen" ? "\u6B64\u8282\u70B9\u5DF2\u88AB\u51BB\u7ED3\uFF08sealed:frozen\uFF09\uFF1A\u4FDD\u7559\u73B0\u6709\u4EA7\u51FA\u3001\u6682\u505C\u4E00\u5207\u6539\u52A8\uFF0C\u4E0D\u63A5\u53D7\u4EFB\u4F55\u63D0\u4EA4\u6216\u4FEE\u6539\u3002\u8981\u7EE7\u7EED\u987B\u7531\u4EBA\u5728\u6539\u56FE\u91CC reopen \u89E3\u51BB\uFF1B\u4F60\u82E5\u662F agent\u3001\u786E\u6709\u5FC5\u8981\u6539\uFF0C\u8BF7\u63D0 gap \u8BF4\u660E\u8BC9\u6C42" : lifecycle === "sealed:cancelled" ? "\u6B64\u8282\u70B9\u5DF2\u88AB\u53D6\u6D88\u5E9F\u5F03\uFF08sealed:cancelled\uFF09\uFF1A\u4F9D\u8D56\u8FB9\u5DF2\u65AD\uFF0C\u4E0D\u518D\u63A5\u53D7\u4EFB\u4F55\u4FEE\u6539" : lifecycle === "sealed:accepted" ? "\u6B64\u8282\u70B9\u5DF2\u9A8C\u6536\u7ED3\u6848\uFF08sealed:accepted\uFF09\uFF1A\u4E0D\u518D\u63A5\u53D7\u4FEE\u6539\uFF1B\u786E\u9700\u6539\u52A8\u8BF7\u5148 reopen" : `artifact is ${lifecycle}, no further changes`;
|
|
3459
|
+
throw new KernelError(`${why}: ${artifactId}`);
|
|
3377
3460
|
}
|
|
3378
3461
|
artifactOrThrow(id) {
|
|
3379
3462
|
const artifact = this.model.artifacts.get(id);
|
|
@@ -3842,6 +3925,37 @@ async function assembleContext(args) {
|
|
|
3842
3925
|
...partSpec?.deps && partSpec.deps.length > 0 ? [`- \u4F60\u4F9D\u8D56\u7684\u5144\u5F1F\u90E8\u4EF6\uFF08\u5DF2\u5148\u4EA7\u51FA\uFF0C\u89C1\u90BB\u57DF/\u5F53\u524D\u5185\u5BB9\uFF09\uFF1A${partSpec.deps.join("\u3001")}`] : [],
|
|
3843
3926
|
`- \u4E25\u5B88\u4E0A\u6E38\u7EA6\u5B9A\u7684\u63A5\u53E3/\u547D\u540D\uFF0C\u5404\u90E8\u4EF6\u624D\u62FC\u5F97\u8D77\u6765\u3002\u96C6\u6210\u7531\u7CFB\u7EDF\u5728\u5404\u90E8\u4EF6\u9F50\u4E86\u540E\u6536\u53E3\uFF0C**\u4E0D\u5F52\u4F60\u505A**\u3002`
|
|
3844
3927
|
] : [],
|
|
3928
|
+
// integrate:把「当初为什么这么切」铺给收口人。此前它只拿到部件**名字**(handler 的 queuedPartLabels)
|
|
3929
|
+
// 与各部件的产出内容,看不到 spec——而边界("只改你名下目录 X")、契约("面向契约类型编程、测试用 fake")、
|
|
3930
|
+
// 逐条交付清单全在 `add_part.payload.spec` 里(实测每条上千字)。少了它,integrate 只能看着几坨产出猜:
|
|
3931
|
+
// 某块是不是越界改了别人的文件、合起来 typecheck 红是预期内还是真 bug、某块是不是压根没做完。
|
|
3932
|
+
// 这些是 owner 当初**外化**过的决策依据,本该每轮递给它——不该靠续会话去继承(best-effort、换节点即失效、
|
|
3933
|
+
// 冷启动 runtime 不支持,且 whole produce 那轮结束时各部件**尚未动工**,续过来反而是陈旧心智)。
|
|
3934
|
+
// 守卫 queuedParts.length:队列为空不是真正的 integrate 场景(computeIntegrateJobs 只在有排队产出时派发),
|
|
3935
|
+
// 此时把所有已声明部件列成「缺块」既无意义又污染 TASK.md。
|
|
3936
|
+
...integrating && queuedParts.length > 0 ? (() => {
|
|
3937
|
+
const defined = artifact.parts ?? [];
|
|
3938
|
+
const queuedNames = new Set(queuedParts.map((p2) => p2.part));
|
|
3939
|
+
const missing = defined.filter((d) => !queuedNames.has(d.name));
|
|
3940
|
+
const lines = [``, `**\u672C\u4EA7\u7269\u5F53\u521D\u88AB\u5E76\u884C\u5206\u89E3\u6210 ${defined.length || queuedParts.length} \u4E2A\u90E8\u4EF6\uFF0C\u4F60\u73B0\u5728\u8981\u628A\u5B83\u4EEC\u5408\u6210\u5B8C\u6574\u7684\u4E00\u7248\u3002\u5F53\u521D\u6BCF\u5757\u662F\u8FD9\u4E48\u5207\u7684\uFF1A**`];
|
|
3941
|
+
for (const q of queuedParts) {
|
|
3942
|
+
const def = defined.find((d) => d.name === q.part);
|
|
3943
|
+
lines.push(``, `### \u90E8\u4EF6 \`${q.part}\`${def?.deps?.length ? `\uFF08\u4F9D\u8D56\uFF1A${def.deps.join("\u3001")}\uFF09` : ""}`);
|
|
3944
|
+
lines.push(`- \u5185\u5BB9\u5728 \`parts/${slug2(q.part)}/\``);
|
|
3945
|
+
lines.push(
|
|
3946
|
+
def?.spec ? `- \u5F53\u521D\u8981\u6C42\u5B83\u4EA7\u51FA\uFF1A
|
|
3947
|
+
${def.spec.split("\n").map((l) => ` > ${l}`).join("\n")}` : `- \uFF08\u65E0 spec \u8BB0\u5F55${def ? "" : "\uFF1B\u8BE5 revision \u672A\u6807 part\uFF0C\u6309\u5185\u5BB9\u81EA\u884C\u5224\u65AD"}\uFF09`
|
|
3948
|
+
);
|
|
3949
|
+
}
|
|
3950
|
+
for (const m2 of missing) {
|
|
3951
|
+
lines.push(``, `### \u26A0 \u90E8\u4EF6 \`${m2.name}\` \u2014\u2014 **\u5B9A\u4E49\u4E86\u4F46\u6CA1\u6709\u4EA7\u51FA\u6392\u961F**`);
|
|
3952
|
+
if (m2.spec) lines.push(`- \u5F53\u521D\u8981\u6C42\u5B83\u4EA7\u51FA\uFF1A
|
|
3953
|
+
${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
3954
|
+
lines.push(`- **\u7F3A\u8FD9\u4E00\u5757**\uFF1A\u5148\u5224\u65AD\u80FD\u4E0D\u80FD\u5408\uFF1B\u4E0D\u80FD\u5C31\u522B\u786C\u5408\uFF0C\`oasis add-revision\` \u628A\u5B83\u6D3E\u51FA\u53BB\u8865\u3002`);
|
|
3955
|
+
}
|
|
3956
|
+
lines.push(``, `\u5408\u5E76\u65F6\u6309\u5404\u5757\u5F53\u521D\u7EA6\u5B9A\u7684\u8FB9\u754C\u4E0E\u63A5\u53E3\u5BF9\u9F50\uFF1B\u67D0\u5757\u6CA1\u505A\u5230\u5B83 spec \u8981\u6C42\u7684\uFF0C\u4F60\u53EF\u4EE5 \`oasis add-revision\` \u6253\u56DE\u53BB\u8865\uFF0C\u4E0D\u5FC5\u81EA\u5DF1\u66FF\u5B83\u5199\u3002`);
|
|
3957
|
+
return lines;
|
|
3958
|
+
})() : [],
|
|
3845
3959
|
``,
|
|
3846
3960
|
`## \u600E\u4E48\u63D0\u4EA4`,
|
|
3847
3961
|
``,
|
|
@@ -3867,17 +3981,15 @@ async function assembleContext(args) {
|
|
|
3867
3981
|
})
|
|
3868
3982
|
];
|
|
3869
3983
|
})() : canvasMode ? [
|
|
3870
|
-
|
|
3984
|
+
// 内核只出「你产什么 + 内核权威锚点」——**设计工作流散文全在你的人设(identity/AGENTS.md「产出流程」)**,
|
|
3985
|
+
// 那是单一真源、改它=改配置不发版(提案 design-conversational-driving 治本,2026-07-17)。这里不重复正文,
|
|
3986
|
+
// 只钉住内核唯一不能漂的两件事:真实 artifactId、缺前置的逃生口 gap。
|
|
3987
|
+
`\u4F60\u8D1F\u8D23 **design \u4EA7\u7269 \`${artifactId}\`**\uFF0C\u8FD0\u884C\u5728**\u901A\u7528\u8FD0\u884C\u65F6**\u4E0A\u2014\u2014\u4F60\u662F\u7532\u65B9\u8BBE\u8BA1\u8D1F\u8D23\u4EBA\uFF0C\u591A\u8F6E\u5BF9\u8BDD\u9A71\u52A8**\u534F\u4F5C\u753B\u677F\u5F15\u64CE**\u6253\u78E8\u754C\u9762\u7A3F\u3002`,
|
|
3871
3988
|
``,
|
|
3872
|
-
|
|
3873
|
-
` oasis design chat ${artifactId} --turn continue --message "<\u8BFB\u5B8C\u4E0A\u4E00\u7248\u4EA7\u7269\u540E\uFF0C\u8981\u6539\u54EA\u91CC>"`,
|
|
3989
|
+
`**\u5B8C\u6574\u5DE5\u4F5C\u6D41\uFF08\u600E\u4E48\u53D6\u8D27/\u8D77\u8F6E/\u8BFB\u4EA7\u7269/\u4EA4\u7A3F/\u522B\u624B\u6539\u677F\u6587\u4EF6\u2026\uFF09\u89C1\u4F60\u7684\u4EBA\u8BBE \`identity/AGENTS.md\` \u7684\u300C\u4EA7\u51FA\u6D41\u7A0B\uFF08design \u4EA7\u7269\uFF09\u300D**\u2014\u2014\u628A\u91CC\u9762 \`<artifactId>\` \u90FD\u6362\u6210\u672C\u4EA7\u7269 \`${artifactId}\`\u3002`,
|
|
3874
3990
|
``,
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
`2. **\u8BFB\u4EA7\u7269**\uFF1A\u547D\u4EE4\u8DD1\u5B8C\u4F1A\u6253\u5370\u672C\u8F6E\u4EA4\u4ED8\u7684 artifact \u6E05\u5355\uFF08\`index.html\` / \`acceptance.md\` \u53CA status\uFF09\u2014\u2014**\u6253\u5F00 \`index.html\` \u771F\u8BFB\u4E00\u904D**\uFF0C\u5BF9\u7167 \`DESIGN_BRIEF.md\` \u4E0E \`inputs/\` \u6838\uFF1A\u6570\u636E\u5BF9\u4E0D\u5BF9\uFF1F\u72B6\u6001/\u8FB9\u754C\u6001\u5168\u4E0D\u5168\uFF1F\u6709\u6CA1\u6709\u7F16\u9020\uFF1F`,
|
|
3878
|
-
`3. **\u51B3\u5B9A**\uFF1A\u591F\u597D \u2192 \`oasis propose ${artifactId} --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"\` \u4EA4\u7A3F\uFF1B\u8FD8\u5DEE \u2192 \`oasis design chat ${artifactId} --turn continue --message "<\u5177\u4F53\u6539\u4EC0\u4E48>"\` **\u518D\u4E00\u8F6E**\u6253\u78E8\uFF1B\u9047\u5230**\u4F60\u4E5F\u5B9A\u4E0D\u4E86\u7684\u53D6\u820D**\uFF08\u5982\u67D0\u6001\u7528\u54EA\u4E2A\u4E70\u5BB6\u627F\u8F7D\uFF09\u2192 \u5199\u8FDB acceptance.md \u7684\u300C\u5F00\u653E\u95EE\u9898\u300D\uFF0C\u6216 \`oasis gap ${artifactId} --desc "<\u8981\u4EBA\u5B9A\u4EC0\u4E48>"\` \u5192\u6CE1\u7ED9\u4EBA\uFF1B`,
|
|
3879
|
-
`- **\u522B\u628A\u7B2C\u4E00\u7248\u76F2\u76EE propose**\u2014\u2014\u5148\u8BFB\u3001\u5148\u81EA\u68C0\u3001\u4E0D\u591F\u5C31\u518D\u4E00\u8F6E\uFF0C\u6BD4 propose \u51FA\u53BB\u88AB\u4E0B\u6E38\u6253\u56DE\u3001\u7ED5\u6574\u5F20\u56FE\u4E00\u5708\u4FBF\u5B9C\u5F97\u591A\uFF1B`,
|
|
3880
|
-
`- \u5F15\u64CE\u4E00\u8F6E\u8981 13\u201344 \u5206\u949F\uFF08\u771F\u5728\u753B\u5E03\u4E0A\u753B\uFF09\uFF0C\`oasis design chat\` \u5185\u90E8\u5DF2\u8F6E\u8BE2 30 \u5206\u949F\u3002**\u522B\u7528 \`timeout\` \u5305\u5B83\u3001\u522B 15 \u5206\u949F\u5C31\u5F53\u5B83\u5931\u8D25**\u2014\u2014\u8010\u5FC3\u7B49\u5B83\u8DD1\u5B8C\uFF1B`,
|
|
3991
|
+
`\u5185\u6838\u53EA\u5728\u6B64\u9489\u4E24\u6761\u4E0D\u53EF\u6F02\u7684\uFF1A`,
|
|
3992
|
+
`- **\u4EA4\u7A3F\u8D70 \`oasis propose ${artifactId} --from-dir <\u76EE\u5F55> --reason "\u2026"\`**\uFF08proposed \u624D\u8FDB\u7248\u672C\u53F2\u3001\u4E0B\u6E38\u624D\u62FF\u5F97\u5230\uFF1B\u4E0D propose = head \u4ECD \u2205\uFF09\uFF1B`,
|
|
3881
3993
|
`- \u7F3A**\u8FD8\u4E0D\u5B58\u5728\u7684\u4E0A\u6E38\u524D\u7F6E**\u505A\u4E0D\u4E0B\u53BB \u2192 \`oasis gap ${artifactId} --desc "<\u7F3A\u4EC0\u4E48>"\` \u62A5\u7F3A\u53E3\u540E\u6536\u5DE5\u3002`
|
|
3882
3994
|
] : (() => {
|
|
3883
3995
|
const codeRepo = args.codeRepo ?? null;
|
|
@@ -3933,7 +4045,7 @@ async function assembleContext(args) {
|
|
|
3933
4045
|
``,
|
|
3934
4046
|
...canvasMode ? [
|
|
3935
4047
|
`## \u5173\u4E8E\u5DE5\u5177`,
|
|
3936
|
-
`oasis CLI \u5DF2\u6CE8\u5165\uFF08\`OASIS_SERVER\` / \`OASIS_TOKEN\` \u5C31\u7EEA\uFF0C\u65E0\u9700\u914D\u7F6E\uFF09\
|
|
4048
|
+
`oasis CLI \u5DF2\u6CE8\u5165\uFF08\`OASIS_SERVER\` / \`OASIS_TOKEN\` \u5C31\u7EEA\uFF0C\u65E0\u9700\u914D\u7F6E\uFF09\u3002\u8BBE\u8BA1\u5DE5\u4F5C\u6D41\u7528\u54EA\u4E9B\u547D\u4EE4\u3001\u600E\u4E48\u7528\uFF0C\u89C1\u4F60\u7684\u4EBA\u8BBE \`identity/AGENTS.md\` \u7684\u300C\u4EA7\u51FA\u6D41\u7A0B\u300D\u3002\u8BBE\u8BA1\u9700\u6C42\u89C1\u672C\u76EE\u5F55 \`DESIGN_BRIEF.md\`\uFF0C\u4E0A\u6E38\u8F93\u5165\u5728 \`inputs/\`\u3002`
|
|
3937
4049
|
] : commandReference({
|
|
3938
4050
|
artifactId,
|
|
3939
4051
|
action: args.action ?? "produce",
|
|
@@ -3961,14 +4073,14 @@ async function assembleContext(args) {
|
|
|
3961
4073
|
(s2) => `- ${s2.upstream}: pin=${s2.pinned ?? "\u2205"} \u2192 \u6700\u65B0 ${s2.latest}${s2.upstreamCancelled ? "\uFF08\u26A0 \u4E0A\u6E38\u5DF2 cancelled\uFF09" : ""}`
|
|
3962
4074
|
)
|
|
3963
4075
|
] : [],
|
|
3964
|
-
//
|
|
4076
|
+
// 画板模式:守则正文(甲方多轮/读产物再交/喂真数据/别本地手改板…)在人设 identity/AGENTS.md,此处不重复。
|
|
4077
|
+
// 只留内核锚点:你产哪一个、不归你定的别硬编。你在通用 runtime、CLI 齐全(design chat/propose/gap 都能用)。
|
|
3965
4078
|
...canvasMode ? [
|
|
3966
4079
|
``,
|
|
3967
4080
|
`## \u751F\u4EA7\u8005\u5B88\u5219\uFF08\u753B\u677F\u7248\uFF09`,
|
|
3968
|
-
`- \
|
|
4081
|
+
`- **\u5B8C\u6574\u8BBE\u8BA1\u5DE5\u4F5C\u6D41\u5B88\u5219\u89C1\u4F60\u7684\u4EBA\u8BBE \`identity/AGENTS.md\`\u300C\u4EA7\u51FA\u6D41\u7A0B\u300D**\uFF08\u600E\u4E48\u53D6\u8D27/\u8D77\u8F6E/\u8BFB\u4EA7\u7269/\u4EA4\u7A3F/\u522B\u624B\u6539\u677F\u6587\u4EF6\u7B49\uFF09\u3002`,
|
|
3969
4082
|
`- \u4F60\u53EA\u4EA7**\u8FD9\u4E00\u4E2A**\u8BBE\u8BA1\u4EA7\u7269\uFF1B**\u4E0D\u5F52\u4F60\u5B9A\u7684\u51B3\u7B56\u522B\u786C\u7F16**\uFF08\u4F1A\u88AB\u6253\u56DE\uFF09\u2014\u2014\u62FF\u4E0D\u51C6\u7684\u53D6\u820D\u5199\u8FDB acceptance.md \u7684\u300C\u5F00\u653E\u95EE\u9898\u300D\uFF0C\u6216 \`oasis gap\` \u5192\u6CE1\u7ED9\u4EBA\u3002`,
|
|
3970
4083
|
`- \u5FE0\u5B9E\u4E8E task-context/ \u91CC\u7684\u4E0A\u6E38\u8F93\u5165\uFF08PRD/\u603B\u7EB2\uFF09\uFF1B\u4E0E\u4E0A\u6E38\u51B2\u7A81\u5904\u4EE5\u4E0A\u6E38\u4E3A\u51C6\uFF0C\u5E76\u5728\u5F00\u653E\u95EE\u9898\u91CC\u6807\u6CE8\u5F02\u8BAE\u3002`,
|
|
3971
|
-
`- \u771F\u5B9E\u793A\u4F8B\u6570\u636E\uFF08\u4EA7\u54C1/\u4E70\u5BB6/\u8BA2\u5355\u7B49\uFF09**\u5FC5\u987B\u5728 \`--message\` \u91CC\u5582\u7ED9\u5F15\u64CE**\u2014\u2014\u5B83\u62FF\u4E0D\u5230\u7684\u4E1C\u897F\u4F1A\u81EA\u5DF1\u7F16\uFF0C\u522B\u8BA9\u5B83\u66FF\u4F60\u9020\u6570\u636E\u3002`,
|
|
3972
4084
|
`- \u754C\u9762\u7A3F\u5FC5\u987B**\u771F\u5B9E\u53EF\u6253\u5F00**\uFF08\u81EA\u5305\u542B HTML\uFF09\uFF0C\u522B\u4EA4\u793A\u610F\u63CF\u8FF0\u3002`
|
|
3973
4085
|
] : [],
|
|
3974
4086
|
// review 会话不产出、不该给生产者守则(它只投票,守则的 propose/conclude/gap/add-revision 全不适用)
|
|
@@ -135279,6 +135391,100 @@ var init_workorder_drafts = __esm({
|
|
|
135279
135391
|
});
|
|
135280
135392
|
|
|
135281
135393
|
// ../server/src/governance/draft-edit.ts
|
|
135394
|
+
function assertNotDeliverySummary(draft, ids, action) {
|
|
135395
|
+
const summary = ids.map((id) => spawnById(draft, id)).find((o) => o?.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
135396
|
+
if (!summary) return;
|
|
135397
|
+
throw new Error(`\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u4EBA\u5DE5${action}\uFF1B\u8BF7\u4FEE\u6539\u5176\u5B83\u4E1A\u52A1\u8282\u70B9\uFF0C\u7CFB\u7EDF\u4F1A\u91CD\u65B0\u5224\u65AD\u672B\u7AEF\u95ED\u73AF\u3002`);
|
|
135398
|
+
}
|
|
135399
|
+
function reconcileDeliverySummaryPlan(draft) {
|
|
135400
|
+
const summaries = spawnOps(draft).filter((op) => op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
135401
|
+
const business = spawnOps(draft).filter((op) => op.type !== "brief" && op.type !== DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
135402
|
+
const businessIds = new Set(business.map((op) => op.id));
|
|
135403
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
135404
|
+
for (const op of business) {
|
|
135405
|
+
for (const edge of op.inputs ?? []) if (businessIds.has(edge.to)) consumed.add(edge.to);
|
|
135406
|
+
}
|
|
135407
|
+
for (const op of draft.plan.ops) {
|
|
135408
|
+
if (op.action === "link" && businessIds.has(op.artifactId) && businessIds.has(op.to)) consumed.add(op.to);
|
|
135409
|
+
}
|
|
135410
|
+
const terminals = business.filter((op) => !consumed.has(op.id));
|
|
135411
|
+
const finals = business.filter((op) => op.isFinalOutput === true);
|
|
135412
|
+
const directFinal = finals.length === 1 && terminals.length === 1 && finals[0].id === terminals[0].id;
|
|
135413
|
+
if (business.length === 0 || directFinal) {
|
|
135414
|
+
const summaryIds2 = new Set(summaries.map((op) => op.id));
|
|
135415
|
+
draft.plan.ops = draft.plan.ops.filter((op) => {
|
|
135416
|
+
if (op.action === "spawn" && op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE) return false;
|
|
135417
|
+
if (op.action === "link" || op.action === "unlink") return !summaryIds2.has(op.artifactId) && !summaryIds2.has(op.to);
|
|
135418
|
+
if (op.action === "annotate" || op.action === "edit" || op.action === "assign") return !summaryIds2.has(op.artifactId);
|
|
135419
|
+
return true;
|
|
135420
|
+
});
|
|
135421
|
+
return;
|
|
135422
|
+
}
|
|
135423
|
+
const existing = summaries[0];
|
|
135424
|
+
const used = new Set(spawnOps(draft).map((op) => op.id));
|
|
135425
|
+
const brief = spawnOps(draft).find((op) => op.type === "brief");
|
|
135426
|
+
const manager = typeof brief?.fields?.["manager"] === "string" ? brief.fields["manager"] : void 0;
|
|
135427
|
+
const owner = existing?.owner ?? manager ?? (draft.draftedBy.startsWith("actor:agent:") ? draft.draftedBy : PENDING_UNASSIGNED);
|
|
135428
|
+
const summary = {
|
|
135429
|
+
action: "spawn",
|
|
135430
|
+
id: existing?.id ?? deriveArtifactId(DELIVERY_SUMMARY_ARTIFACT_TYPE, draft.workspace, "\u4EA4\u4ED8\u6C47\u603B", used),
|
|
135431
|
+
type: DELIVERY_SUMMARY_ARTIFACT_TYPE,
|
|
135432
|
+
workspace: draft.workspace,
|
|
135433
|
+
owner,
|
|
135434
|
+
title: "\u4EA4\u4ED8\u6C47\u603B",
|
|
135435
|
+
description: existing?.description ?? SUMMARY_TASK_BOOK,
|
|
135436
|
+
inputs: terminals.map((op) => ({ to: op.id, required: true })),
|
|
135437
|
+
isFinalOutput: true
|
|
135438
|
+
};
|
|
135439
|
+
const summaryIds = new Set(summaries.map((op) => op.id));
|
|
135440
|
+
draft.plan.ops = draft.plan.ops.filter((op) => {
|
|
135441
|
+
if (op.action === "spawn" && op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE) return false;
|
|
135442
|
+
if (op.action === "link" || op.action === "unlink") return !summaryIds.has(op.artifactId) && !summaryIds.has(op.to);
|
|
135443
|
+
if (op.action === "annotate" || op.action === "edit" || op.action === "assign") return !summaryIds.has(op.artifactId);
|
|
135444
|
+
return true;
|
|
135445
|
+
});
|
|
135446
|
+
draft.plan.ops.push(summary);
|
|
135447
|
+
}
|
|
135448
|
+
function assertDeliverySummaryPlanIntegrity(submitted, trusted) {
|
|
135449
|
+
const summaries = (plan) => (plan?.ops ?? []).filter((op) => op.action === "spawn" && op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
135450
|
+
const actual = summaries(submitted);
|
|
135451
|
+
const expected = summaries(trusted);
|
|
135452
|
+
if (!trusted && actual.length === 0) return;
|
|
135453
|
+
if (!trusted) throw new Error("\u4EA4\u4ED8\u6C47\u603B\u5FC5\u987B\u6765\u81EA\u670D\u52A1\u7AEF\u751F\u6210\u7684\u5EFA\u5355\u8349\u6848\uFF0C\u4E0D\u80FD\u7531\u5BA2\u6237\u7AEF\u81EA\u884C\u521B\u5EFA\u3002");
|
|
135454
|
+
if (actual.length !== expected.length) throw new Error("\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u5220\u9664\u6216\u65B0\u589E\u3002");
|
|
135455
|
+
const protectedShape = (op) => ({
|
|
135456
|
+
id: op.id,
|
|
135457
|
+
type: op.type,
|
|
135458
|
+
owner: op.owner,
|
|
135459
|
+
workspace: op.workspace,
|
|
135460
|
+
title: op.title,
|
|
135461
|
+
description: op.description,
|
|
135462
|
+
fields: op.fields,
|
|
135463
|
+
inputs: op.inputs ?? [],
|
|
135464
|
+
isFinalOutput: op.isFinalOutput
|
|
135465
|
+
});
|
|
135466
|
+
for (const expectedSummary of expected) {
|
|
135467
|
+
const actualSummary = actual.find((op) => op.id === expectedSummary.id);
|
|
135468
|
+
if (!actualSummary || JSON.stringify(protectedShape(actualSummary)) !== JSON.stringify(protectedShape(expectedSummary))) {
|
|
135469
|
+
throw new Error("\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7684\u8282\u70B9\u3001\u8D1F\u8D23\u4EBA\u3001\u4EFB\u52A1\u4E66\u548C\u8FDE\u7EBF\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u4EBA\u5DE5\u4FEE\u6539\u3002");
|
|
135470
|
+
}
|
|
135471
|
+
const protectedIds = /* @__PURE__ */ new Set([expectedSummary.id]);
|
|
135472
|
+
for (const op of submitted.ops) {
|
|
135473
|
+
if ((op.action === "edit" || op.action === "assign") && protectedIds.has(op.artifactId)) {
|
|
135474
|
+
throw new Error("\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u8FFD\u52A0\u4EBA\u5DE5\u7F16\u8F91\u6216\u6539\u6D3E\u64CD\u4F5C\u3002");
|
|
135475
|
+
}
|
|
135476
|
+
if ((op.action === "link" || op.action === "unlink") && (protectedIds.has(op.artifactId) || protectedIds.has(op.to))) {
|
|
135477
|
+
throw new Error("\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7684\u8FDE\u7EBF\u7531\u7CFB\u7EDF\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u8FFD\u52A0\u4EBA\u5DE5\u8FDE\u7EBF\u64CD\u4F5C\u3002");
|
|
135478
|
+
}
|
|
135479
|
+
}
|
|
135480
|
+
}
|
|
135481
|
+
const expectedMarkers = new Map(trusted.ops.filter((op) => op.action === "spawn" && !!op.id).map((op) => [op.id, op.isFinalOutput === true]));
|
|
135482
|
+
for (const op of submitted.ops) {
|
|
135483
|
+
if (op.action === "spawn" && op.id && expectedMarkers.has(op.id) && op.isFinalOutput === true !== expectedMarkers.get(op.id)) {
|
|
135484
|
+
throw new Error("\u8282\u70B9\u7684\u6700\u7EC8\u7ED3\u679C\u89D2\u8272\u7531\u52A8\u6001\u89C4\u5212\u7EF4\u62A4\uFF0C\u4E0D\u80FD\u4EBA\u5DE5\u4FEE\u6539\u3002");
|
|
135485
|
+
}
|
|
135486
|
+
}
|
|
135487
|
+
}
|
|
135282
135488
|
function resolveRef(ref2, draft) {
|
|
135283
135489
|
const res = resolveNodeRef(ref2, candidatesOf(draft));
|
|
135284
135490
|
if (res.ok) return res.id;
|
|
@@ -135289,6 +135495,9 @@ function resolveRef(ref2, draft) {
|
|
|
135289
135495
|
function editDraftPlan(draft, op) {
|
|
135290
135496
|
switch (op.action) {
|
|
135291
135497
|
case "spawn": {
|
|
135498
|
+
if (op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE) {
|
|
135499
|
+
throw new Error("\u300C\u4EA4\u4ED8\u6C47\u603B\u300D\u7531\u7CFB\u7EDF\u6309\u52A8\u6001\u534F\u4F5C\u56FE\u81EA\u52A8\u521B\u5EFA\uFF0C\u4E0D\u80FD\u624B\u52A8\u65B0\u589E\u3002");
|
|
135500
|
+
}
|
|
135292
135501
|
const title = op.title?.trim();
|
|
135293
135502
|
if (!title) throw new Error("\u7ED9\u8349\u6848\u52A0\u8282\u70B9\u8981 --title\uFF08\u636E (type,title) \u6D3E\u751F id\uFF09");
|
|
135294
135503
|
if (candidatesOf(draft).some((c) => c.type === op.type && (c.title ?? "").toLowerCase() === title.toLowerCase()))
|
|
@@ -135310,6 +135519,7 @@ function editDraftPlan(draft, op) {
|
|
|
135310
135519
|
}
|
|
135311
135520
|
case "edit": {
|
|
135312
135521
|
const id = resolveRef(op.artifactId, draft);
|
|
135522
|
+
assertNotDeliverySummary(draft, [id], "\u7F16\u8F91\u8282\u70B9\u5B9A\u4E49");
|
|
135313
135523
|
const target = spawnOps(draft).find((o) => o.id === id);
|
|
135314
135524
|
if (!target) throw new Error(`\u8349\u6848\u91CC\u6CA1\u6709\u8282\u70B9 ${id} \u7684 spawn`);
|
|
135315
135525
|
if (op.title !== void 0) target.title = op.title;
|
|
@@ -135320,12 +135530,14 @@ function editDraftPlan(draft, op) {
|
|
|
135320
135530
|
case "link": {
|
|
135321
135531
|
const consumer = resolveRef(op.artifactId, draft);
|
|
135322
135532
|
const upstream = resolveRef(op.to, draft);
|
|
135533
|
+
assertNotDeliverySummary(draft, [consumer, upstream], "\u4FEE\u6539\u8FDE\u7EBF");
|
|
135323
135534
|
draft.plan.ops.push({ action: "link", artifactId: consumer, to: upstream, ...op.required !== void 0 ? { required: op.required } : {} });
|
|
135324
135535
|
break;
|
|
135325
135536
|
}
|
|
135326
135537
|
case "unlink": {
|
|
135327
135538
|
const consumer = resolveRef(op.artifactId, draft);
|
|
135328
135539
|
const upstream = resolveRef(op.to, draft);
|
|
135540
|
+
assertNotDeliverySummary(draft, [consumer, upstream], "\u4FEE\u6539\u8FDE\u7EBF");
|
|
135329
135541
|
draft.plan.ops = draft.plan.ops.filter((o) => !(o.action === "link" && o.artifactId === consumer && o.to === upstream));
|
|
135330
135542
|
for (const o of draft.plan.ops) if (o.action === "spawn" && o.id === consumer && o.inputs) o.inputs = o.inputs.filter((e) => e.to !== upstream);
|
|
135331
135543
|
break;
|
|
@@ -135333,6 +135545,7 @@ function editDraftPlan(draft, op) {
|
|
|
135333
135545
|
case "seal": {
|
|
135334
135546
|
if (op.reason !== "cancelled") throw new Error(`\u8349\u6848\u8282\u70B9\u53EA\u652F\u6301 cancel\uFF08\u5220\u9664\uFF09\uFF0C\u4E0D\u652F\u6301 ${op.reason}\u2014\u2014\u8282\u70B9\u8FD8\u6CA1\u843D\u5E93`);
|
|
135335
135547
|
const id = resolveRef(op.artifactId, draft);
|
|
135548
|
+
assertNotDeliverySummary(draft, [id], "\u5220\u9664\u8282\u70B9");
|
|
135336
135549
|
draft.plan.ops = draft.plan.ops.filter((o) => {
|
|
135337
135550
|
if (o.action === "spawn" && o.id === id) return false;
|
|
135338
135551
|
if (o.action === "annotate" && o.artifactId === id) return false;
|
|
@@ -135345,14 +135558,24 @@ function editDraftPlan(draft, op) {
|
|
|
135345
135558
|
default:
|
|
135346
135559
|
throw new Error(`\u8349\u6848\u7F16\u8F91\u6682\u4E0D\u652F\u6301 ${op.action}\uFF08\u8349\u6848\u9636\u6BB5\u53EA\u652F\u6301 spawn / edit / link / unlink / cancel\uFF09`);
|
|
135347
135560
|
}
|
|
135561
|
+
reconcileDeliverySummaryPlan(draft);
|
|
135348
135562
|
}
|
|
135349
|
-
var spawnOps, candidatesOf;
|
|
135563
|
+
var spawnOps, candidatesOf, spawnById, SUMMARY_TASK_BOOK;
|
|
135350
135564
|
var init_draft_edit = __esm({
|
|
135351
135565
|
"../server/src/governance/draft-edit.ts"() {
|
|
135352
135566
|
"use strict";
|
|
135567
|
+
init_src();
|
|
135353
135568
|
init_src2();
|
|
135354
135569
|
spawnOps = (draft) => draft.plan.ops.filter((o) => o.action === "spawn" && !!o.id);
|
|
135355
135570
|
candidatesOf = (draft) => spawnOps(draft).map((o) => ({ id: o.id, type: o.type, ...o.title ? { title: o.title } : {} }));
|
|
135571
|
+
spawnById = (draft, id) => spawnOps(draft).find((o) => o.id === id);
|
|
135572
|
+
SUMMARY_TASK_BOOK = [
|
|
135573
|
+
"# \u4EA4\u4ED8\u6C47\u603B\u4EFB\u52A1\u4E66",
|
|
135574
|
+
"",
|
|
135575
|
+
"\u4F60\u662F\u672C\u5DE5\u5355\u534F\u8C03\u8005\uFF0C\u8D1F\u8D23\u628A\u534F\u4F5C\u6D41\u5DF2\u7ECF\u4EA7\u51FA\u7684\u6700\u7EC8\u7ED3\u679C\u6574\u7406\u6210\u7528\u6237\u53EF\u4EE5\u76F4\u63A5\u9886\u53D6\u548C\u4F7F\u7528\u7684\u4E00\u4EFD\u5B8C\u6574\u4EA4\u4ED8\u3002",
|
|
135576
|
+
"\u8FD9\u4E0D\u662F\u9A8C\u6536\u8282\u70B9\uFF1A\u4E0D\u8981\u91CD\u65B0\u6D4B\u8BD5\u3001\u4E0D\u8981\u5224\u5B9A\u901A\u8FC7\u3001\u4E0D\u8981\u6C42\u7528\u6237\u7B7E\u6536\u3002",
|
|
135577
|
+
"\u8F93\u51FA\u987B\u8BF4\u660E\u7528\u6237\u62FF\u5230\u4E86\u4EC0\u4E48\u3001\u5728\u54EA\u91CC\u62FF\u3001\u600E\u4E48\u4F7F\u7528\u3001\u5F53\u524D\u662F\u54EA\u4E00\u7248\uFF1B\u53EA\u5F15\u7528\u8F93\u5165\u53CA\u5176\u4E0A\u6E38\u7684\u771F\u5B9E\u4EA7\u7269\u3002"
|
|
135578
|
+
].join("\n");
|
|
135356
135579
|
}
|
|
135357
135580
|
});
|
|
135358
135581
|
|
|
@@ -135619,7 +135842,7 @@ async function plannerAvailableActors(registry2) {
|
|
|
135619
135842
|
}
|
|
135620
135843
|
async function plannerArtifactTypes(schema, registry2) {
|
|
135621
135844
|
if (!registry2) {
|
|
135622
|
-
return schema.filter((def) => def.name !== "brief").map((def) => ({
|
|
135845
|
+
return schema.filter((def) => def.name !== "brief" && def.name !== DELIVERY_SUMMARY_ARTIFACT_TYPE).map((def) => ({
|
|
135623
135846
|
name: def.name,
|
|
135624
135847
|
...def.ownerRole ? { ownerRole: def.ownerRole } : {},
|
|
135625
135848
|
contentType: def.contentType,
|
|
@@ -135628,7 +135851,7 @@ async function plannerArtifactTypes(schema, registry2) {
|
|
|
135628
135851
|
}
|
|
135629
135852
|
const actors = await plannerAvailableActors(registry2);
|
|
135630
135853
|
const staffableRoles = new Set(actors.flatMap((actor) => actor.roles));
|
|
135631
|
-
return schema.filter((def) => def.name !== "brief" && (def.ownerRole === void 0 || staffableRoles.has(def.ownerRole))).map((def) => ({
|
|
135854
|
+
return schema.filter((def) => def.name !== "brief" && def.name !== DELIVERY_SUMMARY_ARTIFACT_TYPE && (def.ownerRole === void 0 || staffableRoles.has(def.ownerRole))).map((def) => ({
|
|
135632
135855
|
name: def.name,
|
|
135633
135856
|
...def.ownerRole ? { ownerRole: def.ownerRole } : {},
|
|
135634
135857
|
contentType: def.contentType
|
|
@@ -135723,7 +135946,8 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
135723
135946
|
...def.ownerRole ? { role: def.ownerRole } : {},
|
|
135724
135947
|
owner: ownerActor,
|
|
135725
135948
|
dependsOn: node.dependsOn,
|
|
135726
|
-
...node.brief ? { brief: node.brief } : {}
|
|
135949
|
+
...node.brief ? { brief: node.brief } : {},
|
|
135950
|
+
...node.isFinalOutput ? { isFinalOutput: true } : {}
|
|
135727
135951
|
});
|
|
135728
135952
|
}
|
|
135729
135953
|
} else {
|
|
@@ -135738,11 +135962,12 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
135738
135962
|
const ownerActor = owner?.actor ?? (!def.ownerRole ? PENDING_UNASSIGNED : type === primaryType ? input.actor : `pending:role:${def.ownerRole}`);
|
|
135739
135963
|
if (enforceStaffing && def.ownerRole && !owner?.actor && type !== primaryType) continue;
|
|
135740
135964
|
const id = type === primaryType ? primaryId : `artifact:${type}:${slug5}`;
|
|
135741
|
-
availableNodes.push({ type, id, ...def.ownerRole ? { role: def.ownerRole } : {}, owner: ownerActor });
|
|
135965
|
+
availableNodes.push({ type, id, ...def.ownerRole ? { role: def.ownerRole } : {}, owner: ownerActor, ...type === primaryType ? { isFinalOutput: true } : {} });
|
|
135742
135966
|
}
|
|
135743
135967
|
}
|
|
135744
135968
|
for (const node of availableNodes) {
|
|
135745
135969
|
const inputs = agentGraph ? agentEdgesFor(node.dependsOn ?? [], availableNodes, briefId, issues) : ruleEdgesFor(node.type, availableNodes, briefId);
|
|
135970
|
+
node.inputs = inputs;
|
|
135746
135971
|
const shortTitle = node.title ?? (!agentGraph && node.type === "prd" && issues.length > 0 ? "\u964D\u7EA7\u65B9\u6848\u6587\u6863" : labelForType(node.type));
|
|
135747
135972
|
const briefBody = node.brief ?? taskBookFor(node.type, input.description, node.role, issues, agentGraph?.notes, shortTitle);
|
|
135748
135973
|
ops.push({
|
|
@@ -135756,10 +135981,59 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
135756
135981
|
// 所有类型(含 document)统一:description = 完整任务书,直接进 owner 的 TASK.md,**不再造 open 人类 annotation**
|
|
135757
135982
|
//(那条 annotation 默认 kind=change-request、触发 hasOpenHumanChangeRequest 焊死自动合并 + 假审核,是迁移遗留)。
|
|
135758
135983
|
// document 的 docType/title 走独立字段;老文档缺独立字段的仍由 decodeDocumentDescription 兜底解析 description(保留)。
|
|
135759
|
-
description: briefBody
|
|
135984
|
+
description: briefBody,
|
|
135985
|
+
...node.isFinalOutput ? { isFinalOutput: true } : {}
|
|
135760
135986
|
});
|
|
135761
135987
|
spawned.push({ id: node.id, type: node.type, role: node.role, owner: node.owner });
|
|
135762
135988
|
}
|
|
135989
|
+
if (availableNodes.length > 0) {
|
|
135990
|
+
const consumed = new Set(availableNodes.flatMap((node) => (node.inputs ?? []).map((edge) => edge.to)));
|
|
135991
|
+
const terminalNodes = availableNodes.filter((node) => !consumed.has(node.id));
|
|
135992
|
+
const finalNodes = availableNodes.filter((node) => node.isFinalOutput);
|
|
135993
|
+
const directFinal = finalNodes.length === 1 && terminalNodes.length === 1 && finalNodes[0].id === terminalNodes[0].id;
|
|
135994
|
+
if (agentGraph && finalNodes.length === 0) {
|
|
135995
|
+
issues.push({
|
|
135996
|
+
code: "planner_invalid",
|
|
135997
|
+
severity: "warning",
|
|
135998
|
+
message: "pm_agent \u6CA1\u6709\u6807\u8BB0\u76F4\u63A5\u56DE\u7B54\u7528\u6237\u9700\u6C42\u7684\u6700\u7EC8\u7ED3\u679C\u8282\u70B9\uFF0C\u7CFB\u7EDF\u5DF2\u7528\u4EA4\u4ED8\u6C47\u603B\u515C\u5E95\u3002"
|
|
135999
|
+
});
|
|
136000
|
+
}
|
|
136001
|
+
if (directFinal) {
|
|
136002
|
+
} else {
|
|
136003
|
+
const summaryDef = schemaByName.get(DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
136004
|
+
if (!summaryDef) {
|
|
136005
|
+
issues.push({
|
|
136006
|
+
code: "missing_artifact_type",
|
|
136007
|
+
severity: "blocking",
|
|
136008
|
+
artifactType: DELIVERY_SUMMARY_ARTIFACT_TYPE,
|
|
136009
|
+
message: `\u7F3A\u5C11\u7CFB\u7EDF ArtifactType ${DELIVERY_SUMMARY_ARTIFACT_TYPE}\uFF0C\u672C\u6B21\u65E0\u6CD5\u521B\u5EFA\u4EA4\u4ED8\u6C47\u603B\u8282\u70B9\u3002`
|
|
136010
|
+
});
|
|
136011
|
+
} else if (terminalNodes.length > 0) {
|
|
136012
|
+
const summaryId = deriveArtifactId(DELIVERY_SUMMARY_ARTIFACT_TYPE, input.workspace, "\u4EA4\u4ED8\u6C47\u603B", usedIds);
|
|
136013
|
+
const summaryOwner = input.aiActorId ?? (input.actor.startsWith("actor:agent:") ? input.actor : PENDING_UNASSIGNED);
|
|
136014
|
+
if (summaryOwner === PENDING_UNASSIGNED) {
|
|
136015
|
+
issues.push({
|
|
136016
|
+
code: "missing_owner",
|
|
136017
|
+
severity: "blocking",
|
|
136018
|
+
artifactType: DELIVERY_SUMMARY_ARTIFACT_TYPE,
|
|
136019
|
+
message: "\u4EA4\u4ED8\u6C47\u603B\u5FC5\u987B\u7531\u672C\u5DE5\u5355\u7BA1\u7406\u8005\u8D1F\u8D23\uFF0C\u4F46\u5F53\u524D brief \u6CA1\u6709 manager\uFF1B\u8BF7\u5148\u6307\u5B9A\u7BA1\u7406\u8005\u3002"
|
|
136020
|
+
});
|
|
136021
|
+
}
|
|
136022
|
+
ops.push({
|
|
136023
|
+
action: "spawn",
|
|
136024
|
+
id: summaryId,
|
|
136025
|
+
type: DELIVERY_SUMMARY_ARTIFACT_TYPE,
|
|
136026
|
+
owner: summaryOwner,
|
|
136027
|
+
workspace: input.workspace,
|
|
136028
|
+
title: "\u4EA4\u4ED8\u6C47\u603B",
|
|
136029
|
+
inputs: terminalNodes.map((node) => ({ to: node.id, required: true })),
|
|
136030
|
+
description: deliverySummaryTaskBook(finalNodes, terminalNodes),
|
|
136031
|
+
isFinalOutput: true
|
|
136032
|
+
});
|
|
136033
|
+
spawned.push({ id: summaryId, type: DELIVERY_SUMMARY_ARTIFACT_TYPE, owner: summaryOwner });
|
|
136034
|
+
}
|
|
136035
|
+
}
|
|
136036
|
+
}
|
|
135763
136037
|
return {
|
|
135764
136038
|
plan: {
|
|
135765
136039
|
reason: `\u52A8\u6001\u89C4\u5212\u5DE5\u5355\uFF1A${displayTitle}`,
|
|
@@ -135804,15 +136078,19 @@ function buildPmAgentPlannerPrompt(input) {
|
|
|
135804
136078
|
"",
|
|
135805
136079
|
JSON.stringify({
|
|
135806
136080
|
nodes: [
|
|
135807
|
-
{ type: "prd", title: "\u9700\u6C42\u4E0E\u8303\u56F4\u8BF4\u660E", dependsOn: ["brief"], brief: "\u8FD9\u4E2A\u8282\u70B9\u5177\u4F53\u8981\u505A\u4EC0\u4E48\u7684\u89C4\u683C\uFF1A\u4EA7\u51FA\u4EC0\u4E48\u3001\u8981\u70B9\u3001\u7EA6\u675F" },
|
|
135808
|
-
{ type: "research", title: "\u7ADE\u54C1\u8C03\u7814", dependsOn: ["brief"], brief: "\u2026" },
|
|
135809
|
-
{ type: "dev", title: "\
|
|
136081
|
+
{ type: "prd", title: "\u9700\u6C42\u4E0E\u8303\u56F4\u8BF4\u660E", dependsOn: ["brief"], brief: "\u8FD9\u4E2A\u8282\u70B9\u5177\u4F53\u8981\u505A\u4EC0\u4E48\u7684\u89C4\u683C\uFF1A\u4EA7\u51FA\u4EC0\u4E48\u3001\u8981\u70B9\u3001\u7EA6\u675F", isFinalOutput: false },
|
|
136082
|
+
{ type: "research", title: "\u7ADE\u54C1\u8C03\u7814", dependsOn: ["brief"], brief: "\u2026", isFinalOutput: false },
|
|
136083
|
+
{ type: "dev", title: "\u4EA7\u54C1\u5B9E\u73B0", dependsOn: ["prd:\u9700\u6C42\u4E0E\u8303\u56F4\u8BF4\u660E"], brief: "\u4EA7\u51FA\u7528\u6237\u9700\u8981\u7684\u4EA7\u54C1\u548C\u4F7F\u7528\u8BF4\u660E", isFinalOutput: true },
|
|
136084
|
+
{ type: "qa", title: "\u8D28\u91CF\u68C0\u67E5", dependsOn: ["dev:\u4EA7\u54C1\u5B9E\u73B0"], brief: "\u68C0\u67E5\u4EA7\u54C1\u662F\u5426\u53EF\u7528", isFinalOutput: false }
|
|
135810
136085
|
],
|
|
135811
136086
|
notes: ["\u53EF\u9009\uFF1A\u89C4\u5212\u7406\u7531\u6216\u98CE\u9669\u63D0\u793A"]
|
|
135812
136087
|
}, null, 2),
|
|
135813
136088
|
"",
|
|
135814
136089
|
"\u89C4\u5219\uFF1A",
|
|
135815
136090
|
"- brief \u6839\u8282\u70B9\u7531\u7CFB\u7EDF\u56FA\u5B9A\u521B\u5EFA\uFF0C\u4F60\u4E0D\u8981\u628A brief \u5199\u8FDB nodes\u3002",
|
|
136091
|
+
`- ${DELIVERY_SUMMARY_ARTIFACT_TYPE}\uFF08\u4EA4\u4ED8\u6C47\u603B\uFF09\u7531\u7CFB\u7EDF\u56FA\u5B9A\u521B\u5EFA\uFF0C\u4F60\u4E0D\u8981\u628A\u5B83\u5199\u8FDB nodes\u3002`,
|
|
136092
|
+
"- \u6BCF\u4E2A\u8282\u70B9\u5FC5\u987B\u7ED9 isFinalOutput\u3002true \u8868\u793A\u8BE5\u8282\u70B9\u7684\u4EA7\u7269\u76F4\u63A5\u56DE\u7B54\u7528\u6237\u9700\u6C42\uFF1B\u5B83\u4E0D\u662F\u8BC4\u5BA1\u3001QA \u6216\u662F\u5426\u5B8C\u6210\u7684\u72B6\u6001\u3002\u8FC7\u7A0B/\u652F\u6491/\u95F8\u95E8\u8282\u70B9\u5199 false\u3002",
|
|
136093
|
+
"- \u81F3\u5C11\u4E00\u4E2A\u8282\u70B9\u5E94\u4E3A isFinalOutput:true\u3002\u4F8B\uFF1A\u53EA\u505A\u4E00\u4EFD PRD \u65F6 PRD=true\uFF1B\u4E09\u4EFD\u5E73\u884C\u8C03\u7814\u6C47\u5165\u4E00\u4EFD\u7EFC\u5408\u62A5\u544A\u65F6\u53EA\u6807\u7EFC\u5408\u62A5\u544A=true\uFF1B\u505A\u4EA7\u54C1\u65F6\u4EA7\u51FA\u4EA7\u54C1\u548C\u4F7F\u7528\u8BF4\u660E\u7684\u5B9E\u73B0\u8282\u70B9=true\uFF0C\u800C\u90E8\u7F72/QA=false\u3002",
|
|
135816
136094
|
"- type \u53EA\u80FD\u4ECE\u4E0A\u9762\u3010\u53EF\u7528 ArtifactType\u3011\u76EE\u5F55\u91CC\u9009\uFF08\u4EE5\u6CE8\u5165\u76EE\u5F55\u4E3A\u51C6\uFF09\u3002",
|
|
135817
136095
|
"- \u6BCF\u4E2A\u8282\u70B9\u5FC5\u7ED9 title\uFF08\u226420\u5B57\u3001\u7528\u6765\u533A\u5206\u8282\u70B9\uFF09+ brief\uFF08\u8FD9\u4E2A\u8282\u70B9\u8981\u4EA7\u51FA\u4EC0\u4E48\u7684\u89C4\u683C\uFF0C\u522B\u5957\u6A21\u677F\u3001\u522B\u53EA\u5199\u7C7B\u578B\u540D\uFF09\u3002",
|
|
135818
136096
|
'- \u3010\u53EF\u6709\u591A\u4E2A\u540C type \u8282\u70B9\u3011\uFF0C\u7528\u4E0D\u540C title \u533A\u5206\uFF08\u5982\u4E24\u4E2A prd\uFF1A"\u524D\u7AEF\u9700\u6C42"\u3001"\u540E\u7AEF\u9700\u6C42"\uFF1B\u591A\u4EFD\u8C03\u7814\u62A5\u544A\u5404\u53D6\u5176\u540D\uFF09\u3002',
|
|
@@ -135839,7 +136117,8 @@ function parseAgentWorkorderPlan(text) {
|
|
|
135839
136117
|
type: n.type.trim().toLowerCase(),
|
|
135840
136118
|
...Array.isArray(n.dependsOn) ? { dependsOn: n.dependsOn.filter((x2) => typeof x2 === "string").map((x2) => x2.trim().toLowerCase()).filter(Boolean) } : {},
|
|
135841
136119
|
...typeof n.title === "string" && n.title.trim() ? { title: n.title.trim() } : {},
|
|
135842
|
-
...typeof n.brief === "string" && n.brief.trim() ? { brief: n.brief.trim() } : {}
|
|
136120
|
+
...typeof n.brief === "string" && n.brief.trim() ? { brief: n.brief.trim() } : {},
|
|
136121
|
+
...n.isFinalOutput === true ? { isFinalOutput: true } : {}
|
|
135843
136122
|
});
|
|
135844
136123
|
}
|
|
135845
136124
|
if (nodes.length === 0) return null;
|
|
@@ -135915,13 +136194,14 @@ function desiredArtifacts(primaryType, description) {
|
|
|
135915
136194
|
return ["prd", "research", "design", "adr", "dev", "qa"].filter((type) => wanted.has(type));
|
|
135916
136195
|
}
|
|
135917
136196
|
function normalizeAgentPlan(plan, validTypes) {
|
|
135918
|
-
const allowed = validTypes.map((t) => t.trim().toLowerCase()).filter((t) => t !== "brief");
|
|
136197
|
+
const allowed = validTypes.map((t) => t.trim().toLowerCase()).filter((t) => t !== "brief" && t !== DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
135919
136198
|
const nodes = [];
|
|
135920
136199
|
const seen = /* @__PURE__ */ new Set();
|
|
135921
136200
|
const dupTitles = [];
|
|
135922
136201
|
for (const node of plan.nodes) {
|
|
135923
136202
|
const type = node.type.trim().toLowerCase();
|
|
135924
136203
|
if (type === "brief") continue;
|
|
136204
|
+
if (type === DELIVERY_SUMMARY_ARTIFACT_TYPE) continue;
|
|
135925
136205
|
if (!allowed.includes(type)) continue;
|
|
135926
136206
|
const title = (node.title?.trim() || labelForType(type)).slice(0, 40);
|
|
135927
136207
|
const key = `${type}:${title.toLowerCase()}`;
|
|
@@ -135934,7 +136214,8 @@ function normalizeAgentPlan(plan, validTypes) {
|
|
|
135934
136214
|
type,
|
|
135935
136215
|
title,
|
|
135936
136216
|
dependsOn: node.dependsOn?.map((d) => d.trim()).filter(Boolean) ?? [],
|
|
135937
|
-
...node.brief ? { brief: node.brief } : {}
|
|
136217
|
+
...node.brief ? { brief: node.brief } : {},
|
|
136218
|
+
...node.isFinalOutput ? { isFinalOutput: true } : {}
|
|
135938
136219
|
});
|
|
135939
136220
|
}
|
|
135940
136221
|
return nodes.length > 0 ? { nodes, dupTitles, ...plan.notes?.length ? { notes: plan.notes } : {} } : null;
|
|
@@ -136012,6 +136293,29 @@ ${plannerNotes.map((note) => `- ${note}`).join("\n")}` : "";
|
|
|
136012
136293
|
notes
|
|
136013
136294
|
].join("\n");
|
|
136014
136295
|
}
|
|
136296
|
+
function deliverySummaryTaskBook(finalNodes, terminalNodes) {
|
|
136297
|
+
const labels = (nodes) => nodes.map((node) => node.title ?? labelForType(node.type));
|
|
136298
|
+
return [
|
|
136299
|
+
"# \u4EA4\u4ED8\u6C47\u603B\u4EFB\u52A1\u4E66",
|
|
136300
|
+
"",
|
|
136301
|
+
"\u4F60\u662F\u672C\u5DE5\u5355\u534F\u8C03\u8005\uFF0C\u8D1F\u8D23\u628A\u534F\u4F5C\u6D41\u5DF2\u7ECF\u4EA7\u51FA\u7684\u6700\u7EC8\u7ED3\u679C\u6574\u7406\u6210\u7528\u6237\u53EF\u4EE5\u76F4\u63A5\u9886\u53D6\u548C\u4F7F\u7528\u7684\u4E00\u4EFD\u5B8C\u6574\u4EA4\u4ED8\u3002",
|
|
136302
|
+
"\u8FD9\u4E0D\u662F\u9A8C\u6536\u8282\u70B9\uFF1A\u4E0D\u8981\u91CD\u65B0\u6D4B\u8BD5\u3001\u4E0D\u8981\u5224\u5B9A\u901A\u8FC7\u3001\u4E0D\u8981\u6C42\u7528\u6237\u7B7E\u6536\uFF0C\u4E5F\u4E0D\u8981\u628A\u6240\u6709\u8FC7\u7A0B\u8282\u70B9\u90FD\u585E\u8FDB\u6765\u3002",
|
|
136303
|
+
"",
|
|
136304
|
+
"## \u89C4\u5212\u8BC6\u522B\u7684\u6700\u7EC8\u7ED3\u679C\u8282\u70B9",
|
|
136305
|
+
...finalNodes.length > 0 ? labels(finalNodes).map((item) => `- ${item}`) : ["- \u89C4\u5212\u672A\u660E\u786E\u6807\u8BB0\uFF1B\u8BF7\u6839\u636E\u5DE5\u5355\u9700\u6C42\u548C\u8F93\u5165\u4EA7\u7269\u6574\u7406\u771F\u5B9E\u4EA4\u4ED8\u3002"],
|
|
136306
|
+
"",
|
|
136307
|
+
"## \u672C\u8282\u70B9\u76F4\u63A5\u627F\u63A5\u7684\u534F\u4F5C\u6D41\u7EC8\u70B9",
|
|
136308
|
+
...labels(terminalNodes).map((item) => `- ${item}`),
|
|
136309
|
+
"",
|
|
136310
|
+
"## \u8F93\u51FA\u5FC5\u987B\u56DE\u7B54",
|
|
136311
|
+
"- \u6211\u62FF\u5230\u4E86\u4EC0\u4E48\uFF1A\u4EA7\u54C1\u3001\u6587\u6863\u3001\u65B9\u6848\u3001\u4ED3\u5E93\u6216\u5176\u5B83\u76F4\u63A5\u56DE\u7B54\u9700\u6C42\u7684\u7ED3\u679C\u3002",
|
|
136312
|
+
"- \u5728\u54EA\u91CC\u62FF\uFF1A\u7ED9\u51FA\u53EF\u8BBF\u95EE\u5730\u5740\u3001\u4E0B\u8F7D\u4F4D\u7F6E\u3001\u4ED3\u5E93/\u7248\u672C\u6216\u5176\u5B83\u51C6\u786E\u5B9A\u4F4D\u3002",
|
|
136313
|
+
"- \u63A5\u4E0B\u6765\u600E\u4E48\u7528\uFF1A\u7ED9\u51FA\u5B89\u88C5\u3001\u6253\u5F00\u3001\u4E0A\u4F20\u3001\u6388\u6743\u6216\u4E3B\u8981\u64CD\u4F5C\u6B65\u9AA4\u3002",
|
|
136314
|
+
"- \u5F53\u524D\u662F\u54EA\u4E00\u7248\uFF1A\u5F15\u7528\u5404\u4E0A\u6E38\u5F53\u524D\u4EA4\u4ED8\u7248\u672C\uFF1B\u4E0A\u6E38\u53D8\u5316\u540E\u751F\u6210\u65B0\u7684\u5B8C\u6574\u6C47\u603B\u7248\u672C\uFF0C\u4E0D\u8986\u76D6\u5386\u53F2\u3002",
|
|
136315
|
+
"",
|
|
136316
|
+
"\u53EA\u5F15\u7528\u8F93\u5165\u8282\u70B9\u53CA\u5176\u4E0A\u6E38\u91CC\u7684\u771F\u5B9E\u4EA7\u7269\uFF0C\u4E0D\u8981\u81C6\u9020\u94FE\u63A5\u6216\u5B8C\u6210\u60C5\u51B5\u3002\u7F3A\u5C11\u53EF\u9886\u53D6\u7ED3\u679C\u6216\u5FC5\u8981\u4F7F\u7528\u8BF4\u660E\u65F6\uFF0C\u7528 `oasis gap` \u660E\u786E\u62A5\u544A\uFF0C\u8865\u9F50\u524D\u4E0D\u8981 conclude\u3002"
|
|
136317
|
+
].join("\n");
|
|
136318
|
+
}
|
|
136015
136319
|
function dedupeIssues(issues) {
|
|
136016
136320
|
const seen = /* @__PURE__ */ new Set();
|
|
136017
136321
|
const out = [];
|
|
@@ -136031,7 +136335,8 @@ function labelForType(type) {
|
|
|
136031
136335
|
design: "\u8BBE\u8BA1",
|
|
136032
136336
|
adr: "\u6280\u672F\u65B9\u6848",
|
|
136033
136337
|
dev: "\u5B9E\u73B0",
|
|
136034
|
-
qa: "\u6D4B\u8BD5\u9A8C\u6536"
|
|
136338
|
+
qa: "\u6D4B\u8BD5\u9A8C\u6536",
|
|
136339
|
+
[DELIVERY_SUMMARY_ARTIFACT_TYPE]: "\u4EA4\u4ED8\u6C47\u603B"
|
|
136035
136340
|
};
|
|
136036
136341
|
return labels[type] ?? type;
|
|
136037
136342
|
}
|
|
@@ -136043,16 +136348,26 @@ var DEFAULT_TYPES, WORKORDER_SPEC_PREFIX;
|
|
|
136043
136348
|
var init_planner = __esm({
|
|
136044
136349
|
"../server/src/domains/collab/planner.ts"() {
|
|
136045
136350
|
"use strict";
|
|
136351
|
+
init_src();
|
|
136046
136352
|
init_src2();
|
|
136047
136353
|
init_identity();
|
|
136048
136354
|
DEFAULT_TYPES = [
|
|
136049
|
-
// brief 的 goal/acceptanceCriteria
|
|
136355
|
+
// brief 的 goal/acceptanceCriteria 现在是【自定义字段】
|
|
136356
|
+
//(Phase 3,替代旧 OASIS_WORKORDER_SPEC 批注,铲 #1 死锁根)。
|
|
136050
136357
|
// brief 不绑岗位:内置产物,owner 恒 = 发起人本人(决策 0026)——ownerRole 从不被解析。
|
|
136051
136358
|
{ name: "brief", contentType: "text", fieldDefs: [
|
|
136052
136359
|
{ name: "goal", type: "string", description: "\u4E00\u53E5\u8BDD\u76EE\u6807\uFF1A\u8FD9\u4E2A\u5DE5\u5355\u8981\u8FBE\u6210\u4EC0\u4E48" },
|
|
136053
136360
|
{ name: "acceptanceCriteria", type: "string[]", description: "\u9A8C\u6536\u6761\u76EE\uFF08\u6EE1\u8DB3\u5373\u7B97\u5B8C\u6210\uFF09" },
|
|
136054
136361
|
{ name: "manager", type: "string", description: "\u672C\u5DE5\u5355\u7BA1\u7406\u8005 agent\uFF08\u966A\u53D1\u8D77\u4EBA\u804A\u51FA\u6B64\u5355\u7684 AI \u5B9E\u4F8B\uFF09\uFF1A\u8D1F\u8D23\u672C\u5DE5\u5355\u7684\u534F\u8C03/\u515C\u5E95\uFF0C\u641E\u4E0D\u5B9A\u5347\u7EA7\u7ED9 owner\uFF08\u51B3\u7B56 0026\uFF09" }
|
|
136055
136362
|
] },
|
|
136363
|
+
{
|
|
136364
|
+
name: DELIVERY_SUMMARY_ARTIFACT_TYPE,
|
|
136365
|
+
contentType: "text",
|
|
136366
|
+
description: "\u7CFB\u7EDF\u751F\u6210\u7684\u5DE5\u5355\u672B\u7AEF\u95ED\u73AF\uFF1A\u7531\u672C\u5DE5\u5355\u7BA1\u7406\u8005\u628A\u534F\u4F5C\u6D41\u91CC\u7684\u6700\u7EC8\u7ED3\u679C\u6574\u7406\u6210\u4E00\u4EFD\u53EF\u9886\u53D6\u3001\u53EF\u5B9A\u4F4D\u3001\u53EF\u4F7F\u7528\u7684\u4EA4\u4ED8\uFF1B\u4E0D\u627F\u62C5\u9A8C\u6536\u3002",
|
|
136367
|
+
// 交付汇总是普通文本产物节点,视觉沿用 PRD 的 blue;不另造“封箱/验收”身份。
|
|
136368
|
+
appearance: { accent: "blue" },
|
|
136369
|
+
cascade: "auto"
|
|
136370
|
+
},
|
|
136056
136371
|
{ name: "prd", contentType: "text", ownerRole: "pm" },
|
|
136057
136372
|
{ name: "research", contentType: "text", ownerRole: "research" },
|
|
136058
136373
|
{ name: "design", contentType: "text", ownerRole: "designer" },
|
|
@@ -136063,8 +136378,22 @@ var init_planner = __esm({
|
|
|
136063
136378
|
name: "provision",
|
|
136064
136379
|
contentType: "text",
|
|
136065
136380
|
ownerRole: "devops",
|
|
136066
|
-
description: "\u4EE3\u7801\u4ED3\u5E93\u4F9B\u7ED9\uFF08\u5EFA\u4ED3\uFF09\uFF1A\u5F53\u9879\u76EE\u91CC\u6CA1\u6709\u4E0B\u6E38\u5B9E\u73B0\u6240\u9700\u7684\u4EE3\u7801\u4ED3\u5E93\u65F6\uFF0C\u7528\u6B64\u8282\u70B9\u5EFA\u4ED3\u2014\u2014\u6309\u7ED3\u6784\uFF08\u5355\u4ED3/\u4F1E\u4ED3\uFF09\u4E0E\u547D\u540D\u5EFA\u597D\u4ED3\u5E93\uFF0C\u521D\u59CB\u5316\u9879\u76EE\u6846\u67B6\u3001\u5FC5\u5907\u6587\u6863\u3001CI/CD \u57FA\u5EFA\u4E0E dev/prod \u73AF\u5883\u914D\u7F6E\uFF0C\u5E76
|
|
136067
|
-
reviews: { gates: [{ on: "conclude", reviewers: ["architect"], quorum: 1 }] }
|
|
136381
|
+
description: "\u4EE3\u7801\u4ED3\u5E93\u4F9B\u7ED9\uFF08\u5EFA\u4ED3\uFF09\uFF1A\u5F53\u9879\u76EE\u91CC\u6CA1\u6709\u4E0B\u6E38\u5B9E\u73B0\u6240\u9700\u7684\u4EE3\u7801\u4ED3\u5E93\u65F6\uFF0C\u7528\u6B64\u8282\u70B9\u5EFA\u4ED3\u2014\u2014\u6309\u7ED3\u6784\uFF08\u5355\u4ED3/\u4F1E\u4ED3\uFF09\u4E0E\u547D\u540D\u5EFA\u597D\u4ED3\u5E93\uFF0C\u521D\u59CB\u5316\u9879\u76EE\u6846\u67B6\u3001\u5FC5\u5907\u6587\u6863\u3001CI/CD \u57FA\u5EFA\uFF08GitHub Actions ci/cd workflow\uFF09\u4E0E dev/prod \u73AF\u5883\u914D\u7F6E\uFF0C\u5E76**\u767B\u8BB0\u5230\u9879\u76EE\u4E14\u6838\u9A8C\u767B\u8BB0\u771F\u7684\u843D\u8FDB\u5185\u6838**\uFF08\u4E0D\u662F\u5199\u7BC7\u6587\u6863\u8BF4\u914D\u597D\u4E86\u5C31\u7B97\uFF09\u3002**\u5EFA\u56FE/\u8865\u56FE\u65F6\uFF0C\u82E5\u53D1\u73B0\u9879\u76EE\u7F3A\u67D0\u4E2A dev\uFF08\u4EE3\u7801\u5B9E\u73B0\uFF09\u8282\u70B9\u6240\u9700\u7684\u4EE3\u7801\u4ED3\u5E93\uFF0C\u5E94\u65B0\u589E\u4E00\u4E2A\u6B64\u7C7B\u578B\u8282\u70B9\uFF0C\u4F5C\u4E3A\u90A3\u4E2A dev \u8282\u70B9\u7684\u524D\u7F6E\u3001\u6392\u5728\u5B83\u4E4B\u524D\u3002** \u4EA7\u51FA\u4E3A\u5EFA\u4ED3\u8BB0\u5F55\uFF08\u8BF4\u660E\u5EFA\u4E86\u54EA\u4E9B\u4ED3\u3001\u903B\u8F91 id \u4E0E\u7ED3\u6784\u3001CI/CD \u9AA8\u67B6\uFF09\uFF0C\u67B6\u6784\u5E08\u8BC4\u5BA1\u3002\u6536\u5C3E\u524D\u987B `oasis record-action <\u672C\u8282\u70B9> --name registration_verified --pass true` \u7559\u75D5\uFF08\u5148\u771F\u6838\u9A8C\u767B\u8BB0\u843D\u5E93\uFF09\u3002",
|
|
136382
|
+
reviews: { gates: [{ on: "conclude", reviewers: ["architect"], quorum: 1 }] },
|
|
136383
|
+
// grounding:登记必须真落库才收口(ADR-0070/§9.2)。防「写篇文档说仓配好了就算交付」(delivery C-2)。
|
|
136384
|
+
grounding: { requiredActions: [{ name: "registration_verified", mustPass: true }] }
|
|
136385
|
+
},
|
|
136386
|
+
{
|
|
136387
|
+
// deploy 此前只在生产经 API 手工新增、不在代码常量里(零审计,见 ADR-0067 背景与 ADR-0070)。
|
|
136388
|
+
// 收编进 DEFAULT_TYPES:给它一份规范定义作为新环境/测试/文档的事实源。
|
|
136389
|
+
// 注意 ensureDefaultWorkorderTypes 只“补缺”——生产已存在的 deploy 条目不会被此定义覆盖。
|
|
136390
|
+
name: "deploy",
|
|
136391
|
+
contentType: "text",
|
|
136392
|
+
ownerRole: "devops",
|
|
136393
|
+
description: "\u771F\u5B9E\u90E8\u7F72\u4E0E\u8054\u8C03\uFF1A\u628A\u5BF9\u5E94 dev\uFF08\u4EE3\u7801\u5B9E\u73B0\uFF09\u4EA7\u51FA\u90E8\u7F72\u5230\u76EE\u6807\u73AF\u5883\u5E76\u8DD1\u901A\u7AEF\u5230\u7AEF\u8054\u8C03\uFF0C\u4EA7\u51FA\u53EF\u8BBF\u95EE\u7684\u90E8\u7F72\u5730\u5740 + \u90E8\u7F72\u8BB0\u5F55\uFF08\u73AF\u5883/\u670D\u52A1/\u7AEF\u53E3/\u5065\u5EB7\u68C0\u67E5\u8BC1\u636E\uFF09\u3002**\u4F9D\u8D56\u5BF9\u5E94\u7684 dev \u8282\u70B9\uFF08required\uFF09\uFF0C\u6392\u5728\u5B83\u4E4B\u540E\uFF1B\u82E5\u672C\u5DE5\u5355\u6709 adr\uFF08\u6280\u672F\u65B9\u6848\uFF0C\u542B CI/CD \u4E0E\u90E8\u7F72\u73AF\u5883\u51B3\u7B56\uFF09\uFF0C\u4E5F\u5E94\u4F9D\u8D56\u8BE5 adr\u2014\u2014\u5982\u6B64\u6280\u672F\u65B9\u6848\u6216\u4EE3\u7801\u4E00\u51FA\u65B0\u91CC\u7A0B\u7891\uFF0C\u672C\u8282\u70B9\u5373\u88AB\u7EA7\u8054\u8FD4\u5DE5\u91CD\u65B0\u90E8\u7F72\uFF08ADR-0067\uFF09\u3002** \u5EFA\u56FE/\u8865\u56FE\u65F6\uFF0C\u5F53\u5DE5\u5355\u9700\u8981\u771F\u90E8\u7F72/\u4E0A\u7EBF\u800C\u975E\u4EC5\u4EA4\u4ED8\u4EE3\u7801\u65F6\u65B0\u589E\u6B64\u8282\u70B9\u3002\u5065\u5EB7\u68C0\u67E5\u987B\u5916\u90E8\u53EF\u8FBE\u3001\u7981\u5047\u7EFF\uFF1B\u4E0B\u6E38\uFF08\u5982 QA\uFF09\u53D1\u73B0\u90E8\u7F72\u7ED3\u679C\u4E0D\u5BF9\u65F6\u5BF9\u672C\u8282\u70B9\u56DE\u538B\uFF08annotate --from\uFF09\u3002\u6536\u5C3E\u524D\u987B\u5148\u771F\u8DD1\u5916\u90E8\u5065\u5EB7\u63A2\u9488\u3001\u518D `oasis record-action <\u672C\u8282\u70B9> --name health_probe --pass true` \u7559\u75D5\uFF0C\u5426\u5219\u6536\u4E0D\u4E86\u53E3\u3002",
|
|
136394
|
+
reviews: { gates: [{ on: "conclude", reviewers: ["qa"], quorum: 1 }] },
|
|
136395
|
+
// grounding:必须有「通过的健康探针」留痕才收口(ADR-0070/§9.2)。机械堵假绿——force 也豁免不了。
|
|
136396
|
+
grounding: { requiredActions: [{ name: "health_probe", mustPass: true }] }
|
|
136068
136397
|
}
|
|
136069
136398
|
];
|
|
136070
136399
|
WORKORDER_SPEC_PREFIX = "OASIS_WORKORDER_SPEC ";
|
|
@@ -136189,6 +136518,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
|
|
|
136189
136518
|
};
|
|
136190
136519
|
};
|
|
136191
136520
|
const runtimeByArtifact = buildRuntimeByArtifact(dispatchJournal, ref2);
|
|
136521
|
+
const hasDeliverySummary = arts.some((a) => a.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
136192
136522
|
const nodes = arts.map((a) => {
|
|
136193
136523
|
const info = nodeInfo(model, a);
|
|
136194
136524
|
const observedRuntime = runtimeByArtifact.get(a.id);
|
|
@@ -136217,6 +136547,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
|
|
|
136217
136547
|
queue: info.queueLen,
|
|
136218
136548
|
blocked: blockedOf(model, a.id).blocked,
|
|
136219
136549
|
owner: ref2(a.owner),
|
|
136550
|
+
...(hasDeliverySummary ? a.type === DELIVERY_SUMMARY_ARTIFACT_TYPE : a.isFinalOutput === true) ? { isFinalOutput: true } : {},
|
|
136220
136551
|
// 封存原因透出:stage 只到 "sealed" 粒度,原因(accepted/cancelled/frozen)另给,供前端区分展示。
|
|
136221
136552
|
...lifecycle !== "active" ? { sealedReason: lifecycle.slice("sealed:".length) } : {},
|
|
136222
136553
|
...runtime ? { runtime } : {},
|
|
@@ -136290,6 +136621,7 @@ function buildWorkorderDraftDetail(draft, resolveActor, typeReviewerPreview) {
|
|
|
136290
136621
|
return { id, ...extra?.name ? { name: extra.name } : {}, ...extra?.role ? { role: extra.role } : {}, ...extra?.avatar ? { avatar: extra.avatar } : {} };
|
|
136291
136622
|
};
|
|
136292
136623
|
const spawns = draft.plan.ops.filter((op) => op.action === "spawn" && !!op.id);
|
|
136624
|
+
const hasDeliverySummary = spawns.some((op) => op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE);
|
|
136293
136625
|
const nodes = spawns.map((op) => {
|
|
136294
136626
|
const manual = draft.plan.ops.find((o) => o.action === "edit" && o.artifactId === op.id)?.reviewers?.filter((r) => r.source === "manual").map((r) => r.actor) ?? [];
|
|
136295
136627
|
const typePv = typeReviewerPreview?.(op.type) ?? null;
|
|
@@ -136303,6 +136635,7 @@ function buildWorkorderDraftDetail(draft, resolveActor, typeReviewerPreview) {
|
|
|
136303
136635
|
queue: 0,
|
|
136304
136636
|
blocked: false,
|
|
136305
136637
|
owner: ref2(op.owner ?? draft.draftedBy),
|
|
136638
|
+
...(hasDeliverySummary ? op.type === DELIVERY_SUMMARY_ARTIFACT_TYPE : op.isFinalOutput === true) ? { isFinalOutput: true } : {},
|
|
136306
136639
|
...pv ? { reviewers: pv.reviewers.map((r) => ({ actor: ref2(r.actor), source: r.source })), quorum: pv.quorum, typeName: pv.typeName } : {}
|
|
136307
136640
|
};
|
|
136308
136641
|
});
|
|
@@ -136581,6 +136914,7 @@ var init_workorder_detail = __esm({
|
|
|
136581
136914
|
"../server/src/domains/collab/workorder-detail.ts"() {
|
|
136582
136915
|
"use strict";
|
|
136583
136916
|
init_src2();
|
|
136917
|
+
init_src();
|
|
136584
136918
|
init_node_state();
|
|
136585
136919
|
init_stall();
|
|
136586
136920
|
init_workorders();
|
|
@@ -137478,10 +137812,11 @@ async function runCommand(kernel, blobs, oplog, actor, command, args, ctx = {})
|
|
|
137478
137812
|
const goal = optStr(args, "goal");
|
|
137479
137813
|
const rawCriteria = args["acceptance_criteria"] ?? args["acceptanceCriteria"];
|
|
137480
137814
|
const acceptanceCriteria = Array.isArray(rawCriteria) ? rawCriteria.filter((x2) => typeof x2 === "string" && x2.trim().length > 0).map((x2) => x2.trim()) : void 0;
|
|
137481
|
-
const briefForPlanner =
|
|
137482
|
-
|
|
137483
|
-
|
|
137484
|
-
${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}` :
|
|
137815
|
+
const briefForPlanner = [
|
|
137816
|
+
brief,
|
|
137817
|
+
...acceptanceCriteria && acceptanceCriteria.length > 0 ? [`\u9A8C\u6536\u6807\u51C6\uFF1A
|
|
137818
|
+
${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}`] : []
|
|
137819
|
+
].join("\n\n");
|
|
137485
137820
|
const agentIssues = [];
|
|
137486
137821
|
let agentPlan = null;
|
|
137487
137822
|
const inlinePlan = args["plan"];
|
|
@@ -137629,7 +137964,6 @@ ${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}` : brief;
|
|
|
137629
137964
|
return annotation !== void 0 && isHumanChangeRequest(annotation);
|
|
137630
137965
|
}) : hasOpenHumanChangeRequest2(kernel, artifactId));
|
|
137631
137966
|
const changeRequestParent = resolves !== void 0 ? latestDeclaredRevisionAnchor(kernel, resolves) : isAgent(actor) ? latestOpenHumanChangeRequestParent(kernel, artifactId) : void 0;
|
|
137632
|
-
const holdForReview = args["holdForReview"] === true || args["review"] === true;
|
|
137633
137967
|
const continuation = args["continuation"];
|
|
137634
137968
|
if (continuation !== void 0 && (continuation === null || typeof continuation !== "object" || continuation.checkpoint !== true || continuation.continue !== true)) {
|
|
137635
137969
|
throw new Error("continuation \u5FC5\u987B\u662F { checkpoint: true, continue: true }");
|
|
@@ -137653,7 +137987,7 @@ ${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}` : brief;
|
|
|
137653
137987
|
const typeDefForLand = artForLand ? ctx.schema?.find((t) => t.name === artForLand.type) : void 0;
|
|
137654
137988
|
const isExternalFF = handlerForType(typeDefForLand?.contentType)?.mergeMode === "external-ff";
|
|
137655
137989
|
let landed = false;
|
|
137656
|
-
if (!
|
|
137990
|
+
if (!requiresHumanReview && qBefore === 0 && (revision.part === void 0 || parts.length <= 1 || isExternalFF)) {
|
|
137657
137991
|
try {
|
|
137658
137992
|
const r = await kernel.advanceQueue(artifactId, actor);
|
|
137659
137993
|
landed = r.landed.some((x2) => x2.id === revision.id);
|
|
@@ -137661,7 +137995,8 @@ ${acceptanceCriteria.map((c) => `- ${c}`).join("\n")}` : brief;
|
|
|
137661
137995
|
} catch {
|
|
137662
137996
|
}
|
|
137663
137997
|
}
|
|
137664
|
-
|
|
137998
|
+
const tail = landed ? " \u2192 \u5DF2\u843D\u5730\u4E3A head" : requiresHumanReview ? " \u2192 \u7B49\u5F85\u4EBA\u5DE5\u5BA1\u6838" : pendingConcludeAttempt(kernel.model, artifactId) ? " \u2192 \u5DF2\u5165\u961F\uFF1B\u5F53\u524D\u4EA7\u7269\u6B63\u5728\u6536\u5C3E\u8BC4\u5BA1\uFF08\u6682\u51BB\u7ED3\uFF09\uFF0C\u8BC4\u5BA1\u51FA\u7ED3\u679C\u3001\u89E3\u51BB\u540E\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u628A\u5B83\u843D\u4E3A head\u2014\u2014\u65E0\u9700\u91CD\u8BD5" : kernel.isFrozen(artifactId) ? " \u2192 \u5DF2\u5165\u961F\uFF1B\u5F53\u524D\u4EA7\u7269\u88AB\u51BB\u7ED3\uFF08\u96C6\u6210/\u6539\u56FE\u4E2D\uFF09\uFF0C\u89E3\u51BB\u540E\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u63A8\u8FDB\u2014\u2014\u65E0\u9700\u91CD\u8BD5" : "";
|
|
137999
|
+
return { message: `proposed ${revision.id} base=${revision.base ?? "\u2205"}\uFF08${revision.contentKind}\uFF09${revision.part ? ` part=${revision.part}` : ""}${tail}`, data: revision };
|
|
137665
138000
|
}
|
|
137666
138001
|
case "merge": {
|
|
137667
138002
|
const revisionId = optStr(args, "revisionId");
|
|
@@ -138505,6 +138840,8 @@ async function startOasisServer(opts) {
|
|
|
138505
138840
|
);
|
|
138506
138841
|
return;
|
|
138507
138842
|
}
|
|
138843
|
+
const trustedDraft = targetWs && opts.workorderDrafts ? await opts.workorderDrafts.forWorkspace(targetWs) : void 0;
|
|
138844
|
+
assertDeliverySummaryPlanIntegrity(body.plan, trustedDraft?.plan);
|
|
138508
138845
|
const principalRegistry = engine.registry ?? opts.registry;
|
|
138509
138846
|
if (principalRegistry) {
|
|
138510
138847
|
const principalErrors = await validateWorkorderPrincipals(body.plan, body.briefArtifactId, (id) => principalRegistry.getActor(id));
|
|
@@ -138660,71 +138997,26 @@ async function startOasisServer(opts) {
|
|
|
138660
138997
|
try {
|
|
138661
138998
|
const body = JSON.parse(rawBody || "{}");
|
|
138662
138999
|
const ctx = resolveDiscussContext(engine.kernel.model, body, actor ?? void 0);
|
|
138663
|
-
let retainedRt = opts.retainedSession?.(
|
|
138664
|
-
body.annotationId ? { annotationId: body.annotationId, ...ctx.anchorArtifactId ? { artifactId: ctx.anchorArtifactId } : {} } : body
|
|
138665
|
-
);
|
|
138666
|
-
if (!retainedRt && opts.escalateDiscussRetain && body.artifactId) {
|
|
138667
|
-
const raw = opts.escalateDiscussRetain.get(`esc:${body.artifactId}`);
|
|
138668
|
-
if (raw) {
|
|
138669
|
-
try {
|
|
138670
|
-
const rec = JSON.parse(raw);
|
|
138671
|
-
if (rec.runtimeSessionId && rec.human === ctx.ownerId) retainedRt = rec.runtimeSessionId;
|
|
138672
|
-
} catch {
|
|
138673
|
-
}
|
|
138674
|
-
}
|
|
138675
|
-
}
|
|
138676
|
-
if (retainedRt && body.draftId && opts.escalateDiscussRetain) {
|
|
138677
|
-
const claimKey = `draftclaim:${body.draftId}`;
|
|
138678
|
-
const claimer = opts.escalateDiscussRetain.get(claimKey);
|
|
138679
|
-
if (claimer && claimer !== ctx.ownerId) retainedRt = void 0;
|
|
138680
|
-
else if (!claimer) opts.escalateDiscussRetain.set(claimKey, ctx.ownerId);
|
|
138681
|
-
}
|
|
138682
139000
|
const chatStore = opts.chatSession;
|
|
138683
139001
|
const baseItemKey = body.draftId ? `draft:${body.draftId}` : body.annotationId ? `ann:${body.annotationId}` : `esc:${body.artifactId}`;
|
|
138684
139002
|
const itemKey = `${baseItemKey}:${ctx.ownerId}`;
|
|
138685
139003
|
let chatSessionId;
|
|
138686
|
-
let createdThisCall = false;
|
|
138687
139004
|
if (chatStore) {
|
|
138688
139005
|
const { randomUUID: randomUUID22 } = await import("node:crypto");
|
|
138689
139006
|
const known = discussSessions.get(itemKey);
|
|
138690
139007
|
if (known && await chatStore.getSession(known).catch(() => null)) chatSessionId = known;
|
|
138691
139008
|
if (!chatSessionId) {
|
|
138692
139009
|
chatSessionId = randomUUID22();
|
|
138693
|
-
createdThisCall = true;
|
|
138694
139010
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
138695
139011
|
const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
|
|
138696
139012
|
const reg0 = (await resolveEngine(currentCompanyId).catch(() => null))?.registry ?? opts.registry;
|
|
138697
139013
|
const mgrBinding = reg0 ? await reg0.getBinding(ctx.managerId).catch(() => null) : null;
|
|
138698
139014
|
const managerNodeId = mgrBinding?.status === "active" ? mgrBinding.nodeId : "";
|
|
138699
139015
|
const managerRuntimeKind = mgrBinding?.status === "active" ? mgrBinding.runtimeKind : void 0;
|
|
138700
|
-
await chatStore.createSession({ id: chatSessionId, humanActorId: ctx.ownerId, aiActorId: ctx.managerId, runtimeId: managerNodeId, ...managerRuntimeKind ? { runtimeKind: managerRuntimeKind } : {}, runtimeSessionId:
|
|
139016
|
+
await chatStore.createSession({ id: chatSessionId, humanActorId: ctx.ownerId, aiActorId: ctx.managerId, runtimeId: managerNodeId, ...managerRuntimeKind ? { runtimeKind: managerRuntimeKind } : {}, runtimeSessionId: null, title, touchedAt: now, createdAt: now, workspace: ctx.workspace }).catch(() => void 0);
|
|
138701
139017
|
await chatStore.linkWorkOrder(chatSessionId, ctx.workspace).catch(() => void 0);
|
|
138702
139018
|
}
|
|
138703
139019
|
discussSessions.set(itemKey, chatSessionId);
|
|
138704
|
-
await chatStore.appendMessage({ id: randomUUID22(), sessionId: chatSessionId, role: "user", content: ctx.seed, createdAt: (/* @__PURE__ */ new Date()).toISOString() }).catch(() => void 0);
|
|
138705
|
-
}
|
|
138706
|
-
let session;
|
|
138707
|
-
try {
|
|
138708
|
-
session = await opts.dispatchChat({ actorId: ctx.managerId, message: ctx.seed, workspace: ctx.workspace, ...retainedRt ? { sessionId: retainedRt } : {}, ...chatSessionId ? { chatSessionId } : {} });
|
|
138709
|
-
} catch (err) {
|
|
138710
|
-
if (createdThisCall && chatStore && chatSessionId) {
|
|
138711
|
-
await chatStore.deleteSession(chatSessionId).catch(() => void 0);
|
|
138712
|
-
discussSessions.delete(itemKey);
|
|
138713
|
-
}
|
|
138714
|
-
throw err;
|
|
138715
|
-
}
|
|
138716
|
-
if (chatStore && chatSessionId) {
|
|
138717
|
-
const sid = chatSessionId;
|
|
138718
|
-
let reply = "";
|
|
138719
|
-
session.onOutput((chunk) => {
|
|
138720
|
-
reply += chunk;
|
|
138721
|
-
});
|
|
138722
|
-
void session.done.then(async () => {
|
|
138723
|
-
const { randomUUID: randomUUID22 } = await import("node:crypto");
|
|
138724
|
-
if (reply || session.runId) {
|
|
138725
|
-
await chatStore.appendMessage({ id: randomUUID22(), sessionId: sid, role: "assistant", content: reply, createdAt: (/* @__PURE__ */ new Date()).toISOString(), ...session.runId ? { runId: session.runId } : {} }).catch(() => void 0);
|
|
138726
|
-
}
|
|
138727
|
-
}).catch(() => void 0);
|
|
138728
139020
|
}
|
|
138729
139021
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ sessionId: chatSessionId ?? null, managerId: ctx.managerId, workspace: ctx.workspace }));
|
|
138730
139022
|
} catch (err) {
|
|
@@ -139313,8 +139605,8 @@ async function startOasisServer(opts) {
|
|
|
139313
139605
|
if (actorCtx) {
|
|
139314
139606
|
const { mkdtempSync: mkdtempSync5, mkdirSync: mkdirSync17, writeFileSync: writeFileSync15 } = await import("node:fs");
|
|
139315
139607
|
const { join: join24, dirname: dirname20 } = await import("node:path");
|
|
139316
|
-
const { tmpdir:
|
|
139317
|
-
const dir = mkdtempSync5(join24(
|
|
139608
|
+
const { tmpdir: tmpdir9 } = await import("node:os");
|
|
139609
|
+
const dir = mkdtempSync5(join24(tmpdir9(), "oasis-chat-"));
|
|
139318
139610
|
if (actorCtx.config?.prompt) {
|
|
139319
139611
|
for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
139320
139612
|
const file = join24(dir, rel);
|
|
@@ -143613,6 +143905,7 @@ async function seedRoleCatalog(store, src) {
|
|
|
143613
143905
|
await store.put({
|
|
143614
143906
|
name,
|
|
143615
143907
|
label: known?.label ?? fallbackLabel(name),
|
|
143908
|
+
...known?.description ? { description: known.description } : {},
|
|
143616
143909
|
...known?.accent ? { appearance: { accent: known.accent } } : {},
|
|
143617
143910
|
status: "active"
|
|
143618
143911
|
});
|
|
@@ -143627,13 +143920,17 @@ var init_roles_seed = __esm({
|
|
|
143627
143920
|
"use strict";
|
|
143628
143921
|
KNOWN = {
|
|
143629
143922
|
founder: { label: "\u521B\u59CB\u4EBA", accent: "slate" },
|
|
143630
|
-
pm: { label: "\u9700\u6C42\u5206\u6790", accent: "blue" },
|
|
143631
|
-
architect: { label: "\u67B6\u6784\u8BBE\u8BA1", accent: "violet" },
|
|
143632
|
-
designer: { label: "\u754C\u9762\u8BBE\u8BA1", accent: "fuchsia" },
|
|
143633
|
-
research: { label: "\u5E02\u573A\u8C03\u7814", accent: "cyan" },
|
|
143634
|
-
dev: { label: "\u4EE3\u7801\u5B9E\u73B0", accent: "emerald" },
|
|
143635
|
-
qa: { label: "\u8D28\u91CF\u4FDD\u969C", accent: "rose" },
|
|
143636
|
-
devops: {
|
|
143923
|
+
pm: { label: "\u9700\u6C42\u5206\u6790", accent: "blue", description: "\u628A\u8BC9\u6C42\u62C6\u6210 PRD \u4E0E\u9A8C\u6536\u6807\u51C6\uFF0C\u505A\u4EA7\u54C1\u51B3\u7B56\u4E0E\u4F18\u5148\u7EA7\u3002" },
|
|
143924
|
+
architect: { label: "\u67B6\u6784\u8BBE\u8BA1", accent: "violet", description: "\u6280\u672F\u9009\u578B\u3001\u7CFB\u7EDF\u67B6\u6784\u3001\u63A5\u53E3\u5951\u7EA6\u3001ADR\uFF1B\u628A\u6280\u672F\u65B9\u6848\u843D\u6210\u53EF\u5B9E\u73B0\u7684\u51B3\u7B56\u3002" },
|
|
143925
|
+
designer: { label: "\u754C\u9762\u8BBE\u8BA1", accent: "fuchsia", description: "\u754C\u9762\u4E0E\u4EA4\u4E92\u8BBE\u8BA1\u3001\u8BBE\u8BA1\u7CFB\u7EDF\u4E0E\u89C6\u89C9\u89C4\u8303\u3002" },
|
|
143926
|
+
research: { label: "\u5E02\u573A\u8C03\u7814", accent: "cyan", description: "\u7ADE\u54C1\u3001\u5E02\u573A\u3001\u7528\u6237\u4E0E\u5B9A\u4EF7\u7B49\u8C03\u7814\u3002" },
|
|
143927
|
+
dev: { label: "\u4EE3\u7801\u5B9E\u73B0", accent: "emerald", description: "\u6309\u63A5\u53E3\u5951\u7EA6\u5B9E\u73B0\u524D\u540E\u7AEF\u4EE3\u7801\u3002" },
|
|
143928
|
+
qa: { label: "\u8D28\u91CF\u4FDD\u969C", accent: "rose", description: "\u6D4B\u8BD5\u89C4\u5212\u3001\u771F\u673A\u9A8C\u6536\u4E0E\u56DE\u5F52\uFF1B\u53D1\u73B0\u95EE\u9898\u56DE\u538B\u5BF9\u5E94\u4EA7\u51FA\u8282\u70B9\u3002" },
|
|
143929
|
+
devops: {
|
|
143930
|
+
label: "\u8FD0\u7EF4\u90E8\u7F72",
|
|
143931
|
+
accent: "amber",
|
|
143932
|
+
description: "\u5E73\u53F0\u5DE5\u7A0B\uFF1A\u4EE3\u7801\u4ED3\u5E93\u4F9B\u7ED9\uFF08\u5EFA\u4ED3\uFF09\u3001CI/CD \u6D41\u6C34\u7EBF\u4E0E GitHub Actions\u3001\u7EC4\u7EC7\u8D44\u4EA7\u53F0\u8D26\u7EF4\u62A4\uFF0C\u4EE5\u53CA\u771F\u5B9E\u90E8\u7F72\u4E0E\u8054\u8C03\uFF1B\u5176\u5B83\u73AF\u8282\u51FA\u73B0\u90E8\u7F72/\u8FD0\u7EF4\u7C7B\u95EE\u9898\u65F6\u515C\u5E95\u3002\u8D1F\u8D23 provision \u4E0E deploy \u4EA4\u4ED8\u7269\u7C7B\u578B\u3002"
|
|
143933
|
+
},
|
|
143637
143934
|
writer: { label: "\u6587\u6863\u64B0\u5199", accent: "slate" },
|
|
143638
143935
|
"design-lead": { label: "\u8BBE\u8BA1\u8D1F\u8D23\u4EBA", accent: "fuchsia" },
|
|
143639
143936
|
"eng-lead": { label: "\u6280\u672F\u8D1F\u8D23\u4EBA", accent: "violet" }
|
|
@@ -146792,13 +147089,46 @@ async function startDesignRun(base, fetchImpl, args) {
|
|
|
146792
147089
|
async function fetchResultPackage(base, fetchImpl, runId) {
|
|
146793
147090
|
const body = await odApi(base, fetchImpl, "GET", `/api/runs/${encodeURIComponent(runId)}/result-package`);
|
|
146794
147091
|
const artifacts = (body.artifacts ?? []).map((a) => ({
|
|
146795
|
-
path: a.path ?? "",
|
|
147092
|
+
path: a.path ?? a.file ?? "",
|
|
146796
147093
|
kind: a.kind ?? null,
|
|
146797
147094
|
title: a.title ?? null,
|
|
146798
147095
|
status: a.status ?? null
|
|
146799
147096
|
}));
|
|
146800
147097
|
return { artifacts, fileCount: body.project?.fileCount ?? artifacts.length };
|
|
146801
147098
|
}
|
|
147099
|
+
async function fetchBoardStatus(base, fetchImpl, artifactId) {
|
|
147100
|
+
const boardKey = deriveBoardKey(artifactId);
|
|
147101
|
+
let boardExists = true;
|
|
147102
|
+
let artifacts = [];
|
|
147103
|
+
try {
|
|
147104
|
+
const listing = await odApi(
|
|
147105
|
+
base,
|
|
147106
|
+
fetchImpl,
|
|
147107
|
+
"GET",
|
|
147108
|
+
`/api/projects/${encodeURIComponent(boardKey)}/files`
|
|
147109
|
+
);
|
|
147110
|
+
artifacts = (listing.files ?? []).filter((f2) => !f2.path.startsWith("task-context/") && f2.artifactManifest !== void 0).map((f2) => ({ path: f2.path, kind: f2.kind ?? null, status: f2.artifactManifest?.status ?? null, mtime: f2.mtime ?? null })).sort((a, b2) => (b2.mtime ?? 0) - (a.mtime ?? 0));
|
|
147111
|
+
} catch {
|
|
147112
|
+
boardExists = false;
|
|
147113
|
+
}
|
|
147114
|
+
let runs = [];
|
|
147115
|
+
if (boardExists) {
|
|
147116
|
+
try {
|
|
147117
|
+
const body = await odApi(
|
|
147118
|
+
base,
|
|
147119
|
+
fetchImpl,
|
|
147120
|
+
"GET",
|
|
147121
|
+
`/api/runs?projectId=${encodeURIComponent(boardKey)}`
|
|
147122
|
+
);
|
|
147123
|
+
runs = (body.runs ?? []).map((r) => ({
|
|
147124
|
+
runId: String(r["runId"] ?? r["id"] ?? ""),
|
|
147125
|
+
status: String(r["status"] ?? "unknown")
|
|
147126
|
+
}));
|
|
147127
|
+
} catch {
|
|
147128
|
+
}
|
|
147129
|
+
}
|
|
147130
|
+
return { boardKey, boardExists, runs, artifacts };
|
|
147131
|
+
}
|
|
146802
147132
|
async function pumpDesignEvents(base, fetchImpl, runId, onLine) {
|
|
146803
147133
|
const res = await fetchImpl(`${base}/api/runs/${runId}/events`);
|
|
146804
147134
|
if (!res.ok || !res.body) return;
|
|
@@ -146852,11 +147182,16 @@ async function harvestBoard(base, fetchImpl, publicBase, workRoot, boardKey, run
|
|
|
146852
147182
|
if (!res.ok) throw new Error(`od export ${rel} \u2192 ${res.status}`);
|
|
146853
147183
|
return await res.text();
|
|
146854
147184
|
};
|
|
147185
|
+
const fetchRaw = async (rel) => {
|
|
147186
|
+
const res = await fetchImpl(`${base}/api/projects/${encodeURIComponent(boardKey)}/raw/${rel.split("/").map(encodeURIComponent).join("/")}`);
|
|
147187
|
+
if (!res.ok) throw new Error(`od raw ${rel} \u2192 ${res.status}`);
|
|
147188
|
+
return await res.text();
|
|
147189
|
+
};
|
|
146855
147190
|
fs8.writeFileSync(path7.join(dir, "index.html"), await fetchInline(entry));
|
|
146856
147191
|
for (const f2 of listing.files ?? []) {
|
|
146857
147192
|
if (f2.path.endsWith(".md") && !f2.path.includes("/")) {
|
|
146858
147193
|
try {
|
|
146859
|
-
fs8.writeFileSync(path7.join(dir, f2.path), await
|
|
147194
|
+
fs8.writeFileSync(path7.join(dir, f2.path), await fetchRaw(f2.path));
|
|
146860
147195
|
} catch {
|
|
146861
147196
|
}
|
|
146862
147197
|
}
|
|
@@ -146895,7 +147230,7 @@ async function runOpenDesignSession(opts) {
|
|
|
146895
147230
|
const { dir, entry } = await harvestBoard(opts.base, fetchImpl, opts.publicBase, workRoot, boardKey, runId);
|
|
146896
147231
|
return { dir, entry, boardKey, runId };
|
|
146897
147232
|
}
|
|
146898
|
-
async function
|
|
147233
|
+
async function startDesignChatTurn(opts) {
|
|
146899
147234
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
146900
147235
|
const boardKey = deriveBoardKey(opts.artifactId);
|
|
146901
147236
|
const { conversationId, resolvedDir } = await ensureProject(opts.base, fetchImpl, boardKey, opts.title);
|
|
@@ -146908,6 +147243,11 @@ async function runDesignChatTurn(opts) {
|
|
|
146908
147243
|
message: opts.message,
|
|
146909
147244
|
...opts.systemPrompt !== void 0 ? { systemPrompt: opts.systemPrompt } : {}
|
|
146910
147245
|
});
|
|
147246
|
+
return { boardKey, conversationId, runId, userMessageId };
|
|
147247
|
+
}
|
|
147248
|
+
async function runDesignChatTurn(opts) {
|
|
147249
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
147250
|
+
const { boardKey, conversationId, runId, userMessageId } = await startDesignChatTurn(opts);
|
|
146911
147251
|
if (opts.onLine) void pumpDesignEvents(opts.base, fetchImpl, runId, opts.onLine).catch(() => {
|
|
146912
147252
|
});
|
|
146913
147253
|
const status = await pollDesignRun(opts.base, fetchImpl, runId, {
|
|
@@ -147300,12 +147640,12 @@ function scrubLeakyEnv(env) {
|
|
|
147300
147640
|
}
|
|
147301
147641
|
function classifyExit(result) {
|
|
147302
147642
|
if (!result) return void 0;
|
|
147303
|
-
|
|
147304
|
-
|
|
147305
|
-
if (
|
|
147306
|
-
|
|
147307
|
-
if (
|
|
147308
|
-
return
|
|
147643
|
+
if (result.stop_reason === "max_tokens") return "output-limit";
|
|
147644
|
+
const subtypeSaysError = String(result.subtype ?? "").startsWith("error");
|
|
147645
|
+
if (result.is_error !== true && !subtypeSaysError) return "clean";
|
|
147646
|
+
const status = Number(result.api_error_status);
|
|
147647
|
+
if (status === 429 || status === 529) return "rate-limit";
|
|
147648
|
+
return "error";
|
|
147309
147649
|
}
|
|
147310
147650
|
var import_node_child_process7, import_node_crypto13, fs10, path9, readline, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
|
|
147311
147651
|
var init_claude_code = __esm({
|
|
@@ -157335,7 +157675,7 @@ ${body || "\uFF08\u672A\u586B\u5199\uFF09"}`;
|
|
|
157335
157675
|
"\u7531\u300C\u5267\u672C \xB7 Bug \u4FEE\u590D\u300D\u53D1\u8D77\u3002"
|
|
157336
157676
|
].join("\n");
|
|
157337
157677
|
const plan = {
|
|
157338
|
-
nodes: BUG_FIX_STRUCTURE.map((n) => ({ type: n.type, title: n.title, dependsOn: n.dependsOn, brief: n.brief(title) }))
|
|
157678
|
+
nodes: BUG_FIX_STRUCTURE.map((n) => ({ type: n.type, title: n.title, dependsOn: n.dependsOn, brief: n.brief(title), ...n.isFinalOutput ? { isFinalOutput: true } : {} }))
|
|
157339
157679
|
};
|
|
157340
157680
|
return {
|
|
157341
157681
|
produces: "workorder",
|
|
@@ -157397,7 +157737,8 @@ var init_registry2 = __esm({
|
|
|
157397
157737
|
title: "\u590D\u73B0\u9A8C\u8BC1\u4E0E\u56DE\u5F52",
|
|
157398
157738
|
dependsOn: ["dev:\u4FEE\u590D\u5B9E\u73B0"],
|
|
157399
157739
|
role: "\u6D4B\u8BD5",
|
|
157400
|
-
brief: () => `\u6309 brief \u91CC\u7684\u590D\u73B0\u6B65\u9AA4\u9A8C\u8BC1 bug \u5DF2\u4FEE\u590D\uFF08\u4E0D\u518D\u590D\u73B0\uFF09\uFF1B\u8865\u5145\u5E76\u8FD0\u884C\u56DE\u5F52\u7528\u4F8B\uFF0C\u786E\u8BA4\u6CA1\u6709\u5F15\u5165\u65B0\u56DE\u5F52\u3002\u4EA7\u51FA\u6D4B\u8BD5\u62A5\u544A\u3002
|
|
157740
|
+
brief: () => `\u6309 brief \u91CC\u7684\u590D\u73B0\u6B65\u9AA4\u9A8C\u8BC1 bug \u5DF2\u4FEE\u590D\uFF08\u4E0D\u518D\u590D\u73B0\uFF09\uFF1B\u8865\u5145\u5E76\u8FD0\u884C\u56DE\u5F52\u7528\u4F8B\uFF0C\u786E\u8BA4\u6CA1\u6709\u5F15\u5165\u65B0\u56DE\u5F52\u3002\u4EA7\u51FA\u6D4B\u8BD5\u62A5\u544A\u3002`,
|
|
157741
|
+
isFinalOutput: true
|
|
157401
157742
|
}
|
|
157402
157743
|
];
|
|
157403
157744
|
BUILTIN2 = {
|
|
@@ -158999,6 +159340,94 @@ var init_builtin_skills = __esm({
|
|
|
158999
159340
|
}
|
|
159000
159341
|
});
|
|
159001
159342
|
|
|
159343
|
+
// ../server/src/design/board-watch.ts
|
|
159344
|
+
function decideBoardLetter(c, nowMs, quietMs) {
|
|
159345
|
+
if (c.boardMtime === null) return false;
|
|
159346
|
+
if (!c.hasRevision) return false;
|
|
159347
|
+
if (c.lastOpAtMs === null || c.boardMtime <= c.lastOpAtMs) return false;
|
|
159348
|
+
if (nowMs - c.boardMtime < quietMs) return false;
|
|
159349
|
+
if (c.hasOpenWatchLetter) return false;
|
|
159350
|
+
if (c.lastWatchMtime !== null && c.boardMtime <= c.lastWatchMtime) return false;
|
|
159351
|
+
return true;
|
|
159352
|
+
}
|
|
159353
|
+
var MARKER_PREFIX, boardWatchMarker, parseMarker, BoardWatcher;
|
|
159354
|
+
var init_board_watch = __esm({
|
|
159355
|
+
"../server/src/design/board-watch.ts"() {
|
|
159356
|
+
"use strict";
|
|
159357
|
+
init_src2();
|
|
159358
|
+
MARKER_PREFIX = "[od-board-watch mtime:";
|
|
159359
|
+
boardWatchMarker = (mtimeMs) => `${MARKER_PREFIX}${mtimeMs}]`;
|
|
159360
|
+
parseMarker = (body) => {
|
|
159361
|
+
const i = body.indexOf(MARKER_PREFIX);
|
|
159362
|
+
if (i < 0) return null;
|
|
159363
|
+
const n = Number.parseInt(body.slice(i + MARKER_PREFIX.length), 10);
|
|
159364
|
+
return Number.isFinite(n) ? n : null;
|
|
159365
|
+
};
|
|
159366
|
+
BoardWatcher = class {
|
|
159367
|
+
constructor(deps) {
|
|
159368
|
+
this.deps = deps;
|
|
159369
|
+
}
|
|
159370
|
+
/** 查一块板的交付物(排 task-context/、只算带 artifactManifest 的)。404/网络错 → null(板不存在)。 */
|
|
159371
|
+
async boardFiles(boardKey) {
|
|
159372
|
+
const fetchImpl = this.deps.fetchImpl ?? fetch;
|
|
159373
|
+
try {
|
|
159374
|
+
const res = await fetchImpl(`${this.deps.odBase}/api/projects/${encodeURIComponent(boardKey)}/files`);
|
|
159375
|
+
if (!res.ok) return null;
|
|
159376
|
+
const body = await res.json();
|
|
159377
|
+
return (body.files ?? []).filter((f2) => !f2.path.startsWith("task-context/") && f2.artifactManifest !== void 0).map((f2) => ({ path: f2.path, kind: f2.kind ?? null, mtime: f2.mtime ?? null }));
|
|
159378
|
+
} catch {
|
|
159379
|
+
return null;
|
|
159380
|
+
}
|
|
159381
|
+
}
|
|
159382
|
+
async tick(now = Date.now()) {
|
|
159383
|
+
const { kernel, boardKeyOf, log: log3 } = this.deps;
|
|
159384
|
+
const quietMs = this.deps.quietMs ?? 10 * 6e4;
|
|
159385
|
+
const maxPerTick = this.deps.maxLettersPerTick ?? 2;
|
|
159386
|
+
const actor = this.deps.actor ?? "actor:system";
|
|
159387
|
+
const model = kernel.model;
|
|
159388
|
+
let written = 0;
|
|
159389
|
+
for (const a of model.artifacts.values()) {
|
|
159390
|
+
if (a.type !== "design") continue;
|
|
159391
|
+
if (lifecycleOf(model, a.id) !== "active") continue;
|
|
159392
|
+
if (written >= maxPerTick) {
|
|
159393
|
+
log3?.(`[board-watch] \u672C\u8F6E\u5199\u4FE1\u5DF2\u8FBE\u4E0A\u9650 ${maxPerTick}\uFF0C\u5176\u4F59\u677F\u4E0B\u8F6E\u518D\u770B`);
|
|
159394
|
+
break;
|
|
159395
|
+
}
|
|
159396
|
+
const boardKey = boardKeyOf(a.id);
|
|
159397
|
+
const files = await this.boardFiles(boardKey);
|
|
159398
|
+
if (!files || files.length === 0) continue;
|
|
159399
|
+
const boardMtime = files.reduce((mx, f2) => f2.mtime !== null && (mx === null || f2.mtime > mx) ? f2.mtime : mx, null);
|
|
159400
|
+
const watchLetters = annotationsOf(model, a.id).filter((x2) => x2.author === actor && parseMarker(x2.body) !== null);
|
|
159401
|
+
const lastOpAt = model.lastOpAt.get(a.id);
|
|
159402
|
+
const candidate = {
|
|
159403
|
+
boardMtime,
|
|
159404
|
+
hasRevision: revisionsOf(model, a.id).length > 0,
|
|
159405
|
+
lastOpAtMs: lastOpAt ? Date.parse(lastOpAt) : null,
|
|
159406
|
+
hasOpenWatchLetter: watchLetters.some((x2) => x2.state === "open"),
|
|
159407
|
+
lastWatchMtime: watchLetters.reduce((mx, x2) => {
|
|
159408
|
+
const m2 = parseMarker(x2.body);
|
|
159409
|
+
return m2 !== null && (mx === null || m2 > mx) ? m2 : mx;
|
|
159410
|
+
}, null)
|
|
159411
|
+
};
|
|
159412
|
+
if (!decideBoardLetter(candidate, now, quietMs)) continue;
|
|
159413
|
+
const newest = files.filter((f2) => f2.mtime !== null && candidate.lastOpAtMs !== null && f2.mtime > candidate.lastOpAtMs).sort((x2, y) => (y.mtime ?? 0) - (x2.mtime ?? 0));
|
|
159414
|
+
const listed = (newest.length > 0 ? newest : files).slice(0, 5).map((f2) => `- ${f2.path}\uFF08${f2.kind ?? "?"}\uFF09\xB7 ${f2.mtime ? new Date(f2.mtime).toISOString() : "?"}`).join("\n");
|
|
159415
|
+
const body = [
|
|
159416
|
+
boardWatchMarker(boardMtime),
|
|
159417
|
+
`\u753B\u677F ${boardKey} \u4E0A\u6709 Oasis \u4E4B\u5916\u7684\u65B0\u52A8\u9759\uFF08\u4EBA\u5728\u677F\u4E0A\u5BF9\u8BDD/\u6539\u7A3F\uFF0C\u6216\u5F15\u64CE\u4EA7\u4E86\u6CA1\u4EBA\u6536\u7684\u65B0\u7248\uFF09\uFF0C\u6BD4\u672C\u4EA7\u7269\u6700\u8FD1\u4E00\u6B21\u64CD\u4F5C\uFF08${lastOpAt ?? "?"}\uFF09\u65B0\u3001\u4E14\u5DF2\u9759\u9ED8 ${Math.round(quietMs / 6e4)} \u5206\u949F\uFF1A`,
|
|
159418
|
+
listed,
|
|
159419
|
+
``,
|
|
159420
|
+
`\u8BF7\u53D6\u8D27\u6838\u5BF9\uFF1A\`oasis design status ${a.id} --pull\` \u2192 \u5185\u5BB9\u5408\u610F\u5C31 \`oasis propose ${a.id} --from-dir <\u76EE\u5F55> --reason "<\u6536\u5F55\u677F\u4E0A\u4EBA\u5DE5\u8FED\u4EE3>"\` \u6536\u5F55\u4E3A\u65B0\u7248\u672C\uFF1B\u4E0D\u5408\u610F/\u4E0D\u5FC5\u6536\u5F55\uFF0C\u56DE\u5E16\u8BF4\u660E\u540E\u6309 wontfix \u5904\u7406\u5373\u53EF\uFF08\u540C\u4E00\u7248\u4E0D\u4F1A\u518D\u6765\u4FE1\uFF09\u3002`
|
|
159421
|
+
].join("\n");
|
|
159422
|
+
await kernel.annotate({ artifactId: a.id, actor, body, kind: "comment" });
|
|
159423
|
+
written++;
|
|
159424
|
+
log3?.(`[board-watch] ${a.id} \u2190 \u677F ${boardKey} \u6709\u65B0\u5185\u5BB9\uFF08mtime=${new Date(boardMtime).toISOString()}\uFF09\u2192 \u5DF2\u5199\u4FE1\u5524 owner`);
|
|
159425
|
+
}
|
|
159426
|
+
}
|
|
159427
|
+
};
|
|
159428
|
+
}
|
|
159429
|
+
});
|
|
159430
|
+
|
|
159002
159431
|
// ../server/src/index.ts
|
|
159003
159432
|
var init_src7 = __esm({
|
|
159004
159433
|
"../server/src/index.ts"() {
|
|
@@ -159055,6 +159484,7 @@ var init_src7 = __esm({
|
|
|
159055
159484
|
init_workorder_drafts();
|
|
159056
159485
|
init_builtin_skills();
|
|
159057
159486
|
init_connector_skills();
|
|
159487
|
+
init_board_watch();
|
|
159058
159488
|
}
|
|
159059
159489
|
});
|
|
159060
159490
|
|
|
@@ -169772,6 +170202,14 @@ async function startServe(opts) {
|
|
|
169772
170202
|
console.error(`[cascade] ${action.artifactId} \u5931\u8D25: ${String(err)}`);
|
|
169773
170203
|
}
|
|
169774
170204
|
}
|
|
170205
|
+
for (const { artifactId } of computeAdvanceableRevisions(kernel.model, schemaMap)) {
|
|
170206
|
+
try {
|
|
170207
|
+
const landed = await kernel.advanceOrphans(artifactId);
|
|
170208
|
+
for (const rev of landed) console.log(`[self-heal] ${artifactId} \u8865\u843D\u5B64\u513F\u961F\u9996 ${rev.id}\uFF08\u89E3\u51BB\u540E\u9057\u7559\uFF0C60s \u5FAA\u73AF\u515C\u5E95\uFF09`);
|
|
170209
|
+
} catch (err) {
|
|
170210
|
+
console.error(`[self-heal] ${artifactId} \u8865\u843D\u5931\u8D25: ${String(err)}`);
|
|
170211
|
+
}
|
|
170212
|
+
}
|
|
169775
170213
|
for (const a of kernel.model.artifacts.values()) {
|
|
169776
170214
|
if (!a.owner.startsWith("actor:human:")) continue;
|
|
169777
170215
|
if (lifecycleOf(kernel.model, a.id) !== "active") continue;
|
|
@@ -170010,6 +170448,18 @@ async function startServe(opts) {
|
|
|
170010
170448
|
const automationTimer = setInterval(() => {
|
|
170011
170449
|
void automationScheduler.tick().catch((err) => console.error(`[automation-scheduler] tick \u5931\u8D25: ${String(err)}`));
|
|
170012
170450
|
}, 3e4);
|
|
170451
|
+
let boardWatchTimer;
|
|
170452
|
+
const boardWatchFlag = (process.env["OASIS_BOARD_WATCH"] ?? "").trim().toLowerCase();
|
|
170453
|
+
if (!["0", "false", "off"].includes(boardWatchFlag)) {
|
|
170454
|
+
const odBase = (process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
170455
|
+
const boardWatcher = new BoardWatcher({ kernel, odBase, boardKeyOf: deriveBoardKey, log: (m2) => console.log(m2) });
|
|
170456
|
+
boardWatchTimer = setInterval(() => {
|
|
170457
|
+
void boardWatcher.tick().catch((err) => console.error(`[board-watch] tick \u5931\u8D25: ${String(err)}`));
|
|
170458
|
+
}, 6e4);
|
|
170459
|
+
console.log(`[serve] \u753B\u677F\u76D1\u89C6\u5668\u5DF2\u542F\u7528\uFF08od=${odBase}\uFF0C\u9759\u9ED8\u7A97 10min\uFF0C\u6BCF\u8F6E\u4E0A\u9650 2 \u5C01\u4FE1\uFF1BOASIS_BOARD_WATCH=0 \u53EF\u5173\uFF09`);
|
|
170460
|
+
} else {
|
|
170461
|
+
console.log(`[serve] \u753B\u677F\u76D1\u89C6\u5668\u5DF2\u88AB OASIS_BOARD_WATCH=${boardWatchFlag} \u663E\u5F0F\u5173\u95ED`);
|
|
170462
|
+
}
|
|
170013
170463
|
return {
|
|
170014
170464
|
baseUrl: server.baseUrl,
|
|
170015
170465
|
operatorToken,
|
|
@@ -170022,6 +170472,7 @@ async function startServe(opts) {
|
|
|
170022
170472
|
if (livenessTimer) clearInterval(livenessTimer);
|
|
170023
170473
|
if (orphanSweepTimer) clearInterval(orphanSweepTimer);
|
|
170024
170474
|
clearInterval(automationTimer);
|
|
170475
|
+
if (boardWatchTimer) clearInterval(boardWatchTimer);
|
|
170025
170476
|
clearInterval(serverHeartbeatTimer);
|
|
170026
170477
|
hub?.close();
|
|
170027
170478
|
await server.close();
|
|
@@ -170681,9 +171132,15 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
170681
171132
|
design run <artifactId> [--brief <t>] [--reason <t>] [--od-url <url>] [--title <t>] [--agent <id>]
|
|
170682
171133
|
# design \u4EA7\u7269\uFF1A\u5728\u901A\u7528 runtime \u4E0A\u9A71\u52A8 open-design \u753B\u677F\u5F15\u64CE\u4EA7\u754C\u9762\u7A3F\u5E76\u4EA4\u7A3F\uFF08\u63D0\u6848 design-node-runtime-to-cli-tool\uFF09\u3002
|
|
170683
171134
|
# --brief \u7F3A\u7701\u8BFB\u5F53\u524D\u76EE\u5F55 DESIGN_BRIEF.md\uFF08\u5176\u6B21 TASK.md\uFF09\uFF1B\u4E0A\u4E0B\u6587\u53D6\u5F53\u524D\u76EE\u5F55 inputs/\uFF1Bod \u5730\u5740\u7F3A\u7701 $OASIS_OPEN_DESIGN_URL \u6216\u672C\u673A 7457\u3002
|
|
171135
|
+
design chat <artifactId> --message <t> [--turn first|continue] [--async] [--system <t>]
|
|
171136
|
+
# \u591A\u8F6E\u5BF9\u8BDD\u9A71\u52A8\u753B\u677F\uFF08\u63D0\u6848 design-conversational-driving\uFF09\uFF1A\u4E0D\u81EA\u52A8\u4EA4\u7A3F\uFF0C\u8BFB\u4EA7\u7269\u540E\u81EA\u884C propose/gap\u3002
|
|
171137
|
+
# --async \u8D77\u5B8C\u5373\u8FD4\uFF08\u5F15\u64CE\u5728\u670D\u52A1\u7AEF\u8DD1 13\u201344min\uFF0C\u4E0E\u672C\u8FDB\u7A0B\u65E0\u5173\uFF09\uFF1B\u8FDB\u5EA6/\u53D6\u8D27\u7528 design status\u3002
|
|
171138
|
+
design status <artifactId> [--pull]
|
|
171139
|
+
# \u67E5\u753B\u677F\u73B0\u72B6\uFF08\u6062\u590D\u4F18\u5148\uFF09\uFF1A\u88AB\u6D3E\u53D1\u5148\u8DD1\u5B83\u2014\u2014\u5F15\u64CE\u5728\u8DD1\u5C31\u522B\u8D77\u65B0\u8F6E\uFF1B\u677F\u4E0A\u6709\u8D27 --pull \u62C9\u672C\u5730\u8BFB\uFF0C\u8BFB\u5B8C propose --from-dir\u3002
|
|
170684
171140
|
|
|
170685
171141
|
\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09
|
|
170686
171142
|
annotate <artifactId> --body <text> [--from <\u4E0B\u6E38> --blocks true]
|
|
171143
|
+
record-action <artifactId> --name <\u52A8\u4F5C\u540D> [--pass true] [--result <json>] [--params <json>] # \xA79.2 grounding \u7559\u75D5\uFF1A\u4E3A action_vs_oplog \u8BB0\u4E00\u6761\u901A\u8FC7\u7684 tool_call\uFF08\u771F\u8DD1\u8FC7\u5065\u5EB7\u63A2\u9488\u540E record-action --name health_probe --pass true\uFF09\uFF1B\u58F0\u660E\u4E86 requiredActions \u7684\u7C7B\u578B\u6CA1\u6709\u5B83 conclude \u4F1A\u88AB\u673A\u68B0\u62E6
|
|
170687
171144
|
resolve <annotationId> [--as resolved|wontfix|acknowledged]
|
|
170688
171145
|
gap <artifactId> --desc <text>
|
|
170689
171146
|
add-revision <artifactId> --desc <\u8981\u5B83\u5B8C\u6210\u4EC0\u4E48> [--role <\u8C01\u6765\u505A\uFF0C\u9ED8\u8BA4owner\u81EA\u5DF1>] # \xA79 \u592A\u5927\u5C31\u6D3E\u4E00\u6761\u5B50revision\u51FA\u53BB\u5E76\u884C\uFF0C\u6D3E\u5B8C\u53EF\u6536\u5DE5\u7B49\u7ED3\u679C
|
|
@@ -170742,7 +171199,7 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
170742
171199
|
function parseArgs(argv) {
|
|
170743
171200
|
const positional = [];
|
|
170744
171201
|
const flags = /* @__PURE__ */ new Map();
|
|
170745
|
-
const booleanFlags = /* @__PURE__ */ new Set(["checkpoint", "continue"]);
|
|
171202
|
+
const booleanFlags = /* @__PURE__ */ new Set(["checkpoint", "continue", "async", "pull"]);
|
|
170746
171203
|
for (let i = 0; i < argv.length; i++) {
|
|
170747
171204
|
const a = argv[i];
|
|
170748
171205
|
if (a.startsWith("--")) {
|
|
@@ -171594,15 +172051,25 @@ ${res.warning}`);
|
|
|
171594
172051
|
}
|
|
171595
172052
|
}
|
|
171596
172053
|
}
|
|
171597
|
-
|
|
171598
|
-
const turn = await runDesignChatTurn({
|
|
172054
|
+
const baseTurnOpts = {
|
|
171599
172055
|
base: odBase2,
|
|
171600
172056
|
agentId: flags.get("agent") ?? "claude",
|
|
171601
172057
|
artifactId: artifactId2,
|
|
171602
172058
|
title: flags.get("title") ?? artifactId2,
|
|
171603
172059
|
message: message2,
|
|
171604
172060
|
...flags.get("system") !== void 0 ? { systemPrompt: flags.get("system") } : {},
|
|
171605
|
-
...isContinue ? {} : { contextFiles: contextFiles2 }
|
|
172061
|
+
...isContinue ? {} : { contextFiles: contextFiles2 }
|
|
172062
|
+
};
|
|
172063
|
+
if (flags.get("async") === "true") {
|
|
172064
|
+
println(`[design] \u753B\u677F ${deriveBoardKey(artifactId2)} \u2190 ${artifactId2}\uFF1B${isContinue ? "\u7EED\u8F6E" : "\u9996\u8F6E"}\uFF08--async\uFF09\u2192 od \u5F15\u64CE ${odBase2} \u2026`);
|
|
172065
|
+
const started = await startDesignChatTurn(baseTurnOpts);
|
|
172066
|
+
println(`[design] \u5DF2\u4E0B\u5355\uFF1Arun ${started.runId.slice(0, 8)}\uFF08board ${started.boardKey}, \u53EF\u89C1 user \u56DE\u5408 ${started.userMessageId.slice(0, 8)}\uFF09\u3002\u5F15\u64CE\u901A\u5E38\u8981 13\u201344 \u5206\u949F\u3002`);
|
|
172067
|
+
println(`[design] \u4E4B\u540E\u7528 oasis design status ${artifactId2} \u67E5\u8FDB\u5EA6/\u53D6\u8D27\uFF08--pull \u62C9\u4EA7\u7269\u5230\u672C\u5730\u8BFB\uFF09\uFF1B\u4E0D\u5FC5\u5B88\u7740\u7B49\u3002`);
|
|
172068
|
+
break;
|
|
172069
|
+
}
|
|
172070
|
+
println(`[design] \u753B\u677F ${deriveBoardKey(artifactId2)} \u2190 ${artifactId2}\uFF1B${isContinue ? "\u7EED\u8F6E" : "\u9996\u8F6E"}\u5BF9\u8BDD\u9A71\u52A8 od \u5F15\u64CE ${odBase2} \u2026`);
|
|
172071
|
+
const turn = await runDesignChatTurn({
|
|
172072
|
+
...baseTurnOpts,
|
|
171606
172073
|
onLine: (line) => println(`[od] ${line.length > 500 ? line.slice(0, 500) + "\u2026" : line}`)
|
|
171607
172074
|
});
|
|
171608
172075
|
println(`[design] \u672C\u8F6E\u4EA4\u4ED8\uFF08board ${turn.boardKey}, run ${turn.runId.slice(0, 8)}, \u53EF\u89C1 user \u56DE\u5408 ${turn.userMessageId.slice(0, 8)}\uFF09\uFF1A`);
|
|
@@ -171610,7 +172077,39 @@ ${res.warning}`);
|
|
|
171610
172077
|
println(`[design] \u8BFB\u4EA7\u7269\u540E\u81EA\u884C\u51B3\u5B9A\uFF1A\u591F\u597D \u2192 oasis propose\uFF1B\u6709\u5206\u6B67/\u7F3A\u4FE1\u606F \u2192 oasis gap\uFF1B\u4E0D\u591F \u2192 \u518D\u4E00\u8F6E oasis design chat ${artifactId2} --turn continue --message "<\u4E0B\u4E00\u53E5>"`);
|
|
171611
172078
|
break;
|
|
171612
172079
|
}
|
|
171613
|
-
if (sub
|
|
172080
|
+
if (sub === "status") {
|
|
172081
|
+
const artifactId2 = needPos(positional, 1, "oasis design status <artifactId> [--pull]");
|
|
172082
|
+
const odBase2 = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
172083
|
+
const st = await fetchBoardStatus(odBase2, fetch, artifactId2);
|
|
172084
|
+
if (!st.boardExists) {
|
|
172085
|
+
println(`[design] \u753B\u677F ${st.boardKey} \u5C1A\u4E0D\u5B58\u5728\u2014\u2014\u8FD8\u6CA1\u8D77\u8FC7\u4EFB\u4F55\u4E00\u8F6E\u3002\u5F00\u5DE5\uFF1Aoasis design chat ${artifactId2} --message "<\u8BBE\u8BA1\u9700\u6C42+\u771F\u5B9E\u6570\u636E>" --async`);
|
|
172086
|
+
break;
|
|
172087
|
+
}
|
|
172088
|
+
const live = st.runs.filter((r) => r.status === "running" || r.status === "queued");
|
|
172089
|
+
if (live.length > 0) {
|
|
172090
|
+
for (const r of live) println(`[design] \u5F15\u64CE\u5728\u8DD1\uFF1Arun ${r.runId.slice(0, 8)} \u72B6\u6001=${r.status}\u2014\u2014\u522B\u518D\u8D77\u65B0\u8F6E\uFF1B\u8FC7\u51E0\u5206\u949F\u518D status\uFF0C\u6216\u672C\u8F6E\u6536\u5DE5\u7B49\u91CD\u6D3E\u3002`);
|
|
172091
|
+
} else if (st.runs.length > 0) {
|
|
172092
|
+
for (const r of st.runs.slice(0, 3)) println(`[design] \u8FD1\u671F run\uFF1A${r.runId.slice(0, 8)} \u7EC8\u6001=${r.status}`);
|
|
172093
|
+
} else {
|
|
172094
|
+
println(`[design] \u65E0\u5728\u4E16 run \u8BB0\u5F55\uFF08od \u91CD\u542F\u540E\u4E3A\u7A7A\uFF0C\u5C5E\u6B63\u5E38\uFF09\u2014\u2014\u770B\u4E0B\u9762\u677F\u4E0A\u4EA7\u7269\u5373\u6301\u4E45\u771F\u76F8\u3002`);
|
|
172095
|
+
}
|
|
172096
|
+
if (st.artifacts.length === 0) {
|
|
172097
|
+
println(`[design] \u677F\u4E0A\u8FD8\u6CA1\u6709\u4EA4\u4ED8\u7269\u3002${live.length > 0 ? "\u7B49\u5F15\u64CE\u8DD1\u5B8C\u518D\u6765\u3002" : `\u8D77\u4E00\u8F6E\uFF1Aoasis design chat ${artifactId2} --message "<\u2026>" --async`}`);
|
|
172098
|
+
break;
|
|
172099
|
+
}
|
|
172100
|
+
println(`[design] \u677F\u4E0A\u4EA4\u4ED8\u7269\uFF08\u6301\u4E45\uFF0C\u65B0\u2192\u65E7\uFF09\uFF1A`);
|
|
172101
|
+
for (const a of st.artifacts) println(` - ${a.path}\uFF08${a.kind ?? "?"}\uFF09status=${a.status ?? "?"}${a.mtime ? ` \xB7 ${new Date(a.mtime).toISOString()}` : ""}`);
|
|
172102
|
+
if (flags.get("pull") === "true") {
|
|
172103
|
+
const odPublic2 = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
172104
|
+
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2, os8.tmpdir(), st.boardKey, st.runs[0]?.runId ?? "status-pull");
|
|
172105
|
+
println(`[design] \u5DF2\u62C9\u5230\u672C\u5730\uFF1A${dir3}\uFF08\u5165\u53E3 ${entry2}\uFF09`);
|
|
172106
|
+
println(`[design] \u8BFB\u5B8C\u6EE1\u610F\u5373\u4EA4\u7A3F\uFF1Aoasis propose ${artifactId2} --from-dir ${dir3} --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"`);
|
|
172107
|
+
} else {
|
|
172108
|
+
println(`[design] \u53D6\u8D27\uFF1Aoasis design status ${artifactId2} --pull\uFF08\u62C9\u5230\u672C\u5730\u76EE\u5F55\u8BFB\uFF0C\u8BFB\u5B8C propose --from-dir \u4EA4\u7A3F\uFF09`);
|
|
172109
|
+
}
|
|
172110
|
+
break;
|
|
172111
|
+
}
|
|
172112
|
+
if (sub !== "run") throw new Error("\u7528\u6CD5\uFF1Aoasis design run <artifactId> \u2026\uFF1Boasis design chat <artifactId> --message <t> [--turn first|continue] [--async]\uFF1Boasis design status <artifactId> [--pull]");
|
|
171614
172113
|
const artifactId = needPos(positional, 1, "oasis design run <artifactId>");
|
|
171615
172114
|
const odBase = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
171616
172115
|
const odPublic = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
@@ -171708,6 +172207,18 @@ ${res.warning}`);
|
|
|
171708
172207
|
println(message);
|
|
171709
172208
|
break;
|
|
171710
172209
|
}
|
|
172210
|
+
case "record-action": {
|
|
172211
|
+
const artifactId = needPos(positional, 0, "oasis record-action <artifactId> --name <\u52A8\u4F5C\u540D> [--pass true] [--result <json>] [--params <json>]");
|
|
172212
|
+
const result = flags.get("result") !== void 0 ? JSON.parse(flags.get("result")) : { pass: flags.get("pass") === "true" };
|
|
172213
|
+
const { message } = await api.cmd("toolCall", {
|
|
172214
|
+
artifactId,
|
|
172215
|
+
name: need(flags, "name"),
|
|
172216
|
+
...flags.get("params") !== void 0 ? { params: JSON.parse(flags.get("params")) } : {},
|
|
172217
|
+
result
|
|
172218
|
+
});
|
|
172219
|
+
println(message);
|
|
172220
|
+
break;
|
|
172221
|
+
}
|
|
171711
172222
|
case "reply": {
|
|
171712
172223
|
const { message } = await api.cmd("reply", {
|
|
171713
172224
|
annotationId: needPos(positional, 0, "oasis reply <annotationId> --body <\u7B54\u590D>"),
|
|
@@ -172270,7 +172781,7 @@ ${res.warning}`);
|
|
|
172270
172781
|
init_src6();
|
|
172271
172782
|
|
|
172272
172783
|
// src/index.ts
|
|
172273
|
-
var PKG_VERSION = true ? "0.1.
|
|
172784
|
+
var PKG_VERSION = true ? "0.1.63" : "dev";
|
|
172274
172785
|
var OASIS_DIR = path21.join(os9.homedir(), ".oasis");
|
|
172275
172786
|
var CONFIG_FILE = path21.join(OASIS_DIR, "node-config.json");
|
|
172276
172787
|
var PID_FILE = path21.join(OASIS_DIR, "node.pid");
|