@umacloud/knowledge 1.0.21 → 1.0.22
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.
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: open-decisions-parking-lot-register
|
|
3
|
+
title: 悬而未决登记册(停车场清单:延后/受阻/待触发的决策一个都不丢,开工即复现,商业级必读)
|
|
4
|
+
domain: agentic-delivery
|
|
5
|
+
category: 01-standards
|
|
6
|
+
difficulty: advanced
|
|
7
|
+
tags: [open-decisions, parking-lot, deferred-decision, blocked-item, pending-trigger, append-only, resolve-in-place, resurface-at-task-start, decision-log, adr, third-memory-channel, waiting-on-external-condition, design-decision-to-evaluate, existing-design-boundary, 悬而未决, 停车场清单, 延后决策, 受阻项, 待触发, 只追加, 就地关闭, 开工复现, 决策日志, 第三记忆通道]
|
|
8
|
+
quality_score: 95
|
|
9
|
+
last_updated: 2026-07-02
|
|
10
|
+
---
|
|
11
|
+
# 悬而未决登记册(停车场清单,商业级必读)
|
|
12
|
+
|
|
13
|
+
> 一次长程交付里,真正让团队丢分的往往不是"没做完",而是"某个当时定不下来、只能先放一放的事,后来彻底忘了"——一个缺失的外部密钥、一个要等下游任务才能接的依赖、一个当时拿不准、说好"回头再评估"的设计选择、一个开放问题、一个先跳过的校验、一个"先这样、有保留"的边界。这些项目**只活在工作记忆里、或在对话里被提过一次**,随着上下文滚动就蒸发了:没有可追溯、没有复现、没人再想起来。
|
|
14
|
+
> 一个真实的研发团队会把这些放进一张**停车场清单(parking-lot)/ 悬而未决登记册**:写下来、归类、留痕,开工时再拿出来过一遍。这份规范把这张清单升级成**第三条持久记忆通道**——它和"已解析事实"(`agentic-delivery/01-standards/self-improving-memory-and-regression-sets` 记忆底座里的事实存储)、"踩坑账本"(pitfall ledger)并列:事实存的是**已经定死的结论**,踩坑账本存的是**吃过的亏**,而这张登记册存的是**还没定、正悬着的决策**。三者互补,缺一不可。
|
|
15
|
+
|
|
16
|
+
## 1. 什么必须进登记册(触发条件)
|
|
17
|
+
|
|
18
|
+
只要出现下面任一情形,且它**不能在当前这步就地解决**,就必须落一条:
|
|
19
|
+
|
|
20
|
+
- **等待外部条件**:缺密钥/凭据/账号、等上游答复、要等别的团队或第三方。
|
|
21
|
+
- **依赖下游任务**:现在做了也没意义,要等某个后续任务先落地。
|
|
22
|
+
- **有歧义的设计决策**:当前信息不足,先选了一个临时方案,说好"数据/负载/需求明朗后再评估"。
|
|
23
|
+
- **开放问题**:一个还没有答案、但会影响后续的问题。
|
|
24
|
+
- **延后的校验**:为了先跑通主流程而暂时跳过的验证/测试/边界检查。
|
|
25
|
+
- **有保留地接受的边界**:明知有局限但当前范围内接受,约定"开始咬人再回来"。
|
|
26
|
+
|
|
27
|
+
判据一句话:**"我现在定不下来 / 先放一放"的任何东西**,都不许只留在脑子里或聊天里——必须写进登记册。
|
|
28
|
+
|
|
29
|
+
## 2. 三类归类(category)
|
|
30
|
+
|
|
31
|
+
每条只归一类,用固定 slug,便于检索与统计:
|
|
32
|
+
|
|
33
|
+
| 类别 slug | 含义 | 典型触发 |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `waiting-on-external-condition` | 受阻于本次交付之外的条件 | 缺密钥、等下游任务、等上游答复 |
|
|
36
|
+
| `design-decision-to-evaluate` | 有歧义、待重新评估的设计选择 | 会话存 cookie 还是 Redis、选哪个 ORM |
|
|
37
|
+
| `existing-design-boundary` | 有保留地接受的既有边界/局限 | v1 只单区域部署、暂不做多租户 |
|
|
38
|
+
|
|
39
|
+
不要发明新类别;拿不准就往最接近的一类归,把细节写进字段里。
|
|
40
|
+
|
|
41
|
+
## 3. 一条登记的结构化字段
|
|
42
|
+
|
|
43
|
+
每条都用同一套字段,缺失填 `none yet`,不要留空导致再解析时丢字段:
|
|
44
|
+
|
|
45
|
+
- **Date**:`YYYY-MM-DD`,落条日期。
|
|
46
|
+
- **Source**:来源——发起它的需求 / ADR 编号 / 任务 id,保证可回溯到"为什么会有这条"。
|
|
47
|
+
- **Open item**:悬着的事本身,一句话说清"到底什么没定/没做"。
|
|
48
|
+
- **Related constraints**:约束这条的相关约束(性能/合规/接口/成本等)。
|
|
49
|
+
- **Current leaning**:当前的倾向/临时方案,没有就写 `none yet`——留倾向能让复现时快速接上思路。
|
|
50
|
+
- **Blocked by**:卡住决策的东西(缺什么、等谁)。
|
|
51
|
+
- **Resolves when**:**触发关闭的条件**——什么发生了这条就能定了。这是最关键的字段:它让"悬而未决"变成"有明确复活条件的待办",而不是一句永远悬着的空话。
|
|
52
|
+
|
|
53
|
+
登记册本身是一个**项目内可见、随代码提交**的文档(放在 `docs/decisions/` 这类正常目录,而不是被 gitignore 的临时目录)——因为悬而未决是团队和用户都应当能读、能评审、能 diff 的东西。
|
|
54
|
+
|
|
55
|
+
## 4. 只追加 + 就地关闭(append-only, resolve-in-place)
|
|
56
|
+
|
|
57
|
+
- **只追加**:新条目永远追加到文件末尾,**绝不重写、绝不删除**已有条目。历史决策的痕迹必须留存。
|
|
58
|
+
- **就地关闭**:一条被解决时,不是删掉它,而是**把它的 `OPEN` 标记翻成 `RESOLVED`,并补一条 `Resolution:`(决定了什么 + 为什么 + 日期)**。留痕的意义在于:三个月后有人问"当初为什么这么定/为什么没做多区域",答案在册子里,而不是靠某个人的记忆。
|
|
59
|
+
- 一条 Markdown 条目形如:`## OPEN — <category> — <标题>`,下面跟上一节的字段;关闭时改成 `## RESOLVED — …` 并加 `Resolution` 行。
|
|
60
|
+
|
|
61
|
+
这条纪律和 `self-improving-memory-and-regression-sets` 里的**增量增删(delta)**一脉相承:对记忆只做增量、不做整篇重写,避免"上下文坍缩"把积累的细节抹平。
|
|
62
|
+
|
|
63
|
+
## 5. 开工即复现(resurface-at-task-start)
|
|
64
|
+
|
|
65
|
+
登记册**只写不看等于没写**。规范要求:**每次任务/阶段开始时,把还 `OPEN` 的条目自动复现到工作上下文的最前面**,并带上 `(N 未决 + M 已决)` 的汇总,让上一轮悬着的项目主动"跳出来",而不是指望执行者记得去翻文件。
|
|
66
|
+
|
|
67
|
+
- 复现是**有界的**:只复现未决项、按最久优先(最容易被遗忘的先冒头)、条数与字节双封顶——它是一层薄高信噪的提示,不是把整册子灌进去。
|
|
68
|
+
- 复现是**自门控的**:只在真正干活的回合注入;纯聊天/寒暄回合不注入,零开销。
|
|
69
|
+
- 复现是**fail-open 的**:没有登记册、文件损坏、无未决项 → 复现为空,行为与从前一致,绝不因此报错或卡住。
|
|
70
|
+
- 复现时的动作要求:**逐条判断当前这步能不能把它关掉**;能关就地关闭(翻 `RESOLVED` + 补 `Resolution`),关不掉就让它继续悬着——但它已经"被看见"了,不会再丢。
|
|
71
|
+
|
|
72
|
+
## 6. 与相邻规范的分工
|
|
73
|
+
|
|
74
|
+
- 与"已解析事实存储":事实存的是**定死可复用的结论**(路径/端口/命令/已定架构决策);本登记册存的是**还没定的**。一条 `OPEN` 被关闭后,如果产出了一个稳定可复用的结论,可以顺手沉淀成一条事实。
|
|
75
|
+
- 与"踩坑账本 / 回归集"(`self-improving-memory-and-regression-sets`):账本存**吃过的亏**并沉淀成回归用例;本登记册存**悬着的决策**。二者都反对"同样的东西下次再踩/再丢"。
|
|
76
|
+
- 与 ADR(架构决策记录):ADR 记录**已经做出的**决策;本登记册记录**尚未做出、正悬着的**决策,并在 `Resolves when` 触发、就地关闭时,可升格成一条 ADR。
|
|
77
|
+
|
|
78
|
+
## 7. 反模式(antipatterns)
|
|
79
|
+
|
|
80
|
+
- 把"先放一放"只留在聊天里或脑子里 → 上下文一滚就丢,零可追溯。
|
|
81
|
+
- 关闭时直接删除条目 → 决策痕迹消失,事后无法回答"当初为什么"。
|
|
82
|
+
- 只写不复现 → 册子越写越长却从不被看,等于没有。
|
|
83
|
+
- `Resolves when` 写成空话("以后再说")→ 永远悬着,失去"有明确复活条件"的意义。
|
|
84
|
+
- 无界复现(把整册子灌进上下文)→ 触发上下文过载,挤掉当前这步真正需要的信息。
|
|
85
|
+
- 发明一堆自定义类别 → 检索/统计失效;坚持三类固定 slug。
|
|
86
|
+
|
|
87
|
+
## 8. 落地检查清单(checklist)
|
|
88
|
+
|
|
89
|
+
- [ ] 出现"定不下来/先放一放"时,是否**立刻**落了一条,而不是留在对话里?
|
|
90
|
+
- [ ] 归类是否用三类固定 slug 之一?
|
|
91
|
+
- [ ] 七个字段是否齐全,`Resolves when` 是否是**可判定的具体条件**?
|
|
92
|
+
- [ ] 登记册是否放在**项目内可见、随代码提交**的目录,而非临时/被忽略目录?
|
|
93
|
+
- [ ] 关闭时是否**就地翻 `RESOLVED` + 补 `Resolution`**,而不是删除?
|
|
94
|
+
- [ ] 每次开工是否把**未决项自动复现**在最前面并逐条判断能否关闭?
|
|
95
|
+
- [ ] 复现是否**有界、自门控、fail-open**?
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umacloud/knowledge",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "UmaDev curated engineering knowledge corpus (standards, methodologies, expert playbooks, design systems, miniprogram/uniapp guides). Platform-independent data shipped once so npm users get the full KB offline.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": { "type": "git", "url": "https://github.com/umacloud/umadev.git" },
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: dependency-install-before-tests
|
|
3
|
+
title: 运行测试/lint 前先装依赖(含 dev/test extras,一步到位不返工)
|
|
4
|
+
domain: testing
|
|
5
|
+
category: 01-standards
|
|
6
|
+
difficulty: intermediate
|
|
7
|
+
tags: [dependency, dev-extras, test-tooling, uv, pip, poetry, pdm, npm, pytest, ruff, one-pass, no-retry, 依赖安装, 测试依赖, 开发依赖, 一步到位, 商业级]
|
|
8
|
+
quality_score: 95
|
|
9
|
+
last_updated: 2026-07-02
|
|
10
|
+
---
|
|
11
|
+
# 运行测试/lint 前先装依赖(含 dev/test extras)
|
|
12
|
+
|
|
13
|
+
> 这条规范修的是一个高频浪费:自动化跑流程时,直接就去执行 `uv run python -m pytest -q` / `uv run ruff check`,结果环境里根本没装 `pytest`、`ruff`,报 `No module named pytest`,然后才回头 `uv sync --extra dev` 再重试——白白多走一整轮。
|
|
14
|
+
> 核心结论:**跑测试/lint 之前,先把项目依赖(含 dev/test extras)一步装好,再跑测试。** 测试运行时报"缺某个模块/命令"几乎都是**你漏了装依赖这一步**,不是测试真的挂了。
|
|
15
|
+
|
|
16
|
+
## 1. 铁律:先装依赖,再跑测试/lint
|
|
17
|
+
|
|
18
|
+
- 跑任何测试或 lint 命令**之前**,先确认依赖已安装,而且**包含 dev/test extras**(`pytest`、`ruff`、`mypy`、`eslint`、`jest` 这些工具都在开发依赖里,不在运行依赖里)。
|
|
19
|
+
- 安装要**一步到位**:一条 sync/install 命令把运行依赖 + 开发/测试依赖一起装好,然后再跑测试。不要"先跑、报错、再补装、再重试"——那是把一步拆成三步。
|
|
20
|
+
- 看到 `No module named pytest` / `ModuleNotFoundError` / `pytest: command not found` / `ruff: not found`:**这是漏装依赖,不是测试失败**。正确动作是回到"装依赖(含 dev/test)"这一步,而**不是**原样重试同一条命令、也不是去改测试代码。
|
|
21
|
+
|
|
22
|
+
## 2. 各生态的准确命令
|
|
23
|
+
|
|
24
|
+
### Python · uv(本条最容易踩的坑)
|
|
25
|
+
|
|
26
|
+
- **默认的 `uv sync` 不装 dev/test extras**。只跑 `uv sync` 之后再 `uv run pytest` / `uv run ruff`,工具找不到,就会报 `No module named pytest`。
|
|
27
|
+
- 正确做法(任选其一,按项目声明方式):
|
|
28
|
+
- `uv sync --extra dev`(`pyproject.toml` 里用 `[project.optional-dependencies].dev` 声明时)
|
|
29
|
+
- `uv sync --all-extras`(一次装齐所有 extras)
|
|
30
|
+
- `uv sync --group dev`(用 dependency-groups 声明时)
|
|
31
|
+
- 装好后再 `uv run pytest -q` / `uv run ruff check`。
|
|
32
|
+
|
|
33
|
+
### Python · pip / venv
|
|
34
|
+
|
|
35
|
+
- `pip install -e '.[dev]'`(`pyproject.toml` / `setup.cfg` 声明了 `dev` extra 时;注意引号,zsh 下 `.[dev]` 会被当成通配符)
|
|
36
|
+
- 或 `pip install -r requirements-dev.txt`(有独立开发依赖清单时)
|
|
37
|
+
|
|
38
|
+
### Python · poetry / pdm
|
|
39
|
+
|
|
40
|
+
- poetry:`poetry install --with dev`(`--with` 装 dev group;`--only` 会**只**装某组,别误用)
|
|
41
|
+
- pdm:`pdm install -G dev`(`-G/--group` 指定开发组)
|
|
42
|
+
|
|
43
|
+
### Node · npm / pnpm / yarn
|
|
44
|
+
|
|
45
|
+
- `npm ci`(按 lockfile 精确安装,**包含 devDependencies**——`jest`/`eslint`/`vitest` 就在这里)
|
|
46
|
+
- pnpm:`pnpm install --frozen-lockfile`;yarn:`yarn install --frozen-lockfile`
|
|
47
|
+
- 注意:`npm ci --omit=dev` / `NODE_ENV=production` 会**跳过** devDependencies,那样测试工具就装不上——跑测试的环境不要用生产安装模式。
|
|
48
|
+
|
|
49
|
+
## 3. 判断准则(把"缺模块报错"归类对)
|
|
50
|
+
|
|
51
|
+
- 测试运行时出现"缺模块/缺命令"(`No module named X`、`X: command not found`、`is not recognized`)→ **依赖问题**,去装依赖,不是测试问题。
|
|
52
|
+
- 缺的是**测试/lint 工具本身**(pytest/ruff/mypy/eslint/jest…)→ 是 **dev/test extras 没装**,用上面对应生态的命令补齐。
|
|
53
|
+
- 缺的是**业务依赖**(如 `requests`、`lodash`)→ 是运行依赖没装或没声明,正常 install/add 后再跑。
|
|
54
|
+
- 只有在**依赖确已装齐**的前提下,测试仍然红,才是真正的测试失败,这时才去看断言与实现。
|
|
55
|
+
|
|
56
|
+
## 4. 反模式(不要这样做)
|
|
57
|
+
|
|
58
|
+
- 直接 `uv run pytest` 前不 sync,报错后才 `uv sync --extra dev` 再重试——多走一轮。
|
|
59
|
+
- 报 `No module named pytest` 后去**改测试代码 / 加 skip / 装错包**,而不是装 dev 依赖。
|
|
60
|
+
- 用生产安装模式(`--omit=dev` / `--only main` / `NODE_ENV=production`)准备测试环境,导致测试工具缺失。
|
|
61
|
+
- 把 `uv sync --extra dev` 当成"报错后的补救",而不是"跑测试前的既定第一步"。
|