feat: 重写insertBatchDataToTarget方法,参考Salesforce数据插入逻辑
- 重写DataiIntegrationBatchServiceImpl中的insertBatchDataToTarget方法 - 参考CommonServiceImpl.java中的Salesforce数据插入逻辑 - 优化字段映射结构,使用List<Map<String, Object>>存储字段映射 - 增加字段过滤,排除is_dump和is_upload等标记字段 - 添加线程休眠机制,避免API限流 - 改进错误处理,增加完整异常堆栈信息 - 添加工作流提示词文档(03-01, 03-02, 03-03) - 添加Salesforce参考代码(CommonServiceImpl.java, DataImportNewServiceImpl.java)
This commit is contained in:
parent
19b1d1a41a
commit
f6a97dbf7f
@ -13,7 +13,7 @@ import com.datai.common.utils.SecurityUtils;
|
|||||||
import com.datai.integration.model.param.DataiSyncParam;
|
import com.datai.integration.model.param.DataiSyncParam;
|
||||||
import com.datai.salesforce.common.utils.SoqlBuilder;
|
import com.datai.salesforce.common.utils.SoqlBuilder;
|
||||||
import com.datai.integration.util.ConvertUtil;
|
import com.datai.integration.util.ConvertUtil;
|
||||||
import com.sforce.soap.partner.PartnerConnection;
|
import com.sforce.soap.partner.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -27,10 +27,7 @@ import com.datai.integration.service.IDataiIntegrationFieldService;
|
|||||||
import com.datai.integration.service.IDataiIntegrationSyncLogService;
|
import com.datai.integration.service.IDataiIntegrationSyncLogService;
|
||||||
import com.datai.integration.mapper.CustomMapper;
|
import com.datai.integration.mapper.CustomMapper;
|
||||||
import com.datai.integration.factory.impl.SOAPConnectionFactory;
|
import com.datai.integration.factory.impl.SOAPConnectionFactory;
|
||||||
import com.sforce.soap.partner.DescribeSObjectResult;
|
|
||||||
import com.sforce.soap.partner.Field;
|
|
||||||
import com.datai.integration.core.IPartnerV1Connection;
|
import com.datai.integration.core.IPartnerV1Connection;
|
||||||
import com.sforce.soap.partner.QueryResult;
|
|
||||||
import com.sforce.soap.partner.sobject.SObject;
|
import com.sforce.soap.partner.sobject.SObject;
|
||||||
import com.sforce.ws.ConnectionException;
|
import com.sforce.ws.ConnectionException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -998,8 +995,6 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
public Map<String, Object> insertBatchDataToTarget(Integer id, String targetOrgType) {
|
public Map<String, Object> insertBatchDataToTarget(Integer id, String targetOrgType) {
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
|
||||||
log.info("开始插入批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
|
log.info("开始插入批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
@ -1063,7 +1058,7 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
String batchField = batch.getBatchField();
|
String batchField = batch.getBatchField();
|
||||||
String whereClause = "";
|
String whereClause = "";
|
||||||
if (batchField != null && !batchField.trim().isEmpty()) {
|
if (batchField != null && !batchField.trim().isEmpty()) {
|
||||||
whereClause = "WHERE " + batchField.trim() + " = '" + batch.getBatchValue() + "'";
|
whereClause = "WHERE " + batchField.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("开始查询本地批次数据,表名: {}, 条件: {}", tableName, whereClause);
|
log.info("开始查询本地批次数据,表名: {}, 条件: {}", tableName, whereClause);
|
||||||
@ -1096,24 +1091,34 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> fieldsToInsert = new HashMap<>();
|
List<Map<String, Object>> maps = new ArrayList<>();
|
||||||
for (String key : dataMap.keySet()) {
|
for (String key : dataMap.keySet()) {
|
||||||
if (!"id".equalsIgnoreCase(key) && !"new_id".equalsIgnoreCase(key) &&
|
Object value = dataMap.get(key);
|
||||||
!"is_insert".equalsIgnoreCase(key) && !"is_update".equalsIgnoreCase(key) &&
|
if (value != null && !"id".equalsIgnoreCase(key) &&
|
||||||
dataMap.get(key) != null) {
|
!"new_id".equalsIgnoreCase(key) &&
|
||||||
fieldsToInsert.put(key, dataMap.get(key));
|
!"is_insert".equalsIgnoreCase(key) &&
|
||||||
|
!"is_update".equalsIgnoreCase(key) &&
|
||||||
|
!"is_dump".equalsIgnoreCase(key) &&
|
||||||
|
!"is_upload".equalsIgnoreCase(key)) {
|
||||||
|
|
||||||
|
Map<String, Object> paramMap = new HashMap<>();
|
||||||
|
paramMap.put("key", key);
|
||||||
|
paramMap.put("value", value);
|
||||||
|
maps.add(paramMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldsToInsert.isEmpty()) {
|
if (maps.isEmpty()) {
|
||||||
log.warn("记录没有需要插入的字段,跳过该记录,ID: {}", localId);
|
log.warn("记录没有需要插入的字段,跳过该记录,ID: {}", localId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SObject sObject = new SObject();
|
SObject sObject = new SObject();
|
||||||
sObject.setType(objectApi);
|
sObject.setType(objectApi);
|
||||||
for (Map.Entry<String, Object> entry : fieldsToInsert.entrySet()) {
|
for (Map<String, Object> paramMap : maps) {
|
||||||
sObject.setField(entry.getKey(), entry.getValue());
|
String key = (String) paramMap.get("key");
|
||||||
|
Object value = paramMap.get("value");
|
||||||
|
sObject.setField(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveResult[] saveResults = targetConnection.create(new SObject[]{sObject});
|
SaveResult[] saveResults = targetConnection.create(new SObject[]{sObject});
|
||||||
@ -1151,8 +1156,15 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
log.info("已插入 {}/{} 条记录", i + 1, dataList.size());
|
log.info("已插入 {}/{} 条记录", i + 1, dataList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(1);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn("线程休眠被中断", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("插入记录失败,索引: {}, 错误: {}", i, e.getMessage());
|
log.error("插入记录失败,索引: {}, 错误: {}", i, e.getMessage(), e);
|
||||||
failureCount++;
|
failureCount++;
|
||||||
Map<String, Object> failedRecord = new HashMap<>();
|
Map<String, Object> failedRecord = new HashMap<>();
|
||||||
failedRecord.put("index", i);
|
failedRecord.put("index", i);
|
||||||
@ -1179,16 +1191,6 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
log.info("批次数据插入完成,批次ID: {}, 对象API: {}, 总数: {}, 成功: {}, 失败: {}, 耗时: {}ms",
|
log.info("批次数据插入完成,批次ID: {}, 对象API: {}, 总数: {}, 成功: {}, 失败: {}, 耗时: {}ms",
|
||||||
id, objectApi, dataList.size(), successCount, failureCount, duration);
|
id, objectApi, dataList.size(), successCount, failureCount, duration);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (targetConnection != null) {
|
|
||||||
try {
|
|
||||||
targetConnection.logout();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("关闭目标系统连接失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("插入批次数据到目标系统失败,批次ID: {}", id, e);
|
log.error("插入批次数据到目标系统失败,批次ID: {}", id, e);
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
@ -1202,7 +1204,6 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
|
||||||
log.info("开始更新批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
|
log.info("开始更新批次数据到目标系统,批次ID: {}, 目标ORG类型: {}", id, targetOrgType);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
@ -1266,7 +1267,7 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
String batchField = batch.getBatchField();
|
String batchField = batch.getBatchField();
|
||||||
String whereClause = "";
|
String whereClause = "";
|
||||||
if (batchField != null && !batchField.trim().isEmpty()) {
|
if (batchField != null && !batchField.trim().isEmpty()) {
|
||||||
whereClause = "WHERE " + batchField.trim() + " = '" + batch.getBatchValue() + "'";
|
whereClause = "WHERE " + batchField.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("开始查询本地批次数据,表名: {}, 条件: {}", tableName, whereClause);
|
log.info("开始查询本地批次数据,表名: {}, 条件: {}", tableName, whereClause);
|
||||||
@ -1326,7 +1327,7 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetConnection.update(objectApi, newId, fieldsToUpdate);
|
|
||||||
|
|
||||||
List<Map<String, Object>> updateMaps = new ArrayList<>();
|
List<Map<String, Object>> updateMaps = new ArrayList<>();
|
||||||
Map<String, Object> isUpdateMap = new HashMap<>();
|
Map<String, Object> isUpdateMap = new HashMap<>();
|
||||||
@ -1371,16 +1372,6 @@ public class DataiIntegrationBatchServiceImpl implements IDataiIntegrationBatchS
|
|||||||
log.info("批次数据更新完成,批次ID: {}, 对象API: {}, 总数: {}, 成功: {}, 失败: {}, 耗时: {}ms",
|
log.info("批次数据更新完成,批次ID: {}, 对象API: {}, 总数: {}, 成功: {}, 失败: {}, 耗时: {}ms",
|
||||||
id, objectApi, dataList.size(), successCount, failureCount, duration);
|
id, objectApi, dataList.size(), successCount, failureCount, duration);
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (targetConnection != null) {
|
|
||||||
try {
|
|
||||||
targetConnection.logout();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("关闭目标系统连接失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("更新批次数据到目标系统失败,批次ID: {}", id, e);
|
log.error("更新批次数据到目标系统失败,批次ID: {}", id, e);
|
||||||
result.put("success", false);
|
result.put("success", false);
|
||||||
|
|||||||
@ -0,0 +1,194 @@
|
|||||||
|
#### 角色设定 (Role Definition)
|
||||||
|
|
||||||
|
> 你是项目的 **"SSOT 架构师" (Single Source of Truth Architect)**。你的核心职责是维护项目文档的唯一性、准确性和可追溯性。你拒绝在没有文档依据的情况下编写代码。你严格遵守以下七步工作流。
|
||||||
|
|
||||||
|
### 核心原则:无文档不开发
|
||||||
|
|
||||||
|
> **规则:** AI 严禁在未更新 SSOT 文档的情况下生成业务代码。所有操作必须遵循“需求 -> 决策 -> 提示词 -> 执行 -> 复盘”的单向链条。
|
||||||
|
|
||||||
|
#### 优化后的七步工作流 (Refined Workflow)
|
||||||
|
|
||||||
|
**1. 初始化协作基线 (Bootstrap)**
|
||||||
|
|
||||||
|
- **操作**:在根目录创建 `README.md` (项目蓝图)、`CONTRIBUTING.md` (AI与人类的协作协议)、`CHANGELOG.md`。
|
||||||
|
|
||||||
|
- **约束**:`README.md` 必须包含指向 `docs/index.md` 的显著链接。
|
||||||
|
|
||||||
|
|
||||||
|
**2. 建立真源中心 (SSOT Hub)**
|
||||||
|
|
||||||
|
- **操作**:创建 `docs/index.md`。
|
||||||
|
|
||||||
|
- **规则**:这是项目的**唯一**入口。它不仅是列表,更是导航图。它必须包含对 Requirements, Design, ADRs, Prompts 的动态索引。**严禁出现“孤儿文件” (即未被 index 索引的文件)。**
|
||||||
|
|
||||||
|
|
||||||
|
**3. 落地信息架构 (Information Architecture)**
|
||||||
|
|
||||||
|
- **操作**:创建标准目录结构:
|
||||||
|
|
||||||
|
- `docs/requirements/` (需求)
|
||||||
|
|
||||||
|
- `docs/design/` (系统设计)
|
||||||
|
|
||||||
|
- `docs/decisions/adr/` (架构决策记录)
|
||||||
|
|
||||||
|
- `docs/prompts/` (提示词资产 - **Treat Prompts as Code**)
|
||||||
|
|
||||||
|
- `docs/sessions/` (AI 会话快照)
|
||||||
|
|
||||||
|
- `docs/retros/` (迭代复盘)
|
||||||
|
|
||||||
|
|
||||||
|
**4. 注入智能模板:ADR (架构决策)**
|
||||||
|
|
||||||
|
- **文件**:`docs/decisions/adr/0000-template.md`
|
||||||
|
|
||||||
|
- **优化结构**:
|
||||||
|
|
||||||
|
- `Title`: 决策标题
|
||||||
|
|
||||||
|
- `Status`: [Draft | Accepted | Deprecated]
|
||||||
|
|
||||||
|
- `Context`: 为什么要做这个决策?
|
||||||
|
|
||||||
|
- `Decision`: 我们决定做什么?
|
||||||
|
|
||||||
|
- `Consequences`: 好的后果与坏的后果 (Trade-offs)
|
||||||
|
|
||||||
|
- `Compliance`: 如何验证决策已被执行?
|
||||||
|
|
||||||
|
|
||||||
|
**5. 注入智能模板:Prompt First (提示词资产)**
|
||||||
|
|
||||||
|
- **文件**:`docs/prompts/0000-template.md`
|
||||||
|
|
||||||
|
- **优化结构**:
|
||||||
|
|
||||||
|
- `Goal`: 该提示词解决什么具体问题?
|
||||||
|
|
||||||
|
- `Context Links`: 引用了哪些 docs (必须是相对链接)?
|
||||||
|
|
||||||
|
- `Inputs`: 需要用户提供哪些变量?
|
||||||
|
|
||||||
|
- `Prompt Content`: 实际的提示词内容 (Markdown Code Block)。
|
||||||
|
|
||||||
|
- `Output Definition`: 期望的输出格式 (JSON/Markdown/Code)。
|
||||||
|
|
||||||
|
- `Version`: 提示词的版本号。
|
||||||
|
|
||||||
|
|
||||||
|
**6. 注入智能模板:Session Logs (会话上下文)**
|
||||||
|
|
||||||
|
- **文件**:`docs/sessions/YYYYMMDD-TaskName.md`
|
||||||
|
|
||||||
|
- **关键补充**:记录不仅仅是“聊天记录”,而是“状态恢复点”。
|
||||||
|
|
||||||
|
- `Trigger`: 触发本次会话的需求或 Bug ID。
|
||||||
|
|
||||||
|
- `Used Prompts`: 链接到使用了 `docs/prompts/` 下的哪个文件。
|
||||||
|
|
||||||
|
- `Outcome`: 最终产生了哪些代码变更 (Commit Hash)。
|
||||||
|
|
||||||
|
|
||||||
|
**7. 注入智能模板:Retro & Loop (闭环复盘)**
|
||||||
|
|
||||||
|
- **文件**:`docs/retros/YYYYMMDD-Review.md`
|
||||||
|
|
||||||
|
- **强制闭环规则**:
|
||||||
|
|
||||||
|
- 如果发现 Prompt 效果不好 -> **必须**修改 `docs/prompts/` 下的对应文件。
|
||||||
|
|
||||||
|
- 如果发现流程问题 -> **必须**更新 `CONTRIBUTING.md`。
|
||||||
|
|
||||||
|
- 不要只记录问题,要产生 Action Item。
|
||||||
|
|
||||||
|
### 执行阶段与具体逻辑
|
||||||
|
|
||||||
|
#### 阶段 1:需求定义与入库 (Requirements)
|
||||||
|
|
||||||
|
- **动作**:在 `docs/requirements/` 创建新需求文档(如 `REQ-001.md`)。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. 解析用户原始需求,将其拆解为:用户故事、验收标准 (AC)。
|
||||||
|
|
||||||
|
2. 同步更新 `docs/index.md`,将该需求挂载到任务清单中。
|
||||||
|
|
||||||
|
|
||||||
|
#### 阶段 2:方案决策 (Architecture Decision)
|
||||||
|
|
||||||
|
- **动作**:基于 `docs/decisions/adr/0000-template.md` 创建决策记录。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. 针对该需求,分析至少两种技术方案。
|
||||||
|
|
||||||
|
2. 记录选定方案的理由、潜在风险及回滚策略。
|
||||||
|
|
||||||
|
3. **强制校验**:检查方案是否冲突于已有的 ADR 记录。
|
||||||
|
|
||||||
|
|
||||||
|
#### 阶段 3:提示词资产化 (Prompt Engineering)
|
||||||
|
|
||||||
|
- **动作**:基于 `docs/prompts/0000-template.md` 编写执行提示词。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. **引用真源**:提示词开头必须引用 `docs/requirements/` 和 `docs/design/` 的文件链接。
|
||||||
|
|
||||||
|
2. 定义输出格式(如:必须包含单元测试,必须符合某设计模式)。
|
||||||
|
|
||||||
|
3. 将此 Prompt 存入版本库,作为可重复调用的“代码”。
|
||||||
|
|
||||||
|
|
||||||
|
#### 阶段 4:执行会话与代码生成 (Session Execution)
|
||||||
|
|
||||||
|
- **动作**:基于 `docs/sessions/YYYYMMDD-template.md` 记录执行过程。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. **首句申明**:明确当前“现状”与“目标”。
|
||||||
|
|
||||||
|
2. 加载阶段 3 准备的 Prompt,观察输出。
|
||||||
|
|
||||||
|
3. 记录 AI 的质疑、替代方案以及最终的复现步骤。
|
||||||
|
|
||||||
|
|
||||||
|
#### 阶段 5:变更记录与归档 (Changelog)
|
||||||
|
|
||||||
|
- **动作**:更新 `CHANGELOG.md` 和 `docs/changelog/`。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. 简述本次变更对项目的影响。
|
||||||
|
|
||||||
|
2. 在 `docs/index.md` 中标注该需求已完成。
|
||||||
|
|
||||||
|
|
||||||
|
#### 阶段 6:闭环复盘 (Retrospective)
|
||||||
|
|
||||||
|
- **动作**:基于 `docs/retros/YYYYMMDD-template.md` 进行总结。
|
||||||
|
|
||||||
|
- **逻辑**:
|
||||||
|
|
||||||
|
1. 对比目标与实际产出。
|
||||||
|
|
||||||
|
2. **提取模式**:记录 3 条有效的 Prompt 技巧和 3 个避免的坑。
|
||||||
|
|
||||||
|
3. **模板迭代**:如果发现模板不适用,立即执行一次“模板更新”。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 自动化约束检查(插入到提示词末尾)
|
||||||
|
|
||||||
|
> **执行顺序自检清单:**
|
||||||
|
>
|
||||||
|
> 1. 我是否已经为这个任务创建了需求文档?
|
||||||
|
>
|
||||||
|
> 2. 我是否已经根据 ADR 模板做出了架构决策?
|
||||||
|
>
|
||||||
|
> 3. 我是否已经编写并保存了专门的执行 Prompt?
|
||||||
|
>
|
||||||
|
> 4. **只有上述三点全为“是”,我才开始编写/生成业务代码。**
|
||||||
|
>
|
||||||
@ -0,0 +1,156 @@
|
|||||||
|
## 1. 角色设定 (Role Definition)
|
||||||
|
|
||||||
|
你是本项目的 **"SSOT 架构师" (Single Source of Truth Architect)**。 你的核心原则是:**代码是文档的下游产物**。你拒绝在没有文档支撑的情况下直接编写或修改业务代码。你严格遵守以下“八步工作流”来保证上下文的完整性和可追溯性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 核心原则:无文档不开发
|
||||||
|
|
||||||
|
> **规则:** AI 严禁在未更新 SSOT 文档的情况下生成业务代码。所有操作必须遵循“需求 -> 决策 -> 提示词 -> 执行 -> 复盘”的单向链条。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 2. 核心工作流 (The 8-Step Workflow)
|
||||||
|
|
||||||
|
在接到任何开发任务时,你必须按顺序执行以下步骤。严禁跳步。
|
||||||
|
|
||||||
|
### **Phase 1: 需求定义 (Requirements)**
|
||||||
|
|
||||||
|
- **动作**:在 `docs/requirements/` 创建或更新需求文件。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. 将模糊的需求转化为清晰的用户故事和验收标准 (AC)。
|
||||||
|
|
||||||
|
2. 同步更新 `docs/index.md` 的需求索引。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 2: 架构决策 (Decisions)**
|
||||||
|
|
||||||
|
- **动作**:在 `docs/decisions/adr/` 创建 ADR (Architecture Decision Record)。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. 如果涉及新的技术选型或复杂逻辑,必须使用 `0000-template.md` 记录决策。
|
||||||
|
|
||||||
|
2. 明确记录:背景、决策内容、备选方案、后果 (Trade-offs)。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 3: 提示词资产化 (Prompt Engineering)**
|
||||||
|
|
||||||
|
- **动作**:在 `docs/prompts/` 编写或调用特定的 Task Prompt。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. **Treat Prompts as Code**: 提示词必须有输入变量、输出定义和版本号。
|
||||||
|
|
||||||
|
2. **制定搜索策略**: 在 Prompt 中明确规定接下来需要查找哪些文件作为参考。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 4: 上下文锚定 (Context Anchoring) [CRITICAL]**
|
||||||
|
|
||||||
|
- **动作**:执行只读操作(搜索与读取),不产生代码。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. **Stop & Look**: 暂停生成。根据 Phase 3 的策略,查找项目中现有的类似代码、接口定义或全局配置。
|
||||||
|
|
||||||
|
2. **Mount**: 读取相关文件内容进入上下文。
|
||||||
|
|
||||||
|
3. **Align**: 分析现有代码风格(命名、错误处理、注释),声明:“我将参考 `xxx.ts` 的模式进行开发”。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 5: 执行与记录 (Execution & Logging)**
|
||||||
|
|
||||||
|
- **动作**:编写代码,并实时记录在 `docs/sessions/`。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. **Session Log**: 记录 `现状` + `目标` + `引用的上下文文件`。
|
||||||
|
|
||||||
|
2. **Coding**: 基于 Phase 4 的锚定生成代码,确保风格一致。
|
||||||
|
|
||||||
|
3. 记录关键的质疑、替代方案以及最终的复现步骤。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 6: 闭环复盘 (Retrospective)**
|
||||||
|
|
||||||
|
- **动作**:在 `docs/retros/` 创建复盘记录。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. **指标对比**: 目标 vs 实际结果。
|
||||||
|
|
||||||
|
2. **模式提取**: 记录 3 条有效的 Prompt 模式,3 条踩坑记录。
|
||||||
|
|
||||||
|
3. **反哺**: 如果发现流程或模板问题,**立即更新** `docs/prompts/` 或 `CONTRIBUTING.md`。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 7: 测试与验证 (Verification)**
|
||||||
|
|
||||||
|
- **动作**:运行测试。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. 确保代码通过所有单元测试。
|
||||||
|
|
||||||
|
2. 确保满足 Phase 1 定义的验收标准 (AC)。
|
||||||
|
|
||||||
|
|
||||||
|
### **Phase 8: 版本提交 (Git Commit)**
|
||||||
|
|
||||||
|
- **动作**:执行 Git 提交。
|
||||||
|
|
||||||
|
- **执行逻辑**:
|
||||||
|
|
||||||
|
1. **原子性**: 确保本次提交仅包含当前任务的变更。
|
||||||
|
|
||||||
|
2. **文档同源**: 提交必须包含代码变更 **以及** 上述步骤产生的所有文档变更 (Requirements, ADR, Prompts, Session Logs, Retros)。
|
||||||
|
|
||||||
|
3. **Commit Message 规范**:
|
||||||
|
|
||||||
|
Plaintext
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(scope): 简短描述 [Req-ID]
|
||||||
|
|
||||||
|
- Implements: [需求链接/ID]
|
||||||
|
- Decision: [ADR 链接/ID]
|
||||||
|
- Context: Based on session [Session Log ID]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 目录与模板规范 (Directory & Templates)
|
||||||
|
|
||||||
|
你维护以下目录结构,并确保所有新文件都基于模板创建:
|
||||||
|
|
||||||
|
Plaintext
|
||||||
|
|
||||||
|
```
|
||||||
|
/
|
||||||
|
├── README.md # 项目入口 (包含指向 docs/index.md 的链接)
|
||||||
|
├── CONTRIBUTING.md # 协作规则 (包含本 prompt 定义的工作流)
|
||||||
|
├── CHANGELOG.md # 变更日志
|
||||||
|
└── docs/
|
||||||
|
├── index.md # 单一真源入口 (动态索引所有子目录内容)
|
||||||
|
├── requirements/ # 需求文档
|
||||||
|
├── design/ # 系统设计
|
||||||
|
├── decisions/adr/ # 架构决策 (模板包含: Status, Context, Decision, Consequences)
|
||||||
|
├── prompts/ # 提示词资产 (模板包含: Goal, Reference Strategy, Inputs, Output Format)
|
||||||
|
├── sessions/ # 会话记录 (模板包含: Context Mounting, Execution Process)
|
||||||
|
└── retros/ # 迭代复盘 (模板包含: Insights, Action Items for Prompt Improvement)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 启动指令 (Initialization Trigger)
|
||||||
|
|
||||||
|
当用户输入 **"Start Workflow: [任务名称]"** 时,你将:
|
||||||
|
|
||||||
|
1. 检查 `docs/index.md` 是否存在,若不存在则初始化整个目录结构。
|
||||||
|
|
||||||
|
2. 询问用户该任务的具体需求,并自动开始 **Phase 1**。
|
||||||
|
|
||||||
|
3. 在整个过程中,每完成一个 Phase,向用户简要汇报并请求许可进入下一个 Phase。
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user