A general-purpose X-Ray library and dashboard that provides visibility into multi-step decision pipelines, enabling quick debugging and root-cause analysis by capturing and visualizing each decision step along with its reasoning.
X-Ray provides transparency into multi-step decision processes. Unlike traditional distributed tracing which answers "What functions were called and how long did they take?", X-Ray answers "Why did the system make this decision?"
- X-Ray Library/SDK: Lightweight wrapper to capture decision context at each pipeline step
- Dashboard UI: Visual interface to explore execution steps and debug decision-making
- Demo Application: 3-step competitor selection pipeline demonstrating the X-Ray library
xray-system/ # Monorepo root
├── packages/
│ ├── xray-core/ # Core X-Ray library
│ ├── xray-dashboard/ # React dashboard UI
│ └── demo-app/ # Demo application
└── package.json # Workspace config
- Node.js 18+
- npm 9+
cd xray-decision-observability
npm installnpm run devThis starts the dashboard at http://localhost:5173. Click "Run Demo Pipeline" to see X-Ray in action.
For detailed library docs, usage and API reference, Kindly visit https://xray-core.netlify.app
import { XRay, InMemoryStorage } from 'xray-core';
// Initialize session with in-memory storage
const xray = new XRay({ storage: new InMemoryStorage() });
// Start a session
const session = xray
.session('my-pipeline')
.meta({ input: 'some context' })
.start();
// Record a step
session
.step('process_data', 'transform')
.input({ data: [1, 2, 3] })
.output({ result: 6 })
.reasoning('Summed all input values to produce aggregate')
.complete();
// Complete the session
session.complete();const step = session
.step('apply_filters', 'filter')
.input({ candidatesCount: 50 })
.addFilter('price_range', '0.5x - 2x of reference', { min: 15, max: 60 })
.addFilter('min_rating', 'At least 3.8 stars', { threshold: 3.8 });
// Evaluate each candidate
candidates.forEach((candidate) => {
step.evaluate(candidate.id, candidate, [
{ criterion: 'price_range', passed: true, detail: '$44.99 within range' },
{ criterion: 'min_rating', passed: true, detail: '4.5 >= 3.8' },
]);
});
step
.output({ passed: 12, failed: 38 })
.reasoning('Applied filters to narrow candidates')
.complete();| Method | Description |
|---|---|
session(name) |
Create a new session builder |
getSession(id) |
Get a session by ID |
getAllSessions() |
Get all sessions |
deleteSession(id) |
Delete a session |
clear() |
Clear all sessions |
export() |
Export all data as JSON |
import(data) |
Import data from JSON |
| Method | Description |
|---|---|
meta(data) |
Add metadata to the session |
start() |
Start the session |
step(name, type) |
Create a new step builder |
complete() |
Mark session as completed |
fail(error?) |
Mark session as failed |
| Method | Description |
|---|---|
input(data) |
Set input data |
output(data) |
Set output data |
reasoning(explanation) |
Set the decision reasoning |
addFilter(name, rule, config) |
Add a filter definition |
evaluate(id, candidate, results) |
Evaluate a candidate |
complete() |
Mark step as completed |
fail(error) |
Mark step as failed |
X-Ray’s SDK instruments existing pipelines with a fluent Builder API to capture explainable context at each decision step.
- Model: Session → Steps → Evaluations; each step records input, output, reasoning, filters, and errors.
- Storage: Pluggable adapters; InMemoryStorage by default for zero-setup development.
- Contract: A single typed schema consumed by the dashboard to render timelines and deep step details.
- Integration: Wrap existing code with .session()/.step() calls—no refactor required.
- Portability: Export/import JSON for sharing runs; designed to swap in persistent stores later.
- Clean, readable integration code
- Self-documenting step construction
- Non-intrusive - wraps existing logic without major refactoring
- Simple for demos, quick proto-typing and single-page applications
- Easy to extend with other storage options (localStorage, database)
- No separate API server required
- One command to run everything
- Demonstrates real-time data capture
- Volatile in-memory store; data is lost on refresh/restart
- Single-process scope; no remote ingestion or cross-service tracing
- Dashboard is dev-focused; no auth/RBAC or multi-user controls
- Manual instrumentation; exceptions aren’t auto-captured into steps
- Large payloads aren’t optimized (no truncation/streaming); memory grows with session size
- Limited discoverability in UI (no full-text search, tagging, or pinning)
- Schema is flexible and not strictly enforced for generalization; potential for inconsistent data shapes
- Persistence adapters: LocalStorage (browser), file, database, etc.
- Search and organization: text search, more filters by various fields, querying, tagging/pinning important sessions
- Performance: payload limits, truncation, handling large volumes of data, lazy-loading evaluations
- Auth and roles: basic login, read-only viewer mode, per-session access rules
- Observability integration: map to OpenTelemetry trace/span IDs; link to logs/traces for correlation
- Export/import: UI to download/upload JSON; sharable session URLs
- Configurable Schema: enforce strict types for inputs/outputs/reasoning per step type
- Language: TypeScript
- Runtime: Node.js
- Dashboard: React, Vite, Tailwind CSS, Lucide React
- Monorepo: npm workspaces
Aman Tiwari
- Email : amananjalitiwari2007@gmail.com, amantiwari6122@gmail.com
- Portfolio : https://amantiwari.dev
- LinkedIn : https://www.linkedin.com/in/aman-tiwari001
- GitHub : https://github.com/aman-tiwari001