Skip to content

Commit e19cf82

Browse files
authored
Merge pull request #16 from MB3R-Lab/feat/mvp-bootstrap-contract
[MVP][PR2] Discover/validate CLI + deterministic artifact + examples/docs
2 parents 7963112 + 7d100d3 commit e19cf82

16 files changed

Lines changed: 1945 additions & 0 deletions

cmd/bering/main.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
"github.com/MB3R-Lab/Bering/internal/app"
7+
)
8+
9+
func main() {
10+
runner := app.NewRunner(os.Stdout, os.Stderr)
11+
os.Exit(runner.Run(os.Args[1:]))
12+
}

configs/replicas.sample.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
replicas:
2+
frontend: 2
3+
checkout: 3
4+
payment: 2
5+
inventory: 2
6+

docs/mvp-scope-and-limits.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# MVP Scope and Limits
2+
3+
## In scope
4+
5+
- Discover model from trace files/directories.
6+
- Emit Sheaft-compatible `bering-model.json` (v1.0.0 contract).
7+
- Validate artifact with strict `metadata.schema` match.
8+
- Deterministic output ordering and canonical JSON serialization.
9+
10+
## Out of scope (MVP)
11+
12+
- Non-trace connectors (runtime service registries, topology APIs).
13+
- Advanced dependency semantics (timeouts, retries, circuit breakers).
14+
- Correlated failures and probabilistic calibration from production data.
15+
- Multi-version schema negotiation.
16+
17+
## Confidence heuristic (MVP)
18+
19+
`metadata.confidence` is deterministic and computed from discovery coverage:
20+
21+
- base score: `0.35`
22+
- `+0.20` if more than one service discovered
23+
- `+0.15` if at least one edge discovered
24+
- `+0.15` if at least one endpoint inferred
25+
- `+min(0.15, cross_service_parent_child_ratio * 0.15)`
26+
27+
Result is clamped to `[0,1]` and rounded to 2 decimals.
28+
29+
This score is informational in MVP and should not be interpreted as a calibrated
30+
probability of correctness.
31+

