File size: 8,678 Bytes
a688aff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
"""
Stress test: proves compiler resilience under adversarial conditions.
- Malformed markdown injection
- Contradictory policy data
- Semantic diff verification
- Concurrency limit verification

Usage:
    python scripts/stress_test.py

Requires: backend running on http://localhost:8080
"""

import requests
import time
import sys
import os
import json

API = "http://localhost:8080"
COMPANY = "rivanly-inc"

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEST_DIR = os.path.join(BASE_DIR, "data", "sources", COMPANY)


def check_health():
    print("1. Checking API health...")
    r = requests.get(f"{API}/health")
    assert r.status_code == 200, f"Health check failed: {r.text}"
    data = r.json()
    print(f"   API: {data['status']}, vLLM: {data['vllm']}, DB: {data['database']}")
    return True


def compile_and_wait(label="Compile"):
    """Trigger compilation and poll until complete."""
    print(f"   [{label}] Triggering compilation...")
    r = requests.post(f"{API}/compile", json={"company_id": COMPANY})
    assert r.status_code == 200, f"Compile failed: {r.text}"
    job_id = r.json()["job_id"]
    print(f"   Job ID: {job_id}")

    for attempt in range(60):
        time.sleep(5)
        try:
            status_req = requests.get(f"{API}/compile/{job_id}/status")
            if status_req.status_code == 200:
                job_info = status_req.json()
                if job_info.get("status") == "error":
                    print(f"   [FAIL] Job failed: {job_info.get('error_detail')}")
                    return {"status": "error", "error": job_info.get("error_detail")}
                if job_info.get("status") == "complete":
                    sk = requests.get(f"{API}/skills/{COMPANY}")
                    if sk.status_code == 200:
                        data = sk.json()
                        skills = data.get("skills", [])
                        print(
                            f"   Compilation produced {len(skills)} skills (version: {data.get('version', 'N/A')})"
                        )
                        return data
        except Exception:
            pass
        print(f"   Waiting... ({(attempt + 1) * 5}s)")

    return {"status": "timeout"}


def test_malformed_markdown():
    """Inject malformed markdown and verify the pipeline doesn't crash."""
    print("\n2. Malformed source resilience test...")

    malformed = """## Corrupted Table
| Header 1 | Header 2
| --- | ---
| broken row

## Nested
### Subsection with no body

||||
|--|-|

Unclosed bracket [[[[
"""

    # Save malformed file
    path = os.path.join(TEST_DIR, "malformed_test.md")
    with open(path, "w", encoding="utf-8") as f:
        f.write(malformed)
    print("   Injected malformed markdown file")

    # Recompile
    result = compile_and_wait("Malformed")
    success = result.get("status") != "error"

    # Clean up
    if os.path.exists(path):
        os.remove(path)
    print(f"   Cleaned up test file")

    if success:
        print("   [PASS] Pipeline survived malformed input")
    else:
        print(
            f"   [FAIL] Pipeline crashed on malformed input: {result.get('error', '')}"
        )


def test_contradictory_policy():
    """Inject contradictory data and verify detection."""
    print("\n3. Contradiction detection test...")

    # Slack message that contradicts refund SOP
    contradictory = json.dumps(
        [
            {
                "user": "founder",
                "channel": "revenue",
                "text": "Ignore the 14-day refund policy. If a customer complains loudly enough, give them whatever they want. We'll sort it out later.",
            }
        ]
    )
    path = os.path.join(TEST_DIR, "slack_hot_take.json")
    with open(path, "w", encoding="utf-8") as f:
        f.write(contradictory)
    print("   Injected contradictory Slack hot take")

    # Compile
    result = compile_and_wait("Contradiction")
    success = result.get("status") != "error"

    if os.path.exists(path):
        os.remove(path)
    print("   Cleaned up test file")

    if success:
        skills = result.get("skills", [])
        print(f"   Produced {len(skills)} skills despite contradiction")
        print("   [PASS] Contradiction test passed")
    else:
        print(
            f"   [FAIL] Pipeline crashed on contradictory input: {result.get('error', '')}"
        )


