# SigMap — AGENTS.md

Instructions for Codex-style agents working in this repository.

## Append Strategy (Required)

When writing generated signature content, never overwrite human-written notes above the marker.

Use this marker block for all appendable context files:

```
## Tools

<!-- sigmap-tools -->

```json
[
  {
    "name": "sigmap_ask",
    "description": "Rank source files by relevance to a natural-language query. Run before exploring the codebase.",
    "command": "sigmap ask \"$QUERY\""
  },
  {
    "name": "sigmap_validate",
    "description": "Validate SigMap config and measure context coverage. Run after changing config or source dirs.",
    "command": "sigmap validate"
  },
  {
    "name": "sigmap_judge",
    "description": "Score an LLM response for groundedness against source context. Use to verify answer quality.",
    "command": "sigmap judge --response \"$RESPONSE\" --context \"$CONTEXT\""
  },
  {
    "name": "sigmap_query",
    "description": "Rank all files by relevance using TF-IDF and write a focused mini-context.",
    "command": "sigmap --query \"$QUERY\" --context"
  },
  {
    "name": "sigmap_weights",
    "description": "Show learned file-ranking multipliers accumulated from past sessions.",
    "command": "sigmap weights"
  }
]
```

## Auto-generated signatures
<!-- Updated by gen-context.js -->
# Code signatures

## SigMap commands

| When | Command |
|------|---------|
| Before answering a question | `sigmap ask "<your question>"` |
| After code changes | `sigmap validate` |
| To query by topic | `sigmap --query "<topic>"` |

Always run `sigmap ask` or `sigmap --query` before searching for files relevant to a task.
## deps
```
src/extractors/python_ast.py ← ast
```

## packages

### packages/adapters/llm-full.js
```
module.exports = { name: 'llm-full', format, outputPath, write }
function outputPath(cwd)
function format(context, opts)
function write(context, cwd, opts)
```

### packages/core/README.md
```
h1 sigmap-core
h2 Installation
h2 Quick start
h2 API reference
h3 `extract(src, language)` → `string[]`
h3 `rank(query, sigIndex, opts?)` → `Result[]`
h3 `buildSigIndex(cwd)` → `Map<string, string[]>`
h3 `scan(sigs, filePath)` → `{ safe: string[], redacted: boolean }`
h3 `score(cwd)` → `HealthResult`
h2 Migration from v2.3 and earlier
h2 v3.0 — Multi-Adapter Architecture (released)
h2 Zero dependencies
code-fence bash
code-fence plain
code-fence js
code-fence ---
```

### packages/adapters/copilot.js
```
module.exports = { name, format, outputPath, write }
function format(context, opts = {}) → string
function _confidenceMeta(opts)
function outputPath(cwd) → string
function write(context, cwd, opts = {})
```

### packages/adapters/cursor.js
```
module.exports = { name, format, outputPath }
function format(context, opts = {}) → string
function _confidenceMeta(opts)
function outputPath(cwd) → string
```

### packages/adapters/gemini.js
```
module.exports = { name, format, outputPath, write }
function format(context, opts = {}) → string
function outputPath(cwd) → string
function write(context, cwd, opts = {})
function _confidenceMeta(opts)
```

### packages/adapters/openai.js
```
module.exports = { name, format, outputPath }
function format(context, opts = {}) → string
function outputPath(cwd) → string
function _confidenceMeta(opts)
```

### packages/adapters/windsurf.js
```
module.exports = { name, format, outputPath }
function format(context, opts = {}) → string
function _confidenceMeta(opts)
function outputPath(cwd) → string
```

### packages/adapters/claude.js
```
module.exports = { name, format, outputPath, write }
function format(context, opts = {}) → string
function _confidenceMeta(opts)
function outputPath(cwd) → string
function write(context, cwd, opts = {})
```

### packages/adapters/codex.js
```
module.exports = { name, format, outputPath, write }
function format(context, opts = {}) → string
function outputPath(cwd) → string
function write(context, cwd, opts = {})
```

### packages/adapters/index.js
```
module.exports = { getAdapter, listAdapters, adapt, outputsToAdapters }
function getAdapter(name) → { name: string, format: F
function listAdapters() → string[]
function adapt(context, adapterName, opts = {}) → string
function outputsToAdapters(outputs) → string[]
```

### packages/adapters/willow.js
```
module.exports = { name, format, outputPath, write }
function format(context, opts = {}) → string
function outputPath(cwd) → string
function generateAtomId(filepath) → string
async function fetchWithTimeout(url, opts, timeoutMs) → Promise<Response>
async function postAtomWithRetry(atom, mcpUrl, timeoutMs, maxRetries) → Promise<boolean>
async function write(context, cwd, opts = {}) → Promise<void>
```

### packages/core/index.js
```
module.exports = { extract, rank, buildSigIndex, scan, score, adapt }
function _resolveExtractor(language)
function extract(src, language) → string[]
function rank(query, sigIndex, opts) → { file: string, score: nu
function buildSigIndex(cwd) → Map<string, string[]>
function scan(sigs, filePath) → { safe: string[], redacte
function score(cwd) → { * score: number, * grad
function adapt(context, adapterName, opts = {}) → string
```

## src

### src/extractors/python_dataclass.js
```
module.exports = { extract }
function extract(src) → string[]
```

### src/extractors/typescript_react.js
```
module.exports = { extract }
function extract(src) → string[]
```

### src/extractors/vue_sfc.js
```
module.exports = { extract }
function extract(src) → string[]
```

### src/extractors/generic.js
```
module.exports = { extract }
function extract(src)
```

### src/format/llm-txt.js
```
module.exports = { format, outputPath }
function outputPath(cwd)
function format(context, cwd, version)
```

### src/format/llms-txt.js
```
module.exports = { format, outputPath }
function outputPath(cwd)
function getShortCommit(cwd)
function detectVersion(cwd)
function format(context, cwd, writtenFiles, sigmapVersion)
```

### src/format/dashboard.js
```
module.exports = { generateDashboardHtml, renderHistoryCharts, computeExtractorCoverage, percentile, overBudgetStreak }
function toNumber(v)
function percentile(values, p)
function overBudgetStreak(entries)
function loadConfig(cwd)
function shouldExclude(rel, excludeSet)
function detectLanguage(filePath)
function walkFiles(dir, maxDepth, depth, out, excludeSet)
function computeExtractorCoverage(cwd)
function readBenchmarkTrend(cwd)
function lineChartSvg(values, title, ySuffix)
function barChartSvg(perLanguage)
function sparkline(values)
function buildDashboardData(cwd, health)
function generateDashboardHtml(cwd, health)
function renderHistoryCharts(cwd, health)
```

### src/judge/judge-engine.js
```
module.exports = { groundedness, judge }
function tokenize(text)
function groundedness(response, context)
function extractContextFiles(context, cwd)
function judge(response, context, opts = {})
```

### src/format/benchmark-report.js
```
module.exports = { loadBenchmarkReports, buildBenchmarkSummary, generateBenchmarkReportHtml, writeBenchmarkReport }
function escapeHtml(value)
function formatInt(value)
function formatCompact(value)
function formatPct(value, digits = 1)
function formatMaybePct(value, digits = 1)
function formatRatio(value, digits = 1)
function formatMoney(value)
function durationLabel(ms)
function maxOrZero(values)
function readJson(filePath)
function loadBenchmarkReports(cwd)
function buildRetrievalSummary(retrieval)
function buildBenchmarkSummary(reports, matrixSummary)
function renderCard(label, value, hint, tone)
function renderProgress(label, value, max, suffix)
function renderMatrixSection(matrix)
function renderTokenSection(token)
function renderRetrievalSection(retrieval)
function renderQualitySection(quality)
function renderTaskSection(task)
function generateBenchmarkReportHtml(reports, opts = {})
function writeBenchmarkReport(cwd, opts = {})
```

### src/analysis/coverage-score.js
```
module.exports = { coverageScore, CODE_EXTS }
function coverageScore(cwd, fileEntries, config)
function _walk(dir, excludeSet, out)
```

### src/cache/sig-cache.js
```
module.exports = { loadCache, saveCache, getChangedFiles, updateCacheEntries }
function cachePath(cwd)
function loadCache(cwd, currentVersion) → Map<string, { mtime: numb
function saveCache(cwd, currentVersion, cache)
function getChangedFiles(files, cache) → { changed: string[], unch
function updateCacheEntries(cache, extracted)
```

### src/mcp/handlers.js
```
module.exports = { readContext, searchSignatures, getMap, createCheckpoint, getRouting, explainFile, listModules, queryContext, getImpact }
function readContext(args, cwd)
function searchSignatures(args, cwd)
function getMap(args, cwd)
function createCheckpoint(args, cwd)
function getRouting(args, cwd)
function explainFile(args, cwd)
function listModules(args, cwd)
function queryContext(args, cwd)
function getImpact(args, cwd)
```

### src/tracking/logger.js
```
module.exports = { logRun, readLog, summarize }
function logRun(entry, cwd)
function readLog(cwd) → object[]
function summarize(entries) → object
```

### src/extractors/typescript.js
```
module.exports = { extract }
function extract(src) → string[]
function extractBlock(src, startIndex)
function extractInterfaceMembers(block)
function extractClassMembers(block)
function normalizeParams(params)
```

### src/learning/weights.js
```
module.exports = { BASELINE, DECAY, MAX_MULT, MIN_MULT, weightsPath, clampMultiplier, normalizeFile, loadWeights, saveWeights, updateWeights, boostFiles, penalizeFiles, resetWeights, exportWeights, importWeights }
function weightsPath(cwd)
function clampMultiplier(value)
function normalizeFile(cwd, filePath)
function sanitizeWeights(cwd, weights)
function loadWeights(cwd)
function saveWeights(cwd, weights)
function updateWeights(cwd, opts = {})
function boostFiles(cwd, files, amount = 0.15)
function penalizeFiles(cwd, files, amount = 0.10)
function resetWeights(cwd)
function exportWeights(cwd, outputPath)
function importWeights(cwd, importPath, replace)
```

### src/config/loader.js
```
module.exports = { loadConfig, loadBaseConfig }
function loadBaseConfig(extendsVal, cwd)
function detectAutoSrcDirs(cwd, excludeList) → string[]
function _legacyDetectAutoSrcDirs(cwd, excludeList) → string[]
function loadConfig(cwd) → object
function deepClone(obj)
```

### src/discovery/framework-detector.js
```
module.exports = { detectFrameworks }
function detectFrameworks(cwd)
function _readDeps(cwd)
function _readFile(p)
function _existsAnywhere(cwd, filename, maxDepth)
function _walkFind(dir, name, depth)
```

### src/discovery/sigmapignore.js
```
module.exports = { loadIgnorePatterns, matchesIgnorePattern }
function loadIgnorePatterns(cwd)
function matchesIgnorePattern(dirName, patterns)
```

### src/plan/planner.js
```
module.exports = { createPlan }
function createPlan(goal, cwd, config)
```

### src/session/memory.js
```
module.exports = { loadSession, saveSession, mergeSessionContext, clearSession }
function sessionPath(cwd)
function loadSession(cwd)
function saveSession(cwd, { intent, topFiles, query })
function mergeSessionContext(scores, session, currentIntent)
function clearSession(cwd)
```

### src/config/defaults.js
```
module.exports = { DEFAULTS }
```

### src/discovery/source-root-scorer.js
```
module.exports = { scoreCandidate, getRecentlyChangedDirs, ROOT_ENTRYPOINTS, JVM_PATH_PATTERN }
function getRecentlyChangedDirs(cwd)
function scoreCandidate(dirName, fullPath, context)
function _countSourceFiles(dir, depth)
```

### src/eval/usefulness-scorer.js
```
module.exports = { scoreUsefulness, computeUsefulnessStats }
function scoreUsefulness(taskResult, rankingScore)
function computeUsefulnessStats(taskResults)
```

### src/workspace/detector.js
```
module.exports = { detectWorkspaces, inferPackage, scopeToPackage }
function detectWorkspaces(cwd)
function inferPackage(query, workspaceDirs, cwd)
function _getMatchLength(name, token)
function scopeToPackage(filePath, packageDir)
```

### src/discovery/source-root-registry.js
```
module.exports = { REGISTRY }
```

### src/extractors/python.js
```
module.exports = { extract, tryNativeExtract }
function tryNativeExtract(filePath) → string[]|null
function extract(src, filePath) → string[]
function extractClassMethods(stripped, startIndex)
function tryExtractDataclassFields(stripped, classIndex)
function tryExtractBaseModelFields(stripped, bodyStart)
function extractClassConstants(stripped, startIndex)
function extractReturnType(sigLine)
function normalizeParams(params)
function extractDocHint(src, fnName, fnSigLine)
```

### src/extractors/python_ast.py
```
def annotation_to_str(node)  # Convert an AST annotation node to a string representation
def format_args(args_node)  # Format a function arguments node into a compact signature st
def get_decorator_names(node)  # Return a list of decorator name strings for a function/class
def is_dataclass(node)
def is_basemodel(bases)  # Check if class bases include BaseModel or BaseSettings
def is_optional_annotation(annotation)  # Check if an annotation represents an Optional type
def get_docstring_hint(node)  # Extract first sentence of docstring, if present
def extract_dataclass_fields(class_node)  # Return a collapsed fields string for a @dataclass class
def extract_basemodel_fields(class_node)  # Return a compact {required*, optional
def extract_class_constants(class_node)  # Yield ALL_CAPS constant assignments from class body
def extract_method_sig(func_node)  # Format a method signature string (already indented by caller
def extract_function_sig(func_node, src_lines)  # Format a top-level function signature string
def extract_fastapi_routes(tree, src_lines)  # Extract FastAPI route signatures from top-level decorated fu
def extract(filepath)
def main()
```

### src/discovery/source-root-resolver.js
```
module.exports = { resolveSourceRoots }
function resolveSourceRoots(cwd, opts = {})
function _detectMonorepo(cwd)
function _enumerateCandidates(cwd, isMonorepo, ignorePatterns, excludeList)
function _applySpecialRules(scored, cwd, primaryFw, fwEntry, frameworks)
function _dedupeNested(scored)
function _computeConfidence(frameworks, languages, scoredCount)
```

### src/extractors/gdscript.js
```
module.exports = { extract }
function extract(src) → string[]
function extractInnerMembers(stripped, startIndex)
function normalizeParams(params)
```

### src/discovery/language-detector.js
```
module.exports = { detectLanguages }
function detectLanguages(cwd)
function _walkDepth(dir, depth, extCount)
```

### src/eval/analyzer.js
```
module.exports = { analyzeFiles, formatAnalysisTable, formatAnalysisJSON }
function isDockerfile(name)
function getExtractorName(filePath)
function tokenCount(sigs)
function hasCoverage(filePath, cwd)
function loadExtractor(name, cwd)
function analyzeFiles(files, cwd, opts) → object[]
function formatAnalysisTable(stats, showSlow) → string
function formatAnalysisJSON(stats) → object
```

### src/analysis/diagnostics.js
```
module.exports = { formatFileDecision, computeFileMetrics, explainInclusion, explainExclusion, estimateTokens }
function estimateTokens(text)
function formatFileDecision(entry, decision, reason, score = null)
function computeFileMetrics(entry)
function explainInclusion(fileEntries, budgetLimit)
function explainExclusion(dropped, reason)
```

### src/map/import-graph.js
```
module.exports = { analyze, extractImports, buildReverseGraph, resolveJsPath, detectCycles }
function extractImports(filePath, content, fileSet)
function resolveJsPath(dir, importStr, fileSet)
function detectCycles(graph)
function buildReverseGraph(graph)
function analyze(files, cwd)
```

### src/discovery/r-manifest.js
```
module.exports = { readDescription, readNamespace, collectLocalDefs }
function readDescription(cwd) → object|null
function splitDeps(value)
function readNamespace(cwd) → object|null
function splitArgs(raw)
function stripQuotes(s)
function collectLocalDefs(rFiles) → Map<string, string>
```

### src/extractors/deps.js
```
module.exports = { extractPythonDeps, extractTSDeps, extractRDeps, buildReverseDepMap }
function extractPythonDeps(src) → string[]
function extractTSDeps(src) → string[]
function extractRDeps(src) → string[]
function buildReverseDepMap(forwardMap) → Map<string, string[]>
```

### src/extractors/r.js
```
module.exports = { extract }
function extract(src) → string[]
function collectRoxygenHints(src)
function pickRoxygenLine(block, tag)
function applyHint(hints, name)
function extractListMethods(body, cap)
function inAnyRange(pos, ranges)
function readFirstStringArg(body)
function readBalancedParens(src, openIdx, cap = 16384)
function normalizeParams(raw)
```

### src/graph/builder.js
```
module.exports = { build, buildFromCwd, extractFileDeps, normalizePath }
function normalizePath(p)
function resolveJsPath(dir, importStr, fileSet) → string|null
function escapeRegex(s)
function resolveRPath(dir, importStr, fileSet, cwd)
function extractFileDeps(filePath, content, fileSet, cwd, ctx) → string[]
function build(files, cwd, ctx) → { forward: Map<string,str
function buildFromCwd(cwd, opts) → { forward: Map<string,str
```

### src/graph/impact.js
```
module.exports = { getImpact, analyzeImpact, formatImpact, formatImpactJSON }
function normalizePath(p)
function bfs(startFile, reverseGraph, maxDepth) → { direct: Set<string>, tr
function isTestFile(f)
function isRouteFile(f)
function getImpact(changedFile, graph, opts) → { * changed: string, * di
function analyzeImpact(changedFiles, cwd, opts) → { file: string, impact: o
function formatImpact(result) → string
function formatImpactJSON(result) → object
```

### src/mcp/server.js
```
module.exports = { start }
function respond(id, result)
function respondError(id, code, message)
function dispatch(msg, cwd)
function start(cwd)
```

### src/retrieval/ranker.js
```
module.exports = { rank, buildSigIndex, scoreFile, formatRankTable, formatRankJSON, DEFAULT_WEIGHTS, GRAPH_BOOST_AMOUNTS, detectIntent }
function _computePenalty(filePath)
function _computeHubs(graph)
function _isHub(filePath)
function scoreFile(filePath, sigs, queryTokens, weights) → { score: number, signals:
function rank(query, sigIndex, opts) → { file: string, score: nu
function _parseContextFile(contextPath) → Map<string, string[]>
function buildSigIndex(cwd, opts) → Map<string, string[]>
function formatRankTable(results, query) → string
function formatRankJSON(results, query) → object
function detectIntent(query)
```
