@o-lang/resolver-tests 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ name: O-Lang Resolver Certification
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+
8
+ jobs:
9
+ certify:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write # 👈 Required to allow git push back to the repo
13
+
14
+ outputs:
15
+ status: ${{ steps.set-status.outputs.status }}
16
+
17
+ steps:
18
+ # 1️⃣ Checkout repository
19
+ - name: Checkout repository
20
+ uses: actions/checkout@v4
21
+
22
+ # 2️⃣ Setup Node.js
23
+ - name: Setup Node.js
24
+ uses: actions/setup-node@v4
25
+ with:
26
+ node-version: 18
27
+
28
+ # 3️⃣ Install dependencies
29
+ - name: Install dependencies
30
+ run: npm install
31
+
32
+ # 4️⃣ Run resolver tests
33
+ - name: Run resolver tests
34
+ id: run-tests
35
+ run: |
36
+ set -e
37
+ npm test || echo "failed" > result.txt
38
+
39
+ # 5️⃣ Set job status
40
+ - name: Set status output
41
+ id: set-status
42
+ run: |
43
+ if [ -f result.txt ]; then
44
+ echo "status=failed" >> $GITHUB_OUTPUT
45
+ else
46
+ echo "status=passed" >> $GITHUB_OUTPUT
47
+ fi
48
+
49
+ # 6️⃣ Generate SVG badge
50
+ - name: Generate badge
51
+ run: |
52
+ mkdir -p badges
53
+ STATUS="${{ steps.set-status.outputs.status }}"
54
+ if [ "$STATUS" = "passed" ]; then
55
+ COLOR="brightgreen"
56
+ MESSAGE="pass"
57
+ else
58
+ COLOR="red"
59
+ MESSAGE="fail"
60
+ fi
61
+ echo "<svg xmlns='http://www.w3.org/2000/svg' width='120' height='20'>
62
+ <linearGradient id='b' x2='0' y2='100%'>
63
+ <stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
64
+ <stop offset='1' stop-opacity='.1'/>
65
+ </linearGradient>
66
+ <mask id='a'>
67
+ <rect width='120' height='20' rx='3' fill='#fff'/>
68
+ </mask>
69
+ <g mask='url(#a)'>
70
+ <rect width='70' height='20' fill='#555'/>
71
+ <rect x='70' width='50' height='20' fill='$COLOR'/>
72
+ <rect width='120' height='20' fill='url(#b)'/>
73
+ </g>
74
+ <g fill='#fff' text-anchor='middle' font-family='Verdana' font-size='11'>
75
+ <text x='35' y='14'>Certified</text>
76
+ <text x='95' y='14'>$MESSAGE</text>
77
+ </g>
78
+ </svg>" > badges/certified.svg
79
+
80
+ # 7️⃣ Commit and push badge back to repo
81
+ - name: Commit and push badge
82
+ if: always()
83
+ run: |
84
+ git config --global user.name "O-Lang CI"
85
+ git config --global user.email "ci@olang.org"
86
+ git add badges/certified.svg
87
+ git commit -m "Update resolver certification badge [skip ci]" || echo "No changes to commit"
88
+ git push
@@ -0,0 +1,21 @@
1
+ # R-001 Allowlist Resolver Test
2
+
3
+ **Purpose:**
4
+ This test verifies that the O-Lang parser correctly captures and normalizes the list of allowed resolvers declared in a workflow.
5
+
6
+ **Workflow:**
7
+ - Workflow Name: `TestResolverAllowlist`
8
+ - Allowed Resolvers:
9
+ - `SimpleResolver`
10
+ - `AdvancedResolver`
11
+
12
+ **Assertions:**
13
+ 1. All allowed resolvers are captured correctly.
14
+ 2. Resolver names are normalized (no spaces, invalid characters).
15
+ 3. Workflow name is correctly parsed.
16
+ 4. No parser warnings are generated for valid syntax.
17
+
18
+ **Spec References:**
19
+ - §4.2 Allowed Resolvers
20
+ - §3.1 Workflow Parsing
21
+ - §2.3 Symbol Normalization
@@ -0,0 +1,55 @@
1
+ {
2
+ "test_id": "R-001-allowlist",
3
+ "protocol_version": "1.1",
4
+ "category": "resolver",
5
+ "description": "Tests that the parser correctly captures and normalizes allowed resolvers.",
6
+ "spec_ref": [
7
+ "§4.2 Allowed Resolvers",
8
+ "§3.1 Workflow Parsing",
9
+ "§2.3 Symbol Normalization"
10
+ ],
11
+ "fixtures": {
12
+ "inputs": [
13
+ {
14
+ "workflow": "R-001-allowlist/workflow.ol",
15
+ "values": {}
16
+ }
17
+ ]
18
+ },
19
+ "assertions": [
20
+ {
21
+ "id": "allowed_resolvers_listed",
22
+ "type": "allowed_resolvers_listed",
23
+ "expected": ["SimpleResolver", "AdvancedResolver"],
24
+ "severity": "fatal",
25
+ "description": "Parser must capture all allowed resolvers"
26
+ },
27
+ {
28
+ "id": "resolver_names_normalized",
29
+ "type": "resolver_names_normalized",
30
+ "severity": "fatal",
31
+ "description": "All resolver names must conform to symbol normalization rules (start with letter, alphanumeric only)"
32
+ },
33
+ {
34
+ "id": "workflow_name_present",
35
+ "type": "workflow_name_present",
36
+ "expected": "TestResolverAllowlist",
37
+ "severity": "fatal",
38
+ "description": "Workflow name must be parsed correctly"
39
+ },
40
+ {
41
+ "id": "workflow_return_values_empty",
42
+ "type": "workflow_return_values_empty",
43
+ "expected": [],
44
+ "severity": "fatal",
45
+ "description": "Return values must be empty as per workflow"
46
+ },
47
+ {
48
+ "id": "no_parse_warnings",
49
+ "type": "no_parse_warnings",
50
+ "expected": 0,
51
+ "severity": "warning",
52
+ "description": "No warnings should be issued for valid syntax"
53
+ }
54
+ ]
55
+ }
@@ -0,0 +1,7 @@
1
+ Workflow "TestResolverAllowlist"
2
+
3
+ Allow resolvers:
4
+ - SimpleResolver
5
+ - AdvancedResolver
6
+
7
+ Return
@@ -0,0 +1,26 @@
1
+ # R-002 IO Contract Resolver Test
2
+
3
+ **Purpose:**
4
+ This test validates that resolver input/output contracts are correctly recognized, including the proper handling of `Ask` and `Use` steps, and that `saveAs` values are normalized.
5
+
6
+ **Workflow:**
7
+ - Workflow Name: `TestResolverIOContract`
8
+ - Parameters: `userInput`
9
+ - Allowed Resolvers:
10
+ - `Calculator`
11
+ - `WeatherService`
12
+ - Steps:
13
+ 1. `Ask Calculator` → `saveAs: calcResult`
14
+ 2. `Use WeatherService` → `saveAs: weatherInfo`
15
+ - Return Values: `calcResult, weatherInfo`
16
+
17
+ **Assertions:**
18
+ 1. Step 1 is parsed as an `ask` step with normalized `saveAs`.
19
+ 2. Step 2 is parsed as a `use` step with normalized `saveAs`.
20
+ 3. Return statement lists all resolver outputs.
21
+ 4. No parser warnings are generated.
22
+
23
+ **Spec References:**
24
+ - §4.3 Resolver Input/Output Contracts
25
+ - §3.2 Step Parsing
26
+ - §2.3 Symbol Normalization
@@ -0,0 +1,76 @@
1
+ {
2
+ "test_id": "R-002-io-contract",
3
+ "protocol_version": "1.1",
4
+ "category": "resolver",
5
+ "description": "Tests that resolver I/O contracts are correctly recognized and saveAs fields are applied.",
6
+ "spec_ref": [
7
+ "§4.3 Resolver Input/Output Contracts",
8
+ "§3.2 Step Parsing",
9
+ "§2.3 Symbol Normalization"
10
+ ],
11
+ "fixtures": {
12
+ "inputs": [
13
+ {
14
+ "workflow": "R-002-io-contract/workflow.ol",
15
+ "values": {
16
+ "userInput": "42"
17
+ }
18
+ }
19
+ ]
20
+ },
21
+ "assertions": [
22
+ {
23
+ "id": "allowed_resolvers_listed",
24
+ "type": "allowed_resolvers_listed",
25
+ "expected": ["Calculator", "WeatherService"],
26
+ "severity": "fatal",
27
+ "description": "Parser must capture all allowed resolvers"
28
+ },
29
+ {
30
+ "id": "ask_step_type",
31
+ "type": "step_type",
32
+ "stepIndex": 0,
33
+ "expected": "ask",
34
+ "severity": "fatal",
35
+ "description": "Step 1 must be parsed as 'ask'"
36
+ },
37
+ {
38
+ "id": "ask_step_saveas",
39
+ "type": "step_saveas",
40
+ "stepIndex": 0,
41
+ "expected": "calcResult",
42
+ "severity": "fatal",
43
+ "description": "Step 1 saveAs must be 'calcResult'"
44
+ },
45
+ {
46
+ "id": "use_step_type",
47
+ "type": "step_type",
48
+ "stepIndex": 1,
49
+ "expected": "use",
50
+ "severity": "fatal",
51
+ "description": "Step 2 must be parsed as 'use'"
52
+ },
53
+ {
54
+ "id": "use_step_saveas",
55
+ "type": "step_saveas",
56
+ "stepIndex": 1,
57
+ "expected": "weatherInfo",
58
+ "severity": "fatal",
59
+ "description": "Step 2 saveAs must be 'weatherInfo'"
60
+ },
61
+ {
62
+ "id": "workflow_return_values",
63
+ "type": "workflow_return_values",
64
+ "expected": ["calcResult", "weatherInfo"],
65
+ "severity": "fatal",
66
+ "description": "Return statement must list all saved outputs"
67
+ },
68
+ {
69
+ "id": "no_parse_warnings",
70
+ "type": "no_parse_warnings",
71
+ "expected": 0,
72
+ "severity": "warning",
73
+ "description": "No warnings for valid I/O contracts"
74
+ }
75
+ ]
76
+ }
@@ -0,0 +1,13 @@
1
+ Workflow "TestResolverIOContract" with userInput
2
+
3
+ Allow resolvers:
4
+ - Calculator
5
+ - WeatherService
6
+
7
+ Step 1: Ask Calculator
8
+ Save as calcResult
9
+
10
+ Step 2: Use WeatherService
11
+ Save as weatherInfo
12
+
13
+ Return calcResult, weatherInfo
@@ -0,0 +1,27 @@
1
+ # R-003 Failure Modes Resolver Test
2
+
3
+ **Purpose:**
4
+ This test validates that resolver failures, missing resolvers, and runtime errors are correctly handled and surfaced by the parser/runtime.
5
+
6
+ **Workflow:**
7
+ - Workflow Name: `TestResolverFailureModes`
8
+ - Parameters: `userInput`
9
+ - Allowed Resolvers:
10
+ - `ReliableResolver`
11
+ - `UnstableResolver`
12
+ - Steps:
13
+ 1. `Ask ReliableResolver` → `saveAs: reliableResult`
14
+ 2. `Ask UnstableResolver` → `saveAs: unstableResult`
15
+ - Return Values: `reliableResult, unstableResult`
16
+
17
+ **Assertions:**
18
+ 1. Steps 1 & 2 are correctly parsed as `ask` resolver steps.
19
+ 2. `saveAs` values are normalized.
20
+ 3. Return statement lists all resolver outputs.
21
+ 4. Errors from failing resolvers (e.g., `UnstableResolver`) are surfaced.
22
+ 5. Missing resolvers (e.g., `MissingResolver`) trigger proper errors.
23
+
24
+ **Spec References:**
25
+ - §4.4 Resolver Failure Modes
26
+ - §3.2 Step Parsing
27
+ - §5.1 Error Handling
@@ -0,0 +1,84 @@
1
+ {
2
+ "test_id": "R-003-failure-modes",
3
+ "protocol_version": "1.1",
4
+ "category": "resolver",
5
+ "description": "Tests that resolver failure modes and retry policies are parsed and exposed.",
6
+ "spec_ref": [
7
+ "§4.4 Resolver Failure Modes",
8
+ "§3.3 Step Parsing",
9
+ "§2.3 Symbol Normalization"
10
+ ],
11
+ "fixtures": {
12
+ "inputs": [
13
+ {
14
+ "workflow": "R-003-failure-modes/workflow.ol",
15
+ "values": {
16
+ "userInput": "someInput"
17
+ }
18
+ }
19
+ ]
20
+ },
21
+ "assertions": [
22
+ {
23
+ "id": "allowed_resolvers_listed",
24
+ "type": "allowed_resolvers_listed",
25
+ "expected": ["ReliableResolver", "UnstableResolver"],
26
+ "severity": "fatal",
27
+ "description": "Allowed resolvers must be captured"
28
+ },
29
+ {
30
+ "id": "step_0_saveas",
31
+ "type": "step_saveas",
32
+ "stepIndex": 0,
33
+ "expected": "reliableResult",
34
+ "severity": "fatal",
35
+ "description": "Step 0 saveAs"
36
+ },
37
+ {
38
+ "id": "step_1_saveas",
39
+ "type": "step_saveas",
40
+ "stepIndex": 1,
41
+ "expected": "unstableResult",
42
+ "severity": "fatal",
43
+ "description": "Step 1 saveAs"
44
+ },
45
+ {
46
+ "id": "workflow_name_present",
47
+ "type": "workflow_name_present",
48
+ "expected": "TestResolverFailureModes",
49
+ "severity": "fatal",
50
+ "description": "Workflow name parsed"
51
+ },
52
+ {
53
+ "id": "workflow_return_values",
54
+ "type": "workflow_return_values",
55
+ "expected": ["reliableResult", "unstableResult"],
56
+ "severity": "fatal",
57
+ "description": "Return values listed"
58
+ },
59
+ {
60
+ "id": "unstable_resolver_failure_policies",
61
+ "type": "step_failure_policies",
62
+ "stepIndex": 1,
63
+ "expected": {
64
+ "TIMEOUT": {
65
+ "action": "retry",
66
+ "count": 2
67
+ },
68
+ "NETWORK_ERROR": {
69
+ "action": "fail",
70
+ "count": 0
71
+ }
72
+ },
73
+ "severity": "fatal",
74
+ "description": "Failure modes and retry counts must be parsed"
75
+ },
76
+ {
77
+ "id": "no_parse_warnings",
78
+ "type": "no_parse_warnings",
79
+ "expected": 0,
80
+ "severity": "warning",
81
+ "description": "No warnings for valid failure mode syntax"
82
+ }
83
+ ]
84
+ }
@@ -0,0 +1,13 @@
1
+ Workflow "TestResolverFailureModes" with userInput
2
+
3
+ Allow resolvers:
4
+ - ReliableResolver
5
+ - UnstableResolver
6
+
7
+ Step 1: Ask ReliableResolver
8
+ Save as reliableResult
9
+
10
+ Step 2: Ask UnstableResolver
11
+ Save as unstableResult
12
+
13
+ Return reliableResult, unstableResult
@@ -0,0 +1,5 @@
1
+ # R-005: Resolver Metadata Contract
2
+
3
+ Validates that resolver packages declare valid **inputs**, **outputs**, **resolverName**, and **failure modes**.
4
+
5
+ This test ensures that static resolver contracts (e.g., `resolver.js`) are well-formed and align with O-lang’s governance model—enabling tooling, linting, and safe composition.
@@ -0,0 +1,57 @@
1
+ {
2
+ "test_id": "R-004-invalid-syntax",
3
+ "protocol_version": "1.1",
4
+ "category": "resolver",
5
+ "description": "Tests that parser emits warnings or errors for invalid syntax.",
6
+ "spec_ref": [
7
+ "§2.3 Symbol Normalization",
8
+ "§3.1 Workflow Parsing",
9
+ "§4.2 Allowed Resolvers"
10
+ ],
11
+ "fixtures": {
12
+ "inputs": [
13
+ {
14
+ "workflow": "R-004-invalid-syntax/workflow.ol",
15
+ "values": {}
16
+ }
17
+ ]
18
+ },
19
+ "assertions": [
20
+ {
21
+ "id": "warns_on_invalid_resolver_name",
22
+ "type": "contains_warning",
23
+ "expected_substring": "invalid resolver name",
24
+ "severity": "fatal",
25
+ "description": "Must warn about resolver name with space"
26
+ },
27
+ {
28
+ "id": "warns_on_invalid_saveas",
29
+ "type": "contains_warning",
30
+ "expected_substring": "invalid identifier",
31
+ "severity": "fatal",
32
+ "description": "Must warn about malformed Save as"
33
+ },
34
+ {
35
+ "id": "warns_on_unrecognized_step",
36
+ "type": "contains_warning",
37
+ "expected_substring": "unrecognized step",
38
+ "severity": "fatal",
39
+ "description": "Must warn about unknown step type"
40
+ },
41
+ {
42
+ "id": "warns_on_duplicate_saveas",
43
+ "type": "contains_warning",
44
+ "expected_substring": "duplicate saveAs",
45
+ "severity": "fatal",
46
+ "description": "Must warn about duplicate Save as names"
47
+ },
48
+ {
49
+ "id": "parse_status_has_warnings",
50
+ "type": "status_greater_than",
51
+ "path": "__warnings.length",
52
+ "expected": 0,
53
+ "severity": "fatal",
54
+ "description": "Parser must emit at least one warning"
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,16 @@
1
+ // resolver.ol (treated as a JS module in test)
2
+ module.exports = {
3
+ resolverName: "RiskAssessment",
4
+ inputs: [
5
+ { name: "transaction_id", type: "string", required: true },
6
+ { name: "user_id", type: "string", required: true }
7
+ ],
8
+ outputs: [
9
+ { name: "risk_score", type: "number" },
10
+ { name: "confidence", type: "number" }
11
+ ],
12
+ failures: [
13
+ { code: "DATA_UNAVAILABLE", retries: 1 },
14
+ { code: "MODEL_ERROR", retries: 0 }
15
+ ]
16
+ };
@@ -0,0 +1,5 @@
1
+ # R-005: Resolver Metadata Contract
2
+
3
+ Validates that resolver packages declare valid **inputs**, **outputs**, **resolverName**, and **failure modes**.
4
+
5
+ This test ensures that static resolver contracts (e.g., `resolver.js`) are well-formed and align with O-lang’s governance model—enabling tooling, linting, and safe composition.
@@ -0,0 +1,16 @@
1
+ // R-005-resolver-metadata-contract/resolver.js
2
+ module.exports = {
3
+ resolverName: "RiskAssessment",
4
+ inputs: [
5
+ { name: "transaction_id", type: "string", required: true },
6
+ { name: "user_id", type: "string", required: true }
7
+ ],
8
+ outputs: [
9
+ { name: "risk_score", type: "number" },
10
+ { name: "confidence", type: "number" }
11
+ ],
12
+ failures: [
13
+ { code: "DATA_UNAVAILABLE", retries: 1 },
14
+ { code: "MODEL_ERROR", retries: 0 }
15
+ ]
16
+ };
@@ -0,0 +1,60 @@
1
+ {
2
+ "test_id": "R-005-resolver-metadata-contract",
3
+ "protocol_version": "1.1",
4
+ "category": "resolver",
5
+ "description": "Tests that resolver metadata (inputs, outputs, name) is valid and complete.",
6
+ "spec_ref": [
7
+ "§4.3 Resolver Input/Output Contracts",
8
+ "§4.4 Resolver Failure Modes",
9
+ "§2.3 Symbol Normalization"
10
+ ],
11
+ "fixtures": {
12
+ "inputs": [
13
+ {
14
+ "resolver_contract": "R-005-resolver-metadata-contract/resolver.ol"
15
+ }
16
+ ]
17
+ },
18
+ "assertions": [
19
+ {
20
+ "id": "resolver_has_name",
21
+ "type": "resolver_has_field",
22
+ "field": "resolverName",
23
+ "expected": "RiskAssessment",
24
+ "severity": "fatal",
25
+ "description": "Resolver must declare resolverName"
26
+ },
27
+ {
28
+ "id": "resolver_inputs_valid",
29
+ "type": "resolver_inputs_valid",
30
+ "severity": "fatal",
31
+ "description": "Inputs must be array of {name, type, required}"
32
+ },
33
+ {
34
+ "id": "resolver_outputs_valid",
35
+ "type": "resolver_outputs_valid",
36
+ "severity": "fatal",
37
+ "description": "Outputs must be array of {name, type}"
38
+ },
39
+ {
40
+ "id": "resolver_input_names_normalized",
41
+ "type": "field_names_normalized",
42
+ "field": "inputs",
43
+ "severity": "fatal",
44
+ "description": "Input names must follow symbol normalization"
45
+ },
46
+ {
47
+ "id": "resolver_output_names_normalized",
48
+ "type": "field_names_normalized",
49
+ "field": "outputs",
50
+ "severity": "fatal",
51
+ "description": "Output names must follow symbol normalization"
52
+ },
53
+ {
54
+ "id": "resolver_failures_declared",
55
+ "type": "resolver_failures_valid",
56
+ "severity": "warning",
57
+ "description": "Failure modes should be declared for production resolvers"
58
+ }
59
+ ]
60
+ }
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # O-Lang Resolver Test Suite
2
+
3
+ **Version:** 1.0.0
4
+ **Maintained by:** O-Lang Core Team
5
+ **Specification:** O-Lang Resolver Contract v1.x
6
+ **License:** MIT
7
+
8
+ ---
9
+
10
+ ## Certification Badge
11
+
12
+ [![O-Lang Resolver Certification](badges/certified.svg)](https://medium.com/@o-lang/olang-resolver-certification-essay)
13
+
14
+ Click the badge to read the official essay on Medium explaining your resolver certification process, conformance philosophy, and project vision.
15
+
16
+ You can also link to the GitHub repo directly:
17
+
18
+ [![O-Lang Resolver Certification](badges/certified.svg)](https://github.com/O-Lang-Central/resolver-test)
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ This repository provides the **official O-Lang Resolver Test Harness**, designed to validate any O-Lang resolver implementation against:
25
+
26
+ - Allowlist compliance
27
+ - Input/output contracts
28
+ - Failure modes
29
+
30
+ It mirrors the **kernel test philosophy**: deterministic, safe, and locked to a single entrypoint.
31
+
32
+ All tests are **self-contained** in folders `R-001`, `R-002`, `R-003`, etc., each containing:
33
+
34
+ - `workflow.ol` — the workflow for the test
35
+ - `test.json` — the assertions for this test suite
36
+ - `resolver.js` — for metadata (if applicable)
37
+ - `README.md` — notes for this suite
38
+
39
+ ---
40
+
41
+ ## Environment Setup
42
+
43
+ Set the resolver to test:
44
+
45
+ ```bash
46
+ export OLANG_RESOLVER=./path-to-your-resolver
@@ -0,0 +1,18 @@
1
+ <svg xmlns='http://www.w3.org/2000/svg' width='120' height='20'>
2
+ <linearGradient id='b' x2='0' y2='100%'>
3
+ <stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
4
+ <stop offset='1' stop-opacity='.1'/>
5
+ </linearGradient>
6
+ <mask id='a'>
7
+ <rect width='120' height='20' rx='3' fill='#fff'/>
8
+ </mask>
9
+ <g mask='url(#a)'>
10
+ <rect width='70' height='20' fill='#555'/>
11
+ <rect x='70' width='50' height='20' fill='red'/>
12
+ <rect width='120' height='20' fill='url(#b)'/>
13
+ </g>
14
+ <g fill='#fff' text-anchor='middle' font-family='Verdana' font-size='11'>
15
+ <text x='35' y='14'>Certified</text>
16
+ <text x='95' y='14'>fail</text>
17
+ </g>
18
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="159" height="20" role="img" aria-label="O-Lang v1: Conformant"><title>O-Lang v1: Conformant</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="159" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="84" height="20" fill="#555"/><rect x="84" width="75" height="20" fill="#4c1"/><rect width="159" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+"/><text aria-hidden="true" x="515" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="570">O-Lang v1</text><text x="515" y="140" transform="scale(.1)" fill="#fff" textLength="570">O-Lang v1</text><text aria-hidden="true" x="1205" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="650">Conformant</text><text x="1205" y="140" transform="scale(.1)" fill="#fff" textLength="650">Conformant</text></g></svg>