def test_diff_works():
    """Compile, change a file, recompile, verify diff is non-empty."""
    print("\n4. Semantic diff verification test...")

    sop_path = os.path.join(TEST_DIR, "notion_refund_sop.md")
    if not os.path.exists(sop_path):
        print("   [SKIP] Refund SOP not found")
        return

    # Read original
    with open(sop_path, "r", encoding="utf-8") as f:
        original = f.read()

    # Get current version
    r = requests.get(f"{API}/brain/versions/{COMPANY}")
    v1 = "unknown"
    if r.status_code == 200:
        versions = r.json().get("versions", [])
        if versions:
            v1 = versions[0]["version"]

    # Modify and recompile
    modified = original.replace("30 day", "60 day").replace("30-day", "60-day")
    with open(sop_path, "w", encoding="utf-8") as f:
        f.write(modified)

    compile_and_wait("Diff V2")

    # Get new version
    r = requests.get(f"{API}/brain/versions/{COMPANY}")
    v2 = "unknown"
    if r.status_code == 200:
        versions = r.json().get("versions", [])
        if versions:
            v2 = versions[0]["version"]

    # Restore original
    with open(sop_path, "w", encoding="utf-8") as f:
        f.write(original)
    print("   Restored original SOP")

    # Call diff endpoint
    if v1 != "unknown" and v2 != "unknown":
        r = requests.get(f"{API}/diff/{v1}/{v2}", params={"company_id": COMPANY})
        if r.status_code == 200:
            diff = r.json()
            summary = diff.get("summary", {})
            total_changes = (
                summary.get("added_count", 0)
                + summary.get("deleted_count", 0)
                + summary.get("modified_count", 0)
                + summary.get("confidence_shift_count", 0)
            )
            print(f"   Total changes detected: {total_changes}")
            print(
                f"   V1: {summary.get('v1_skills')} skills, V2: {summary.get('v2_skills')} skills"
            )

            if total_changes > 0:
                print("   [PASS] Semantic diff correctly detected changes")
                for m in diff.get("modified", []):
                    print(f"     - {m['id']}: {m['field']} changed")
                for cs in diff.get("confidence_shifts", []):
                    print(
                        f"     - {cs['id']}: {cs['old_confidence']}{cs['new_confidence']}"
                    )
            else:
                print("   [WARN] No changes detected — manual verification needed")
        else:
            print(f"   [FAIL] Diff endpoint returned {r.status_code}")
    else:
        print("   [SKIP] Could not determine versions for diff")


def test_multi_compile_stability():
    """Run 3 compiles in a row to verify stability."""
    print("\n5. Multi-compile stability test...")
    for i in range(3):
        print(f"\n   Run {i + 1}/3...")
        result = compile_and_wait(f"Stability Run {i + 1}")
        if result.get("status") == "error":
            print(f"   [FAIL] Compilation {i + 1} failed: {result.get('error', '')}")
            return False
        skills = result.get("skills", [])
        print(f"   Run {i + 1}: {len(skills)} skills produced")

    print("   [PASS] 3 consecutive compilations succeeded")
    return True


def main():
    print("=" * 60)
    print("KERNL STRESS TEST — Proving compiler resilience")
    print("=" * 60)

    try:
        check_health()
    except Exception as e:
        print(f"   [FATAL] API not reachable: {e}")
        sys.exit(1)

    # Test 1: Malformed input resilience
    try:
        test_malformed_markdown()
    except Exception as e:
        print(f"   [ERROR] Malformed markdown test failed: {e}")

    # Test 2: Contradictory input
    try:
        test_contradictory_policy()
    except Exception as e:
        print(f"   [ERROR] Contradiction test failed: {e}")

    # Test 3: Semantic diff
    try:
        test_diff_works()
    except Exception as e:
        print(f"   [ERROR] Diff test failed: {e}")

    # Test 4: Multi-compile stability
    try:
        test_multi_compile_stability()
    except Exception as e:
        print(f"   [ERROR] Stability test failed: {e}")

    print("\n" + "=" * 60)
    print("STRESS TEST COMPLETE")
    print("=" * 60)


if __name__ == "__main__":
    main()