@betterdanlins/ai-memory 0.4.0 → 0.6.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 +37 -1
- package/README.zh-CN.md +37 -1
- package/bin/cli.js +9 -2
- package/package.json +1 -1
- package/src/framework.js +52 -13
- package/src/managed-blocks.js +62 -0
- package/src/manifest.js +7 -1
- package/templates/claude/.claude/commands/update-memory.md +4 -3
- package/templates/claude/.claude/skills/memory-update/SKILL.md +1 -1
- package/templates/claude/.claude/skills/model-routing/SKILL.md +1 -1
- package/templates/claude/CLAUDE.md +6 -1
- package/templates/codex/.agents/skills/memory-update/SKILL.md +1 -1
- package/templates/codex/.agents/skills/model-routing/SKILL.md +1 -1
- package/templates/codex/AGENTS.md +6 -1
- package/templates/common/.ai/README.md +19 -5
- package/templates/common/.ai/memory/MEMORY.md +12 -7
- package/templates/common/.ai/memory/feedback.md +11 -2
- package/templates/common/.ai/memory/user-profile.md +19 -7
- package/templates/common/.ai/skills/feature-design.md +1 -1
- package/templates/common/.ai/skills/memory-update.md +10 -0
- package/templates/common/.ai/skills/project-inception.md +1 -1
- /package/templates/common/.ai/runs/{.gitignore → .gitignore.template} +0 -0
package/README.md
CHANGED
|
@@ -44,6 +44,22 @@ An initialized project cannot be initialized again. A newer CLI first uses `upda
|
|
|
44
44
|
|
|
45
45
|
## Versions and compatibility
|
|
46
46
|
|
|
47
|
+
### v0.6.0 — actionable memory loading
|
|
48
|
+
|
|
49
|
+
- Turns `user-profile.md` and `feedback.md` from passive import files into core session context. Every session loads the profile, durable collaboration rules, project state, and the latest session entry in a fixed order.
|
|
50
|
+
- Adds an explicit memory write router: confirmed cross-project preferences go to `user-profile.md`, reusable user corrections go to `feedback.md`, project facts stay in project memory, and one-off instructions are not persisted.
|
|
51
|
+
- Forbids inferred personal profiling and credential storage. Sensitive information is omitted by default and requires both an explicit request and confirmation of repository visibility; newer feedback replaces conflicting older rules.
|
|
52
|
+
- Adds task-specific loading routes so agents do not read the whole knowledge base. The architecture methodology is now explicitly loaded only by project inception and feature design.
|
|
53
|
+
- Connects Claude and Codex model-routing skills to their concrete native agent names, removing the implicit tier-to-executor gap.
|
|
54
|
+
|
|
55
|
+
### v0.5.0 — managed entry blocks
|
|
56
|
+
|
|
57
|
+
- Wraps the framework-owned sections of generated `AGENTS.md` and `CLAUDE.md` in explicit `ai-memory:managed` markers. Future updates replace only that block and preserve project commands and custom rules outside it.
|
|
58
|
+
- An unchanged v0.4.0 entry file can migrate to marked blocks automatically because its generated baseline hash proves it has not been edited. A modified unmarked v0.4.0 file requires one manual merge; after markers are established, later framework updates no longer conflict with user-section changes.
|
|
59
|
+
- Missing, duplicated, or malformed markers fail conservatively instead of triggering a whole-file overwrite. Managed-block updates also re-check the current file hash immediately before writing.
|
|
60
|
+
- `.claude/settings.json` remains a mixed JSON file and still requires review when both the framework and user changed it; Markdown markers are intentionally not applied to JSON.
|
|
61
|
+
- Fixes npm's automatic `.gitignore` template renaming and safely replaces the unchanged v0.4.0 `.ai/runs/.npmignore`; a locally edited obsolete file still requires review.
|
|
62
|
+
|
|
47
63
|
### v0.4.0 — staged model routing and verified handoffs
|
|
48
64
|
|
|
49
65
|
- Adds opt-in `inherit`, `balanced`, and `quality` profiles. New and upgraded projects default to `inherit`, so installing v0.4.0 does not silently increase model cost or change v0.3.0 workflow depth.
|
|
@@ -73,6 +89,24 @@ npx @betterdanlins/ai-memory@0.4.0 models configure --profile balanced
|
|
|
73
89
|
|
|
74
90
|
After the update, the profile remains `inherit` until explicitly changed. Do not re-run `init` on an existing v0.3.0 project. If dry-run reports merge or review items, merge them with the generated v0.4.0 files as references, then run dry-run again.
|
|
75
91
|
|
|
92
|
+
### Upgrade from v0.4.0 to v0.5.0
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npx @betterdanlins/ai-memory@0.5.0 update --dry-run
|
|
96
|
+
npx @betterdanlins/ai-memory@0.5.0 update --yes
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If `AGENTS.md` or `CLAUDE.md` is still the unchanged v0.4.0 generated version, it migrates automatically. If either unmarked file was customized, dry-run reports `merge`; compare it with a fresh v0.5.0 reference, keep project-specific content in the user block, and retry. Once markers exist, edit only outside `<!-- ai-memory:managed:start/end -->`.
|
|
100
|
+
|
|
101
|
+
### Upgrade from v0.5.0 to v0.6.0
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx @betterdanlins/ai-memory@0.6.0 update --dry-run
|
|
105
|
+
npx @betterdanlins/ai-memory@0.6.0 update --yes
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The managed sections of `AGENTS.md` / `CLAUDE.md` and unchanged framework files update automatically. Existing `user-profile.md`, `feedback.md`, project state, and feature memory remain user-owned and are never overwritten. The new entry and memory-update protocols start using that existing content immediately; richer profile/feedback starter structures are used only for fresh or still-missing files.
|
|
109
|
+
|
|
76
110
|
## What it generates
|
|
77
111
|
|
|
78
112
|
```
|
|
@@ -82,7 +116,7 @@ After the update, the profile remains `inherit` until explicitly changed. Do not
|
|
|
82
116
|
├── config/
|
|
83
117
|
│ └── model-routing.json # inherit/balanced/quality stage routing; user-owned
|
|
84
118
|
├── memory/
|
|
85
|
-
│ ├── MEMORY.md #
|
|
119
|
+
│ ├── MEMORY.md # core/on-demand memory loading index
|
|
86
120
|
│ ├── project-state.md # stack, current version, requirement progress
|
|
87
121
|
│ ├── session-log.md # rolling log of progress & next steps
|
|
88
122
|
│ ├── user-profile.md # background, preferences, communication style
|
|
@@ -141,12 +175,14 @@ The generator is a small set of focused modules:
|
|
|
141
175
|
- **render** — substitutes `{{variable}}` placeholders and throws on any undefined variable, so a broken template fails loudly instead of shipping `{{...}}`.
|
|
142
176
|
- **scaffold** — validates safe destinations and symbolic links, resolves conflicts, and reads/renders the complete plan in memory before writing; it also validates `--import` and pulls `user-profile` / `feedback` from it (falling back to the template with an explicit report when an individual source file is missing).
|
|
143
177
|
- **framework metadata** — a fresh init records framework/schema versions, ownership, and generated hashes; update uses them to distinguish safe updates from user changes. Metadata-free v0.1 projects are planned conservatively as legacy installations.
|
|
178
|
+
- **managed entry blocks** — Markdown entry files update only their validated framework block. Unmarked or malformed customized files remain manual merges; JSON settings keep conservative whole-file review semantics.
|
|
144
179
|
- **model routing** — optional profiles map existing workflow stages to premium, standard, economy, inherited, or no-model execution. Claude and Codex adapters use native custom-agent configuration; routing never creates extra S/M/L stages.
|
|
145
180
|
- **workflow handoff** — a local manifest references formal requirements/design/plan files by path and SHA-256. Verification fails closed on stale inputs, unresolved decisions, changed routing, path escape, or symbolic links.
|
|
146
181
|
|
|
147
182
|
## Design principles
|
|
148
183
|
|
|
149
184
|
- **Single source** — content lives only in `.ai/`; `.claude/` and `.agents/` are trigger wrappers.
|
|
185
|
+
- **Actionable scoped memory** — every session loads a small core set; durable user preferences, reusable feedback, project facts, and feature decisions have separate write destinations, while task artifacts remain on-demand.
|
|
150
186
|
- **Engineering-node memory** — write session-log entries for independently verifiable features/phases, durable decisions, status changes, or tool handoffs, avoiding noise from tiny implementation steps.
|
|
151
187
|
- **Dual requirement directories** — human draft (`draft/`) → AI final (`final/`) behind a mandatory critic gate.
|
|
152
188
|
- **Project engineering baseline** — 0-to-1 projects establish language-agnostic system, data, quality-attribute, and deployment baselines once; ordinary features record only deltas.
|
package/README.zh-CN.md
CHANGED
|
@@ -44,6 +44,22 @@ npx @betterdanlins/ai-memory models configure --profile balanced
|
|
|
44
44
|
|
|
45
45
|
## 版本与兼容性
|
|
46
46
|
|
|
47
|
+
### v0.6.0 —— 可执行的记忆加载闭环
|
|
48
|
+
|
|
49
|
+
- 将 `user-profile.md` 和 `feedback.md` 从被动导入文件接入核心会话上下文。每次会话按固定顺序加载用户画像、长期协作规则、项目状态和最新 session 条目。
|
|
50
|
+
- 增加明确的记忆写入路由:已确认的跨项目偏好进入 `user-profile.md`,可复用的用户纠正进入 `feedback.md`,项目事实留在项目记忆,一次性要求不落盘。
|
|
51
|
+
- 禁止推断个人画像和保存凭据。敏感信息默认不写,只有用户明确要求并确认仓库可见性后才能记录;新反馈与旧规则冲突时替换旧规则。
|
|
52
|
+
- 增加按任务加载路由,避免 Agent 一次性读取整个知识库;架构方法论只在项目启动和功能设计时明确加载。
|
|
53
|
+
- Claude 与 Codex 的模型路由 skill 现在显式映射实际原生代理名称,补齐等级到执行者之间的隐式断点。
|
|
54
|
+
|
|
55
|
+
### v0.5.0 —— 入口文件受管区块
|
|
56
|
+
|
|
57
|
+
- 为生成的 `AGENTS.md` 和 `CLAUDE.md` 框架区域增加明确的 `ai-memory:managed` 标记。后续升级只替换该区块,区块外的项目命令和自定义规则保持不变。
|
|
58
|
+
- 未修改的 v0.4.0 入口文件可依据生成基线哈希自动迁移为带标记结构。已经修改且没有标记的 v0.4.0 文件需要一次人工合并;标记建立后,后续框架升级不再与用户区块修改冲突。
|
|
59
|
+
- 标记缺失、重复或格式损坏时保守拒绝自动合并,不会退化为整文件覆盖。写入受管区块前还会再次核对当前文件哈希。
|
|
60
|
+
- `.claude/settings.json` 仍是混合 JSON 文件;框架和用户都修改时继续要求审查,不会向 JSON 强行加入 Markdown 标记。
|
|
61
|
+
- 修复 npm 自动改名 `.gitignore` 模板的问题,并安全替换未修改的 v0.4.0 `.ai/runs/.npmignore`;若该废弃文件被本地修改,仍要求人工审查。
|
|
62
|
+
|
|
47
63
|
### v0.4.0 —— 分阶段模型路由与可靠交接
|
|
48
64
|
|
|
49
65
|
- 新增可选的 `inherit`、`balanced`、`quality` profile。新项目和升级项目默认保持 `inherit`,安装 v0.4.0 不会静默增加模型成本,也不会改变 v0.3.0 的工作流深度。
|
|
@@ -73,6 +89,24 @@ npx @betterdanlins/ai-memory@0.4.0 models configure --profile balanced
|
|
|
73
89
|
|
|
74
90
|
升级完成后 profile 仍为 `inherit`,只有显式配置才会改变。不要在已有 v0.3.0 项目重新运行 `init`。若 dry-run 出现 merge/review 项,应以新生成的 v0.4.0 文件为参考人工合并,然后重新执行 dry-run。
|
|
75
91
|
|
|
92
|
+
### 从 v0.4.0 升级到 v0.5.0
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npx @betterdanlins/ai-memory@0.5.0 update --dry-run
|
|
96
|
+
npx @betterdanlins/ai-memory@0.5.0 update --yes
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
如果 `AGENTS.md` 或 `CLAUDE.md` 仍是未修改的 v0.4.0 生成版本,会自动迁移。若无标记入口已被定制,dry-run 会报告 `merge`;应对照全新 v0.5.0 参考文件,把项目内容放进 user 区块后重试。标记建立后,只在 `<!-- ai-memory:managed:start/end -->` 之外编辑。
|
|
100
|
+
|
|
101
|
+
### 从 v0.5.0 升级到 v0.6.0
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx @betterdanlins/ai-memory@0.6.0 update --dry-run
|
|
105
|
+
npx @betterdanlins/ai-memory@0.6.0 update --yes
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`AGENTS.md` / `CLAUDE.md` 的受管区块和未修改的框架文件会自动更新。已有 `user-profile.md`、`feedback.md`、项目状态和 feature 记忆继续属于用户资产,绝不覆盖;新的进场和 memory-update 协议会立即使用已有内容。更完整的画像/反馈初始结构只用于全新项目或仍缺失的文件。
|
|
109
|
+
|
|
76
110
|
## 生成什么
|
|
77
111
|
|
|
78
112
|
```
|
|
@@ -82,7 +116,7 @@ npx @betterdanlins/ai-memory@0.4.0 models configure --profile balanced
|
|
|
82
116
|
├── config/
|
|
83
117
|
│ └── model-routing.json # inherit/balanced/quality 阶段路由;属于用户配置
|
|
84
118
|
├── memory/
|
|
85
|
-
│ ├── MEMORY.md #
|
|
119
|
+
│ ├── MEMORY.md # 核心/按需记忆加载索引
|
|
86
120
|
│ ├── project-state.md # 技术栈、当前版本、需求进度
|
|
87
121
|
│ ├── session-log.md # 进展与下一步的流水日志
|
|
88
122
|
│ ├── user-profile.md # 背景、偏好、沟通方式
|
|
@@ -141,12 +175,14 @@ AGENTS.md + .agents/ + .codex/# Codex:skills 与分层自定义 agents
|
|
|
141
175
|
- **render** —— 替换 `{{变量}}` 占位符,遇到任何未定义变量即抛错,让坏掉的模板大声失败,而不是把 `{{...}}` 发出去。
|
|
142
176
|
- **scaffold** —— 预检安全目标路径和符号链接,处理冲突并在内存中完成全部读取/渲染后再逐个写入;提供 `--import` 时先校验导入目录,再从中拉取 `user-profile` / `feedback`(单个源文件缺失则回退到模板并明确报告)。
|
|
143
177
|
- **framework metadata** —— 全新 init 记录 framework/schema 版本、文件所有权和生成哈希;update 据此区分安全更新与用户修改。无元数据的 v0.1 项目按 legacy 保守规划。
|
|
178
|
+
- **managed entry blocks** —— Markdown 入口只更新通过校验的框架区块;无标记或标记损坏的定制文件仍人工合并,JSON settings 继续采用保守整文件审查。
|
|
144
179
|
- **model routing** —— 可选 profile 把现有阶段映射为 premium、standard、economy、inherit 或无模型执行;Claude/Codex 使用原生自定义 agent 配置,路由不会增加 S/M/L 阶段。
|
|
145
180
|
- **workflow handoff** —— 本地清单只用路径和 SHA-256 引用正式需求/设计/计划;输入过期、未决问题、路由变化、路径越界或符号链接都会关闭式失败。
|
|
146
181
|
|
|
147
182
|
## 设计原则
|
|
148
183
|
|
|
149
184
|
- **单一源** —— 正文只在 `.ai/`;`.claude/`、`.agents/` 只是触发包装。
|
|
185
|
+
- **可执行的分域记忆** —— 每次会话只加载小型核心集合;长期用户偏好、可复用反馈、项目事实和功能决策分别写入不同位置,任务产物继续按需加载。
|
|
150
186
|
- **工程节点记忆** —— 只在可独立验收的功能/阶段、关键决策、状态变化或工具切换时写 session-log,避免细碎步骤制造噪声。
|
|
151
187
|
- **需求双目录** —— 人工粗稿(`draft/`)→ AI 定稿(`final/`),中间隔一道强制 critic 门。
|
|
152
188
|
- **项目工程基线** —— 0→1 项目先建立语言无关的系统、数据、质量属性和部署基线;普通功能只记录增量,不重复设计全局架构。
|
package/bin/cli.js
CHANGED
|
@@ -119,7 +119,7 @@ program
|
|
|
119
119
|
if (r.imported.length) for (const d of r.imported) console.log(` 已导入 ${d}`);
|
|
120
120
|
if (r.fallback.length) for (const d of r.fallback) console.log(` 导入源缺失,使用模板 ${d}`);
|
|
121
121
|
if (r.skipped.length) for (const d of r.skipped) console.log(` 跳过 ${d}`);
|
|
122
|
-
console.log('下一步:打开项目让 agent 读 .ai/
|
|
122
|
+
console.log('下一步:打开项目让 agent 读 .ai/README.md;把项目命令补进 CLAUDE.md/AGENTS.md 的 user 区块。');
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
const models = program.command('models').description('查看或配置阶段模型路由');
|
|
@@ -203,8 +203,9 @@ program
|
|
|
203
203
|
printUpdatePlan(plan);
|
|
204
204
|
if (opts.yes) {
|
|
205
205
|
const result = await applyFrameworkUpdate({ targetDir: process.cwd(), templatesRoot: TEMPLATES, plan });
|
|
206
|
-
console.log(`安全更新完成:写入 ${result.written.length}`);
|
|
206
|
+
console.log(`安全更新完成:写入 ${result.written.length},移除 ${result.removed.length}`);
|
|
207
207
|
for (const dest of result.written) console.log(` ${dest}`);
|
|
208
|
+
for (const dest of result.removed) console.log(` 移除 ${dest}`);
|
|
208
209
|
}
|
|
209
210
|
});
|
|
210
211
|
|
|
@@ -216,6 +217,10 @@ program.parseAsync().catch((e) => {
|
|
|
216
217
|
if (e.name === 'ScaffoldError') {
|
|
217
218
|
console.error(`已写入 ${e.summary.written.length}:`);
|
|
218
219
|
for (const d of e.summary.written) console.error(` ${d}`);
|
|
220
|
+
if (e.summary.removed?.length) {
|
|
221
|
+
console.error(`已移除 ${e.summary.removed.length}:`);
|
|
222
|
+
for (const d of e.summary.removed) console.error(` ${d}`);
|
|
223
|
+
}
|
|
219
224
|
console.error(`尚未写入 ${e.notWritten.length}:`);
|
|
220
225
|
for (const d of e.notWritten) console.error(` ${d}`);
|
|
221
226
|
if (e.summary.skipped.length) {
|
|
@@ -238,6 +243,8 @@ function printUpdatePlan(plan) {
|
|
|
238
243
|
const groups = [
|
|
239
244
|
['add', '新增'],
|
|
240
245
|
['update', '可安全更新'],
|
|
246
|
+
['update-managed', '更新受管区块'],
|
|
247
|
+
['remove', '安全移除'],
|
|
241
248
|
['merge', '需要合并'],
|
|
242
249
|
['review', '需要人工审查'],
|
|
243
250
|
['review-remove', '需要确认移除'],
|
package/package.json
CHANGED
package/src/framework.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { access, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { buildManifest } from './manifest.js';
|
|
5
5
|
import { matchesLegacyV01Baseline } from './legacy-v0.1.js';
|
|
6
|
+
import { hasValidManagedBlock, isManagedBlockFile, replaceManagedBlock } from './managed-blocks.js';
|
|
6
7
|
import { migrationsBetween } from './migrations.js';
|
|
7
8
|
import { assertNoSymlinkPath, resolveSafeDestination } from './path-safety.js';
|
|
8
9
|
import { render } from './render.js';
|
|
@@ -111,6 +112,9 @@ export async function planFrameworkUpdate({ targetDir, templatesRoot, frameworkV
|
|
|
111
112
|
|
|
112
113
|
const currentHash = hashContent(current);
|
|
113
114
|
const desiredHash = hashContent(desired);
|
|
115
|
+
if (isManagedBlockFile(dest) && !hasValidManagedBlock(desired)) {
|
|
116
|
+
throw new Error(`受管模板缺少有效 managed 标记: ${dest}`);
|
|
117
|
+
}
|
|
114
118
|
if (currentHash === desiredHash) {
|
|
115
119
|
actions.push({ action: 'unchanged', dest, ownership });
|
|
116
120
|
} else if (ownership === 'user') {
|
|
@@ -119,18 +123,33 @@ export async function planFrameworkUpdate({ targetDir, templatesRoot, frameworkV
|
|
|
119
123
|
const matchesBaseline = installation.kind === 'metadata'
|
|
120
124
|
? installation.metadata.files[dest]?.sha256 === currentHash
|
|
121
125
|
: matchesLegacyV01Baseline(dest, current, vars);
|
|
122
|
-
|
|
123
|
-
|
|
126
|
+
if (isManagedBlockFile(dest) && hasValidManagedBlock(current)) {
|
|
127
|
+
const merged = replaceManagedBlock(current, desired);
|
|
128
|
+
actions.push({
|
|
129
|
+
action: merged === current ? 'unchanged' : 'update-managed',
|
|
130
|
+
dest, ownership, currentHash, desiredHash,
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
const action = matchesBaseline ? 'update' : ownership === 'mixed' ? 'merge' : 'review';
|
|
134
|
+
actions.push({ action, dest, ownership, currentHash, desiredHash });
|
|
135
|
+
}
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
if (installation.kind === 'metadata') {
|
|
128
140
|
for (const [dest, record] of Object.entries(installation.metadata.files)) {
|
|
129
|
-
|
|
141
|
+
const destPath = resolveSafeDestination(targetDir, dest);
|
|
142
|
+
const current = await readOptional(destPath);
|
|
143
|
+
if (desiredDests.has(dest) || current === undefined) continue;
|
|
144
|
+
const currentHash = hashContent(current);
|
|
145
|
+
const canRemove = record.ownership === 'framework'
|
|
146
|
+
&& ownershipFor(dest) === 'framework'
|
|
147
|
+
&& record.sha256 === currentHash;
|
|
130
148
|
actions.push({
|
|
131
|
-
action: record.ownership === 'user' ? 'preserve' : 'review-remove',
|
|
149
|
+
action: record.ownership === 'user' ? 'preserve' : canRemove ? 'remove' : 'review-remove',
|
|
132
150
|
dest,
|
|
133
151
|
ownership: record.ownership,
|
|
152
|
+
currentHash,
|
|
134
153
|
});
|
|
135
154
|
}
|
|
136
155
|
}
|
|
@@ -161,26 +180,46 @@ export async function applyFrameworkUpdate({ targetDir, templatesRoot, plan }) {
|
|
|
161
180
|
const sources = new Map(manifest.map(entry => [entry.dest, entry.src]));
|
|
162
181
|
const candidates = [];
|
|
163
182
|
|
|
164
|
-
for (const action of plan.actions.filter(item =>
|
|
183
|
+
for (const action of plan.actions.filter(item => ['add', 'update', 'update-managed', 'remove'].includes(item.action))) {
|
|
184
|
+
if (action.action === 'remove') {
|
|
185
|
+
const destPath = resolveSafeDestination(targetDir, action.dest);
|
|
186
|
+
await assertNoSymlinkPath(targetDir, destPath);
|
|
187
|
+
const current = await readFile(destPath, 'utf8');
|
|
188
|
+
if (hashContent(current) !== action.currentHash) {
|
|
189
|
+
throw new Error(`文件在预检后发生变化,请重新 dry-run: ${action.dest}`);
|
|
190
|
+
}
|
|
191
|
+
candidates.push({ ...action, destPath });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
165
194
|
const src = sources.get(action.dest);
|
|
166
195
|
if (!src) throw new Error(`升级计划缺少当前模板: ${action.dest}`);
|
|
167
196
|
const destPath = resolveSafeDestination(targetDir, action.dest);
|
|
168
197
|
await assertNoSymlinkPath(targetDir, destPath);
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
let current;
|
|
199
|
+
if (action.action !== 'add') {
|
|
200
|
+
current = await readFile(destPath, 'utf8');
|
|
171
201
|
if (action.currentHash && hashContent(current) !== action.currentHash) {
|
|
172
202
|
throw new Error(`文件在预检后发生变化,请重新 dry-run: ${action.dest}`);
|
|
173
203
|
}
|
|
174
204
|
}
|
|
175
|
-
|
|
205
|
+
const desired = render(await readFile(src, 'utf8'), vars);
|
|
206
|
+
const content = action.action === 'update-managed'
|
|
207
|
+
? replaceManagedBlock(current, desired)
|
|
208
|
+
: desired;
|
|
209
|
+
candidates.push({ ...action, destPath, content });
|
|
176
210
|
}
|
|
177
211
|
|
|
178
|
-
const summary = { written: [], skipped: [], imported: [], fallback: [] };
|
|
212
|
+
const summary = { written: [], removed: [], skipped: [], imported: [], fallback: [] };
|
|
179
213
|
for (const [index, item] of candidates.entries()) {
|
|
180
214
|
try {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
215
|
+
if (item.action === 'remove') {
|
|
216
|
+
await unlink(item.destPath);
|
|
217
|
+
summary.removed.push(item.dest);
|
|
218
|
+
} else {
|
|
219
|
+
await mkdir(path.dirname(item.destPath), { recursive: true });
|
|
220
|
+
await writeFile(item.destPath, item.content, { flag: item.action === 'add' ? 'wx' : 'w' });
|
|
221
|
+
summary.written.push(item.dest);
|
|
222
|
+
}
|
|
184
223
|
} catch (err) {
|
|
185
224
|
throw new ScaffoldError({
|
|
186
225
|
phase: 'update', dest: item.dest, destPath: item.destPath, cause: err, summary,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const MANAGED_BLOCK_START = '<!-- ai-memory:managed:start -->';
|
|
2
|
+
export const MANAGED_BLOCK_END = '<!-- ai-memory:managed:end -->';
|
|
3
|
+
|
|
4
|
+
const MANAGED_BLOCK_FILES = new Set(['AGENTS.md', 'CLAUDE.md']);
|
|
5
|
+
|
|
6
|
+
export class ManagedBlockError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'ManagedBlockError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isManagedBlockFile(dest) {
|
|
14
|
+
return MANAGED_BLOCK_FILES.has(dest);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function replaceManagedBlock(current, desired) {
|
|
18
|
+
const currentBlock = locateManagedBlock(current, '当前文件');
|
|
19
|
+
const desiredBlock = locateManagedBlock(desired, '新版模板');
|
|
20
|
+
const eol = current.includes('\r\n') ? '\r\n' : '\n';
|
|
21
|
+
const replacement = normalizeEol(desired.slice(desiredBlock.start, desiredBlock.end), eol);
|
|
22
|
+
return current.slice(0, currentBlock.start) + replacement + current.slice(currentBlock.end);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function hasValidManagedBlock(content) {
|
|
26
|
+
try {
|
|
27
|
+
locateManagedBlock(content, '文件');
|
|
28
|
+
return true;
|
|
29
|
+
} catch (err) {
|
|
30
|
+
if (err instanceof ManagedBlockError) return false;
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function locateManagedBlock(content, label) {
|
|
36
|
+
if (typeof content !== 'string') throw new ManagedBlockError(`${label}内容必须是字符串`);
|
|
37
|
+
const starts = occurrences(content, MANAGED_BLOCK_START);
|
|
38
|
+
const ends = occurrences(content, MANAGED_BLOCK_END);
|
|
39
|
+
if (starts.length !== 1 || ends.length !== 1) {
|
|
40
|
+
throw new ManagedBlockError(`${label}必须且只能包含一组 ai-memory managed 标记`);
|
|
41
|
+
}
|
|
42
|
+
const start = starts[0];
|
|
43
|
+
const end = ends[0] + MANAGED_BLOCK_END.length;
|
|
44
|
+
if (end <= start) throw new ManagedBlockError(`${label}的 ai-memory managed 标记顺序无效`);
|
|
45
|
+
return { start, end };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function occurrences(content, token) {
|
|
49
|
+
const positions = [];
|
|
50
|
+
let offset = 0;
|
|
51
|
+
while (offset < content.length) {
|
|
52
|
+
const index = content.indexOf(token, offset);
|
|
53
|
+
if (index === -1) break;
|
|
54
|
+
positions.push(index);
|
|
55
|
+
offset = index + token.length;
|
|
56
|
+
}
|
|
57
|
+
return positions;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeEol(content, eol) {
|
|
61
|
+
return content.replace(/\r?\n/g, eol);
|
|
62
|
+
}
|
package/src/manifest.js
CHANGED
|
@@ -13,7 +13,7 @@ export async function buildManifest(templatesRoot, tools) {
|
|
|
13
13
|
if (!enabled(tools)) continue;
|
|
14
14
|
const groupDir = path.join(templatesRoot, group);
|
|
15
15
|
for (const rel of await walk(groupDir, '')) {
|
|
16
|
-
entries.push({ src: path.join(groupDir, ...rel.split('/')), dest: rel });
|
|
16
|
+
entries.push({ src: path.join(groupDir, ...rel.split('/')), dest: templateDestination(rel) });
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
const sorted = entries.sort((a, b) => a.dest < b.dest ? -1 : a.dest > b.dest ? 1 : 0);
|
|
@@ -21,6 +21,12 @@ export async function buildManifest(templatesRoot, tools) {
|
|
|
21
21
|
return sorted;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function templateDestination(rel) {
|
|
25
|
+
return rel.endsWith('/.gitignore.template') || rel === '.gitignore.template'
|
|
26
|
+
? rel.slice(0, -'.template'.length)
|
|
27
|
+
: rel;
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
function assertUniqueDestinations(entries) {
|
|
25
31
|
const sourcesByDest = new Map();
|
|
26
32
|
for (const { src, dest } of entries) {
|
|
@@ -3,6 +3,7 @@ description: 主动总结当前进展并按路由写入 .ai/memory/
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
按 `.ai/skills/memory-update.md` 执行:
|
|
6
|
-
1. 读 `.ai/memory/MEMORY.md`
|
|
7
|
-
2.
|
|
8
|
-
3.
|
|
6
|
+
1. 读 `.ai/memory/MEMORY.md` 和本次内容可能写入的目标文件
|
|
7
|
+
2. 先区分用户级、项目级、功能级或一次性信息,再按写入路由更新
|
|
8
|
+
3. 只有满足工程节点触发条件时才追加 session-log;不要每次调用都制造流水
|
|
9
|
+
4. 用户画像只记录明确确认的长期信息,协作规范只记录可复用的明确反馈
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: memory-update
|
|
3
|
-
description: Use when completing an independently verifiable feature, phase, or release; making a durable decision; changing requirement/design/delivery status; preserving a cross-session risk; switching tools; or
|
|
3
|
+
description: Use when completing an independently verifiable feature, phase, or release; making a durable decision; changing requirement/design/delivery status; preserving a cross-session risk; switching tools; the user states a durable preference or corrects agent behavior; or the user explicitly asks to update memory
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
读取并严格遵循 `.ai/skills/memory-update.md` 的写入路由与硬性约束执行。
|
|
@@ -3,4 +3,4 @@ name: model-routing
|
|
|
3
3
|
description: 按项目模型策略路由规划、实现、测试和审查,并在跨模型阶段创建和校验结构化交接。用于准备阶段切换、选择执行代理或验证 handoff。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
先读取 `.ai/skills/model-routing.md` 与 `.ai/config/model-routing.json
|
|
6
|
+
先读取 `.ai/skills/model-routing.md` 与 `.ai/config/model-routing.json`。风险流程决定阶段,模型路由只选择执行者。Claude 代理映射:premium 规划=`premium-planner`,premium 实现=`premium-implementer`,standard 实现=`standard-implementer`,economy/standard 测试=`economy-test-worker`/`standard-test-worker`,premium 审查=`premium-reviewer`。跨模型前创建并校验 handoff;失败时停止,不得用对话摘要补缺失输入。
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
+
<!-- ai-memory:managed:start -->
|
|
3
4
|
## AI 协作框架(ai-memory)
|
|
4
5
|
|
|
5
|
-
进场先读 `.ai/
|
|
6
|
+
进场先读 `.ai/README.md`,严格按其中的核心记忆与任务路由加载协议执行。
|
|
7
|
+
本 managed 区块由 ai-memory 更新;项目命令和自定义规则只写到下方 user 区块。
|
|
6
8
|
|
|
7
9
|
- 0→1 项目/首次架构基线/重大重构 → project-inception skill,产物在 `docs/architecture/`;普通功能不要重复触发
|
|
8
10
|
- 需求 what/why 与外部行为定稿 → requirements-flow skill,产物在 `docs/requirements/vX.Y.Z/{draft,final}/`
|
|
@@ -18,8 +20,11 @@
|
|
|
18
20
|
2. S 级跳过 brainstorming/writing-plans;M 级只对未决高影响 how 选择性使用;L 级可使用完整流程
|
|
19
21
|
3. 所有 Superpowers 结论必须回写 `docs/design/`,临时 spec/plan 不是唯一事实源
|
|
20
22
|
4. code review 使用适合风险等级的流程,叠加 `.ai/skills/code-review.md` 的项目检查项
|
|
23
|
+
<!-- ai-memory:managed:end -->
|
|
21
24
|
|
|
25
|
+
<!-- ai-memory:user:start -->
|
|
22
26
|
## 项目信息
|
|
23
27
|
|
|
24
28
|
- 技术栈:{{techStack}}
|
|
25
29
|
<!-- 在此补充启动/测试/构建命令 -->
|
|
30
|
+
<!-- ai-memory:user:end -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: memory-update
|
|
3
|
-
description: Use when completing an independently verifiable feature, phase, or release; making a durable decision; changing requirement/design/delivery status; preserving a cross-session risk; switching tools; or
|
|
3
|
+
description: Use when completing an independently verifiable feature, phase, or release; making a durable decision; changing requirement/design/delivery status; preserving a cross-session risk; switching tools; the user states a durable preference or corrects agent behavior; or the user explicitly asks to update memory
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
读取并严格遵循 `.ai/skills/memory-update.md` 的写入路由与硬性约束执行。
|
|
@@ -3,4 +3,4 @@ name: model-routing
|
|
|
3
3
|
description: 按项目模型策略路由规划、实现、测试和审查,并在跨模型阶段创建和校验结构化交接。用于准备阶段切换、选择执行代理或验证 handoff。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
先读取 `.ai/skills/model-routing.md` 与 `.ai/config/model-routing.json
|
|
6
|
+
先读取 `.ai/skills/model-routing.md` 与 `.ai/config/model-routing.json`。风险流程决定阶段,模型路由只选择执行者。Codex 代理映射:premium 规划=`premium_planner`,premium 实现=`premium_implementer`,standard 实现=`standard_implementer`,economy/standard 测试=`economy_test_worker`/`standard_test_worker`,premium 审查=`premium_reviewer`。跨模型前创建并校验 handoff;失败时停止,不得用对话摘要补缺失输入。
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
+
<!-- ai-memory:managed:start -->
|
|
3
4
|
## AI 协作框架(ai-memory)
|
|
4
5
|
|
|
5
|
-
进场先读 `.ai/
|
|
6
|
+
进场先读 `.ai/README.md`,严格按其中的核心记忆与任务路由加载协议执行。
|
|
7
|
+
本 managed 区块由 ai-memory 更新;项目命令和自定义规则只写到下方 user 区块。
|
|
6
8
|
|
|
7
9
|
- 0→1 项目/首次架构基线/重大重构 → project-inception skill,产物在 `docs/architecture/`;普通功能不要重复触发
|
|
8
10
|
- 需求 what/why 与外部行为定稿 → requirements-flow skill,产物在 `docs/requirements/vX.Y.Z/{draft,final}/`
|
|
@@ -18,8 +20,11 @@
|
|
|
18
20
|
2. S 级跳过 brainstorming/writing-plans;M 级只对未决高影响 how 选择性使用;L 级可使用完整流程
|
|
19
21
|
3. 所有 Superpowers 结论必须回写 `docs/design/`,临时 spec/plan 不是唯一事实源
|
|
20
22
|
4. code review 使用适合风险等级的流程,叠加 `.ai/skills/code-review.md` 的项目检查项
|
|
23
|
+
<!-- ai-memory:managed:end -->
|
|
21
24
|
|
|
25
|
+
<!-- ai-memory:user:start -->
|
|
22
26
|
## 项目信息
|
|
23
27
|
|
|
24
28
|
- 技术栈:{{techStack}}
|
|
25
29
|
<!-- 在此补充启动/测试/构建命令 -->
|
|
30
|
+
<!-- ai-memory:user:end -->
|
|
@@ -5,10 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
## 进场协议(每次会话开始)
|
|
7
7
|
|
|
8
|
-
1. 读 `memory/MEMORY.md`
|
|
9
|
-
2.
|
|
10
|
-
3.
|
|
11
|
-
4. 跨模型阶段先按 `skills/model-routing.md` 创建并校验 handoff
|
|
8
|
+
1. 读 `memory/MEMORY.md`,再依次加载 `user-profile.md` 当前画像、`feedback.md` 当前规则、`project-state.md` 活跃区段与 `session-log.md` 最新条目;历史归档只在追溯时读取。
|
|
9
|
+
2. 先用核心记忆校准沟通方式、用户长期约束、项目现状和上次进度;文件为空时直接继续,不臆测补全。
|
|
10
|
+
3. 按任务路由只加载当前需要的方法论和正式产物,禁止一次性读取整个 `.ai/` 与 `docs/`。
|
|
11
|
+
4. 跨模型阶段先按 `skills/model-routing.md` 创建并校验 handoff,不用对话摘要替代正式输入。
|
|
12
|
+
|
|
13
|
+
核心记忆只保留当前有效的精简结论;过期偏好应替换,历史 session 应归档,不以无限增长换取“记得更多”。
|
|
14
|
+
|
|
15
|
+
## 任务加载路由
|
|
16
|
+
|
|
17
|
+
| 任务 | 必读增量 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| 0→1、首次基线、重大重构 | `skills/project-inception.md` + 现有 `docs/architecture/` |
|
|
20
|
+
| 新建/定稿需求 | `skills/requirements-flow.md` + 相关 feature 记忆与需求文档 |
|
|
21
|
+
| M/L 功能 how | `skills/feature-design.md` + final 需求、相关架构基线与 feature 记忆 |
|
|
22
|
+
| 实现或修复 | final 需求、适用设计/计划;跨模型时再读 `skills/model-routing.md` |
|
|
23
|
+
| Review | `skills/code-review.md` + 契约、diff 与验证证据 |
|
|
24
|
+
| 交付/发布 | `skills/delivery-readiness.md` + final 需求、设计、架构基线与差异 |
|
|
25
|
+
| 更新记忆 | `skills/memory-update.md`;按内容归属选择目标文件 |
|
|
12
26
|
|
|
13
27
|
## 目录
|
|
14
28
|
|
|
@@ -16,7 +30,7 @@
|
|
|
16
30
|
- `config/model-routing.json` — 可选阶段模型策略;默认 `inherit` 不改变旧行为
|
|
17
31
|
- `memory/` — 记忆层:MEMORY.md 索引、project-state 全景、session-log 流水、user-profile/feedback 用户级记忆、features/ 功能档案
|
|
18
32
|
- `runs/` — 本地交接清单和阶段回执;默认不进入 Git
|
|
19
|
-
- `skills/` — 方法论层:project-inception、requirements-flow、feature-design、delivery-readiness、model-routing、
|
|
33
|
+
- `skills/` — 方法论层:project-inception、requirements-flow、feature-design、delivery-readiness、model-routing、code-review、critic、memory-update
|
|
20
34
|
|
|
21
35
|
## 与工具专属配置的关系
|
|
22
36
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 记忆索引与加载策略
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 每次会话先读取核心记忆;任务记忆按需加载。新增记忆文件必须在本索引登记,禁止一次性加载整个目录。
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
## 核心记忆(每次会话)
|
|
6
|
+
|
|
7
|
+
1. [用户画像](user-profile.md) — 已确认的背景、沟通偏好与长期约束
|
|
8
|
+
2. [协作规范](feedback.md) — 用户明确反馈沉淀的可执行规则
|
|
9
|
+
3. [项目状态](project-state.md) — 读基本信息、当前需求和遗留问题;归档摘要仅在追溯时读取
|
|
10
|
+
4. [Session 日志](session-log.md) — 只读最新条目,接续进展与下一步
|
|
11
|
+
|
|
12
|
+
## 任务记忆(按需)
|
|
13
|
+
|
|
14
|
+
<!-- features/ 功能档案逐行登记;只在任务涉及对应功能时读取 -->
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# 协作规范
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
>
|
|
3
|
+
> 从用户明确纠正或要求中提炼的跨项目行为规则。只记可重复执行的规则,不记录一次性情绪、项目事实或未经确认的推断。
|
|
4
|
+
> 写入前先去重;新规则与旧规则冲突时,以用户最新明确反馈为准并替换旧规则。
|
|
5
|
+
|
|
6
|
+
## 规则格式
|
|
7
|
+
|
|
8
|
+
- **规则**:必须/不要做什么
|
|
9
|
+
- 原因:用户为什么提出
|
|
10
|
+
- 应用:何时触发、具体怎么做
|
|
11
|
+
- 来源:YYYY-MM-DD 用户明确反馈
|
|
12
|
+
|
|
13
|
+
## 当前规则
|
|
5
14
|
|
|
6
15
|
(暂无条目)
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
# 用户画像
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 跨项目复用的用户级记忆。只记录用户明确表达或确认的稳定信息;不从语气、姓名或项目内容推断身份、能力和敏感属性。敏感信息默认不写,密钥和凭据永不写。
|
|
4
|
+
> 保持精简;偏好变化时以最新明确表达为准。仅对当前项目有效的信息写入 `project-state.md`。
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## 背景与角色(已确认)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- 技术背景:
|
|
9
|
+
- 当前角色与主要职责:
|
|
10
|
+
- 常用工具或工作环境:
|
|
8
11
|
|
|
9
|
-
##
|
|
12
|
+
## 沟通与决策偏好
|
|
10
13
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
+
- 默认语言:
|
|
15
|
+
- 回复详细度与表达方式:
|
|
16
|
+
- 可自主执行的范围:
|
|
17
|
+
- 必须先确认的操作:
|
|
18
|
+
- 方案比较与决策方式:
|
|
19
|
+
|
|
20
|
+
## 长期工程偏好与约束
|
|
21
|
+
|
|
22
|
+
- 质量、速度与成本取舍:
|
|
23
|
+
- 技术或架构偏好:
|
|
24
|
+
- 明确避免的做法:
|
|
25
|
+
- 其他跨项目约束:
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
## 流程
|
|
12
12
|
|
|
13
|
-
1. 读取 `final/<需求名>.md`
|
|
13
|
+
1. 读取 `final/<需求名>.md` 的实现交接、`.ai/skills/architecture.md`,以及相关 `docs/architecture/`、源码和 feature 记忆。
|
|
14
14
|
2. 若需求存在矛盾或阻塞开放问题,退回 requirements-flow;不要用实现假设偷偷补需求。
|
|
15
15
|
3. 在 `docs/design/vX.Y.Z/<需求名>.md` 按模板形成设计,只填写适用章节,不涉及也要简述原因。
|
|
16
16
|
4. 为真实边界定义技术接口契约;不要为所有私有函数写文档。
|
|
@@ -16,11 +16,21 @@
|
|
|
16
16
|
|
|
17
17
|
| 内容 | 去处 |
|
|
18
18
|
|---|---|
|
|
19
|
+
| 用户明确表达的稳定背景、沟通/决策偏好、跨项目约束 | `user-profile.md` 对应字段 |
|
|
20
|
+
| 用户明确纠正且可跨项目复用的 Agent 行为规则 | `feedback.md` 去重后新增或替换 |
|
|
19
21
|
| 工程节点、当前进度、下一步、阻塞 | `session-log.md` 追加 |
|
|
20
22
|
| 需求、设计、里程碑或交付状态 | `project-state.md` 对应行 |
|
|
21
23
|
| 稳定功能决策与契约变化摘要 | `features/<名>.md` |
|
|
22
24
|
| 新增记忆文件 | `MEMORY.md` 加索引 |
|
|
23
25
|
|
|
26
|
+
## 用户级记忆判定
|
|
27
|
+
|
|
28
|
+
1. 只记录用户明确说出、确认或纠正的长期信息;不得根据对话风格、代码水平、姓名或项目类型推断画像。
|
|
29
|
+
2. 先判断作用域:跨项目才进入 `user-profile.md` / `feedback.md`;当前项目事实进入项目状态或 feature 记忆;一次性要求不落盘。
|
|
30
|
+
3. `user-profile.md` 记录“用户是谁、偏好怎样协作”;`feedback.md` 记录“Agent 以后具体必须怎样做”,不得重复抄写。
|
|
31
|
+
4. 身份、联系方式、健康、财务等敏感信息默认不写;只有用户明确要求并确认仓库可见性后才允许记录必要的最小范围。密钥、令牌和凭据永不写入。
|
|
32
|
+
5. 用户撤回或修改偏好时更新旧条目,不并列保留相互冲突的规则。
|
|
33
|
+
|
|
24
34
|
## 约束
|
|
25
35
|
|
|
26
36
|
- 写前读取目标文件,只记录增量和新事实,不复制需求/设计/测试输出。
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## 工作流
|
|
14
14
|
|
|
15
|
-
1.
|
|
15
|
+
1. 读取项目目标、现有代码/文档、`.ai/memory/project-state.md` 与 `.ai/skills/architecture.md` 的语言无关边界原则。
|
|
16
16
|
2. 判断是 0→1、新增基线还是重大重构;不适用则停止并转入需求或功能设计流程。
|
|
17
17
|
3. 只询问会改变架构方向的阻塞信息;非阻塞信息采用保守假设并明确标记。
|
|
18
18
|
4. 按 `docs/architecture/` 的四份模板建立或增量更新工程基线:
|
|
File without changes
|