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
25 changes: 25 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,31 @@ Say "setup omc" or run `/oh-my-claudecode:omc-setup`.

<!-- User Overrides — NOT managed by OMC, persists across updates -->

## Mandatory Codebase Discovery Preflight

For any task that requires finding files, symbols, classes, modules, call chains,
cross-file relationships, or unknown implementation locations, the first discovery
step MUST be Codebase Memory.

Required sequence:

1. If Codebase Memory tools are not currently visible, resolve them first:
`ToolSearch("select:mcp__codebase-memory__index_status")`.
2. Call `mcp__codebase-memory__index_status`.
3. If the project is indexed, use:
- `mcp__codebase-memory__search_graph` for symbols/classes/modules/files;
- `mcp__codebase-memory__trace_path` for call chains/dependencies;
- `mcp__codebase-memory__get_architecture` for module structure;
- `mcp__codebase-memory__get_code_snippet` for targeted code.
4. If the project is not indexed or path is ambiguous, use
`mcp__codebase-memory__list_projects` and/or `mcp__codebase-memory__index_repository`.
5. Only if Codebase Memory is unavailable or fails after retry, fall back to
Glob/Grep/Read/LSP.

Do not start first-pass codebase discovery with `git status`, Bash, Glob, Grep,
or Read. `git status` is allowed for worktree safety before edits/staging, but it
does not satisfy discovery preflight and must not replace Codebase Memory.

## Specific Overrides

- "Delegate" → always route via `~/.claude/rules/delegation.md` routing table; never decide ad-hoc.
Expand Down
11 changes: 10 additions & 1 deletion .claude/agents/architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ You are Architect. Analyze code, diagnose bugs, and provide actionable architect

## Investigation Protocol

1) Gather context first (MANDATORY): Glob project structure, Grep/Read relevant implementations, check manifests, find tests. Execute in parallel.
1) Gather context first (MANDATORY):
for non-trivial codebase questions, run Codebase Memory preflight before Glob/Grep/Read:
`index_status` → `search_graph` / `trace_path` / `get_architecture` → targeted Read/LSP.
Use Glob/Grep only as fallback or precision confirmation.
2) For debugging: Read error messages completely. Check recent changes (git log/blame). Find working examples. Compare broken vs working.
3) Form hypothesis and document BEFORE looking deeper.
4) Cross-reference hypothesis against actual code. Cite file:line for every claim.
Expand All @@ -35,6 +38,12 @@ You are Architect. Analyze code, diagnose bugs, and provide actionable architect

## Tool Usage

- **Codebase Memory — primary for codebase discovery**:
`mcp__codebase-memory__index_status`,
`mcp__codebase-memory__search_graph`,
`mcp__codebase-memory__trace_path`,
`mcp__codebase-memory__get_architecture`,
`mcp__codebase-memory__get_code_snippet`
- **Core**: Glob, Grep, Read, Bash (git blame/log)
- **Context-mode**: ctx_search, ctx_execute, ctx_execute_file, ctx_batch_execute, ctx_fetch_and_index
- **LSP**: lsp_diagnostics, lsp_diagnostics_directory, lsp_hover, lsp_goto_definition, lsp_find_references, lsp_document_symbols, lsp_workspace_symbols, lsp_code_actions, lsp_rename, lsp_servers
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ You are Debugger. Trace bugs to their root cause and recommend minimal fixes. Ge

## Tool Usage

- **Codebase Memory**: use `index_status` → `search_graph` / `trace_path` / `get_code_snippet` before Grep/Read when tracing call chains or cross-file dependencies in unfamiliar code.
- **Core**: Read, Grep, Bash (git blame/log, build commands), Edit (minimal fixes only)
- **Context-mode**: ctx_search, ctx_execute, ctx_execute_file, ctx_batch_execute, ctx_fetch_and_index
- **LSP**: lsp_diagnostics, lsp_diagnostics_directory (preferred over CLI for TypeScript), lsp_hover, lsp_goto_definition, lsp_find_references, lsp_document_symbols, lsp_workspace_symbols
Expand Down
26 changes: 25 additions & 1 deletion .claude/agents/explore.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,28 @@ disallowedTools: Write, Edit

