#!/usr/bin/env bash
set -Eeuo pipefail

BASE="/home/yeff/public_html/devon"
CANON="$BASE/canon"
DATA="$BASE/panel/data"
DOCS="$BASE/docs/index.php"
HUB="$DATA/hub_index.json"
MASTER="$DATA/master_architecture_index.md"
CONTINUITY="$DATA/devon_continuity.md"

print_file() {
  local f="$1"
  echo
  echo "----- $(basename "$f") -----"
  if [ -f "$f" ]; then
    cat "$f"
  else
    echo "MISSING: $f"
  fi
}

echo "===== CANON ====="
for f in \
  "$CANON/03_RULES_OF_OPERATION.md" \
  "$CANON/06_DECISIONS.md" \
  "$CANON/07_SCOPE.md" \
  "$CANON/08_NEXT_ACTION.md"
do
  print_file "$f"
done

echo
echo "===== CORE ARCHITECTURE ====="
if [ -f "$MASTER" ]; then
  cat "$MASTER"
else
  echo "MISSING: $MASTER"
fi

echo
echo "===== CONTINUITY ====="
if [ -f "$CONTINUITY" ]; then
  cat "$CONTINUITY"
else
  echo "MISSING: $CONTINUITY"
fi

echo

echo
echo "===== DH EXECUTION LAW ====="
cat <<'EOF'
# DOCUMENTATION HUB EXECUTION LAW

Core law:
Documentation Hub is not documentation-only.
Documentation Hub is simultaneously:
1. canonical documentation
2. execution system
3. contract base for the operational panel

Non-optional rule:
Every category, subcategory, bucket and item must serve two functions at the same time:

A) Documentary function
- define the role of the category in the project
- define authority, scope, dependencies and boundaries
- preserve coherence with master, phase and sibling categories

B) Operational function
- define what must exist materially
- define what must be installed
- define what must be configured
- define what must be validated
- define what proves completion
- define what fails
- define what unlocks next

Invalid states:
- if a bucket only explains but does not execute, it is incomplete
- if a bucket only lists checks but does not define canonical meaning, it is incomplete
- if a bucket cannot orient the future operational panel, it is incomplete

Execution rule:
Each bucket must answer both questions:
1. what this bucket means inside this specific category
2. what must be done and proven on the server for this bucket to be complete

Category-writing law:
There is no copy-template between categories.
What exists is a common documentation-execution architecture with exclusive content for:
- each phase
- each category
- each bucket

Hard rule:
Prerequisites for one category may not read like Prerequisites for another category unless the real operational requirements are materially identical.
Installation for one category may not be generalized from another category.
Validation for one category may not be generalized from another category.

DH-to-Panel alignment rule:
Documentation Hub must be written as the contract source for the future operational panel.
Each bucket must be useful to both:
- human documentary reading
- operational execution, monitoring, gating, evidence and recovery flows in the panel

Operational consequence:
The future panel depends on DH to know:
- what is pending
- what is pass
- what is fail
- what is missing
- what evidence to expose
- what dependencies block progress
- what recovery path is allowed
- what unlocks next phase/category/bucket

Canonical bucket architecture:
Every bucket must contain, in category-specific language:

1. bucket purpose
- why this bucket exists in this category specifically

2. material conditions
- files
- keys
- bindings
- routes
- branches
- contracts
- dependencies
- render paths
- source identities
- endpoints when applicable

3. required actions
- install
- register
- expose
- configure
- bind
- validate
- recover
- promote
- block when invalid

4. observable evidence
- real path
- real source
- real render
- real contract
- real machine-readable evidence when applicable

5. validation criteria
- explicit boolean checks
- pass/fail/missing logic
- no subjective wording as completion criteria

6. failure conditions
- exact conditions that create FAIL
- exact conditions that create MISSING
- exact structural or authority conflicts

7. operational impact
- what this bucket unlocks
- what remains blocked if incomplete
- what the panel must later reflect

8. exit rule
- the exact condition under which this bucket is complete

Boolean law:
If a requirement cannot be reduced to a real observable check, it is not yet execution-grade.
If a statement cannot eventually feed panel validation, it is not yet strong enough.

Strategic rule:
DH text is not decorative prose.
DH text is canonical execution guidance.

System consequence:
Documentation Hub must become the general orientation center for project execution.
Without this alignment, the operational panel has no trustworthy contract baseline.
EOF

echo "===== DOCUMENTATION HUB SNAPSHOT ====="
if [ -f "$HUB" ]; then
  python3 - <<'PY'
from pathlib import Path
import json
import re

hub = json.loads(Path("/home/yeff/public_html/devon/panel/data/hub_index.json").read_text())

