@deployxai/dxc 0.2.0 → 0.2.2
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/README.md +4 -2
- package/dist/index.js +244 -45
- package/package.json +1 -1
- package/skills/dxc-article-outline/SKILL.md +28 -0
- package/skills/dxc-article-outline/agents/openai.yaml +6 -0
- package/skills/dxc-article-outline/references/outline-methods.md +57 -0
- package/skills/dxc-article-write/SKILL.md +39 -0
- package/skills/dxc-article-write/agents/openai.yaml +6 -0
- package/skills/dxc-article-write/references/writing-methods.md +62 -0
- package/skills/dxc-content-brief/SKILL.md +33 -0
- package/skills/dxc-content-brief/agents/openai.yaml +6 -0
- package/skills/dxc-content-brief/references/brief-method.md +52 -0
- package/skills/dxc-content-review/SKILL.md +35 -0
- package/skills/dxc-content-review/agents/openai.yaml +6 -0
- package/skills/dxc-content-review/references/review-checklist.md +51 -0
- package/skills/dxc-content-workflow/SKILL.md +40 -11
- package/skills/dxc-content-workflow/agents/openai.yaml +2 -2
- package/skills/dxc-content-workflow/references/stages.md +6 -4
- package/skills/dxc-knowledge/SKILL.md +1 -1
- package/skills/dxc-memory/SKILL.md +1 -1
- package/skills/dxc-profile/SKILL.md +1 -1
- package/skills/dxc-project-overview/SKILL.md +26 -0
- package/skills/dxc-project-overview/agents/openai.yaml +6 -0
- package/skills/dxc-quote-curator/SKILL.md +1 -1
- package/skills/dxc-research/SKILL.md +39 -0
- package/skills/dxc-research/agents/openai.yaml +6 -0
- package/skills/dxc-research/references/research-method.md +77 -0
- package/skills/dxc-title-write/SKILL.md +34 -0
- package/skills/dxc-title-write/agents/openai.yaml +6 -0
- package/skills/dxc-title-write/references/title-methods.md +41 -0
- package/skills/dxc-visual-plan/SKILL.md +43 -0
- package/skills/dxc-visual-plan/agents/openai.yaml +6 -0
- package/skills/dxc-visual-plan/references/visual-methods.md +53 -0
- package/skills/dxc-wechat-publisher/SKILL.md +39 -0
- package/skills/dxc-wechat-publisher/agents/openai.yaml +6 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DeployX 内容工作台(DxC)
|
|
2
2
|
|
|
3
|
-
这是 DxC 的官方 CLI
|
|
3
|
+
这是 DxC 的官方 CLI 与 14 个领域 Skill。
|
|
4
4
|
|
|
5
5
|
安装、权限范围、Windows/WorkBuddy 使用方式与源码核验,请阅读:
|
|
6
6
|
https://deployxai.com/dxc/
|
|
@@ -8,7 +8,9 @@ https://deployxai.com/dxc/
|
|
|
8
8
|
## 包含内容
|
|
9
9
|
|
|
10
10
|
- `dxc` CLI:本地文章工作流、画像、内容记忆、历史知识库、金句库和微信草稿交付;
|
|
11
|
-
- `dxc-content-workflow
|
|
11
|
+
- `dxc-content-workflow`:八步文章生产总控;
|
|
12
|
+
- 八个阶段 Skill:可独立从研究、Brief、大纲、正文、标题、视觉、审校或微信交付进入;
|
|
13
|
+
- `dxc-project-overview`:本机已登记项目总览;
|
|
12
14
|
- `dxc-profile`、`dxc-memory`、`dxc-knowledge`、`dxc-quote-curator`:四个长期资产入口。
|
|
13
15
|
|
|
14
16
|
安装本包不会自动登录微信、绑定公众号、读取历史文章、上传内容或创建草稿。每项敏感操作
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
createWechatLoginSessionResponseSchema,
|
|
33
33
|
deviceSessionStatusResponseSchema,
|
|
34
34
|
doctorResultSchema,
|
|
35
|
+
ensurePrivateDirectory,
|
|
35
36
|
portableRelativePathSchema,
|
|
36
37
|
preflightResultSchema,
|
|
37
38
|
proveDeviceBindingSessionResponseSchema,
|
|
@@ -23265,7 +23266,7 @@ import os3 from "node:os";
|
|
|
23265
23266
|
// apps/cli/package.json
|
|
23266
23267
|
var package_default = {
|
|
23267
23268
|
name: "@dxc/cli",
|
|
23268
|
-
version: "0.2.
|
|
23269
|
+
version: "0.2.2",
|
|
23269
23270
|
private: true,
|
|
23270
23271
|
type: "module",
|
|
23271
23272
|
bin: {
|
|
@@ -27177,6 +27178,7 @@ var MANIFEST_NAME = "dxc.project.json";
|
|
|
27177
27178
|
var MANIFEST_MAXIMUM_BYTES = 32 * 1024;
|
|
27178
27179
|
var PROJECT_INDEX_MAXIMUM_BYTES = 512 * 1024;
|
|
27179
27180
|
var PROJECT_INDEX_RELATIVE_PATH = ".dxc/content-projects.json";
|
|
27181
|
+
var DEFAULT_PROJECTS_RELATIVE_PATH = ".dxc/projects";
|
|
27180
27182
|
var DEFAULT_ARTIFACT_PATHS = {
|
|
27181
27183
|
article: "artifacts/04-article.md",
|
|
27182
27184
|
brief: "artifacts/02-brief.md",
|
|
@@ -27268,7 +27270,8 @@ var ProjectCli = class {
|
|
|
27268
27270
|
await writePrivateJson(indexPath(this.#homeDirectory), { projects, schemaVersion: "1" });
|
|
27269
27271
|
}
|
|
27270
27272
|
async initialize(directoryInput, title) {
|
|
27271
|
-
const
|
|
27273
|
+
const projectId = this.#randomUUID();
|
|
27274
|
+
const directory = directoryInput === void 0 ? path3.join(this.#homeDirectory, DEFAULT_PROJECTS_RELATIVE_PATH, projectId) : resolveUserPath({
|
|
27272
27275
|
currentDirectory: this.#currentDirectory,
|
|
27273
27276
|
homeDirectory: this.#homeDirectory,
|
|
27274
27277
|
input: directoryInput
|
|
@@ -27289,7 +27292,7 @@ var ProjectCli = class {
|
|
|
27289
27292
|
artifacts: DEFAULT_ARTIFACT_PATHS,
|
|
27290
27293
|
assetsDirectory: "assets",
|
|
27291
27294
|
createdAt: this.#now().toISOString(),
|
|
27292
|
-
projectId
|
|
27295
|
+
projectId,
|
|
27293
27296
|
schemaVersion: "1",
|
|
27294
27297
|
title,
|
|
27295
27298
|
workflowId: CONTENT_WORKFLOW_ID
|
|
@@ -27298,8 +27301,14 @@ var ProjectCli = class {
|
|
|
27298
27301
|
throw new ProjectCliError("DXC_PROJECT_INVALID", "\u9879\u76EE\u6807\u9898\u6216\u76EE\u5F55\u4E0D\u5408\u6CD5\u3002");
|
|
27299
27302
|
}
|
|
27300
27303
|
try {
|
|
27301
|
-
|
|
27302
|
-
|
|
27304
|
+
if (directoryInput === void 0) {
|
|
27305
|
+
await ensurePrivateDirectory(directory);
|
|
27306
|
+
await ensurePrivateDirectory(path3.join(directory, "artifacts"));
|
|
27307
|
+
await ensurePrivateDirectory(path3.join(directory, parsed.data.assetsDirectory));
|
|
27308
|
+
} else {
|
|
27309
|
+
await mkdir(path3.join(directory, "artifacts"), { recursive: true });
|
|
27310
|
+
await mkdir(path3.join(directory, parsed.data.assetsDirectory), { recursive: true });
|
|
27311
|
+
}
|
|
27303
27312
|
await writePrivateJson(manifestTarget, parsed.data);
|
|
27304
27313
|
await this.#remember(directory, parsed.data);
|
|
27305
27314
|
} catch (error) {
|
|
@@ -27308,7 +27317,22 @@ var ProjectCli = class {
|
|
|
27308
27317
|
}
|
|
27309
27318
|
throw new ProjectCliError("DXC_PROJECT_IO_FAILED", "\u65E0\u6CD5\u521B\u5EFA\u5185\u5BB9\u9879\u76EE\u3002");
|
|
27310
27319
|
}
|
|
27311
|
-
return { data: { manifest: parsed.data } };
|
|
27320
|
+
return { data: { directory, manifest: parsed.data } };
|
|
27321
|
+
}
|
|
27322
|
+
async locateByProjectId(projectIdInput) {
|
|
27323
|
+
const projectId = projectIdInput.trim().toLocaleLowerCase("en-US");
|
|
27324
|
+
const index = await readIndex(this.#homeDirectory);
|
|
27325
|
+
const entry = index.projects.find(
|
|
27326
|
+
(candidate) => candidate.projectId.toLocaleLowerCase("en-US") === projectId
|
|
27327
|
+
);
|
|
27328
|
+
if (entry === void 0) {
|
|
27329
|
+
throw new ProjectCliError("DXC_PROJECT_NOT_FOUND", "\u6CA1\u6709\u627E\u5230\u6307\u5B9A\u7684\u5185\u5BB9\u9879\u76EE\u3002");
|
|
27330
|
+
}
|
|
27331
|
+
const manifest = await readManifest(entry.directory);
|
|
27332
|
+
if (manifest.projectId !== entry.projectId) {
|
|
27333
|
+
throw new ProjectCliError("DXC_PROJECT_INVALID", "\u672C\u5730\u9879\u76EE\u767B\u8BB0\u4E0E\u9879\u76EE\u6587\u4EF6\u4E0D\u4E00\u81F4\u3002");
|
|
27334
|
+
}
|
|
27335
|
+
return { directory: entry.directory, manifest };
|
|
27312
27336
|
}
|
|
27313
27337
|
async locate(directoryInput) {
|
|
27314
27338
|
if (directoryInput !== void 0) {
|
|
@@ -27368,6 +27392,25 @@ var ProjectCli = class {
|
|
|
27368
27392
|
}
|
|
27369
27393
|
return locations;
|
|
27370
27394
|
}
|
|
27395
|
+
async list() {
|
|
27396
|
+
const index = await readIndex(this.#homeDirectory);
|
|
27397
|
+
const projects = [];
|
|
27398
|
+
for (const entry of index.projects) {
|
|
27399
|
+
try {
|
|
27400
|
+
const manifest = await readManifest(entry.directory);
|
|
27401
|
+
projects.push({
|
|
27402
|
+
entry,
|
|
27403
|
+
...manifest.projectId === entry.projectId ? { location: { directory: entry.directory, manifest } } : {}
|
|
27404
|
+
});
|
|
27405
|
+
} catch (error) {
|
|
27406
|
+
if (!(error instanceof ProjectCliError)) {
|
|
27407
|
+
throw error;
|
|
27408
|
+
}
|
|
27409
|
+
projects.push({ entry });
|
|
27410
|
+
}
|
|
27411
|
+
}
|
|
27412
|
+
return projects;
|
|
27413
|
+
}
|
|
27371
27414
|
};
|
|
27372
27415
|
|
|
27373
27416
|
// apps/cli/src/skills.ts
|
|
@@ -27377,6 +27420,15 @@ import path4 from "node:path";
|
|
|
27377
27420
|
import { fileURLToPath } from "node:url";
|
|
27378
27421
|
var OFFICIAL_SKILLS = [
|
|
27379
27422
|
"dxc-content-workflow",
|
|
27423
|
+
"dxc-research",
|
|
27424
|
+
"dxc-content-brief",
|
|
27425
|
+
"dxc-article-outline",
|
|
27426
|
+
"dxc-article-write",
|
|
27427
|
+
"dxc-title-write",
|
|
27428
|
+
"dxc-visual-plan",
|
|
27429
|
+
"dxc-content-review",
|
|
27430
|
+
"dxc-wechat-publisher",
|
|
27431
|
+
"dxc-project-overview",
|
|
27380
27432
|
"dxc-profile",
|
|
27381
27433
|
"dxc-memory",
|
|
27382
27434
|
"dxc-knowledge",
|
|
@@ -30123,13 +30175,22 @@ async function plannedVisualAssets(visualPlanFile, assetsDirectoryInput) {
|
|
|
30123
30175
|
[assetsDirectory],
|
|
30124
30176
|
"inline-image"
|
|
30125
30177
|
);
|
|
30178
|
+
const sourceLogicalPath = asset["sourcePath"];
|
|
30179
|
+
if (sourceLogicalPath !== void 0 && (typeof sourceLogicalPath !== "string" || !isSafeLogicalAssetPath(sourceLogicalPath))) {
|
|
30180
|
+
throw new WechatCliError(
|
|
30181
|
+
"DXC_PUBLISHING_VISUAL_PLAN_INVALID",
|
|
30182
|
+
"\u6B63\u6587\u914D\u56FE\u7684\u539F\u59CB\u8DEF\u5F84\u5FC5\u987B\u662F\u9879\u76EE\u5185\u5B89\u5168\u76F8\u5BF9\u8DEF\u5F84\u3002"
|
|
30183
|
+
);
|
|
30184
|
+
}
|
|
30126
30185
|
const digest = createHash4("sha256").update(absolutePath).digest("hex").slice(0, 12);
|
|
30127
30186
|
const fileName = safeFileName(path5.basename(absolutePath)) || `visual-${digest}.png`;
|
|
30128
30187
|
return {
|
|
30129
30188
|
absolutePath,
|
|
30130
30189
|
alt: typeof asset["purpose"] === "string" ? asset["purpose"] : path5.basename(absolutePath, path5.extname(absolutePath)),
|
|
30131
30190
|
logicalPath: `assets/dxc-visuals/${digest}-${fileName}`,
|
|
30132
|
-
placementAnchor: asset["placementAnchor"]
|
|
30191
|
+
placementAnchor: asset["placementAnchor"],
|
|
30192
|
+
plannedPath: asset["path"],
|
|
30193
|
+
...sourceLogicalPath === void 0 ? {} : { sourceLogicalPath }
|
|
30133
30194
|
};
|
|
30134
30195
|
})
|
|
30135
30196
|
)
|
|
@@ -30175,30 +30236,45 @@ async function preparePublishingDraft(input) {
|
|
|
30175
30236
|
const availableByFileName = new Map(
|
|
30176
30237
|
availableImages.map((candidate) => [path5.basename(candidate), candidate])
|
|
30177
30238
|
);
|
|
30178
|
-
const
|
|
30239
|
+
const projectDirectory = input.assetsDirectory === void 0 ? articleDirectory : commonDirectory(articleDirectory, path5.resolve(input.assetsDirectory));
|
|
30240
|
+
const resolveDeclaredAsset = (logicalPath) => availableByFileName.get(path5.posix.basename(logicalPath)) ?? path5.resolve(projectDirectory, logicalPath);
|
|
30179
30241
|
const referenced = new Set(logicalInlinePaths(originalBundle));
|
|
30180
30242
|
const automaticAssetDirectories = [
|
|
30181
30243
|
articleDirectory,
|
|
30182
30244
|
...input.assetsDirectory === void 0 ? [] : [path5.resolve(input.assetsDirectory)]
|
|
30183
30245
|
];
|
|
30184
|
-
const referencedFilesByLogicalPath = new Map(
|
|
30185
|
-
[...referenced].map((logicalPath) => [logicalPath, resolveDeclaredAsset(logicalPath)])
|
|
30186
|
-
);
|
|
30187
|
-
const referencedFiles = new Set(referencedFilesByLogicalPath.values());
|
|
30188
30246
|
const articleCoverCandidate = originalBundle.coverImage !== void 0 && isSafeLogicalAssetPath(originalBundle.coverImage) ? resolveDeclaredAsset(originalBundle.coverImage) : void 0;
|
|
30189
30247
|
const namedCoverCandidate = availableImages.find(
|
|
30190
30248
|
(candidate) => /^cover(?:[._-]|$)/iu.test(path5.basename(candidate))
|
|
30191
30249
|
);
|
|
30192
30250
|
const explicitCover = input.coverFile !== void 0 && input.coverFile !== "auto" ? input.coverFile : void 0;
|
|
30193
30251
|
const planned = input.visualPlanFile === void 0 ? void 0 : await plannedVisualAssets(input.visualPlanFile, input.assetsDirectory);
|
|
30252
|
+
const plannedInline = planned?.inline ?? [];
|
|
30253
|
+
const plannedReferenceFiles = /* @__PURE__ */ new Map();
|
|
30254
|
+
const plannedInlineForInjection = plannedInline.filter((asset) => {
|
|
30255
|
+
const referencedLogicalPath = [asset.sourceLogicalPath, asset.plannedPath].find(
|
|
30256
|
+
(candidate) => candidate !== void 0 && referenced.has(candidate)
|
|
30257
|
+
);
|
|
30258
|
+
if (referencedLogicalPath === void 0) {
|
|
30259
|
+
return true;
|
|
30260
|
+
}
|
|
30261
|
+
plannedReferenceFiles.set(referencedLogicalPath, asset.absolutePath);
|
|
30262
|
+
return false;
|
|
30263
|
+
});
|
|
30264
|
+
const referencedFilesByLogicalPath = new Map(
|
|
30265
|
+
[...referenced].map((logicalPath) => [
|
|
30266
|
+
logicalPath,
|
|
30267
|
+
plannedReferenceFiles.get(logicalPath) ?? resolveDeclaredAsset(logicalPath)
|
|
30268
|
+
])
|
|
30269
|
+
);
|
|
30270
|
+
const referencedFiles = new Set(referencedFilesByLogicalPath.values());
|
|
30194
30271
|
const coverCandidate = explicitCover ?? planned?.coverAbsolutePath ?? articleCoverCandidate ?? namedCoverCandidate;
|
|
30195
30272
|
const coverMode = explicitCover !== void 0 ? "explicit-file" : planned?.coverAbsolutePath !== void 0 ? "visual-plan" : articleCoverCandidate !== void 0 ? "article-frontmatter" : namedCoverCandidate !== void 0 ? "assets-directory" : void 0;
|
|
30196
|
-
const plannedInline = planned?.inline ?? [];
|
|
30197
30273
|
const pickupCandidates = availableImages.filter(
|
|
30198
30274
|
(candidate) => candidate !== namedCoverCandidate && candidate !== articleCoverCandidate && !referencedFiles.has(path5.resolve(candidate)) && input.visualPlanFile === void 0
|
|
30199
30275
|
);
|
|
30200
30276
|
const injected = [
|
|
30201
|
-
...
|
|
30277
|
+
...plannedInlineForInjection,
|
|
30202
30278
|
...pickupCandidates.slice(0, Math.max(0, MAXIMUM_INLINE_IMAGES - referenced.size)).map((candidate) => {
|
|
30203
30279
|
const digest = createHash4("sha256").update(candidate).digest("hex").slice(0, 12);
|
|
30204
30280
|
const fileName = safeFileName(path5.basename(candidate)) || `visual-${digest}.png`;
|
|
@@ -30607,6 +30683,9 @@ async function optimizePublishingImages(input) {
|
|
|
30607
30683
|
frontmatter2["coverAsset"] = finalPath;
|
|
30608
30684
|
frontmatter2["coverSha256"] = sha256(finalBytes);
|
|
30609
30685
|
} else if (entry.record !== void 0) {
|
|
30686
|
+
if (finalPath !== assetPath && entry.record["sourcePath"] === void 0) {
|
|
30687
|
+
entry.record["sourcePath"] = assetPath;
|
|
30688
|
+
}
|
|
30610
30689
|
entry.record["path"] = finalPath;
|
|
30611
30690
|
entry.record["sha256"] = sha256(finalBytes);
|
|
30612
30691
|
}
|
|
@@ -31374,7 +31453,7 @@ var WechatCli = class {
|
|
|
31374
31453
|
`);
|
|
31375
31454
|
output.writeStderr(
|
|
31376
31455
|
result.data.mutations.length === 0 ? `\u56FE\u7247\u5747\u5DF2\u7B26\u5408\u5FAE\u4FE1\u4EA4\u4ED8\u4F53\u79EF\u8981\u6C42\uFF1B\u5DF2\u590D\u7B97 ${result.data.unchangedCount} \u5F20\u56FE\u7247\u54C8\u5E0C\u3002
|
|
31377
|
-
` : `\u5DF2\u751F\u6210 ${result.data.mutations.length} \u5F20\u4F18\u5316\u6D3E\u751F\u56FE\u5E76\u66F4\u65B0\u89C6\u89C9\u8BA1\u5212\uFF1B\
|
|
31456
|
+
` : `\u5DF2\u751F\u6210 ${result.data.mutations.length} \u5F20\u4F18\u5316\u6D3E\u751F\u56FE\u5E76\u66F4\u65B0\u89C6\u89C9\u8BA1\u5212\uFF1B\u672C\u6B21\u9884\u89C8\u5C06\u76F4\u63A5\u4F7F\u7528\u6D3E\u751F\u56FE\uFF0C\u539F\u56FE\u672A\u88AB\u8986\u76D6\u3002
|
|
31378
31457
|
`
|
|
31379
31458
|
);
|
|
31380
31459
|
return result;
|
|
@@ -32177,16 +32256,32 @@ function nextStep(lastCompletedStep) {
|
|
|
32177
32256
|
const nextIndex = lastCompletedStep === null ? 0 : CONTENT_ARTIFACT_KINDS.indexOf(lastCompletedStep) + 1;
|
|
32178
32257
|
return CONTENT_ARTIFACT_KINDS[nextIndex] ?? null;
|
|
32179
32258
|
}
|
|
32180
|
-
function
|
|
32259
|
+
function previousStep(step) {
|
|
32260
|
+
const index = CONTENT_ARTIFACT_KINDS.indexOf(step);
|
|
32261
|
+
return index <= 0 ? null : CONTENT_ARTIFACT_KINDS[index - 1] ?? null;
|
|
32262
|
+
}
|
|
32263
|
+
function requestedStep(value) {
|
|
32264
|
+
const step = value;
|
|
32265
|
+
if (!CONTENT_ARTIFACT_KINDS.includes(step)) {
|
|
32266
|
+
throw new WorkflowCliError(
|
|
32267
|
+
"DXC_WORKFLOW_STEP_INVALID",
|
|
32268
|
+
`\u672A\u77E5\u9636\u6BB5 ${step}\u3002\u8BF7\u4F7F\u7528 ${CONTENT_ARTIFACT_KINDS.join("\u3001")}\u3002`
|
|
32269
|
+
);
|
|
32270
|
+
}
|
|
32271
|
+
return step;
|
|
32272
|
+
}
|
|
32273
|
+
function inputPaths(directory, manifest, step) {
|
|
32181
32274
|
const inputs = CONTENT_STAGE_INPUTS[step];
|
|
32182
|
-
return [...inputs.required, ...inputs.optional].map(
|
|
32275
|
+
return [...inputs.required, ...inputs.optional].map(
|
|
32276
|
+
(kind) => path8.join(directory, manifest.artifacts[kind])
|
|
32277
|
+
);
|
|
32183
32278
|
}
|
|
32184
32279
|
function workItem(location, state) {
|
|
32185
32280
|
const step = nextStep(state.lastCompletedStep);
|
|
32186
32281
|
return {
|
|
32187
32282
|
done: step === null,
|
|
32188
|
-
inputs: step === null ? [] : inputPaths(location.manifest, step),
|
|
32189
|
-
output: step === null ? null : location.manifest.artifacts[step],
|
|
32283
|
+
inputs: step === null ? [] : inputPaths(location.directory, location.manifest, step),
|
|
32284
|
+
output: step === null ? null : path8.join(location.directory, location.manifest.artifacts[step]),
|
|
32190
32285
|
project: projectSummary(location),
|
|
32191
32286
|
step
|
|
32192
32287
|
};
|
|
@@ -32286,7 +32381,16 @@ var WorkflowCli = class {
|
|
|
32286
32381
|
now: this.#now
|
|
32287
32382
|
});
|
|
32288
32383
|
}
|
|
32289
|
-
async #
|
|
32384
|
+
async #locate(directory, projectId) {
|
|
32385
|
+
if (directory !== void 0 && projectId !== void 0) {
|
|
32386
|
+
throw new WorkflowCliError(
|
|
32387
|
+
"DXC_WORKFLOW_PROJECT_REFERENCE_INVALID",
|
|
32388
|
+
"\u9879\u76EE\u76EE\u5F55\u548C\u9879\u76EE ID \u53EA\u80FD\u6307\u5B9A\u4E00\u4E2A\u3002"
|
|
32389
|
+
);
|
|
32390
|
+
}
|
|
32391
|
+
return projectId === void 0 ? this.#projects.locate(directory) : this.#projects.locateByProjectId(projectId);
|
|
32392
|
+
}
|
|
32393
|
+
async #loadState(location, persistMigration = true, migrationUpdatedAt = this.#now().toISOString()) {
|
|
32290
32394
|
try {
|
|
32291
32395
|
const raw = await readPrivateFile(
|
|
32292
32396
|
statePath(location.directory),
|
|
@@ -32332,36 +32436,113 @@ var WorkflowCli = class {
|
|
|
32332
32436
|
const migrated = {
|
|
32333
32437
|
lastCompletedStep,
|
|
32334
32438
|
projectId: location.manifest.projectId,
|
|
32335
|
-
updatedAt:
|
|
32439
|
+
updatedAt: migrationUpdatedAt,
|
|
32336
32440
|
version: 1
|
|
32337
32441
|
};
|
|
32338
|
-
|
|
32442
|
+
if (persistMigration) {
|
|
32443
|
+
await writePrivateJson(statePath(location.directory), migrated);
|
|
32444
|
+
}
|
|
32339
32445
|
return migrated;
|
|
32340
32446
|
}
|
|
32341
32447
|
async start(options) {
|
|
32342
|
-
|
|
32448
|
+
if (options.directory !== void 0 && options.projectId !== void 0) {
|
|
32449
|
+
throw new WorkflowCliError(
|
|
32450
|
+
"DXC_WORKFLOW_PROJECT_REFERENCE_INVALID",
|
|
32451
|
+
"\u9879\u76EE\u76EE\u5F55\u548C\u9879\u76EE ID \u53EA\u80FD\u6307\u5B9A\u4E00\u4E2A\u3002"
|
|
32452
|
+
);
|
|
32453
|
+
}
|
|
32454
|
+
const directory = options.directory === void 0 ? void 0 : resolveUserPath({
|
|
32343
32455
|
currentDirectory: this.#currentDirectory,
|
|
32344
32456
|
homeDirectory: this.#homeDirectory,
|
|
32345
32457
|
input: options.directory
|
|
32346
32458
|
});
|
|
32347
|
-
const
|
|
32348
|
-
|
|
32349
|
-
|
|
32350
|
-
|
|
32351
|
-
}
|
|
32459
|
+
const requested = options.from === void 0 ? void 0 : requestedStep(options.from);
|
|
32460
|
+
let location;
|
|
32461
|
+
if (options.projectId !== void 0) {
|
|
32462
|
+
location = await this.#projects.locateByProjectId(options.projectId);
|
|
32463
|
+
} else if (directory !== void 0) {
|
|
32464
|
+
try {
|
|
32465
|
+
location = await this.#projects.locate(directory);
|
|
32466
|
+
} catch (error) {
|
|
32467
|
+
if (!(error instanceof ProjectCliError) || error.code !== "DXC_PROJECT_NOT_FOUND") {
|
|
32468
|
+
throw error;
|
|
32469
|
+
}
|
|
32470
|
+
if (options.title === void 0 || options.title.trim().length === 0) {
|
|
32471
|
+
throw new WorkflowCliError(
|
|
32472
|
+
"DXC_WORKFLOW_TITLE_REQUIRED",
|
|
32473
|
+
"\u521B\u5EFA\u65B0\u9879\u76EE\u65F6\u9700\u8981\u63D0\u4F9B\u6587\u7AE0\u4E3B\u9898\u3002"
|
|
32474
|
+
);
|
|
32475
|
+
}
|
|
32476
|
+
const initialized = await this.#projects.initialize(directory, options.title);
|
|
32477
|
+
location = { directory: initialized.data.directory, manifest: initialized.data.manifest };
|
|
32478
|
+
}
|
|
32479
|
+
} else {
|
|
32480
|
+
if (options.title === void 0 || options.title.trim().length === 0) {
|
|
32481
|
+
throw new WorkflowCliError("DXC_WORKFLOW_TITLE_REQUIRED", "\u521B\u5EFA\u65B0\u9879\u76EE\u65F6\u9700\u8981\u63D0\u4F9B\u6587\u7AE0\u4E3B\u9898\u3002");
|
|
32482
|
+
}
|
|
32483
|
+
const initialized = await this.#projects.initialize(void 0, options.title);
|
|
32484
|
+
location = { directory: initialized.data.directory, manifest: initialized.data.manifest };
|
|
32485
|
+
}
|
|
32486
|
+
if (requested === void 0 && options.projectId !== void 0) {
|
|
32487
|
+
const state2 = await this.#loadState(location);
|
|
32488
|
+
return {
|
|
32489
|
+
command: "workflow.next",
|
|
32490
|
+
data: { match: "ready", work: workItem(location, state2) },
|
|
32491
|
+
ok: true
|
|
32492
|
+
};
|
|
32493
|
+
}
|
|
32494
|
+
if (requested === void 0 && directory !== void 0) {
|
|
32495
|
+
const state2 = await this.#loadState(location);
|
|
32496
|
+
if (state2.lastCompletedStep !== null) {
|
|
32497
|
+
return {
|
|
32498
|
+
command: "workflow.next",
|
|
32499
|
+
data: { match: "ready", work: workItem(location, state2) },
|
|
32500
|
+
ok: true
|
|
32501
|
+
};
|
|
32502
|
+
}
|
|
32503
|
+
}
|
|
32504
|
+
const step = requested ?? "research";
|
|
32352
32505
|
const state = {
|
|
32353
|
-
lastCompletedStep:
|
|
32506
|
+
lastCompletedStep: previousStep(step),
|
|
32354
32507
|
projectId: location.manifest.projectId,
|
|
32355
32508
|
updatedAt: this.#now().toISOString(),
|
|
32356
32509
|
version: 1
|
|
32357
32510
|
};
|
|
32358
|
-
await writePrivateJson(statePath(directory), state);
|
|
32511
|
+
await writePrivateJson(statePath(location.directory), state);
|
|
32359
32512
|
return {
|
|
32360
32513
|
command: "workflow.next",
|
|
32361
32514
|
data: { match: "ready", work: workItem(location, state) },
|
|
32362
32515
|
ok: true
|
|
32363
32516
|
};
|
|
32364
32517
|
}
|
|
32518
|
+
async listProjects() {
|
|
32519
|
+
const projects = [];
|
|
32520
|
+
for (const indexed of await this.#projects.list()) {
|
|
32521
|
+
if (indexed.location === void 0) {
|
|
32522
|
+
projects.push({
|
|
32523
|
+
available: false,
|
|
32524
|
+
directory: indexed.entry.directory,
|
|
32525
|
+
done: false,
|
|
32526
|
+
projectId: indexed.entry.projectId,
|
|
32527
|
+
step: null,
|
|
32528
|
+
title: indexed.entry.title,
|
|
32529
|
+
updatedAt: indexed.entry.updatedAt
|
|
32530
|
+
});
|
|
32531
|
+
continue;
|
|
32532
|
+
}
|
|
32533
|
+
const state = await this.#loadState(indexed.location, false, indexed.entry.updatedAt);
|
|
32534
|
+
const step = nextStep(state.lastCompletedStep);
|
|
32535
|
+
projects.push({
|
|
32536
|
+
...projectSummary(indexed.location),
|
|
32537
|
+
available: true,
|
|
32538
|
+
done: step === null,
|
|
32539
|
+
step,
|
|
32540
|
+
updatedAt: state.updatedAt
|
|
32541
|
+
});
|
|
32542
|
+
}
|
|
32543
|
+
projects.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
32544
|
+
return { command: "project.list", data: { projects }, ok: true };
|
|
32545
|
+
}
|
|
32365
32546
|
async next(query, directory) {
|
|
32366
32547
|
const projects = await this.#projects.find(query, directory);
|
|
32367
32548
|
if (projects.length === 0) {
|
|
@@ -32385,8 +32566,8 @@ var WorkflowCli = class {
|
|
|
32385
32566
|
ok: true
|
|
32386
32567
|
};
|
|
32387
32568
|
}
|
|
32388
|
-
async complete(directory) {
|
|
32389
|
-
const location = await this.#
|
|
32569
|
+
async complete(directory, projectId) {
|
|
32570
|
+
const location = await this.#locate(directory, projectId);
|
|
32390
32571
|
const state = await this.#loadState(location);
|
|
32391
32572
|
const step = nextStep(state.lastCompletedStep);
|
|
32392
32573
|
if (step === null) {
|
|
@@ -32416,8 +32597,8 @@ var WorkflowCli = class {
|
|
|
32416
32597
|
ok: true
|
|
32417
32598
|
};
|
|
32418
32599
|
}
|
|
32419
|
-
async deliveryInputs(directory) {
|
|
32420
|
-
const location = await this.#
|
|
32600
|
+
async deliveryInputs(directory, projectId) {
|
|
32601
|
+
const location = await this.#locate(directory, projectId);
|
|
32421
32602
|
const state = await this.#loadState(location);
|
|
32422
32603
|
if (nextStep(state.lastCompletedStep) !== "delivery") {
|
|
32423
32604
|
throw new WorkflowCliError(
|
|
@@ -32548,7 +32729,7 @@ var WorkflowDeliveryCli = class {
|
|
|
32548
32729
|
await writePrivateJson(path9.join(projectDirectory, DELIVERY_STATE_FILE), state);
|
|
32549
32730
|
}
|
|
32550
32731
|
async preview(options) {
|
|
32551
|
-
const inputs = await this.#workflow.deliveryInputs(options.directory);
|
|
32732
|
+
const inputs = await this.#workflow.deliveryInputs(options.directory, options.projectId);
|
|
32552
32733
|
const accounts = availableAccounts(await this.#wechat.accounts(this.#output));
|
|
32553
32734
|
if (accounts.length === 0) {
|
|
32554
32735
|
throw new WechatCliError(
|
|
@@ -32631,7 +32812,7 @@ var WorkflowDeliveryCli = class {
|
|
|
32631
32812
|
"\u8BF7\u5148\u67E5\u770B\u5FAE\u4FE1\u9884\u89C8\u5E76\u660E\u786E\u786E\u8BA4\u521B\u5EFA\u8349\u7A3F\u3002"
|
|
32632
32813
|
);
|
|
32633
32814
|
}
|
|
32634
|
-
const inputs = await this.#workflow.deliveryInputs(options.directory);
|
|
32815
|
+
const inputs = await this.#workflow.deliveryInputs(options.directory, options.projectId);
|
|
32635
32816
|
let state = await this.#readState(inputs.projectDirectory);
|
|
32636
32817
|
if (state.projectId !== inputs.project.projectId) {
|
|
32637
32818
|
throw new WorkflowCliError(
|
|
@@ -32877,14 +33058,19 @@ function createProgram(context) {
|
|
|
32877
33058
|
)
|
|
32878
33059
|
);
|
|
32879
33060
|
const workflow = program2.command("workflow").description("\u521B\u5EFA\u3001\u7EE7\u7EED\u548C\u4EA4\u4ED8\u6587\u7AE0");
|
|
32880
|
-
workflow.command("start").description("\u521B\u5EFA\
|
|
33061
|
+
workflow.command("start").description("\u521B\u5EFA\u6216\u91CD\u65B0\u8FDB\u5165\u4E00\u7BC7\u6587\u7AE0").option("--title <title>", "\u65B0\u9879\u76EE\u7684\u6587\u7AE0\u4E3B\u9898").option("--directory <path>", "\u81EA\u5B9A\u4E49\u9879\u76EE\u76EE\u5F55").option("--from <stage>", "\u4ECE\u6307\u5B9A\u5185\u5BB9\u9636\u6BB5\u8FDB\u5165").option("--project <uuid>", "\u5DF2\u6709\u9879\u76EE ID").option("--json", "\u8F93\u51FA JSON").action(
|
|
32881
33062
|
async (options) => runAction(
|
|
32882
33063
|
context,
|
|
32883
33064
|
options.json === true,
|
|
32884
33065
|
() => new WorkflowCli({
|
|
32885
33066
|
currentDirectory: context.currentDirectory,
|
|
32886
33067
|
homeDirectory: context.homeDirectory
|
|
32887
|
-
}).start({
|
|
33068
|
+
}).start({
|
|
33069
|
+
...options.directory === void 0 ? {} : { directory: options.directory },
|
|
33070
|
+
...options.from === void 0 ? {} : { from: options.from },
|
|
33071
|
+
...options.project === void 0 ? {} : { projectId: options.project },
|
|
33072
|
+
...options.title === void 0 ? {} : { title: options.title }
|
|
33073
|
+
})
|
|
32888
33074
|
)
|
|
32889
33075
|
);
|
|
32890
33076
|
workflow.command("next").description("\u8FD4\u56DE\u552F\u4E00\u9700\u8981\u6267\u884C\u7684\u4E0B\u4E00\u6B65").argument("[query]", "\u6587\u7AE0\u6807\u9898\u6216\u9879\u76EE ID").option("--directory <path>", "\u6307\u5B9A\u9879\u76EE\u76EE\u5F55").option("--json", "\u8F93\u51FA JSON").action(
|
|
@@ -32897,14 +33083,14 @@ function createProgram(context) {
|
|
|
32897
33083
|
}).next(query, options.directory)
|
|
32898
33084
|
)
|
|
32899
33085
|
);
|
|
32900
|
-
workflow.command("complete").description("\u4FDD\u5B58\u5F53\u524D\u6B65\u9AA4\u5E76\u8FD4\u56DE\u4E0B\u4E00\u6B65").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--json", "\u8F93\u51FA JSON").action(
|
|
33086
|
+
workflow.command("complete").description("\u4FDD\u5B58\u5F53\u524D\u6B65\u9AA4\u5E76\u8FD4\u56DE\u4E0B\u4E00\u6B65").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--project <uuid>", "\u9879\u76EE ID").option("--json", "\u8F93\u51FA JSON").action(
|
|
32901
33087
|
async (options) => runAction(
|
|
32902
33088
|
context,
|
|
32903
33089
|
options.json === true,
|
|
32904
33090
|
() => new WorkflowCli({
|
|
32905
33091
|
currentDirectory: context.currentDirectory,
|
|
32906
33092
|
homeDirectory: context.homeDirectory
|
|
32907
|
-
}).complete(options.directory)
|
|
33093
|
+
}).complete(options.directory, options.project)
|
|
32908
33094
|
)
|
|
32909
33095
|
);
|
|
32910
33096
|
const deliveryAction = async (json, action) => runAction(context, json, () => {
|
|
@@ -32920,27 +33106,40 @@ function createProgram(context) {
|
|
|
32920
33106
|
})
|
|
32921
33107
|
);
|
|
32922
33108
|
});
|
|
32923
|
-
workflow.command("preview").description("\u51C6\u5907\u5E76\u6253\u5F00\u5F53\u524D\u6587\u7AE0\u7684\u5FAE\u4FE1\u9884\u89C8").option("--account <uuid>", "\u591A\u4E2A\u516C\u4F17\u53F7\u65F6\u9009\u62E9\u76EE\u6807\u8D26\u53F7").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--browser <agent|system>", "\u9884\u89C8\u6253\u5F00\u4F4D\u7F6E", "system").option("--json", "\u8F93\u51FA JSON").action(
|
|
33109
|
+
workflow.command("preview").description("\u51C6\u5907\u5E76\u6253\u5F00\u5F53\u524D\u6587\u7AE0\u7684\u5FAE\u4FE1\u9884\u89C8").option("--account <uuid>", "\u591A\u4E2A\u516C\u4F17\u53F7\u65F6\u9009\u62E9\u76EE\u6807\u8D26\u53F7").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--project <uuid>", "\u9879\u76EE ID").option("--browser <agent|system>", "\u9884\u89C8\u6253\u5F00\u4F4D\u7F6E", "system").option("--json", "\u8F93\u51FA JSON").action(
|
|
32924
33110
|
async (options) => deliveryAction(
|
|
32925
33111
|
options.json === true,
|
|
32926
33112
|
(delivery) => delivery.preview({
|
|
32927
33113
|
...options.account === void 0 ? {} : { accountId: options.account },
|
|
32928
33114
|
browserMode: previewBrowserMode(options.browser),
|
|
32929
|
-
...options.directory === void 0 ? {} : { directory: options.directory }
|
|
33115
|
+
...options.directory === void 0 ? {} : { directory: options.directory },
|
|
33116
|
+
...options.project === void 0 ? {} : { projectId: options.project }
|
|
32930
33117
|
})
|
|
32931
33118
|
)
|
|
32932
33119
|
);
|
|
32933
|
-
workflow.command("deliver").description("\u786E\u8BA4\u5F53\u524D\u9884\u89C8\u5E76\u521B\u5EFA\u5FAE\u4FE1\u516C\u4F17\u53F7\u8349\u7A3F").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--confirm", "\u786E\u8BA4\u5DF2\u7ECF\u67E5\u770B\u9884\u89C8\u5E76\u521B\u5EFA\u8349\u7A3F").option("--json", "\u8F93\u51FA JSON").action(
|
|
33120
|
+
workflow.command("deliver").description("\u786E\u8BA4\u5F53\u524D\u9884\u89C8\u5E76\u521B\u5EFA\u5FAE\u4FE1\u516C\u4F17\u53F7\u8349\u7A3F").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55").option("--project <uuid>", "\u9879\u76EE ID").option("--confirm", "\u786E\u8BA4\u5DF2\u7ECF\u67E5\u770B\u9884\u89C8\u5E76\u521B\u5EFA\u8349\u7A3F").option("--json", "\u8F93\u51FA JSON").action(
|
|
32934
33121
|
async (options) => deliveryAction(
|
|
32935
33122
|
options.json === true,
|
|
32936
33123
|
(delivery) => delivery.deliver({
|
|
32937
33124
|
confirmed: options.confirm === true,
|
|
32938
|
-
...options.directory === void 0 ? {} : { directory: options.directory }
|
|
33125
|
+
...options.directory === void 0 ? {} : { directory: options.directory },
|
|
33126
|
+
...options.project === void 0 ? {} : { projectId: options.project }
|
|
32939
33127
|
})
|
|
32940
33128
|
)
|
|
32941
33129
|
);
|
|
33130
|
+
const project = program2.command("project").description("\u67E5\u770B\u672C\u673A\u5185\u5BB9\u9879\u76EE");
|
|
33131
|
+
project.command("list").description("\u5217\u51FA\u672C\u673A\u5DF2\u767B\u8BB0\u7684\u5185\u5BB9\u9879\u76EE").option("--json", "\u8F93\u51FA JSON").action(
|
|
33132
|
+
async (options) => runAction(
|
|
33133
|
+
context,
|
|
33134
|
+
options.json === true,
|
|
33135
|
+
() => new WorkflowCli({
|
|
33136
|
+
currentDirectory: context.currentDirectory,
|
|
33137
|
+
homeDirectory: context.homeDirectory
|
|
33138
|
+
}).listProjects()
|
|
33139
|
+
)
|
|
33140
|
+
);
|
|
32942
33141
|
const skills = program2.command("skills").description("\u5B89\u88C5 DxC \u5B98\u65B9 Skills");
|
|
32943
|
-
skills.command("install").description("\u5B89\u88C5
|
|
33142
|
+
skills.command("install").description("\u5B89\u88C5 14 \u4E2A\u5B98\u65B9 Skill").option("--target <codex|workbuddy>", "\u5B89\u88C5\u76EE\u6807", skillInstallTarget, "workbuddy").option("--directory <path>", "\u81EA\u5B9A\u4E49\u5B89\u88C5\u76EE\u5F55").option("--force", "\u66FF\u6362\u540C\u540D DxC Skill").option("--json", "\u8F93\u51FA JSON").action(
|
|
32944
33143
|
async (options) => runAction(context, options.json === true, async () => {
|
|
32945
33144
|
const result = await new SkillInstaller(
|
|
32946
33145
|
context.homeDirectory,
|
package/package.json
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dxc-article-outline
|
|
3
|
+
description: 为 DxC 文章完成大纲阶段,把 Brief、研究材料或用户已有构思组织为可直接写作的章节结构。用户要求列大纲、重构文章结构,或 dxc-content-workflow 返回 outline 阶段时使用;可以作为八步工作流的独立起点。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DxC 文章大纲
|
|
7
|
+
|
|
8
|
+
内部固定使用 `@deployxai/dxc@0.2.2`;Windows 通过 `npm.cmd exec`,macOS/Linux 通过 `npm exec`
|
|
9
|
+
运行,不切换到 PATH 中的其他版本。
|
|
10
|
+
|
|
11
|
+
## 进入阶段
|
|
12
|
+
|
|
13
|
+
- 总控返回 `step: outline` 时,读取 CLI 返回且真实存在的输入。
|
|
14
|
+
- 直接从大纲开始或重新进入已有项目时,调用:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
dxc workflow start --from outline --title "<主题>" --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
已有项目改为 `--project "<项目 ID>"` 并省略 `--title`;用户在对话中给出的 Brief 或材料可以直接使用。
|
|
21
|
+
|
|
22
|
+
- 只使用本页列出的 workflow 领域命令。
|
|
23
|
+
|
|
24
|
+
## 生成大纲
|
|
25
|
+
|
|
26
|
+
完整读取 [references/outline-methods.md](references/outline-methods.md),选择一个最适合当前内容的主结构。
|
|
27
|
+
每节写清目标、论点、证据责任和承接关系,避免为显得复杂而混搭框架。把结果写入 CLI 返回的
|
|
28
|
+
`output`,再调用 `dxc workflow complete --project "<项目 ID>" --json`。
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 大纲结构与标记
|
|
2
|
+
|
|
3
|
+
## 专家方法来源
|
|
4
|
+
|
|
5
|
+
- 原始方法真值是开发仓库 `docs/员工BCDE的skill/employee-c-outline-architect/SKILL.md`
|
|
6
|
+
的第 3–12 节;发布包不含原文,执行时以本胶囊为准。
|
|
7
|
+
- 本胶囊承接情绪/传播要素判定、结构选型、C→D→E 标记和自检。产物路径与进度由 CLI 统一处理。
|
|
8
|
+
|
|
9
|
+
## 结构选择
|
|
10
|
+
|
|
11
|
+
| 内容与情绪 | 首选结构 |
|
|
12
|
+
| -------------------- | ------------------------------------ |
|
|
13
|
+
| 怕、怒、问题需要解决 | PAS:痛点、放大、方案 |
|
|
14
|
+
| 暖、敬、人物经历 | 目标、阻碍、努力、转折、结果 |
|
|
15
|
+
| 站队、观点争议 | 痛点、新观点、正例、反例、价值、行动 |
|
|
16
|
+
| 搞懂、认知升级 | SCQA:情境、冲突、问题、答案 |
|
|
17
|
+
| 方法教程 | 问题、原则、方法、案例、清单 |
|
|
18
|
+
| 专业论证 | 结论先行、分论点、证据 |
|
|
19
|
+
| 深度叙事 | 起、承、转、合 |
|
|
20
|
+
|
|
21
|
+
只选最符合 Brief 的主结构。情绪型结构必须有出路,不能只放大焦虑。
|
|
22
|
+
|
|
23
|
+
## 选型前的两项判定
|
|
24
|
+
|
|
25
|
+
1. **情绪属性**:判断读者此刻是需要被理解、被说服、被解释、被推动还是被安放;情绪是
|
|
26
|
+
结构张力,不等于在每段标注情绪词。
|
|
27
|
+
2. **传播要素**:判断本篇最需要的是认知反差、具体利益、故事共鸣、身份认同还是可执行
|
|
28
|
+
方法。它用于检查开头、核心论点和收束是否有记忆点,而不是制造标题党。
|
|
29
|
+
|
|
30
|
+
选型后先写一句“读者从什么状态到什么状态”的结构承诺。若结构不能兑现这个变化,应换
|
|
31
|
+
结构或收窄 Brief,而不是叠加多个框架。
|
|
32
|
+
|
|
33
|
+
## 标记 contract
|
|
34
|
+
|
|
35
|
+
| 标记 | 下游动作 |
|
|
36
|
+
| ----------------- | ------------------------------------------------------------------------------------------------ |
|
|
37
|
+
| `[钩子]` | 正文前三行直接进入冲突、问题或具体场景 |
|
|
38
|
+
| `[情绪:<类型>]` | 类型可选痛点、放大、方案、好奇、愤怒、释然、满足、行动欲或搞懂 |
|
|
39
|
+
| `[金句位:<类型>]` | 类型可选共鸣、观点或反讽;正文写一句可独立成立且服务当前段落的话 |
|
|
40
|
+
| `[数据位:说明]` | 只补有来源的数据,缺失时保留待核实 |
|
|
41
|
+
| `[案例位:说明]` | 补真实、用户提供或明确脱敏的案例 |
|
|
42
|
+
| `[配图:<类型>]` | 类型可选思维导图、概念图、流程图、数据图、金句图、场景插画或氛围;视觉计划读取,不在正文直接插图 |
|
|
43
|
+
|
|
44
|
+
标记必须位于相关章节内。不要把标记堆到文末。三层以上层级、概念关系、步骤、数据和金句
|
|
45
|
+
分别是思维导图、概念图、流程图、数据图和金句图的信号。
|
|
46
|
+
|
|
47
|
+
## 自检
|
|
48
|
+
|
|
49
|
+
- 大纲是否回答 Brief 的核心问题;
|
|
50
|
+
- 每节是否承担一个明确任务;
|
|
51
|
+
- 证据与案例是否有放置位置;
|
|
52
|
+
- 开头是否在前三行进入问题;
|
|
53
|
+
- 情绪放大后是否有方案;
|
|
54
|
+
- 金句和视觉锚点是否服务内容,而不是凑数量。
|
|
55
|
+
- 结构是否把读者阻碍、转折、证据和行动放在恰当顺序,而非只罗列知识点;
|
|
56
|
+
- 每个反例是否服务主张,结尾是否回收开头承诺;
|
|
57
|
+
- 标记是否让 D 能写、E 能画,而不是留下不可执行的抽象词。
|