You are Explorer. Find files, code patterns, and relationships in the codebase and return actionable results. Answer "where is X?", "which files contain Y?", "how does Z connect to W?" Not responsible for modifying code, implementing features, or external documentation search. Route external docs/literature requests to document-specialist.

## Codebase Discovery Protocol

For non-trivial repository investigation, architecture questions, cross-file relationships,
call chains, refactors, or unknown implementation locations:

1. First check `mcp__codebase-memory__index_status`.
2. If the project is not indexed, stale, or path is ambiguous, use
`mcp__codebase-memory__list_projects` and/or `mcp__codebase-memory__index_repository`.
3. Use `mcp__codebase-memory__search_graph` for symbols, classes, modules, and files.
4. Use `mcp__codebase-memory__trace_path` for call chains and dependency flow.
5. Use `mcp__codebase-memory__get_code_snippet` for targeted code snippets.
6. Use Glob/Grep/Read only after Codebase Memory, or as fallback if Codebase Memory is unavailable.

Do not start non-trivial codebase discovery with Glob or Grep.

## Constraints

- Read-only: cannot create, modify, or delete files
- Always use absolute paths (starting with /)
- Return results as message text, never store in files
- For symbol usage lookups requiring lsp_find_references, escalate to explore-high
- Launch 3+ parallel searches on first action, broad-to-narrow strategy
- For non-trivial codebase discovery, first run Codebase Memory preflight; then launch parallel searches if additional confirmation is needed.
- Cross-validate across multiple tools (Grep vs Glob vs ast_grep_search)
- Cap exploratory depth: stop after 2 rounds of diminishing returns
- Medium effort: 3-5 parallel searches; thorough: 5-10; quick lookups: 1-2
Expand All @@ -28,6 +43,15 @@ You are Explorer. Find files, code patterns, and relationships in the codebase a

## Tools

