ccgx-workflow 1.0.0 → 1.0.1

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 (60) hide show
  1. package/README.md +37 -5
  2. package/README.zh-CN.md +35 -5
  3. package/dist/cli.mjs +1 -1
  4. package/dist/index.mjs +2 -2
  5. package/dist/shared/{ccgx-workflow.WgUzkiC3.mjs → ccgx-workflow.SJPbUy5_.mjs} +17 -110
  6. package/package.json +2 -1
  7. package/templates/commands/agents/phase-runner.md +321 -321
  8. package/templates/commands/autonomous.md +792 -792
  9. package/templates/commands/cancel.md +132 -132
  10. package/templates/commands/debug.md +226 -226
  11. package/templates/commands/status.md +206 -206
  12. package/templates/commands/team.md +484 -0
  13. package/templates/hooks/ccg-session-state.cjs +510 -510
  14. package/templates/scripts/ccg-phase-runner-launcher.mjs +467 -467
  15. package/templates/scripts/invoke-model.mjs +64 -0
  16. package/templates/skills/domains/ai/SKILL.md +35 -35
  17. package/templates/skills/domains/ai/agent-dev.md +242 -242
  18. package/templates/skills/domains/ai/llm-security.md +288 -288
  19. package/templates/skills/domains/ai/rag-system.md +542 -542
  20. package/templates/skills/domains/architecture/SKILL.md +43 -43
  21. package/templates/skills/domains/architecture/api-design.md +225 -225
  22. package/templates/skills/domains/architecture/cloud-native.md +285 -285
  23. package/templates/skills/domains/architecture/security-arch.md +297 -297
  24. package/templates/skills/domains/data-engineering/SKILL.md +208 -208
  25. package/templates/skills/domains/development/SKILL.md +47 -47
  26. package/templates/skills/domains/development/cpp.md +246 -246
  27. package/templates/skills/domains/development/go.md +323 -323
  28. package/templates/skills/domains/development/java.md +277 -277
  29. package/templates/skills/domains/development/python.md +288 -288
  30. package/templates/skills/domains/development/rust.md +313 -313
  31. package/templates/skills/domains/development/shell.md +313 -313
  32. package/templates/skills/domains/development/typescript.md +277 -277
  33. package/templates/skills/domains/devops/SKILL.md +40 -40
  34. package/templates/skills/domains/devops/database.md +217 -217
  35. package/templates/skills/domains/devops/devsecops.md +198 -198
  36. package/templates/skills/domains/devops/git-workflow.md +181 -181
  37. package/templates/skills/domains/devops/testing.md +283 -283
  38. package/templates/skills/domains/frontend-design/SKILL.md +244 -244
  39. package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +121 -121
  40. package/templates/skills/domains/frontend-design/component-patterns.md +202 -202
  41. package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +142 -142
  42. package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +139 -139
  43. package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +145 -145
  44. package/templates/skills/domains/frontend-design/state-management.md +680 -680
  45. package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -110
  46. package/templates/skills/domains/frontend-design/ux-principles.md +156 -156
  47. package/templates/skills/domains/infrastructure/SKILL.md +201 -201
  48. package/templates/skills/domains/mobile/SKILL.md +225 -225
  49. package/templates/skills/domains/orchestration/SKILL.md +30 -30
  50. package/templates/skills/domains/orchestration/multi-agent.md +228 -228
  51. package/templates/skills/domains/security/SKILL.md +73 -73
  52. package/templates/skills/domains/security/blue-team.md +436 -436
  53. package/templates/skills/domains/security/code-audit.md +265 -265
  54. package/templates/skills/domains/security/pentest.md +226 -226
  55. package/templates/skills/domains/security/red-team.md +374 -374
  56. package/templates/skills/domains/security/threat-intel.md +372 -372
  57. package/templates/skills/domains/security/vuln-research.md +369 -369
  58. package/templates/skills/tools/lib/shared.js +98 -98
  59. package/templates/skills/tools/override-refusal/SKILL.md +53 -53
  60. package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -226
@@ -186,6 +186,61 @@ function lookPath(cmd, opts = {}) {
186
186
  return cmd; // let spawn surface ENOENT
187
187
  }
188
188
 
