@clawos-dev/clawd 0.2.396 → 0.2.398

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/cli.cjs CHANGED
@@ -6678,7 +6678,7 @@ var init_topic = __esm({
6678
6678
  init_zod();
6679
6679
  init_dispatch();
6680
6680
  nonBlank2 = external_exports.string().trim().min(1);
6681
- TOPIC_STATES = ["planning", "running", "done", "archived"];
6681
+ TOPIC_STATES = ["planning", "running", "done"];
6682
6682
  TopicStateSchema = external_exports.enum(TOPIC_STATES);
6683
6683
  TopicActivityEntrySchema = external_exports.object({
6684
6684
  at: external_exports.string().min(1),
@@ -6786,7 +6786,9 @@ var init_topic = __esm({
6786
6786
  });
6787
6787
  TopicCloseArgsSchema = external_exports.object({
6788
6788
  topicId: external_exports.string().min(1),
6789
- state: external_exports.enum(["done", "archived"])
6789
+ // 单值 enum 而不是 z.literal:缺字段时 enum 报 invalid_type、literal 报 invalid_literal,
6790
+ // 而 method-args-contract 的必填探测只认前者(literal 会让 state 被判成非必填)。
6791
+ state: external_exports.enum(["done"])
6790
6792
  });
6791
6793
  TopicRenameArgsSchema = external_exports.object({
6792
6794
  topicId: external_exports.string().min(1),
@@ -8539,7 +8541,7 @@ var init_methods = __esm({
8539
8541
  }
8540
8542
  },
8541
8543
  "topic:close": {
8542
- summary: "\u6536\u655B\u8BDD\u9898\uFF1Astate \u7F6E done / archived",
8544
+ summary: "\u6536\u655B\u8BDD\u9898\uFF1Astate \u7F6E done\u3002\u5F52\u6863\u4E0D\u8D70\u8FD9\u91CC\uFF08\u5F52\u6863\u6253\u5728\u8BE5\u8BDD\u9898 Master \u4F1A\u8BDD\u7684 archivedAt \u4E0A\uFF09",
8543
8545
  args: TopicCloseArgsSchema
8544
8546
  },
8545
8547
  "topic:rename": {
@@ -8672,7 +8674,7 @@ var init_methods = __esm({
8672
8674
  args: NO_ARGS
8673
8675
  },
8674
8676
  "persona:get": {
8675
- summary: "\u53D6\u5355\u4E2A persona \u8BE6\u60C5\uFF0C**\u542B personality\uFF08CLAUDE.md \u6B63\u6587\uFF09**\u2014\u2014\u552F\u4E00\u643A\u5E26\u6B63\u6587\u7684 method",
8677
+ summary: "\u53D6\u5355\u4E2A persona \u8BE6\u60C5\uFF0C**\u542B personality\uFF08CLAUDE.md \u6B63\u6587\uFF09**\u2014\u2014\u552F\u4E00\u643A\u5E26\u6B63\u6587\u7684 method\u3002\u54CD\u5E94\u628A PersonaFile \u5E73\u94FA\u5728\u5E27\u4E0A\uFF08\u65E0 persona \u5305\u88F9\u952E\uFF09\uFF1B\u67E5\u4E0D\u5230 / guest \u65E0\u6743\u9650\u629B PERSONA_NOT_FOUND",
8676
8678
  args: PersonaIdArgsSchema
8677
8679
  },
8678
8680
  "persona:update": {
@@ -8971,7 +8973,10 @@ var init_errors2 = __esm({
8971
8973
  CONTACT_NOT_FOUND: "CONTACT_NOT_FOUND",
8972
8974
  // 统一 RPC 鉴权(spec 2026-07-28):personaDispatch:get 查不到台账行,或 guest ctx
8973
8975
  // 查非自己发起的行(越权与未知 id 同码,不泄露存在性)。A 端轮询遇此码立即判失败。
8974
- DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND"
8976
+ DISPATCH_NOT_FOUND: "DISPATCH_NOT_FOUND",
8977
+ // persona:get 查不到该 personaId,或 guest ctx 查非 public / 无 read grant 的 persona
8978
+ // (与 DISPATCH_NOT_FOUND 同款:越权与未知 id 同码,不泄露存在性)。
8979
+ PERSONA_NOT_FOUND: "PERSONA_NOT_FOUND"
8975
8980
  };
8976
8981
  ClawdError = class extends Error {
8977
8982
  constructor(code, message) {
@@ -52904,7 +52909,19 @@ function createTopicStore(deps) {
52904
52909
  };
52905
52910
  const lineMetaOf = (t, lineId) => t.lineMeta[lineId] ??= { rejectCount: 0, accepted: false, overrideCount: 0 };
52906
52911
  return {
52907
- load: file.load,
52912
+ /**
52913
+ * 读盘后把存量 `state: 'archived'` 归一成 `'done'`。
52914
+ *
52915
+ * 归档已改由该话题 Master 会话的 `archivedAt` 承载(spec 2026-08-25-topic-archive-and-pin),
52916
+ * `TOPIC_STATES` 随之退掉那一档。json-store 读盘本身不过 zod,但 `topic:list` 的响应要过
52917
+ * `TopicListResultSchema.parse` —— 留着这个值会让**整个频道**的话题列表 parse 失败。
52918
+ */
52919
+ async load() {
52920
+ await file.load();
52921
+ for (const t of file.all()) {
52922
+ if (t.state === "archived") t.state = "done";
52923
+ }
52924
+ },
52908
52925
  flushNow: file.flushNow,
52909
52926
  get,
52910
52927
  getByMasterSession: (masterSessionId) => file.all().find((t) => t.masterSessionId === masterSessionId),
@@ -62096,7 +62113,7 @@ function computeMethodAccess(args) {
62096
62113
  }
62097
62114
 
62098
62115
  // src/version.ts
62099
- var version = "0.2.396".length > 0 ? "0.2.396" : "dev";
62116
+ var version = "0.2.398".length > 0 ? "0.2.398" : "dev";
62100
62117
 
62101
62118
  // src/cli-probe/probe.ts
62102
62119
  var fs66 = __toESM(require("fs"), 1);
@@ -62241,16 +62258,18 @@ function buildPersonaHandlers(deps) {
62241
62258
  };
62242
62259
  const get = async (frame, _client, ctx) => {
62243
62260
  const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:get");
62244
- const persona = personaRegistry.get(args.personaId) ?? null;
62261
+ let persona = personaRegistry.get(args.personaId) ?? null;
62245
62262
  if (!persona) {
62246
- return { response: { type: "persona:info", persona: null } };
62263
+ personaRegistry.reload();
62264
+ persona = personaRegistry.get(args.personaId) ?? null;
62247
62265
  }
62248
62266
  const isGuest = ctx?.principal.kind === "guest";
62249
- if (isGuest) {
62250
- const allowed = persona.public && assertGrant(ctx.grants, { type: "persona", id: persona.personaId }, "read");
62251
- if (!allowed) {
62252
- return { response: { type: "persona:info", persona: null } };
62253
- }
62267
+ const denied = isGuest && !(persona?.public && assertGrant(ctx.grants, { type: "persona", id: persona.personaId }, "read"));
62268
+ if (!persona || denied) {
62269
+ throw new ClawdError(
62270
+ ERROR_CODES.PERSONA_NOT_FOUND,
62271
+ `unknown personaId: ${args.personaId}`
62272
+ );
62254
62273
  }
62255
62274
  const personality = personaManager.readPersonality(args.personaId) ?? "";
62256
62275
  const skills = personaManager.listSkills(args.personaId);
@@ -62275,7 +62294,7 @@ function buildPersonaHandlers(deps) {
62275
62294
  return { response: { type: "persona:info", ...persona } };
62276
62295
  };
62277
62296
  const del = async (frame) => {
62278
- const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:get");
62297
+ const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:delete");
62279
62298
  personaManager.delete(args.personaId);
62280
62299
  return {
62281
62300
  response: { type: "persona:deleted", personaId: args.personaId }
@@ -21866,7 +21866,7 @@ var ChannelDeleteResultSchema = external_exports.object({
21866
21866
 
21867
21867
  // ../protocol/src/topic.ts
21868
21868
  var nonBlank2 = external_exports.string().trim().min(1);
21869
- var TOPIC_STATES = ["planning", "running", "done", "archived"];
21869
+ var TOPIC_STATES = ["planning", "running", "done"];
21870
21870
  var TopicStateSchema = external_exports.enum(TOPIC_STATES);
21871
21871
  var TopicActivityEntrySchema = external_exports.object({
21872
21872
  at: external_exports.string().min(1),
@@ -21974,7 +21974,9 @@ var TopicAcceptArgsSchema = external_exports.object({
21974
21974
  });
21975
21975
  var TopicCloseArgsSchema = external_exports.object({
21976
21976
  topicId: external_exports.string().min(1),
21977
- state: external_exports.enum(["done", "archived"])
21977
+ // 单值 enum 而不是 z.literal:缺字段时 enum 报 invalid_type、literal 报 invalid_literal,
21978
+ // 而 method-args-contract 的必填探测只认前者(literal 会让 state 被判成非必填)。
21979
+ state: external_exports.enum(["done"])
21978
21980
  });
21979
21981
  var TopicRenameArgsSchema = external_exports.object({
21980
21982
  topicId: external_exports.string().min(1),
@@ -23599,7 +23601,7 @@ var METHOD_DOCS = {
23599
23601
  }
23600
23602
  },
23601
23603
  "topic:close": {
23602
- summary: "\u6536\u655B\u8BDD\u9898\uFF1Astate \u7F6E done / archived",
23604
+ summary: "\u6536\u655B\u8BDD\u9898\uFF1Astate \u7F6E done\u3002\u5F52\u6863\u4E0D\u8D70\u8FD9\u91CC\uFF08\u5F52\u6863\u6253\u5728\u8BE5\u8BDD\u9898 Master \u4F1A\u8BDD\u7684 archivedAt \u4E0A\uFF09",
23603
23605
  args: TopicCloseArgsSchema
23604
23606
  },
23605
23607
  "topic:rename": {
@@ -23732,7 +23734,7 @@ var METHOD_DOCS = {
23732
23734
  args: NO_ARGS
23733
23735
  },
23734
23736
  "persona:get": {
23735
- summary: "\u53D6\u5355\u4E2A persona \u8BE6\u60C5\uFF0C**\u542B personality\uFF08CLAUDE.md \u6B63\u6587\uFF09**\u2014\u2014\u552F\u4E00\u643A\u5E26\u6B63\u6587\u7684 method",
23737
+ summary: "\u53D6\u5355\u4E2A persona \u8BE6\u60C5\uFF0C**\u542B personality\uFF08CLAUDE.md \u6B63\u6587\uFF09**\u2014\u2014\u552F\u4E00\u643A\u5E26\u6B63\u6587\u7684 method\u3002\u54CD\u5E94\u628A PersonaFile \u5E73\u94FA\u5728\u5E27\u4E0A\uFF08\u65E0 persona \u5305\u88F9\u952E\uFF09\uFF1B\u67E5\u4E0D\u5230 / guest \u65E0\u6743\u9650\u629B PERSONA_NOT_FOUND",
23736
23738
  args: PersonaIdArgsSchema
23737
23739
  },
23738
23740
  "persona:update": {
@@ -151,9 +151,11 @@ worker 干到一半上报「答不了的问题」(它会以回报形式带出
151
151
  `topic:accept` 返回 `allAccepted: true` → 合并 → 自己先验一遍 → 交付。
152
152
  给老板:**结论优先,流水在后**。收敛判据看 daemon 给的 `allAccepted`,不要自己数线。
153
153
 
154
- **话题状态不用你收**:最后一条线判合格时 daemon 自己把话题推到 `done`(老板在频道
155
- flyout 里看到的就是这个状态);已收敛的话题被打回一条线会自动退回 `running`。
156
- `topic:close` 只用于老板要归档(`archived`)的场合。
154
+ **话题状态不用你收**:最后一条线判合格时 daemon 自己把话题推到 `done`(老板在 sidebar
155
+ 频道分区的话题行上看到的就是这个状态);已收敛的话题被打回一条线会自动退回 `running`。
156
+
157
+ **归档不归你管**:归档是老板的显式动作,落在该话题 Master 会话上(`session:archive`),
158
+ 不是话题状态的一档 —— `topic:close` 只收 `done`。你没有归档入口,也不需要有。
157
159
 
158
160
  ## 落账纪律(硬性)
159
161