Skip to content

refactor: rename Sarthi→TrackGuard, Charaka→AnomalyDetector, Mantripa…#25

Merged
Aparnap2 merged 1 commit into
mainfrom
feat/startup-guardian
Jun 16, 2026
Merged

refactor: rename Sarthi→TrackGuard, Charaka→AnomalyDetector, Mantripa…#25
Aparnap2 merged 1 commit into
mainfrom
feat/startup-guardian

Conversation

@Aparnap2

@Aparnap2 Aparnap2 commented Jun 16, 2026

Copy link
Copy Markdown
Owner

…rishad→AlertCouncil, Nyayadish→ConflictResolver, SarthiRouter→WorkflowRouter

  • Product name: Sarthi → TrackGuard (all configs, prompts, strings)
  • Go: SarthiRouter → WorkflowRouter, sarthi_router.go → workflow_router.go
  • Python: Charaka → AnomalyDetector, CharakaAlert → AnomalyAlert
  • Python: Mantriparishad → AlertCouncil, CouncilAlert → AlertCouncilResult
  • Python: Nyayadish → ConflictResolver
  • Python: get_sarthi_database_url → get_database_url
  • Files: sarthi_scheduler.py → trackguard_scheduler.py
  • Files: sarthi-mocks.json → trackguard-mocks.json
  • All config strings sarthi.* → trackguard.*
  • README: updated with TrackGuard naming, removed Kautilya/Arthashastra refs
  • .gitignore: added graphify-out/

Summary by CodeRabbit

Release Notes

  • Infrastructure

    • Refactored LLM client to use OpenAI Python SDK with streaming support
    • Added Opencode graphify plugin for execution monitoring
  • Branding & Identity

    • Completed rebranding from Sarthi to TrackGuard across all services, channels, and configurations
    • Improved internal component naming for clarity (e.g., AnomalyDetector, AlertCouncil)
  • Configuration

    • Updated service identifiers, database connections, and message queues to TrackGuard namespace
    • Standardized database URL sourcing across all modules
  • Documentation

    • Added operational guide for Langfuse trace analysis and continuous improvement

…rishad→AlertCouncil, Nyayadish→ConflictResolver, SarthiRouter→WorkflowRouter

- Product name: Sarthi → TrackGuard (all configs, prompts, strings)
- Go: SarthiRouter → WorkflowRouter, sarthi_router.go → workflow_router.go
- Python: Charaka → AnomalyDetector, CharakaAlert → AnomalyAlert
- Python: Mantriparishad → AlertCouncil, CouncilAlert → AlertCouncilResult
- Python: Nyayadish → ConflictResolver
- Python: get_sarthi_database_url → get_database_url
- Files: sarthi_scheduler.py → trackguard_scheduler.py
- Files: sarthi-mocks.json → trackguard-mocks.json
- All config strings sarthi.* → trackguard.*
- README: updated with TrackGuard naming, removed Kautilya/Arthashastra refs
- .gitignore: added graphify-out/
@Aparnap2 Aparnap2 merged commit 31e0ce4 into main Jun 16, 2026
1 of 14 checks passed
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e9c270b9-20cc-4af0-a1c2-fb8bdc9afbb7

📥 Commits

Reviewing files that changed from the base of the PR and between 38a7950 and 82a2a13.

