@clawos-dev/clawd 0.2.490 → 0.2.492
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/app-builder-plugin/mcp-server.cjs +29 -0
- package/dist/cli.cjs +87 -8
- package/dist/dispatch/mcp-server.cjs +29 -0
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +55 -2
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-XUxeACMw.js → guest-BY7eFa9K.js} +133 -133
- package/dist/share-ui/assets/{guest-BVnHMXcA.css → guest-Bs9R1ccn.css} +1 -1
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
|
@@ -21360,6 +21360,8 @@ var DeployFileSchema = external_exports.object({
|
|
|
21360
21360
|
version: external_exports.literal(1),
|
|
21361
21361
|
manifest: EnvironmentManifestSchema
|
|
21362
21362
|
}).strict();
|
|
21363
|
+
var SCAN_BASE_KINDS = ["hard", "soft"];
|
|
21364
|
+
var ScanBaseKindSchema = external_exports.enum(SCAN_BASE_KINDS);
|
|
21363
21365
|
var DeployScanStatusSchema = external_exports.enum(["scanning", "done", "failed"]);
|
|
21364
21366
|
var DeployScanSchema = external_exports.object({
|
|
21365
21367
|
/** 干这次扫描的 butler 会话,「看它怎么干的」入口 */
|
|
@@ -21379,6 +21381,26 @@ var DeployScanSchema = external_exports.object({
|
|
|
21379
21381
|
* 缺席 = 旧版 clawd 扫的记录。**一律当过时**:没有第三种情况,重扫一次就有了。
|
|
21380
21382
|
*/
|
|
21381
21383
|
head: external_exports.string().min(1).optional(),
|
|
21384
|
+
/**
|
|
21385
|
+
* 上次**发布**推的那个 commit ——「线上正跑的是哪一版」在本机唯一的答案,
|
|
21386
|
+
* 也就是软扫的基准。只有 `deploy:release` 写它,扫描不动。
|
|
21387
|
+
*
|
|
21388
|
+
* 为什么不能用 `head` 顶替:`head` 被扫描和发布轮流覆盖(扫描前落存一版、发布后又挪一版),
|
|
21389
|
+
* 它回答的是「清单绑在哪个 commit 上」,回答不了「上次发布是哪一版」。
|
|
21390
|
+
*
|
|
21391
|
+
* 缺席 = 这个 persona 还从没发布过,没有线上版本可比,软扫退硬扫。
|
|
21392
|
+
*/
|
|
21393
|
+
releasedHead: external_exports.string().min(1).optional(),
|
|
21394
|
+
/**
|
|
21395
|
+
* 这次**实际**怎么扫的。是结果不是入参——`deploy:start` 收到的 mode 可能因为没有可比的
|
|
21396
|
+
* 基准而退成硬扫,页面要显示的是真正发生的那个。
|
|
21397
|
+
*
|
|
21398
|
+
* `.default('hard')` 而不是必填:这个文件是 strict 解析的,存量记录没有这个字段,
|
|
21399
|
+
* 定成必填会让 `readScan` 当场抛、上云页面直接打不开。而老记录确实都是从零扫的。
|
|
21400
|
+
*/
|
|
21401
|
+
baseKind: ScanBaseKindSchema.default("hard"),
|
|
21402
|
+
/** 软扫比的那个 commit(= `releasedHead`)。硬扫时缺席 */
|
|
21403
|
+
base: external_exports.string().min(1).optional(),
|
|
21382
21404
|
startedAt: external_exports.number(),
|
|
21383
21405
|
finishedAt: external_exports.number().optional(),
|
|
21384
21406
|
error: external_exports.string().optional()
|
|
@@ -21444,6 +21466,13 @@ var DeployReleaseResultSchema = external_exports.object({
|
|
|
21444
21466
|
var DeployPersonaArgsSchema = external_exports.object({
|
|
21445
21467
|
personaId: external_exports.string().min(1)
|
|
21446
21468
|
}).strict();
|
|
21469
|
+
var DeployStartArgsSchema = DeployPersonaArgsSchema.extend({
|
|
21470
|
+
/**
|
|
21471
|
+
* 缺省 soft。真正用哪一档由 daemon 定(软扫比不了时会退硬扫),结果看 `DeployScan.baseKind`。
|
|
21472
|
+
* 复用上面那个中央定义的字面量,不在这里手抄一份。
|
|
21473
|
+
*/
|
|
21474
|
+
mode: ScanBaseKindSchema.optional()
|
|
21475
|
+
}).strict();
|
|
21447
21476
|
var DeployPatchArgsSchema = external_exports.object({
|
|
21448
21477
|
personaId: external_exports.string().min(1),
|
|
21449
21478
|
patch: external_exports.object({
|
package/dist/cli.cjs
CHANGED
|
@@ -6045,7 +6045,7 @@ function cloudEngineOk(tool) {
|
|
|
6045
6045
|
function repoSlug(url) {
|
|
6046
6046
|
return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
|
|
6047
6047
|
}
|
|
6048
|
-
var DeployFileSchema, DeployScanStatusSchema, DeployScanSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, DeployStateSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
|
|
6048
|
+
var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, DeployStateSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployStartArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
|
|
6049
6049
|
var init_deploy_schemas = __esm({
|
|
6050
6050
|
"../protocol/src/deploy-schemas.ts"() {
|
|
6051
6051
|
"use strict";
|
|
@@ -6055,6 +6055,8 @@ var init_deploy_schemas = __esm({
|
|
|
6055
6055
|
version: external_exports.literal(1),
|
|
6056
6056
|
manifest: EnvironmentManifestSchema
|
|
6057
6057
|
}).strict();
|
|
6058
|
+
SCAN_BASE_KINDS = ["hard", "soft"];
|
|
6059
|
+
ScanBaseKindSchema = external_exports.enum(SCAN_BASE_KINDS);
|
|
6058
6060
|
DeployScanStatusSchema = external_exports.enum(["scanning", "done", "failed"]);
|
|
6059
6061
|
DeployScanSchema = external_exports.object({
|
|
6060
6062
|
/** 干这次扫描的 butler 会话,「看它怎么干的」入口 */
|
|
@@ -6074,6 +6076,26 @@ var init_deploy_schemas = __esm({
|
|
|
6074
6076
|
* 缺席 = 旧版 clawd 扫的记录。**一律当过时**:没有第三种情况,重扫一次就有了。
|
|
6075
6077
|
*/
|
|
6076
6078
|
head: external_exports.string().min(1).optional(),
|
|
6079
|
+
/**
|
|
6080
|
+
* 上次**发布**推的那个 commit ——「线上正跑的是哪一版」在本机唯一的答案,
|
|
6081
|
+
* 也就是软扫的基准。只有 `deploy:release` 写它,扫描不动。
|
|
6082
|
+
*
|
|
6083
|
+
* 为什么不能用 `head` 顶替:`head` 被扫描和发布轮流覆盖(扫描前落存一版、发布后又挪一版),
|
|
6084
|
+
* 它回答的是「清单绑在哪个 commit 上」,回答不了「上次发布是哪一版」。
|
|
6085
|
+
*
|
|
6086
|
+
* 缺席 = 这个 persona 还从没发布过,没有线上版本可比,软扫退硬扫。
|
|
6087
|
+
*/
|
|
6088
|
+
releasedHead: external_exports.string().min(1).optional(),
|
|
6089
|
+
/**
|
|
6090
|
+
* 这次**实际**怎么扫的。是结果不是入参——`deploy:start` 收到的 mode 可能因为没有可比的
|
|
6091
|
+
* 基准而退成硬扫,页面要显示的是真正发生的那个。
|
|
6092
|
+
*
|
|
6093
|
+
* `.default('hard')` 而不是必填:这个文件是 strict 解析的,存量记录没有这个字段,
|
|
6094
|
+
* 定成必填会让 `readScan` 当场抛、上云页面直接打不开。而老记录确实都是从零扫的。
|
|
6095
|
+
*/
|
|
6096
|
+
baseKind: ScanBaseKindSchema.default("hard"),
|
|
6097
|
+
/** 软扫比的那个 commit(= `releasedHead`)。硬扫时缺席 */
|
|
6098
|
+
base: external_exports.string().min(1).optional(),
|
|
6077
6099
|
startedAt: external_exports.number(),
|
|
6078
6100
|
finishedAt: external_exports.number().optional(),
|
|
6079
6101
|
error: external_exports.string().optional()
|
|
@@ -6139,6 +6161,13 @@ var init_deploy_schemas = __esm({
|
|
|
6139
6161
|
DeployPersonaArgsSchema = external_exports.object({
|
|
6140
6162
|
personaId: external_exports.string().min(1)
|
|
6141
6163
|
}).strict();
|
|
6164
|
+
DeployStartArgsSchema = DeployPersonaArgsSchema.extend({
|
|
6165
|
+
/**
|
|
6166
|
+
* 缺省 soft。真正用哪一档由 daemon 定(软扫比不了时会退硬扫),结果看 `DeployScan.baseKind`。
|
|
6167
|
+
* 复用上面那个中央定义的字面量,不在这里手抄一份。
|
|
6168
|
+
*/
|
|
6169
|
+
mode: ScanBaseKindSchema.optional()
|
|
6170
|
+
}).strict();
|
|
6142
6171
|
DeployPatchArgsSchema = external_exports.object({
|
|
6143
6172
|
personaId: external_exports.string().min(1),
|
|
6144
6173
|
patch: external_exports.object({
|
|
@@ -55466,6 +55495,11 @@ async function listSecrets(exec, dir) {
|
|
|
55466
55495
|
return { env: x.name, ...Number.isFinite(at2) ? { setAt: at2 } : {} };
|
|
55467
55496
|
});
|
|
55468
55497
|
}
|
|
55498
|
+
async function hasCommit(exec, dir, sha) {
|
|
55499
|
+
if (!sha) return false;
|
|
55500
|
+
const r = await git(exec, dir, ["cat-file", "-e", `${sha}^{commit}`]);
|
|
55501
|
+
return !r.spawnError && r.code === 0;
|
|
55502
|
+
}
|
|
55469
55503
|
async function commitAndPush(exec, args) {
|
|
55470
55504
|
await mustGit(exec, args.dir, ["add", "-A"], "\u6682\u5B58\u6587\u4EF6");
|
|
55471
55505
|
const staged = await git(exec, args.dir, ["diff", "--cached", "--quiet"]);
|
|
@@ -55489,6 +55523,17 @@ async function release(exec, args) {
|
|
|
55489
55523
|
return { sha, actionsUrl: `https://github.com/${repoSlug(info.url)}/actions` };
|
|
55490
55524
|
}
|
|
55491
55525
|
|
|
55526
|
+
// src/deploy/scan-base.ts
|
|
55527
|
+
function pickScanBase(args) {
|
|
55528
|
+
if (args.mode === "hard") return { kind: "hard" };
|
|
55529
|
+
if (!args.hasUsableManifest || !args.releasedHead) return { kind: "hard" };
|
|
55530
|
+
return { kind: "soft", base: args.releasedHead };
|
|
55531
|
+
}
|
|
55532
|
+
var SCAN_BASE_LABEL = {
|
|
55533
|
+
hard: "\u786C\u626B",
|
|
55534
|
+
soft: "\u8F6F\u626B"
|
|
55535
|
+
};
|
|
55536
|
+
|
|
55492
55537
|
// src/deploy/run-status.ts
|
|
55493
55538
|
init_protocol();
|
|
55494
55539
|
var TIMEOUT_MS = 8e3;
|
|
@@ -55701,7 +55746,7 @@ function buildDeployHandlers(deps) {
|
|
|
55701
55746
|
});
|
|
55702
55747
|
const start = async (frame, _client, ctx) => {
|
|
55703
55748
|
ensureOwner(ctx);
|
|
55704
|
-
const { personaId: personaId2 } = parseArgs2(
|
|
55749
|
+
const { personaId: personaId2, mode } = parseArgs2(DeployStartArgsSchema, frame, "deploy:start");
|
|
55705
55750
|
const dir = mustPersona(personaId2);
|
|
55706
55751
|
const wrong = wrongEngine(deps.personaEngine(personaId2)?.tool);
|
|
55707
55752
|
if (wrong) throw invalid(wrong);
|
|
@@ -55724,11 +55769,35 @@ function buildDeployHandlers(deps) {
|
|
|
55724
55769
|
throw toClawdError(err);
|
|
55725
55770
|
}
|
|
55726
55771
|
runCache.delete(personaId2);
|
|
55727
|
-
await
|
|
55772
|
+
const prevManifest = await readDeployFile(dir).catch(() => void 0);
|
|
55773
|
+
const scanBase = pickScanBase({
|
|
55774
|
+
mode,
|
|
55775
|
+
// **文件在 ≠ 清单能用**:硬扫一开头就写了一份空清单,那一轮没跑完(OTA 重启 / butler 崩,
|
|
55776
|
+
// 见 scan-task.ts 的收尾判定)的话文件在、内容是空的。所以判据连上「上一轮扫完了」。
|
|
55777
|
+
hasUsableManifest: prevManifest !== void 0 && current?.status === "done",
|
|
55778
|
+
releasedHead: await hasCommit(deps.exec, dir, current?.releasedHead) ? current?.releasedHead : void 0
|
|
55779
|
+
});
|
|
55780
|
+
if (scanBase.kind === "hard") await writeDeployFile(dir, emptyDeployFile());
|
|
55728
55781
|
const startedAt = deps.now();
|
|
55729
|
-
const base = {
|
|
55782
|
+
const base = {
|
|
55783
|
+
evidence: scanBase.kind === "hard" ? [] : current?.evidence ?? [],
|
|
55784
|
+
// notes 反过来不沿用:它是「这次扫描要老板判断的事」,沿用会把上次的存疑项一直复读
|
|
55785
|
+
notes: [],
|
|
55786
|
+
scannedAssets: [],
|
|
55787
|
+
startedAt,
|
|
55788
|
+
head,
|
|
55789
|
+
// 发布记的那个 commit 跟扫描无关,原样带过去,别让重扫把软扫的基准弄丢。
|
|
55790
|
+
//
|
|
55791
|
+
// **哪怕上面 hasCommit 刚判定它已经不在仓库里,也照样留着**:探测失败也包括 git 没跑起来
|
|
55792
|
+
// 这种一过性情况,据此把它抹掉就等于「一次 git 抽风 → 永久失去软扫,直到下次发布」,
|
|
55793
|
+
// 比留一个死 sha 糟得多。留着的代价只是 UI 上「从零重扫」多显示一阵子(那期间两个按钮
|
|
55794
|
+
// 都退硬扫、行为一致不出错),下次发布就自愈。
|
|
55795
|
+
...current?.releasedHead ? { releasedHead: current.releasedHead } : {},
|
|
55796
|
+
baseKind: scanBase.kind,
|
|
55797
|
+
...scanBase.base ? { base: scanBase.base } : {}
|
|
55798
|
+
};
|
|
55730
55799
|
await writeScan(dir, { status: "scanning", ...base });
|
|
55731
|
-
const started = deps.startScan(personaId2);
|
|
55800
|
+
const started = deps.startScan(personaId2, scanBase);
|
|
55732
55801
|
if ("sessionId" in started) {
|
|
55733
55802
|
await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...base });
|
|
55734
55803
|
} else {
|
|
@@ -55856,7 +55925,7 @@ function buildDeployHandlers(deps) {
|
|
|
55856
55925
|
const result = await release(deps.exec, { dir, now: deps.now });
|
|
55857
55926
|
runCache.delete(personaId2);
|
|
55858
55927
|
const scanned = await readScan(dir);
|
|
55859
|
-
if (scanned) await writeScan(dir, { ...scanned, head: result.sha });
|
|
55928
|
+
if (scanned) await writeScan(dir, { ...scanned, head: result.sha, releasedHead: result.sha });
|
|
55860
55929
|
return { response: { type: "deploy:release", ...result } };
|
|
55861
55930
|
} catch (err) {
|
|
55862
55931
|
throw toClawdError(err);
|
|
@@ -65534,7 +65603,7 @@ function computeMethodAccess(args) {
|
|
|
65534
65603
|
}
|
|
65535
65604
|
|
|
65536
65605
|
// src/version.ts
|
|
65537
|
-
var version = "0.2.
|
|
65606
|
+
var version = "0.2.492".length > 0 ? "0.2.492" : "dev";
|
|
65538
65607
|
|
|
65539
65608
|
// src/cli-probe/probe.ts
|
|
65540
65609
|
var fs72 = __toESM(require("fs"), 1);
|
|
@@ -70747,14 +70816,24 @@ async function startDaemon(config) {
|
|
|
70747
70816
|
exec: runCommand,
|
|
70748
70817
|
org: PERSONA_REPO_ORG,
|
|
70749
70818
|
now: () => Date.now(),
|
|
70750
|
-
startScan: (personaId2) => {
|
|
70819
|
+
startScan: (personaId2, scanBase) => {
|
|
70751
70820
|
const assetLines = SCANNABLE_ASSETS.map(
|
|
70752
70821
|
(a) => ` - ${a.name}${a.path ? `\uFF08${a.path(config.dataDir)}\uFF09` : ""}\uFF1A${a.what}`
|
|
70753
70822
|
).join("\n");
|
|
70823
|
+
const baseLines = scanBase.base ? [
|
|
70824
|
+
`\u672C\u6B21\u662F**${SCAN_BASE_LABEL[scanBase.kind]}**\uFF1A\u53EA\u770B\u8DDF\u7EBF\u4E0A\u6B63\u8DD1\u90A3\u7248\u7684\u5DEE\u522B\uFF0C`,
|
|
70825
|
+
`\u90A3\u4E00\u7248\u662F commit ${scanBase.base}\u3002`,
|
|
70826
|
+
`\u5148\u5728 persona \u76EE\u5F55\u8DD1 \`git diff --name-only ${scanBase.base} -- .\` \u62FF\u5230\u6539\u52A8\u6E05\u5355\uFF0C`,
|
|
70827
|
+
"\u53EA\u91CD\u770B\u8FD9\u4E9B\u6587\u4EF6\uFF08\u53CA\u5B83\u4EEC\u5F15\u51FA\u53BB\u7684\u90A3\u4E00\u8DF3\uFF09\uFF0C\u6E05\u5355\u91CC\u5176\u4F59\u6761\u76EE\u539F\u6837\u7559\u7740\u4E0D\u7528\u91CD\u62A5\u3002"
|
|
70828
|
+
] : [
|
|
70829
|
+
`\u672C\u6B21\u662F**${SCAN_BASE_LABEL[scanBase.kind]}**\uFF1A\u4ECE\u96F6\u628A persona \u6574\u4E2A\u8BFB\u4E00\u904D\uFF0C\u6E05\u5355\u662F\u7A7A\u7684\u3002`
|
|
70830
|
+
];
|
|
70754
70831
|
const prompt = [
|
|
70755
70832
|
`\u626B\u63CF persona\u300C${personaId2}\u300D\u7684\u90E8\u7F72\u73AF\u5883\uFF0CpersonaId=${personaId2}\u3002`,
|
|
70756
70833
|
"",
|
|
70757
70834
|
`persona \u76EE\u5F55\uFF1A${personaStore.personaDirPath(personaId2)}`,
|
|
70835
|
+
...baseLines,
|
|
70836
|
+
"",
|
|
70758
70837
|
"\u53EF\u4EE5\u58F0\u660E\u7684 persona \u76EE\u5F55\u4E4B\u5916\u7684\u5171\u4EAB\u8D44\u4EA7\uFF08\u7528\u5230\u54EA\u6761\u5C31\u62A5\u54EA\u6761\uFF09\uFF1A",
|
|
70759
70838
|
assetLines || " \uFF08\u65E0\uFF09",
|
|
70760
70839
|
"",
|
|
@@ -21353,6 +21353,8 @@ var DeployFileSchema = external_exports.object({
|
|
|
21353
21353
|
version: external_exports.literal(1),
|
|
21354
21354
|
manifest: EnvironmentManifestSchema
|
|
21355
21355
|
}).strict();
|
|
21356
|
+
var SCAN_BASE_KINDS = ["hard", "soft"];
|
|
21357
|
+
var ScanBaseKindSchema = external_exports.enum(SCAN_BASE_KINDS);
|
|
21356
21358
|
var DeployScanStatusSchema = external_exports.enum(["scanning", "done", "failed"]);
|
|
21357
21359
|
var DeployScanSchema = external_exports.object({
|
|
21358
21360
|
/** 干这次扫描的 butler 会话,「看它怎么干的」入口 */
|
|
@@ -21372,6 +21374,26 @@ var DeployScanSchema = external_exports.object({
|
|
|
21372
21374
|
* 缺席 = 旧版 clawd 扫的记录。**一律当过时**:没有第三种情况,重扫一次就有了。
|
|
21373
21375
|
*/
|
|
21374
21376
|
head: external_exports.string().min(1).optional(),
|
|
21377
|
+
/**
|
|
21378
|
+
* 上次**发布**推的那个 commit ——「线上正跑的是哪一版」在本机唯一的答案,
|
|
21379
|
+
* 也就是软扫的基准。只有 `deploy:release` 写它,扫描不动。
|
|
21380
|
+
*
|
|
21381
|
+
* 为什么不能用 `head` 顶替:`head` 被扫描和发布轮流覆盖(扫描前落存一版、发布后又挪一版),
|
|
21382
|
+
* 它回答的是「清单绑在哪个 commit 上」,回答不了「上次发布是哪一版」。
|
|
21383
|
+
*
|
|
21384
|
+
* 缺席 = 这个 persona 还从没发布过,没有线上版本可比,软扫退硬扫。
|
|
21385
|
+
*/
|
|
21386
|
+
releasedHead: external_exports.string().min(1).optional(),
|
|
21387
|
+
/**
|
|
21388
|
+
* 这次**实际**怎么扫的。是结果不是入参——`deploy:start` 收到的 mode 可能因为没有可比的
|
|
21389
|
+
* 基准而退成硬扫,页面要显示的是真正发生的那个。
|
|
21390
|
+
*
|
|
21391
|
+
* `.default('hard')` 而不是必填:这个文件是 strict 解析的,存量记录没有这个字段,
|
|
21392
|
+
* 定成必填会让 `readScan` 当场抛、上云页面直接打不开。而老记录确实都是从零扫的。
|
|
21393
|
+
*/
|
|
21394
|
+
baseKind: ScanBaseKindSchema.default("hard"),
|
|
21395
|
+
/** 软扫比的那个 commit(= `releasedHead`)。硬扫时缺席 */
|
|
21396
|
+
base: external_exports.string().min(1).optional(),
|
|
21375
21397
|
startedAt: external_exports.number(),
|
|
21376
21398
|
finishedAt: external_exports.number().optional(),
|
|
21377
21399
|
error: external_exports.string().optional()
|
|
@@ -21437,6 +21459,13 @@ var DeployReleaseResultSchema = external_exports.object({
|
|
|
21437
21459
|
var DeployPersonaArgsSchema = external_exports.object({
|
|
21438
21460
|
personaId: external_exports.string().min(1)
|
|
21439
21461
|
}).strict();
|
|
21462
|
+
var DeployStartArgsSchema = DeployPersonaArgsSchema.extend({
|
|
21463
|
+
/**
|
|
21464
|
+
* 缺省 soft。真正用哪一档由 daemon 定(软扫比不了时会退硬扫),结果看 `DeployScan.baseKind`。
|
|
21465
|
+
* 复用上面那个中央定义的字面量,不在这里手抄一份。
|
|
21466
|
+
*/
|
|
21467
|
+
mode: ScanBaseKindSchema.optional()
|
|
21468
|
+
}).strict();
|
|
21440
21469
|
var DeployPatchArgsSchema = external_exports.object({
|
|
21441
21470
|
personaId: external_exports.string().min(1),
|
|
21442
21471
|
patch: external_exports.object({
|
package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md
CHANGED
|
@@ -5,10 +5,39 @@ description: 老板要把某个 persona 发布到云上时触发——把这个
|
|
|
5
5
|
|
|
6
6
|
# 扫 persona 的上云环境
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
一起进 git
|
|
8
|
+
老板在界面上点了「发布到云上」,这个 persona 的部署文件(`.clawd/deploy.json`,会随 persona
|
|
9
|
+
一起进 git 仓库)等着你填。**页面是随你干活一点点长出来的**——他正看着,你查明白一条
|
|
10
10
|
就报一条,别攒到最后一次性倒出来。
|
|
11
11
|
|
|
12
|
+
## 先看这次是硬扫还是软扫
|
|
13
|
+
|
|
14
|
+
**任务里会写明,照它做,不要自己另判。** 是硬是软由 daemon 定(它知道线上正跑的是哪一版、
|
|
15
|
+
那个 commit 还在不在、清单读不读得出来),你手上那份记录看不出这些。
|
|
16
|
+
|
|
17
|
+
| 档 | 任务里会说 | 你要做什么 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **硬扫** | 「从零把 persona 整个读一遍」 | 清单是空的,从零填 |
|
|
20
|
+
| **软扫** | 「只看跟线上正跑那版的差别,那一版是 commit `<sha>`」 | 在**已有清单**上打补丁 |
|
|
21
|
+
|
|
22
|
+
软扫的第一件事,在 persona 目录里跑:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
git diff --name-only <任务里给的 sha> -- .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
拿到的就是要重看的文件——**这就是「线上那版跟现在」的全部差别**。清单里其余条目原样有效,
|
|
29
|
+
不用重报:重报没变的东西不但白花时间,还会让本来稳定的字段(比如凭据的命名引用)无谓地变来变去。
|
|
30
|
+
|
|
31
|
+
两件最容易做错的事:
|
|
32
|
+
|
|
33
|
+
- **改动列表是空的,不等于没活干。** 老板点了重扫,页面正卡在「分析中」,你照样要走到收尾那步
|
|
34
|
+
调 `deploy:finishScan`,只是中间什么都不用报。
|
|
35
|
+
- **diff 给的是入口,不是边界。** 改的可能只是 `CLAUDE.md` 里一行命令,而那行命令背后的脚本
|
|
36
|
+
带着一整串工具依赖。**改动文件引出去的那一跳照样要跟**,规则同下面「读什么」那节。
|
|
37
|
+
|
|
38
|
+
两档都一样:任务里列出的**共享资产都要照判据过一遍**——那部分判据就写在任务里,不用读
|
|
39
|
+
persona 目录,很便宜,漏了的话资产进不了镜像,容器里那条能力就是空的。
|
|
40
|
+
|
|
12
41
|
## 你要回答的问题
|
|
13
42
|
|
|
14
43
|
这个 persona 如果被搬到一台**干净的 Linux 容器**里跑(没有任何人的 home 目录、没有预装工具、
|
|
@@ -134,6 +163,30 @@ call({ method: "deploy:reportFinding", args: {
|
|
|
134
163
|
|
|
135
164
|
## 收尾
|
|
136
165
|
|
|
166
|
+
### 先删掉不该再在清单里的条目(只有软扫需要)
|
|
167
|
+
|
|
168
|
+
`deploy:reportFinding` 只会新增和覆盖,**删不掉东西**。硬扫不用管——清单本来就是空的重填。
|
|
169
|
+
软扫下清单是上一轮留下来的,如果线上那版之后**删掉了某个依赖的来源**(skill 被删了、脚本不再
|
|
170
|
+
调那个工具、`.mcp.json` 里那个 server 撤了),那条会一直赖在清单里:镜像继续装没用的东西,
|
|
171
|
+
如果是凭据还会一直拦着老板发布。
|
|
172
|
+
|
|
173
|
+
确认某条该删,就在 `finishScan` **之前**调一次,交出**完整**的 manifest(不是只交要删的):
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
call({ method: "deploy:patch", args: {
|
|
177
|
+
personaId: "<任务里给的>",
|
|
178
|
+
patch: { manifest: { version: 1, clis: [...], secrets: [...], assets: [...], connectors: [...] } }
|
|
179
|
+
}})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
先把 `.clawd/deploy.json` 读出来,去掉该去的那几条,其余原样带上。**没有要删的就别调**——
|
|
183
|
+
整份改写是有风险的动作,没必要时不做。
|
|
184
|
+
|
|
185
|
+
判「该删」要有依据:来源文件在这次 diff 里被删了,或者你读了改动后的文件、确认它不再引用那个
|
|
186
|
+
东西。**光是「这次没重报它」不是依据**——软扫下没重报是常态。
|
|
187
|
+
|
|
188
|
+
### 然后收尾
|
|
189
|
+
|
|
137
190
|
全部查完,调一次:
|
|
138
191
|
|
|
139
192
|
```
|