-------------------------------------------------------------------------------- DOCUMENT CONTROL (HEADER) -------------------------------------------------------------------------------- Document ID : DARH_TECH_PARSER_001 Title : Daralbeida BPGP Viewer Parser, Code Manual and Limitations Reference Version : 1.10 Status : DRAFT Classification : Internal; sharable with AI tools and contractors on onboarding Prepared By : PYB / Daralbeida Reviewed By : (pending) Approved By : (pending) Approval Date : (pending) Owner : PYB / Daralbeida Date Created : 2026-05-30 Last Revised : 2026-05-30 17:00 UTC Update Cycle : 90 days Next Review Due : 2026-08-28 Annual Review : 2027-05-30 Retention : Duration of Daralbeida operations Department : TECH Style : BPGP Keywords : BPGP, parser, viewer, document management, code manual, technical reference, limitations Related Docs : DARH_STDS_BPGP_202605300724.txt (BPGP v3.0 standard); _devt/11/0101/darx_txt_vwr.php (the parser source) Supersedes : (none, initial issue) Superseded By : (none, current version) -------------------------------------------------------------------------------- OUTLINE -------------------------------------------------------------------------------- 1. Purpose and Scope 2. Parser Architecture 2.1 Pipeline Overview 2.2 Server vs Client Responsibilities 2.3 Entry Points 3. Header Block Parsing 3.1 Boundary Detection 3.2 Field Extraction 3.3 Document ID Display 3.4 Captured Fields 4. Section Detection 4.1 Bar Title Bar Pattern, BPGP v3.0 4.2 Title Bar Pattern, Legacy v1.x 4.3 ALL CAPS Title Requirement 4.4 Section Numbering and Anchor IDs 5. Sub-Section Detection 5.1 N.N and N.N.N Pattern 5.2 Title Casing (BPGP v3.1) 5.3 Disambiguation Safeguards 5.4 Preserved Number Format 6. Document Control Footer 6.1 Trigger Variants Accepted 6.2 Flush Left Requirement 6.3 First Match Wins Rule 7. END OF DOCUMENT Terminator 7.1 Bare String Match 7.2 Legacy DOC ID Suffix Variant 7.3 Flush Left Anchor 8. Outline Block Extraction 8.1 Detection 8.2 Entry Parsing 8.3 Rendered TOC Card 8.4 Anchor ID Synthesis 9. Block Types in the Body Loop 9.1 Paragraphs and R1 Collapse 9.2 Sub-Labels, Three Patterns 9.3 Template Blocks 9.4 Bullet Lists 9.5 Horizontal Rules 9.6 Matrix Tables 9.7 Definition Rows, Acronyms and Glossary 9.8 Document Control Key Value Rows 10. Inline Acronym Auto Boxing 10.1 Detection Rule 10.2 Lower Case Neighbour Filter 10.3 Hyphenated Compound IDs 10.4 False Positive Mitigations 11. Filename Conventions Understood 11.1 Entity Prefix 11.2 Date and Date Plus Time Stamps 11.3 Category Token Routing 12. Filesystem Metadata Layer 12.1 Server Side Stat 12.2 Encoded Stamp Decoding 12.3 Integrity Check, Three Way Comparison 13. Entity Color Program 13.1 Three Entities Plus Default 13.2 CSS Custom Property Override 13.3 Department Name Mapping 14. Exception Registry 14.1 What This Is 14.2 Current Entries (EX-01 through EX-17) 14.3 Adding a New Exception (four-step procedure) 14.4 Golden Rule for Exception Additions 15. Canary Set and Regression Protocol 15.1 What a Canary Doc Is 15.2 The Ten Canary Docs 15.3 Pre-Change Checklist 15.4 Visual Audit Page 15.5 Snapshot Diff CLI 16. Known Limitations 16.1 Header Parsing 16.2 Section Detection (Top Level) 16.3 Body Rendering 16.4 Definition Rows 16.5 Acronym Inline Boxing 16.6 Performance 17. Extension Points 18. AI Prompts 19. Revision History 20. Acronyms 21. Glossary DOCUMENT CONTROL (FOOTER) -------------------------------------------------------------------------------- RULE SUMMARY (R1, R2, R3) ================================================================================ This document conforms to BPGP v3.0. Three rules govern its formatting. R1 Each body paragraph is a SINGLE unbroken line. No internal line breaks. Paragraphs are separated by one blank line. Paragraph lines are the only lines permitted to exceed 80 characters. R2 The AI PROMPTS section (Section 16) is mandatory and carries a copy-paste prompt that regenerates this document with fresh content. R3 Every line that is NOT a body paragraph is 80 characters or fewer. ================================================================================ 1. PURPOSE AND SCOPE ================================================================================ This document is the technical reference for the Daralbeida BPGP viewer parser implemented at _devt/11/0101/darx_txt_vwr.php. It documents every detection rule, block type, transformation, and rendering decision the parser makes, plus the limitations a contributor must be aware of when authoring BPGP documents or extending the parser. It is intended for the engineer (or AI agent) maintaining the viewer, not for end users who simply read documents through it. The parser is the single most important piece of code in the document management system because it dictates which BPGP files render correctly and which do not. Authors must produce files that conform to the contracts in this manual; engineers extending the parser must preserve those contracts and document deviations here. ================================================================================ 2. PARSER ARCHITECTURE ================================================================================ 2.1 PIPELINE OVERVIEW The viewer pipeline runs entirely in the browser after the PHP server inlines a small metadata block. The user navigates to darx_txt_vwr.php with a file2show URL parameter; PHP sanitises and stats the target file and inlines the result as JSON; the page loads; the client script fetches the .txt content; the parser walks the text line by line and produces a sequence of typed blocks; the renderer turns the blocks into HTML; helpers populate the chrome (top nav, bottom nav, source readout, outline card) from the parsed header and section list. 2.2 SERVER VS CLIENT RESPONSIBILITIES The server handles filename sanitisation, file existence and readability checks, byte size, mtime, ctime, line count, encoded YYYYMMDDHHMM stamp decoding, and integrity comparison metadata. Everything else, including all section detection, block type assignment, and rendering, runs in the browser. 2.3 ENTRY POINTS The browser pipeline lives inside a single async IIFE. The entry sequence is parse URL, apply entity style, fetch file, parseDoc(raw), extractOutline(raw), populateChrome(filename, header, entityKey), populateFilesystemMeta(header), renderSections(sections, outline), renderBottomNav(sections), setupScrollSpy(), scrollToHashTarget(). Each helper is independent and can be replaced without disturbing the others, provided contracts (block-type list, section shape, header field set) are preserved. ================================================================================ 3. HEADER BLOCK PARSING ================================================================================ 3.1 BOUNDARY DETECTION The header parser begins at line zero and consumes lines until one of three boundary conditions: a line starting with four or more equals signs (the body begins), or the BPGP legacy Title plus Bar pattern (an ALL CAPS numbered title line immediately followed by an equals rule). The second condition exists so that v1.x files with the legacy section layout do not silently swallow the first section title into the header preamble. 3.2 FIELD EXTRACTION Each line in the captured header block is then re-walked. Separator lines (long runs of hyphens or equals) are skipped. A line that matches the pattern UPPERCASE_CODE separator UPPERCASE_CODE (e.g. DARM_LEG_RESEARCH_001) and has not yet been claimed as Document ID becomes the docId. Otherwise the parser tries to match Key : Value with the regex caret CapitalLetter then letters or whitespace then colon then whitespace then value, lowercases the key, and dispatches on the result. 3.3 DOCUMENT ID DISPLAY Per BPGP v2.0+, Document IDs use underscores. The parser preserves the underscored form in display (earlier versions converted to hyphens, which violated the standard). When a v1.x file with a hyphenated ID is loaded, the hyphenated form is shown verbatim (no normalisation is performed), since converting would mask the legacy nature of the file. 3.4 CAPTURED FIELDS The header parser populates a header object with these fields when present: title, version, date (alias for Date Created), owner (alias for Prepared By), classification, docId (alias for Document or Document ID), status, dept, lastRevised, updateCycle, nextReview, annualReview, keywords. Continuation lines starting with a bare colon (older convention) are ignored. Lines that match no rule and arrive when header.title has been set are silently consumed. ================================================================================ 4. SECTION DETECTION ================================================================================ 4.1 BAR TITLE BAR PATTERN, BPGP v3.0 The canonical pattern is three lines: an 80-character rule of equals signs, a numbered title in the form N. TITLE, then another 80-character rule. The parser checks isBar on the current line and isBar on the line two ahead and applies a regex N period whitespace title to the line in between. When all three conditions match, a new section is pushed and the index advances by three lines. 4.2 TITLE BAR PATTERN, LEGACY v1.x Many v1.x documents place the equals rule below the title only. The parser accepts this pattern by checking the current line against the same N period whitespace title regex and the next line against isBar. The title must additionally be ALL CAPS for this branch to fire, which prevents false positives when a paragraph happens to begin with a digit and a period. 4.3 ALL CAPS TITLE REQUIREMENT In both patterns, the title must be ALL CAPS to qualify as a section heading. Mixed case in the title disqualifies the line so that lines like 6.1 Legal Framework do not become top-level sections (those become sub-sections via the 5.1 branch). 4.4 SECTION NUMBERING AND ANCHOR IDS The parser preserves the section number as written. Anchors are formed by prefixing s and replacing dots with underscores: top-level becomes s1, s2; sub-sections become s5_1, s5_2; sub-sub-sections become s5_1_1. The bottom nav and the OUTLINE TOC use these anchors to link directly to the rendered DOM. ================================================================================ 5. SUB-SECTION DETECTION ================================================================================ 5.1 N.N AND N.N.N PATTERN Within the body of a section, a line that matches the regex `^(\d+\.\d+(?:\.\d+)?)\s+(.+?)\s*$` is a candidate H2 sub-section heading. The regex captures both two-segment numbers (sub-section, 5.1) and three-segment numbers (sub-sub-section, 5.1.2). Sub-sub-sections render as H2 with the deeper number; the page rendering model carries two heading levels (H1 for top-level sections, H2 for everything beneath). 5.2 TITLE CASING (BPGP v3.1) As of parser manual v1.2, BOTH casings are accepted for sub-section titles: (a) ALL CAPS, canonical BPGP v3.0 form, e.g. "5.1 YEAR 1 PROOF OF CONCEPT". (b) Title Case, real-world editorial form, e.g. "5.1 Year 1 — Proof of Concept". This was added to support business-plan documents that follow standard English editorial conventions for headings instead of the all-caps shouting style. The BPGP v3.1 standard treats both as conforming. 5.3 DISAMBIGUATION SAFEGUARDS Without the legacy ALL-CAPS-only filter, ordinary prose that happens to start with a digit-pair (for example "5.1 of the contract states that the supplier shall...") risks being detected as a heading. Three safeguards in combination keep the detector accurate: (a) Overall line length must be at most 100 characters. Headings stay short in BPGP; a long line is paragraph content. (b) The title portion must not end with sentence-ending punctuation (period, semicolon, colon, exclamation, question mark). Headings have no trailing terminator; paragraphs do. (c) The next non-blank context must be one of: a blank line, another sub-section heading, a top-level section heading, or a bar rule. In BPGP, headings sit alone on their own line and are followed by a blank line before any body content. A line that continues into prose on the next line is paragraph content. A candidate must satisfy all three guards. If any one fails, the line falls through to the paragraph buffer. 5.4 PRESERVED NUMBER FORMAT The parser preserves the section number verbatim in the captured group. Anchor IDs are formed by replacing dots with underscores: top-level becomes s1, s2; sub-sections become s5_1, s5_2; sub-sub-sections become s5_1_1. The bottom nav and OUTLINE TOC link to these anchors. ================================================================================ 6. DOCUMENT CONTROL FOOTER ================================================================================ 6.1 TRIGGER VARIANTS ACCEPTED The footer block is triggered by either the bare string DOCUMENT CONTROL or the v3.0 self-documenting form DOCUMENT CONTROL (FOOTER). Both must be flush left to avoid catching the same string when it appears inside an example block in the BPGP standard itself. 6.2 FLUSH LEFT REQUIREMENT The original implementation used the trimmed line for comparison, which caused the BPGP standard document to spawn three phantom footers (one for the real footer, two for indented examples). The fix is to compare the raw line; only column-zero matches are treated as triggers. 6.3 FIRST MATCH WINS RULE Even with flush-left matching, a long document with multiple discussion-block examples could produce more than one trigger. The parser tracks whether any section has the isControl flag set and silently ignores subsequent triggers, so a document has at most one DC entry. ================================================================================ 7. END OF DOCUMENT TERMINATOR ================================================================================ 7.1 BARE STRING MATCH The canonical terminator is the exact line END OF DOCUMENT (no suffix, no punctuation). The parser breaks out of the body loop on this line. 7.2 LEGACY DOC ID SUFFIX VARIANT Older OPS-track docs use END OF DOCUMENT followed by an em dash and the Document ID. The parser also accepts this suffix variant via a regex that requires the literal prefix and a hyphen or em dash separator with non-empty content after it. 7.3 FLUSH LEFT ANCHOR Both variants must be flush left at column zero. Indented examples of the terminator inside the BPGP standard itself (Section 13.5 of DARH_STDS_BPGP) are deliberately not matched. ================================================================================ 8. OUTLINE BLOCK EXTRACTION ================================================================================ 8.1 DETECTION The OUTLINE block sits in the preamble before the first equals rule. The extractOutline helper scans the raw text for a line equal to OUTLINE, skips any number of hyphen rules immediately after it, and reads entries until the next hyphen rule. 8.2 ENTRY PARSING Each entry is detected by the regex any-indent then a numbered code (N, N.N, or N.N.N) then a period and whitespace then a title. The level (0, 1, or 2) is inferred from the dot count in the number. 8.3 RENDERED TOC CARD The renderer turns the entries into an aside class outline-card with a head bar (label, count, collapse toggle) and a nav list of clickable items. Each item is an anchor pointing to the synthesized section ID (#s1, #s5_2, etc.). The card supports a collapsed state via a class on the wrapper. 8.4 ANCHOR ID SYNTHESIS The synthesised ID mirrors the rendered heading IDs: s plus the dotted number with dots replaced by underscores. If the dotted number in the OUTLINE block does not correspond to a real rendered heading (typo, mismatched outline), the anchor will fail silently. Validating the outline against the rendered sections is the author's responsibility. ================================================================================ 9. BLOCK TYPES IN THE BODY LOOP ================================================================================ 9.1 PARAGRAPHS AND R1 COLLAPSE The default block type is p (paragraph). Consecutive non-empty non-special lines accumulate into a buf array. When a blank line, terminator, or block-changing line is encountered, flushParagraph joins the buffer with single spaces (collapsing internal whitespace runs) and pushes a p block. This is R1 enforcement on render, which makes pre-R1 v1.x documents flow correctly without their hard wraps becoming visible breaks. 9.2 SUB-LABELS, THREE PATTERNS A sublabel is an inline editorial mark like Decision criteria. Three forms are recognised: title case with trailing colon (canonical), ALL CAPS with trailing colon (banner), and ALL CAPS without colon (legacy chat-files-inventory pattern). All three are limited to 50 characters and must contain only letters, digits, spaces, and the punctuation set hyphen, slash, ampersand, parentheses, and comma. 9.3 TEMPLATE BLOCKS A line that begins with the literal Template followed by an em dash and a topic starts a template block. The body collects following non-empty lines until a blank line. The renderer outputs a styled quotation with a gold left border. 9.4 BULLET LISTS A bullet list is triggered by a line matching whitespace then hyphen then space. Consecutive bullet lines are gathered, with continuation lines (four or more leading spaces, no leading hyphen) appended to the previous item. The output is a ul. 9.5 HORIZONTAL RULES A line of five or more hyphens, equals signs, U+2500, or U+2550 becomes a rule block, rendered as an hr with the doc-rule class. ASCII equals signs were added to this class so legacy v1.x mid-body PART 2 dividers render as separators instead of paragraph text. 9.6 MATRIX TABLES A header row immediately followed by a row of U+2500 box-drawing characters becomes a matrix. The parser identifies column anchor positions from the runs of U+2500, then parses each subsequent row by snapping space-separated segments to the nearest anchor. A blank row, a hyphen rule, or another section heading ends the table. ASCII hyphens as the separator are not recognised; this is a parser contract that authors must follow. 9.7 DEFINITION ROWS, ACRONYMS AND GLOSSARY When the current section's title matches the substring acronym (case-insensitive) or glossar, each body line is fed through tryDefLine before paragraph accumulation. The acronym pattern is leading whitespace then a code of one to twelve characters in letters, digits, slash, dash, dot, underscore, or plus, then two or more spaces, then a definition. The glossary pattern is leading whitespace then a term then an em dash then a definition. Continuation lines append to the previous definition. The output is a def block with term and def fields, rendered as a two-column grid with a colored chip and definition text. 9.8 DOCUMENT CONTROL KEY VALUE ROWS Inside the DC footer, lines matching CapitalLetter then non-colon characters then colon then whitespace then value are emitted as kv blocks and rendered as info rows in a styled info block. Other lines inside the footer fall through to paragraph rendering. ================================================================================ 10. INLINE ACRONYM AUTO BOXING ================================================================================ 10.1 DETECTION RULE After paragraph escapes are applied, wrapAcronyms scans for any run of two or more consecutive uppercase letters with optional internal hyphens and a trailing digit run (regex caret-boundary then bracket A-Z bracket 2 comma then non-capturing hyphen plus bracket A-Z 0-9 bracket plus close star then non-capturing bracket 0-9 bracket plus question close then boundary). 10.2 LOWER CASE NEIGHBOUR FILTER A candidate match is only wrapped when at least one of its neighbour words (the closest word-character run before or after, within 40 characters) contains a lowercase letter. This filter prevents boxing in all-caps headings, all-caps banners, and adjacent all-caps phrase pairs like DOCUMENT CONTROL. 10.3 HYPHENATED COMPOUND IDS Compound IDs like DAB-SOP-SOURCING-001 are wrapped as a single span because the regex's internal hyphen group captures them. 10.4 FALSE POSITIVE MITIGATIONS Numbers alone do not trigger (the regex requires uppercase letters). Single uppercase characters do not trigger (the regex requires two or more). Compound forms with mixed case (e.g. ACoS in the parsed acronym list) match because the run of uppercase A and C and S in sequence is two; the parser preserves the source mixed case verbatim inside the span. 10.5 EXCEPTION LIST (ACRONYM_EXCEPTIONS) Even with the lowercase-neighbour filter, certain ALL-CAPS tokens are not real acronyms in prose and should read as natural words. The most common offender is a corporate suffix sitting next to a brand name, where the suffix would otherwise be wrapped as a chip and visually fragment the wordmark (for example, "Daralbeida Maroc SARL" should never render as "Daralbeida Maroc [SARL]" with the SARL boxed). ACRONYM_EXCEPTIONS is a Set of uppercase tokens that are bypassed before the neighbour test runs. Membership is checked via Set.has on the uppercased acronym match, so it is case-insensitive at the call site (the entries themselves MUST be uppercase). 10.6 EXCEPTION LIST, DEFAULT MEMBERSHIP The list ships pre-populated with the categories below. Maintainers should extend the list as new false positives are observed in real documents; the change is one line per token, no other code needs to be touched. (a) Anglo company suffixes: LLC, LLP, LP, PLLC, INC, CORP, CO, LTD, PLC. (b) France, Maroc, Belgium, Lux company suffixes: SARL, SAS, SASU, SA, SCI, SCS, SNC, EURL, SCA, SCP. (c) German, Austrian, Swiss company suffixes: GMBH, AG, KG, OHG, UG, GBR. (d) Benelux company suffixes: BV, NV, CV, VOF. (e) Iberian and Italian company suffixes: SL, SLU, SLNE, SPA, SRL, SAPA, SCRL. (f) Nordic and Baltic company suffixes: AB, ASA, APS, OY, OYJ, AS. (g) Asian company suffixes: KK, YK, PVT, PTE, BHD, SDN. (h) Country and region codes seen naked in prose: US, USA, UK, EU, UAE, KSA, MA. (i) Currency codes seen naked in prose: USD, EUR, GBP, MAD, AED, CHF, JPY, CNY. (j) Other two-letter common words: OK. 10.7 EXTENDING THE EXCEPTION LIST To add a new exception, open darx_txt_vwr.php, locate ACRONYM_EXCEPTIONS (declared immediately above wrapAcronyms in the IIFE body), and add the uppercase token as a new Set entry. No cache busting is required beyond the usual filemtime suffix on the viewer file include. Removed tokens reactivate boxing for that string on next reload. 10.8 WHAT NOT TO ADD Do not add tokens that ARE meaningful in the document body and should keep being boxed: real acronyms (KPI, ROI, EBITDA, GTIN, ASIN, FBA, P&L are intentionally boxed because they read as technical terms). Do not add internal Daralbeida identifiers (DARX, DARH, DARM, DAB) because they appear at the head of every document ID and the box is the intended visual cue. ================================================================================ 11. FILENAME CONVENTIONS UNDERSTOOD ================================================================================ 11.1 ENTITY PREFIX Filenames must begin with DARX, DARH, DARM, or DAB. The entity prefix selects the color program (gold, navy, terracotta, or default gold) and the displayed legal entity name in the centered banner. 11.2 DATE AND DATE PLUS TIME STAMPS The parser's filename helpers accept either an 8-digit YYYYMMDD stamp (legacy v1.x and v2.0) or a 12-digit YYYYMMDDHHMM stamp (BPGP v2.2 and v3.0). The 12-digit form is the canonical and current standard; the 8-digit form is supported for backwards compatibility. 11.3 CATEGORY TOKEN ROUTING The CATEGORY token (the second underscore-separated segment of the filename) is mapped to a department name via the DEPTS table. The mapping is used in the centered banner and may also be set from the header's Department field, which takes precedence when present. ================================================================================ 12. FILESYSTEM METADATA LAYER ================================================================================ 12.1 SERVER SIDE STAT The PHP entry sanitises the file2show parameter, resolves the file under _devt/11/0101/txt/, and calls filesize, filemtime, and filectime. Line count is computed by streaming the file and substr-counting newline characters. The result is inlined as a JSON script block on the page. 12.2 ENCODED STAMP DECODING If the filename matches the canonical pattern, the YYYYMMDDHHMM token is decoded into a Unix timestamp via gmmktime. Both 8-digit and 12-digit forms are supported. The decoded timestamp is included in the metadata for the integrity check. 12.3 INTEGRITY CHECK, THREE WAY COMPARISON The browser compares three sources of truth for the document's revision instant: the filesystem mtime, the YYYYMMDDHHMM encoded in the filename, and the Last Revised field declared inside the document header. A discrepancy greater than five minutes between any pair surfaces as a red Integrity warning pill in the Source row. ================================================================================ 13. ENTITY COLOR PROGRAM ================================================================================ 13.1 THREE ENTITIES PLUS DEFAULT Four entity registries are defined: DARH (Holdings, navy), DARX (Brands, gold), DARM (Maroc, terracotta), and DAB (legacy default, gold). Each carries an accent triplet, a sublabel (now superseded by the full entity name), and the human entity name. 13.2 CSS CUSTOM PROPERTY OVERRIDE The selected entity's accent values override the root variables --accent, --accent-mid, and --accent-bg. Everything else in the chrome that uses these variables (def chips, sub-labels, table headers, scroll ruler) re-themes automatically. 13.3 DEPARTMENT NAME MAPPING A separate DEPTS table maps category codes (LEG, COMM, OPS, BI, etc.) to full department names. This is used to populate the LEGAL or OPERATIONS or BUSINESS INTELLIGENCE label below the entity name in the centered banner. ================================================================================ 14. EXCEPTION REGISTRY ================================================================================ 14.1 WHAT THIS IS The EXCEPTION REGISTRY is the catalogue of every special-text condition the parser handles beyond the BPGP canonical form. Each entry pairs an exception ID (EX-NN) with the detector that handles it. The registry lives at the top of parseDoc in darx_txt_vwr.php as a comment block. Each detector in the body loop carries a matching banner comment that references its EX-NN. 14.2 CURRENT ENTRIES EX-01 Legacy Title-Bar section heading (v1.x). Accepted alongside the v3 Bar-Title-Bar canonical form. EX-02 Legacy END OF DOCUMENT suffix variant. "END OF DOCUMENT — DOC_ID" accepted alongside the bare "END OF DOCUMENT" terminator. EX-03 Flush-left rule for the DOCUMENT CONTROL trigger. Prevents catching the trigger string inside indented examples within the BPGP standard itself. First flush-left match wins. EX-04 Title Case sub-section titles. As of BPGP v3.1, both ALL CAPS and Title Case are accepted for N.N and N.N.N headings. Disambiguated by line length (at most 100 chars), no trailing sentence-end punctuation, and next-line-must-be-blank-or-heading-or-bar. EX-05 Sub-label three-variant acceptance: Title Case plus colon, ALL CAPS plus colon, and ALL CAPS without colon (legacy inventory-style docs). EX-06 Horizontal rule accepts four characters: ASCII hyphen, ASCII equals, U+2500 box-draw, U+2550 double box-draw. ASCII equals supports legacy v1.x inline dividers. EX-07 KV value continuation in DOCUMENT CONTROL footer. Indented wrap lines (no Key prefix) are appended to the previous kv value instead of falling through to the paragraph buffer. EX-08 Glossary stacked form (BPGP v3.1). Term flush-left, definition indented on next line. Accepted alongside the inline em-dash form. EX-09 Acronym flush-left form (BPGP v3.1). Acronym code at column zero, two-space gap, definition. Accepted alongside the indented form. EX-10 R1 paragraph collapse. Multi-line source paragraphs are joined into a single line on render. Soft returns inside a paragraph are lost; authors who need preserved line breaks must use a template block. EX-11 Stacked glossary entry takes priority over sub-label detection when the current section is a Glossary. A flush-left line whose content is a single all-caps token (acronym-as-term, for example "VQIP" or "WHO") immediately followed by an indented definition line is a glossary entry, not a sub-label banner. Without this priority the sub-label detector at position h consumes the term and the definition orphans into a standalone paragraph. The priority is implemented as detector position g0 in the body loop, gated on isGlossarySection so it does not affect other section types. The tryStackedGlossaryAt helper drops its previous "no all-uppercase term" guard accordingly and adds a colon to its trailing-punctuation rejection so a sub-label-like line such as "Brand terms:" still falls through to the sub-label detector. EX-12 Sub-section heading followed by a horizontal rule counts as "sits alone" for safeguard (iii) of Section 5.3. Some authors underline a sub-section heading with a rule of hyphens, equals, U+2500 box-draws, or U+2550 double box-draws (at least five characters long). For example: 4.1 Narrative v2 (full length) ------------------------------------------------------------ Without this exception the sub-section detector would reject the heading because the rule line is not blank, is not another heading, and is not a section bar of equals. With the exception, the heading is consumed AND the rule line that immediately follows is also skipped so it does not render as a redundant horizontal rule below the H2. The skip rule is important: the heading already carries visual weight on its own (boxed background plus gold left bar), and a separate hairline directly under it would compete with that styling. EX-13 Matrix table dash row may use ASCII hyphens instead of the canonical Unicode U+2500 box-drawing horizontal bar. BPGP v3.0 and v3.1 mandate U+2500 for new documents (Section 9.2 of DARH_STDS_BPGP_001), but many real-world legacy documents use ASCII hyphens because U+2500 is awkward to type on most keyboards. The parser accepts both forms. For example: Element Specification --------------------- --------------------------------------------------- Developer Morocco Foodex Technical partner FAO Co-financiers European Union, EBRD ... The isDashRow detector recognises a dash row in either of two patterns. The canonical pattern is any line containing a run of five or more U+2500 characters. The legacy ASCII pattern is a line consisting only of hyphens and spaces (no other characters allowed) containing at least two separate runs of at least three hyphens each. A single contiguous hyphen run is still a horizontal rule and is caught downstream by detector j, not as a dash row. The two-run minimum is the disambiguator: a column-separator dash row by definition has multiple columns and therefore multiple runs. The column-anchor scanner that follows isDashRow has also been extended to count both U+2500 and ASCII hyphen as dash characters when computing column-start positions, so legacy tables anchor their columns correctly. This exception is for backwards compatibility with the existing document corpus. Authors and AI agents creating new BPGP documents should use U+2500 as required by the standard. The exception will not be removed but should not be relied upon as a shortcut by new content. EX-17 Legacy "between-bars" header layout. Some BPGP documents place the DOCUMENT CONTROL field block BETWEEN two ==== bars at the top of the file, rather than BEFORE the first ==== bar as the canonical BPGP v3 layout requires. The original header collector stopped at line 0 when line 0 was already a bar and therefore captured zero header lines, leaving the viewer chrome to fall back to filename-derived title strings for those documents. EX-17 detects the legacy layout: line 0 must be an ==== bar, a second ==== bar must appear within the next 30 lines, and the content between the bars must contain at least one "Key: value" field line and NO "N. SECTION TITLE" pattern (the second condition disambiguates from a Bar-Title-Bar section heading right at the top of the body). When detected, the collector reads the between-bars range as headerLines and resumes the body parse after the closing bar. The same kv parsing logic applies to the between-bars header that applies to the canonical preamble header. Paired with EX-17 the field-name aliases were extended so legacy field spellings populate the same viewer chrome slots as their canonical names: "DOC ID" maps to docId, "Dept" maps to department, "Last Modified" maps to last revised. Documents in the legacy layout therefore render with correct browser tab title, page H1, eyebrow, and department banner without requiring field-by-field rewrites. Approximately twenty documents in the corpus used this legacy layout as of parser manual v1.10. A one-shot migration script at _devt/api/migrate_legacy_headers.php converted all of them to BPGP v3 canonical layout. EX-17 remains in the parser to handle any future docs that arrive in the legacy form or are pasted in from older external sources. EX-16 extractOutline terminates at the first non-blank flush-left line. The OUTLINE block in a BPGP document is composed of indented entries (typically 2 spaces of leading whitespace) following the OUTLINE header line and its hyphen rule. Many documents end the block with an explicit hyphen rule before the first section heading; some do not. For documents that do not, the original extractor had only the hyphen-rule terminator and walked past the outline into the body, picking up both flush-left section H1s and indented numbered list items inside section bodies as outline entries. EX-16 adds a flush-left terminator: any non-blank line whose first character is not whitespace ends the outline block. Hyphen-rule and equals-bar terminators are retained for documents that do use them. Blank lines inside the outline are tolerated so that authors can group entries visually. This exception was triggered by DARX_COMM_HERITAGE_NARRATIVE_20260429 whose OUTLINE block ends with a blank line followed by the section 1 header "1. PURPOSE AND SCOPE" (flush-left). Without the flush-left terminator the extractor captured the section H1 of every section in the document AND every indented numbered list item it encountered, producing a duplicated outline with restarting numerals (1-10 from the legitimate outline, then 1-2 from section H1s, then 1-2 from numbered list items in section 2's body). EX-15 Matrix table with a SINGLE-RUN full-width dash rule. Real-world documents frequently write the dash rule as one contiguous hyphen run that spans the entire table width with no gap between columns. For example: Category Rating ---------------------------------------- Supply availability LOW Quality fitness LOW Trade policy / tariffs HIGH ... The legacy column-anchor scanner (which counts dash-run start positions in the rule) returns only ONE anchor for a single-run rule. With colStarts of length 1 the existing parser bails and the table falls through to paragraph rendering, with R1 collapsing every row into one prose blob. EX-15 adds a fallback: when the dash rule is single-run, the parser infers column anchors from the HEADER row's text-gap positions (segments separated by 2 or more spaces) and uses those as the column anchors instead. Tight disambiguator: both the header row AND the first data row must contain at least 2 multi-space-separated segments. A prose paragraph followed by a stray hyphen rule (the line above has only one segment) does NOT false-fire, because the header-segment fallback requires 2+ segments in the header. The isDashRow detector was widened to also return true for a single run of at least 5 hyphens (was previously requiring 2+ runs of at least 3 hyphens each). The matrix detector then verifies the multi-segment header AND multi-segment data row before committing to a table parse, so the wider isDashRow does not over-fire on standalone hyphen rules. Structural change paired with EX-15: the flushParagraph call inside the matrix detector is now DEFERRED until a 2-or-more column table is confirmed. Earlier code flushed the paragraph buffer the moment a dash row was seen (anywhere) and then fell through if the table did not parse, splitting the surrounding paragraph in two. The new behaviour is: only flush when the parser actually commits to rendering a table block. EX-14 Matrix table detection at position f defers to def-row detection at position n when the current section is an Acronyms or Glossary section. Acronyms and Glossary sections frequently use a header row plus a hyphen dash rule that looks like a 2-column matrix table to isDashRow, but the entries below are meant to render as gold acronym chips alongside their definitions, not as table cells with a column gap. For example: Acronym Expansion -------- ------------------------------------------------------------ BPGP Bullet-Proof Ground-Plane (Daralbeida plain-text document standard) CAP Common Agricultural Policy (European Union) COA Certificate of Analysis ... Without this exception EX-13 would let the matrix table detector claim the block before the def-row detector ran, and the acronym chips would not appear. The fix is a section-type guard: when current is Acronyms or Glossary, matrix-table detection at position f is skipped and the dash row and data lines fall through to the def-row detector at position n which renders them as proper acronym entries. This mirrors EX-11 which gives stacked glossary entries priority over the sub-label detector inside Glossary sections. This exception was added immediately after EX-13 to repair the regression EX-13 introduced for Acronyms sections that follow the standard header-and-rule convention. EX-13 remains in effect for non-acronym, non-glossary sections where a 2-column table is the intended rendering. 14.3 ADDING A NEW EXCEPTION The procedure has four steps and MUST be followed in this order: (a) Identify the smallest disambiguator. An exception that loosens detection must have a counterweight (a length cap, a trailing-punctuation rule, a next-line check) so the canonical form keeps detecting AND prose lines that happen to match the new pattern get rejected. (b) Add the exception entry to the EXCEPTION REGISTRY block at the top of parseDoc in darx_txt_vwr.php. Use the next free EX-NN number. (c) Modify (or add) the matching detector with a banner comment referencing the new EX-NN. (d) Add a regression note in _devt/docs/claude_work_log.md describing the source document that surfaced the exception and the disambiguation chosen. The next maintainer should be able to read the work log and immediately understand WHY the exception was added, not just what it does. 14.4 GOLDEN RULE FOR EXCEPTION ADDITIONS An exception must NEVER suppress canonical detection. If the canonical form was correctly handled before, it MUST remain correctly handled after. Verify by re-rendering the canary set (Section 15) after every exception change. ================================================================================ 15. CANARY SET AND REGRESSION PROTOCOL ================================================================================ 15.1 WHAT A CANARY DOC IS A canary doc is a chosen test document, like the canary in a coal mine. It is a known-good file that is re-checked after any parser change. If a canary doc's rendering changes unexpectedly, something broke that was not supposed to break. The term comes from software testing. The canary set named below is the official regression-test corpus for the parser. After every parser change, every canary doc MUST be re-rendered and verified before the change is considered complete. The audit infrastructure in Sections 15.4 and 15.5 makes this fast. 15.2 THE TEN CANARY DOCS Each canary is chosen to exercise one or more EXCEPTION REGISTRY entries plus a category of source-doc style. The set is small enough to scroll through in a few minutes; together the ten cover every EX-NN entry as of parser v1.6. (1) DARH_STDS_BPGP_202605301215.txt The BPGP v3.1 standard itself. Canonical form for everything the parser does. Exercises: bar-title-bar section headings (canonical), U+2500 dash-rule matrix tables, inline em-dash glossary (Form A), indented acronyms (Form A), DOCUMENT CONTROL header and footer with the full kv field set, OUTLINE block, AI Prompts section, END OF DOCUMENT terminator. The single most important canary. If it does not render correctly, nothing else can be trusted. Must-not-break: EX-01 through EX-14 must all leave this doc rendering identically. This is the strictest canary. (2) DARH_STDS_WEB_VISUAL_202605301530.txt The Website Visual Consistency standard. Another canonical-form doc at higher content density. Exercises: heavy use of sub-section headings, ALL-CAPS Section 3.4 style headers, sub-labels inside sections, multiple AI prompt blocks, multi-paragraph glossary entries. Must-not-break: any change affecting sub-section detection (EX-04, EX-12) or sub-label detection (EX-05). (3) DARX_STRAT_MOROCCO_QUALITY_SHIFT_20260512.txt Tests EX-13 (ASCII hyphen matrix table in Section 2.1, the Morocco Foodex element-specification table) AND EX-14 (Acronyms section with header-row plus hyphen-rule that must defer to def-rows: BPGP, CAP, COA, DAB, DARX must render as gold acronym chips, NOT as table cells with a column gap). These two exceptions are paired in this canary because EX-13 introduced the regression that EX-14 repaired. Must-not-break: EX-13 normal-section behaviour (the Morocco Foodex table must render as a 2-column matrix table). EX-14 acronym behaviour (BPGP-CAP-COA must be gold chips). (4) DARX_COMM_COMPANY_DESC_20260410.txt Tests the widest spread of EXCEPTION REGISTRY entries in one doc. Exercises: EX-04 (Title Case sub-section "4.1 Narrative v2 (full length)"), EX-08 (stacked Glossary form: Backup Supplier, Concentration Risk, Daralbeida, Primary Supplier, Single-Supplier Dependency), EX-11 (VQIP-style ALL-CAPS acronym-as-term in glossary, must render as gold chip not as a sub-label), EX-12 (sub-section heading underlined by hyphen rule). Must-not-break: any change to sub-section detection, glossary stacked detection, or section-type-aware priority. This is the workhorse multi-exception canary. (5) DARX_BI_SOURCING_REMARKS_20260401.txt The doc that originally surfaced EX-08. Has a glossary section that uses the stacked form exclusively. Exercises: EX-08 (stacked glossary, Form B), entity color program for DARX (gold), Department mapping for BI (Business Intelligence). Must-not-break: glossary detection for the stacked form. (6) DARM_LEG_RESEARCH_20260525.txt Tests the DARM entity (Maroc, terracotta accent) and the LEG department mapping (Legal). Verifies that the entity color program correctly applies a non-gold accent across all components including chips, headings, sub-labels, and the gold-tint heading gradient. Must-not-break: entity color program, Department mapping, ACRONYM_EXCEPTIONS for SARL (the company suffix in Daralbeida Maroc SARL must render as plain text, not as an inline acronym chip). (7) DARH_LEG_STRUCTURE_20260525.txt Tests the DARH entity (Holdings, navy accent) and the LEG department mapping. Same role as canary (6) for the navy entity. Must-not-break: DARH entity color, ACRONYM_EXCEPTIONS for LLC (in Daralbeida Holdings LLC). (8) DARX_STRAT_KB_001_v1_1_20260513.txt A v3.0-upgraded knowledge base doc. Tests Acronyms section using the indented inline form (BPGP v3.0 canonical: CODE plus 2-space gap plus definition, indented). Must-not-break: tryDefLine acronym detection at position n. (9) DARX_OPS_BPGP_20260501.txt A legacy v1.x document. Exercises: EX-01 (legacy Title-Bar section heading where the equals rule sits only BELOW the title), EX-02 (legacy END OF DOCUMENT em-dash DOC_ID terminator variant), EX-06 (ASCII equals sign runs used as inline dividers inside section bodies). Must-not-break: legacy section detection, legacy terminator detection, horizontal rule detection for ASCII equals. (10) DARX_MI_RISK_20260510.txt Tests inline acronym auto-boxing density (155 acronyms in the body) and the ACRONYM_EXCEPTIONS list (corporate suffixes that must NOT be wrapped). Long doc with heavy prose. Must-not-break: wrapAcronyms behaviour and the exception list. 15.3 PRE-CHANGE CHECKLIST Before claiming a parser change is complete, the maintainer (human or AI) MUST run through: (a) Did the new pattern from the change render correctly on its source doc? (b) Did the canonical pattern still render correctly on canary (1) DARH_STDS_BPGP_202605301215.txt? (c) For each canary doc that exercises the changed detector or its neighbours in the body-loop priority order, did the rendering remain visually identical? (d) For changes affecting Acronyms or Glossary section detection: did canaries (3), (4), (5), and (8) all still render their gold chips? (e) For changes affecting sub-section detection: did canaries (1), (2), (4) all still show their sub-section headings styled correctly? A change that fails any item is NOT complete. Repair, re-verify, then close. 15.4 VISUAL AUDIT PAGE A single visual audit page at /_devt/_audit/parser/ shows the ten canary docs in a vertical stack of iframes with a "what to look for" label next to each one. Open the page, scroll through, eyeball-verify the expected rendering, done. 15.5 SNAPSHOT DIFF CLI A command-line tool at _devt/api/audit_snapshot.php captures the rendered HTML of each canary doc to a baseline file. After a parser change, run the tool in diff mode and it produces a per-canary unified diff. If a diff appears in a doc the change was not supposed to affect, the alarm has fired. The tool can also exit non-zero on any diff for integration into a pre-commit hook later. Modes: capture Save current rendering of every canary as the new baseline. Use when intentional changes have been ratified. diff Render every canary and unified-diff against the baseline. Print the diff. Exit zero if all match. verify Like diff but quiet; print only PASS or FAIL per canary. Exit non-zero if any canary differs. The baseline lives in _devt/_audit/snapshots/. Re-capturing is the formal sign-off that the new rendering is the new expected behaviour. ================================================================================ 16. KNOWN LIMITATIONS ================================================================================ 14.1 HEADER PARSING The kv regex does not accept values containing colons. A field like Approval Date with a value 2026-05-29 works fine, but a value containing a colon (e.g. a URL or a time-of-day) would have its tail truncated at the colon. Workaround: avoid colons in header field values, or extend the kv regex if a future field requires them. 14.2 SECTION DETECTION (TOP LEVEL) Top-level section headings (one-digit number plus title) still require ALL CAPS in the title. This is the strongest disambiguator against prose lines like "1. The first reason is...". A mixed-case top-level title is silently rejected. Sub-sections (N.N and N.N.N) DO accept Title Case as of parser v1.2 because the digit-pair pattern is rare in prose. See Section 5.2 and 5.3. 14.3 BODY RENDERING The R1 collapse joins multi-line paragraphs with single spaces. If a v1.x document intentionally uses hard line breaks for stylistic reasons (a poem block, a code-like inline example), those breaks are lost. The author can use a template block to preserve the layout (template blocks render with internal line breaks visible). 14.4 DEFINITION ROWS The acronym detection only fires inside sections whose title contains acronym (case-insensitive). A section titled CODES or LOOKUPS or ABBREVIATIONS will not get the def-row treatment unless the title is updated. The glossary detection uses the substring glossar; sections named DEFINITIONS or REFERENCE TERMS are similarly missed. 14.5 ACRONYM INLINE BOXING The lower-case-neighbour filter occasionally misses or over-fires. It misses a candidate that sits at the very start or end of a paragraph with no word on the empty side; in that case the wrapping depends on whether the single neighbour contains lowercase. It over-fires on intentionally emphasised ALL CAPS words like NEVER or MUST when surrounded by normal prose; those get wrapped as acronyms even though semantically they are not. 14.6 PERFORMANCE The parser runs in O(n) lines and is fast on documents up to a few thousand lines. Very large files (greater than 10,000 lines) may incur a noticeable pause on the main thread because parsing is synchronous. Splitting into a Web Worker is a known extension point but not currently implemented. ================================================================================ 17. EXTENSION POINTS ================================================================================ Future extensions should preserve the contracts in Sections 4 through 7 (section detection, footer trigger, terminator) and the block-type interface in Section 9. Specifically, any new block type must be added both to parseDoc (producer) and renderSections (consumer); skipping either side will silently drop the new content from the page. Candidate extensions identified during the current implementation pass: support for footnote markers (caret 1 caret 2 etc.) with a footnote section at the document end; explicit drop cap markup so authors can opt in or out per section; collapsible sections similar to the OUTLINE card; search inside the document; soft hyphenation control for long technical terms; and Web Worker offload for parsing large files. ================================================================================ 18. AI PROMPTS ================================================================================ This is the mandatory AI PROMPTS section (BPGP R2). The prompt below regenerates this parser manual with current code state. Edit the bracketed values, then paste into an AI chat to produce a fresh copy. ================================================================================ START OF PROMPT ================================================================================ Produce the Daralbeida BPGP Viewer Parser Code Manual as a single plain-text .txt BPGP v3.0 document. Edit the bracketed values before running. Document ID : DARH_TECH_PARSER_001 New version : [NEXT_VERSION, e.g. 1.1] Date+time : [YYYYMMDDHHMM in UTC] Supersedes : [PRIOR_FILENAME, e.g. DARH_TECH_PARSER_MANUAL_202605301046.txt] 1. Obey BPGP v3.0 format: 1a. Plain-text .txt only. No HTML, markdown, bullets, or markup. 1b. Each body paragraph is ONE line with no internal line breaks. (R1) 1c. Every non-paragraph line is 80 characters or fewer. (R3) 1d. File names and Document IDs use underscores only, never hyphens; the file name ends with date+time as YYYYMMDDHHMM in UTC. 1e. Include the mandatory AI PROMPTS section with this prompt updated for the next version. (R2) 1f. Table separators use the Unicode U+2500 box-drawing horizontal bar. 1g. The absolute final line is the exact string END OF DOCUMENT. 2. Include the full DOCUMENT CONTROL (HEADER) field set in the header block. 3. Include these numbered sections in order: 3a. Purpose and Scope 3b. Parser Architecture (pipeline, server vs client, entry points) 3c. Header Block Parsing (boundary, fields, doc ID display) 3d. Section Detection (Bar Title Bar, Title Bar, ALL CAPS, anchors) 3e. Sub Section Detection (N.N, N.N.N, ALL CAPS filter) 3f. Document Control Footer (triggers, flush left, first match wins) 3g. END OF DOCUMENT Terminator (bare, legacy suffix, flush left) 3h. Outline Block Extraction (detection, parsing, card, anchors) 3i. Block Types in the Body Loop (paragraphs, sub-labels, templates, lists, rules, matrix tables, definition rows, kv rows) 3j. Inline Acronym Auto Boxing (rule, neighbour filter, compounds, false positive mitigations, ACRONYM_EXCEPTIONS list and how to extend it) 3k. Filename Conventions Understood 3l. Filesystem Metadata Layer (server stat, stamp decoding, integrity) 3m. Entity Color Program 3n. Known Limitations (header, section, body, def-rows, acronym inline, performance) 3o. Extension Points 3p. AI Prompts (this section) 3q. Revision History (one row per version, newest last) 3r. Acronyms (alphabetical) 3s. Glossary (alphabetical with full definitions) 4. Carry forward any [DESCRIBE_CHANGES_FOR_NEXT_VERSION] requested for the new version above. 5. Close with a DOCUMENT CONTROL (FOOTER) block, wrapped in 80 hyphens, ending with the exact line END OF DOCUMENT. ================================================================================ END OF PROMPT ================================================================================ ================================================================================ 19. REVISION HISTORY ================================================================================ Every revision is logged here, newest row last. Version Date Author Summary ─────── ────────── ────── ────────────────────────────────────────────── 1.0 2026-05-30 PYB Initial issue. Documents the parser implementation state as of the editorial- typography overhaul (Fixes M through P in claude_work_log.md). Covers BPGP v3.0 section detection, OUTLINE TOC, def-row detection, inline acronym auto-boxing, filesystem metadata, entity color program, and the known limitations of each layer. 1.1 2026-05-30 PYB Acronym auto-box ACRONYM_EXCEPTIONS list added (Section 10.5 through 10.8) so that corporate suffixes (LLC, SARL, GMBH, BV, SPA, etc.), country and currency codes (USD, EUR, MAD, USA, UK, etc.), and a few doubled-letter common words (OK) bypass boxing and render as natural prose. Lists the default membership and the rule for extending the set as new false positives are observed. 1.10 2026-05-31 PYB EX-17 added: legacy "between-bars" header layout now parses correctly. About 20 docs in the corpus had their DOCUMENT CONTROL fields sandwiched between two ==== bars at the top of the file; the original collector stopped at line 0 and captured zero header data, leaving the viewer chrome to fall back to filename- derived title strings. EX-17 detects the layout and reads the between-bars range as header content. Paired with field-name aliases ("DOC ID" → docId, "Dept" → dept, "Last Modified" → last revised) so legacy field spellings populate the same chrome slots. Migration script at _devt/api/migrate_legacy_headers.php converted all 20 legacy docs to v3 canonical layout in one pass. 1.9 2026-05-31 PYB EX-16 added: extractOutline now terminates at the first non-blank flush-left line in addition to its existing hyphen-rule and equals-bar terminators. Triggered by DARX_COMM_HERITAGE_NARRATIVE which had no explicit terminator after the OUTLINE block; the extractor walked past the outline into the body and captured flush-left section H1s and indented numbered list items from section 2 as bogus outline entries (the "1. PURPOSE AND SCOPE" / "2. VERSION HISTORY" duplicates followed by "1. Olive oil and wine..." / "2. Caesar directed production..." in the rendered card). With the flush-left terminator the extractor stops at the first section heading. 1.8 2026-05-30 PYB EX-15 added: matrix tables with full-width single-run dash rules now parse correctly. Triggered by a rolled-up risk summary table in DARX_MI_RISK whose 71-hyphen single- run rule was failing the legacy multi-run-required column-anchor scanner. The detector now falls back to header-row text-gap positions for column anchors when the dash rule is single-run, gated by a multi-segment check on BOTH header and first data row. The matrix detector's flushParagraph call is also DEFERRED until a valid 2+ column table is confirmed, fixing a long-standing paragraph-splitting bug where the buffer was flushed the moment a dash row was seen (regardless of whether the table actually parsed). 1.7 2026-05-30 PYB Regression-control suite introduced. New Section 15 CANARY SET AND REGRESSION PROTOCOL documents the ten canary docs that exercise EX-01 through EX-14, the pre-change checklist, the visual audit page at _devt/_audit/parser/, and the snapshot diff CLI at _devt/api/audit_snapshot .php. Sections 15 through 19 renumbered to 16 through 20; outline updated. Maintainers (human or AI) now have a named, deterministic regression test for every parser change. 1.6 2026-05-30 PYB EX-14 added: matrix table detection at position f now defers to def-row detection at position n when the current section is Acronyms or Glossary. This repairs an EX-13 regression where the matrix table detector claimed the header row plus hyphen rule that prologues an Acronyms list, rendering BPGP, CAP, COA and so on as plain table cells with a wide column gap instead of as the gold acronym chips that the def-row detector produces. EX-13 remains in effect for non-acronym, non-glossary sections where a 2-column table is the intended rendering. Section-type gating pattern mirrors EX-11. 1.5 2026-05-30 PYB EX-13 added: matrix table dash row now accepts ASCII hyphens (in addition to the canonical Unicode U+2500) as a legacy form. Real-world docs commonly use ASCII hyphens because U+2500 is hard to type, and that mismatch was collapsing entire tables into prose with hyphen artifacts visible in the rendered output. The isDashRow detector now accepts a line of only hyphens and spaces with at least two separate runs of at least three hyphens. The column- anchor scanner counts both U+2500 and ASCII hyphen as dash chars. A single contiguous hyphen run is still a horizontal rule (caught by detector j), not a dash row. BPGP v3.0 and v3.1 still mandate U+2500 for new documents in Section 9.2 of DARH_STDS_BPGP_001; the exception covers legacy corpus only. 1.4 2026-05-30 PYB EX-12 added: sub-section heading followed by a horizontal rule (any of hyphens, equals, U+2500, U+2550 runs of five or more) now counts as "sits alone" for sub-section detection safeguard (iii). Surfaced by DARX_COMM_COMPANY_DESC where the sub-section "4.1 Narrative v2 (full length)" was underlined with a hyphen rule and consequently fell through to paragraph rendering. The detector now also skips the rule line immediately after consuming the heading, so a redundant horizontal rule is not rendered below the styled H2. Parallel visual fix: the section H1 numeral was sized 11 px and read as a tiny decoration next to the 24 px italic title. Bumped to 16 px tabular mono with a refined baseline alignment so the numeral now reads as a peer of the title in the section masthead. 1.3 2026-05-30 PYB EX-11 added: stacked glossary entry now takes priority over the sub-label detector when the current section is a Glossary. Surfaced by a document whose glossary contained a single ALL-CAPS acronym-as-term "VQIP" followed by an indented definition; the sub-label detector was consuming the term and orphaning the definition into a paragraph below. Implemented as a new detector position g0 in the body loop, gated on isGlossarySection so other section types are unaffected. The tryStackedGlossaryAt helper dropped its "no all-uppercase term" guard accordingly and added a colon to its trailing-punctuation rejection so that a sub-label-like line such as "Brand terms:" still falls through to the sub-label detector. Section 14.2 EXCEPTION REGISTRY updated. 1.2 2026-05-30 PYB Sub-section detector now accepts BOTH ALL CAPS and Title Case titles (Section 5.2) with three disambiguation safeguards (Section 5.3): line length cap, no- trailing-punct check, next-line context check. EXCEPTION REGISTRY introduced as a formal catalogue (new Section 14) with ten current entries (EX-01 through EX-10) and a four-step procedure for adding future exceptions safely. KV value continuation in DOCUMENT CONTROL footer documented as EX-07; v3.1 stacked glossary and flush-left acronym entries documented as EX-08 and EX-09. Parser source file reorganised: master EXCEPTION REGISTRY block at the top of parseDoc; ── DETECTOR: ── banner comments above every detector in the body loop for visual demarcation. No logic changes outside the sub-section detector — pure readability improvement for the rest. Manual sections 14 through 19 renumbered to 15 through 20 to make room for the new Section 14. ================================================================================ 20. ACRONYMS ================================================================================ AI Artificial Intelligence (chat assistant context) BPGP Business Plan / General Purpose (Daralbeida plain-text format) CSS Cascading Style Sheets DAB Daralbeida document and entity prefix (legacy) DARH Daralbeida Holdings LLC (entity code) DARM Daralbeida Maroc SARL (entity code) DARX Daralbeida Brands LLC (entity code; document-ID prefix) DC Document Control (footer block) DEPT Department DMS Document Management System DOM Document Object Model GPU Graphics Processing Unit HTML HyperText Markup Language ID Identifier IIFE Immediately-Invoked Function Expression JSON JavaScript Object Notation N.N Two-level decimal section numbering (e.g. 5.1) N.N.N Three-level decimal section numbering (e.g. 5.1.1) PHP PHP Hypertext Preprocessor (the server-side language) R1 Rule 1: single-line body paragraphs R2 Rule 2: mandatory AI Prompts section R3 Rule 3: 80-character non-paragraph line limit TOC Table of Contents UTC Coordinated Universal Time UTF-8 Unicode Transformation Format, 8-bit encoding ================================================================================ 21. GLOSSARY ================================================================================ Anchor ID The synthesised HTML id attribute used by the renderer for each section, sub-section, and outline entry. Format: s plus the dotted number with dots replaced by underscores. Example: section 5.1 becomes #s5_1. Bar Title Bar The canonical BPGP v3.0 section heading pattern: an 80-character equals rule, the numbered title in ALL CAPS, then another 80-character equals rule. See Section 4.1. Block A typed unit of parsed content. The parser produces a sequence of blocks per section (paragraph, sub-label, template, list, rule, matrix, def, kv) and the renderer dispatches on the type. Extension points must update both producer and consumer. Body Loop The parser's main pass through the file after the header has been consumed. Iterates line by line, dispatching to the appropriate block builder based on line patterns and current section context. CATEGORY Token The second underscore-separated segment of a BPGP filename (DARX_CATEGORY_DESCRIPTOR_DATE.ext). Determines department routing in the document library and the department label in the viewer's centered banner. Def Block A definition entry produced inside Acronyms or Glossary sections. Carries a term and a def field. Renders as a two-column row with a colored chip on the left. Definition Row Rendered output of a def block. Two-column grid with chip and definition text, hover-tinted background, 2 px gold left rail. Defined visually in Section 9.7. Entity One of the four Daralbeida legal entities (DARX Brands, DARH Holdings, DARM Maroc, DAB legacy default). Selects the accent color program and the legal entity name displayed in the centered banner. Flush Left A line that begins at column zero (no leading whitespace). The DOCUMENT CONTROL trigger and the END OF DOCUMENT terminator both require flush-left placement to anchor the parser. Header Object The plain JavaScript object populated from the file's preamble. Fields include title, version, status, classification, owner, dept, lastRevised, updateCycle, nextReview, annualReview, keywords, docId. Passed to populateChrome to dress the page. Hysteresis The technique of using different thresholds for entering and exiting a state to avoid rapid toggling near a boundary. Used in the chrome auto-tuck (80 px to hide, 60 px to show) and analogous mechanisms. Inline Acronym A short run of consecutive uppercase letters appearing inside body prose, surrounded by at least one lowercase word. Detected by wrapAcronyms and rendered as a styled inline chip. See Section 10. KV Block A key-value pair extracted from the DOCUMENT CONTROL footer. Renders as an info row inside the styled doc-control panel. Matrix Block A parsed table with column anchors derived from a U+2500 separator row beneath the header line. Renders as a styled HTML table. Outline Block The preamble TOC carried in the BPGP source between the OUTLINE marker and the next 80-hyphen rule. Extracted into a clickable card above the first section in the rendered page. Parser Contract A formatting rule whose purpose is correct rendering. A violation produces a render failure (silent drop, misclassification, broken anchor), not merely an aesthetic issue. Authors must follow these contracts; engineers extending the parser must preserve them. R1 Collapse The transformation applied in flushParagraph that joins a multi-line paragraph buffer into a single space-separated line. Allows pre-R1 v1.x documents to flow correctly without their hard wraps becoming visible breaks. Sub-Label A small editorial mark like Decision criteria embedded inside a section. Three recognised forms documented in Section 9.2. Template Block A quoted example block, triggered by a line beginning with the literal Template followed by em dash and topic. Rendered as a styled quotation with a gold left border and internal line breaks visible. Three-Way Integrity Check The comparison among filesystem mtime, the filename-encoded YYYYMMDDHHMM stamp, and the document-header Last Revised field. A discrepancy greater than five minutes flags an integrity warning on the Source row. See Section 12.3. TOC Card The clickable outline panel rendered above the first section. Carries the entries extracted from the OUTLINE block plus a collapse toggle. -------------------------------------------------------------------------------- DOCUMENT CONTROL (FOOTER) -------------------------------------------------------------------------------- Document ID : DARH_TECH_PARSER_001 Version : 1.0 Status : DRAFT Last Revised : 2026-05-30 10:46 UTC Update Cycle : 90 days Next Review Due : 2026-08-28 Annual Review : 2027-05-30 Owner : PYB / Daralbeida Distribution : Internal; engineers and AI agents maintaining or extending the viewer parser. Section 16 regeneration prompt may be shared into AI chats as needed. Review Triggers : Any change to the parser implementation in darx_txt_vwr.php; any change to the BPGP standard that affects detection rules; any new block type added to the renderer; identification of a parsing bug in a production document. COMPLIANCE : This manual must be updated in the same revision that changes a parser contract. A bug fix that does not affect contracts may defer manual update to the next scheduled review. Section 16 regeneration prompt must be kept in sync with this document on every revision. Revision History: See Section 17 -------------------------------------------------------------------------------- END OF DOCUMENT