@clawos-dev/clawd 0.2.548 → 0.2.550

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.
@@ -21687,6 +21687,9 @@ var DeployReleaseResultSchema = external_exports.discriminatedUnion("outcome", [
21687
21687
  var DeployPersonaArgsSchema = external_exports.object({
21688
21688
  personaId: external_exports.string().min(1)
21689
21689
  }).strict();
21690
+ var DeployReleaseArgsSchema = DeployPersonaArgsSchema.extend({
21691
+ scanBase: ScanBaseKindSchema.optional()
21692
+ }).strict();
21690
21693
  var DeployPatchArgsSchema = external_exports.object({
21691
21694
  personaId: external_exports.string().min(1),
21692
21695
  patch: external_exports.object({
@@ -24173,8 +24176,8 @@ var METHOD_DOCS = {
24173
24176
  args: DeployFinishScanArgsSchema
24174
24177
  },
24175
24178
  "deploy:release": {
24176
- summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002owner-only",
24177
- args: DeployPersonaArgsSchema
24179
+ summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002\u5E26 scanBase\uFF08hard / soft\uFF09= \u8FD9\u6B21\u4E00\u5B9A\u5148\u626B\u3001\u6309\u8BE5\u6863\u4F4D\u626B\uFF08soft \u4E0D\u6210\u7ACB\u81EA\u52A8\u9000 hard\uFF09\uFF0C\u6E05\u5355\u65B0\u9C9C\u4E5F\u56DE scanning\uFF1Bowner-only",
24180
+ args: DeployReleaseArgsSchema
24178
24181
  },
24179
24182
  "deploy:rerunJob": {
24180
24183
  summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08GitHub REST rerun job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",
package/dist/cli.cjs CHANGED
@@ -6098,7 +6098,7 @@ function cloudEngineOk(tool) {
6098
6098
  function repoSlug(url) {
6099
6099
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6100
6100
  }
6101
- var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, 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;
6101
+ var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, DeployStateSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployReleaseArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6102
6102
  var init_deploy_schemas = __esm({
6103
6103
  "../protocol/src/deploy-schemas.ts"() {
6104
6104
  "use strict";
@@ -6228,6 +6228,9 @@ var init_deploy_schemas = __esm({
6228
6228
  DeployPersonaArgsSchema = external_exports.object({
6229
6229
  personaId: external_exports.string().min(1)
6230
6230
  }).strict();
6231
+ DeployReleaseArgsSchema = DeployPersonaArgsSchema.extend({
6232
+ scanBase: ScanBaseKindSchema.optional()
6233
+ }).strict();
6231
6234
  DeployPatchArgsSchema = external_exports.object({
6232
6235
  personaId: external_exports.string().min(1),
6233
6236
  patch: external_exports.object({
@@ -8999,8 +9002,8 @@ var init_methods = __esm({
8999
9002
  args: DeployFinishScanArgsSchema
9000
9003
  },
9001
9004
  "deploy:release": {
9002
- summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002owner-only",
9003
- args: DeployPersonaArgsSchema
9005
+ summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002\u5E26 scanBase\uFF08hard / soft\uFF09= \u8FD9\u6B21\u4E00\u5B9A\u5148\u626B\u3001\u6309\u8BE5\u6863\u4F4D\u626B\uFF08soft \u4E0D\u6210\u7ACB\u81EA\u52A8\u9000 hard\uFF09\uFF0C\u6E05\u5355\u65B0\u9C9C\u4E5F\u56DE scanning\uFF1Bowner-only",
9006
+ args: DeployReleaseArgsSchema
9004
9007
  },
9005
9008
  "deploy:rerunJob": {
9006
9009
  summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08GitHub REST rerun job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",
@@ -59593,6 +59596,7 @@ async function release(exec, api, args) {
59593
59596
 
59594
59597
  // src/deploy/scan-base.ts
59595
59598
  function pickScanBase(args) {
59599
+ if (args.want === "hard") return { kind: "hard" };
59596
59600
  if (!args.hasUsableManifest || !args.releasedHead) return { kind: "hard" };
59597
59601
  return { kind: "soft", base: args.releasedHead };
59598
59602
  }
@@ -59719,14 +59723,27 @@ function toClawdError(err) {
59719
59723
  if (err instanceof RepoError || err instanceof GithubApiError) return new ClawdError(ERROR_CODES.INTERNAL, err.message);
59720
59724
  return new ClawdError(ERROR_CODES.INTERNAL, err instanceof Error ? err.message : String(err));
59721
59725
  }
59722
- function mustBeScanning(scan, method) {
59723
- if (scan?.status !== "scanning") {
59724
- throw invalid(`${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u5F53\u524D ${scan?.status ?? "\u6CA1\u6709\u626B\u63CF\u8BB0\u5F55"}\uFF09`);
59725
- }
59726
- return scan;
59726
+ function isLiveScan(live, scan) {
59727
+ if (!live) return false;
59728
+ return live.sessionId === void 0 || live.sessionId === scan.scanSessionId;
59727
59729
  }
59728
59730
  function buildDeployHandlers(deps) {
59729
59731
  const scannableAssets = deps.scannableAssets ?? SCANNABLE_ASSETS;
59732
+ const liveScans = /* @__PURE__ */ new Map();
59733
+ const settleStale = async (dir, scan) => {
59734
+ const settled = { ...scan, status: "failed", finishedAt: deps.now(), error: "\u626B\u63CF\u8BB0\u5F55\u505C\u5728 scanning\uFF0C\u4F46\u6CA1\u6709\u6B63\u5728\u8DD1\u7684\u626B\u63CF\u4F1A\u8BDD" };
59735
+ await writeScan(dir, settled);
59736
+ return settled;
59737
+ };
59738
+ const mustBeLiveScan = (personaId2, scan, method) => {
59739
+ if (scan?.status !== "scanning") {
59740
+ throw invalid(`${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u5F53\u524D ${scan?.status ?? "\u6CA1\u6709\u626B\u63CF\u8BB0\u5F55"}\uFF09`);
59741
+ }
59742
+ if (!isLiveScan(liveScans.get(personaId2), scan)) {
59743
+ throw invalid(`${method} \u53EA\u5728\u626B\u63CF\u671F\u53EF\u7528\uFF08\u8BB0\u5F55\u505C\u5728 scanning\uFF0C\u4F46\u6CA1\u6709\u6B63\u5728\u8DD1\u7684\u626B\u63CF\u4F1A\u8BDD\uFF09`);
59744
+ }
59745
+ return scan;
59746
+ };
59730
59747
  const cacheMs = deps.secretsCacheMs ?? SECRETS_CACHE_MS;
59731
59748
  const secretsCache = /* @__PURE__ */ new Map();
59732
59749
  const runCache = /* @__PURE__ */ new Map();
@@ -59763,6 +59780,7 @@ function buildDeployHandlers(deps) {
59763
59780
  fileError = err instanceof Error ? err.message : String(err);
59764
59781
  }
59765
59782
  let scan = await readScan(dir);
59783
+ if (scan?.status === "scanning" && !isLiveScan(liveScans.get(personaId2), scan)) scan = await settleStale(dir, scan);
59766
59784
  if (scan && scan.status === "done") {
59767
59785
  const stale = describeStaleAssets(staleScannerAssets(scan, scannableAssets));
59768
59786
  const kept = scan.notes.filter((n2) => !n2.startsWith(STALE_ASSETS_NOTE_PREFIX));
@@ -59798,13 +59816,15 @@ function buildDeployHandlers(deps) {
59798
59816
  const view = async (personaId2) => ({
59799
59817
  response: { type: "deploy:state", ...await stateOf(personaId2) }
59800
59818
  });
59801
- async function beginScan(personaId2, dir, current, head) {
59819
+ async function beginScan(personaId2, dir, current, head, want) {
59820
+ liveScans.set(personaId2, {});
59802
59821
  const prevManifest = await readDeployFile(dir).catch(() => void 0);
59803
59822
  const scanBase = pickScanBase({
59804
59823
  // **文件在 ≠ 清单能用**:硬扫一开头就写了一份空清单,那一轮没跑完(OTA 重启 / butler 崩,
59805
59824
  // 见 scan-task.ts 的收尾判定)的话文件在、内容是空的。所以判据连上「上一轮扫完了」。
59806
59825
  hasUsableManifest: prevManifest !== void 0 && current?.status === "done",
59807
- releasedHead: await hasCommit(deps.exec, dir, current?.releasedHead) ? current?.releasedHead : void 0
59826
+ releasedHead: await hasCommit(deps.exec, dir, current?.releasedHead) ? current?.releasedHead : void 0,
59827
+ ...want ? { want } : {}
59808
59828
  });
59809
59829
  const startedAt = deps.now();
59810
59830
  const base = {
@@ -59842,8 +59862,23 @@ function buildDeployHandlers(deps) {
59842
59862
  };
59843
59863
  const started = deps.startScan(personaId2, scanBase);
59844
59864
  if ("sessionId" in started) {
59865
+ liveScans.set(personaId2, { sessionId: started.sessionId });
59845
59866
  await writeScan(dir, { status: "scanning", scanSessionId: started.sessionId, ...withMcp });
59867
+ const mine = () => liveScans.get(personaId2)?.sessionId === started.sessionId;
59868
+ void started.ended.then(async (outcome) => {
59869
+ if (mine()) liveScans.delete(personaId2);
59870
+ const current2 = await readScan(dir).catch(() => void 0);
59871
+ if (liveScans.has(personaId2) || current2?.scanSessionId !== started.sessionId) return;
59872
+ const settled = settleEndedScan(outcome, current2, deps.now());
59873
+ if (!settled) return;
59874
+ await writeScan(dir, settled);
59875
+ deps.warn?.("deploy scan ended without finishScan", { personaId: personaId2, why: settled.error });
59876
+ }).catch((err) => {
59877
+ if (mine()) liveScans.delete(personaId2);
59878
+ deps.warn?.("deploy scan settle failed", { personaId: personaId2, error: String(err) });
59879
+ });
59846
59880
  } else {
59881
+ liveScans.delete(personaId2);
59847
59882
  await writeScan(dir, {
59848
59883
  status: "failed",
59849
59884
  ...withMcp,
@@ -59896,7 +59931,7 @@ function buildDeployHandlers(deps) {
59896
59931
  ensureOwner(ctx);
59897
59932
  const args = parseArgs2(DeployReportFindingArgsSchema, frame, "deploy:reportFinding");
59898
59933
  const dir = mustPersona(args.personaId);
59899
- const scan = mustBeScanning(await readScan(dir), "deploy:reportFinding");
59934
+ const scan = mustBeLiveScan(args.personaId, await readScan(dir), "deploy:reportFinding");
59900
59935
  let item;
59901
59936
  try {
59902
59937
  item = parseFinding(args.kind, args.item);
@@ -59917,7 +59952,7 @@ function buildDeployHandlers(deps) {
59917
59952
  ensureOwner(ctx);
59918
59953
  const args = parseArgs2(DeployFinishScanArgsSchema, frame, "deploy:finishScan");
59919
59954
  const dir = mustPersona(args.personaId);
59920
- const scan = mustBeScanning(await readScan(dir), "deploy:finishScan");
59955
+ const scan = mustBeLiveScan(args.personaId, await readScan(dir), "deploy:finishScan");
59921
59956
  await writeScan(dir, {
59922
59957
  ...scan,
59923
59958
  status: "done",
@@ -59934,7 +59969,7 @@ function buildDeployHandlers(deps) {
59934
59969
  };
59935
59970
  const releaseHandler = async (frame, _client, ctx) => {
59936
59971
  ensureOwner(ctx);
59937
- const { personaId: personaId2 } = parseArgs2(DeployPersonaArgsSchema, frame, "deploy:release");
59972
+ const { personaId: personaId2, scanBase } = parseArgs2(DeployReleaseArgsSchema, frame, "deploy:release");
59938
59973
  const dir = mustPersona(personaId2);
59939
59974
  const wrong = wrongEngine(deps.personaEngine(personaId2)?.tool);
59940
59975
  if (wrong) throw invalid(wrong);
@@ -59951,10 +59986,15 @@ function buildDeployHandlers(deps) {
59951
59986
  if (!repo2) throw new ClawdError(ERROR_CODES.INTERNAL, "\u4ED3\u5E93\u5EFA\u597D\u4E86\u4F46\u8BFB\u4E0D\u5230 origin");
59952
59987
  }
59953
59988
  if (repo2.branch !== "main") throw invalid(`\u5F53\u524D\u5728\u5206\u652F ${repo2.branch}\uFF0C\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u53EA\u8BA4 main\uFF1B\u5207\u56DE main \u518D\u53D1\u5E03`);
59954
- const current = await readScan(dir);
59955
- if (current?.status === "scanning") return { response: { type: "deploy:release", outcome: "scanning" } };
59989
+ const starting = liveScans.get(personaId2);
59990
+ if (starting && starting.sessionId === void 0) return { response: { type: "deploy:release", outcome: "scanning" } };
59991
+ let current = await readScan(dir);
59992
+ if (current?.status === "scanning") {
59993
+ if (isLiveScan(liveScans.get(personaId2), current)) return { response: { type: "deploy:release", outcome: "scanning" } };
59994
+ current = await settleStale(dir, current);
59995
+ }
59956
59996
  const fileUsable = await readDeployFile(dir).then((f2) => f2 !== void 0).catch(() => false);
59957
- if (!fileUsable || !isScanFresh(current, repo2)) {
59997
+ if (scanBase !== void 0 || !fileUsable || !isScanFresh(current, repo2)) {
59958
59998
  let head;
59959
59999
  try {
59960
60000
  head = await commitAll(deps.exec, { dir, message: `clawd: \u626B\u63CF\u524D\u843D\u5B58 ${new Date(deps.now()).toISOString()}` });
@@ -59962,7 +60002,12 @@ function buildDeployHandlers(deps) {
59962
60002
  throw toClawdError(err);
59963
60003
  }
59964
60004
  runCache.delete(personaId2);
59965
- await beginScan(personaId2, dir, current, head);
60005
+ try {
60006
+ await beginScan(personaId2, dir, current, head, scanBase);
60007
+ } catch (err) {
60008
+ liveScans.delete(personaId2);
60009
+ throw err;
60010
+ }
59966
60011
  return { response: { type: "deploy:release", outcome: "scanning" } };
59967
60012
  }
59968
60013
  const file = await readDeployFile(dir);
@@ -70925,7 +70970,7 @@ function computeMethodAccess(args) {
70925
70970
  }
70926
70971
 
70927
70972
  // src/version.ts
70928
- var version = "0.2.548".length > 0 ? "0.2.548" : "dev";
70973
+ var version = "0.2.550".length > 0 ? "0.2.550" : "dev";
70929
70974
 
70930
70975
  // src/cli-probe/probe.ts
70931
70976
  var fs78 = __toESM(require("fs"), 1);
@@ -74587,6 +74632,7 @@ async function startDaemon(config) {
74587
74632
  githubApi: (token) => createGithubApi({ token }),
74588
74633
  org: PERSONA_REPO_ORG,
74589
74634
  now: () => Date.now(),
74635
+ warn: (msg, meta) => logger.warn(msg, meta),
74590
74636
  startScan: (personaId2, scanBase) => {
74591
74637
  const assetLines = SCANNABLE_ASSETS.map(
74592
74638
  (a2) => ` - ${a2.name}${a2.path ? `\uFF08${a2.path(config.dataDir)}\uFF09` : ""}\uFF1A${a2.what}`
@@ -74618,16 +74664,7 @@ async function startDaemon(config) {
74618
74664
  logger.error("deploy scan session failed to start", { personaId: personaId2, error: String(err) });
74619
74665
  return { error: String(err) };
74620
74666
  }
74621
- void handle.ended.then(async (outcome) => {
74622
- const dir = personaStore.personaDirPath(personaId2);
74623
- const settled = settleEndedScan(outcome, await readScan(dir).catch(() => void 0), Date.now());
74624
- if (!settled) return;
74625
- await writeScan(dir, settled);
74626
- logger.warn("deploy scan ended without finishScan", { personaId: personaId2, why: settled.error });
74627
- }).catch((err) => {
74628
- logger.warn("deploy scan settle failed", { personaId: personaId2, error: String(err) });
74629
- });
74630
- return { sessionId: handle.sessionId };
74667
+ return { sessionId: handle.sessionId, ended: handle.ended };
74631
74668
  }
74632
74669
  });
74633
74670
  Object.assign(handlers, deployHandlers);
@@ -21501,6 +21501,9 @@ var DeployReleaseResultSchema = external_exports.discriminatedUnion("outcome", [
21501
21501
  var DeployPersonaArgsSchema = external_exports.object({
21502
21502
  personaId: external_exports.string().min(1)
21503
21503
  }).strict();
21504
+ var DeployReleaseArgsSchema = DeployPersonaArgsSchema.extend({
21505
+ scanBase: ScanBaseKindSchema.optional()
21506
+ }).strict();
21504
21507
  var DeployPatchArgsSchema = external_exports.object({
21505
21508
  personaId: external_exports.string().min(1),
21506
21509
  patch: external_exports.object({
@@ -23987,8 +23990,8 @@ var METHOD_DOCS = {
23987
23990
  args: DeployFinishScanArgsSchema
23988
23991
  },
23989
23992
  "deploy:release": {
23990
- summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002owner-only",
23991
- args: DeployPersonaArgsSchema
23993
+ summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002\u5E26 scanBase\uFF08hard / soft\uFF09= \u8FD9\u6B21\u4E00\u5B9A\u5148\u626B\u3001\u6309\u8BE5\u6863\u4F4D\u626B\uFF08soft \u4E0D\u6210\u7ACB\u81EA\u52A8\u9000 hard\uFF09\uFF0C\u6E05\u5355\u65B0\u9C9C\u4E5F\u56DE scanning\uFF1Bowner-only",
23994
+ args: DeployReleaseArgsSchema
23992
23995
  },
23993
23996
  "deploy:rerunJob": {
23994
23997
  summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08GitHub REST rerun job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",
@@ -21687,6 +21687,9 @@ var DeployReleaseResultSchema = external_exports.discriminatedUnion("outcome", [
21687
21687
  var DeployPersonaArgsSchema = external_exports.object({
21688
21688
  personaId: external_exports.string().min(1)
21689
21689
  }).strict();
21690
+ var DeployReleaseArgsSchema = DeployPersonaArgsSchema.extend({
21691
+ scanBase: ScanBaseKindSchema.optional()
21692
+ }).strict();
21690
21693
  var DeployPatchArgsSchema = external_exports.object({
21691
21694
  personaId: external_exports.string().min(1),
21692
21695
  patch: external_exports.object({
@@ -24173,8 +24176,8 @@ var METHOD_DOCS = {
24173
24176
  args: DeployFinishScanArgsSchema
24174
24177
  },
24175
24178
  "deploy:release": {
24176
- summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002owner-only",
24177
- args: DeployPersonaArgsSchema
24179
+ summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002\u5E26 scanBase\uFF08hard / soft\uFF09= \u8FD9\u6B21\u4E00\u5B9A\u5148\u626B\u3001\u6309\u8BE5\u6863\u4F4D\u626B\uFF08soft \u4E0D\u6210\u7ACB\u81EA\u52A8\u9000 hard\uFF09\uFF0C\u6E05\u5355\u65B0\u9C9C\u4E5F\u56DE scanning\uFF1Bowner-only",
24180
+ args: DeployReleaseArgsSchema
24178
24181
  },
24179
24182
  "deploy:rerunJob": {
24180
24183
  summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08GitHub REST rerun job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",
@@ -270,7 +270,12 @@ GitHub release / apt,你得告诉我它从哪装」。
270
270
 
271
271
  ## 纪律
272
272
 
273
- - **只读不写**:不要修改被扫 persona 目录里的任何文件,不要执行它的脚本。
273
+ - **只读不写**:不要修改被扫 persona 目录里的任何文件,不要执行它的脚本。**`.clawd/deploy.json` 和
274
+ `.clawd/deploy-scan.json` 也在内**——它们只能经 `deploy:reportFinding` / `deploy:patch` / `deploy:finishScan` 改。
275
+ 把扫描记录手改回 `scanning` 没有用:daemon 只认它自己起的、还活着的扫描,会话一结束记录就不归你了,
276
+ 改回去只会被翻成 failed。
277
+ - **扫完之后老板在这个会话里让你「重新扫」「改成硬扫 / 软扫」:不要动。** 不改文件、不重跑流程、不再上报。
278
+ 回一句让他去页面重新点「发布」——按钮右边的下拉能选硬扫 / 软扫,daemon 会起新的扫描会话。
274
279
  - **宁缺毋滥**:拿不准的去查清,不要编一条依赖进清单;查清了、且过得了 `notes` 那三道门槛的才是 note。
275
280
  多报一条假依赖会让镜像装一堆没用的东西;漏报一条真依赖,云上试跑和用起来会发现,补一行再发一次就行。
276
281
  - **没调 `finishScan` 就等于没扫完**——中途卡住也要调,把卡在哪写进 `notes`,别让页面一直停在
@@ -21687,6 +21687,9 @@ var DeployReleaseResultSchema = external_exports.discriminatedUnion("outcome", [
21687
21687
  var DeployPersonaArgsSchema = external_exports.object({
21688
21688
  personaId: external_exports.string().min(1)
21689
21689
  }).strict();
21690
+ var DeployReleaseArgsSchema = DeployPersonaArgsSchema.extend({
21691
+ scanBase: ScanBaseKindSchema.optional()
21692
+ }).strict();
21690
21693
  var DeployPatchArgsSchema = external_exports.object({
21691
21694
  personaId: external_exports.string().min(1),
21692
21695
  patch: external_exports.object({
@@ -24173,8 +24176,8 @@ var METHOD_DOCS = {
24173
24176
  args: DeployFinishScanArgsSchema
24174
24177
  },
24175
24178
  "deploy:release": {
24176
- summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002owner-only",
24177
- args: DeployPersonaArgsSchema
24179
+ summary: "\u53D1\u5E03\u2014\u2014\u4E0A\u4E91\u552F\u4E00\u7684\u52A8\u4F5C\uFF0C\u626B\u63CF\u662F\u5B83\u7684\u7B2C\u4E00\u6BB5\u3002**\u6CA1\u4ED3\u5E93\u5148\u5EFA\u4ED3**\uFF08GitHub REST \u5EFA\u5728\u7EC4\u7EC7\u4E0B\u3001\u79C1\u6709\uFF0Cgit \u63A8\u9996\u4E2A\u63D0\u4EA4\uFF1Btoken \u6765\u81EA\u672C\u673A git \u7684\u8EAB\u4EFD\uFF0C\u6CA1\u6388\u6743\u5148\u62D2\uFF09\u3002\u6E05\u5355\u8FC7\u65F6\uFF08persona \u6539\u8FC7 / \u6CA1\u626B\u8FC7 / \u4E0A\u6B21\u626B\u5931\u8D25\uFF09\uFF1A\u5148\u628A persona \u76EE\u5F55\u63D0\u4EA4\u5230\u672C\u5730\uFF08\u4E0D\u63A8\uFF09\uFF0C\u8D77 persona-butler \u7684\u626B\u63CF\u4F1A\u8BDD\uFF0C\u56DE outcome=scanning\u2014\u2014\u7ED3\u679C\u5199\u8FDB .clawd/deploy.json\uFF08\u6E05\u5355\uFF0C\u8FDB\u4ED3\u5E93\uFF09\u4E0E .clawd/deploy-scan.json\uFF08\u8BC1\u636E\uFF0C\u4E0D\u8FDB\u4ED3\u5E93\uFF09\uFF0C\u6B63\u5728\u626B\u7684\u8BDD\u539F\u6837\u8FD4\u56DE\u4E0D\u8D77\u7B2C\u4E8C\u4E2A\u4F1A\u8BDD\u3002\u6E05\u5355\u65B0\u9C9C\uFF1A\u8FC7\u95F8\uFF08\u6BCF\u4E2A\u53D8\u91CF\u540D\u90FD\u5728 Secrets \u91CC\u3001\u8FDE\u63A5\u5668\u6765\u6E90\u70B9\u8FC7\u3001\u9009\u4E86\u6A21\u578B\uFF09\u2192 \u91CD\u5199 workflow \u6A21\u677F \u2192 git add -A \u2192 \u7A7A\u63D0\u4EA4\u4E5F\u5141\u8BB8 \u2192 push\uFF0C\u56DE outcome=pushed \u5E26 commit \u4E0E Actions \u5730\u5740\uFF1B\u4ED3\u5E93\u91CC\u7684\u6D41\u6C34\u7EBF\u63A5\u7740\u6784\u955C\u50CF\u3001\u8BD5\u8DD1\u3001\u767B\u8BB0\u3002\u5E26 scanBase\uFF08hard / soft\uFF09= \u8FD9\u6B21\u4E00\u5B9A\u5148\u626B\u3001\u6309\u8BE5\u6863\u4F4D\u626B\uFF08soft \u4E0D\u6210\u7ACB\u81EA\u52A8\u9000 hard\uFF09\uFF0C\u6E05\u5355\u65B0\u9C9C\u4E5F\u56DE scanning\uFF1Bowner-only",
24180
+ args: DeployReleaseArgsSchema
24178
24181
  },
24179
24182
  "deploy:rerunJob": {
24180
24183
  summary: "\u539F\u6837\u91CD\u8DD1\u6700\u65B0\u90A3\u6761\u6D41\u6C34\u7EBF\u91CC\u5931\u8D25\u7684\u67D0\u4E00\u6BB5\uFF08GitHub REST rerun job\uFF09\u3002**\u540C\u4E00\u4E2A commit\u3001\u540C\u4E00\u4EFD\u8F93\u5165**\uFF0C\u4E0D\u4EA7\u751F\u65B0\u63D0\u4EA4\u2014\u2014\u6539\u4E86 persona \u5185\u5BB9\u6216\u51ED\u636E\u8981\u8D70 deploy:release\u3002jobId \u5FC5\u987B\u5C5E\u4E8E\u6700\u65B0\u90A3\u6761 run\uFF1Bowner-only",