Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,23 @@ Do not mark an acceptance gate complete without recorded evidence. External revi
uv sync --extra dev
uv run pytest
```

## Tagging draft snapshots and releases

Snapshot repo state with **git tags**, not zip archives. GitHub already
generates a downloadable source zip/tarball for every tag or release, so
committing archives into the repo only adds undiffable bloat.

- `specification/v0.4/conformance.md` asks implementers to cite claims like
*"aligned with v0.4-draft as observed on 2026-07-21"*. That citation is
only checkable if the repo state on that date is retrievable — that's
what a tag is for.
- Use `vX.Y-draft-YYYY-MM-DD` for an informal, citable snapshot of an
in-progress milestone (draft content keeps moving, so date-stamp it).
- Reserve the bare `vX.Y` tag for when a milestone's acceptance criteria
(see each milestone's `acceptance-criteria.md`) are fully checked and the
layer actually freezes — that tag then means something stable, not a
moving draft.
- Attach a GitHub Release on top of a tag once it's worth announcing
externally (e.g. summarizing which acceptance gates closed); not required
for every draft snapshot.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ AI frameworks and instrumentation
observability, evaluation, safety, and operations tools
```

DeepAgentLabs stewards the specification. AgenticLens, Agentic Chaos, and DeepAgent MCP may implement or consume it, but none of them owns the contract.
DeepAgentLabs stewards the specification today and is its sole editor. AgenticLens, Agentic Chaos, and DeepAgent MCP may implement or consume it, but none of them owns the contract. Vendor-neutrality is the design goal, not yet an established fact: several acceptance gates — independent implementer review, validation against artifacts from at least two unrelated producers — remain open (see each milestone's acceptance criteria and the [roadmap](ROADMAP.md)). Treat "vendor-neutral" as the intended end state until those gates close.

## Current maturity

Expand Down
4 changes: 4 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ Formalize concepts proven in implementation repositories.
- optional report/investigation artifact schemas (if implementation usage
proves the need)
- incident context and operator-facing summary semantics
- OpenTelemetry GenAI semantic convention binding — a non-normative mapping
document from canonical `aiops.*` events and common attributes to OTel
spans, span events, and resource attributes, so producers already emitting
OTel do not need to invent their own bridge independently

Success means implementations can attach provenance to findings using
spec-standard objects, and producers can run conformance checks independently.
Expand Down
3 changes: 3 additions & 0 deletions specification/v0.4/acceptance-criteria.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
- [x] Requests, Steps, Agents, runtime occurrences, evidence, Incidents, relationships, and semantic events are representable.
- [x] Valid and invalid fixtures are automatically tested.
- [x] Sensitive content is optional and extensibility is namespaced.
- [x] `event_name` accepts both the canonical `aiops.*` catalog and reverse-domain
namespaced extension events; extension names MUST NOT collide with the
`aiops` namespace.

## Review gates

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"spec_version": "0.4-draft",
"artifact_type": "run",
"id": "run-collision",
"started_at": "2026-07-21T06:00:00Z",
"status": "completed",
"requests": [],
"steps": [],
"relationships": [],
"events": [
{"event_id": "event-1", "event_name": "aiops.custom.event", "occurred_at": "2026-07-21T06:00:00Z", "object_id": "run-collision", "object_type": "run"}
]
}
13 changes: 13 additions & 0 deletions specification/v0.4/examples/valid/run-extension-event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"spec_version": "0.4-draft",
"artifact_type": "run",
"id": "run-ext-001",
"started_at": "2026-07-21T06:00:00Z",
"status": "completed",
"requests": [],
"steps": [],
"relationships": [],
"events": [
{"event_id": "event-ext-1", "event_name": "io.deepagentlabs.agenticlens.custom_event", "occurred_at": "2026-07-21T06:00:00Z", "object_id": "run-ext-001", "object_type": "run"}
]
}
10 changes: 8 additions & 2 deletions specification/v0.4/schemas/common.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"$defs": {
"id": {"type": "string", "minLength": 1, "pattern": ".*\\S.*"},
"time": {"type": "string", "format": "date-time"},
"extensions": {"type": "object", "propertyNames": {"pattern": "^[a-z0-9]+(?:[.-][a-z0-9]+)+$"}},
"extension_name": {"type": "string", "pattern": "^(?!aiops(?:\\.|$))[a-z0-9]+(?:[_-][a-z0-9]+)*(?:\\.[a-z0-9]+(?:[_-][a-z0-9]+)*){2,}$"},
"extensions": {"type": "object", "propertyNames": {"$ref": "#/$defs/extension_name"}},
"reference": {
"type": "object",
"required": ["id", "type"],
Expand Down Expand Up @@ -33,11 +34,16 @@
"allOf": [{"if": {"properties": {"name": {"const": "cost"}}, "required": ["name"]}, "then": {"required": ["currency"]}}],
"additionalProperties": false
},
"canonical_event_name": {"enum": ["aiops.run.started", "aiops.run.completed", "aiops.run.failed", "aiops.run.cancelled", "aiops.request.received", "aiops.request.completed", "aiops.request.rejected", "aiops.step.started", "aiops.step.completed", "aiops.step.failed", "aiops.step.cancelled", "aiops.agent.started", "aiops.agent.waiting", "aiops.agent.completed", "aiops.agent.failed", "aiops.model.requested", "aiops.model.responded", "aiops.model.failed", "aiops.prompt.rendered", "aiops.context.assembled", "aiops.tool.requested", "aiops.tool.authorized", "aiops.tool.completed", "aiops.tool.failed", "aiops.retrieval.started", "aiops.retrieval.completed", "aiops.retrieval.failed", "aiops.memory.read", "aiops.memory.written", "aiops.memory.updated", "aiops.memory.deleted", "aiops.memory.failed", "aiops.evaluation.completed", "aiops.evaluation.failed", "aiops.safety.detected", "aiops.safety.reviewed", "aiops.safety.mitigated", "aiops.reliability.detected", "aiops.reliability.recovered", "aiops.incident.opened", "aiops.incident.updated", "aiops.incident.mitigated", "aiops.incident.resolved"]},
"event": {
"type": "object",
"required": ["event_id", "event_name", "occurred_at", "object_id", "object_type"],
"properties": {
"event_id": {"$ref": "#/$defs/id"}, "event_name": {"enum": ["aiops.run.started", "aiops.run.completed", "aiops.run.failed", "aiops.run.cancelled", "aiops.request.received", "aiops.request.completed", "aiops.request.rejected", "aiops.step.started", "aiops.step.completed", "aiops.step.failed", "aiops.step.cancelled", "aiops.agent.started", "aiops.agent.waiting", "aiops.agent.completed", "aiops.agent.failed", "aiops.model.requested", "aiops.model.responded", "aiops.model.failed", "aiops.prompt.rendered", "aiops.context.assembled", "aiops.tool.requested", "aiops.tool.authorized", "aiops.tool.completed", "aiops.tool.failed", "aiops.retrieval.started", "aiops.retrieval.completed", "aiops.retrieval.failed", "aiops.memory.read", "aiops.memory.written", "aiops.memory.updated", "aiops.memory.deleted", "aiops.memory.failed", "aiops.evaluation.completed", "aiops.evaluation.failed", "aiops.safety.detected", "aiops.safety.reviewed", "aiops.safety.mitigated", "aiops.reliability.detected", "aiops.reliability.recovered", "aiops.incident.opened", "aiops.incident.updated", "aiops.incident.mitigated", "aiops.incident.resolved"]},
"event_id": {"$ref": "#/$defs/id"},
"event_name": {
"description": "Either a canonical aiops.* name from the reviewed catalog, or a reverse-domain namespaced extension event (e.g. io.deepagentlabs.agenticlens.custom_event). Extension names MUST NOT start with the aiops namespace.",
Comment thread
pramodbn27 marked this conversation as resolved.
"anyOf": [{"$ref": "#/$defs/canonical_event_name"}, {"$ref": "#/$defs/extension_name"}]
},
"occurred_at": {"$ref": "#/$defs/time"}, "object_id": {"$ref": "#/$defs/id"}, "object_type": {"enum": ["run", "request", "step", "agent", "model_interaction", "prompt", "context", "tool_invocation", "rag_retrieval", "memory_operation", "evaluation", "safety_signal", "reliability_event", "incident"]},
"attributes": {"type": "object"}, "extensions": {"$ref": "#/$defs/extensions"}
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_v04_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def test_v04_schemas_are_valid() -> None:
def test_v03_event_catalog_matches_v04_schema() -> None:
conventions = (ROOT / "specification" / "v0.3" / "semantic-conventions.md").read_text(encoding="utf-8")
documented = set(re.findall(r"`(aiops\.[a-z0-9.]+)`", conventions))
schema_events = set(SCHEMA_DOCUMENTS["common.schema.json"]["$defs"]["event"]["properties"]["event_name"]["enum"])
schema_events = set(SCHEMA_DOCUMENTS["common.schema.json"]["$defs"]["canonical_event_name"]["enum"])
assert documented == schema_events


Expand Down
Loading