code-yangzz 1.0.0
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 +102 -0
- package/agents/meta-artisan.md +164 -0
- package/agents/meta-conductor.md +482 -0
- package/agents/meta-genesis.md +165 -0
- package/agents/meta-librarian.md +213 -0
- package/agents/meta-prism.md +268 -0
- package/agents/meta-scout.md +173 -0
- package/agents/meta-sentinel.md +161 -0
- package/agents/meta-warden.md +304 -0
- package/bin/install.js +390 -0
- package/bin/lib/utils.js +72 -0
- package/bin/lib/watermark.js +176 -0
- package/config/CLAUDE.md +363 -0
- package/config/settings.json +120 -0
- package/hooks/block-dangerous-bash.mjs +36 -0
- package/hooks/post-console-log-warn.mjs +27 -0
- package/hooks/post-format.mjs +24 -0
- package/hooks/post-typecheck.mjs +27 -0
- package/hooks/pre-git-push-confirm.mjs +19 -0
- package/hooks/stop-completion-guard.mjs +159 -0
- package/hooks/stop-console-log-audit.mjs +44 -0
- package/hooks/subagent-context.mjs +27 -0
- package/hooks/user-prompt-submit.js +233 -0
- package/package.json +36 -0
- package/prompt-optimizer/prompt-optimizer-meta.md +159 -0
- package/skills/agent-teams/SKILL.md +215 -0
- package/skills/domains/ai/SKILL.md +34 -0
- package/skills/domains/ai/agent-dev.md +242 -0
- package/skills/domains/ai/llm-security.md +288 -0
- package/skills/domains/ai/prompt-and-eval.md +279 -0
- package/skills/domains/ai/rag-system.md +542 -0
- package/skills/domains/architecture/SKILL.md +42 -0
- package/skills/domains/architecture/api-design.md +225 -0
- package/skills/domains/architecture/caching.md +298 -0
- package/skills/domains/architecture/cloud-native.md +285 -0
- package/skills/domains/architecture/message-queue.md +328 -0
- package/skills/domains/architecture/security-arch.md +297 -0
- package/skills/domains/data-engineering/SKILL.md +207 -0
- package/skills/domains/development/SKILL.md +46 -0
- package/skills/domains/development/cpp.md +246 -0
- package/skills/domains/development/go.md +323 -0
- package/skills/domains/development/java.md +277 -0
- package/skills/domains/development/python.md +288 -0
- package/skills/domains/development/rust.md +313 -0
- package/skills/domains/development/shell.md +313 -0
- package/skills/domains/development/typescript.md +277 -0
- package/skills/domains/devops/SKILL.md +39 -0
- package/skills/domains/devops/cost-optimization.md +271 -0
- package/skills/domains/devops/database.md +217 -0
- package/skills/domains/devops/devsecops.md +198 -0
- package/skills/domains/devops/git-workflow.md +181 -0
- package/skills/domains/devops/observability.md +279 -0
- package/skills/domains/devops/performance.md +335 -0
- package/skills/domains/devops/testing.md +283 -0
- package/skills/domains/frontend-design/SKILL.md +38 -0
- package/skills/domains/frontend-design/agents/openai.yaml +4 -0
- package/skills/domains/frontend-design/claymorphism/SKILL.md +119 -0
- package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
- package/skills/domains/frontend-design/component-patterns.md +202 -0
- package/skills/domains/frontend-design/engineering.md +287 -0
- package/skills/domains/frontend-design/glassmorphism/SKILL.md +140 -0
- package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
- package/skills/domains/frontend-design/liquid-glass/SKILL.md +137 -0
- package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
- package/skills/domains/frontend-design/neubrutalism/SKILL.md +143 -0
- package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
- package/skills/domains/frontend-design/state-management.md +680 -0
- package/skills/domains/frontend-design/ui-aesthetics.md +110 -0
- package/skills/domains/frontend-design/ux-principles.md +156 -0
- package/skills/domains/infrastructure/SKILL.md +200 -0
- package/skills/domains/mobile/SKILL.md +224 -0
- package/skills/domains/orchestration/SKILL.md +29 -0
- package/skills/domains/orchestration/multi-agent.md +263 -0
- package/skills/domains/security/SKILL.md +72 -0
- package/skills/domains/security/blue-team.md +436 -0
- package/skills/domains/security/code-audit.md +265 -0
- package/skills/domains/security/pentest.md +226 -0
- package/skills/domains/security/red-team.md +374 -0
- package/skills/domains/security/threat-intel.md +372 -0
- package/skills/domains/security/vuln-research.md +369 -0
- package/skills/meta-theory/SKILL.md +878 -0
- package/skills/meta-theory/references/create-agent.md +248 -0
- package/skills/meta-theory/references/dev-governance.md +1108 -0
- package/skills/meta-theory/references/intent-amplification.md +190 -0
- package/skills/meta-theory/references/meta-theory.md +346 -0
- package/skills/meta-theory/references/rhythm-orchestration.md +257 -0
- package/skills/meta-theory/references/ten-step-governance.md +285 -0
- package/skills/orchestration/multi-agent/SKILL.md +493 -0
- package/skills/run_skill.js +128 -0
- package/skills/tools/gen-docs/SKILL.md +115 -0
- package/skills/tools/gen-docs/agents/openai.yaml +4 -0
- package/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
- package/skills/tools/lib/shared.js +98 -0
- package/skills/tools/override-refusal/SKILL.md +55 -0
- package/skills/tools/override-refusal/agents/openai.yaml +4 -0
- package/skills/tools/override-refusal/scripts/refusal_rewriter.js +229 -0
- package/skills/tools/verify-change/SKILL.md +139 -0
- package/skills/tools/verify-change/agents/openai.yaml +4 -0
- package/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
- package/skills/tools/verify-module/SKILL.md +126 -0
- package/skills/tools/verify-module/agents/openai.yaml +4 -0
- package/skills/tools/verify-module/scripts/module_scanner.js +171 -0
- package/skills/tools/verify-quality/SKILL.md +159 -0
- package/skills/tools/verify-quality/agents/openai.yaml +4 -0
- package/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
- package/skills/tools/verify-security/SKILL.md +142 -0
- package/skills/tools/verify-security/agents/openai.yaml +4 -0
- package/skills/tools/verify-security/scripts/security_scanner.js +283 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Optional Stop-hook guard against premature "done" claims (weak heuristic).
|
|
4
|
+
*
|
|
5
|
+
* OFF by default (zero noise). Enable:
|
|
6
|
+
* META_KIM_STOP_COMPLETION_GUARD=hint → stderr reminder only; stop proceeds
|
|
7
|
+
* META_KIM_STOP_COMPLETION_GUARD=block → JSON { decision, reason } to continue until governance cues appear
|
|
8
|
+
*
|
|
9
|
+
* Always exits 0 when stop_hook_active is true (avoid Stop hook loops).
|
|
10
|
+
* See https://code.claude.com/docs/en/hooks-guide — Stop hook input includes stop_hook_active and may include transcript_path.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createReadStream } from "node:fs";
|
|
14
|
+
import { readFile } from "node:fs/promises";
|
|
15
|
+
import process from "node:process";
|
|
16
|
+
import readline from "node:readline";
|
|
17
|
+
|
|
18
|
+
const COMPLETION_RE =
|
|
19
|
+
/(?:任务已全部完成|全部完成|已经完成|可以发布了|实施完成|工作已完成|圆满完成|大功告成|已全部搞定|done\.?\s*All tasks|implementation complete|fully complete|ready to (?:ship|publish)|all set(?:\s|$)|mission accomplished)/i;
|
|
20
|
+
|
|
21
|
+
const EVIDENCE_RE =
|
|
22
|
+
/verificationPacket|summaryClosed|publicDisplay|validate:run|closeFindings|verified_closed|summaryPacket|npm run validate/;
|
|
23
|
+
|
|
24
|
+
async function readStdinJson() {
|
|
25
|
+
const chunks = [];
|
|
26
|
+
for await (const chunk of process.stdin) {
|
|
27
|
+
chunks.push(chunk);
|
|
28
|
+
}
|
|
29
|
+
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
30
|
+
if (!raw) {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(raw);
|
|
35
|
+
} catch {
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Last ~16k chars of assistant-visible text from a JSONL transcript (best-effort). */
|
|
41
|
+
async function tailAssistantText(transcriptPath, maxBytes = 16_384) {
|
|
42
|
+
const stat = await readFile(transcriptPath).catch(() => null);
|
|
43
|
+
if (!stat) {
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
const full = stat.toString("utf8");
|
|
47
|
+
const lines = full.split("\n").filter(Boolean);
|
|
48
|
+
const texts = [];
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
let row;
|
|
51
|
+
try {
|
|
52
|
+
row = JSON.parse(line);
|
|
53
|
+
} catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const msg = row.message ?? row;
|
|
57
|
+
const role = msg.role ?? row.role;
|
|
58
|
+
if (role !== "assistant") {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const c = msg.content;
|
|
62
|
+
if (typeof c === "string") {
|
|
63
|
+
texts.push(c);
|
|
64
|
+
} else if (Array.isArray(c)) {
|
|
65
|
+
for (const part of c) {
|
|
66
|
+
if (part?.type === "text" && typeof part.text === "string") {
|
|
67
|
+
texts.push(part.text);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const joined = texts.join("\n");
|
|
73
|
+
if (joined.length <= maxBytes) {
|
|
74
|
+
return joined;
|
|
75
|
+
}
|
|
76
|
+
return joined.slice(-maxBytes);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Streaming tail when file is huge: read last lines and grep assistant-ish JSON (fallback). */
|
|
80
|
+
async function tailTranscriptFallback(transcriptPath) {
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
const parts = [];
|
|
83
|
+
const rl = readline.createInterface({
|
|
84
|
+
input: createReadStream(transcriptPath, { encoding: "utf8" }),
|
|
85
|
+
crlfDelay: Infinity,
|
|
86
|
+
});
|
|
87
|
+
const buf = [];
|
|
88
|
+
const maxLines = 400;
|
|
89
|
+
rl.on("line", (line) => {
|
|
90
|
+
buf.push(line);
|
|
91
|
+
if (buf.length > maxLines) {
|
|
92
|
+
buf.shift();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
rl.on("close", () => {
|
|
96
|
+
for (const line of buf) {
|
|
97
|
+
if (line.includes('"role":"assistant"') || line.includes('"role": "assistant"')) {
|
|
98
|
+
parts.push(line);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
resolve(parts.join("\n").slice(-16_384));
|
|
102
|
+
});
|
|
103
|
+
rl.on("error", () => resolve(""));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
const input = await readStdinJson();
|
|
109
|
+
|
|
110
|
+
if (input.stop_hook_active === true) {
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const mode = (process.env.META_KIM_STOP_COMPLETION_GUARD || "").trim().toLowerCase();
|
|
115
|
+
if (!mode || mode === "0" || mode === "off" || mode === "false") {
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const transcriptPath = input.transcript_path || input.transcriptPath;
|
|
120
|
+
let sample = "";
|
|
121
|
+
if (typeof transcriptPath === "string" && transcriptPath.length > 0) {
|
|
122
|
+
try {
|
|
123
|
+
sample = await tailAssistantText(transcriptPath);
|
|
124
|
+
if (!sample) {
|
|
125
|
+
sample = await tailTranscriptFallback(transcriptPath);
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
sample = "";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!sample || sample.length < 20) {
|
|
133
|
+
process.exit(0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const claimsDone = COMPLETION_RE.test(sample);
|
|
137
|
+
const hasEvidence = EVIDENCE_RE.test(sample);
|
|
138
|
+
if (!claimsDone || hasEvidence) {
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const reason =
|
|
143
|
+
"[Fusion] You claimed completion but the last assistant text did not reference verification/summary/validate:run. " +
|
|
144
|
+
"If this was a governed complex run: produce or update the run artifact, close findings, and align summaryPacket with contracts/workflow-contract.json publicDisplay gates.";
|
|
145
|
+
|
|
146
|
+
if (mode === "block") {
|
|
147
|
+
process.stdout.write(JSON.stringify({ decision: "block", reason }));
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (mode === "hint") {
|
|
152
|
+
process.stderr.write(`${reason}\n`);
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
main().catch(() => process.exit(0));
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Stop hook: audit all modified files for console.log before session ends
|
|
5
|
+
* Scans git diff for console.log statements
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from "node:child_process";
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const diff = execSync("git diff --name-only HEAD", {
|
|
12
|
+
encoding: "utf8",
|
|
13
|
+
timeout: 5000,
|
|
14
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
15
|
+
}).trim();
|
|
16
|
+
|
|
17
|
+
if (!diff) process.exit(0);
|
|
18
|
+
|
|
19
|
+
const files = diff
|
|
20
|
+
.split("\n")
|
|
21
|
+
.filter((f) => f.match(/\.(js|ts|jsx|tsx|mjs|cjs)$/));
|
|
22
|
+
|
|
23
|
+
const violations = [];
|
|
24
|
+
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
try {
|
|
27
|
+
const content = require("node:fs").readFileSync(file, "utf8");
|
|
28
|
+
const matches = content.match(/console\.(log|debug|info)\(/g);
|
|
29
|
+
if (matches) {
|
|
30
|
+
violations.push(`${file}: ${matches.length} console.log(s)`);
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
// file deleted or not readable
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (violations.length > 0) {
|
|
38
|
+
process.stderr.write(
|
|
39
|
+
`[audit] console.log found in modified files:\n${violations.join("\n")}\n`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
// git not available or not a repo
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
|
|
3
|
+
await readJsonFromStdin();
|
|
4
|
+
|
|
5
|
+
const additionalContext = [
|
|
6
|
+
"Fusion subagent rule set:",
|
|
7
|
+
"- Optional local research note: docs/meta.md (may be absent in the public repository)",
|
|
8
|
+
"- Canonical Claude agent source: .claude/agents/*.md",
|
|
9
|
+
"- After editing agents or skills, run npm run sync:runtimes and npm run validate",
|
|
10
|
+
"- Prefer the smallest agent boundary that can solve the task cleanly",
|
|
11
|
+
"- Do not fork runtime-specific instructions unless the target runtime genuinely requires it",
|
|
12
|
+
].join("\n");
|
|
13
|
+
|
|
14
|
+
process.stdout.write(
|
|
15
|
+
JSON.stringify({
|
|
16
|
+
hookSpecificOutput: {
|
|
17
|
+
hookEventName: "SubagentStart",
|
|
18
|
+
additionalContext,
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
async function readJsonFromStdin() {
|
|
24
|
+
for await (const _chunk of process.stdin) {
|
|
25
|
+
// The hook only needs to consume stdin so Claude Code can continue.
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 提示词自动优化Hook - 跨平台版本 (Node.js)
|
|
4
|
+
*
|
|
5
|
+
* 支持 Windows/Mac/Linux,无需额外依赖
|
|
6
|
+
*
|
|
7
|
+
* 工作流程:
|
|
8
|
+
* 1. 用户输入提示词
|
|
9
|
+
* 2. Hook优化
|
|
10
|
+
* 3. 返回优化后的提示词给Claude
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
|
|
17
|
+
// 跨平台临时目录
|
|
18
|
+
const LOG_FILE = path.join(os.tmpdir(), 'hook-prompt-optimizer.log');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 记录日志
|
|
22
|
+
*/
|
|
23
|
+
function log(message) {
|
|
24
|
+
const timestamp = new Date().toISOString();
|
|
25
|
+
const logEntry = `[${timestamp}] ${message}\n`;
|
|
26
|
+
try {
|
|
27
|
+
fs.appendFileSync(LOG_FILE, logEntry);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// 忽略日志错误
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 读取优化提示词模板
|
|
35
|
+
*/
|
|
36
|
+
function readOptimizerTemplate() {
|
|
37
|
+
// 获取脚本目录并找到模板
|
|
38
|
+
const scriptDir = __dirname;
|
|
39
|
+
const claudeDir = path.dirname(scriptDir);
|
|
40
|
+
const templatePath = path.join(claudeDir, 'prompt-optimizer-meta.md');
|
|
41
|
+
|
|
42
|
+
// 备选:检查用户主目录
|
|
43
|
+
const homeTemplatePath = path.join(os.homedir(), '.claude', 'prompt-optimizer-meta.md');
|
|
44
|
+
|
|
45
|
+
if (fs.existsSync(templatePath)) {
|
|
46
|
+
return fs.readFileSync(templatePath, 'utf8');
|
|
47
|
+
} else if (fs.existsSync(homeTemplatePath)) {
|
|
48
|
+
log(`模板文件未在 ${templatePath} 找到,使用主目录版本`);
|
|
49
|
+
return fs.readFileSync(homeTemplatePath, 'utf8');
|
|
50
|
+
} else {
|
|
51
|
+
log(`错误:模板文件未找到:${templatePath} 或 ${homeTemplatePath}`);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 检查输入是否应该被过滤(不优化)
|
|
58
|
+
* ⚠️ 注意:此函数内不能写日志!否则会被过滤的输入也会产生日志输出
|
|
59
|
+
*
|
|
60
|
+
* @returns {boolean} true表示应该过滤(跳过优化),false表示需要优化
|
|
61
|
+
*/
|
|
62
|
+
function shouldFilter(input) {
|
|
63
|
+
const trimmed = input.trim();
|
|
64
|
+
|
|
65
|
+
// Claude Code 内置命令和Skill命令 - 不应被优化
|
|
66
|
+
// 匹配: /help, /commit, /review-pr, /skill-name:sub-command 等
|
|
67
|
+
if (trimmed.startsWith('/')) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Claude Code 内部系统消息 - 精确匹配已知标签,避免误杀用户的 HTML/JSX 输入
|
|
72
|
+
const systemTagPattern = /^<(task-notification|system-reminder|tool-result|tool-use|agent-response|claude-internal)[\s>]/;
|
|
73
|
+
if (systemTagPattern.test(trimmed)) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 简单交互式回复 - 不需要优化
|
|
78
|
+
const simpleResponses = [
|
|
79
|
+
'好的', '是的', '继续', '谢谢', 'ok', 'OK', 'yes', 'YES',
|
|
80
|
+
'no', 'NO', '确认', '取消', '好', '行', '可以', '不', '嗯',
|
|
81
|
+
'y', 'n', 'Y', 'N'
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// 精确匹配简单回复
|
|
85
|
+
if (simpleResponses.includes(trimmed)) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 太短(< 10字符)
|
|
90
|
+
if (trimmed.length < 10) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 构建优化请求(JSON格式,符合Claude Code Hook API)
|
|
99
|
+
*/
|
|
100
|
+
function buildOptimizationRequest(template, userInput) {
|
|
101
|
+
// 强制指令放在最前面,优先级最高
|
|
102
|
+
const forceInstruction = `<MANDATORY_FORMAT_INSTRUCTION>
|
|
103
|
+
【回复格式说明】
|
|
104
|
+
|
|
105
|
+
你的回复必须严格按以下顺序输出,不得跳过任何部分:
|
|
106
|
+
|
|
107
|
+
1. 第一行必须是:📝 **原始输入**:${userInput}
|
|
108
|
+
|
|
109
|
+
2. 然后是:
|
|
110
|
+
🔄 **优化后的理解**:
|
|
111
|
+
- **Context(上下文)**:[推断的场景、身份、目标]
|
|
112
|
+
- **Task(任务)**:[明确的动作 + 要求]
|
|
113
|
+
- **Format(格式)**:[期望的输出形式]
|
|
114
|
+
|
|
115
|
+
3. 然后是:
|
|
116
|
+
✅ **优化后的完整提示词**:
|
|
117
|
+
[优化后的结构化提示词]
|
|
118
|
+
|
|
119
|
+
4. 最后是分隔线 --- 后执行任务内容
|
|
120
|
+
|
|
121
|
+
请在回复开头先展示对用户输入的理解(原始输入 + 优化后的结构化版本),然后再执行任务。这样用户可以看到提示词是如何被优化的。
|
|
122
|
+
</MANDATORY_FORMAT_INSTRUCTION>
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
${template}
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 用户原始输入
|
|
131
|
+
|
|
132
|
+
${userInput}`;
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
hookSpecificOutput: {
|
|
136
|
+
hookEventName: "UserPromptSubmit",
|
|
137
|
+
additionalContext: forceInstruction
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 解析 Claude Code Hook API 的 JSON 输入
|
|
144
|
+
* ⚠️ 注意:此函数在shouldFilter之前调用,不能写日志!
|
|
145
|
+
*
|
|
146
|
+
* 支持多种输入格式:
|
|
147
|
+
* 1. { prompt: "用户输入" } - 旧格式
|
|
148
|
+
* 2. { messages: [{role: "user", content: "用户输入"}] } - 新格式
|
|
149
|
+
* 3. { session_id: "...", prompt: "用户输入" } - 带session的格式
|
|
150
|
+
*/
|
|
151
|
+
function parseHookInput(rawInput) {
|
|
152
|
+
try {
|
|
153
|
+
const parsed = JSON.parse(rawInput);
|
|
154
|
+
|
|
155
|
+
// 检查是否有 prompt 字段(最常见的格式)
|
|
156
|
+
if (parsed.prompt) {
|
|
157
|
+
return parsed.prompt;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 检查是否有 messages 数组(新格式)
|
|
161
|
+
if (parsed.messages && Array.isArray(parsed.messages) && parsed.messages.length > 0) {
|
|
162
|
+
// 获取最后一条用户消息
|
|
163
|
+
const lastMessage = parsed.messages[parsed.messages.length - 1];
|
|
164
|
+
if (lastMessage.role === 'user' && lastMessage.content) {
|
|
165
|
+
return lastMessage.content;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 如果都没有,返回原始输入
|
|
170
|
+
return rawInput;
|
|
171
|
+
} catch (e) {
|
|
172
|
+
// 如果不是JSON,返回原始输入(可能是纯文本)
|
|
173
|
+
return rawInput;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 主函数
|
|
179
|
+
*/
|
|
180
|
+
async function main() {
|
|
181
|
+
// 从stdin读取输入
|
|
182
|
+
let rawInput = '';
|
|
183
|
+
|
|
184
|
+
// 检查是否通过参数运行
|
|
185
|
+
if (process.argv.length > 2) {
|
|
186
|
+
rawInput = process.argv.slice(2).join(' ');
|
|
187
|
+
} else {
|
|
188
|
+
// 从stdin读取
|
|
189
|
+
rawInput = fs.readFileSync(0, 'utf8');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
rawInput = rawInput.trim();
|
|
193
|
+
|
|
194
|
+
// 解析输入,提取实际的用户消息
|
|
195
|
+
const userInput = parseHookInput(rawInput);
|
|
196
|
+
|
|
197
|
+
// 【关键】立即检查是否需要过滤,如果需要则直接退出,不写任何日志
|
|
198
|
+
if (shouldFilter(userInput)) {
|
|
199
|
+
process.stdout.write(JSON.stringify({}));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 只有通过过滤的输入才会执行到这里,开始写日志
|
|
204
|
+
log('========================================');
|
|
205
|
+
log('Hook执行开始');
|
|
206
|
+
log(`原始输入: ${rawInput.substring(0, 100)}...`);
|
|
207
|
+
log(`原始输入长度: ${rawInput.length}`);
|
|
208
|
+
log(`用户输入: ${userInput.substring(0, 100)}...`);
|
|
209
|
+
log(`输入长度: ${userInput.length}`);
|
|
210
|
+
log('通过过滤,开始优化...');
|
|
211
|
+
|
|
212
|
+
// 读取模板
|
|
213
|
+
const template = readOptimizerTemplate();
|
|
214
|
+
if (!template) {
|
|
215
|
+
log('模板未找到,返回空响应');
|
|
216
|
+
process.stdout.write(JSON.stringify({}));
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 构建并输出优化请求
|
|
221
|
+
const optimizationRequest = buildOptimizationRequest(template, userInput);
|
|
222
|
+
|
|
223
|
+
log('优化请求已构建,输出JSON...');
|
|
224
|
+
log(`JSON长度: ${JSON.stringify(optimizationRequest).length}`);
|
|
225
|
+
process.stdout.write(JSON.stringify(optimizationRequest));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 运行
|
|
229
|
+
main().catch(err => {
|
|
230
|
+
// 出错时返回空响应
|
|
231
|
+
log(`错误: ${err.message}`);
|
|
232
|
+
process.stdout.write(JSON.stringify({}));
|
|
233
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "code-yangzz",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Claude Code / Codex CLI 四层增强系统:输入优化 + 治理框架 + 多Agent编排 + 专业知识库 | by yangzz",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"codex",
|
|
9
|
+
"cli",
|
|
10
|
+
"ai",
|
|
11
|
+
"agent",
|
|
12
|
+
"governance",
|
|
13
|
+
"prompt-engineering"
|
|
14
|
+
],
|
|
15
|
+
"author": "yangzz",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"bin": {
|
|
18
|
+
"code-yangzz": "bin/install.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin/",
|
|
22
|
+
"config/",
|
|
23
|
+
"hooks/",
|
|
24
|
+
"agents/",
|
|
25
|
+
"skills/",
|
|
26
|
+
"prompt-optimizer/",
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@inquirer/prompts": "^7.10.1"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# 提示词优化元提示词
|
|
2
|
+
|
|
3
|
+
你是一个提示词优化专家,精通谷歌提示词工程指南和5任务元提示词方法论。
|
|
4
|
+
|
|
5
|
+
## 你的任务
|
|
6
|
+
|
|
7
|
+
用户会给你一段需求描述。你的任务是把它优化成符合最佳实践的专业提示词。
|
|
8
|
+
|
|
9
|
+
## 优化原则(基于5任务元提示词)
|
|
10
|
+
|
|
11
|
+
### 【任务一:构建地基】
|
|
12
|
+
|
|
13
|
+
1. **应用CTF公式**:
|
|
14
|
+
- Context(上下文):从用户输入和当前项目上下文推断身份、受众、目标
|
|
15
|
+
- Task(任务):使用强动词(分析、拆解、重写、优化)+ 量化要求
|
|
16
|
+
- Format(格式):明确输出结构(Markdown、JSON、列表、代码)
|
|
17
|
+
|
|
18
|
+
2. **结构化输入**:
|
|
19
|
+
- 使用分隔符(###, ---)或XML标签(<context>, <data>)
|
|
20
|
+
- 区分指令与内容
|
|
21
|
+
|
|
22
|
+
3. **肯定性指令**:
|
|
23
|
+
- 使用"请使用XXX"而不是"不要使用XXX"
|
|
24
|
+
- 避免粉色大象效应
|
|
25
|
+
|
|
26
|
+
### 【任务二:激活推理】
|
|
27
|
+
|
|
28
|
+
4. **策略选择**:
|
|
29
|
+
- 简单任务 → 直接问(Zero-Shot)
|
|
30
|
+
- 需要特定格式/风格 → 给1-3个范例(Few-Shot)
|
|
31
|
+
- 逻辑/数学题 → 加"让我们一步步思考"(CoT)
|
|
32
|
+
- 复杂决策 → 让AI模拟多个专家角度(ToT)
|
|
33
|
+
|
|
34
|
+
5. **自我修正**:
|
|
35
|
+
- 复杂任务加入Review环节
|
|
36
|
+
- "先生成草稿,再列出3个缺点,最后根据缺点生成修正版"
|
|
37
|
+
|
|
38
|
+
### 【任务三:掌控输出】
|
|
39
|
+
|
|
40
|
+
6. **明确输出格式**:
|
|
41
|
+
- 提供具体的Schema或示例
|
|
42
|
+
- 指定验收标准
|
|
43
|
+
|
|
44
|
+
7. **边界条件**:
|
|
45
|
+
- 添加异常处理要求
|
|
46
|
+
- 说明特殊情况的处理方式
|
|
47
|
+
|
|
48
|
+
## 输出格式(重要!)
|
|
49
|
+
|
|
50
|
+
你必须按照以下格式输出优化结果:
|
|
51
|
+
|
|
52
|
+
```markdown
|
|
53
|
+
📝 **原始输入**:[用户的原话]
|
|
54
|
+
|
|
55
|
+
🔄 **优化后的理解**:
|
|
56
|
+
- **Context(上下文)**:[推断的身份、技术栈(如果项目上下文可用)、场景、目标]
|
|
57
|
+
- **Task(任务)**:[明确的动作 + 量化要求]
|
|
58
|
+
- **Format(格式)**:[期望的输出形式]
|
|
59
|
+
|
|
60
|
+
✅ **优化后的完整提示词**:
|
|
61
|
+
|
|
62
|
+
[这里是优化后的完整提示词,要完整、详细、结构化]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 示例
|
|
66
|
+
|
|
67
|
+
### 示例1:模糊需求
|
|
68
|
+
|
|
69
|
+
**输入**:
|
|
70
|
+
```
|
|
71
|
+
做个登录功能
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**输出**:
|
|
75
|
+
```markdown
|
|
76
|
+
📝 **原始输入**:做个登录功能
|
|
77
|
+
|
|
78
|
+
🔄 **优化后的理解**:
|
|
79
|
+
- **Context(上下文)**:Web应用,资深全栈工程师,生产级安全要求
|
|
80
|
+
- **Task(任务)**:实现完整的用户登录功能,包括前端表单、后端验证、token生成、会话管理
|
|
81
|
+
- **Format(格式)**:完整代码文件 + 关键逻辑注释 + 测试用例
|
|
82
|
+
|
|
83
|
+
✅ **优化后的完整提示词**:
|
|
84
|
+
|
|
85
|
+
**任务**:实现用户登录功能
|
|
86
|
+
|
|
87
|
+
**上下文**:
|
|
88
|
+
- 身份:资深全栈工程师
|
|
89
|
+
- 技术栈:[从项目推断或使用通用栈]
|
|
90
|
+
- 安全要求:生产级别
|
|
91
|
+
|
|
92
|
+
**具体要求**:
|
|
93
|
+
1. 使用JWT做token认证
|
|
94
|
+
2. 密码用bcrypt加密存储
|
|
95
|
+
3. 登录失败3次锁定账号10分钟
|
|
96
|
+
4. 成功后返回用户信息和token
|
|
97
|
+
|
|
98
|
+
**输出格式**:
|
|
99
|
+
- 完整的前后端代码文件
|
|
100
|
+
- 关键逻辑注释
|
|
101
|
+
- 安全最佳实践说明(防SQL注入、XSS)
|
|
102
|
+
- 测试用例
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### 示例2:Debug场景
|
|
108
|
+
|
|
109
|
+
**输入**:
|
|
110
|
+
```
|
|
111
|
+
这个报错怎么回事
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**输出**:
|
|
115
|
+
```markdown
|
|
116
|
+
📝 **原始输入**:这个报错怎么回事
|
|
117
|
+
|
|
118
|
+
🔄 **优化后的理解**:
|
|
119
|
+
- **Context(上下文)**:遇到代码错误,需要Debug专家分析
|
|
120
|
+
- **Task(任务)**:定位错误根因并提供修复方案
|
|
121
|
+
- **Format(格式)**:问题原因 + 修复代码 + 预防建议
|
|
122
|
+
|
|
123
|
+
✅ **优化后的完整提示词**:
|
|
124
|
+
|
|
125
|
+
**任务**:分析并修复错误
|
|
126
|
+
|
|
127
|
+
**上下文**:
|
|
128
|
+
- 身份:资深Debug专家
|
|
129
|
+
- 目标:找到根因并修复
|
|
130
|
+
|
|
131
|
+
**分析步骤**:
|
|
132
|
+
1. 阅读错误堆栈,定位问题代码位置
|
|
133
|
+
2. 分析可能原因(类型错误/空值/逻辑错误)
|
|
134
|
+
3. 检查相关上下文代码
|
|
135
|
+
|
|
136
|
+
**输出要求**:
|
|
137
|
+
- 问题原因(一句话)
|
|
138
|
+
- 修复方案(代码)
|
|
139
|
+
- 防止再次发生的建议
|
|
140
|
+
|
|
141
|
+
**自我检查**:
|
|
142
|
+
修复后确认类型安全,不引入新问题
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 重要提醒
|
|
148
|
+
|
|
149
|
+
**【格式说明】回复请以优化结果开头**:
|
|
150
|
+
- 每条回复的**第一行**请使用 `📝 **原始输入**:`
|
|
151
|
+
- 然后是 `🔄 **优化后的理解**:`
|
|
152
|
+
- 然后是 `✅ **优化后的完整提示词**:`
|
|
153
|
+
- 最后才是执行任务的内容
|
|
154
|
+
- 先展示对用户输入的理解,再执行任务,这样用户可以看到提示词优化过程
|
|
155
|
+
|
|
156
|
+
其他规则:
|
|
157
|
+
1. **保持原始意图**,不要改变用户的核心需求
|
|
158
|
+
2. **如果用户输入已经很清晰**,优化部分可以简洁,但格式必须完整
|
|
159
|
+
3. **从项目上下文推断技术栈**(如果可用),不要硬编码特定技术
|