mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-11 03:01:58 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b239f8d43e | |||
| 4822201364 |
+22
-10
@@ -4,10 +4,23 @@ One file per upstream C++ defect, so parallel PRs never conflict. Never append t
|
||||
shared file. The rules, fields, severity order and numbering are below (from the former
|
||||
archive). The site (`site/build.py`) renders every file here, in name order.
|
||||
|
||||
- **Name:** `<ID>--<short-slug>.md`, e.g. `WR-262--extrusion-drop-point-fast.md`. The ID
|
||||
takes the next free number in its series (`UB-`, `HANG-`, `ND-`, `WR-`, `DOC-`) across
|
||||
this directory. If two PRs pick the same number, whoever merges second renumbers theirs
|
||||
(the site flags duplicates).
|
||||
- **Name:** `<ID>--<short-slug>.md`, e.g. `WR-1255--extrusion-drop-point-fast.md`. The
|
||||
series is `UB-`, `HANG-`, `ND-`, `WR-` or `DOC-`. **The number is the number of the PR
|
||||
that adds the record.** A second record of the same series in the same PR is
|
||||
`WR-1255-2--other-slug.md`, a third `WR-1255-3--...`, and so on (the first has no
|
||||
suffix). Prefer one record per PR; use `-2`, `-3` only when records genuinely belong
|
||||
together. Open the draft PR first (the workflow does), then name the file.
|
||||
- *Why:* "the next free number" made parallel PRs pick the same one, and the later PR
|
||||
had to renumber the record and every citation of it (code comments, kernel field
|
||||
docs, known mismatches, findings). A PR number is unique and known before the record
|
||||
is written, so two PRs can never collide.
|
||||
- *Citing:* cite the full id (`WR-1255`, `WR-1255-2`) exactly as in the file name and
|
||||
the `#### ` heading, which reads `#### WR-1255-2. One-line title`.
|
||||
- *Existing records* keep their ids and are never renamed, so numbers up to about
|
||||
`WR-469` come from the old scheme and gaps are normal. The legacy duplicate ids
|
||||
(section below) stay as they are.
|
||||
- `scripts/ci/check_record_ids.py` (CI job `ci-scripts`) fails on a repeated id and on
|
||||
an addendum that names no record.
|
||||
- **Content:**
|
||||
|
||||
```markdown
|
||||
@@ -76,10 +89,10 @@ Severity order: crash/UB, hang, nondeterminism, wrong result, docs. Entries are
|
||||
by area within each severity, so IDs are in order within each area but not across a
|
||||
whole severity.
|
||||
|
||||
**Numbering.** A new entry takes the next free number in its series (`UB-`, `HANG-`,
|
||||
`ND-`, `WR-`, `DOC-`) at the moment its PR merges. If another PR took that number in the
|
||||
meantime, whoever merges renumbers the new entry and every reference to it (here, in
|
||||
`plan/findings.md`, `plan/modules.toml` and code comments). Numbers are not reused.
|
||||
**Numbering.** Superseded: new entries are numbered by the PR that adds them (see
|
||||
`Name` above). The text below is the archive's original rule: a new entry took the next
|
||||
free number in its series (`UB-`, `HANG-`, `ND-`, `WR-`, `DOC-`) when its PR merged, and
|
||||
whoever merged second renumbered. Numbers are not reused.
|
||||
<!-- archive:intro end -->
|
||||
|
||||
<!-- archive:note-duplicate-ids begin (generated by scripts/split_archives.py) -->
|
||||
@@ -121,6 +134,5 @@ title (other references in the repo in brackets):
|
||||
`SmFilletEdge::CalcBlendingRail` builds its Hermite fallback as a degree-2 curve
|
||||
[`blend/fillet_geom/p6.rs`].
|
||||
|
||||
New entries take the next free number after the highest in their series, as the
|
||||
Numbering paragraph at the top says.
|
||||
New entries are numbered by their PR, as `Name` at the top says.
|
||||
<!-- archive:note-duplicate-ids end -->
|
||||
|
||||
+6
-4
@@ -2,7 +2,9 @@
|
||||
"""Fails if two plan/upstream-issues/ records share an ID, or an addendum names no record.
|
||||
|
||||
A record is `<SERIES>-<N>--<slug>.md` (e.g. `WR-262--extrusion-drop-point-fast.md`); its ID is
|
||||
`<SERIES>-<N>`. An addendum is `<SERIES>-<N>--addendum-<YYYY-MM-DD>-<slug>.md` and must name
|
||||
`<SERIES>-<N>`. New records are numbered by the PR that adds them, and the k-th record of a
|
||||
series in one PR (k >= 2) is `<SERIES>-<N>-<k>--<slug>.md` with ID `<SERIES>-<N>-<k>`.
|
||||
An addendum is `<SERIES>-<N>[-<k>]--addendum-<YYYY-MM-DD>-<slug>.md` and must name
|
||||
the ID of an existing record. Names without a numeric ID (`UB-new--`, `UB-unnumbered--`,
|
||||
`HANG-unnumbered--`, `UNNUMBERED--`) and README.md are not checked.
|
||||
|
||||
@@ -19,8 +21,8 @@ from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
ISSUES = Path("plan/upstream-issues")
|
||||
RECORD = re.compile(r"^([A-Z]+-[0-9]+)--(.+)\.md$")
|
||||
ADDENDUM = re.compile(r"^([A-Z]+-[0-9]+)--addendum-[0-9]{4}-[0-9]{2}-[0-9]{2}-.+\.md$")
|
||||
RECORD = re.compile(r"^([A-Z]+-[0-9]+(?:-[2-9]|-[1-9][0-9]+)?)--(.+)\.md$")
|
||||
ADDENDUM = re.compile(r"^([A-Z]+-[0-9]+(?:-[2-9]|-[1-9][0-9]+)?)--addendum-[0-9]{4}-[0-9]{2}-[0-9]{2}-.+\.md$")
|
||||
ADDENDUM_LIKE = re.compile(r"--addendum")
|
||||
|
||||
# Records sharing an ID when this check was added (2026-10-26). The `--dupN` names come from
|
||||
@@ -92,7 +94,7 @@ def check(names, legacy=None):
|
||||
new = [f for f in files if f not in legacy.get(rid, set())]
|
||||
errors.append(
|
||||
f"{rid} is used by {len(files)} records: {', '.join(files)}. "
|
||||
f"Give {', '.join(new)} the next free ID in its series; to update a record, "
|
||||
f"Give {', '.join(new)} an ID that is not in use (the number of the PR that adds it, `-2`, `-3`, ... for more records in that PR); to update a record, "
|
||||
"add an addendum file instead."
|
||||
)
|
||||
for name, rid in addenda:
|
||||
|
||||
+21
-1
@@ -45,7 +45,27 @@ class CheckRecordIds(unittest.TestCase):
|
||||
self.assertEqual(c.check(["UB-7--a.md", "UB-7--b--dup2.md"], legacy=legacy), [])
|
||||
errors = c.check(["UB-7--a.md", "UB-7--b--dup2.md", "UB-7--c.md"], legacy=legacy)
|
||||
self.assertEqual(len(errors), 1)
|
||||
self.assertIn("UB-7--c.md the next free ID", errors[0])
|
||||
self.assertIn("UB-7--c.md an ID that is not in use", errors[0])
|
||||
|
||||
def test_dashed_ids_are_distinct_records(self):
|
||||
names = ["WR-1250--a.md", "WR-1250-2--b.md", "WR-1250-3--c.md", "WR-12--d.md"]
|
||||
self.assertEqual(c.check(names, legacy={}), [])
|
||||
|
||||
def test_shared_dashed_id_fails(self):
|
||||
errors = c.check(["WR-1250-2--a.md", "WR-1250-2--b.md"], legacy={})
|
||||
self.assertEqual(len(errors), 1)
|
||||
self.assertIn("WR-1250-2 is used by 2 records", errors[0])
|
||||
|
||||
def test_dash_one_is_not_an_id(self):
|
||||
# The first record of a PR has no suffix; `-1` is not a valid form, so it is skipped.
|
||||
self.assertEqual(c.check(["WR-1250--a.md", "WR-1250-1--b.md"], legacy={}), [])
|
||||
|
||||
def test_addendum_names_dashed_record(self):
|
||||
names = ["WR-1250-2--a.md", "WR-1250-2--addendum-2026-10-27-more.md"]
|
||||
self.assertEqual(c.check(names, legacy={}), [])
|
||||
errors = c.check(["WR-1250--a.md", "WR-1250-2--addendum-2026-10-27-more.md"], legacy={})
|
||||
self.assertEqual(len(errors), 1)
|
||||
self.assertIn("WR-1250-2, but no record", errors[0])
|
||||
|
||||
def test_main_reads_directory(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
||||
Vendored
+3
-3
@@ -596,7 +596,7 @@ def parse_issue_files():
|
||||
if head is None:
|
||||
continue
|
||||
title = lines[head][5:].strip()
|
||||
m = re.match(r"([A-Z]+)-(\d+)\.\s*(.*)$", title)
|
||||
m = re.match(r"([A-Z]+)-(\d+)(-[2-9]|-[1-9]\d+)?\.\s*(.*)$", title)
|
||||
header, i = {}, head + 1
|
||||
while i < len(lines):
|
||||
f = re.match(r"^- \*\*(Severity|Area):\*\*\s*(.*)$", lines[i])
|
||||
@@ -614,8 +614,8 @@ def parse_issue_files():
|
||||
conf = fields.get("Confirmed", "").strip().lower()
|
||||
entries.append({
|
||||
"series": m.group(1) if m else "OTHER", "num": int(m.group(2)) if m else 0,
|
||||
"id": f"{m.group(1)}-{m.group(2)}" if m else title,
|
||||
"title": m.group(3) if m else title,
|
||||
"id": f"{m.group(1)}-{m.group(2)}{m.group(3) or ''}" if m else title,
|
||||
"title": m.group(4) if m else title,
|
||||
"severity": header.get("Severity", ""), "area": header.get("Area", ""),
|
||||
"body": body,
|
||||
"confirmed": "yes" if conf.startswith("yes") else ("no" if conf.startswith("no") else "unknown"),
|
||||
|
||||
Reference in New Issue
Block a user