CATEGORY_PHASE_FALLBACK = {
    "overview_scope": "phase-01",
    "architecture_engineering_core": "phase-02",
    "cognitive_flow": "phase-03",
    "containerization": "phase-04",
    "latency_performance": "phase-05",
    "noise_reduction": "phase-06",
    "observability_audit": "phase-07",
    "security_governance": "phase-08",
    "memory_learning_reasoning": "phase-08",
    "operational_flows": "phase-09",
    "delivery_layer": "phase-09",
    "monitoring_observability": "phase-10",
}

def norm_phase(value):
    if not value:
        return None
    v = str(value).strip().lower().replace("_", "-")
    m = re.match(r"phase[- ]?(\d+)$", v)
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return v

def parse_phase_from_badge(badge):
    if not badge:
        return None
    m = re.search(r"phase[- ]?(\d+)", str(badge).lower())
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return None

def phase_id_of(ph, idx):
    return norm_phase(
        ph.get("id")
        or ph.get("phase_id")
        or ph.get("key")
        or f"phase-{idx+1:02d}"
    )

def phase_label_of(ph, idx):
    return (
        ph.get("label")
        or ph.get("title")
        or ph.get("name")
        or ph.get("badge")
        or phase_id_of(ph, idx)
    )

def category_label(cat):
    return cat.get("label") or cat.get("title") or cat.get("name") or cat.get("id")

def doc_label(doc):
    return doc.get("label") or doc.get("title") or doc.get("name") or doc.get("id")

def category_phase(cat):
    explicit = (
        cat.get("phase_id")
        or cat.get("phase")
        or cat.get("phase_ref")
        or cat.get("parent_phase")
    )
    explicit = norm_phase(explicit)
    if explicit:
        return explicit

    docs = cat.get("docs", [])
    if docs:
        doc_phase = norm_phase(docs[0].get("phase"))
        if doc_phase:
            return doc_phase

    badge_phase = parse_phase_from_badge(cat.get("badge"))
    if badge_phase:
        return badge_phase

    return CATEGORY_PHASE_FALLBACK.get(cat.get("id"), "UNBOUND")

phases = hub.get("phases", [])
cats = hub.get("categories", [])

print("PHASE COUNT:", len(phases))
for i, ph in enumerate(phases):
    print(f"- {phase_id_of(ph, i)} | {phase_label_of(ph, i)}")

print()
print("CATEGORY COUNT:", len(cats))
for cat in cats:
    docs = cat.get("docs", [])
    print(f"CATEGORY: {cat.get('id')} | LABEL: {category_label(cat)} | PHASE: {category_phase(cat)} | DOCS: {len(docs)}")
    for doc in docs:
        print(f"  DOC: {doc.get('id')} | LABEL: {doc_label(doc)} | TYPE: {doc.get('type')}")
    print()
PY
else
  echo "MISSING: $HUB"
fi

echo
echo "===== PHASE 01 + PHASE 02 DOC MAP ====="
if [ -f "$HUB" ]; then
  python3 - <<'PY'
from pathlib import Path
import json
import re

hub = json.loads(Path("/home/yeff/public_html/devon/panel/data/hub_index.json").read_text())

CATEGORY_PHASE_FALLBACK = {
    "overview_scope": "phase-01",
    "architecture_engineering_core": "phase-02",
    "cognitive_flow": "phase-03",
    "containerization": "phase-04",
    "latency_performance": "phase-05",
    "noise_reduction": "phase-06",
    "observability_audit": "phase-07",
    "security_governance": "phase-08",
    "memory_learning_reasoning": "phase-08",
    "operational_flows": "phase-09",
    "delivery_layer": "phase-09",
    "monitoring_observability": "phase-10",
}

def norm_phase(value):
    if not value:
        return None
    v = str(value).strip().lower().replace("_", "-")
    m = re.match(r"phase[- ]?(\d+)$", v)
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return v

def parse_phase_from_badge(badge):
    if not badge:
        return None
    m = re.search(r"phase[- ]?(\d+)", str(badge).lower())
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return None

def category_label(cat):
    return cat.get("label") or cat.get("title") or cat.get("name") or cat.get("id")

def doc_label(doc):
    return doc.get("label") or doc.get("title") or doc.get("name") or doc.get("id")

def category_phase(cat):
    explicit = (
        cat.get("phase_id")
        or cat.get("phase")
        or cat.get("phase_ref")
        or cat.get("parent_phase")
    )
    explicit = norm_phase(explicit)
    if explicit:
        return explicit

    docs = cat.get("docs", [])
    if docs:
        doc_phase = norm_phase(docs[0].get("phase"))
        if doc_phase:
            return doc_phase

    badge_phase = parse_phase_from_badge(cat.get("badge"))
    if badge_phase:
        return badge_phase

    return CATEGORY_PHASE_FALLBACK.get(cat.get("id"), "UNBOUND")