📒 Files selected for processing (130)
  • .gitignore
  • .opencode/opencode.json
  • .opencode/plugins/graphify.js
  • README.md
  • apps/ai/.deepeval/.deepeval_telemetry.txt
  • apps/ai/src/activities/__init__.py
  • apps/ai/src/activities/log_decision.py
  • apps/ai/src/activities/send_telegram.py
  • apps/ai/src/activities/synthesize_weekly_brief.py
  • apps/ai/src/agents/__init__.py
  • apps/ai/src/agents/anomaly/__init__.py
  • apps/ai/src/agents/anomaly/graph.py
  • apps/ai/src/agents/base.py
  • apps/ai/src/agents/bi/__init__.py
  • apps/ai/src/agents/bi/nodes.py
  • apps/ai/src/agents/bi/prompts.py
  • apps/ai/src/agents/cofounder/__init__.py
  • apps/ai/src/agents/cofounder/arbiter.py
  • apps/ai/src/agents/cofounder/joint_council.py
  • apps/ai/src/agents/cofounder/router.py
  • apps/ai/src/agents/ops/__init__.py
  • apps/ai/src/agents/ops/nodes.py
  • apps/ai/src/agents/ops/prompts.py
  • apps/ai/src/config/__init__.py
  • apps/ai/src/config/config_module.py
  • apps/ai/src/config/database.py
  • apps/ai/src/config/event_dictionary.py
  • apps/ai/src/config/llm.py
  • apps/ai/src/config/llm_guard.py
  • apps/ai/src/db/__init__.py
  • apps/ai/src/db/hiring.py
  • apps/ai/src/db/investor_relationships.py
  • apps/ai/src/debug_server.py
  • apps/ai/src/events/__init__.py
  • apps/ai/src/events/bus.py
  • apps/ai/src/events/redpanda.py
  • apps/ai/src/guardian/__init__.py
  • apps/ai/src/hitl/__init__.py
  • apps/ai/src/integrations/__init__.py
  • apps/ai/src/integrations/plaid.py
  • apps/ai/src/integrations/product_db.py
  • apps/ai/src/integrations/slack.py
  • apps/ai/src/integrations/stripe.py
  • apps/ai/src/legacy/agents/v2/anomaly/nodes.py
  • apps/ai/src/legacy/agents/v2/anomaly/prompts.py
  • apps/ai/src/legacy/agents/v2/pulse/__init__.py
  • apps/ai/src/legacy/agents/v2/pulse/nodes.py
  • apps/ai/src/legacy/agents/v2/pulse/prompts.py
  • apps/ai/src/legacy/agents/v2/qa/prompts.py
  • apps/ai/src/llmops/__init__.py
  • apps/ai/src/memory/__init__.py
  • apps/ai/src/memory/compressed.py
  • apps/ai/src/memory/qdrant_ops.py
  • apps/ai/src/orchestration/run_weekly_synthesis.py
  • apps/ai/src/registry/registry.py
  • apps/ai/src/scheduler/__init__.py
  • apps/ai/src/scheduler/trackguard_scheduler.py
  • apps/ai/src/schemas/__init__.py
  • apps/ai/src/schemas/desk_results.py
  • apps/ai/src/schemas/event_envelope.py
  • apps/ai/src/schemas/guardian.py
  • apps/ai/src/services/delivery/__init__.py
  • apps/ai/src/services/delivery/formatter.py
  • apps/ai/src/services/delivery/schemas.py
  • apps/ai/src/services/langfuse_client.py
  • apps/ai/src/services/memory/__init__.py
  • apps/ai/src/services/weekly_checkin.py
  • apps/ai/src/services/workflow/__init__.py
  • apps/ai/src/services/workflow/events.py
  • apps/ai/src/services/workflow/worker.py
  • apps/ai/src/session/001_session_layer.sql
  • apps/ai/src/session/__init__.py
  • apps/ai/src/session/context.py
  • apps/ai/src/slackbot.py
  • apps/ai/src/sops/__init__.py
  • apps/ai/src/sops/base.py
  • apps/ai/src/sops/registry.py
  • apps/ai/src/worker.py
  • apps/ai/src/workflows/__init__.py
  • apps/ai/test_verification.py
  • apps/ai/tests/agent_test_server.py
  • apps/ai/tests/agentic/conftest.py
  • apps/ai/tests/agentic/test_agentic_ai.py
  • apps/ai/tests/agentic/test_real_agent_capabilities.py
  • apps/ai/tests/docker-compose.test.yml
  • apps/ai/tests/e2e/__init__.py
  • apps/ai/tests/e2e/conftest.py
  • apps/ai/tests/evals/__init__.py
  • apps/ai/tests/evals/datasets/__init__.py
  • apps/ai/tests/evals/run_evals.py
  • apps/ai/tests/integration/conftest.py
  • apps/ai/tests/integration/test_mission_state.py
  • apps/ai/tests/integration/test_mockoon_endpoints.py
  • apps/ai/tests/mock_slack_server.py
  • apps/ai/tests/mocks/trackguard-mocks.json
  • apps/ai/tests/test_dspy_evals.py
  • apps/ai/tests/test_event_bus.py
  • apps/ai/tests/test_event_dictionary.py
  • apps/ai/tests/test_llm_eval.py
  • apps/ai/tests/test_llm_evals.py
  • apps/ai/tests/test_llm_responses.py
  • apps/ai/tests/unit/test_agentic_comprehensive.py
  • apps/ai/tests/unit/test_delivery_service.py
  • apps/ai/tests/unit/test_integrations.py
  • apps/ai/tests/unit/test_redpanda_bus.py
  • apps/ai/tests/unit/test_session_layer.py
  • apps/ai/tests/unit/test_workflow_service.py
  • apps/ai/tests/unit/test_workflows.py
  • apps/core/cmd/server/main.go
  • apps/core/cmd/worker/main.go
  • apps/core/internal/api/handlers.go
  • apps/core/internal/api/telegram.go
  • apps/core/internal/api/telegram_mock_test.go
  • apps/core/internal/api/telegram_test.go
  • apps/core/internal/db/migration_002_test.go
  • apps/core/internal/db/migrations/001_sarthi_sop_runtime.sql
  • apps/core/internal/db/migrations/002_sarthi_v1.sql
  • apps/core/internal/db/schema/internal_ops.sql
  • apps/core/internal/events/envelope.go
  • apps/core/internal/events/normalizer.go
  • apps/core/internal/redpanda/client.go
  • apps/core/internal/redpanda/producer_test.go
  • apps/core/internal/web/handler.go
  • apps/core/internal/workflow/business_os_workflow.go
  • apps/core/internal/workflow/business_os_workflow_test.go
  • apps/core/internal/workflow/workflow_router.go
  • apps/core/internal/workflow/workflow_router_test.go
  • apps/core/migrations/008_sarthi_internal_ops.sql
  • docs/langfuse-trace-reading.md
  • test_verification.py

