Commit 3aff6ac017c1f4c40ae8c39de5da7263991d48bd
1 parent
733ce1e2
docs: routine-narrative playbook + gen_catalog preservation patch
- en/scripts/gen_catalog.py + zh/scripts/gen_catalog.py: snapshot the hand-written ## Narrative / ## 说明 section before the rmtree and re-inject it during regen, so manual prose survives. - en/scripts/narrate_routines.md: playbook for the long-running job of adding business-context narratives to the 1,684 procs + 177 funcs under auto-catalog/. Defines shape, lookup recipe, style rules, and the subagent resume protocol. - 3 sample narratives (Fn_find_modleAllId, sp_get_sOppositeColor, PRO_ERPMERGEBASESISWORKCENTER) demonstrate the shape and verify the generator preserves them across regen. - zh/docs/auto-catalog/* whitespace drift: regen aligns the committed zh catalog with the current generator template; no semantic content change, future regens are now no-op.
Showing
1928 changed files
with
3405 additions
and
3054 deletions
Too many changes to show.
To preserve performance only 100 of 1928 files are displayed.
en/docs/auto-catalog/functions/Fn_find_modleAllId.md
| ... | ... | @@ -20,4 +20,28 @@ _Body is not pre-cached. To inspect: `mysql --defaults-file=~/.my.cnf -e 'SHOW C |
| 20 | 20 | |
| 21 | 21 | ## Narrative |
| 22 | 22 | |
| 23 | -_No human-written narrative yet._ | |
| 23 | +**Business context:** Permission system, one-time initialization. | |
| 24 | +This is a niche helper, not a runtime utility — it's called by exactly | |
| 25 | +one routine: `sp_do_initsysjurisdiction`, which is the proc that | |
| 26 | +populates the per-user permission table (`sysjurisdiction`) when an | |
| 27 | +administrator runs the "initialize permissions" action on the | |
| 28 | +permission-management page. The function builds the module's full | |
| 29 | +ancestor-id chain so jurisdictions granted at a parent module | |
| 30 | +"inherit" to descendants via a `LIKE '-{ancestor}-%'` match on the | |
| 31 | +denormalized `gdsmodule.sAllId` column. | |
| 32 | + | |
| 33 | +**What it does:** walks `gdsmodule.sParentId` up from the input module | |
| 34 | +and returns the ancestor path joined with `-`, in the shape | |
| 35 | +`-{root}-{l4}-{l3}-{l2}-{l1}-{p_sModelId}`. The leading dash is | |
| 36 | +intentional — it makes the column suitable for prefix matching. | |
| 37 | + | |
| 38 | +**Where it sits in the module tree:** not user-visible; runs only | |
| 39 | +during permission initialization. Normal page loads read the | |
| 40 | +already-stored `gdsmodule.sAllId` column directly. | |
| 41 | + | |
| 42 | +**Caveats:** | |
| 43 | + | |
| 44 | +- **Depth-limited to 5 ancestors.** The body unrolls the parent walk | |
| 45 | + five times; modules deeper than 5 levels fall off the end and the | |
| 46 | + function returns NULL (no final `RETURN` statement). | |
| 47 | +- The live module tree is ≤4 levels deep today, so this hasn't bitten. | ... | ... |
en/docs/auto-catalog/procedures/PRO_ERPMERGEBASESISWORKCENTER.md
| ... | ... | @@ -17,4 +17,27 @@ _Body is not pre-cached. To inspect: `mysql --defaults-file=~/.my.cnf -e 'SHOW C |
| 17 | 17 | |
| 18 | 18 | ## Narrative |
| 19 | 19 | |
| 20 | -_No human-written narrative yet._ | |
| 20 | +**Business context:** Manufacturing — Work Center base data. When a | |
| 21 | +shop-floor work center (a press, a die-cutter, a binding line — a | |
| 22 | +production resource that owns work orders) is renamed in the | |
| 23 | +**工作中心** (Work Center) maintenance page, this proc updates the | |
| 24 | +denormalized work-center name on every historical | |
| 25 | +`ERPMERGEPRODUCTIONREPORT` row that references it. Without it, the | |
| 26 | +production reports under | |
| 27 | +**选择工序(轮转/丝印/胶印/按产品分类)** | |
| 28 | +(Choose Process — Rotary / Silk-screen / Offset / By-product-classification) | |
| 29 | +would keep displaying the old name forever. | |
| 30 | + | |
| 31 | +**What it does:** reads `SISWORKCENTER.sName` for the given id, then | |
| 32 | +updates every `ERPMERGEPRODUCTIONREPORT` row whose `sWorkCenterId` | |
| 33 | +matches. One-shot denormalization push. | |
| 34 | + | |
| 35 | +**Invocation:** the JMS `CHANGE_GDS_MODULE` consumer runs the | |
| 36 | +`PRO_ERPMERGEBASE*` family after a base-data row mutates, keeping | |
| 37 | +denormalized reporting tables in sync without a full rebuild. See | |
| 38 | +[Cache invalidation on metadata change](../../reference/maintainer/cache-invalidation.md) | |
| 39 | +for the dispatch mechanism — this is the JMS path, *not* the Redis | |
| 40 | +@CacheEvict path. | |
| 41 | + | |
| 42 | +**Tenant scope:** none — keyed only by globally-unique | |
| 43 | +`sSisWorkCenterId`. Caller is responsible for passing the right id. | ... | ... |
en/docs/auto-catalog/procedures/sp_get_sOppositeColor.md
| ... | ... | @@ -21,4 +21,29 @@ _Body is not pre-cached. To inspect: `mysql --defaults-file=~/.my.cnf -e 'SHOW C |
| 21 | 21 | |
| 22 | 22 | ## Narrative |
| 23 | 23 | |
| 24 | -_No human-written narrative yet._ | |
| 24 | +**Business context:** Printing-industry production setup. "Opposite | |
| 25 | +color" (`sOppositeColor` on `mftworkordercontrol`) is a per-work-order | |
| 26 | +print-color configuration — typically the alternate face's color list | |
| 27 | +for a double-sided print job, or a substitute-color mapping when the | |
| 28 | +target ink isn't available. This proc reads that configuration off a | |
| 29 | +specific work-order control row and forwards it for processing. | |
| 30 | + | |
| 31 | +**Status: appears orphaned.** No caller found in any channel — no | |
| 32 | +Java/MyBatis code, no SQL templates, no other procs, no metadata-side | |
| 33 | +form-master row, no module hook. Either: (a) called only from | |
| 34 | +customer-override SQL not in this snapshot, (b) called via dynamic | |
| 35 | +dispatch by a name passed in at runtime, or (c) dead code. Worth a | |
| 36 | +maintainer audit before relying on it. | |
| 37 | + | |
| 38 | +**What it does:** two steps. Reads `mftworkordercontrol.sOppositeColor` | |
| 39 | +for the input `sWorkOrderControlId`, tenant-scoped by | |
| 40 | +`sBrId`/`sSuId`. Then forwards that value (plus tenant ids and the | |
| 41 | +two OUT params) to | |
| 42 | +[`sp_get_sOppositeColor_data`](sp_get_sOppositeColor_data.md), which | |
| 43 | +does the actual color resolution. The split lets the same `*_data` | |
| 44 | +proc be called with an already-known `sOppositeColor` value — a | |
| 45 | +common xly pattern where `<proc>` / `<proc>_data` form an | |
| 46 | +"I have the id" / "I have the value" pair. | |
| 47 | + | |
| 48 | +**Naming note:** lowercase `sp_` prefix (vs. the majority `Sp_*`) — a | |
| 49 | +naming-style outlier, same engine type, just inconsistent casing. | ... | ... |
en/scripts/gen_catalog.py
| ... | ... | @@ -29,6 +29,35 @@ import pymysql |
| 29 | 29 | ROOT = Path(__file__).resolve().parent.parent |
| 30 | 30 | OUT = ROOT / "docs" / "auto-catalog" |
| 31 | 31 | |
| 32 | +# The Narrative section is the one place humans hand-edit auto-catalog pages | |
| 33 | +# (see narrate_routines.md for the playbook). collect_existing_narratives() | |
| 34 | +# snapshots these before the rmtree so the regen preserves them. | |
| 35 | +NARRATIVE_HEADER = "## Narrative" | |
| 36 | +NARRATIVE_PLACEHOLDER_PREFIX = "_No human-written narrative" | |
| 37 | + | |
| 38 | + | |
| 39 | +def collect_existing_narratives(root: Path) -> dict[str, str]: | |
| 40 | + """Map "<kind>/<slug>" → preserved Narrative body. Anything that still | |
| 41 | + holds the auto-generated placeholder is skipped, so the regen rewrites it | |
| 42 | + fresh in the new language/format.""" | |
| 43 | + preserved: dict[str, str] = {} | |
| 44 | + for sub in ("tables", "views", "procedures", "functions"): | |
| 45 | + d = root / sub | |
| 46 | + if not d.exists(): | |
| 47 | + continue | |
| 48 | + for f in d.glob("*.md"): | |
| 49 | + if f.name == "index.md": | |
| 50 | + continue | |
| 51 | + content = f.read_text(encoding="utf-8") | |
| 52 | + idx = content.find(NARRATIVE_HEADER) | |
| 53 | + if idx < 0: | |
| 54 | + continue | |
| 55 | + block = content[idx + len(NARRATIVE_HEADER):].lstrip("\n").rstrip() | |
| 56 | + if not block or block.startswith(NARRATIVE_PLACEHOLDER_PREFIX): | |
| 57 | + continue | |
| 58 | + preserved[f"{sub}/{f.stem}"] = block | |
| 59 | + return preserved | |
| 60 | + | |
| 32 | 61 | |
| 33 | 62 | def read_my_cnf() -> tuple[dict, str]: |
| 34 | 63 | """Parse ~/.my.cnf [client] section. Returns (connect_kwargs, db_name).""" |
| ... | ... | @@ -90,7 +119,7 @@ def write_index(path: Path, kind: str, items: list[dict], summary_keys: list[tup |
| 90 | 119 | path.write_text("\n".join(lines) + "\n", encoding="utf-8") |
| 91 | 120 | |
| 92 | 121 | |
| 93 | -def gen_tables(conn, db: str, out_dir: Path) -> list[dict]: | |
| 122 | +def gen_tables(conn, db: str, out_dir: Path, narratives: dict[str, str]) -> list[dict]: | |
| 94 | 123 | out_dir.mkdir(parents=True, exist_ok=True) |
| 95 | 124 | cur = conn.cursor() |
| 96 | 125 | cur.execute(""" |
| ... | ... | @@ -173,8 +202,12 @@ def gen_tables(conn, db: str, out_dir: Path) -> list[dict]: |
| 173 | 202 | |
| 174 | 203 | md.append("## Narrative") |
| 175 | 204 | md.append("") |
| 176 | - md.append("_No human-written narrative yet — when this table is exercised by a " | |
| 177 | - "[vertical slice](../../slices/index.md), link from there back to this page._") | |
| 205 | + preserved = narratives.get(f"tables/{slug(name)}") | |
| 206 | + if preserved: | |
| 207 | + md.append(preserved) | |
| 208 | + else: | |
| 209 | + md.append("_No human-written narrative yet — when this table is exercised by a " | |
| 210 | + "[vertical slice](../../slices/index.md), link from there back to this page._") | |
| 178 | 211 | md.append("") |
| 179 | 212 | |
| 180 | 213 | (out_dir / f"{slug(name)}.md").write_text("\n".join(md), encoding="utf-8") |
| ... | ... | @@ -191,7 +224,7 @@ def gen_tables(conn, db: str, out_dir: Path) -> list[dict]: |
| 191 | 224 | return views_meta |
| 192 | 225 | |
| 193 | 226 | |
| 194 | -def gen_views(conn, db: str, out_dir: Path, views_meta: list[dict]) -> None: | |
| 227 | +def gen_views(conn, db: str, out_dir: Path, views_meta: list[dict], narratives: dict[str, str]) -> None: | |
| 195 | 228 | out_dir.mkdir(parents=True, exist_ok=True) |
| 196 | 229 | cur = conn.cursor() |
| 197 | 230 | cur.execute(""" |
| ... | ... | @@ -248,7 +281,11 @@ def gen_views(conn, db: str, out_dir: Path, views_meta: list[dict]) -> None: |
| 248 | 281 | md.append("") |
| 249 | 282 | md.append("## Narrative") |
| 250 | 283 | md.append("") |
| 251 | - md.append("_No human-written narrative yet._") | |
| 284 | + preserved = narratives.get(f"views/{slug(name)}") | |
| 285 | + if preserved: | |
| 286 | + md.append(preserved) | |
| 287 | + else: | |
| 288 | + md.append("_No human-written narrative yet._") | |
| 252 | 289 | md.append("") |
| 253 | 290 | (out_dir / f"{slug(name)}.md").write_text("\n".join(md), encoding="utf-8") |
| 254 | 291 | |
| ... | ... | @@ -261,7 +298,7 @@ def gen_views(conn, db: str, out_dir: Path, views_meta: list[dict]) -> None: |
| 261 | 298 | write_index(out_dir / "index.md", "views", items, [("comment", "Comment")]) |
| 262 | 299 | |
| 263 | 300 | |
| 264 | -def gen_routines(conn, db: str, procs_dir: Path, fns_dir: Path) -> None: | |
| 301 | +def gen_routines(conn, db: str, procs_dir: Path, fns_dir: Path, narratives: dict[str, str]) -> None: | |
| 265 | 302 | procs_dir.mkdir(parents=True, exist_ok=True) |
| 266 | 303 | fns_dir.mkdir(parents=True, exist_ok=True) |
| 267 | 304 | cur = conn.cursor() |
| ... | ... | @@ -329,7 +366,12 @@ def gen_routines(conn, db: str, procs_dir: Path, fns_dir: Path) -> None: |
| 329 | 366 | |
| 330 | 367 | md.append("## Narrative") |
| 331 | 368 | md.append("") |
| 332 | - md.append("_No human-written narrative yet._") | |
| 369 | + kind_sub = "procedures" if rtype == "PROCEDURE" else "functions" | |
| 370 | + preserved = narratives.get(f"{kind_sub}/{slug(name)}") | |
| 371 | + if preserved: | |
| 372 | + md.append(preserved) | |
| 373 | + else: | |
| 374 | + md.append("_No human-written narrative yet._") | |
| 333 | 375 | md.append("") |
| 334 | 376 | |
| 335 | 377 | (out_dir / f"{slug(name)}.md").write_text("\n".join(md), encoding="utf-8") |
| ... | ... | @@ -356,15 +398,19 @@ def main() -> int: |
| 356 | 398 | print(f"Connecting to {cnf['host']}:{cnf['port']} db={db} as {cnf['user']}") |
| 357 | 399 | conn = pymysql.connect(database=db, **cnf) |
| 358 | 400 | try: |
| 401 | + # Snapshot hand-written Narrative sections so the regen preserves them. | |
| 402 | + narratives = collect_existing_narratives(OUT) | |
| 403 | + if narratives: | |
| 404 | + print(f"Preserving {len(narratives)} hand-written narrative(s).") | |
| 359 | 405 | # Wipe and rewrite each output dir to keep it strictly in sync with the live DB. |
| 360 | 406 | for sub in ("tables", "views", "procedures", "functions"): |
| 361 | 407 | d = OUT / sub |
| 362 | 408 | if d.exists(): |
| 363 | 409 | shutil.rmtree(d) |
| 364 | 410 | print(f"Writing to {OUT}") |
| 365 | - views_meta = gen_tables(conn, db, OUT / "tables") | |
| 366 | - gen_views(conn, db, OUT / "views", views_meta) | |
| 367 | - gen_routines(conn, db, OUT / "procedures", OUT / "functions") | |
| 411 | + views_meta = gen_tables(conn, db, OUT / "tables", narratives) | |
| 412 | + gen_views(conn, db, OUT / "views", views_meta, narratives) | |
| 413 | + gen_routines(conn, db, OUT / "procedures", OUT / "functions", narratives) | |
| 368 | 414 | print("Done.") |
| 369 | 415 | finally: |
| 370 | 416 | conn.close() | ... | ... |
en/scripts/narrate_routines.md
0 → 100644
| 1 | +# Routine Narratives — Playbook | |
| 2 | + | |
| 3 | +Long-running job: write a business-context narrative for every procedure | |
| 4 | +(1,687) and function (177) page in `en/docs/auto-catalog/{procedures,functions}/`, | |
| 5 | +replacing the auto-generated `_No human-written narrative yet._` placeholder | |
| 6 | +under each page's `## Narrative` heading. | |
| 7 | + | |
| 8 | +Goal: a maintainer reading the page learns **what business action this routine | |
| 9 | +serves**, not just what its parameter list is. The file:line citations live in | |
| 10 | +`reference/maintainer/`; routine narratives stay business-first. | |
| 11 | + | |
| 12 | +--- | |
| 13 | + | |
| 14 | +## Narrative shape (≤ ~15 lines per routine) | |
| 15 | + | |
| 16 | +``` | |
| 17 | +**Business context:** [module path from gdsmodule.sChinese — leaf → root, | |
| 18 | +" → " separated] — [one sentence: what user action / business outcome | |
| 19 | +triggers this] | |
| 20 | + | |
| 21 | +**What it does:** [terse mechanism, 1-3 sentences] | |
| 22 | + | |
| 23 | +**Invocation:** [how it's reached — form-master sSqlStr, gdsmodule hook, | |
| 24 | +chained from another proc, JMS CHANGE_GDS_MODULE path, or "no callers | |
| 25 | +found (candidate dead code)"] | |
| 26 | + | |
| 27 | +[Caveats / bugs / edge cases — only when worth flagging] | |
| 28 | +``` | |
| 29 | + | |
| 30 | +Three already-written samples for reference: | |
| 31 | +- `en/docs/auto-catalog/functions/Fn_find_modleAllId.md` | |
| 32 | +- `en/docs/auto-catalog/procedures/sp_get_sOppositeColor.md` (orphan example) | |
| 33 | +- `en/docs/auto-catalog/procedures/PRO_ERPMERGEBASESISWORKCENTER.md` (denorm-merge family) | |
| 34 | + | |
| 35 | +--- | |
| 36 | + | |
| 37 | +## Lookup recipe (per routine) | |
| 38 | + | |
| 39 | +```bash | |
| 40 | +ROUTINE="<name>" | |
| 41 | + | |
| 42 | +# 1. Body | |
| 43 | +mysql --defaults-file=~/.my.cnf xlyweberp_saas_ai \ | |
| 44 | + -e "SHOW CREATE {PROCEDURE|FUNCTION} $ROUTINE" | |
| 45 | + | |
| 46 | +# 2. Business-module location — form embeds (procs primarily) | |
| 47 | +mysql --defaults-file=~/.my.cnf xlyweberp_saas_ai -e " | |
| 48 | + SELECT gfm.sId AS form_sId, m.sId AS module_sId, m.sChinese, m.sParentId | |
| 49 | + FROM gdsconfigformmaster gfm | |
| 50 | + LEFT JOIN gdsmodule m ON gfm.sParentId = m.sId | |
| 51 | + WHERE gfm.sSqlStr LIKE '%$ROUTINE%' | |
| 52 | + OR gfm.sConfigSqlStr LIKE '%$ROUTINE%' | |
| 53 | + OR gfm.sSqlCondition LIKE '%$ROUTINE%'" | |
| 54 | + | |
| 55 | +# 3. Business-module location — module hooks (procs only) | |
| 56 | +mysql --defaults-file=~/.my.cnf xlyweberp_saas_ai -e " | |
| 57 | + SELECT sId, sChinese, sParentId, | |
| 58 | + sSaveProName, sSaveProNameBefore, sDeleteProName, sProcName | |
| 59 | + FROM gdsmodule | |
| 60 | + WHERE sSaveProName = '$ROUTINE' | |
| 61 | + OR sSaveProNameBefore = '$ROUTINE' | |
| 62 | + OR sDeleteProName = '$ROUTINE' | |
| 63 | + OR sProcName = '$ROUTINE'" | |
| 64 | + | |
| 65 | +# 4. Climb the module tree for any sId found in #2 or #3 (replace MID) | |
| 66 | +mysql --defaults-file=~/.my.cnf xlyweberp_saas_ai -e " | |
| 67 | + SELECT 1 d, sId, sChinese, sParentId FROM gdsmodule WHERE sId='MID' | |
| 68 | + UNION SELECT 2, sId, sChinese, sParentId FROM gdsmodule | |
| 69 | + WHERE sId=(SELECT sParentId FROM gdsmodule WHERE sId='MID') | |
| 70 | + UNION SELECT 3, m3.sId, m3.sChinese, m3.sParentId | |
| 71 | + FROM gdsmodule m3 | |
| 72 | + JOIN gdsmodule m2 ON m3.sId = m2.sParentId | |
| 73 | + JOIN gdsmodule m1 ON m2.sId = m1.sParentId | |
| 74 | + WHERE m1.sId = 'MID' | |
| 75 | + ORDER BY d" | |
| 76 | + | |
| 77 | +# 5. Other-routine callers (procs that CALL it, funcs that reference it) | |
| 78 | +mysql --defaults-file=~/.my.cnf xlyweberp_saas_ai -sNe " | |
| 79 | + SELECT ROUTINE_TYPE, ROUTINE_NAME | |
| 80 | + FROM information_schema.ROUTINES | |
| 81 | + WHERE ROUTINE_SCHEMA = 'xlyweberp_saas_ai' | |
| 82 | + AND ROUTINE_NAME != '$ROUTINE' | |
| 83 | + AND ROUTINE_DEFINITION LIKE '%$ROUTINE%'" | |
| 84 | + | |
| 85 | +# 6. Java / MyBatis XML / SQL-template refs | |
| 86 | +grep -rln "$ROUTINE" /Users/reporkey/Desktop/revs_engi_wiki/xly-src \ | |
| 87 | + --include="*.java" --include="*.xml" --include="*.sql" 2>/dev/null | |
| 88 | +``` | |
| 89 | + | |
| 90 | +**Orphan rule:** if #2 + #3 + #5 + #6 are all empty, the routine has no | |
| 91 | +discoverable caller. Flag in the narrative as `Status: appears orphaned. No | |
| 92 | +caller found in any channel — candidate for maintainer audit.` | |
| 93 | + | |
| 94 | +**`sSaveProName`/`sSaveProNameBefore`/`sDeleteProName`/`sProcName` live on | |
| 95 | +`gdsmodule`**, not on `gdsconfigformmaster`. The auto-catalog page text and | |
| 96 | +older wiki drafts sometimes confuse this — trust the queries above. | |
| 97 | + | |
| 98 | +--- | |
| 99 | + | |
| 100 | +## Style rules | |
| 101 | + | |
| 102 | +- **Keep Chinese module names in Chinese.** `sChinese` is what the user sees | |
| 103 | + in BACK. Don't translate `工作中心`, `选择工序(轮转)`, etc. — translating | |
| 104 | + breaks searchability against the live UI. | |
| 105 | +- **Use the three headings literally:** `**Business context:**`, | |
| 106 | + `**What it does:**`, `**Invocation:**`. Consistent shape aids scanning. | |
| 107 | +- **1–3 sentences per section. ≤15 lines total.** If the body is small and | |
| 108 | + self-explanatory, the narrative can be shorter. Don't pad. | |
| 109 | +- **No file:line citations to xly-src** in routine narratives. Those belong | |
| 110 | + in `reference/maintainer/`. Exception: if the routine is uniquely tied to | |
| 111 | + a single Java caller, name the class (not the line). | |
| 112 | +- **Cross-link only when load-bearing.** Relative paths: | |
| 113 | + `../../slices/...`, `../../reference/maintainer/...`, | |
| 114 | + `../procedures/<other>.md`, `../functions/<other>.md`. Test that the | |
| 115 | + target exists before adding the link. | |
| 116 | +- **Don't translate identifiers** — proc/function/column/table names stay as | |
| 117 | + written. | |
| 118 | +- **Don't editorialize** ("interestingly", "it's worth noting") — state | |
| 119 | + directly. | |
| 120 | +- **Don't claim Java callers without grepping.** The lookup recipe's step 6 | |
| 121 | + is the ground truth. | |
| 122 | + | |
| 123 | +--- | |
| 124 | + | |
| 125 | +## Resume protocol — what counts as "done" | |
| 126 | + | |
| 127 | +A routine is **done** when its `.md` file's `## Narrative` block contains | |
| 128 | +anything other than `_No human-written narrative yet._`. | |
| 129 | + | |
| 130 | +To get the live pending count and next batch: | |
| 131 | + | |
| 132 | +```bash | |
| 133 | +cd /Users/reporkey/Desktop/revs_engi_wiki/xly-wiki | |
| 134 | + | |
| 135 | +# Pending count | |
| 136 | +grep -l "_No human-written narrative yet._" \ | |
| 137 | + en/docs/auto-catalog/procedures/*.md \ | |
| 138 | + en/docs/auto-catalog/functions/*.md | wc -l | |
| 139 | + | |
| 140 | +# Next 20 pending (alphabetical) | |
| 141 | +grep -l "_No human-written narrative yet._" \ | |
| 142 | + en/docs/auto-catalog/procedures/*.md \ | |
| 143 | + en/docs/auto-catalog/functions/*.md | sort | head -20 | |
| 144 | +``` | |
| 145 | + | |
| 146 | +--- | |
| 147 | + | |
| 148 | +## Persistence — `gen_catalog.py` is patched | |
| 149 | + | |
| 150 | +Both `en/scripts/gen_catalog.py` and `zh/scripts/gen_catalog.py` now | |
| 151 | +snapshot the `## Narrative` (en) / `## 说明` (zh) block before the | |
| 152 | +`shutil.rmtree`, and re-inject preserved content during the regen. So | |
| 153 | +re-running the generator does **not** wipe human prose. Safe to regen | |
| 154 | +at any time. | |
| 155 | + | |
| 156 | +zh translation is a follow-up pass after en is complete. For now, write | |
| 157 | +English narratives only. | |
| 158 | + | |
| 159 | +--- | |
| 160 | + | |
| 161 | +## Subagent prompt template | |
| 162 | + | |
| 163 | +When the user says "continue", spawn ONE subagent with this prompt: | |
| 164 | + | |
| 165 | +``` | |
| 166 | +Read /Users/reporkey/Desktop/revs_engi_wiki/xly-wiki/en/scripts/narrate_routines.md | |
| 167 | +in full. It contains the goal, narrative shape, lookup recipe, style rules, | |
| 168 | +and resume protocol for adding business-context narratives to xly's stored | |
| 169 | +procedures and functions. | |
| 170 | + | |
| 171 | +Identify the next N pending routines using the resume-protocol command in the | |
| 172 | +playbook. N = 20 (or fewer if the routines are large/complex — judge from the | |
| 173 | +ROUTINE_DEFINITION size: large bodies take longer to read; aim for ≤90 minutes | |
| 174 | +of work). | |
| 175 | + | |
| 176 | +For each routine, in alphabetical order: | |
| 177 | + | |
| 178 | +1. Run the Lookup recipe end-to-end. Capture findings. | |
| 179 | +2. Write the narrative in the shape the playbook specifies — three labelled | |
| 180 | + sections, business-first, Chinese module names preserved. | |
| 181 | +3. Edit the .md file: replace `_No human-written narrative yet._` with the | |
| 182 | + narrative prose. Leave the `## Narrative` heading and surrounding blanks | |
| 183 | + intact. | |
| 184 | + | |
| 185 | +Don't dispatch sub-subagents. Don't rebuild the site. Don't run gen_catalog.py. | |
| 186 | +Don't translate anything to Chinese. | |
| 187 | + | |
| 188 | +When done with the batch: | |
| 189 | +- List the routine names processed, one per line. | |
| 190 | +- Run the resume-protocol command and print the new pending count. | |
| 191 | +- Note any orphans found (status: "no callers found") so the user can audit. | |
| 192 | +- Append a row to the Progress log table in narrate_routines.md. | |
| 193 | +``` | |
| 194 | + | |
| 195 | +--- | |
| 196 | + | |
| 197 | +## Progress log | |
| 198 | + | |
| 199 | +| Date | Procedures done | Functions done | Pending | Notes | | |
| 200 | +|---|---:|---:|---:|---| | |
| 201 | +| 2026-05-11 | 2 | 1 | 1861 | Initial 3 samples + gen_catalog.py preservation patch (en + zh) | | ... | ... |
zh/docs/auto-catalog/functions/CALC_MATERIALS_SMAIL.md
zh/docs/auto-catalog/functions/FUN_DISTINCTJSON_REMOVE_BYNAME.md
| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | |
| 18 | 18 | ## 主体 |
| 19 | 19 | |
| 20 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_DISTINCTJSON_REMOVE_BYNAME`'`。_ | |
| 20 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_DISTINCTJSON_REMOVE_BYNAME`'`。_ | |
| 21 | 21 | |
| 22 | 22 | ## 说明 |
| 23 | 23 | ... | ... |
zh/docs/auto-catalog/functions/FUN_GET_CALCPLAN_DATE_END.md
zh/docs/auto-catalog/functions/FUN_GET_CALC_DATE.md
zh/docs/auto-catalog/functions/FUN_GET_CALC_DATE_END.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC_ADDTIME.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC_STARTDATE.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC_STARTDATE_NEW.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NEW`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NEW`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC_STARTDATE_NEWTYPE.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NEWTYPE`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NEWTYPE`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/FUN_GET_DATE_BC_STARTDATE_NOW.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NOW`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `FUN_GET_DATE_BC_STARTDATE_NOW`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/FUN_GET_DATE_DIFF_MINUTE.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_KT.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_KT_ADD.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_UKT.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_UKT_ADD.md
zh/docs/auto-catalog/functions/FUN_GET_DATE_YX.md
zh/docs/auto-catalog/functions/FUN_GET_DECOMPOSECUSTOMIZE.md
zh/docs/auto-catalog/functions/FUN_GET_to_pinyin.md
zh/docs/auto-catalog/functions/FUN_JSON_CHAR.md
zh/docs/auto-catalog/functions/FUN_JSON_INT.md
zh/docs/auto-catalog/functions/FUN_MATERIALS_SMAIL.md
zh/docs/auto-catalog/functions/F_Gb2Big.md
zh/docs/auto-catalog/functions/Fn_ParseParams.md
zh/docs/auto-catalog/functions/Fn_find_modleAllId.md
zh/docs/auto-catalog/functions/Fn_find_pinyin.md
zh/docs/auto-catalog/functions/Fn_find_pinyin_copy1.md
zh/docs/auto-catalog/functions/Fn_fristPinyin.md
zh/docs/auto-catalog/functions/Fn_json_extract.md
zh/docs/auto-catalog/functions/Fn_spit_length.md
zh/docs/auto-catalog/functions/Fn_split_string.md
zh/docs/auto-catalog/functions/Fun_AnalysisListJson.md
zh/docs/auto-catalog/functions/Fun_AnalysisListJsonEnter.md
zh/docs/auto-catalog/functions/Fun_AnalysisListJsonOld.md
zh/docs/auto-catalog/functions/Fun_AnalysisListJsonTwo.md
zh/docs/auto-catalog/functions/Fun_AnalysisListJson_copy1.md
zh/docs/auto-catalog/functions/Fun_Cashier_GetMaterialsPrice.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/Fun_Cashier_GetMaterialsPrice_Quo.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice_Quo`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice_Quo`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/Fun_Cashier_GetMaterialsPrice_new.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice_new`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetMaterialsPrice_new`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/Fun_Cashier_GetProductPrice.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetProductPrice`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetProductPrice`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_Cashier_GetProductPrice_new.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetProductPrice_new`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_Cashier_GetProductPrice_new`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_Exclusion_algorithm.md
zh/docs/auto-catalog/functions/Fun_FormulaReplace.md
zh/docs/auto-catalog/functions/Fun_Formula_Process.md
zh/docs/auto-catalog/functions/Fun_Gb2Big_ChineseToBig.md
zh/docs/auto-catalog/functions/Fun_GetAddBillNo.md
zh/docs/auto-catalog/functions/Fun_GetAddMapJson.md
zh/docs/auto-catalog/functions/Fun_GetAuxiliaryQtyUnit.md
zh/docs/auto-catalog/functions/Fun_GetBarId.md
zh/docs/auto-catalog/functions/Fun_GetBillStatus.md
zh/docs/auto-catalog/functions/Fun_GetBookStickQty.md
zh/docs/auto-catalog/functions/Fun_GetCalcMaterialsKs.md
zh/docs/auto-catalog/functions/Fun_GetCalcMaterialsKs1.md
zh/docs/auto-catalog/functions/Fun_GetCh.md
zh/docs/auto-catalog/functions/Fun_GetFatherProductId.md
zh/docs/auto-catalog/functions/Fun_GetGb.md
zh/docs/auto-catalog/functions/Fun_GetHumpDiff.md
zh/docs/auto-catalog/functions/Fun_GetJson_Length.md
zh/docs/auto-catalog/functions/Fun_GetLimitDate.md
zh/docs/auto-catalog/functions/Fun_GetListByJson_ByKey.md
zh/docs/auto-catalog/functions/Fun_GetListByJson_ByKey_split.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListByJson_ByKey_split`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListByJson_ByKey_split`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetListByJson_ByKey_wrap.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListByJson_ByKey_wrap`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListByJson_ByKey_wrap`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetListBy_BysCombineChild.md
| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | ## 主体 |
| 18 | 18 | |
| 19 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListBy_BysCombineChild`'`。_ | |
| 19 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListBy_BysCombineChild`'`。_ | |
| 20 | 20 | |
| 21 | 21 | ## 说明 |
| 22 | 22 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey1.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey2.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey5.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey6.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKeyNew.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByKey_copy1.md
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | |
| 20 | 20 | ## 主体 |
| 21 | 21 | |
| 22 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListJson_ByKey_copy1`'`。_ | |
| 22 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetListJson_ByKey_copy1`'`。_ | |
| 23 | 23 | |
| 24 | 24 | ## 说明 |
| 25 | 25 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetListJson_ByName.md
zh/docs/auto-catalog/functions/Fun_GetListJson_ByNameAPS.md
zh/docs/auto-catalog/functions/Fun_GetLoginUser.md
zh/docs/auto-catalog/functions/Fun_GetLoginUserLanguage.md
zh/docs/auto-catalog/functions/Fun_GetLoginUserLanguage_copy1.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetLoginUserLanguage_copy1`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetLoginUserLanguage_copy1`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetLoginUserName.md
zh/docs/auto-catalog/functions/Fun_GetLoginUserType.md
zh/docs/auto-catalog/functions/Fun_GetLookCustomer.md
zh/docs/auto-catalog/functions/Fun_GetLookProcess.md
zh/docs/auto-catalog/functions/Fun_GetMachineLenWidth.md
zh/docs/auto-catalog/functions/Fun_GetMachineLenWidthAPS.md
zh/docs/auto-catalog/functions/Fun_GetMachineWorkEndDate.md
zh/docs/auto-catalog/functions/Fun_GetMachineWorkStartDate.md
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | |
| 21 | 21 | ## 主体 |
| 22 | 22 | |
| 23 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetMachineWorkStartDate`'`。_ | |
| 23 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetMachineWorkStartDate`'`。_ | |
| 24 | 24 | |
| 25 | 25 | ## 说明 |
| 26 | 26 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetMachineWorkWorkType.md
zh/docs/auto-catalog/functions/Fun_GetMaterialsQtyUnit.md
zh/docs/auto-catalog/functions/Fun_GetMaterialsQtyUnitSupple.md
| ... | ... | @@ -21,7 +21,7 @@ |
| 21 | 21 | |
| 22 | 22 | ## 主体 |
| 23 | 23 | |
| 24 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetMaterialsQtyUnitSupple`'`。_ | |
| 24 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetMaterialsQtyUnitSupple`'`。_ | |
| 25 | 25 | |
| 26 | 26 | ## 说明 |
| 27 | 27 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetNum.md
zh/docs/auto-catalog/functions/Fun_GetNumFirst.md
zh/docs/auto-catalog/functions/Fun_GetPackQty.md
zh/docs/auto-catalog/functions/Fun_GetProcessAuxiliaryQty.md
zh/docs/auto-catalog/functions/Fun_GetReelAuxiliaryQtyUnit.md
| ... | ... | @@ -22,7 +22,7 @@ |
| 22 | 22 | |
| 23 | 23 | ## 主体 |
| 24 | 24 | |
| 25 | -_主体未预缓存。如需查看: `mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetReelAuxiliaryQtyUnit`'`。_ | |
| 25 | +_主体未预缓存。如需查看:`mysql --defaults-file=~/.my.cnf -e 'SHOW CREATE FUNCTION `Fun_GetReelAuxiliaryQtyUnit`'`。_ | |
| 26 | 26 | |
| 27 | 27 | ## 说明 |
| 28 | 28 | ... | ... |
zh/docs/auto-catalog/functions/Fun_GetReportId_byLogType.md
zh/docs/auto-catalog/functions/Fun_GetSystemSetting.md
zh/docs/auto-catalog/functions/Fun_GetTestCount.md
zh/docs/auto-catalog/functions/Fun_GetTestMaterialsCount.md