for phase in ("phase-01", "phase-02"):
    print(f"[{phase}]")
    found = False
    for cat in hub.get("categories", []):
        if category_phase(cat) != phase:
            continue
        found = True
        print(f"  {cat.get('id')} => {category_label(cat)}")
        for doc in cat.get("docs", []):
            print(f"    - {doc.get('id')} => {doc_label(doc)}")
    if not found:
        print("  MISSING")
    print()
PY
else
  echo "MISSING: $HUB"
fi

echo
echo "===== DOCS INDEX CUSTOM BRANCHES ====="
if [ -f "$DOCS" ]; then
  grep -n 'if (doc.id === "' "$DOCS" || true
else
  echo "MISSING: $DOCS"
fi

echo
echo "===== DOCS INDEX forceDirectArchitectureRender ====="
if [ -f "$DOCS" ]; then
  python3 - <<'PY'
from pathlib import Path

s = Path("/home/yeff/public_html/devon/docs/index.php").read_text()
needle = "const forceDirectArchitectureRender ="
i = s.find(needle)
if i == -1:
    print("MISSING: forceDirectArchitectureRender block")
else:
    j = s.find("if (!forceDirectArchitectureRender)", i)
    if j == -1:
        j = min(len(s), i + 2200)
    print(s[i:j].rstrip())
PY
else
  echo "MISSING: $DOCS"
fi

echo
echo "===== DOCS INDEX PHASE STATUS SNAPSHOT ====="
if [ -f "$DOCS" ] && [ -f "$HUB" ]; then
  python3 - <<'PY'
from pathlib import Path
import json
import re

docs_text = Path("/home/yeff/public_html/devon/docs/index.php").read_text()
hub = json.loads(Path("/home/yeff/public_html/devon/panel/data/hub_index.json").read_text())

CATEGORY_PHASE_FALLBACK = {
    "overview_scope": "phase-01",
    "architecture_engineering_core": "phase-02",
    "cognitive_flow": "phase-03",
    "containerization": "phase-04",
    "latency_performance": "phase-05",
    "noise_reduction": "phase-06",
    "observability_audit": "phase-07",
    "security_governance": "phase-08",
    "memory_learning_reasoning": "phase-08",
    "operational_flows": "phase-09",
    "delivery_layer": "phase-09",
    "monitoring_observability": "phase-10",
}

def norm_phase(value):
    if not value:
        return None
    v = str(value).strip().lower().replace("_", "-")
    m = re.match(r"phase[- ]?(\d+)$", v)
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return v

def parse_phase_from_badge(badge):
    if not badge:
        return None
    m = re.search(r"phase[- ]?(\d+)", str(badge).lower())
    if m:
        return f"phase-{int(m.group(1)):02d}"
    return None

def category_label(cat):
    return cat.get("label") or cat.get("title") or cat.get("name") or cat.get("id")

def category_phase(cat):
    explicit = (
        cat.get("phase_id")
        or cat.get("phase")
        or cat.get("phase_ref")
        or cat.get("parent_phase")
    )
    explicit = norm_phase(explicit)
    if explicit:
        return explicit

    docs = cat.get("docs", [])
    if docs:
        doc_phase = norm_phase(docs[0].get("phase"))
        if doc_phase:
            return doc_phase

    badge_phase = parse_phase_from_badge(cat.get("badge"))
    if badge_phase:
        return badge_phase

    return CATEGORY_PHASE_FALLBACK.get(cat.get("id"), "UNBOUND")

branches = set()
for m in re.finditer(r'if \(doc\.id === "([^"]+)" && state\.categoryId === "([^"]+)"\)', docs_text):
    branches.add((m.group(1), m.group(2)))

for phase in ("phase-01", "phase-02"):
    print(f"{phase.upper()}:")
    found = False
    for cat in hub.get("categories", []):
        if category_phase(cat) != phase:
            continue
        found = True
        cat_id = cat.get("id")
        print(f"  CATEGORY: {cat_id} | {category_label(cat)}")
        for doc in cat.get("docs", []):
            doc_id = doc.get("id")
            status = "CUSTOM_BRANCH" if (doc_id, cat_id) in branches else "GENERIC_RENDER"
            print(f"    - {doc_id}: {status}")
    if not found:
        print("  MISSING")
    print()
PY
else
  echo "MISSING: $DOCS or $HUB"
fi

echo
echo "===== DOCS INDEX SYNTAX ====="
if [ -f "$DOCS" ]; then
  php -l "$DOCS" || true
else
  echo "MISSING: $DOCS"
fi

echo
echo "===== DUMP STATUS ====="
echo "PASS: canonical + docs + hub context reconstructed from server evidence"