📝 Walkthrough

Walkthrough

This PR adds an Opencode Graphify plugin, refactors AI LLM and database configuration, renames several exported AI types, switches many runtime namespaces from sarthi to trackguard, and updates documentation, fixtures, and tests to match those code changes.

Changes

TrackGuard platform transition

Layer / File(s) Summary
Tooling and operator docs
.opencode/*, .gitignore, README.md, docs/langfuse-trace-reading.md, apps/ai/.deepeval/*
Adds the Graphify Opencode plugin and ignored output directory, updates the main README terminology and architecture labels, and adds a Langfuse trace-reading procedure document.
AI contract and naming updates
apps/ai/src/agents/anomaly/*, apps/ai/src/agents/cofounder/*, apps/ai/src/activities/synthesize_weekly_brief.py, apps/ai/src/agents/{bi,ops,...}/*, apps/ai/tests/agent_test_server.py
Renames exported anomaly and council types and classes, updates related return annotations and re-exports, and rebrands prompt text and Slack-facing AI messaging.
LLM client and shared config plumbing
apps/ai/src/config/{llm,database,__init__}.py, apps/ai/src/{db,orchestration,registry,scheduler}/*, apps/ai/tests/agentic/*, apps/ai/tests/unit/test_agentic_comprehensive.py
Moves chat completion calls to the OpenAI SDK, adds sync and async streaming helpers, centralizes request kwargs and client reset behavior, consolidates database URL access, and updates fixtures and tests around that client layer.
Runtime namespace and routing rewiring
apps/ai/src/{events,services,session,slackbot,worker,memory}/*, apps/core/cmd/*, apps/core/internal/{api,redpanda,workflow}/*, *test_verification.py
Switches queues, topics, stream keys, channels, collection names, consumer groups, workflow signal names, and router names from sarthi to trackguard across Python and Go runtime paths.
Branding sweep and fixture alignment
apps/ai/src/{integrations,schemas,sops,...}/*, apps/ai/tests/**/*, apps/core/internal/**/*, apps/core/migrations/*
Updates remaining docstrings, comments, mock data, database/test defaults, container names, example strings, and topic expectations to TrackGuard naming.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐇 I hopped through queues and topics bright,
from sarthi paths to TrackGuard light.
New prompts now stream, new routers guide,
with tests in tidy hops beside.
A graph says, “Read me!” soft and clear—
the burrow's wiring all is here.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/startup-guardian

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request completes the rebranding of the project from 'Sarthi' to 'TrackGuard' across the entire codebase, including documentation, configuration files, and test suites. It also refactors the LLM client infrastructure in 'apps/ai/src/config/llm.py' to use the OpenAI SDK, introducing support for streaming completions. Additionally, the PR adds a new OpenCode plugin for knowledge graph reminders and updates various infrastructure configurations, such as Kafka topics and database connection strings. The review identified several critical issues, including a task queue name mismatch between the Go service and Python worker, an incorrect implementation of async streaming, potential resource leaks in the client reset logic, and suggestions for improving test environment isolation and documentation consistency.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

}

_, err := h.temporalClient.StartWorkflow(c.Context(), workflowID, "sarthi-queue", input)
_, err := h.temporalClient.StartWorkflow(c.Context(), workflowID, "trackguard-queue", input)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There is an inconsistency in the Temporal task queue name. This Go code hardcodes the queue name as "trackguard-queue", while the Python worker is configured to listen on "TRACKGUARD-MAIN-QUEUE" (from apps/ai/src/worker.py). This mismatch will prevent the Python worker from picking up workflows started by this Go service. These names must be identical. It would also be best practice to make the queue name configurable rather than hardcoding it.

Suggested change
_, err := h.temporalClient.StartWorkflow(c.Context(), workflowID, "trackguard-queue", input)
_, err := h.temporalClient.StartWorkflow(c.Context(), workflowID, "TRACKGUARD-MAIN-QUEUE", input)

Comment thread apps/ai/src/config/llm.py
Comment on lines +174 to +203
async def chat_completion_stream_async(
messages: list[dict[str, str]],
model: str | None = None,
max_tokens: int = 500,
temperature: float = 0.0,
json_mode: bool = False,
**extra: Any,
) -> AsyncGenerator[str, None]:
"""Async stream chat completion chunks as they arrive.

Yields content delta strings. Use for async UI updates or
token-by-token processing in async contexts.

Usage:
async for chunk in chat_completion_stream_async(messages=[...]):
print(chunk, end="", flush=True)
"""
global _async_client
if _async_client is None:
base_url, api_key = _provider_config()
_async_client = AsyncOpenAI(
base_url=base_url,
api_key=api_key,
timeout=60.0,
)
kwargs = _build_kwargs(messages, model, max_tokens, temperature, json_mode, **extra)
async with _async_client.chat.completions.stream(**kwargs) as stream:
async for event in stream:
if event.type == "content.delta" and event.delta:
yield event.delta

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The implementation of chat_completion_stream_async appears incorrect for the openai Python SDK. The use of _async_client.chat.completions.stream() and iterating over event objects with a .type attribute does not match the openai library's API for streaming. This will likely cause a runtime error.

The implementation should be similar to the synchronous chat_completion_stream function, using await _async_client.chat.completions.create(stream=True) and iterating through the resulting ChatCompletionChunk objects.

async def chat_completion_stream_async(
    messages: list[dict[str, str]],
    model: str | None = None,
    max_tokens: int = 500,
    temperature: float = 0.0,
    json_mode: bool = False,
    **extra: Any,
) -> AsyncGenerator[str, None]:
    """Async stream chat completion chunks as they arrive.

    Yields content delta strings. Use for async UI updates or
    token-by-token processing in async contexts.

    Usage:
        async for chunk in chat_completion_stream_async(messages=[...]):
            print(chunk, end="", flush=True)
    """
    global _async_client
    if _async_client is None:
        base_url, api_key = _provider_config()
        _async_client = AsyncOpenAI(
            base_url=base_url,
            api_key=api_key,
            timeout=60.0,
        )
    kwargs = _build_kwargs(messages, model, max_tokens, temperature, json_mode, **extra)
    stream = await _async_client.chat.completions.create(**kwargs, stream=True)
    async for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            yield chunk.choices[0].delta.content

Comment on lines +15 to +17
output.args.command =
'echo "[graphify] Knowledge graph available. Read graphify-out/GRAPH_REPORT.md for god nodes and architecture context before searching files." && ' +
output.args.command;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The string concatenation for building the command can be error-prone and hard to read. Using a template literal would make the code cleaner and safer, especially if more complex commands are built in the future.

Suggested change
output.args.command =
'echo "[graphify] Knowledge graph available. Read graphify-out/GRAPH_REPORT.md for god nodes and architecture context before searching files." && ' +
output.args.command;
output.args.command = `echo "[graphify] Knowledge graph available. Read graphify-out/GRAPH_REPORT.md for god nodes and architecture context before searching files." && ${output.args.command}`;

Comment on lines +1 to +4
DEEPEVAL_ID=73dfc665-6e63-423d-9844-b5787b1991d8
DEEPEVAL_STATUS=old
DEEPEVAL_LAST_FEATURE=evaluation
DEEPEVAL_EVALUATION_STATUS=old

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This telemetry file appears to be auto-generated by a tool and likely shouldn't be checked into source control. Consider removing this file and adding the .deepeval/ directory to your .gitignore file to prevent committing such files in the future.

Comment thread apps/ai/src/config/llm.py
Comment on lines 244 to +250
def reset_client() -> None:
"""Reset cached client."""
global _client
"""Reset cached clients."""
global _client, _async_client
if _client:
_client.close()
_client = None
_async_client = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The reset_client function doesn't properly close the _async_client, which can lead to resource leaks. The AsyncOpenAI client's close() method is a coroutine and must be awaited. Since this function is synchronous, you can use asyncio.run() to execute the async close operation.

Suggested change
def reset_client() -> None:
"""Reset cached client."""
global _client
"""Reset cached clients."""
global _client, _async_client
if _client:
_client.close()
_client = None
_async_client = None
def reset_client() -> None:
"""Reset cached clients."""
import asyncio
global _client, _async_client
if _client:
_client.close()
if _async_client:
asyncio.run(_async_client.close())
_client = None
_async_client = None

Comment on lines 65 to +80
def _set_env():
"""Set environment variables for tests."""
"""Set environment variables for tests, restoring originals on teardown."""
originals = {
"GROQ_API_KEY": os.environ.get("GROQ_API_KEY"),
"GROQ_CHAT_MODEL": os.environ.get("GROQ_CHAT_MODEL"),
"OPENROUTER_EMBED_MODEL": os.environ.get("OPENROUTER_EMBED_MODEL"),
}
os.environ.setdefault("GROQ_API_KEY", "gsk_test_key")
os.environ.setdefault("GROQ_CHAT_MODEL", "qwen/qwen3-32b")
os.environ.setdefault("OPENROUTER_EMBED_MODEL", "nvidia/llama-nemotron-embed-vl-1b-v2:free")
yield
for key, value in originals.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _set_env fixture modifies global state (os.environ) which can affect other tests if not properly isolated. While the teardown logic is a good step, a more robust approach is to use monkeypatch.setenv which is managed by pytest and ensures proper cleanup without manual teardown code.

@pytest.fixture(autouse=True)
def _set_env(monkeypatch):
    """Set environment variables for tests."""
    monkeypatch.setenv("GROQ_API_KEY", "gsk_test_key")
    monkeypatch.setenv("GROQ_CHAT_MODEL", "qwen/qwen3-32b")
    monkeypatch.setenv("OPENROUTER_EMBED_MODEL", "nvidia/llama-nemotron-embed-vl-1b-v2:free")

- Self-hosted: `http://langfuse.local`
- Cloud: `https://cloud.langfuse.com`
2. Filter by:
- **Trace name:** `sarthi-agent-run`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The trace name sarthi-agent-run seems to be a leftover from before the refactoring. For consistency with the project's renaming to TrackGuard, this should probably be trackguard-agent-run.

Suggested change
- **Trace name:** `sarthi-agent-run`
- **Trace name:** `trackguard-agent-run`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant