Add the project rules, requirements and task records
This commit is contained in:
252 files changed
+3829
-8
No files matched your search
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Writes docs/test-map.md: each PRD id, its tasks, their tests."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
LATER = ("MAIL", "AGENT")
|
||||
# Where each area's tests live, named or not.
|
||||
WHERE = {
|
||||
"UX": "crates/ely-ui/tests、shell.sh、doc-shell.sh、settings.sh",
|
||||
"FILE": "crates/ely-files、crates/ely-office、recovery.sh、autosave.sh",
|
||||
"LOK": "crates/ely-lok/src/client/tests、crates/ely-lok/src/view/tests、lokview.sh",
|
||||
"DOC": "apps/ely-doc/src/tests、doc-props.sh",
|
||||
"TABLE": "apps/ely-table/src/tests、theme.sh",
|
||||
"SHOW": "apps/ely-show/src/tests",
|
||||
"PDF": "apps/ely-pdf/src/tests、crates/ely-pdf-engine/tests、pdf-recovery.sh",
|
||||
"TREE": "apps/ely-tree/src/tests",
|
||||
"MARK": "apps/ely-mark 单测、mark-*.sh",
|
||||
"PERF": "tests/perf/bench.py、lag.sh",
|
||||
"QA": "见 docs/qa.md",
|
||||
}
|
||||
|
||||
|
||||
def read(name):
|
||||
with open(os.path.join(ROOT, name)) as text:
|
||||
return text.read()
|
||||
|
||||
|
||||
def ids():
|
||||
"""PRD table rows: id and its requirement."""
|
||||
for line in read("PRD.md").splitlines():
|
||||
if m := re.match(r"\| ([A-Z]+-\d+) \| (.+?) \|", line):
|
||||
yield m.group(1), m.group(2).split("|")[0].strip()
|
||||
|
||||
|
||||
def cites(line):
|
||||
"""PRD ids a line names: single, lists, ranges."""
|
||||
cited = set()
|
||||
for prefix, rest in re.findall(r"([A-Z]+)-(\d+(?:(?: ?至 ?|、)(?:[A-Z]+-)?\d+)*)", line):
|
||||
numbers = re.split(r"(?: ?至 ?|、)(?:[A-Z]+-)?", rest)
|
||||
ranges = re.findall(r"(?: ?至 ?|、)", rest)
|
||||
n = [int(x) for x in numbers]
|
||||
cited.add(n[0])
|
||||
for kind, (a, b) in zip(ranges, zip(n, n[1:])):
|
||||
cited.update(range(a, b + 1) if "至" in kind else [b])
|
||||
yield from (f"{prefix}-{k:02d}" for k in sorted(cited))
|
||||
cited = set()
|
||||
|
||||
|
||||
def tasks():
|
||||
"""Task lines and decisions: a label, the PRD ids, the line."""
|
||||
for line in read("tasks/TASKS.md").splitlines():
|
||||
if m := re.match(r"- \[(.)\] (C[\d.]+[a-z]?) ", line):
|
||||
yield m.group(2) + ("" if m.group(1) == "x" else f"({m.group(1)})"), set(cites(line)), line
|
||||
for line in read("agents.md").splitlines():
|
||||
if m := re.match(r"- (\d{4}-\d\d-\d\d)[^:]*:.*?((C[\d.]+)", line):
|
||||
yield f"决策 {m.group(2)}", set(cites(line)), line
|
||||
|
||||
|
||||
def known():
|
||||
"""Test function and script names present in the tree."""
|
||||
found = subprocess.run(["grep", "-rhoE", r"fn [a-z0-9_]+\(", "crates", "apps", "--include=*.rs"],
|
||||
cwd=ROOT, capture_output=True, text=True).stdout
|
||||
names = {name[3:-1] for name in found.split()}
|
||||
names |= {f for f in os.listdir(os.path.join(ROOT, "tests", "scripts"))}
|
||||
return names
|
||||
|
||||
|
||||
def main():
|
||||
present = known()
|
||||
rows = ["# 功能编号与测试对照", "", "对应 PRD §22。由 `scripts/test-map.py` 从 PRD、`tasks/TASKS.md` 与 `agents.md` 生成:每个编号列出引用它的任务与决策,其中写明、且在代码里确有其名的测试(单测函数名或 `tests/scripts` 的脚本),以及该领域测试所在之处。邮件与 Agent 属第二批,不列。", "",
|
||||
"| 编号 | 要求 | 任务 | 记下的测试 | 测试所在 |", "| --- | --- | --- | --- | --- |"]
|
||||
listed = list(tasks())
|
||||
for id_, need in ids():
|
||||
if id_.startswith(LATER):
|
||||
continue
|
||||
mine = [(label, line) for label, cited, line in listed if id_ in cited]
|
||||
named = []
|
||||
for _, line in mine:
|
||||
for name in re.findall(r"`([a-z0-9_.-]+)`|([a-z0-9-]+\.sh)", line):
|
||||
name = name[0] or name[1]
|
||||
if name in present and name not in named:
|
||||
named.append(name)
|
||||
labels = list(dict.fromkeys(label for label, _ in mine))
|
||||
where = WHERE[id_.split("-")[0]]
|
||||
rows.append(f"| {id_} | {need} | {'、'.join(labels) or '无'} | {'、'.join(f'`{n}`' for n in named) or '—'} | {where} |")
|
||||
with open(os.path.join(ROOT, "docs", "test-map.md"), "w") as out:
|
||||
out.write("\n".join(rows) + "\n")
|
||||
print(f"docs/test-map.md: {len(rows) - 6} ids")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user