@deployxai/dxc 0.1.2 → 0.1.4

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.
Files changed (69) hide show
  1. package/README.md +10 -127
  2. package/dist/chunks/{chunk-UO2FNP6N.js → chunk-GCGIIKQJ.js} +1 -1
  3. package/dist/chunks/chunk-JGUPNE36.js +2077 -0
  4. package/dist/chunks/{knowledge-4ZXXUSDQ.js → knowledge-6LOGJETT.js} +902 -22
  5. package/dist/chunks/{monitor-63LXCSZA.js → monitor-CYJPUX5V.js} +2 -2
  6. package/dist/index.js +575 -63
  7. package/package.json +3 -3
  8. package/skills/dxc-article-outline/references/outline-methods.md +20 -0
  9. package/skills/dxc-article-write/SKILL.md +34 -2
  10. package/skills/dxc-article-write/references/writing-methods.md +20 -0
  11. package/skills/dxc-content-brief/references/brief-method.md +18 -0
  12. package/skills/dxc-content-review/SKILL.md +2 -0
  13. package/skills/dxc-content-review/references/review-checklist.md +17 -0
  14. package/skills/dxc-content-workflow/SKILL.md +42 -8
  15. package/skills/dxc-content-workflow/references/onboarding-questions.md +67 -41
  16. package/skills/dxc-content-workflow/references/stage-contract.md +4 -1
  17. package/skills/dxc-knowledge/SKILL.md +30 -0
  18. package/skills/dxc-knowledge/agents/openai.yaml +6 -0
  19. package/skills/dxc-memory/SKILL.md +28 -0
  20. package/skills/dxc-memory/agents/openai.yaml +6 -0
  21. package/skills/dxc-profile/SKILL.md +32 -0
  22. package/skills/dxc-profile/agents/openai.yaml +6 -0
  23. package/skills/dxc-quote-curator/SKILL.md +35 -0
  24. package/skills/dxc-quote-curator/agents/openai.yaml +6 -0
  25. package/skills/dxc-research/references/research-method.md +21 -0
  26. package/skills/dxc-title-write/SKILL.md +6 -1
  27. package/skills/dxc-title-write/references/title-methods.md +15 -0
  28. package/skills/dxc-visual-plan/SKILL.md +24 -4
  29. package/skills/dxc-visual-plan/references/visual-methods.md +18 -0
  30. package/skills/dxc-wechat-publisher/SKILL.md +1 -0
  31. package/dist/chunks/chunk-ZPBFGBWP.js +0 -16422
  32. package/docs/00-project-context.md +0 -125
  33. package/docs/01-north-star-architecture.md +0 -234
  34. package/docs/02-mvp-technical-design.md +0 -553
  35. package/docs/03-domain-state-api.md +0 -600
  36. package/docs/04-security-and-operations.md +0 -413
  37. package/docs/05-delivery-plan.md +0 -407
  38. package/docs/README.md +0 -44
  39. package/docs/decisions/0001-initial-architecture.md +0 -57
  40. package/docs/decisions/0002-mongodb-environment-boundary.md +0 -42
  41. package/docs/decisions/0003-staged-production-topology.md +0 -33
  42. package/docs/decisions/0004-local-first-agent-research-runtime.md +0 -71
  43. package/docs/decisions/0005-official-skill-orchestration-and-local-content-memory.md +0 -97
  44. package/docs/decisions/0006-separate-wechat-user-login-from-account-authorization.md +0 -87
  45. package/docs/decisions/0007-explicit-personal-wechat-start.md +0 -67
  46. package/docs/decisions/0008-end-to-end-content-workflow-continuity.md +0 -115
  47. package/docs/decisions/0009-privileged-multitenant-draft-scheduling.md +0 -36
  48. package/docs/decisions/0009-versioned-cloud-template-catalog.md +0 -39
  49. package/docs/decisions/0010-cli-runtime-and-default-server.md +0 -31
  50. package/docs/decisions/0011-user-memory-and-explicit-history-library.md +0 -30
  51. package/docs/eight-stage-implementation-audit.md +0 -62
  52. package/docs/first-user-guide.md +0 -191
  53. package/docs/history/content-forge-prd-v0.2-summary.md +0 -81
  54. package/docs/local-development.md +0 -520
  55. package/docs/references/aliyun-oss-production-setup.md +0 -89
  56. package/docs/references/legacy-content-to-wechat-contract.md +0 -223
  57. package/docs/references/renderer-compatibility-report.md +0 -68
  58. package/docs/references/source-inventory.md +0 -179
  59. package/docs/references/wechat-renderer-platform-validation.md +0 -92
  60. package/docs/references/wechat-third-party-platform-setup.md +0 -159
  61. package/docs/references/wechat-website-login-setup.md +0 -137
  62. package/docs/references/wemd-template-attribution.md +0 -25
  63. package/docs/research-monitoring-design.md +0 -235
  64. package/docs/todo-preview-local-first.md +0 -31
  65. package/docs/workbuddy-first-user-runbook.md +0 -244
  66. package/docs//345/221/230/345/267/245BCDE/347/232/204skill/employee-b-research-analyst/SKILL.md +0 -230
  67. package/docs//345/221/230/345/267/245BCDE/347/232/204skill/employee-c-outline-architect/SKILL.md +0 -194
  68. package/docs//345/221/230/345/267/245BCDE/347/232/204skill/employee-d-content-writer/SKILL.md +0 -296
  69. package/docs//345/221/230/345/267/245BCDE/347/232/204skill/employee-e-visual-designer/SKILL.md +0 -268
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire as __dxcCreateRequire } from "node:module"; const require
3
3
  import {
4
4
  SourceCli,
5
5
  SourceCliError
6
- } from "./chunks/chunk-UO2FNP6N.js";
6
+ } from "./chunks/chunk-GCGIIKQJ.js";
7
7
  import {
8
8
  CONTENT_ARTIFACT_KINDS,
9
9
  CONTENT_STAGE_INPUTS,
@@ -21,12 +21,20 @@ import {
21
21
  articleBundleSchema,
22
22
  contentArtifactKindSchema,
23
23
  contentKnowledgeErrorResultSchema,
24
+ contentMemoryAddResultSchema,
25
+ contentMemoryArchiveResultSchema,
26
+ contentMemoryErrorResultSchema,
27
+ contentMemoryInputSchema,
28
+ contentMemoryListResultSchema,
29
+ contentMemoryStoreSchema,
24
30
  contentMonitorErrorResultSchema,
25
31
  contentProfileErrorResultSchema,
26
32
  contentProfileInputSchema,
27
33
  contentProfileSaveResultSchema,
28
34
  contentProfileSchema,
29
35
  contentProfileStatusResultSchema,
36
+ contentProfileUpdateInputSchema,
37
+ contentProfileUpdateResultSchema,
30
38
  contentProjectCheckpointResultSchema,
31
39
  contentProjectErrorResultSchema,
32
40
  contentProjectIndexSchema,
@@ -44,7 +52,7 @@ import {
44
52
  deviceSessionStatusResponseSchema,
45
53
  doctorResultSchema,
46
54
  executionLocationSchema,
47
- external_exports,
55
+ goldenLinesSidecarSchema,
48
56
  portableRelativePathSchema,
49
57
  preflightResultSchema,
50
58
  proveDeviceBindingSessionResponseSchema,
@@ -70,7 +78,7 @@ import {
70
78
  wechatRenderResultSchema,
71
79
  writePrivateBuffer,
72
80
  writePrivateJson
73
- } from "./chunks/chunk-ZPBFGBWP.js";
81
+ } from "./chunks/chunk-JGUPNE36.js";
74
82
 
75
83
  // node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
76
84
  var require_identity = __commonJS({
@@ -23285,7 +23293,7 @@ import path8 from "node:path";
23285
23293
  // apps/cli/package.json
23286
23294
  var package_default = {
23287
23295
  name: "@dxc/cli",
23288
- version: "0.1.2",
23296
+ version: "0.1.4",
23289
23297
  private: true,
23290
23298
  type: "module",
23291
23299
  bin: {
@@ -23308,7 +23316,8 @@ var package_default = {
23308
23316
  commander: "15.0.0",
23309
23317
  "fast-xml-parser": "5.3.3",
23310
23318
  "onnxruntime-web": "1.22.0",
23311
- yaml: "2.9.0"
23319
+ yaml: "2.9.0",
23320
+ zod: "4.4.3"
23312
23321
  }
23313
23322
  };
23314
23323
 
@@ -26731,8 +26740,10 @@ import { randomUUID } from "node:crypto";
26731
26740
  import { readFile, stat } from "node:fs/promises";
26732
26741
  import path2 from "node:path";
26733
26742
  var PROFILE_DISPLAY_PATH = "~/.dxc/content-profile.json";
26743
+ var MEMORY_DISPLAY_PATH = "~/.dxc/content-memory.json";
26734
26744
  var USER_MEMORY_DISPLAY_PATH = "~/.dxc/USER.md";
26735
26745
  var PROFILE_MAXIMUM_BYTES = 64 * 1024;
26746
+ var MEMORY_MAXIMUM_BYTES = 128 * 1024;
26736
26747
  var ProfileCliError = class extends Error {
26737
26748
  constructor(code, message) {
26738
26749
  super(message);
@@ -26741,19 +26752,45 @@ var ProfileCliError = class extends Error {
26741
26752
  }
26742
26753
  code;
26743
26754
  };
26755
+ var ContentMemoryCliError = class extends Error {
26756
+ constructor(code, message) {
26757
+ super(message);
26758
+ this.code = code;
26759
+ this.name = "ContentMemoryCliError";
26760
+ }
26761
+ code;
26762
+ };
26744
26763
  function profilePath(homeDirectory) {
26745
26764
  return path2.join(homeDirectory, ".dxc", "content-profile.json");
26746
26765
  }
26747
26766
  function userMemoryPath(homeDirectory) {
26748
26767
  return path2.join(homeDirectory, ".dxc", "USER.md");
26749
26768
  }
26769
+ function memoryPath(homeDirectory) {
26770
+ return path2.join(homeDirectory, ".dxc", "content-memory.json");
26771
+ }
26750
26772
  function singleLine(value) {
26751
26773
  return value.replace(/[\r\n]+/gu, " ").replace(/\s+/gu, " ").trim();
26752
26774
  }
26753
26775
  function optionalLine(label, value) {
26754
26776
  return value === void 0 ? void 0 : `- ${label}\uFF1A${singleLine(value)}`;
26755
26777
  }
26756
- function renderUserMemory(user) {
26778
+ function memoryKindLabel(kind) {
26779
+ return {
26780
+ "audience-change": "\u53D7\u4F17\u53D8\u5316",
26781
+ "brand-context": "\u54C1\u724C\u80CC\u666F",
26782
+ "business-context": "\u4E1A\u52A1\u80CC\u666F",
26783
+ "temporary-campaign": "\u4E34\u65F6\u6D3B\u52A8",
26784
+ "writing-preference": "\u5199\u4F5C\u504F\u597D"
26785
+ }[kind];
26786
+ }
26787
+ function renderUserMemory(user, memories) {
26788
+ const confirmationPolicy = user.confirmationPolicy ?? "guided";
26789
+ const confirmationDescription = {
26790
+ guided: "\u5173\u952E\u5185\u5BB9\u3001\u6807\u9898\u4E0E\u8349\u7A3F\u4EA4\u4ED8\u786E\u8BA4\uFF08\u63A8\u8350\uFF09",
26791
+ "review-every-stage": "\u6BCF\u4E2A\u5185\u5BB9\u9636\u6BB5\u90FD\u5C55\u793A\u5E76\u7B49\u5F85\u786E\u8BA4",
26792
+ "auto-until-delivery": "\u5185\u5BB9\u9636\u6BB5\u81EA\u52A8\u63A8\u8FDB\uFF0C\u4EC5\u8349\u7A3F\u521B\u5EFA\u4FDD\u7559\u660E\u786E\u786E\u8BA4"
26793
+ }[confirmationPolicy];
26757
26794
  const lines = [
26758
26795
  "# DxC \u7528\u6237\u5168\u5C40\u8BB0\u5FC6",
26759
26796
  "",
@@ -26773,10 +26810,18 @@ function renderUserMemory(user) {
26773
26810
  `- \u8BFB\u8005\u627F\u8BFA\uFF1A${singleLine(user.contentValuePromise)}`,
26774
26811
  "",
26775
26812
  "## \u8868\u8FBE\u4E0E\u8FB9\u754C",
26776
- `- \u6587\u98CE\uFF1A${singleLine(user.writingVoice)}`,
26777
- `- \u4EBA\u79F0\u504F\u597D\uFF1A${singleLine(user.pointOfView)}`,
26778
- `- \u6838\u5FC3\u4EF7\u503C\u89C2\uFF1A${singleLine(user.coreValues)}`,
26779
- `- \u4E0D\u53EF\u89E6\u78B0\u7EA2\u7EBF\uFF1A${singleLine(user.redLines)}`,
26813
+ ...[optionalLine("\u6587\u98CE", user.writingVoice)].filter(
26814
+ (line) => line !== void 0
26815
+ ),
26816
+ ...[optionalLine("\u4EBA\u79F0\u504F\u597D", user.pointOfView)].filter(
26817
+ (line) => line !== void 0
26818
+ ),
26819
+ ...[optionalLine("\u6838\u5FC3\u4EF7\u503C\u89C2", user.coreValues)].filter(
26820
+ (line) => line !== void 0
26821
+ ),
26822
+ ...[optionalLine("\u4E0D\u53EF\u89E6\u78B0\u7EA2\u7EBF", user.redLines)].filter(
26823
+ (line) => line !== void 0
26824
+ ),
26780
26825
  ...[optionalLine("\u66F4\u65B0\u9891\u7387", user.publishingCadence)].filter(
26781
26826
  (line) => line !== void 0
26782
26827
  ),
@@ -26787,8 +26832,19 @@ function renderUserMemory(user) {
26787
26832
  (line) => line !== void 0
26788
26833
  ),
26789
26834
  "",
26835
+ "## \u5DE5\u4F5C\u6D41\u786E\u8BA4",
26836
+ `- \u786E\u8BA4\u7B56\u7565\uFF1A${confirmationDescription}`,
26837
+ "- \u4E0D\u53EF\u7ED5\u8FC7\uFF1A\u521B\u5EFA\u5FAE\u4FE1\u516C\u4F17\u53F7\u8349\u7A3F\u524D\uFF0C\u4ECD\u5FC5\u987B\u5728\u4E0D\u53EF\u53D8\u9884\u89C8\u4E0A\u660E\u786E\u786E\u8BA4\uFF1B\u672A\u6388\u6743\u6216\u8D85\u51FA\u5DF2\u786E\u8BA4\u989D\u5EA6\u7684\u56FE\u7247\u751F\u6210\u4ECD\u4F1A\u6682\u505C\u3002",
26838
+ `- \u56FE\u7247\u751F\u6210\u6388\u6743\uFF1A${user.visualGenerationAuthorization === void 0 ? "\u6BCF\u6B21\u786E\u8BA4" : `\u5355\u6B21\u6700\u591A ${user.visualGenerationAuthorization.maxImagesPerRun} \u5F20\uFF0C\u8303\u56F4\u5185\u53EF\u81EA\u52A8\u751F\u6210`}`,
26839
+ "",
26790
26840
  "## \u672C\u5730\u5386\u53F2\u6587\u7AE0",
26791
26841
  ...user.historyDirectory === void 0 ? ["- \u5C1A\u672A\u9009\u62E9\u76EE\u5F55\u3002\u53EA\u5728\u7528\u6237\u660E\u786E\u6307\u5B9A\u76EE\u5F55\u540E\u5BFC\u5165\uFF0C\u4E0D\u81EA\u52A8\u626B\u63CF\u3002"] : [`- \u5DF2\u6388\u6743\u76EE\u5F55\uFF1A${singleLine(user.historyDirectory)}`],
26842
+ "",
26843
+ "## \u4ECD\u6709\u6548\u7684\u8865\u5145\u8BB0\u5FC6",
26844
+ ...memories.length === 0 ? ["- \u6682\u65E0\u3002\u5185\u5BB9\u5DE5\u4F5C\u6D41\u4F1A\u4ECE\u7528\u6237\u81EA\u7136\u8BED\u8A00\u4E2D\u63D0\u70BC\u7A33\u5B9A\u8865\u5145\u4FE1\u606F\uFF1B\u53EF\u968F\u65F6\u67E5\u770B\u3001\u66F4\u6B63\u6216\u5F52\u6863\u3002"] : memories.slice(0, 8).map((memory) => {
26845
+ const expiry = memory.expiresAt === void 0 ? "" : `\uFF1B\u6709\u6548\u81F3 ${memory.expiresAt}`;
26846
+ return `- [${memoryKindLabel(memory.kind)}] ${singleLine(memory.content)}${expiry}`;
26847
+ }),
26792
26848
  ""
26793
26849
  ];
26794
26850
  return lines.join("\n");
@@ -26797,6 +26853,9 @@ function parseJson(raw, code, message) {
26797
26853
  try {
26798
26854
  return JSON.parse(raw);
26799
26855
  } catch {
26856
+ if (code.startsWith("DXC_MEMORY_")) {
26857
+ throw new ContentMemoryCliError(code, message);
26858
+ }
26800
26859
  throw new ProfileCliError(code, message);
26801
26860
  }
26802
26861
  }
@@ -26821,6 +26880,47 @@ async function readProfile(target) {
26821
26880
  }
26822
26881
  return parsed.data;
26823
26882
  }
26883
+ async function readMemoryStore(target) {
26884
+ let raw;
26885
+ try {
26886
+ raw = await readPrivateFile(target, MEMORY_MAXIMUM_BYTES);
26887
+ } catch (error) {
26888
+ if (error instanceof LocalStateError && error.failure === "missing") {
26889
+ return { memories: [], schemaVersion: "1" };
26890
+ }
26891
+ if (error instanceof LocalStateError && error.failure === "invalid") {
26892
+ throw new ContentMemoryCliError("DXC_MEMORY_INVALID", "Local content memory is invalid");
26893
+ }
26894
+ throw new ContentMemoryCliError("DXC_MEMORY_IO_FAILED", "Unable to read local content memory");
26895
+ }
26896
+ const parsed = contentMemoryStoreSchema.safeParse(
26897
+ parseJson(raw, "DXC_MEMORY_INVALID", "Local content memory is invalid")
26898
+ );
26899
+ if (!parsed.success) {
26900
+ throw new ContentMemoryCliError("DXC_MEMORY_INVALID", "Local content memory is invalid");
26901
+ }
26902
+ return parsed.data;
26903
+ }
26904
+ function activeMemories(store, now) {
26905
+ const memories = store.memories.map(
26906
+ (memory) => memory.status === "active" && memory.expiresAt !== void 0 && memory.expiresAt <= now.toISOString() ? { ...memory, status: "expired", updatedAt: now.toISOString() } : memory
26907
+ );
26908
+ return {
26909
+ memories: memories.filter((memory) => memory.status === "active"),
26910
+ store: { ...store, memories }
26911
+ };
26912
+ }
26913
+ async function refreshUserMemory(homeDirectory, user, now) {
26914
+ if (user === void 0) {
26915
+ return;
26916
+ }
26917
+ const memory = activeMemories(await readMemoryStore(memoryPath(homeDirectory)), now);
26918
+ await writePrivateJson(memoryPath(homeDirectory), memory.store);
26919
+ await writePrivateBuffer(
26920
+ userMemoryPath(homeDirectory),
26921
+ Buffer.from(renderUserMemory(user, memory.memories))
26922
+ );
26923
+ }
26824
26924
  async function readProfileInput(currentDirectory, inputPath) {
26825
26925
  try {
26826
26926
  const target = path2.resolve(currentDirectory, inputPath);
@@ -26870,12 +26970,7 @@ var ProfileCli = class {
26870
26970
  });
26871
26971
  try {
26872
26972
  await writePrivateJson(target, profile);
26873
- if (profile.user !== void 0) {
26874
- await writePrivateBuffer(
26875
- userMemoryPath(this.#homeDirectory),
26876
- Buffer.from(renderUserMemory(profile.user))
26877
- );
26878
- }
26973
+ await refreshUserMemory(this.#homeDirectory, profile.user, this.#now());
26879
26974
  } catch {
26880
26975
  throw new ProfileCliError("DXC_PROFILE_IO_FAILED", "Unable to save local content profile");
26881
26976
  }
@@ -26889,6 +26984,47 @@ var ProfileCli = class {
26889
26984
  ok: true
26890
26985
  });
26891
26986
  }
26987
+ async update(inputPath) {
26988
+ const input = contentProfileUpdateInputSchema.safeParse(
26989
+ await readProfileInput(this.#currentDirectory, inputPath)
26990
+ );
26991
+ if (!input.success) {
26992
+ throw new ProfileCliError("DXC_PROFILE_INPUT_INVALID", "Profile update input is invalid");
26993
+ }
26994
+ const target = profilePath(this.#homeDirectory);
26995
+ const existing = await readProfile(target);
26996
+ if (existing === void 0) {
26997
+ throw new ProfileCliError("DXC_PROFILE_INVALID", "Content profile is not initialized");
26998
+ }
26999
+ const answerByQuestionId = new Map(
27000
+ existing.answers.map((answer) => [answer.questionId, answer])
27001
+ );
27002
+ for (const answer of input.data.answers ?? []) {
27003
+ answerByQuestionId.set(answer.questionId, answer);
27004
+ }
27005
+ const timestamp = this.#now().toISOString();
27006
+ const profile = contentProfileSchema.parse({
27007
+ ...existing,
27008
+ answers: [...answerByQuestionId.values()],
27009
+ ...input.data.user === void 0 ? {} : { user: { ...existing.user, ...input.data.user } },
27010
+ updatedAt: timestamp
27011
+ });
27012
+ try {
27013
+ await writePrivateJson(target, profile);
27014
+ await refreshUserMemory(this.#homeDirectory, profile.user, this.#now());
27015
+ } catch {
27016
+ throw new ProfileCliError("DXC_PROFILE_IO_FAILED", "Unable to update local content profile");
27017
+ }
27018
+ return contentProfileUpdateResultSchema.parse({
27019
+ command: "profile.update",
27020
+ data: {
27021
+ profile,
27022
+ profilePath: PROFILE_DISPLAY_PATH,
27023
+ userMemoryPath: USER_MEMORY_DISPLAY_PATH
27024
+ },
27025
+ ok: true
27026
+ });
27027
+ }
26892
27028
  async status() {
26893
27029
  const profile = await readProfile(profilePath(this.#homeDirectory));
26894
27030
  return contentProfileStatusResultSchema.parse({
@@ -26907,6 +27043,116 @@ var ProfileCli = class {
26907
27043
  });
26908
27044
  }
26909
27045
  };
27046
+ var ContentMemoryCli = class {
27047
+ #currentDirectory;
27048
+ #homeDirectory;
27049
+ #now;
27050
+ #randomUUID;
27051
+ constructor(dependencies) {
27052
+ this.#currentDirectory = dependencies.currentDirectory;
27053
+ this.#homeDirectory = dependencies.homeDirectory;
27054
+ this.#now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
27055
+ this.#randomUUID = dependencies.randomUUID ?? randomUUID;
27056
+ }
27057
+ async add(inputPath) {
27058
+ const input = contentMemoryInputSchema.safeParse(
27059
+ await readProfileInput(this.#currentDirectory, inputPath)
27060
+ );
27061
+ if (!input.success) {
27062
+ throw new ContentMemoryCliError(
27063
+ "DXC_MEMORY_INPUT_INVALID",
27064
+ "Content memory input is invalid"
27065
+ );
27066
+ }
27067
+ const timestamp = this.#now().toISOString();
27068
+ const record = {
27069
+ ...input.data,
27070
+ createdAt: timestamp,
27071
+ id: this.#randomUUID(),
27072
+ source: "user-stated",
27073
+ status: "active",
27074
+ updatedAt: timestamp
27075
+ };
27076
+ const target = memoryPath(this.#homeDirectory);
27077
+ const store = await readMemoryStore(target);
27078
+ if (store.memories.length >= 100) {
27079
+ throw new ContentMemoryCliError("DXC_MEMORY_IO_FAILED", "Content memory capacity is reached");
27080
+ }
27081
+ const next = contentMemoryStoreSchema.parse({
27082
+ ...store,
27083
+ memories: [...store.memories, record]
27084
+ });
27085
+ try {
27086
+ await writePrivateJson(target, next);
27087
+ const profile = await readProfile(profilePath(this.#homeDirectory));
27088
+ await refreshUserMemory(this.#homeDirectory, profile?.user, this.#now());
27089
+ } catch (error) {
27090
+ if (error instanceof ContentMemoryCliError || error instanceof ProfileCliError) {
27091
+ throw error;
27092
+ }
27093
+ throw new ContentMemoryCliError("DXC_MEMORY_IO_FAILED", "Unable to save content memory");
27094
+ }
27095
+ return contentMemoryAddResultSchema.parse({
27096
+ command: "memory.add",
27097
+ data: { memory: record, memories: next.memories, memoryPath: MEMORY_DISPLAY_PATH },
27098
+ ok: true
27099
+ });
27100
+ }
27101
+ async list() {
27102
+ const target = memoryPath(this.#homeDirectory);
27103
+ const state = activeMemories(await readMemoryStore(target), this.#now());
27104
+ try {
27105
+ await writePrivateJson(target, state.store);
27106
+ } catch {
27107
+ throw new ContentMemoryCliError(
27108
+ "DXC_MEMORY_IO_FAILED",
27109
+ "Unable to update content memory state"
27110
+ );
27111
+ }
27112
+ return contentMemoryListResultSchema.parse({
27113
+ command: "memory.list",
27114
+ data: { memories: state.memories, memoryPath: MEMORY_DISPLAY_PATH },
27115
+ ok: true
27116
+ });
27117
+ }
27118
+ async archive(memoryId) {
27119
+ const target = memoryPath(this.#homeDirectory);
27120
+ const store = await readMemoryStore(target);
27121
+ const index = store.memories.findIndex(
27122
+ (memory2) => memory2.id === memoryId && memory2.status === "active"
27123
+ );
27124
+ if (index < 0) {
27125
+ throw new ContentMemoryCliError(
27126
+ "DXC_MEMORY_NOT_FOUND",
27127
+ "Active content memory was not found"
27128
+ );
27129
+ }
27130
+ const timestamp = this.#now().toISOString();
27131
+ const memory = { ...store.memories[index], status: "archived", updatedAt: timestamp };
27132
+ const memories = store.memories.map(
27133
+ (entry, entryIndex) => entryIndex === index ? memory : entry
27134
+ );
27135
+ try {
27136
+ await writePrivateJson(target, { ...store, memories });
27137
+ const profile = await readProfile(profilePath(this.#homeDirectory));
27138
+ await refreshUserMemory(this.#homeDirectory, profile?.user, this.#now());
27139
+ } catch (error) {
27140
+ if (error instanceof ContentMemoryCliError || error instanceof ProfileCliError) {
27141
+ throw error;
27142
+ }
27143
+ throw new ContentMemoryCliError("DXC_MEMORY_IO_FAILED", "Unable to archive content memory");
27144
+ }
27145
+ return contentMemoryArchiveResultSchema.parse({
27146
+ command: "memory.archive",
27147
+ data: {
27148
+ memory,
27149
+ memories: memories.filter((entry) => entry.status === "active"),
27150
+ memoryPath: MEMORY_DISPLAY_PATH
27151
+ },
27152
+ ok: true
27153
+ });
27154
+ }
27155
+ };
26910
27156
 
26911
27157
  // apps/cli/src/project.ts
26912
27158
  import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
@@ -28166,33 +28412,36 @@ var tn = x.lex;
28166
28412
 
28167
28413
  // packages/renderer-wechat/src/article.ts
28168
28414
  var import_yaml = __toESM(require_dist(), 1);
28169
- var dxcArticleMetadataSchema = external_exports.object({
28170
- artifactStatus: external_exports.enum(["complete", "awaiting-user", "blocked"]),
28171
- contract: external_exports.literal("dxc-content-stage@1"),
28172
- createdAt: external_exports.iso.datetime(),
28173
- inputs: external_exports.array(
28174
- external_exports.object({
28175
- kind: external_exports.enum(["research", "brief", "outline"]),
28415
+ import { z as z2 } from "zod";
28416
+ var dxcArticleMetadataSchema = z2.object({
28417
+ artifactStatus: z2.enum(["complete", "awaiting-user", "blocked"]),
28418
+ contract: z2.literal("dxc-content-stage@1"),
28419
+ createdAt: z2.iso.datetime(),
28420
+ inputs: z2.array(
28421
+ z2.object({
28422
+ kind: z2.enum(["research", "brief", "outline"]),
28176
28423
  path: portableRelativePathSchema,
28177
- sha256: external_exports.string().regex(/^[a-f0-9]{64}$/u)
28424
+ sha256: z2.string().regex(/^[a-f0-9]{64}$/u)
28178
28425
  }).strict()
28179
28426
  ),
28180
- projectId: external_exports.uuid(),
28181
- skill: external_exports.string().regex(/^dxc-[a-z0-9]+(?:-[a-z0-9]+)*@\d+\.\d+\.\d+$/u),
28182
- stage: external_exports.literal("article"),
28183
- workflowId: external_exports.literal("dxc-article@1")
28427
+ projectId: z2.uuid(),
28428
+ skill: z2.string().regex(/^dxc-[a-z0-9]+(?:-[a-z0-9]+)*@\d+\.\d+\.\d+$/u),
28429
+ stage: z2.literal("article"),
28430
+ workflowId: z2.literal("dxc-article@1")
28184
28431
  }).strict();
28185
- var rawFrontmatterSchema = external_exports.object({
28186
- title: external_exports.string().trim().min(1).optional(),
28187
- author: external_exports.string().trim().min(1),
28188
- tags: external_exports.array(external_exports.string().trim().min(1)).default([]),
28189
- digest: external_exports.string().trim().min(1).optional(),
28190
- wechat_digest: external_exports.string().trim().min(1).optional(),
28191
- commentsEnabled: external_exports.boolean().optional(),
28192
- wechat_comments: external_exports.union([external_exports.literal(0), external_exports.literal(1), external_exports.boolean()]).optional(),
28193
- coverImage: external_exports.string().trim().min(1).optional(),
28194
- wechat_cover_image: external_exports.string().trim().min(1).optional(),
28195
- dxc_wechat_template_hint: external_exports.string().trim().min(1).optional(),
28432
+ var rawFrontmatterSchema = z2.object({
28433
+ title: z2.string().trim().min(1).optional(),
28434
+ author: z2.string().trim().min(1),
28435
+ tags: z2.array(z2.string().trim().min(1)).default([]),
28436
+ digest: z2.string().trim().min(1).optional(),
28437
+ wechat_digest: z2.string().trim().min(1).optional(),
28438
+ goldenLinesPath: portableRelativePathSchema.optional(),
28439
+ goldenLinesSha256: z2.string().regex(/^[a-f0-9]{64}$/u).optional(),
28440
+ commentsEnabled: z2.boolean().optional(),
28441
+ wechat_comments: z2.union([z2.literal(0), z2.literal(1), z2.boolean()]).optional(),
28442
+ coverImage: z2.string().trim().min(1).optional(),
28443
+ wechat_cover_image: z2.string().trim().min(1).optional(),
28444
+ dxc_wechat_template_hint: z2.string().trim().min(1).optional(),
28196
28445
  dxc: dxcArticleMetadataSchema.optional()
28197
28446
  }).strict();
28198
28447
  var FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/u;
@@ -29096,6 +29345,22 @@ function parseFrontmatter2(source) {
29096
29345
  throw new StageArtifactValidationError(["YAML frontmatter"]);
29097
29346
  }
29098
29347
  }
29348
+ async function validateGoldenLinesSidecar(directory, articleBody, logicalPath, expectedSha256) {
29349
+ const bytes = await readRegularFile(insideProject(directory, logicalPath), 64 * 1024);
29350
+ if (sha256(bytes) !== expectedSha256) {
29351
+ throw new StageArtifactValidationError([`${logicalPath} \u54C8\u5E0C\u4E0D\u4E00\u81F4`]);
29352
+ }
29353
+ let value;
29354
+ try {
29355
+ value = JSON.parse(bytes.toString("utf8"));
29356
+ } catch {
29357
+ throw new StageArtifactValidationError([`${logicalPath} \u4E0D\u662F\u5408\u6CD5\u91D1\u53E5\u4EA4\u63A5\u6587\u4EF6`]);
29358
+ }
29359
+ const parsed = goldenLinesSidecarSchema.safeParse(value);
29360
+ if (!parsed.success || parsed.data.lines.some((line) => !articleBody.includes(line.text))) {
29361
+ throw new StageArtifactValidationError([`${logicalPath} \u91D1\u53E5\u4EA4\u63A5\u4E0E\u6B63\u6587\u4E0D\u4E00\u81F4`]);
29362
+ }
29363
+ }
29099
29364
  function compareInputs(declared, actual) {
29100
29365
  const issues = [];
29101
29366
  if (new Set(declared.map((input) => input.kind)).size !== declared.length) {
@@ -29154,6 +29419,15 @@ async function validateStageArtifact(options) {
29154
29419
  } catch {
29155
29420
  issues.push("\u6B63\u6587\u53D1\u5E03\u683C\u5F0F");
29156
29421
  }
29422
+ const article = parsed.data;
29423
+ if ("goldenLinesPath" in article && "goldenLinesSha256" in article) {
29424
+ await validateGoldenLinesSidecar(
29425
+ options.directory,
29426
+ frontmatter.body,
29427
+ article.goldenLinesPath,
29428
+ article.goldenLinesSha256
29429
+ );
29430
+ }
29157
29431
  }
29158
29432
  if (options.stage === "quality-review") {
29159
29433
  const review = parsed.data;
@@ -29227,7 +29501,8 @@ var TERMINAL_CHECKPOINT_STATUSES = /* @__PURE__ */ new Set([
29227
29501
  "failed",
29228
29502
  "skipped"
29229
29503
  ]);
29230
- var USER_CONFIRMATION_STAGES = /* @__PURE__ */ new Set(["article", "titles", "delivery"]);
29504
+ var DEFAULT_CONFIRMATION_POLICY = "guided";
29505
+ var PROFILE_MAXIMUM_BYTES2 = 64 * 1024;
29231
29506
  var ARTICLE_ADOPTION_SKILL = {
29232
29507
  name: "dxc-content-workflow",
29233
29508
  version: "0.6.0"
@@ -29549,14 +29824,38 @@ async function findNearestProjectDirectory(start) {
29549
29824
  var ProjectCli = class {
29550
29825
  #currentDirectory;
29551
29826
  #now;
29827
+ #profilePath;
29552
29828
  #projectIndexPath;
29553
29829
  #randomUUID;
29554
29830
  constructor(dependencies) {
29555
29831
  this.#currentDirectory = dependencies.currentDirectory;
29556
29832
  this.#now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
29557
29833
  this.#projectIndexPath = path4.join(dependencies.homeDirectory, PROJECT_INDEX_RELATIVE_PATH);
29834
+ this.#profilePath = path4.join(dependencies.homeDirectory, ".dxc", "content-profile.json");
29558
29835
  this.#randomUUID = dependencies.randomUUID ?? randomUUID2;
29559
29836
  }
29837
+ async #confirmationPolicy() {
29838
+ try {
29839
+ const raw = await readPrivateFile(this.#profilePath, PROFILE_MAXIMUM_BYTES2);
29840
+ const profile = contentProfileSchema.safeParse(JSON.parse(raw));
29841
+ return profile.success ? profile.data.user?.confirmationPolicy ?? DEFAULT_CONFIRMATION_POLICY : DEFAULT_CONFIRMATION_POLICY;
29842
+ } catch {
29843
+ return DEFAULT_CONFIRMATION_POLICY;
29844
+ }
29845
+ }
29846
+ async #requiresUserConfirmation(stage) {
29847
+ if (stage === "delivery") {
29848
+ return true;
29849
+ }
29850
+ const policy = await this.#confirmationPolicy();
29851
+ if (policy === "auto-until-delivery") {
29852
+ return false;
29853
+ }
29854
+ if (policy === "review-every-stage") {
29855
+ return true;
29856
+ }
29857
+ return stage === "article" || stage === "titles";
29858
+ }
29560
29859
  async #rememberProject(directory, manifest, updatedAt) {
29561
29860
  const index = await loadProjectIndex(this.#projectIndexPath);
29562
29861
  const projects = [
@@ -29785,7 +30084,8 @@ var ProjectCli = class {
29785
30084
  `\u9636\u6BB5 ${stage.data} \u5FC5\u987B\u7531 ${expectedSkill.name}@${expectedSkill.version} \u5199\u5165\u68C0\u67E5\u70B9\u3002`
29786
30085
  );
29787
30086
  }
29788
- const confirmationRequired = status.data === "completed" && USER_CONFIRMATION_STAGES.has(stage.data) && options.confirmed !== true;
30087
+ const requiresUserConfirmation = await this.#requiresUserConfirmation(stage.data);
30088
+ const confirmationRequired = status.data === "completed" && requiresUserConfirmation && options.confirmed !== true;
29789
30089
  const effectiveStatus = confirmationRequired ? "awaiting-user" : status.data;
29790
30090
  const waitingFor = confirmationRequired ? requestedWaitingFor ?? `\u8BF7\u786E\u8BA4 ${stage.data} \u9636\u6BB5\u5F53\u524D\u5FEB\u7167\uFF1B\u786E\u8BA4\u540E\u4F7F\u7528 --confirm \u5B8C\u6210\u8BE5\u9636\u6BB5\u3002` : requestedWaitingFor;
29791
30091
  if (effectiveStatus === "failed" && options.errorCode === void 0) {
@@ -29904,10 +30204,10 @@ var ProjectCli = class {
29904
30204
  "\u786E\u8BA4\u5FEB\u7167\u4E0E\u5F53\u524D\u9636\u6BB5\u7ECF\u8FC7\u6821\u9A8C\u7684\u5185\u5BB9\u6216\u6E32\u67D3\u5FEB\u7167\u4E0D\u4E00\u81F4\u3002"
29905
30205
  );
29906
30206
  }
29907
- const confirmationRelevant = effectiveStatus === "awaiting-user" || effectiveStatus === "completed" && USER_CONFIRMATION_STAGES.has(stage.data) && options.confirmed;
30207
+ const confirmationRelevant = effectiveStatus === "awaiting-user" || effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed;
29908
30208
  const previousBinding = existing?.checkpointVersion === "3" ? existing.confirmationBinding : null;
29909
30209
  const confirmationSnapshotType = artifactValidation?.snapshotType ?? "stage-artifact";
29910
- if (effectiveStatus === "completed" && USER_CONFIRMATION_STAGES.has(stage.data) && options.confirmed && (existing?.status !== "awaiting-user" || existing.confirmation !== "pending" || previousBinding?.status !== "pending" || previousBinding.snapshotHash !== confirmationSnapshotHash || previousBinding.snapshotType !== confirmationSnapshotType)) {
30210
+ if (effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed && (existing?.status !== "awaiting-user" || existing.confirmation !== "pending" || previousBinding?.status !== "pending" || previousBinding.snapshotHash !== confirmationSnapshotHash || previousBinding.snapshotType !== confirmationSnapshotType)) {
29911
30211
  throw new ProjectCliError(
29912
30212
  "DXC_PROJECT_STAGE_INVALID",
29913
30213
  "\u5F53\u524D\u5185\u5BB9\u6216\u6E32\u67D3\u5FEB\u7167\u4E0D\u662F\u521A\u624D\u7B49\u5F85\u786E\u8BA4\u7684\u7248\u672C\uFF1B\u8BF7\u5148\u91CD\u65B0\u5C55\u793A\u5E76\u5199\u5165 awaiting-user \u68C0\u67E5\u70B9\uFF0C\u518D\u6839\u636E\u7528\u6237\u660E\u786E\u56DE\u7B54\u786E\u8BA4\u3002"
@@ -29926,7 +30226,7 @@ var ProjectCli = class {
29926
30226
  } : {},
29927
30227
  checkpointVersion: "3",
29928
30228
  ...TERMINAL_CHECKPOINT_STATUSES.has(effectiveStatus) ? { completedAt: timestamp } : {},
29929
- confirmation: effectiveStatus === "awaiting-user" ? "pending" : effectiveStatus === "completed" && USER_CONFIRMATION_STAGES.has(stage.data) && options.confirmed ? "confirmed" : "not-required",
30229
+ confirmation: effectiveStatus === "awaiting-user" ? "pending" : effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed ? "confirmed" : "not-required",
29930
30230
  confirmationBinding: confirmationRelevant && confirmationSnapshotHash !== void 0 ? {
29931
30231
  confirmedAt: effectiveStatus === "completed" ? timestamp : null,
29932
30232
  confirmedBy: effectiveStatus === "completed" ? confirmedBy : null,
@@ -29988,6 +30288,10 @@ import path5 from "node:path";
29988
30288
  import { fileURLToPath } from "node:url";
29989
30289
  var OFFICIAL_SKILLS = [
29990
30290
  "dxc-content-workflow",
30291
+ "dxc-profile",
30292
+ "dxc-memory",
30293
+ "dxc-knowledge",
30294
+ "dxc-quote-curator",
29991
30295
  "dxc-research",
29992
30296
  "dxc-content-brief",
29993
30297
  "dxc-article-outline",
@@ -30270,6 +30574,7 @@ import { createHash as createHash6 } from "node:crypto";
30270
30574
  import { constants as fileConstants2 } from "node:fs";
30271
30575
  import { lstat as lstat3, open as open2, readdir as readdir2, realpath } from "node:fs/promises";
30272
30576
  import path6 from "node:path";
30577
+ var import_yaml3 = __toESM(require_dist(), 1);
30273
30578
 
30274
30579
  // apps/cli/src/wechat-error.ts
30275
30580
  var WechatCliError = class extends Error {
@@ -30289,6 +30594,8 @@ var MAXIMUM_IMAGE_BYTES = 5 * 1024 * 1024;
30289
30594
  var MAXIMUM_INLINE_IMAGE_BYTES2 = 1024 * 1024 - 1;
30290
30595
  var MAXIMUM_INLINE_IMAGES = 20;
30291
30596
  var SUPPORTED_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".jpeg", ".jpg", ".png"]);
30597
+ var VISUAL_PLAN_MAXIMUM_BYTES = 128 * 1024;
30598
+ var VISUAL_PLAN_FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u;
30292
30599
  async function readPublishingInput(inputPath, maximumBytes) {
30293
30600
  const target = path6.resolve(inputPath);
30294
30601
  let handle;
@@ -30417,6 +30724,7 @@ function injectCollectedImages(source, images) {
30417
30724
  }
30418
30725
  const lines = source.split("\n");
30419
30726
  const headingLines = [];
30727
+ const headingLineByText = /* @__PURE__ */ new Map();
30420
30728
  let inFence = false;
30421
30729
  for (const [index, line] of lines.entries()) {
30422
30730
  if (/^\s*```/u.test(line)) {
@@ -30425,11 +30733,24 @@ function injectCollectedImages(source, images) {
30425
30733
  }
30426
30734
  if (!inFence && /^##\s+\S/u.test(line)) {
30427
30735
  headingLines.push(index);
30736
+ const text = line.replace(/^##\s+/u, "").replace(/\s+#+\s*$/u, "").trim();
30737
+ headingLineByText.set(text, [...headingLineByText.get(text) ?? [], index]);
30428
30738
  }
30429
30739
  }
30430
30740
  const insertions = /* @__PURE__ */ new Map();
30431
30741
  for (const [index, image] of images.entries()) {
30432
- const headingLine = headingLines[index];
30742
+ let headingLine = headingLines[index];
30743
+ if (image.placementAnchor !== void 0) {
30744
+ const match = /^after-heading:(.+)$/u.exec(image.placementAnchor);
30745
+ const matches = match === null ? void 0 : headingLineByText.get(match[1]?.trim() ?? "");
30746
+ if (matches === void 0 || matches.length !== 1) {
30747
+ throw new WechatCliError(
30748
+ "DXC_PUBLISHING_VISUAL_ANCHOR_INVALID",
30749
+ "\u89C6\u89C9\u8BA1\u5212\u7684\u63D2\u56FE\u951A\u70B9\u5FC5\u987B\u552F\u4E00\u5339\u914D\u6B63\u6587\u4E2D\u7684\u4E00\u4E2A\u4E8C\u7EA7\u6807\u9898\u3002"
30750
+ );
30751
+ }
30752
+ headingLine = matches[0];
30753
+ }
30433
30754
  const target = headingLine === void 0 ? lines.length : headingLine + 1;
30434
30755
  const insertion = `
30435
30756
  ![${image.alt}](${image.logicalPath})
@@ -30445,6 +30766,52 @@ function injectCollectedImages(source, images) {
30445
30766
  }
30446
30767
  return output.join("\n");
30447
30768
  }
30769
+ async function plannedInlineImages(visualPlanFile, availableByFileName) {
30770
+ let source;
30771
+ try {
30772
+ source = (await readPublishingInput(visualPlanFile, VISUAL_PLAN_MAXIMUM_BYTES)).bytes.toString("utf8");
30773
+ } catch {
30774
+ throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30775
+ }
30776
+ const yamlSource = VISUAL_PLAN_FRONTMATTER.exec(source)?.[1];
30777
+ if (yamlSource === void 0) {
30778
+ throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30779
+ }
30780
+ let visualPlan;
30781
+ try {
30782
+ visualPlan = (0, import_yaml3.parse)(yamlSource, { maxAliasCount: 10, uniqueKeys: true });
30783
+ } catch {
30784
+ throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30785
+ }
30786
+ const parsed = visualPlanStageArtifactFrontmatterSchema.safeParse(visualPlan);
30787
+ if (!parsed.success) {
30788
+ throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30789
+ }
30790
+ return Promise.all(parsed.data.inlineAssets.map(async (asset) => {
30791
+ const absolutePath = availableByFileName.get(path6.posix.basename(asset.path));
30792
+ if (absolutePath === void 0) {
30793
+ throw new WechatCliError(
30794
+ "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
30795
+ `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0D\u5728\u6307\u5B9A\u7D20\u6750\u76EE\u5F55\u4E2D\u3002`
30796
+ );
30797
+ }
30798
+ const input = await readPublishingInput(absolutePath, MAXIMUM_INLINE_IMAGE_BYTES2);
30799
+ if (createHash6("sha256").update(input.bytes).digest("hex") !== asset.sha256) {
30800
+ throw new WechatCliError(
30801
+ "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
30802
+ `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0E\u8BB0\u5F55\u7684\u54C8\u5E0C\u4E0D\u4E00\u81F4\u3002`
30803
+ );
30804
+ }
30805
+ const digest = createHash6("sha256").update(absolutePath).digest("hex").slice(0, 12);
30806
+ const fileName = safeFileName(path6.basename(absolutePath)) || `visual-${digest}.png`;
30807
+ return {
30808
+ absolutePath,
30809
+ alt: asset.purpose,
30810
+ logicalPath: `assets/dxc-visuals/${digest}-${fileName}`,
30811
+ placementAnchor: asset.placementAnchor
30812
+ };
30813
+ }));
30814
+ }
30448
30815
  function logicalInlinePaths(bundle) {
30449
30816
  return bundle.assets.filter((asset) => asset.role === "inline").map((asset) => asset.logicalPath);
30450
30817
  }
@@ -30479,18 +30846,22 @@ async function preparePublishingDraft(input) {
30479
30846
  const explicitCover = input.coverFile !== void 0 && input.coverFile !== "auto" ? input.coverFile : void 0;
30480
30847
  const coverCandidate = explicitCover ?? articleCoverCandidate ?? namedCoverCandidate;
30481
30848
  const coverMode = explicitCover !== void 0 ? "explicit-file" : articleCoverCandidate !== void 0 ? "article-frontmatter" : namedCoverCandidate !== void 0 ? "assets-directory" : void 0;
30849
+ const planned = input.visualPlanFile === void 0 ? [] : await plannedInlineImages(input.visualPlanFile, availableByFileName);
30482
30850
  const pickupCandidates = availableImages.filter(
30483
- (candidate) => candidate !== namedCoverCandidate && candidate !== articleCoverCandidate && !referencedFiles.has(path6.resolve(candidate))
30851
+ (candidate) => candidate !== namedCoverCandidate && candidate !== articleCoverCandidate && !referencedFiles.has(path6.resolve(candidate)) && input.visualPlanFile === void 0
30484
30852
  );
30485
- const injected = pickupCandidates.slice(0, Math.max(0, MAXIMUM_INLINE_IMAGES - referenced.size)).map((candidate) => {
30486
- const digest = createHash6("sha256").update(candidate).digest("hex").slice(0, 12);
30487
- const fileName = safeFileName(path6.basename(candidate)) || `visual-${digest}.png`;
30488
- return {
30489
- absolutePath: candidate,
30490
- alt: path6.basename(candidate, path6.extname(candidate)),
30491
- logicalPath: `assets/dxc-visuals/${digest}-${fileName}`
30492
- };
30493
- }).filter((asset) => !referenced.has(asset.logicalPath));
30853
+ const injected = [
30854
+ ...planned,
30855
+ ...pickupCandidates.slice(0, Math.max(0, MAXIMUM_INLINE_IMAGES - referenced.size)).map((candidate) => {
30856
+ const digest = createHash6("sha256").update(candidate).digest("hex").slice(0, 12);
30857
+ const fileName = safeFileName(path6.basename(candidate)) || `visual-${digest}.png`;
30858
+ return {
30859
+ absolutePath: candidate,
30860
+ alt: path6.basename(candidate, path6.extname(candidate)),
30861
+ logicalPath: `assets/dxc-visuals/${digest}-${fileName}`
30862
+ };
30863
+ }).filter((asset) => !referenced.has(asset.logicalPath))
30864
+ ];
30494
30865
  const finalSource = injectCollectedImages(originalSource, injected);
30495
30866
  let bundle;
30496
30867
  try {
@@ -31042,7 +31413,8 @@ var WechatCli = class {
31042
31413
  articleFile: options.articleFile,
31043
31414
  ...options.assetsDirectory === void 0 ? {} : { assetsDirectory: options.assetsDirectory },
31044
31415
  ...options.coverFile === void 0 ? {} : { coverFile: options.coverFile },
31045
- ...options.title === void 0 ? {} : { title: options.title }
31416
+ ...options.title === void 0 ? {} : { title: options.title },
31417
+ ...options.visualPlanFile === void 0 ? {} : { visualPlanFile: options.visualPlanFile }
31046
31418
  });
31047
31419
  const finalBundle = prepared.bundle;
31048
31420
  if (finalBundle.title.length === 0 || [...finalBundle.title].length > 32 || [...finalBundle.author].length > 16 || [...finalBundle.digest].length > 120) {
@@ -31710,7 +32082,7 @@ async function loadKnowledgeModule() {
31710
32082
  Reflect.apply(emitWarning, process, [warning2, ...arguments_]);
31711
32083
  });
31712
32084
  try {
31713
- return await import("./chunks/knowledge-4ZXXUSDQ.js");
32085
+ return await import("./chunks/knowledge-6LOGJETT.js");
31714
32086
  } finally {
31715
32087
  process.emitWarning = emitWarning;
31716
32088
  }
@@ -31724,7 +32096,7 @@ async function loadMonitorModule() {
31724
32096
  Reflect.apply(emitWarning, process, [warning2, ...arguments_]);
31725
32097
  });
31726
32098
  try {
31727
- return await import("./chunks/monitor-63LXCSZA.js");
32099
+ return await import("./chunks/monitor-CYJPUX5V.js");
31728
32100
  } finally {
31729
32101
  process.emitWarning = emitWarning;
31730
32102
  }
@@ -31758,6 +32130,35 @@ async function runProfileAction(context, command, json, action) {
31758
32130
  );
31759
32131
  }
31760
32132
  }
32133
+ async function runMemoryAction(context, command, json, action) {
32134
+ try {
32135
+ const result = await action(
32136
+ new ContentMemoryCli({
32137
+ currentDirectory: context.currentDirectory,
32138
+ homeDirectory: context.homeDirectory
32139
+ })
32140
+ );
32141
+ if (json) {
32142
+ writeJson(context, result);
32143
+ } else {
32144
+ context.writeStderr(`${command} ok
32145
+ `);
32146
+ }
32147
+ } catch (error) {
32148
+ const code = error instanceof ContentMemoryCliError ? error.code : "DXC_MEMORY_IO_FAILED";
32149
+ const message = error instanceof ContentMemoryCliError ? error.message : "Content memory command could not complete";
32150
+ writeActionError(
32151
+ context,
32152
+ json,
32153
+ contentMemoryErrorResultSchema.parse({
32154
+ command,
32155
+ error: { code, message },
32156
+ ok: false
32157
+ }),
32158
+ code
32159
+ );
32160
+ }
32161
+ }
31761
32162
  async function runProjectAction(context, command, json, action) {
31762
32163
  try {
31763
32164
  const result = await action(
@@ -31929,8 +32330,9 @@ function createProgram(context) {
31929
32330
  const wechat = program2.command("wechat").description("\u7ED1\u5B9A\u5E76\u67E5\u8BE2\u5FAE\u4FE1\u516C\u4F17\u53F7");
31930
32331
  const auth = program2.command("auth").description("\u767B\u5F55\u3001\u5173\u8054\u6216\u7BA1\u7406\u5F53\u524D\u8BBE\u5907\u8EAB\u4EFD");
31931
32332
  const profile = program2.command("profile").description("\u7BA1\u7406\u672C\u5730\u521B\u4F5C\u504F\u597D");
32333
+ const memory = program2.command("memory").description("\u7BA1\u7406\u672C\u5730\u5185\u5BB9\u8865\u5145\u8BB0\u5FC6");
31932
32334
  const project = program2.command("project").description("\u5B9A\u4F4D\u5185\u5BB9\u9879\u76EE\u5E76\u7BA1\u7406\u9636\u6BB5 contract");
31933
- const knowledge = program2.command("knowledge").description("\u7BA1\u7406\u672C\u5730\u5386\u53F2\u6587\u7AE0\u77E5\u8BC6\u5E93");
32335
+ const knowledge = program2.command("knowledge").description("\u7BA1\u7406\u672C\u5730\u5386\u53F2\u6587\u7AE0\u4E0E\u91D1\u53E5\u77E5\u8BC6\u5E93");
31934
32336
  const monitor = program2.command("monitor").description("\u7BA1\u7406\u672C\u673A\u516C\u5F00\u6765\u6E90\u76D1\u63A7\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u53D1\u5E03\u5185\u5BB9");
31935
32337
  const skills = program2.command("skills").description("\u5B89\u88C5 DxC \u5B98\u65B9 Skills");
31936
32338
  const source = program2.command("source").description("\u5728\u672C\u673A\u91C7\u96C6\u53EF\u8FFD\u6EAF\u7684\u516C\u5F00\u7814\u7A76\u4FE1\u53F7");
@@ -31947,7 +32349,7 @@ function createProgram(context) {
31947
32349
  );
31948
32350
  })
31949
32351
  );
31950
- skills.command("install").description("\u628A\u4E5D\u4E2A\u5B98\u65B9 Skill \u5B89\u88C5\u5230 WorkBuddy\u3001Codex \u6216\u6307\u5B9A\u76EE\u5F55").option("--target <target>", "workbuddy / codex", "workbuddy").option("--directory <path>", "\u663E\u5F0F\u6307\u5B9A\u5BBF\u4E3B Skills \u76EE\u5F55").option("--force", "\u66FF\u6362\u5DF2\u5B58\u5728\u7684\u540C\u540D\u5B98\u65B9 Skill").option("--json", "\u8F93\u51FA JSON").action(
32352
+ skills.command("install").description("\u628A\u5341\u4E09\u4E2A\u5B98\u65B9 Skill \u5B89\u88C5\u5230 WorkBuddy\u3001Codex \u6216\u6307\u5B9A\u76EE\u5F55").option("--target <target>", "workbuddy / codex", "workbuddy").option("--directory <path>", "\u663E\u5F0F\u6307\u5B9A\u5BBF\u4E3B Skills \u76EE\u5F55").option("--force", "\u66FF\u6362\u5DF2\u5B58\u5728\u7684\u540C\u540D\u5B98\u65B9 Skill").option("--json", "\u8F93\u51FA JSON").action(
31951
32353
  async (options) => {
31952
32354
  if (options.target !== "workbuddy" && options.target !== "codex") {
31953
32355
  throw new CommanderError(
@@ -32076,6 +32478,38 @@ function createProgram(context) {
32076
32478
  async (profileCli) => profileCli.save(options.input)
32077
32479
  )
32078
32480
  );
32481
+ profile.command("update").description("\u5C40\u90E8\u66F4\u65B0\u5DF2\u521D\u59CB\u5316\u7684\u672C\u5730\u521B\u4F5C\u504F\u597D").requiredOption("--input <path>", "\u5C40\u90E8\u66F4\u65B0 JSON \u6587\u4EF6").option("--json", "\u8F93\u51FA JSON").action(
32482
+ async (options) => runProfileAction(
32483
+ context,
32484
+ "profile.update",
32485
+ options.json === true,
32486
+ async (profileCli) => profileCli.update(options.input)
32487
+ )
32488
+ );
32489
+ memory.command("add").description("\u4FDD\u5B58\u4E00\u6761\u4ECE\u7528\u6237\u81EA\u7136\u8BED\u8A00\u63D0\u70BC\u7684\u672C\u5730\u5185\u5BB9\u8865\u5145\u8BB0\u5FC6").requiredOption("--input <path>", "\u8865\u5145\u8BB0\u5FC6 JSON \u6587\u4EF6").option("--json", "\u8F93\u51FA JSON").action(
32490
+ async (options) => runMemoryAction(
32491
+ context,
32492
+ "memory.add",
32493
+ options.json === true,
32494
+ async (memoryCli) => memoryCli.add(options.input)
32495
+ )
32496
+ );
32497
+ memory.command("list").description("\u5217\u51FA\u5F53\u524D\u4ECD\u6709\u6548\u7684\u672C\u5730\u5185\u5BB9\u8865\u5145\u8BB0\u5FC6").option("--json", "\u8F93\u51FA JSON").action(
32498
+ async (options) => runMemoryAction(
32499
+ context,
32500
+ "memory.list",
32501
+ options.json === true,
32502
+ async (memoryCli) => memoryCli.list()
32503
+ )
32504
+ );
32505
+ memory.command("archive").description("\u5F52\u6863\u4E00\u6761\u4E0D\u518D\u9002\u7528\u7684\u672C\u5730\u5185\u5BB9\u8865\u5145\u8BB0\u5FC6").argument("<memory-id>", "\u8BB0\u5FC6 ID").option("--json", "\u8F93\u51FA JSON").action(
32506
+ async (memoryId, options) => runMemoryAction(
32507
+ context,
32508
+ "memory.archive",
32509
+ options.json === true,
32510
+ async (memoryCli) => memoryCli.archive(memoryId)
32511
+ )
32512
+ );
32079
32513
  project.command("init").description("\u521D\u59CB\u5316\u4E00\u4E2A\u53EF\u6062\u590D\u7684\u5185\u5BB9\u9879\u76EE").requiredOption("--title <title>", "\u5185\u5BB9\u9879\u76EE\u6807\u9898").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55", ".").option("--knowledge <files...>", "\u521D\u59CB\u5316\u65F6\u663E\u5F0F\u5BFC\u5165\u5386\u53F2\u6587\u7AE0").option("--lexical-only", "\u5BFC\u5165\u5386\u53F2\u6587\u7AE0\u65F6\u53EA\u5EFA\u7ACB\u5173\u952E\u8BCD\u7D22\u5F15").option("--json", "\u8F93\u51FA JSON").action(
32080
32514
  async (options) => runProjectAction(context, "project.init", options.json === true, async (projectCli) => {
32081
32515
  await projectCli.assertCanInitialize(options.directory);
@@ -32177,7 +32611,7 @@ function createProgram(context) {
32177
32611
  async (knowledgeCli) => knowledgeCli.importDirectory(options.directory, options.lexicalOnly === true)
32178
32612
  )
32179
32613
  );
32180
- knowledge.command("search").description("\u7528\u5173\u952E\u8BCD\u548C\u672C\u5730\u8BED\u4E49\u5411\u91CF\u6DF7\u5408\u53EC\u56DE\u5386\u53F2\u7247\u6BB5").argument("<query>", "\u53EC\u56DE\u76EE\u6807").option("--mode <mode>", "hybrid / lexical / semantic", "hybrid").option("--limit <count>", "\u6700\u591A\u8FD4\u56DE\u7247\u6BB5\u6570", "8").option("--json", "\u8F93\u51FA JSON").action(
32614
+ knowledge.command("search").description("\u7528\u5173\u952E\u8BCD\u548C\u672C\u5730\u8BED\u4E49\u5411\u91CF\u6DF7\u5408\u53EC\u56DE\u5386\u53F2\u7247\u6BB5\u4E0E active \u91D1\u53E5").argument("<query>", "\u53EC\u56DE\u76EE\u6807").option("--mode <mode>", "hybrid / lexical / semantic", "hybrid").option("--limit <count>", "\u6700\u591A\u8FD4\u56DE\u7247\u6BB5\u6570", "8").option("--json", "\u8F93\u51FA JSON").action(
32181
32615
  async (query, options) => runKnowledgeAction(
32182
32616
  context,
32183
32617
  "knowledge.search",
@@ -32193,6 +32627,83 @@ function createProgram(context) {
32193
32627
  async (knowledgeCli) => knowledgeCli.remove(articleId)
32194
32628
  )
32195
32629
  );
32630
+ const quotes = knowledge.command("quotes").description("\u7BA1\u7406\u672C\u673A\u53EF\u7F16\u8F91\u7684\u91D1\u53E5\u6E90\u6587\u4EF6\u548C\u7D22\u5F15");
32631
+ quotes.command("init").description("\u521B\u5EFA\u7528\u6237\u53EF\u76F4\u63A5\u7F16\u8F91\u7684 ~/Documents/DxC/\u91D1\u53E5\u5E93.md \u6A21\u677F\uFF1B\u4E0D\u4F1A\u626B\u63CF\u5176\u4ED6\u76EE\u5F55").option("--json", "\u8F93\u51FA JSON").action(
32632
+ async (options) => runKnowledgeAction(
32633
+ context,
32634
+ "knowledge.quotes.init",
32635
+ options.json === true,
32636
+ async (knowledgeCli) => knowledgeCli.initQuotes()
32637
+ )
32638
+ );
32639
+ quotes.command("status").description("\u68C0\u67E5\u672C\u673A\u91D1\u53E5\u6E90\u6587\u4EF6\u4E0E\u5DF2\u540C\u6B65\u7D22\u5F15\u72B6\u6001").option("--json", "\u8F93\u51FA JSON").action(
32640
+ async (options) => runKnowledgeAction(
32641
+ context,
32642
+ "knowledge.quotes.status",
32643
+ options.json === true,
32644
+ async (knowledgeCli) => knowledgeCli.quoteStatus()
32645
+ )
32646
+ );
32647
+ quotes.command("list").description("\u5217\u51FA\u7528\u6237\u7EF4\u62A4\u7684\u91D1\u53E5\uFF1B\u4E0D\u8BFB\u53D6\u7D22\u5F15\u6216\u626B\u63CF\u76EE\u5F55").option("--json", "\u8F93\u51FA JSON").action(
32648
+ async (options) => runKnowledgeAction(
32649
+ context,
32650
+ "knowledge.quotes.list",
32651
+ options.json === true,
32652
+ async (knowledgeCli) => knowledgeCli.listQuotes()
32653
+ )
32654
+ );
32655
+ quotes.command("add").description("\u65B0\u589E\u4E00\u6761\u91D1\u53E5\u5230\u53EF\u7F16\u8F91 Markdown \u6E90\u6587\u4EF6\uFF1B\u968F\u540E\u7531 sync \u6216\u5DE5\u4F5C\u6D41\u5EFA\u7ACB\u7D22\u5F15").requiredOption("--text <text>", "\u91D1\u53E5\u6B63\u6587").option("--tag <tag>", "\u6807\u7B7E\uFF1B\u53EF\u91CD\u590D\u6307\u5B9A", collectValues, []).option("--source <source>", "\u6765\u6E90\u8BF4\u660E").option("--attribution <attribution>", "\u7B2C\u4E09\u65B9\u5F15\u8BED\u7F72\u540D").option("--origin <origin>", "original / third-party", "original").option(
32656
+ "--verbatim-use <value>",
32657
+ "original / needs-verification / permitted / do-not-use-verbatim"
32658
+ ).option("--json", "\u8F93\u51FA JSON").action(
32659
+ async (options) => runKnowledgeAction(
32660
+ context,
32661
+ "knowledge.quotes.add",
32662
+ options.json === true,
32663
+ async (knowledgeCli) => knowledgeCli.addQuote({
32664
+ ...options.attribution === void 0 ? {} : { attribution: options.attribution },
32665
+ origin: options.origin,
32666
+ ...options.source === void 0 ? {} : { source: options.source },
32667
+ tags: options.tag,
32668
+ text: options.text,
32669
+ ...options.verbatimUse === void 0 ? {} : { verbatimUse: options.verbatimUse }
32670
+ })
32671
+ )
32672
+ );
32673
+ quotes.command("update").description("\u4FEE\u6539\u4E00\u6761\u91D1\u53E5\uFF1B\u91D1\u53E5 ID \u4FDD\u6301\u7A33\u5B9A\uFF0C\u968F\u540E\u7531 sync \u6216\u5DE5\u4F5C\u6D41\u5EFA\u7ACB\u7D22\u5F15").argument("<quote-id>", "\u91D1\u53E5 ID").option("--text <text>", "\u66FF\u6362\u6B63\u6587").option("--tag <tag>", "\u66FF\u6362\u5168\u90E8\u6807\u7B7E\uFF1B\u53EF\u91CD\u590D\u6307\u5B9A", collectValues).option("--source <source>", "\u66FF\u6362\u6765\u6E90\u8BF4\u660E").option("--attribution <attribution>", "\u66FF\u6362\u7B2C\u4E09\u65B9\u5F15\u8BED\u7F72\u540D").option("--origin <origin>", "original / third-party").option(
32674
+ "--verbatim-use <value>",
32675
+ "original / needs-verification / permitted / do-not-use-verbatim"
32676
+ ).option("--json", "\u8F93\u51FA JSON").action(
32677
+ async (quoteId, options) => runKnowledgeAction(
32678
+ context,
32679
+ "knowledge.quotes.update",
32680
+ options.json === true,
32681
+ async (knowledgeCli) => knowledgeCli.updateQuote(quoteId, {
32682
+ ...options.attribution === void 0 ? {} : { attribution: options.attribution },
32683
+ ...options.origin === void 0 ? {} : { origin: options.origin },
32684
+ ...options.source === void 0 ? {} : { source: options.source },
32685
+ ...options.tag === void 0 ? {} : { tags: options.tag },
32686
+ ...options.text === void 0 ? {} : { text: options.text },
32687
+ ...options.verbatimUse === void 0 ? {} : { verbatimUse: options.verbatimUse }
32688
+ })
32689
+ )
32690
+ );
32691
+ quotes.command("archive").description("\u5F52\u6863\u4E00\u6761\u91D1\u53E5\uFF1B\u4E0D\u4F1A\u5220\u9664\u5DF2\u786E\u8BA4\u6587\u7AE0\u4E2D\u7684\u5FEB\u7167").argument("<quote-id>", "\u91D1\u53E5 ID").option("--json", "\u8F93\u51FA JSON").action(
32692
+ async (quoteId, options) => runKnowledgeAction(
32693
+ context,
32694
+ "knowledge.quotes.archive",
32695
+ options.json === true,
32696
+ async (knowledgeCli) => knowledgeCli.archiveQuote(quoteId)
32697
+ )
32698
+ );
32699
+ quotes.command("sync").description("\u6309\u5185\u5BB9\u54C8\u5E0C\u540C\u6B65\u5DF2\u521D\u59CB\u5316\u7684 Markdown \u91D1\u53E5\u5E93\u5230\u672C\u5730\u7D22\u5F15").option("--lexical-only", "\u53EA\u5EFA\u7ACB\u5173\u952E\u8BCD\u7D22\u5F15\uFF0C\u4E0D\u52A0\u8F7D\u672C\u5730\u8BED\u4E49\u6A21\u578B").option("--json", "\u8F93\u51FA JSON").action(
32700
+ async (options) => runKnowledgeAction(
32701
+ context,
32702
+ "knowledge.quotes.sync",
32703
+ options.json === true,
32704
+ async (knowledgeCli) => knowledgeCli.syncQuotes(options.lexicalOnly === true)
32705
+ )
32706
+ );
32196
32707
  auth.command("start").description("\u626B\u7801\u767B\u5F55\uFF1B\u9996\u6B21\u4F7F\u7528\u65F6\u660E\u786E\u521B\u5EFA\u65B0\u7684 DxC \u5185\u5BB9\u7A7A\u95F4").option("--no-open", "\u4E0D\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668").option("--server <url>", "DxC API \u5730\u5740\uFF1B\u9ED8\u8BA4\u5B98\u65B9 DxC Server").option("--timeout <seconds>", "\u7B49\u5F85\u626B\u7801\u7684\u79D2\u6570", "900").action(
32197
32708
  async (options) => runWechatAction(context, async (wechatCli) => {
32198
32709
  await wechatCli.start(
@@ -32258,7 +32769,7 @@ function createProgram(context) {
32258
32769
  })
32259
32770
  );
32260
32771
  const draft = wechat.command("draft").description("\u9884\u89C8\u5E76\u521B\u5EFA\u5FAE\u4FE1\u516C\u4F17\u53F7\u8349\u7A3F");
32261
- draft.command("preview").description("\u91C7\u96C6\u5DF2\u751F\u6210\u6216\u9009\u62E9\u7684\u56FE\u7247\uFF0C\u5E76\u751F\u6210\u4E0D\u53EF\u53D8\u4E91\u7AEF\u9884\u89C8").requiredOption("--article <path>", "Markdown \u6587\u7AE0\u6587\u4EF6").option("--cover <path-or-auto>", "PNG/JPEG \u5185\u5BB9\u5C01\u9762\uFF1Bauto \u4ECE\u6587\u7AE0\u6216\u7D20\u6750\u76EE\u5F55\u89E3\u6790", "auto").option("--assets-directory <path>", "\u91C7\u96C6\u5E76\u5185\u8054\u8BE5\u76EE\u5F55\u4E2D\u5DF2\u51C6\u5907\u597D\u7684 PNG/JPEG").requiredOption("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--title <title>", "\u4F7F\u7528\u5DF2\u786E\u8BA4\u6807\u9898\u8986\u76D6\u6587\u7AE0 frontmatter \u6807\u9898").action(
32772
+ draft.command("preview").description("\u91C7\u96C6\u5DF2\u751F\u6210\u6216\u9009\u62E9\u7684\u56FE\u7247\uFF0C\u5E76\u751F\u6210\u4E0D\u53EF\u53D8\u4E91\u7AEF\u9884\u89C8").requiredOption("--article <path>", "Markdown \u6587\u7AE0\u6587\u4EF6").option("--cover <path-or-auto>", "PNG/JPEG \u5185\u5BB9\u5C01\u9762\uFF1Bauto \u4ECE\u6587\u7AE0\u6216\u7D20\u6750\u76EE\u5F55\u89E3\u6790", "auto").option("--assets-directory <path>", "\u91C7\u96C6\u5E76\u5185\u8054\u8BE5\u76EE\u5F55\u4E2D\u5DF2\u51C6\u5907\u597D\u7684 PNG/JPEG").option("--visual-plan <path>", "\u6309\u89C6\u89C9\u8BA1\u5212\u7684\u7CBE\u786E\u7AE0\u8282\u951A\u70B9\u63D2\u5165\u5DF2\u58F0\u660E\u7684\u6B63\u6587\u56FE\u7247").requiredOption("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--title <title>", "\u4F7F\u7528\u5DF2\u786E\u8BA4\u6807\u9898\u8986\u76D6\u6587\u7AE0 frontmatter \u6807\u9898").action(
32262
32773
  async (options) => runWechatAction(context, async (wechatCli) => {
32263
32774
  await wechatCli.previewDraft(
32264
32775
  {
@@ -32277,7 +32788,8 @@ function createProgram(context) {
32277
32788
  ...options.cover === void 0 ? {} : {
32278
32789
  coverFile: options.cover === "auto" ? "auto" : path8.resolve(context.currentDirectory, options.cover)
32279
32790
  },
32280
- ...options.title === void 0 ? {} : { title: options.title }
32791
+ ...options.title === void 0 ? {} : { title: options.title },
32792
+ ...options.visualPlan === void 0 ? {} : { visualPlanFile: path8.resolve(context.currentDirectory, options.visualPlan) }
32281
32793
  },
32282
32794
  context
32283
32795
  );