When an AI agent opens a codebase, should it read every file first, or should it get a compact map of what those files contain and inspect the important ones on demand?
That is the idea behind Sentinel-IR and Sentinel-IR-MCP. Version 0.2.0 brought TypeScript and TSX into the MCP workflow. Version 0.2.1 made a different, less flashy but equally important improvement: it made incomplete and skipped files visible in the directory summary, rather than letting a low-risk-looking entry hide uncertainty or one unreadable file ruin the whole result.
- npm: "sentinel-ir-mcp 0.2.1" (https://www.npmjs.com/package/sentinel-ir-mcp/v/0.2.1)
- Source at the release tag: "GitLab v0.2.1" (https://gitlab.com/jakubrojicek11/sentinel-ir-mcp/-/tree/v0.2.1?ref_type=tags)
- Project: "sentinel-ir-mcp on GitLab" (https://gitlab.com/jakubrojicek11/sentinel-ir-mcp)
- Core analysis library: "sentinel-ir on GitLab" (https://gitlab.com/jakubrojicek11/sentinel-ir)
This article is deliberately split into three reading depths. Start with the 30-second version, take the friendly tour, or jump to the engineering details.
- The 30-second version
An AI coding agent can spend a lot of context reading source files just to work out where the important things are. Sentinel-IR creates a compact structural summary instead: imports, exports, routes, environment reads, filesystem/network/process activity, selected risk signals, and an explicit analysis status.
Sentinel-IR-MCP exposes that summary to compatible AI clients through the Model Context Protocol (MCP), using three tools:
- "analyze_code": analyze source text supplied by the client.
- "analyze_file": analyze one supported source file within an allowed folder.
- "analyze_directory": scan a folder and return per-file summaries, ordered by risk.
Version 0.2.0: added TypeScript and TSX support alongside JavaScript. The language is selected from the file extension, with an explicit language option available for "analyze_code".
Version 0.2.1: added "incomplete", "statusCounts", and "skipped.unreadable" to the directory summary. A parse-incomplete file is listed separately, and one file that cannot be read or handled must not hide the results for the rest of the directory.
The principle: a missing result must look missing, not safe.
This is a read-only structural analysis aid, not a complete security scanner and not a guarantee that the code is safe.
- The friendly tour: explain it to me like I am new to MCP
The problem: giving an agent a whole library instead of a map
Imagine asking a new teammate to review a project with hundreds of files. You hand them the whole repository and say, “Find the important parts.” They have to discover the layout, hunt for routes and imports, locate the places that touch the filesystem, and work out where commands or network requests might happen.
An AI agent faces a similar problem. Reading more source can consume more context and time, and the most relevant file may be buried among many ordinary files.
Sentinel-IR takes a different first step. It parses supported source files and extracts compact structural facts. The result is closer to a map or an index than a copy of the original file. The agent can use that map to decide which raw files deserve closer inspection.
The map is not the territory. It helps navigation; it does not replace the source code when a detailed review is needed.
What is Sentinel-IR?

Sentinel-IR is the analysis library. It looks at JavaScript or TypeScript structure and produces a compact Intermediate Representation, usually shortened to IR.
In plain English, the IR can tell an agent things such as:
- which modules a file imports;
- which functions or values it exports;
- whether it contains recognised patterns involving dynamic evaluation or process execution;
- which routes, environment-variable reads, filesystem calls, network calls, or crypto-related calls were found by its rules;
- what risk category its current rules assign;
- whether parsing completed successfully.
The point is not to retell every line of code in natural language. It is to provide a smaller, structured set of facts that a tool or agent can inspect consistently.
What does MCP add?
MCP, the Model Context Protocol, is a standard way for an AI application to communicate with tools and other context providers.
Think of Sentinel-IR as the workshop tool and MCP as the standard socket that lets a compatible AI client use it. Instead of creating a special integration for every client, the server exposes named tools with defined inputs and outputs. Clients such as Claude Desktop, Cursor, Windsurf, and other compatible MCP clients can call those tools when configured to do so.
MCP does not make the analysis smarter by itself. It makes the capability accessible through a consistent interface.
What changed in 0.2.0?
Before 0.2.0, this MCP workflow was focused on JavaScript. Version 0.2.0 added TypeScript and TSX support while preserving the existing JavaScript path.
The supported extensions are:
Language| Extensions
JavaScript| ".js", ".mjs", ".cjs"
TypeScript| ".ts", ".mts", ".cts", ".tsx"
For file-based tools, the extension selects the language. For "analyze_code", a "target" filename can provide the extension; an explicit "language" can override the default when necessary.
This matters because TypeScript is not just JavaScript with decorative annotations. Types, type assertions, TS-specific declarations, and TSX syntax affect how a parser should interpret a source file. Language-aware parsing lets the analysis work with the source structure instead of treating TypeScript as if it were always plain JavaScript.
The implementation keeps JavaScript on its existing analysis path rather than forcing all languages through one parser configuration. That is a compatibility decision: supporting another language should not silently rewrite established JavaScript results.
What changed in 0.2.1?
Version 0.2.1 focuses on making the directory summary more honest and resilient.
There are three useful categories to understand:
Complete analysis means the analyzer finished parsing the file according to its current rules. It does not mean the program is proven safe.
Incomplete analysis means the file produced a result, but parsing did not finish cleanly. The file remains in "files", and its status is "incomplete". Because the parser could not fully understand the file, its risk result must not be treated as a safety verdict.
Skipped/unreadable means the file did not produce a normal analyzed entry because the per-file read or analysis operation raised an error. In 0.2.1, it is surfaced in "skipped.unreadable" instead of allowing that file to abort the entire directory operation. The current implementation uses that category for exceptions across the file-read/analysis boundary, so it is an outcome category rather than a detailed taxonomy of every underlying cause.
The new fields are:
- "incomplete": paths whose analysis status is not "complete", listed once and sorted by path;
- "statusCounts": totals for "complete" and "incomplete" among analyzed results;
- "skipped.unreadable": paths that could not produce a normal per-file result because the read/analysis operation failed.
The original "files" shape and risk-based ordering remain unchanged. The IR library itself is not changed by this MCP release.
Why is this important?
Suppose a directory contains:
- "run.ts", where a risky process-execution pattern was detected;
- "broken.ts", which has syntax the parser cannot fully handle;
- "ok.ts", which was analyzed normally;
- "locked.js", which the server cannot read.
A useful report should still tell you about "run.ts" and "ok.ts". It should also clearly say that "broken.ts" is incomplete and "locked.js" did not produce an analyzed result. It should not turn either missing understanding into a quiet “looks safe.”
That is the practical difference between a list of findings and a report that exposes its blind spots.
- The developer section: tools, outputs, limits, and tests
This section is for people integrating the server or evaluating its behavior in a real workflow.
3.1 The integration surface
The server currently exposes three tools, keeping the surface small and explicit:
Tool| Input| Purpose
"analyze_code"| Source text; optional "target" and "language"| Analyze source without first reading a project file through the tool.
"analyze_file"| A path inside an allowed root| Read and analyze one supported file.
"analyze_directory"| Optional directory path, "max_files", and "recursive"| Analyze supported source files and return risk-sorted summaries plus counts and skipped/incomplete lists.
Results are returned as JSON text and as MCP "structuredContent". Tool annotations declare the tools read-only, non-destructive, idempotent, and not open-world. Those annotations describe intended tool behavior; they are not a substitute for inspecting the implementation or configuring the correct allowed roots.
3.2 A copy-ready MCP configuration
The server requires Node.js 20 or newer and can be started with "npx". Give it the absolute path of the project that the agent is permitted to inspect. Replace the example path with your own project path.
"claude_desktop_config.json" entry
The following is a valid JSON configuration object for the relevant part of the Claude Desktop config. Merge the "mcpServers" entry into the existing configuration rather than deleting other servers.
{
"mcpServers": {
"sentinel-ir": {
"command": "npx",
"args": [
"-y",
"sentinel-ir-mcp@0.2.1",
"/absolute/path/to/your/project"
]
}
}
}
Cursor project config: ".cursor/mcp.json"
{
"mcpServers": {
"sentinel-ir": {
"command": "npx",
"args": [
"-y",
"sentinel-ir-mcp@0.2.1",
"${workspaceFolder}"
]
}
}
}
These examples pin the version to "0.2.1" so the configuration does not silently switch to a future release. If you prefer to follow the latest npm version, remove "@0.2.1" from the package name. After changing the client configuration, restart or reload the client as required by that application.
3.3 A copy-ready "analyze_code" tool input
When an MCP client calls "analyze_code", the tool arguments are JSON. This example uses a TypeScript filename so the tool can select the TypeScript language from the extension. The "language" override is included to make the intent explicit.
{
"target": "src/danger.ts",
"language": "typescript",
"code": "import { exec } from \"node:child_process\";\n\nexec(\"echo hello\");\n"
}
This is the tool input, not a standalone JavaScript file. JSON requires quotes and newlines inside a string to be escaped. That is why this form can be pasted into a tool inspector or used as a fixture without guessing where a quote or line break belongs.
3.4 Understanding the 0.2.1 directory summary
"analyze_directory" continues returning its original "files" array in risk order, and adds explicit status information beside the existing risk counts. Here is a reduced, illustrative shape for the relevant fields. The file objects below are intentionally abbreviated to make the summary easier to read; actual entries include more fields, including "forbidden" and structural "facts".
{
"analyzed": 3,
"truncated": false,
"riskCounts": {
"critical": 1,
"high": 0,
"medium": 0,
"low": 2
},
"statusCounts": {
"complete": 2,
"incomplete": 1
},
"incomplete": [
"src/broken.ts"
],
"skipped": {
"tooLarge": [],
"symlinks": 0,
"unreadable": [
"src/locked.js"
]
},
"files": [
{
"path": "src/run.ts",
"analysisStatus": "complete",
"language": "typescript",
"risk": "critical"
},
{
"path": "src/broken.ts",
"analysisStatus": "incomplete",
"language": "typescript",
"risk": "low"
},
{
"path": "src/ok.ts",
"analysisStatus": "complete",
"language": "typescript",
"risk": "low"
}
]
}
The key invariants are more important than any particular example:
- Every path in "incomplete" corresponds to a file entry whose "analysisStatus" is not "complete".
- "incomplete" is unique and sorted by path, independently of the risk order used for "files".
- "statusCounts.complete + statusCounts.incomplete" equals "analyzed".
- The sum of "riskCounts" also equals "analyzed".
- A skipped/unreadable path is not simultaneously counted in "files", "incomplete", or the analyzed totals.
- A file can have a low risk and an incomplete status. The low risk must not override the incomplete status.
In the illustrated example, three files were analyzed and one additional file could not produce an analyzed result. Therefore "analyzed" is 3, not 4. The unreadable file appears in the skipped section and is not counted in the status or risk totals.
One detail about the file limit: a source-file candidate that cannot be read still occupies a slot in "max_files". The limit is applied during collection, before each file's analysis outcome is known. With a small limit, that means a skipped file can consume a slot even though it will not appear in "analyzed".
3.5 Why keep "files" unchanged?
Adding a useful field can still break consumers if it changes the shape, meaning, or order of existing fields. In 0.2.1, "files" keeps its current shape and its risk-first ordering. The new "incomplete" list is a second view designed for a different question: “Which paths need special attention because the analysis did not finish?”
The two lists are intentionally not sorted the same way:
- "files" prioritizes risk so an agent sees the most concerning reported findings first;
- "incomplete" prioritizes stable path order so consumers can review missing analysis deterministically.
This avoids changing the established array ordering while making incomplete files easy to find. It is a small example of additive API evolution: add explicit metadata without silently redefining the existing field.
3.6 Failure isolation and the meaning of "skipped.unreadable"
Before the 0.2.1 fix, an individual file read error could fail the entire directory analysis. The new per-file error boundary lets the loop continue. The server records the affected path under "skipped.unreadable" and continues processing other collected files.
The current implementation catches errors around both reading the file and invoking its analysis. Consequently, a thrown per-file analyzer error is also recorded under "skipped.unreadable". That preserves the “one file must not hide all the others” behavior, but the field name should be understood as the current skipped outcome category, not a promise that every entry failed only because of filesystem permissions. A future schema could separate "readErrors" and "analysisErrors" if consumers need precise root-cause diagnostics; that would be a separate, intentional schema change.
A few other states remain distinct:
- Incomplete: an IR result exists, but parsing did not complete cleanly.
- Skipped/unreadable: the file-read or per-file analysis operation threw before a normal result could be added.
- Too large: the file exceeds the configured byte limit and is listed under "skipped.tooLarge".
- Symlink: directory traversal does not follow symlinks; skipped symlink counts are reported separately.
- Truncated: the directory traversal stopped at "max_files"; "truncated: true" means the report should not be treated as a complete inventory of all eligible files.
A consumer should inspect all applicable status and skipped fields before drawing conclusions from the result.
3.7 Boundaries and safety properties
The MCP server is intended to be read-only. It reads supported source files inside explicitly allowed folders. It does not write project files, execute the analyzed source, run shell commands, or open network connections as part of analysis.
The traversal also has practical limits:
- Node.js 20 or newer is required.
- The default maximum source-file size is 1 MiB.
- "analyze_directory" defaults to 50 files and supports a configured maximum of 500.
- "node_modules", ".git", hidden directories, and symlinks are skipped during directory traversal.
- Resolved paths must stay inside the allowed roots; parent-directory traversal and paths outside those roots are refused.
- Only the documented JavaScript and TypeScript extensions are included.
There is an important prompt-injection nuance. The IR avoids copying full comments, function bodies, or string bodies into the model context, which can reduce exposure to instructions embedded in source text. But the IR is still derived from untrusted repository content. It contains identifiers and selected literals such as route paths, module names, export names, and environment-variable names. Treat it as data, not as trusted instructions. Compactness reduces the amount of source copied; it does not eliminate prompt injection.
And this is not a full security scanner. The risk classification comes from a fixed set of structural patterns. Dynamic behavior that constructs module names at runtime or hides a call in a way the current rules do not recognize can be missed. “No risky pattern found” is not equivalent to “the program is safe.”
3.8 Evidence, tests, and the token question
The 0.2.1 changes include tests for summary consistency and failure cases. The release work reported 29/29 local tests on Node 20, 22, and 24. CI reported 28 passing tests and one skipped test. The skipped case uses a real "chmod 000" file; CI runs as root, which can still read that file, so the real permission test is not meaningful there. Read failures are also covered with a simulated error that works in CI.
The test cases exercise:
- incomplete JavaScript, TypeScript, and TSX inputs;
- malformed JSX/TS dialect combinations, binary-like input, and empty files;
- duplicate basenames in different folders;
- deterministic "incomplete" ordering across repeated runs;
- simulated read errors and simulated analyzer errors;
- a real unreadable file where the local environment honours its permissions;
- "max_files" boundaries;
- consistency between "analyzed", "statusCounts", and "riskCounts".
The released package was also tested through the official MCP client, according to the release report. The reported mixed directory contained a dangerous file, incomplete files, a normal file, and an unreadable file. The expected behavior was that the dangerous file remained first in risk order, incomplete paths appeared separately, unreadable files were excluded from analyzed counts, and the original "files" shape stayed intact.
What about token savings? It is a motivation, but we should not turn motivation into a universal benchmark. The project README records one concrete measurement using the source of "sentinel-ir@0.1.3", an MCP stdio run, and the "o200k_base" tokenizer:
Four files from the library| Tokens
Raw source combined| 11,564
IR combined| 317
Reduction in this sample| about 97.3%
That sample demonstrates how compact the output can be for those files. It is not a promise that every project, every file size, or every tokenizer will see the same reduction. There is also a per-file overhead: the README notes an IR floor of roughly 120 tokens per file, so very small files may not benefit from being summarized individually.
The next useful experiment is therefore not another headline. It is a reproducible comparison on representative projects: task success, relevant-file recall, total tokens, latency, and how often incomplete analysis changes the agent's next action.
3.9 What 0.2.1 does not change
A release is easier to evaluate when the boundaries are explicit.
- It does not change the "sentinel-ir" library or its IR contract.
- It does not change the shape or risk ordering of the existing "files" list.
- It does not add Python support.
- It does not execute, repair, or rewrite source code.
- It does not turn static pattern analysis into a proof of safety.
Version 0.2.0 expanded the language coverage. Version 0.2.1 improved how uncertainty and per-file failure are surfaced through the MCP directory summary. Those are complementary changes: broader input coverage helps the tool understand more source; explicit status reporting helps the agent know when the tool has not understood enough.
3.10 A practical review sequence for an AI agent
The tool is most useful when the agent treats the result as a workflow, not as a magic verdict. A defensible sequence looks like this:
- Inventory first. Call "analyze_directory" on an explicit allowed project root with a sensible "max_files" value.
- Check coverage before conclusions. Inspect "truncated", "skipped", "statusCounts", and "incomplete". If the scan is truncated or files are incomplete/skipped, state that the view is partial.
- Triage reported risk. Start with "critical" and "high" results, then inspect their "forbidden" and "facts" fields. The risk label is a prioritization signal, not a proof.
- Do not ignore incomplete files. Visit every path listed in "incomplete". Use "analyze_file" where appropriate, and if it remains incomplete, inspect the source through the client’s normal, permitted workflow.
- Inspect source only where it matters. Read the raw contents of relevant files after the structural view identifies why they matter.
- Keep the report bounded. State what was analyzed, what was skipped, what remained incomplete, and which conclusions are therefore limited.
This sequence can be embedded into the instructions of an orchestration agent. It is not hard-coded autonomous remediation: the server reports facts, and the client decides what to do with them. For example, it does not repair files, run tests, or modify the project.
A machine-readable review policy is included in the companion JSON examples. It is a suggested policy document, not a configuration automatically consumed by Sentinel-IR-MCP.
3.11 What should a consumer consider a complete inventory?
A response can be internally consistent and still be an incomplete view of the repository. These are separate properties:
- Internal consistency asks whether the returned counts and lists agree with each other.
- Coverage asks whether every eligible file in the intended scope was considered.
- Analysis completeness asks whether the parser produced a complete result for each counted file.
- Risk detection quality asks whether the structural rules recognized the behavior that matters.
For example, "statusCounts.complete + statusCounts.incomplete === analyzed" can be true even while "truncated" is also true. The counts may be perfectly correct for the subset processed, but the entire directory was not scanned. Likewise, every analyzed file can have "analysisStatus: "complete"" while the rule set still misses an obfuscated or dynamically constructed operation.
This is why the consumer should not compress all uncertainty into one boolean called "safe". A robust report keeps these dimensions separate. Version 0.2.1 directly improves one of them: it exposes incomplete and skipped outcomes instead of hiding them inside a risk-sorted list or aborting the entire operation.
3.12 Compatibility questions for integrations
For an MCP client or framework author, there are a few practical integration rules:
- Pin versions in repeatable environments. "sentinel-ir-mcp@0.2.1" identifies the release whose fields and behavior you tested. Pinning is especially useful in CI, reproducible demos, and automated evaluations.
- Prefer structured content when available. The server returns both a JSON text representation and "structuredContent". A client should use the structured representation when its SDK exposes it, rather than parsing a text block unnecessarily. It should still handle tool errors according to its MCP SDK.
- Do not assume a language from source contents when a filename is available. File extensions select JavaScript, TypeScript, or TSX parsing for file-based tools. For code supplied directly as text, pass an appropriate "target" or explicit "language" rather than relying on a default.
- Treat new fields as additive, but do not ignore them. Consumers that parse the directory response should preserve unknown fields where practical and should explicitly read "incomplete", "statusCounts", "skipped", and "truncated" before concluding that the directory is covered.
- Avoid coupling to "mission.objective". The library README describes this as a coarse hint. The more relevant analysis fields for triage are "analysisStatus", "world.risk", "forbidden", and "facts".
The IR schema and MCP response are related, but they are not the same thing. The IR comes from "sentinel-ir"; "sentinel-ir-mcp" packages it into tool calls, applies path and size rules, and adds directory-level results. This release changes the MCP directory summary, not the core IR schema.
3.13 Reproducing the evidence rather than repeating the headline
A release note can say that tests pass. A useful engineering report tells the next person which conditions were actually tested and which conditions were simulated.
For the 0.2.1 summary change, the most meaningful checks are not just “the command returned without throwing.” They are assertions about the semantics of the result:
Scenario| Expected interpretation
Valid, parseable source| One "files" entry with "analysisStatus: "complete"".
Broken JS/TS/TSX syntax| A file entry with "analysisStatus: "incomplete"", and one path in "incomplete".
Two broken files with the same basename in different directories| Two distinct paths in "incomplete", each present once.
Read error for one file| That file is recorded under "skipped.unreadable"; other files still produce results.
Per-file analysis throws| The per-file failure is isolated; under the current implementation it is also recorded in "skipped.unreadable".
More eligible files than "max_files"| "truncated" communicates that the directory inventory is partial.
Unreadable candidate within the limit| It consumes a slot but is not included in "analyzed".
Same directory analyzed repeatedly| The status list remains deterministically path-sorted; risk-first "files" order remains stable for the same inputs.
For a clean verification run, use fixtures whose expected behavior is known before running the analyzer. Keep malformed syntax cases separate from genuinely dangerous patterns, so a test does not accidentally treat a parser failure as a successful risk detection. Then exercise the packed npm tarball through an actual MCP client, because importing local source is not a substitute for testing the artifact users install.
There is also a useful environment distinction in the release report: a local permission test using "chmod 000" may behave differently from the same test in CI if CI runs as root. The test was therefore skipped in that CI environment, while a simulated read error exercised the error-handling path. Reporting that distinction is better than claiming the permission test proved something in an environment where the permission did not prevent access.
A companion checklist JSON records the primary invariants so they can be copied into an issue, release checklist, or future test plan. It is a checklist, not an executable test suite by itself.
3.14 Benchmark the workflow, not just the compressed output
A small IR is promising, but token reduction alone cannot tell us whether the agent found the right file or completed the task correctly. A serious evaluation should compare at least two workflows on the same task set:
- Baseline: the agent navigates and reads source using its usual approach.
- IR-first: the agent begins with "analyze_directory", checks coverage and status, then reads selected raw files.
Keep model, task, repository snapshot, context limit, and success criteria as consistent as possible. Measure:
- task completion and correctness using a pre-defined rubric;
- recall of files known to matter for the task;
- total input and output tokens, including the IR/tool overhead;
- wall-clock latency and number of tool calls;
- how often the agent catches and reports incomplete or skipped analysis;
- false positives and false negatives in the structural risk signals.
Run tasks over several repository sizes and include small files. The IR has per-file overhead, so a workflow that works well on a large repository may not save tokens on a tiny one. Repeat the experiment and report the range or distribution, not just the best run.
The question to answer is not “Is the IR smaller?” The README already gives a concrete small example of that. The more important question is: Does the IR-first workflow help an agent complete real tasks with less wasted context, without causing it to overlook the files or uncertainty that matter? That remains a measurement question, not a claim made by the release.
3.15 Current scope and the next engineering questions
As of 0.2.1, the supported languages are JavaScript, TypeScript, and TSX. Python is not supported by this release. Adding Python will require a deliberate choice about parser architecture, language-specific risk rules, handling incomplete syntax, packaging, and distribution. It should not be described as supported merely because the MCP interface can accept text.
The same rule applies to any future language: adding an extension is not the whole feature. A language should have tests for ordinary code, dangerous patterns, aliases, malformed input, and type- or language-specific syntax. The output contract should remain stable where possible, and uncertainty should remain explicit.
For maintainers, the useful next gates are therefore:
- preserve the existing JavaScript results with regression fixtures;
- keep TypeScript-specific parsing separate where needed to avoid unintentional JavaScript changes;
- test the published package, not only the working tree;
- test every status transition and counter invariant;
- benchmark actual task outcomes before making universal efficiency claims;
- design future language support as a language-specific analyzer that emits a clearly defined common result contract.
These are not promises about what the next release will contain. They are the checks that make a future expansion credible.
Final thought
An AI coding agent does not always need a bigger context window. Sometimes it needs a better index, an honest status field, and a clear signal when part of the map is missing.
Sentinel-IR-MCP 0.2.0 gives the workflow TypeScript and TSX support. Sentinel-IR-MCP 0.2.1 makes incomplete and skipped analysis harder to overlook.
The guiding rule is simple: give the agent a compact map first, let it inspect the relevant source when needed, and never let missing information masquerade as a clean bill of health.
- "Install sentinel-ir-mcp 0.2.1 from npm" (https://www.npmjs.com/package/sentinel-ir-mcp/v/0.2.1)
- "Inspect the v0.2.1 release tag" (https://gitlab.com/jakubrojicek11/sentinel-ir-mcp/-/tree/v0.2.1?ref_type=tags)
- "Read the source and report issues" (https://gitlab.com/jakubrojicek11/sentinel-ir-mcp)
Cursor MCP configuration: Project-specific configuration with a workspace variable.
Claude Desktop config
Server configuration with pre-release version 0.2.1.
AI agents procedures.
Recommended procedure for working with IR. This is a policy draft, not an automatically loaded server configuration

Top comments (2)
TypeScript support and surfacing missing analysis both sound like solid quality-of-life wins. Curious how the visibility of missing analysis is presented in practice.
Thanks! The visibility is built directly into the "analyze_directory" result, rather than being just a warning in the logs.
For example, imagine a folder containing a dangerous file, a file with syntax the parser couldn't fully understand, a normal file, and one the server couldn't read.
The relevant part of the result would look like this:
{
"analyzed": 3,
"statusCounts": {
"complete": 2,
"incomplete": 1
},
"incomplete": [
"src/broken.ts"
],
"skipped": {
"tooLarge": [],
"symlinks": 0,
"unreadable": [
"src/locked.js"
]
},
"files": [
{
"path": "src/run.ts",
"analysisStatus": "complete",
"risk": "critical"
},
{
"path": "src/broken.ts",
"analysisStatus": "incomplete",
"risk": "low"
},
{
"path": "src/ok.ts",
"analysisStatus": "complete",
"risk": "low"
}
]
}
The important detail is that "files" keeps its existing risk-based ordering, while "incomplete" provides a separate, path-sorted list of files that need attention.
Notice that "broken.ts" has a low risk rating, but its analysis status is "incomplete". That low rating is not evidence that the file is safe. The agent is explicitly told to inspect it separately.
The unreadable file is different: it appears under "skipped.unreadable" and isn't counted as analyzed. Most importantly, one unreadable file no longer prevents the agent from receiving results for the rest of the directory.
So the goal isn't just to report what the analyzer found. It's also to make clear what it couldn't reliably determine.
A missing result should look missing, not safe.🤔☺️