# PANEL SITTING — P31 AL-MIZAN · LETTER WING (W1) ADVERSARIAL REVIEW
**Window:** PA1 (Opus) — PANEL WAVE A · 2026-09-03  
**Sources read:** W1-L1 madd_layer.json · W1-L2 nun_system_layer.json · W1-L3 qalqalah_layer.json · W1-L4 waqf_signs_layer.json · W1-L5 sajdah_registry.json · W1-L6 open_ta_layer.json · W1-L7 hamza_layer.json · `00-CORPUS/acquired/waqf_text/_META.json` · `fleet/missions/A4_report.json` (W1-LANDING) · `framework/p31_w1_engines.py` · `framework/p31_w1_engines2.py` · `framework/p31_hamza_dual3.py`  
**Method:** adversarial; a clean pass must be earned; EVIDENCE LAW: every claim carries file+path+value; READ-ONLY

---

## ATTACK TASK 1 — THREE COUNTS RE-DERIVED INDEPENDENTLY

### Count A: Qalqalah total (claimed: 3,415)

**Independent derivation** from `W1-L3/qalqalah_layer.json → totals.by_letter`:

| Letter | Count |
|---|---|
| ب | 1,134 |
| د | 965 |
| ج | 658 |
| ق | 516 |
| ط | 142 |
| **Total** | **3,415** |

`1134 + 965 + 658 + 516 + 142 = 3,415`  
Matches claimed total. **✅ VERIFIED**

**Engine logic audit** (`p31_w1_engines.py` lines 43–57): `QAL = set(u"قطبجد")`; engine scans every character; fires when `ch in QAL and t[i+1] == SUKUN`. Five-letter set matches the tajwid tradition's five qalqalah letters exactly. The count is re-derivable from the same sealed corpus (SHA `fbc8744a...`). **✅ METHOD SOUND**

---

### Count B: Iqlab (claimed: 513)

**Independent derivation** from `W1-L2/nun_system_layer.json → totals.by_class`:  
`"iqlab": 513` ✅ VERIFIED

**Cross-check via _META.json and A4_report.json:** The iqlab marker is U+06E2 (Arabic small high meem, "ۢ") placed by the Uthmani script itself on the nun or tanwin before ب. The engine reads `MIM_SMALL = u"ۢ"` (U+06E2) directly from the sealed text. U+06E2 is NOT among the waqf marks listed in the _META (those are U+06D6–U+06DC range); iqlab is counted from the diacritized corpus (SHA `fbc8744a...`), which is the correct source. No cross-source contamination. **✅ VERIFIED**

---

### Count C: Sajdah (claimed: 15)

Three independent sources agree:

| Source | File | Value |
|---|---|---|
| L5 sajdah registry | `W1-L5/sajdah_registry.json → totals.sajdah_positions` | 15 |
| L4 waqf layer | `W1-L4/waqf_signs_layer.json → totals.sajdah` | 15 |
| A4 acquisition | `W1-LANDING/A4_report.json → mark_counts.U+06E9_sajdah.count` | 15 |

Three-way agreement, no discrepancy. **✅ VERIFIED**

The 15 positions in `W1-L5/sajdah_registry.json` enumerate the standard Hafs sujud al-tilawah locations (7:206, 13:15, 16:50, 17:109, 19:58, 22:18, 22:77, 25:60, 27:26, 32:15, 38:24, 41:38, 53:62, 84:21, 96:19). All 15 match the mushaf convention. **✅ VERIFIED**

---

## ATTACK TASK 2 — MADD V2 CLASSES: 6 MARKED POSITIONS VERIFIED BY EYE

**Rule under test** (`p31_w1_engines2.py` lines 34–43):
- After maddah sign (U+0653), skip harakat; the next base character determines the class
- Same-word hamza → `muttasil`; space + next-word hamza → `munfasil`; shadda or following sukun → `lazim`; else → `(other)`

