autocrew 0.3.8 → 0.3.9
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/package.json +1 -1
- package/src/cli/commands/review.ts +40 -9
- package/src/tools/review.ts +10 -2
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import { getOption, resolveProjectText } from "./index.js";
|
|
|
4
4
|
export const cmd: CommandDef = {
|
|
5
5
|
name: "review",
|
|
6
6
|
description: "Run full content review or auto-fix",
|
|
7
|
-
usage: "autocrew review <
|
|
7
|
+
usage: "autocrew review <id-or-slug> [--platform <p>] [--fix] [--dry-run] [--file <path>]",
|
|
8
8
|
action: async (args, runner) => {
|
|
9
9
|
const id = args[0];
|
|
10
10
|
if (!id && !args.includes("--file")) {
|
|
@@ -15,6 +15,7 @@ export const cmd: CommandDef = {
|
|
|
15
15
|
|
|
16
16
|
const platform = getOption(args, "--platform");
|
|
17
17
|
const isFix = args.includes("--fix");
|
|
18
|
+
const isDryRun = args.includes("--dry-run");
|
|
18
19
|
|
|
19
20
|
const resolved = await resolveProjectText(id, args);
|
|
20
21
|
if (!resolved) {
|
|
@@ -23,7 +24,7 @@ export const cmd: CommandDef = {
|
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
if (isFix) {
|
|
27
|
+
if (isFix || isDryRun) {
|
|
27
28
|
const result = await runner.execute("autocrew_review", {
|
|
28
29
|
action: "auto_fix",
|
|
29
30
|
text: resolved.text,
|
|
@@ -36,13 +37,47 @@ export const cmd: CommandDef = {
|
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
// Write fixed text back to source file
|
|
40
40
|
const fixedText = (result.autoFixedText || result.fixedText || "") as string;
|
|
41
|
+
console.log(` Sensitive words fixed: ${result.sensitiveWordsFixed || 0}`);
|
|
42
|
+
console.log(` AI traces fixed: ${result.aiFixesApplied || 0}`);
|
|
43
|
+
|
|
44
|
+
// Show diff preview
|
|
45
|
+
if (fixedText && fixedText !== resolved.text) {
|
|
46
|
+
// Simple line-by-line diff
|
|
47
|
+
const origLines = resolved.text.split("\n");
|
|
48
|
+
const fixedLines = fixedText.split("\n");
|
|
49
|
+
const diffLines: string[] = [];
|
|
50
|
+
const maxLen = Math.max(origLines.length, fixedLines.length);
|
|
51
|
+
for (let i = 0; i < maxLen; i++) {
|
|
52
|
+
const orig = origLines[i] ?? "";
|
|
53
|
+
const fixed = fixedLines[i] ?? "";
|
|
54
|
+
if (orig !== fixed) {
|
|
55
|
+
if (orig) diffLines.push(` - ${orig}`);
|
|
56
|
+
if (fixed) diffLines.push(` + ${fixed}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (diffLines.length > 0) {
|
|
60
|
+
console.log(`\n Changes preview:`);
|
|
61
|
+
for (const line of diffLines.slice(0, 20)) {
|
|
62
|
+
console.log(line);
|
|
63
|
+
}
|
|
64
|
+
if (diffLines.length > 20) {
|
|
65
|
+
console.log(` ... and ${diffLines.length - 20} more lines`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (isDryRun) {
|
|
71
|
+
console.log(`\n (dry-run mode — no files modified)`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Write fixed text back to source file
|
|
41
76
|
if (fixedText && resolved.source.startsWith("file:")) {
|
|
42
77
|
const fs = await import("node:fs/promises");
|
|
43
78
|
const filePath = resolved.source.replace("file:", "");
|
|
44
79
|
await fs.writeFile(filePath, fixedText, "utf-8");
|
|
45
|
-
console.log(
|
|
80
|
+
console.log(`\n Saved back to ${filePath}`);
|
|
46
81
|
} else if (fixedText && resolved.source.startsWith("pipeline:")) {
|
|
47
82
|
const fs = await import("node:fs/promises");
|
|
48
83
|
const { findProject } = await import("../../storage/pipeline-store.js");
|
|
@@ -51,13 +86,9 @@ export const cmd: CommandDef = {
|
|
|
51
86
|
if (found) {
|
|
52
87
|
const path = await import("node:path");
|
|
53
88
|
await fs.writeFile(path.join(found.dir, "draft.md"), fixedText, "utf-8");
|
|
54
|
-
console.log(
|
|
89
|
+
console.log(`\n Saved back to draft.md`);
|
|
55
90
|
}
|
|
56
|
-
} else {
|
|
57
|
-
console.log(`Auto-fix complete for "${resolved.title}" (${resolved.source})`);
|
|
58
91
|
}
|
|
59
|
-
console.log(` Sensitive words fixed: ${result.sensitiveWordsFixed || 0}`);
|
|
60
|
-
console.log(` AI traces fixed: ${result.aiFixesApplied || 0}`);
|
|
61
92
|
return;
|
|
62
93
|
}
|
|
63
94
|
|
package/src/tools/review.ts
CHANGED
|
@@ -250,13 +250,21 @@ export async function executeReview(params: Record<string, unknown>) {
|
|
|
250
250
|
const fixes: string[] = [];
|
|
251
251
|
if (sensitiveWords.hitCount > 0) {
|
|
252
252
|
fixes.push(`修复 ${sensitiveWords.hitCount} 个敏感词`);
|
|
253
|
-
for (const hit of sensitiveWords.hits.slice(0,
|
|
253
|
+
for (const hit of sensitiveWords.hits.slice(0, 10)) {
|
|
254
254
|
const fix = hit.suggestion ? `"${hit.word}" → "${hit.suggestion}"` : `删除"${hit.word}"`;
|
|
255
|
-
|
|
255
|
+
// Show surrounding context for each hit
|
|
256
|
+
const pos = hit.positions[0];
|
|
257
|
+
const contextStart = Math.max(0, pos - 10);
|
|
258
|
+
const contextEnd = Math.min(fullText.length, pos + hit.word.length + 10);
|
|
259
|
+
const context = fullText.slice(contextStart, contextEnd).replace(/\n/g, " ");
|
|
260
|
+
fixes.push(` - ${fix} (${hit.category}) — "...${context}..."`);
|
|
256
261
|
}
|
|
257
262
|
}
|
|
258
263
|
if (aiCheck.hasAiTraces) {
|
|
259
264
|
fixes.push(`去 AI 味:${aiCheck.changeCount} 处需要修改`);
|
|
265
|
+
for (const change of aiCheck.changes.slice(0, 5)) {
|
|
266
|
+
fixes.push(` - ${change}`);
|
|
267
|
+
}
|
|
260
268
|
}
|
|
261
269
|
for (const note of qualityScore.notes) {
|
|
262
270
|
fixes.push(note);
|