189
+ // Resolve `cmd` against PATH (POSIX) or PATH+PATHEXT (Windows).
190
+ // Returns null when the binary is not found, giving callers a chance to emit
191
+ // a friendly install hint before spawn raises ENOENT.
192
+ function resolveOnPath(cmd, opts = {}) {
193
+ const env = opts.env || process.env;
194
+ const platform = opts.platform || process.platform;
195
+ const stat = opts.statFn || statSync;
196
+ if (path.isAbsolute(cmd) || cmd.includes('/') || (platform === 'win32' && cmd.includes('\\'))) {
197
+ try { const info = stat(cmd); if (info && info.isFile && info.isFile()) return cmd; }
198
+ catch { /* fallthrough */ }
199
+ return null;
200
+ }
201
+ if (platform === 'win32') {
202
+ const resolved = lookPath(cmd, opts);
203
+ return resolved !== cmd ? resolved : null;
204
+ }
205
+ const dirs = (env.PATH || '').split(':').filter(Boolean);
206
+ for (const dir of dirs) {
207
+ const full = path.join(dir, cmd);
208
+ try { const info = stat(full); if (info && info.isFile && info.isFile()) return full; }
209
+ catch { /* keep scanning */ }
210
+ }
211
+ return null;
212
+ }
213
+
214
+ // Print install guidance and exit 127 when the requested backend CLI is not
215
+ // on PATH. Prefers Claude Code plugins (one-click) over manual CLI install.
216
+ function exitMissingBackend(backend) {
217
+ const pluginInstall = backend === 'codex'
218
+ ? '/plugins install codex@openai-codex'
219
+ : backend === 'gemini'
220
+ ? '/plugins install gemini@google-gemini'
221
+ : null;
222
+ const npmInstall = backend === 'codex'
223
+ ? 'npm i -g @openai/codex'
224
+ : backend === 'gemini'
225
+ ? 'npm i -g @google/gemini-cli'
226
+ : null;
227
+ process.stderr.write([
228
+ '',
229
+ `❌ ccgx-workflow fallback: '${backend}' CLI not found on PATH.`,
230
+ '',
231
+ 'Pick one of:',
232
+ pluginInstall
233
+ ? ` • Plugin (recommended): in Claude Code run ${pluginInstall}`
234
+ : ` • Plugin route is unavailable for backend "${backend}".`,
235
+ npmInstall
236
+ ? ` • CLI fallback: ${npmInstall} then ${backend} login / auth`
237
+ : '',
238
+ '',
239
+ 'After installing, start a new Claude Code session.',
240
+ '',
241
+ ].filter(Boolean).join('\n') + '\n');
242
+ }
243
+
189
244
  function expandHome(p) {
190
245
  if (typeof p !== 'string') return p;
191
246
  if (p === '~') return homedir();
@@ -706,6 +761,15 @@ async function main() {
706
761
 
707
762
  const { command, args } = backendCommandAndArgs(cfg, targetArg);
708
763
 
764
+ // Friendly fail when the backend CLI is not installed.
765
+ // Skip for absolute paths — those are already explicit user intent.
766
+ if (!path.isAbsolute(command) && !command.includes('/') && !command.includes('\\')) {
767
+ if (resolveOnPath(command) === null) {
768
+ exitMissingBackend(cfg.backend);
769
+ return 127;
770
+ }
771
+ }
772
+
709
773
  // Startup banner (main.go:432)
710
774
  process.stderr.write(
711
775
  `[${WRAPPER_NAME}]\n` +
@@ -1,35 +1,35 @@
1
- ---
2
- name: ai
3
- description: AI/LLM 能力索引(Agent 开发、LLM 安全、RAG、Prompt 工程)。
4
- license: MIT
5
- user-invocable: false
6
- disable-model-invocation: false
7
- context: fork
8
- ---
9
-
10
- # 丹鼎秘典 · AI/LLM 能力中枢
11
-
12
- ## 能力矩阵
13
-
14
- | Skill | 定位 | 核心能力 |
15
- |-------|------|----------|
16
- | [agent-dev](agent-dev.md) | Agent 开发 | 多 Agent 编排、工具调用、RAG |
17
- | [llm-security](llm-security.md) | LLM 安全 | Prompt 注入、越狱防护、输出安全 |
18
- | [rag-system](rag-system.md) | RAG 系统 | 向量数据库、检索策略、重排算法 |
19
- | [prompt-and-eval](prompt-and-eval.md) | Prompt 工程与模型评估 | Few-shot、CoT、ReAct、RAGAS、LLM-as-Judge |
20
-
21
- ## AI 工程原则
22
-
23
- ```yaml
24
- 设计原则:
25
- - 人机协作,AI 增强而非替代
26
- - 可解释性优先
27
- - 安全边界明确
28
- - 渐进式自主
29
-
30
- 开发原则:
31
- - Prompt 即代码,需版本控制
32
- - 输入输出都需验证
33
- - 成本与效果平衡
34
- - 持续评估与迭代
35
- ```
1
+ ---
2
+ name: ai
3
+ description: AI/LLM 能力索引(Agent 开发、LLM 安全、RAG、Prompt 工程)。
4
+ license: MIT
5
+ user-invocable: false
6
+ disable-model-invocation: false
7
+ context: fork
8
+ ---
9
+
10
+ # 丹鼎秘典 · AI/LLM 能力中枢
11
+
12
+ ## 能力矩阵
13
+
14
+ | Skill | 定位 | 核心能力 |
15
+ |-------|------|----------|
16
+ | [agent-dev](agent-dev.md) | Agent 开发 | 多 Agent 编排、工具调用、RAG |
17
+ | [llm-security](llm-security.md) | LLM 安全 | Prompt 注入、越狱防护、输出安全 |
18
+ | [rag-system](rag-system.md) | RAG 系统 | 向量数据库、检索策略、重排算法 |
19
+ | [prompt-and-eval](prompt-and-eval.md) | Prompt 工程与模型评估 | Few-shot、CoT、ReAct、RAGAS、LLM-as-Judge |
20
+
21
+ ## AI 工程原则
22
+
23
+ ```yaml
24
+ 设计原则:
25
+ - 人机协作,AI 增强而非替代
26
+ - 可解释性优先
27
+ - 安全边界明确
28
+ - 渐进式自主
29
+
30
+ 开发原则:
31
+ - Prompt 即代码,需版本控制
32
+ - 输入输出都需验证
33
+ - 成本与效果平衡
34
+ - 持续评估与迭代
35
+ ```
@@ -1,242 +1,242 @@
1
- ---
2
- name: agent-dev
3
- description: AI Agent 开发。多 Agent 编排、工具调用、RAG 系统、Prompt 工程。当用户提到 Agent、RAG、Prompt、LangChain、向量数据库时使用。
4
- ---
5
-
6
- # 🔮 丹鼎秘典 · AI Agent 开发
7
-
8
-
9
- ## Agent 架构
10
-
11
- ```
12
- ┌─────────────────────────────────────────────────────────────┐
13
- │ Agent 系统 │
14
- ├─────────────────────────────────────────────────────────────┤
15
- │ 用户输入 → 意图理解 → 规划 → 执行 → 反思 → 输出 │
16
- │ │ │ │ │ │
17
- │ Prompt Planner Tools Memory │
18
- └─────────────────────────────────────────────────────────────┘
19
- ```
20
-
21
- ## 核心组件
22
-
23
- ### 1. Prompt 工程
24
-
25
- ```yaml
26
- 结构化 Prompt:
27
- - System: 角色定义、能力边界、行为规范
28
- - Context: 背景信息、相关知识
29
- - Task: 具体任务、输出格式
30
- - Examples: Few-shot 示例
31
-
32
- 技巧:
33
- - 明确角色和边界
34
- - 分步骤引导思考
35
- - 提供输出格式示例
36
- - 设置安全护栏
37
- ```
38
-
39
- ### 2. 工具调用
40
-
41
- ```python
42
- # 工具定义
43
- tools = [
44
- {
45
- "name": "search",
46
- "description": "搜索知识库",
47
- "parameters": {
48
- "type": "object",
49
- "properties": {
50
- "query": {"type": "string", "description": "搜索关键词"}
51
- },
52
- "required": ["query"]
53
- }
54
- }
55
- ]
56
-
57
- # 工具执行
58
- def execute_tool(name: str, args: dict) -> str:
59
- if name == "search":
60
- return search_knowledge_base(args["query"])
61
- raise ValueError(f"Unknown tool: {name}")
62
- ```
63
-
64
- ### 3. 记忆系统
65
-
66
- ```yaml
67
- 短期记忆:
68
- - 对话历史
69
- - 当前任务上下文
70
- - 工具调用结果
71
-
72
- 长期记忆:
73
- - 向量数据库存储
74
- - 用户偏好
75
- - 历史交互摘要
76
-
77
- 记忆管理:
78
- - 滑动窗口
79
- - 摘要压缩
80
- - 重要性排序
81
- ```
82
-
83
- ## RAG 系统
84
-
85
- ### 架构
86
-
87
- ```
88
- 文档 → 分块 → 嵌入 → 向量库
89
-
90
- 查询 → 嵌入 → 检索 → 重排序 → 生成
91
- ```
92
-
93
- ### 实现
94
-
95
- ```python
96
- from langchain.text_splitter import RecursiveCharacterTextSplitter
97
- from langchain.embeddings import OpenAIEmbeddings
98
- from langchain.vectorstores import Chroma
99
-
100
- # 文档处理
101
- splitter = RecursiveCharacterTextSplitter(
102
- chunk_size=1000,
103
- chunk_overlap=200,
104
- separators=["\n\n", "\n", "。", ",", " "]
105
- )
106
- chunks = splitter.split_documents(documents)
107
-
108
- # 向量存储
109
- embeddings = OpenAIEmbeddings()
110
- vectorstore = Chroma.from_documents(chunks, embeddings)
111
-
112
- # 检索
113
- retriever = vectorstore.as_retriever(
114
- search_type="mmr", # 最大边际相关性
115
- search_kwargs={"k": 5, "fetch_k": 20}
116
- )
117
- ```
118
-
119
- ### 优化策略
120
-
121
- ```yaml
122
- 分块策略:
123
- - 语义分块 vs 固定长度
124
- - 重叠避免信息丢失
125
- - 保留元数据
126
-
127
- 检索优化:
128
- - 混合检索 (关键词 + 向量)
129
- - 重排序 (Reranker)
130
- - 查询扩展
131
-
132
- 生成优化:
133
- - 引用来源
134
- - 置信度评估
135
- - 幻觉检测
136
- ```
137
-
138
- ## 多 Agent 编排
139
-
140
- ### 模式
141
-
142
- ```yaml
143
- 顺序执行:
144
- Agent A → Agent B → Agent C
145
-
146
- 并行执行:
147
- Agent A ─┬─→ Agent B ─┬─→ 汇总
148
- └─→ Agent C ─┘
149
-
150
- 层级结构:
151
- Orchestrator
152
- ├── Planner Agent
153
- ├── Executor Agent
154
- └── Reviewer Agent
155
-
156
- 对话式:
157
- Agent A ←→ Agent B (多轮交互)
158
- ```
159
-
160
- ### 实现示例
161
-
162
- ```python
163
- class Orchestrator:
164
- def __init__(self):
165
- self.planner = PlannerAgent()
166
- self.executor = ExecutorAgent()
167
- self.reviewer = ReviewerAgent()
168
-
169
- async def run(self, task: str) -> str:
170
- # 规划
171
- plan = await self.planner.plan(task)
172
-
173
- # 执行
174
- results = []
175
- for step in plan.steps:
176
- result = await self.executor.execute(step)
177
- results.append(result)
178
-
179
- # 审查
180
- final = await self.reviewer.review(task, results)
181
- return final
182
- ```
183
-
184
- ## 评估与监控
185
-
186
- ```yaml
187
- 评估维度:
188
- - 准确性: 答案正确率
189
- - 相关性: 检索质量
190
- - 完整性: 信息覆盖
191
- - 一致性: 多次回答稳定性
192
-
193
- 监控指标:
194
- - 延迟 (P50/P95/P99)
195
- - Token 消耗
196
- - 工具调用成功率
197
- - 用户满意度
198
- ```
199
-
200
- ## 框架选择
201
-
202
- ```yaml
203
- LangChain:
204
- - 优点: 生态丰富,组件多
205
- - 缺点: 抽象层多,调试难
206
- - 适合: 快速原型
207
-
208
- LlamaIndex:
209
- - 优点: RAG 专精
210
- - 缺点: Agent 能力弱
211
- - 适合: 知识库应用
212
-
213
- 原生实现:
214
- - 优点: 完全可控
215
- - 缺点: 开发成本高
216
- - 适合: 生产系统
217
- ```
218
-
219
- ## 最佳实践
220
-
221
- ```yaml
222
- 开发:
223
- - Prompt 版本控制
224
- - 单元测试覆盖
225
- - 成本预算控制
226
- - 降级策略
227
-
228
- 部署:
229
- - 流式输出
230
- - 超时处理
231
- - 重试机制
232
- - 缓存策略
233
-
234
- 安全:
235
- - 输入验证
236
- - 输出过滤
237
- - 权限控制
238
- - 审计日志
239
- ```
240
-
241
- ---
242
-
1
+ ---
2
+ name: agent-dev
3
+ description: AI Agent 开发。多 Agent 编排、工具调用、RAG 系统、Prompt 工程。当用户提到 Agent、RAG、Prompt、LangChain、向量数据库时使用。
4
+ ---
5
+
6
+ # 🔮 丹鼎秘典 · AI Agent 开发
7
+
8
+
9
+ ## Agent 架构
10
+
11
+ ```
12
+ ┌─────────────────────────────────────────────────────────────┐
13
+ │ Agent 系统 │
14
+ ├─────────────────────────────────────────────────────────────┤
15
+ │ 用户输入 → 意图理解 → 规划 → 执行 → 反思 → 输出 │
16
+ │ │ │ │ │ │
17
+ │ Prompt Planner Tools Memory │
18
+ └─────────────────────────────────────────────────────────────┘
19
+ ```
20
+
21
+ ## 核心组件
22
+
23
+ ### 1. Prompt 工程
24
+
25
+ ```yaml
26
+ 结构化 Prompt:
27
+ - System: 角色定义、能力边界、行为规范
28
+ - Context: 背景信息、相关知识
29
+ - Task: 具体任务、输出格式
30
+ - Examples: Few-shot 示例
31
+
32
+ 技巧:
33
+ - 明确角色和边界
34
+ - 分步骤引导思考
35
+ - 提供输出格式示例
36
+ - 设置安全护栏
37
+ ```
38
+
39
+ ### 2. 工具调用
40
+
41
+ ```python
42
+ # 工具定义
43
+ tools = [
44
+ {
45
+ "name": "search",
46
+ "description": "搜索知识库",
47
+ "parameters": {
48
+ "type": "object",
49
+ "properties": {
50
+ "query": {"type": "string", "description": "搜索关键词"}
51
+ },
52
+ "required": ["query"]
53
+ }
54
+ }
55
+ ]
56
+
57
+ # 工具执行
58
+ def execute_tool(name: str, args: dict) -> str:
59
+ if name == "search":
60
+ return search_knowledge_base(args["query"])
61
+ raise ValueError(f"Unknown tool: {name}")
62
+ ```
63
+
64
+ ### 3. 记忆系统
65
+
66
+ ```yaml
67
+ 短期记忆:
68
+ - 对话历史
69
+ - 当前任务上下文
70
+ - 工具调用结果
71
+
72
+ 长期记忆:
73
+ - 向量数据库存储
74
+ - 用户偏好
75
+ - 历史交互摘要
76
+
77
+ 记忆管理:
78
+ - 滑动窗口
79
+ - 摘要压缩
80
+ - 重要性排序
81
+ ```
82
+
83
+ ## RAG 系统
84
+
85
+ ### 架构
86
+
87
+ ```
88
+ 文档 → 分块 → 嵌入 → 向量库
89
+
90
+ 查询 → 嵌入 → 检索 → 重排序 → 生成
91
+ ```
92
+
93
+ ### 实现
94
+
95
+ ```python
96
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
97
+ from langchain.embeddings import OpenAIEmbeddings
98
+ from langchain.vectorstores import Chroma
99
+
100
+ # 文档处理
101
+ splitter = RecursiveCharacterTextSplitter(
102
+ chunk_size=1000,
103
+ chunk_overlap=200,
104
+ separators=["\n\n", "\n", "。", ",", " "]
105
+ )
106
+ chunks = splitter.split_documents(documents)
107
+
108
+ # 向量存储
109
+ embeddings = OpenAIEmbeddings()
110
+ vectorstore = Chroma.from_documents(chunks, embeddings)
111
+
112
+ # 检索
113
+ retriever = vectorstore.as_retriever(
114
+ search_type="mmr", # 最大边际相关性
115
+ search_kwargs={"k": 5, "fetch_k": 20}
116
+ )
117
+ ```
118
+
119
+ ### 优化策略
120
+
121
+ ```yaml
122
+ 分块策略:
123
+ - 语义分块 vs 固定长度
124
+ - 重叠避免信息丢失
125
+ - 保留元数据
126
+
127
+ 检索优化:
128
+ - 混合检索 (关键词 + 向量)
129
+ - 重排序 (Reranker)
130
+ - 查询扩展
131
+
132
+ 生成优化:
133
+ - 引用来源
134
+ - 置信度评估
135
+ - 幻觉检测
136
+ ```
137
+
138
+ ## 多 Agent 编排
139
+
140
+ ### 模式
141
+
142
+ ```yaml
143
+ 顺序执行:
144
+ Agent A → Agent B → Agent C
145
+
146
+ 并行执行:
147
+ Agent A ─┬─→ Agent B ─┬─→ 汇总
148
+ └─→ Agent C ─┘
149
+
150
+ 层级结构:
151
+ Orchestrator
152
+ ├── Planner Agent
153
+ ├── Executor Agent
154
+ └── Reviewer Agent
155
+
156
+ 对话式:
157
+ Agent A ←→ Agent B (多轮交互)
158
+ ```
159
+
160
+ ### 实现示例
161
+
162
+ ```python
163
+ class Orchestrator:
164
+ def __init__(self):
165
+ self.planner = PlannerAgent()
166
+ self.executor = ExecutorAgent()
167
+ self.reviewer = ReviewerAgent()
168
+
169
+ async def run(self, task: str) -> str:
170
+ # 规划
171
+ plan = await self.planner.plan(task)
172
+
173
+ # 执行
174
+ results = []
175
+ for step in plan.steps:
176
+ result = await self.executor.execute(step)
177
+ results.append(result)
178
+
179
+ # 审查
180
+ final = await self.reviewer.review(task, results)
181
+ return final
182
+ ```
183
+
184
+ ## 评估与监控
185
+
186
+ ```yaml
187
+ 评估维度:
188
+ - 准确性: 答案正确率
189
+ - 相关性: 检索质量
190
+ - 完整性: 信息覆盖
191
+ - 一致性: 多次回答稳定性
192
+
193
+ 监控指标:
194
+ - 延迟 (P50/P95/P99)
195
+ - Token 消耗
196
+ - 工具调用成功率
197
+ - 用户满意度
198
+ ```
199
+
200
+ ## 框架选择
201
+
202
+ ```yaml
203
+ LangChain:
204
+ - 优点: 生态丰富,组件多
205
+ - 缺点: 抽象层多,调试难
206
+ - 适合: 快速原型
207
+
208
+ LlamaIndex:
209
+ - 优点: RAG 专精
210
+ - 缺点: Agent 能力弱
211
+ - 适合: 知识库应用
212
+
213
+ 原生实现:
214
+ - 优点: 完全可控
215
+ - 缺点: 开发成本高
216
+ - 适合: 生产系统
217
+ ```
218
+
219
+ ## 最佳实践
220
+
221
+ ```yaml
222
+ 开发:
223
+ - Prompt 版本控制
224
+ - 单元测试覆盖
225
+ - 成本预算控制
226
+ - 降级策略
227
+
228
+ 部署:
229
+ - 流式输出
230
+ - 超时处理
231
+ - 重试机制
232
+ - 缓存策略
233
+
234
+ 安全:
235
+ - 输入验证
236
+ - 输出过滤
237
+ - 权限控制
238
+ - 审计日志
239
+ ```
240
+
241
+ ---
242
+