| # | Class claimed | Ayah | Context | Hamza position | Eye-verdict |
|---|---|---|---|---|---|
| 1 | muttasil | 2:5 | `أُو۟لَٰٓئِكَ عَ` | ئ is hamza-on-ya, in SAME word (أولئك) as the maddah | ✅ CORRECT |
| 2 | muttasil | 2:5 | `أُو۟لَٰٓئِكَ هُ` | Same word, same maddah, hamza (ئ) is intra-word | ✅ CORRECT |
| 3 | munfasil | 2:4 | `َ بِمَآ أُنزِل` | مَآ = maddah on alif; then space; أُنزِل starts with أ (hamza of qat') | ✅ CORRECT |
| 4 | munfasil | 2:4 | `َ وَمَآ أُنزِل` | Same structure; مَآ followed by space + أُ | ✅ CORRECT |
| 5 | marked (other) | 1:7 | `ٱلضَّآلِّينَ` | Maddah on alif; next char is ل (lam), not hamza, not space, not sukun — falls to else | ✅ CORRECT AS CODED |
| 6 | marked lazim | 10:51 | `ِۦٓ ءَآلْـَٰٔن` | Maddah; next base char is ل; t[j+1] = ْ (sukun) → lazim fires | ✅ CORRECT AS CODED |

**The muttasil/munfasil context rule is correctly implemented and produces correct results for samples 1–4 and 6.** Sample 5 reveals a separate issue addressed as Finding F1 below.

---

## ATTACK TASK 3 — NUN-SYSTEM RULE TABLE VS STANDARD TAJWID TABLE

**Standard Hafs nun-sakinah / tanwin table** (al-Jazariyya, al-Muqaddima al-Jazariyya):

| Class | Letters | Engine sets |
|---|---|---|
| Izhar | ء ه ع ح غ خ (six throat sounds) | `IZHAR = set("ءأإئؤهعحغخ")` |
| Iqlab | ب | `IQLAB = set("ب")` |
| Idgham with ghunnah | ي ن م و | `IDGHAM_GH = set("ينمو")` |
| Idgham without ghunnah | ر ل | `IDGHAM_NO = set("رل")` |
| Ikhfa | remaining 15: ت ث ج د ذ ز س ش ص ض ط ظ ف ق ك | catch-all |

**Verdict on table correctness:** The five classes are present; the letters are correctly assigned. The IZHAR set includes all Unicode hamza forms (أ إ ئ ؤ in addition to standalone ء) — this is CORRECT for a character-based implementation; all forms carry hamza sound and trigger izhar. The catch-all ikhfa covers exactly the 15 standard letters.

**One finding — within-word idgham exception not handled:**

The tajwid tradition names four words where noon-sakinah followed by an idgham-class letter (ي) within the SAME word is NOT assimilated: دُنيا · بنيان · قنوان · صنوان (and their declined forms). The engine applies `classify()` via `letters_after()` without a within-word vs cross-word gate; these four word-types are classified as `"idgham-with-ghunnah"` throughout.

Evidence (`p31_w1_engines.py` lines 73–91):
```python
elif ch == NOON:
    nxtmark = t[i + 1] ...
    if nxtmark == SUKUN: trigger = "nun-sakinah"
    ...
if trigger:
    ...
    nxt = letters_after(t, i)
    c = classify(nxt)   # no same-word gate
```

`letters_after()` skips harakat and spaces indiscriminately; a noon-sakinah inside دُنيا whose next real letter (ي) is also inside دُنيا is handed to `classify(ي)` → `"idgham-with-ghunnah"`. Small in absolute count (دنيا alone appears ~100 times) but a named tajwid exception. This is **F3** (SHOULD FIX).

---

## ATTACK TASK 4 — OPEN-TA LIST: 5 WORDS SAMPLED AGAINST MUSHAF ORTHOGRAPHY

**Layer claim** (`W1-L6/open_ta_layer.json`): 158 distinct words, 1,023 positions — "words the rasm writes with OPEN ta while the lemma carries ta-marbuta."

**Five samples chosen from the layer's own list:**

| Word | Count in layer | Classical rasm status | Verdict |
|---|---|---|---|
| رحمة (rahmat) | 42 | Open-ta confirmed: rasm writes رحمت in construct positions (al-Dani, al-Muqni') | ✅ GENUINE |
| نعمة (ni'mat) | 24 | Open-ta confirmed: classical list consensus | ✅ GENUINE |
| صلاة (salat) | 16 | Open-ta confirmed: صلوت in Uthmani rasm | ✅ GENUINE |
| سنة (sunnat) | 6 | Open-ta in specific Uthmani positions | ✅ GENUINE |
| آية (ayah) | 289 | DISPUTED — see below | ❌ CONFLATED |

**آية analysis:** The lemma آية ends in ة. The engine fires when any FORM derived from this lemma ends in ت after diacritic stripping. The singular آية retains ة throughout the Tanzil text. The plural آيات ends in ت — stripped form ends in ت, stripped lemma ends in ة: condition fires. All 289 occurrences of "آية" in the open-ta layer are the PLURAL آيات, not a rasm phenomenon of writing the singular with open ta. This is an ات-plural suffix masquerading as an open-ta rasm case.

**Engine logic** (`p31_w1_engines2.py` lines 73–77):
```python
b=lambda x:"".join(c for c in x if c not in u"ًٌٍَُِّْٰ")
fb=b(s["form"]); lb=b(lem)
if lb.endswith(u"ة") and fb.endswith(u"ت"):
    open_ta[lb]+=1
```

This fires on ANY noun form ending in ت whose lemma ends in ة. Arabic ات-plural forms (جنات, آيات, صالحات, بينات, …) satisfy this condition trivially — they are not rasm phenomena.

**By inspection of the list:** جنة (74), صالحة (62), بينة (53), آية (289) = all high-frequency pluralizing nouns. Their counts represent ات-plural occurrences, not Uthmani rasm open-ta. The true open-ta list in the Quran contains ~10–15 singular words by classical consensus (al-Dani, Ibn Qutayba). The layer's 158-word count is dominated by the pluralizing effect. This is **F2** (FIX-FIRST).

---

## ATTACK TASK 5 — AWAITED CLAIMS: ARE ANY NOW DERIVABLE?

Three AWAITED claims appear across W1 layers:

| Layer | AWAITED claim | Status |
|---|---|---|
| L1 madd | "LENGTHS per school AWAIT the qira'at source" | Still legitimately AWAITED — no qira'at layer (W6-R1) is built |
| L2 nun-system | "the waqf-position (kubra) class AWAITED the A4 acquisition" | **NOW RESOLVABLE** — L4 is built (2026-09-03T14:41:55) with 4,558 waqf positions |
| L3 qalqalah | "at waqf-pause positions (kubra) — AWAITED the waqf-marked text" | **NOW RESOLVABLE** — L4 positions available; verse-final qalqalah letters derivable from quran.json alone |

**L2 / L3 waqf-dependency — evidence that it is now resolvable:**  
`W1-L4/waqf_signs_layer.json` built `2026-09-03T14:41:55`, source SHA `4b91f9e6...` matching `_META.json`. The layer has `"sajdah": 15, "lazim": 22, "sali": 1682, …` — waqf positions are available. The 1,069 "ayah-final (waqf-dependent)" positions in L2 can now be subdivided using L4 data. Qalqalah kubra positions (verse-final qalqalah letters) can be derived from the quran.json last-letter sweep without even needing L4.

**Action**: AWAITED labels in L2 and L3 should be changed to **AVAILABLE — PENDING ENGINE UPDATE**.

---

## FINDINGS

### F1 — MADD LAZIM MUTHAQQAL MISCLASSIFIED · FIX-FIRST

**File:** `framework/p31_w1_engines2.py` line 42  
**What the engine does:**
```python
elif t[j]==SHADDA or (j+1<L and t[j+1]==SUKUN): c="marked lazim (sukun/shadda)"
else: c="marked (other)"
```

**The defect:** In normalized Unicode Arabic, a shadda diacritic (U+0651) follows its base letter, never precedes it. After the loop `while j<L and t[j] in HARAKAT: j+=1` (which skips all diacritics INCLUDING shadda), position j always lands on a base letter — never on a standalone shadda character. Therefore `t[j]==SHADDA` can never fire.

The only live path to `lazim` is `t[j+1]==SUKUN`, which catches madd lazim mukhaffaf (madd followed by explicit sukun, e.g. آلْـَٰٔن at 10:51 and 10:91). This correctly produces 2 positions.

**The missed class:** Madd lazim muthaqqal kalimi — madd followed by a mushadda (double-consonant) letter — is the more common lazim class in the Quran. Example: ٱلضَّآلِّينَ (1:7, 15:42, and many occurrences). Here, after the maddah, j lands on ل (base letter), and `t[j+1]` is kasra (ِ, a vowel — not sukun). The shadda on ل is the character AFTER the kasra, at j+2. The engine never reaches it. This position is classified as "marked (other)."

**Evidence the exemplar at 1:7 is wrong:**  
`W1-L1/madd_layer.json → exemplars["marked (other)"][0] = {"ayah": "1:7", "ctx": "ٱلضَّآلِّينَ"}`.  
ٱلضَّآلِّينَ is a madd lazim muthaqqal (standard tajwid consensus). It appears as the first entry in the "other" bucket — a self-contained counter-example embedded in the layer's own output.

**Scope:** The "marked lazim" count of 2 is severely undercounted. A meaningful fraction of the 678 "marked (other)" positions should be reclassified as lazim. The layer's own law — "the script's testimony first" — cannot be fulfilled correctly until the engine detects the mushadda follow-through.

**Fix required:** After landing on base letter at j, check whether any character in t[j+1 … j+2+] is SHADDA (U+0651) before hitting the next base letter. One approach: `any(t[k]==SHADDA for k in range(j+1, min(j+4, L)) if t[k] in HARAKAT|{SHADDA})`.

---

### F2 — OPEN-TA LAYER CONFLATES ات-PLURALS WITH RASM PHENOMENON · FIX-FIRST

**File:** `framework/p31_w1_engines2.py` lines 73–77  
**Layer:** `W1-L6/open_ta_layer.json`

The engine fires on ANY noun where `stripped_form.endswith("ت")` and `stripped_lemma.endswith("ة")`. This captures:

(a) Genuine Uthmani open-ta: singular (or dual) words written with ت where the lemma's ة is preserved in the rasm as ت — the classical short list (rahmat, ni'mat, sunnat, la'nat, etc.)

(b) Arabic ات-plural forms: any feminine plural ending in ات satisfies the condition (form ends in ت, lemma ends in ة). This is NOT a rasm phenomenon; it is regular Arabic morphology.

**Quantitative impact:** The layer's largest entries are آية (289), جنة (74), صالحة (62), بينة (53) — all high-frequency ات-pluralizing nouns. Their counts represent آيات, جنات, صالحات, بينات occurrences throughout the Quran, not open-ta rasm cases. The classical consensus open-ta word list is approximately 10–15 singular/dual entries. The layer's 158 words is dominated by the plural effect.

**Fix required:** Add a morphological gate: singular or dual forms only. One approach: `if lb.endswith("ة") and fb.endswith("ت") and not fb.endswith("ات"):` as a first approximation; or use the SI morphological POS+NUMBER feature to restrict to singular/dual.

---

### F3 — WITHIN-WORD NUN-SAKINAH IDGHAM EXCEPTION · SHOULD FIX

**File:** `framework/p31_w1_engines.py` lines 73–91  
**Layer:** `W1-L2/nun_system_layer.json`

The standard tajwid tradition (Imam al-Suyuti, al-Itqan; contemporary standard texts) identifies four words where noon-sakinah precedes an idgham-class letter within the SAME word, and where assimilation does NOT apply: دُنيا · بنيان · قنوان · صنوان.

The engine applies the letter-class rule without a same-word gate, classifying these as `"idgham-with-ghunnah"`. The count impact is small (دنيا appears ~130 times in various forms; بنيان ~10; the others less) but these are named exceptions in the standard Hafs tajwid tradition that a verification layer should not erase.

**Fix required:** After detecting noon-sakinah trigger with idgham-class next letter, add check: if the next letter is in the same word (no space between trigger and next), label as `"idgham-within-word (exception class)"` or `"izhar-within-word"` rather than standard idgham.

---

### F4 — L4 WAQF LAYER COUNT DISCREPANCY · SHOULD FIX

**Files:** `W1-L4/waqf_signs_layer.json` totals vs `W1-LANDING/A4_report.json` mark_counts vs `00-CORPUS/acquired/waqf_text/_META.json`

**Discrepancy table:**

| L4 category | L4 count | Closest _META mark | _META count | Difference |
|---|---|---|---|---|
| sali | 1,682 | U+06D6_waqf_qalaa | 1,651 | +31 |
| jaiz | 1,972 | U+06DA_waqf_jaiz | 2,083 | −111 |
| lazim | 22 | U+06D8_waqf_meem | 21 | +1 |
| mu'anaqah | 12 | U+06DB_waqf_three_dots | 6 | +6 |
| la-taqif | 68 | U+06D9_waqf_lam_alef | 0 | +68 |
| rub-el-hizb | 199 | (no corresponding mark in _META) | 0 | +199 |

**The la-taqif gap is the most serious:** _META (and A4 report) record U+06D9 = 0, with note "U+06D9 (lam-alef stop) is rare or absent in standard Hafs Uthmani encoding." Yet L4 lists 68 la-taqif positions. These 68 cannot come from U+06D9 marks. Either the L4 engine sources them from U+06DC (waqf seen, 8 marks — still far from 68), or from text characters (the Arabic letters ل + ا appearing inline in the waqf edition as "لا" signs not recognized by the Unicode mark scan), or from an external list.

**The mu'anaqah gap:** 6 raw marks (U+06DB) in the source → 12 positions in L4. The L4 appears to expand each single U+06DB occurrence into both positions of its pair by inference from verse structure. This is NOT "marks carried verbatim from the acquired text" as the layer law states.

**The rub-el-hizb gap:** 199 positions in L4 with no corresponding mark type in _META. The rub-el-hizb sign (U+06DE ۞) is a structurally different mark not counted by A4's scan (which only tracked U+06D6–U+06DC and U+06E9). If U+06DE is present in the source text and was counted by the L4 engine but missed by the A4 mark count, the _META is incomplete and must be corrected.

**The layer law ("marks carried verbatim from the acquired text") is not met for la-taqif and mu'anaqah at minimum.** The source of la-taqif must be documented. The mu'anaqah pair-inference must be declared explicitly in the law field.

---

### F5 — AWAITED CLAIMS IN L2/L3 NOW RESOLVABLE · INFORMATION

`W1-L2` and `W1-L3` declare "AWAITED A4 acquisition" / "AWAITED the waqf-marked text." A4 completed 2026-09-03. L4 (waqf_signs_layer) is built. The dependency is resolved. These AWAITED labels are stale and should be updated to "AVAILABLE — PENDING ENGINE UPDATE."

The qalqalah kubra count is even derivable without L4: scan the last character of each ayah in quran.json; if it is a qalqalah letter (after stripping harakat), it is a mandatory pause position with qalqalah kubra. No waqf marks required for the verse-final class.

---

## MECHANICAL CHECKS

| Check | Source | Result |
|---|---|---|
| L2 totals sum | `ikhfa(5887)+idgham-GH(3111)+izhar(2563)+ayah-final(1069)+idgham-NO(817)+iqlab(513)` | = 13,960 ✅ matches `"positions": 13960` |
| L3 totals sum | `ب(1134)+د(965)+ج(658)+ق(516)+ط(142)` | = 3,415 ✅ matches `"positions": 3415` |
| SHA consistency L1/L2/L3 | All three layers: `source_sha: "fbc8744a..."` | ✅ consistent — all read sealed corpus |
| SHA consistency L4/L5 | Both layers: `source_sha: "4b91f9e6..."` matching `_META.sha256` | ✅ consistent — both read waqf text |
| Source segregation | L1–L3 use quran.json (sealed diacritized text); L4–L5 use waqf_text (pause-marked edition) | ✅ correct architecture |

---

## SUMMARY TABLE

| # | Finding | Layer(s) | Severity |
|---|---|---|---|
| **F1** | Madd lazim muthaqqal mislabeled as "marked (other)" — `t[j]==SHADDA` never fires in normalized Unicode; only sukun-lazim class is caught; 1:7 exemplar in "other" is the self-refuting counter-example | L1 madd | **FIX-FIRST** |
| **F2** | Open-ta layer conflates ات-plural forms with Uthmani rasm phenomenon; 158 words / 1,023 positions dominated by جنات/آيات etc., not classical open-ta list | L6 open-ta | **FIX-FIRST** |
| **F3** | Within-word nun-sakinah before idgham letters (دنيا, بنيان, قنوان, صنوان) classified as idgham-with-ghunnah; standard Hafs tradition treats these as a named exception | L2 nun-system | SHOULD FIX |
| **F4** | L4 waqf layer la-taqif (68) and rub-el-hizb (199) cannot be reconciled with source mark counts; mu'anaqah pair-position inference (6 marks → 12 entries) violates "verbatim carry" law; _META may miss U+06DE | L4 waqf signs | SHOULD FIX |
| **F5** | L2 and L3 AWAITED labels for waqf-dependency are stale; A4 acquired 2026-09-03; L4 built same day | L2, L3 | INFORMATION |

**Clean passes:** Qalqalah total (3,415 ✅) · Iqlab (513 ✅) · Sajdah (15 — three-way agreement ✅) · Madd muttasil/munfasil rule correct for 4 of 6 samples ✅ · Nun-system five-class structure correctly defined ✅ · Source SHA consistency across all layers ✅ · L2 and L3 totals independently verified ✅

---

## VERDICT

### **FIX-FIRST**

The Wing's architecture is sound — source segregation is clean, SHA provenance is consistent, three core counts are verified, and the tajwid rule table is correctly defined. Two findings prevent a WING-COHERENT verdict:

**F1** is not a minor mis-label: the very exemplar the layer surfaces to demonstrate "marked (other)" (1:7 — ٱلضَّآلِّينَ) is a standard-consensus madd lazim muthaqqal. The "marked lazim" count of 2 is so small that any user reading it assumes lazim is nearly absent from the Quran — the opposite of the truth. This corrupts the layer's stated purpose of giving "the script's own testimony first."

**F2** means the claim "158 distinct words — words the rasm writes with OPEN ta" is materially false. The vast majority of the 158 words are ات-plural morphology, not rasm exceptions. A user relying on this list to identify Uthmani open-ta positions would receive incorrect data.

F3 and F4 must be documented and fixed before the layer is consumed by downstream engines. F5 is a staleness label only.

**The plan is structurally sound. F1 (lazim classification) and F2 (open-ta conflation) must be corrected before W1 is marked WING-COHERENT.**

---
*PA1 (Opus) · PANEL WAVE A · 2026-09-03 · `10-WAQF/reviews/PANEL-P31-W1.md`*
