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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to the TypeScript package will be documented in this file.

## [0.28.1] - 2026-06-10

### Fixed

- **A retrieve call with `semantic`/`rerank` no longer kills the MCP server when the optional `@huggingface/transformers` package is missing**: the rejection previously escaped the stdio serve loop unhandled, terminating the process mid-call so agents saw an infinite spinner instead of an error. Retrieve failures now return an MCP `isError` tool result the agent can read and react to, and the serve loop is hardened so no handler rejection can tear down the server.
- **A project-local `npm install @huggingface/transformers` now actually enables semantic/rerank**: npx-launched and globally installed servers resolve the optional package from the project root (derived from the graph path) in addition to madar's own installation, and the install hint in the error message now points at instructions that work for those installs.
- **Failed semantic model loads no longer poison the pipeline cache**: a rejected load is evicted, so installing the package and retrying succeeds without restarting the server.

### Added

- **Semantic/rerank capability gating in the retrieve tool schema**: `tools/list` omits the `semantic`, `semantic_model`, `rerank`, and `rerank_model` fields when the optional package is not resolvable, so agents never request a capability the machine lacks.
- **`madar doctor` now reports semantic/rerank availability** with the exact enable command, without affecting overall health status.
- **Semantic model loads are bounded by a timeout** (`MADAR_MODEL_LOAD_TIMEOUT_MS`, default 120s) so a stalled first-use model download cannot block the serial stdio request loop indefinitely.

## [0.28.0] - 2026-06-10

### Added
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ It does not record prompt text, answer text, source paths, source content, or re

## What's New

Current version: `0.28.0`.
Current version: `0.28.1`.

This release promotes the public benchmark work to a proof-backed stable release: six public TypeScript `explain-runtime` legacy rows now have checked-in `full_win` receipts, strict runtime-proof gates, direct-evidence answer checks, scoped benchmark roots, and share-safe reports. It also includes retrieval and extraction improvements for runtime handoffs, source-visible framework flows, and benchmark reproducibility.
`0.28.1` is a stability hotfix: a `retrieve` call with `semantic`/`rerank` no longer crashes the MCP server when the optional `@huggingface/transformers` package is missing, a project-local install of that package now enables semantic/rerank under npx-launched or global installs, and the retrieve tool schema only advertises semantic fields when the capability is actually available.

Read the full notes in the [0.28.0 changelog](https://github.com/mohanagy/madar/blob/main/CHANGELOG.md#0280---2026-06-10).
`0.28.0` promoted the public benchmark work to a proof-backed stable release: six public TypeScript `explain-runtime` legacy rows now have checked-in `full_win` receipts, strict runtime-proof gates, direct-evidence answer checks, scoped benchmark roots, and share-safe reports. It also includes retrieval and extraction improvements for runtime handoffs, source-visible framework flows, and benchmark reproducibility.

Read the full notes in the [0.28.1 changelog](https://github.com/mohanagy/madar/blob/main/CHANGELOG.md#0281---2026-06-10).

## Docs

Expand Down
4 changes: 2 additions & 2 deletions docs/mcp-registry/server.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
"source": "github",
"url": "https://github.com/mohanagy/madar"
},
"version": "0.28.0",
"version": "0.28.1",
"packages": [
{
"registryType": "npm",
"registryBaseUrl": "https://registry.npmjs.org",
"identifier": "@lubab/madar",
"version": "0.28.0",
"version": "0.28.1",
"runtimeHint": "npx",
"transport": {
"type": "stdio"
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lubab/madar",
"version": "0.28.0",
"version": "0.28.1",
"description": "Stop AI coding agents from rediscovering large TypeScript/Node repos. Madar compiles task-aware local context packs from what runs for this task.",
"license": "MIT",
"author": "mohanagy",
Expand Down
16 changes: 16 additions & 0 deletions src/infrastructure/doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
resolveOpencodeConfigPath,
} from './install.js'
import { analyzeGraphContextFreshness, graphFreshnessStatusLabel, type GraphContextFreshnessStatus } from '../runtime/freshness.js'
import { isSemanticRuntimeAvailable } from '../runtime/semantic.js'
import { findPackageRoot, readPackageVersion } from '../shared/package-metadata.js'

const MADAR_SECTION_MARKER = '## madar'
Expand Down Expand Up @@ -47,10 +48,18 @@ export interface DoctorReport {
graph: GraphCheck
agents: AgentCheck[]
mcpChecks: McpCheck[]
/** Availability of the optional semantic/rerank runtime. Informational
* only — never part of the `healthy` computation. */
semantic: SemanticCheck
nextCommands: string[]
healthy: boolean
}

interface SemanticCheck {
available: boolean
detail: string
}

interface JsonObject {
[key: string]: unknown
}
Expand Down Expand Up @@ -526,11 +535,17 @@ export function buildDoctorReport(options: DoctorCommandOptions = {}): DoctorRep

const mcpChecks = [claudeMcp, cursorMcp, copilotMcp]

const semanticAvailable = isSemanticRuntimeAvailable(projectDir)
const semantic: SemanticCheck = semanticAvailable
? { available: true, detail: 'optional @huggingface/transformers resolved' }
: { available: false, detail: 'optional — run `npm install @huggingface/transformers` in this project to enable semantic/rerank' }

const partialReport = {
packageVersion,
graph,
agents,
mcpChecks,
semantic,
}
const nextCommands = computeNextCommands(partialReport)
const healthy = graph.exists && graph.freshness === 'fresh' && agents.every((agent) => agent.status === 'configured') && mcpChecks.every((check) => check.status === 'ok')
Expand Down Expand Up @@ -578,6 +593,7 @@ export function runDoctorCommand(options: DoctorCommandOptions = {}): string {
for (const check of report.mcpChecks) {
lines.push(` - ${check.label}: ${check.status} (${check.configPath}; ${check.reason})`)
}
lines.push(`- semantic/rerank: ${report.semantic.available ? 'available' : 'unavailable'} (${report.semantic.detail})`)

if (report.nextCommands.length === 0) {
lines.push('- next commands: none')
Expand Down
13 changes: 11 additions & 2 deletions src/runtime/retrieve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ export interface RetrieveOptions {
semanticModel?: string
rerank?: boolean
rerankerModel?: string
/** Project root used to resolve the optional transformers package when the
* server itself runs from elsewhere (npx cache, global install). */
projectRoot?: string
/** #75 manual override for the retrieval gate. When set (0-5), the gate
* bypasses heuristic classification and emits a decision with reason
* 'manual override' at the supplied level. Caller-side surface for the
Expand Down Expand Up @@ -6369,7 +6372,10 @@ export async function retrieveContextAsync(graph: KnowledgeGraph, options: Retri
semanticScores = await rankCandidatesBySemanticSimilarity(
options.question,
[...candidatesById.values()].map((node) => ({ id: node.id, text: semanticTextForNode(node) })),
options.semanticModel ? { model: options.semanticModel } : {},
{
...(options.semanticModel ? { model: options.semanticModel } : {}),
...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),
},
)
}

Expand Down Expand Up @@ -6398,7 +6404,10 @@ export async function retrieveContextAsync(graph: KnowledgeGraph, options: Retri
rerankScores = await rerankCandidatesWithCrossEncoder(
options.question,
candidatePool.map((node) => ({ id: node.id, text: semanticTextForNode(node) })),
options.rerankerModel ? { model: options.rerankerModel } : {},
{
...(options.rerankerModel ? { model: options.rerankerModel } : {}),
...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),
},
)
}

Expand Down
Loading
Loading