docs/trace-input-format.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Trace Input Format (MVP)
2+
3+
Bering MVP supports two JSON input formats.
4+
5+
## 1) Normalized spans JSON
6+
7+
Top-level shape:
8+
9+
```json
10+
{
11+
"spans": [
12+
{
13+
"trace_id": "trace-1",
14+
"span_id": "span-1",
15+
"parent_span_id": "",
16+
"service": "frontend",
17+
"kind": "server",
18+
"name": "GET /checkout",
19+
"attributes": {
20+
"http.request.method": "GET",
21+
"http.route": "/checkout"
22+
}
23+
}
24+
]
25+
}
26+
```
27+
28+
Accepted aliases:
29+
30+
- `traceId` for `trace_id`
31+
- `spanId` for `span_id`
32+
- `parentSpanId` for `parent_span_id`
33+
- `service_name` or `service.name` for `service`
34+
35+
## 2) Raw OTel JSON payload
36+
37+
Expected hierarchy:
38+
39+
- `resourceSpans[]`
40+
- `resourceSpans[].resource.attributes[]`
41+
- `resourceSpans[].scopeSpans[]` (or `instrumentationLibrarySpans[]`)
42+
- `...scopeSpans[].spans[]`
43+
44+
Supported OTel fields:
45+
46+
- `traceId`, `spanId`, `parentSpanId`, `name`, `kind`
47+
- resource/span attributes in key/value form (`key` + `value.stringValue|intValue|doubleValue|boolValue`)
48+
49+
`service.name` is resolved from resource attributes first, then span attributes.
50+
51+
## Discovery-relevant attributes
52+
53+
- HTTP endpoint inference:
54+
- `http.request.method`, `http.method`
55+
- `http.route`, `url.path`, `http.target`
56+
- Async edge heuristic:
57+
- `messaging.system`
58+
- `messaging.destination`
59+
- `messaging.operation`
60+
- span kind `producer` or `consumer`
61+
62+
## Input mode
63+
64+
- `--input` can point to:
65+
- a single JSON file
66+
- a directory (all `*.json` files recursively, sorted by path)
67+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"edges": [
3+
{
4+
"blocking": true,
5+
"from": "checkout",
6+
"kind": "sync",
7+
"to": "inventory"
8+
},
9+
{
10+
"blocking": false,
11+
"from": "checkout",
12+
"kind": "async",
13+
"to": "payment"
14+
},
15+
{
16+
"blocking": true,
17+
"from": "frontend",
18+
"kind": "sync",
19+
"to": "checkout"
20+
}
21+
],
22+
"endpoints": [
23+
{
24+
"entry_service": "checkout",
25+
"id": "checkout:POST /process",
26+
"success_predicate_ref": "checkout:POST /process"
27+
},
28+
{
29+
"entry_service": "frontend",
30+
"id": "frontend:GET /checkout",
31+
"success_predicate_ref": "frontend:GET /checkout"
32+
},
33+
{
34+
"entry_service": "frontend",
35+
"id": "frontend:GET /health",
36+
"success_predicate_ref": "frontend:GET /health"
37+
}
38+
],
39+
"metadata": {
40+
"confidence": 0.94,
41+
"discovered_at": "2026-03-03T00:00:00Z",
42+
"schema": {
43+
"digest": "sha256:7dc733936a9d3f94ab92f46a30d4c8d0f5c05d60670c4247786c59a3fe7630f7",
44+
"name": "io.mb3r.bering.model",
45+
"uri": "https://schemas.mb3r.dev/bering/model/v1.0.0/model.schema.json",
46+
"version": "1.0.0"
47+
},
48+
"source_ref": "bering://discover?input=examples%2Ftraces%2Fnormalized.sample.json",
49+
"source_type": "bering"
50+
},
51+
"services": [
52+
{
53+
"id": "checkout",
54+
"name": "checkout",
55+
"replicas": 1
56+
},
57+
{
58+
"id": "frontend",
59+
"name": "frontend",
60+
"replicas": 1
61+
},
62+
{
63+
"id": "inventory",
64+
"name": "inventory",
65+
"replicas": 1
66+
},
67+
{
68+
"id": "payment",
69+
"name": "payment",
70+
"replicas": 1
71+
}
72+
]
73+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"edges": [
3+
{
4+
"blocking": true,
5+
"from": "checkout",
6+
"kind": "sync",
7+
"to": "inventory"
8+
},
9+
{
10+
"blocking": false,
11+
"from": "checkout",
12+
"kind": "async",
13+
"to": "payment"
14+
},
15+
{
16+
"blocking": true,
17+
"from": "frontend",
18+
"kind": "sync",
19+
"to": "checkout"
20+
}
21+
],
22+
"endpoints": [
23+
{
24+
"entry_service": "checkout",
25+
"id": "checkout:POST /process",
26+
"success_predicate_ref": "checkout:POST /process"
27+
},
28+
{
29+
"entry_service": "frontend",
30+
"id": "frontend:GET /checkout",
31+
"success_predicate_ref": "frontend:GET /checkout"
32+
},
33+
{
34+
"entry_service": "frontend",
35+
"id": "frontend:GET /health",
36+
"success_predicate_ref": "frontend:GET /health"
37+
}
38+
],
39+
"metadata": {
40+
"confidence": 0.94,
41+
"discovered_at": "2026-03-03T00:00:00Z",
42+
"schema": {
43+
"digest": "sha256:7dc733936a9d3f94ab92f46a30d4c8d0f5c05d60670c4247786c59a3fe7630f7",
44+
"name": "io.mb3r.bering.model",
45+
"uri": "https://schemas.mb3r.dev/bering/model/v1.0.0/model.schema.json",
46+
"version": "1.0.0"
47+
},
48+
"source_ref": "bering://discover?input=examples%2Ftraces%2Fotel.sample.json",
49+
"source_type": "bering"
50+
},
51+
"services": [
52+
{
53+
"id": "checkout",
54+
"name": "checkout",
55+
"replicas": 1
56+
},
57+
{
58+
"id": "frontend",
59+
"name": "frontend",
60+
"replicas": 1
61+
},
62+
{
63+
"id": "inventory",
64+
"name": "inventory",
65+
"replicas": 1
66+
},
67+
{
68+
"id": "payment",
69+
"name": "payment",
70+
"replicas": 1
71+
}
72+
]
73+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"spans": [
3+
{
4+
"trace_id": "t-checkout",
5+
"span_id": "frontend-1",
6+
"service": "frontend",
7+
"kind": "server",
8+
"name": "GET /checkout",
9+
"attributes": {
10+
"http.request.method": "GET",
11+
"http.route": "/checkout"
12+
}
13+
},
14+
{
15+
"trace_id": "t-checkout",
16+
"span_id": "checkout-1",
17+
"parent_span_id": "frontend-1",
18+
"service": "checkout",
19+
"kind": "server",
20+
"name": "POST /process",
21+
"attributes": {
22+
"http.request.method": "POST",
23+
"http.route": "/process"
24+
}
25+
},
26+
{
27+
"trace_id": "t-checkout",
28+
"span_id": "payment-1",
29+
"parent_span_id": "checkout-1",
30+
"service": "payment",
31+
"kind": "consumer",
32+
"name": "kafka consume payment-events",
33+
"attributes": {
34+
"messaging.system": "kafka",
35+
"messaging.destination": "payment-events"
36+
}
37+
},
38+
{
39+
"trace_id": "t-checkout",
40+
"span_id": "inventory-1",
41+
"parent_span_id": "checkout-1",
42+
"service": "inventory",
43+
"kind": "client",
44+
"name": "reserve inventory"
45+
},
46+
{
47+
"trace_id": "t-health",
48+
"span_id": "frontend-2",
49+
"service": "frontend",
50+
"kind": "server",
51+
"name": "GET /health",
52+
"attributes": {
53+
"http.request.method": "GET",
54+
"http.route": "/health"
55+
}
56+
}
57+
]
58+
}
59+

0 commit comments

Comments
 (0)