- **Codebase Memory — primary for codebase discovery**:
`mcp__codebase-memory__index_status`,
`mcp__codebase-memory__list_projects`,
`mcp__codebase-memory__index_repository`,
`mcp__codebase-memory__search_graph`,
`mcp__codebase-memory__trace_path`,
`mcp__codebase-memory__get_code_snippet`,
`mcp__codebase-memory__get_architecture`,
`mcp__codebase-memory__search_code`
- **Core**: Glob (file structure), Grep (text patterns), Read (targeted with offset/limit)
- **Context-mode**: ctx_search, ctx_batch_execute, ctx_execute, ctx_execute_file, ctx_fetch_and_index
- **LSP**: lsp_document_symbols, lsp_workspace_symbols, lsp_hover, lsp_goto_definition, lsp_find_references, lsp_diagnostics
Expand Down
1 change: 1 addition & 0 deletions .claude/agents/tracer.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ You are not responsible for implementation, generic code review, generic summari
- [Confirmation Bias](software-laws.md#confirmation-bias): actively seek disconfirming evidence for the leading hypothesis. Collect evidence against, not just for.

## Tools
**Codebase Memory**: use `index_status` → `search_graph` / `trace_path` / `get_code_snippet` before Grep/Read when tracing call chains or cross-file dependencies in unfamiliar code.
**Core**: Read, Grep, Glob, Bash (focused evidence gathering)
**Context-mode**: ctx_search, ctx_execute, ctx_batch_execute, ctx_execute_file, ctx_fetch_and_index
**LSP**: lsp_diagnostics, lsp_diagnostics_directory, lsp_hover, lsp_goto_definition, lsp_find_references, lsp_document_symbols
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/delegation.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ TaskCreate = conversation tracking only, NOT delegation.

| Category | Agents | Primary | Fallback |
|----------|--------|---------|----------|
| Analysis | explore, analyst, tracer, scientist | ctx_*, python_repl, Grep/Glob, session_search | Bash, DDG |
| Analysis / Architecture | explore, analyst, tracer, architect, scientist | Codebase Memory (`mcp__codebase-memory__*`), ctx_*, python_repl, Grep/Glob, session_search | Bash, DDG |
| Implementation | executor, verifier, debugger, test-engineer | Edit/Write, LSP, ast_grep, ctx_execute, Bash (tests) | Bash, Grep, python_repl |
| Review & Security | code-reviewer, security-reviewer | LSP, ast_grep_search, Grep, ctx_execute_file | Read, Bash |
| Specialist | document-specialist, architect, writer, git-master | context7, GitHub, LSP, ctx_execute_file, Read | DDG, Fetch, gh CLI |
Expand Down
13 changes: 13 additions & 0 deletions .claude/rules/tool-priority.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ LSP, OMC State/Notepad, and AST tools listed as `lsp_*`, `state_*`, `notepad_*`,

## Codebase Memory Usage Policy

This policy applies to the orchestrator and to every subagent that performs codebase discovery.
Subagents must not assume the orchestrator has already completed discovery unless the prompt
explicitly provides the relevant Codebase Memory results, qualified names, or file paths.

If the orchestrator delegates discovery to a subagent, the delegation prompt must either:
1. include explicit Codebase Memory preflight instructions, or
2. provide already verified Codebase Memory results and tell the subagent to continue from them.

The first observable discovery tool call must be Codebase Memory, not Bash, Glob,
Grep, Read, or LSP. Planning text is not enough: if the reasoning says Codebase
Memory will be used, the next discovery action must actually call Codebase Memory
or explicitly report that the tool is unavailable.

Use Codebase Memory before Grep/Read/LSP when the task asks to:
- find where behavior is implemented;
- understand module architecture;
Expand Down
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ itself rather than on generic product or application architecture.
- Use Conventional Commits: `type(scope): summary`.
- Commit headers must be in English and include a descriptive body.

## Codebase Discovery

For non-trivial codebase investigation, architecture questions, cross-file edits,
refactors, call chains, or unknown implementation locations, use Codebase Memory
before Grep/Glob/Read/LSP.

Preferred sequence:
`index_status` → `search_graph` / `trace_path` / `get_code_snippet` → targeted Read/LSP.

Grep/Glob are fallback or precision-confirmation tools, not first-pass architecture discovery.

## Public Entry Headers

Use the project umbrella headers instead of recreating include order manually:
Expand Down
93 changes: 57 additions & 36 deletions include/logit_cpp/logit/loggers/OtlpHttpLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ILogger.hpp"
#include "otlp/OtlpJsonFormatConfig.hpp"
#include "otlp/OtlpJsonSerializer.hpp"
#include "otlp/OtlpPayloadSplitter.hpp"

#ifndef KURLYK_WEBSOCKET_SUPPORT
# define KURLYK_WEBSOCKET_SUPPORT 0
Expand Down Expand Up @@ -63,6 +64,7 @@ namespace logit {
int request_timeout_sec = 3;
long retry_attempts = 2;
long retry_delay_ms = 250;
std::size_t max_payload_bytes = 1024 * 1024;
bool drop_on_overflow = true;
bool async = true;
bool cancel_on_shutdown = false;
Expand Down Expand Up @@ -116,10 +118,6 @@ namespace logit {
if (!m_config.async) {
std::vector<OtlpLogItem> batch;
batch.push_back(item);
{
std::lock_guard<std::mutex> lock(m_state->mutex);
++m_state->http_in_flight;
}
submit_batch_async(batch);
try {
m_client.wait_requests();
Expand Down Expand Up @@ -302,7 +300,6 @@ namespace logit {
}

m_state->space_cv.notify_all();
++m_state->http_in_flight;
}

if (!batch.empty()) {
Expand All @@ -311,46 +308,70 @@ namespace logit {
}
}

/// \brief Submits one batch asynchronously to the configured OTLP endpoint.
/// \brief Submits one batch asynchronously, splitting into payload chunks.
/// \param batch Batch to export.
void submit_batch_async(const std::vector<OtlpLogItem>& batch) {
const std::string payload = build_otlp_logs_json_payload(batch, m_config.format);
auto chunks = build_otlp_logs_json_payload_chunks(
batch, m_config.format, m_config.max_payload_bytes);

if (chunks.empty()) {
return;
}

kurlyk::Headers headers;
headers.emplace("Content-Type", "application/json");

auto weak_state = std::weak_ptr<OtlpHttpLoggerState>(m_state);
bool submitted = false;

try {
submitted = m_client.post(
m_config.path, {}, headers, payload,
[weak_state](kurlyk::HttpResponsePtr response) {
auto state = weak_state.lock();
if (!state) {
return;
}

std::lock_guard<std::mutex> lock(state->mutex);
if (!response || response->status_code < 200 || response->status_code >= 300) {
state->failed_exports.fetch_add(1);
}
if (state->http_in_flight > 0) {
--state->http_in_flight;
}
state->cv.notify_all();

for (auto& chunk : chunks) {
{
std::unique_lock<std::mutex> lock(m_state->mutex);
m_state->cv.wait(lock, [this]() {
return (m_state->stopping && m_config.cancel_on_shutdown) ||
m_state->http_in_flight < m_config.max_in_flight_requests;
});
} catch (...) {
submitted = false;
}

if (!submitted) {
auto state = m_state;
std::lock_guard<std::mutex> lock(state->mutex);
state->failed_exports.fetch_add(1);
if (state->http_in_flight > 0) {
--state->http_in_flight;
if (m_state->stopping && m_config.cancel_on_shutdown) {
m_state->failed_exports.fetch_add(1);
continue;
}

++m_state->http_in_flight;
}

bool submitted = false;

try {
submitted = m_client.post(
m_config.path, {}, headers, std::move(chunk),
[weak_state](kurlyk::HttpResponsePtr response) {
auto state = weak_state.lock();
if (!state) {
return;
}

std::lock_guard<std::mutex> lock(state->mutex);
if (!response || response->status_code < 200 || response->status_code >= 300) {
state->failed_exports.fetch_add(1);
}
if (state->http_in_flight > 0) {
--state->http_in_flight;
}
state->cv.notify_all();
});
} catch (...) {
submitted = false;
}

if (!submitted) {
auto state = m_state;
std::lock_guard<std::mutex> lock(state->mutex);
state->failed_exports.fetch_add(1);
if (state->http_in_flight > 0) {
--state->http_in_flight;
}
state->cv.notify_all();
}
state->cv.notify_all();
}
}

Expand Down
33 changes: 21 additions & 12 deletions include/logit_cpp/logit/loggers/OtlpPayloadLogger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
#include "ILogger.hpp"
#include "otlp/OtlpJsonFormatConfig.hpp"
#include "otlp/OtlpJsonSerializer.hpp"
#include "otlp/OtlpPayloadSplitter.hpp"

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <deque>
#include <functional>
#include <limits>
#include <mutex>
#include <string>
Expand All @@ -38,6 +40,7 @@ namespace logit {
OtlpJsonFormatConfig format;
std::function<void(std::string)> on_payload;
bool async = true;
std::size_t max_payload_bytes = 1024 * 1024;
std::size_t max_batch_size = 256;
std::size_t max_queue_size = 1024;
bool drop_on_overflow = true;
Expand Down Expand Up @@ -88,13 +91,16 @@ namespace logit {
}
std::vector<OtlpLogItem> batch;
batch.push_back(item);
std::string payload = build_otlp_logs_json_payload(batch, m_config.format);
try {
if (m_config.on_payload) {
m_config.on_payload(std::move(payload));
auto chunks = build_otlp_logs_json_payload_chunks(
batch, m_config.format, m_config.max_payload_bytes);
if (m_config.on_payload) {
for (auto& chunk : chunks) {
try {
m_config.on_payload(std::move(chunk));
} catch (...) {
++m_failed_exports;
}
}
} catch (...) {
++m_failed_exports;
}
return;
}
Expand Down Expand Up @@ -269,13 +275,16 @@ namespace logit {
}

if (!batch.empty()) {
std::string payload = build_otlp_logs_json_payload(batch, m_config.format);
try {
if (m_config.on_payload) {
m_config.on_payload(std::move(payload));
auto chunks = build_otlp_logs_json_payload_chunks(
batch, m_config.format, m_config.max_payload_bytes);
if (m_config.on_payload) {
for (auto& chunk : chunks) {
try {
m_config.on_payload(std::move(chunk));
} catch (...) {
++m_failed_exports;
}
}
} catch (...) {
++m_failed_exports;
}
}

Expand Down
Loading
Loading