ast-mcp-server 0.12.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import path from "node:path";
2
+ import packageMetadata from "../../package.json" with { type: "json" };
2
3
  export const RUNTIME_POLICY_ENV_KEYS = Object.freeze([
3
4
  "AST_MAX_PROJECT_SESSIONS",
4
5
  "AST_MAX_QUEUED_OPERATIONS_PER_PROJECT",
@@ -7,6 +8,8 @@ export const RUNTIME_POLICY_ENV_KEYS = Object.freeze([
7
8
  "AST_SHUTDOWN_DRAIN_TIMEOUT_MS",
8
9
  "AST_COMPILER_WORKER_MODE",
9
10
  "AST_COMPILER_WORKER_IDLE_TTL_MS",
11
+ "AST_MCP_APPLY_GUARD",
12
+ "AST_MCP_TEXT_PROJECTION",
10
13
  ]);
11
14
  function parseBoundedInteger(rawValue, defaultValue, minimum, maximum) {
12
15
  if (rawValue === undefined)
@@ -26,8 +29,8 @@ function parseBoundedInteger(rawValue, defaultValue, minimum, maximum) {
26
29
  export function parseRuntimePolicy(environment) {
27
30
  const maxProjectSessions = parseBoundedInteger(environment.AST_MAX_PROJECT_SESSIONS, 8, 1, 32);
28
31
  const maxQueuedOperationsPerProject = parseBoundedInteger(environment.AST_MAX_QUEUED_OPERATIONS_PER_PROJECT, 32, 1, 256);
29
- const queueWaitTimeoutMs = parseBoundedInteger(environment.AST_QUEUE_WAIT_TIMEOUT_MS, 30_000, 100, 300_000);
30
- const operationDeadlineMs = parseBoundedInteger(environment.AST_OPERATION_DEADLINE_MS, 120_000, 1_000, 900_000);
32
+ const queueWaitTimeoutMs = parseBoundedInteger(environment.AST_QUEUE_WAIT_TIMEOUT_MS, packageMetadata.deepseekHarness.timeoutBudget.queueWaitMs, 100, 300_000);
33
+ const operationDeadlineMs = parseBoundedInteger(environment.AST_OPERATION_DEADLINE_MS, packageMetadata.deepseekHarness.timeoutBudget.executionDeadlineMs, 1_000, 900_000);
31
34
  const shutdownDrainTimeoutMs = parseBoundedInteger(environment.AST_SHUTDOWN_DRAIN_TIMEOUT_MS, 10_000, 100, 60_000);
32
35
  const rawWorkerMode = environment.AST_COMPILER_WORKER_MODE;
33
36
  const compilerWorkerMode = rawWorkerMode === "supervised" ? "supervised" : "in_process";
@@ -37,6 +40,22 @@ export function parseRuntimePolicy(environment) {
37
40
  ? "configured"
38
41
  : "invalid_mode";
39
42
  const compilerWorkerIdleTtlMs = parseBoundedInteger(environment.AST_COMPILER_WORKER_IDLE_TTL_MS, 60_000, 0, 86_400_000);
43
+ const rawApplyGuard = environment.AST_MCP_APPLY_GUARD;
44
+ // Fail-closed: only an explicit `allow` permits the apply-effect MCP tool on
45
+ // this surface. A missing value, `deny`, or any invalid value denies apply.
46
+ const denyApply = rawApplyGuard !== "allow";
47
+ const applyGuardReason = rawApplyGuard === undefined
48
+ ? "default"
49
+ : rawApplyGuard === "allow" || rawApplyGuard === "deny"
50
+ ? "configured"
51
+ : "invalid_mode";
52
+ const rawTextProjection = environment.AST_MCP_TEXT_PROJECTION;
53
+ const projectStructuredContentAsText = rawTextProjection === "canonical_json";
54
+ const textProjectionReason = rawTextProjection === undefined
55
+ ? "default"
56
+ : projectStructuredContentAsText
57
+ ? "configured"
58
+ : "invalid_mode";
40
59
  const reasons = Object.freeze({
41
60
  AST_MAX_PROJECT_SESSIONS: maxProjectSessions.reason,
42
61
  AST_MAX_QUEUED_OPERATIONS_PER_PROJECT: maxQueuedOperationsPerProject.reason,
@@ -45,6 +64,8 @@ export function parseRuntimePolicy(environment) {
45
64
  AST_SHUTDOWN_DRAIN_TIMEOUT_MS: shutdownDrainTimeoutMs.reason,
46
65
  AST_COMPILER_WORKER_MODE: compilerWorkerModeReason,
47
66
  AST_COMPILER_WORKER_IDLE_TTL_MS: compilerWorkerIdleTtlMs.reason,
67
+ AST_MCP_APPLY_GUARD: applyGuardReason,
68
+ AST_MCP_TEXT_PROJECTION: textProjectionReason,
48
69
  });
49
70
  return Object.freeze({
50
71
  maxProjectSessions: maxProjectSessions.value,
@@ -54,6 +75,8 @@ export function parseRuntimePolicy(environment) {
54
75
  shutdownDrainTimeoutMs: shutdownDrainTimeoutMs.value,
55
76
  compilerWorkerMode,
56
77
  compilerWorkerIdleTtlMs: compilerWorkerIdleTtlMs.value,
78
+ denyApply,
79
+ projectStructuredContentAsText,
57
80
  reasons,
58
81
  });
59
82
  }
@@ -64,6 +87,46 @@ const WORKER_ENV_KEYS = [
64
87
  "AST_SYMBOL_INDEX_BUSY_TIMEOUT_MS",
65
88
  ];
66
89
  const MAX_WORKER_ENV_VALUE_LENGTH = 4096;
90
+ function parseClosedFixtureRecord(raw, expectedKeys) {
91
+ if (typeof raw !== "string" || raw.length > 1024 || raw.includes("\0"))
92
+ return undefined;
93
+ try {
94
+ const value = JSON.parse(raw);
95
+ if (!value || typeof value !== "object" || Array.isArray(value))
96
+ return undefined;
97
+ const record = value;
98
+ return Object.keys(record).sort().join(",") === expectedKeys ? record : undefined;
99
+ }
100
+ catch {
101
+ return undefined;
102
+ }
103
+ }
104
+ export function parseH03FixtureDescriptor(raw) {
105
+ const record = parseClosedFixtureRecord(raw, "controlDirectory,generation,nonce");
106
+ if (!record)
107
+ return undefined;
108
+ const { controlDirectory, nonce, generation } = record;
109
+ if (typeof controlDirectory !== "string" ||
110
+ controlDirectory.length > MAX_WORKER_ENV_VALUE_LENGTH ||
111
+ !path.isAbsolute(controlDirectory) ||
112
+ path.normalize(controlDirectory) !== controlDirectory ||
113
+ typeof nonce !== "string" ||
114
+ !/^[A-Za-z0-9_-]{16,64}$/.test(nonce) ||
115
+ !Number.isSafeInteger(generation) ||
116
+ generation < 1)
117
+ return undefined;
118
+ return Object.freeze({ controlDirectory, nonce, generation: generation });
119
+ }
120
+ export function parseH05FixtureDescriptor(raw) {
121
+ const record = parseClosedFixtureRecord(raw, "controlDirectory,generation,nonce,ownerToken");
122
+ if (!record)
123
+ return undefined;
124
+ const { ownerToken, ...baseValue } = record;
125
+ if (typeof ownerToken !== "string" || !/^[A-Za-z0-9_-]{16,64}$/.test(ownerToken))
126
+ return undefined;
127
+ const base = parseH03FixtureDescriptor(JSON.stringify(baseValue));
128
+ return base ? Object.freeze({ ...base, ownerToken }) : undefined;
129
+ }
67
130
  function validEnvironmentString(value) {
68
131
  return (typeof value === "string" &&
69
132
  value.length <= MAX_WORKER_ENV_VALUE_LENGTH &&
@@ -88,6 +151,20 @@ export function createCompilerWorkerSpawnSpec(workerEntryPath, environment) {
88
151
  }
89
152
  projected[key] = value;
90
153
  }
154
+ const fixture = environment.AST_H03_FIXTURE;
155
+ if (fixture !== undefined) {
156
+ const descriptor = parseH03FixtureDescriptor(fixture);
157
+ if (!descriptor)
158
+ return { ok: false, reason: "invalid_environment" };
159
+ projected.AST_H03_FIXTURE = JSON.stringify(descriptor);
160
+ }
161
+ const lifecycleFixture = environment.AST_H05_FIXTURE;
162
+ if (lifecycleFixture !== undefined) {
163
+ const descriptor = parseH05FixtureDescriptor(lifecycleFixture);
164
+ if (!descriptor)
165
+ return { ok: false, reason: "invalid_environment" };
166
+ projected.AST_H05_FIXTURE = JSON.stringify(descriptor);
167
+ }
91
168
  const policy = parseRuntimePolicy(environment);
92
169
  Object.assign(projected, {
93
170
  AST_MAX_PROJECT_SESSIONS: String(policy.maxProjectSessions),
@@ -95,6 +172,10 @@ export function createCompilerWorkerSpawnSpec(workerEntryPath, environment) {
95
172
  AST_QUEUE_WAIT_TIMEOUT_MS: String(policy.queueWaitTimeoutMs),
96
173
  AST_OPERATION_DEADLINE_MS: String(policy.operationDeadlineMs),
97
174
  AST_SHUTDOWN_DRAIN_TIMEOUT_MS: String(policy.shutdownDrainTimeoutMs),
175
+ // Forward the parent's resolved apply-guard policy so the supervised worker
176
+ // registers the same tool surface (deny-by-default fail-closed, allow opt-in).
177
+ AST_MCP_APPLY_GUARD: policy.denyApply ? "deny" : "allow",
178
+ ...(policy.projectStructuredContentAsText ? { AST_MCP_TEXT_PROJECTION: "canonical_json" } : {}),
98
179
  });
99
180
  return {
100
181
  ok: true,
@@ -54,9 +54,12 @@ export function defineToolCatalog(input) {
54
54
  apply: names((item) => item.effect === "apply"),
55
55
  }),
56
56
  directToon: names((item) => item.directOutputFormats.length === 2),
57
- registerAll(server) {
58
- for (const descriptor of descriptors)
57
+ registerAll(server, options = {}) {
58
+ for (const descriptor of descriptors) {
59
+ if (options.denyApply === true && descriptor.effect === "apply")
60
+ continue;
59
61
  descriptor.register(server);
62
+ }
60
63
  },
61
64
  });
62
65
  }
@@ -17,7 +17,7 @@ const CallSpinesInputSchema = z.object({
17
17
  max_nodes: z.number().int().min(1).max(MAX_IMPACT_NODES).default(DEFAULT_IMPACT_MAX_NODES),
18
18
  max_edges: z.number().int().min(1).max(MAX_IMPACT_EDGES).default(DEFAULT_IMPACT_MAX_EDGES),
19
19
  });
20
- const ExploreInputSchema = z
20
+ const ExploreInputObjectSchema = z
21
21
  .object({
22
22
  project_root: z
23
23
  .string()
@@ -65,7 +65,8 @@ const ExploreInputSchema = z
65
65
  .default(EXPLORE_DEFAULT_OMISSION_DETAIL_LIMIT)
66
66
  .describe("Maximum deterministic omission detail records; exact counts are always retained."),
67
67
  })
68
- .refine((input) => Boolean(input.query || input.file_path), {
68
+ .strip();
69
+ const ExploreInputSchema = ExploreInputObjectSchema.refine((input) => Boolean(input.query || input.file_path), {
69
70
  message: "Provide query, file_path, or both file_path and symbol_path.",
70
71
  path: ["query"],
71
72
  })
@@ -204,7 +205,7 @@ export function registerExplore(server) {
204
205
  server.registerTool(TOOL_NAME, {
205
206
  title: "Explore project context",
206
207
  description: "Composes bounded structural search, exact selectors, source evidence and compiler references without weakening the primitive AST tools. Returns bounded session freshness metadata for fresh, pending, stale, rebuilding or degraded state.",
207
- inputSchema: ExploreInputSchema,
208
+ inputSchema: ExploreInputObjectSchema,
208
209
  outputSchema: ExploreOutputSchema,
209
210
  annotations: {
210
211
  readOnlyHint: true,
@@ -215,6 +216,7 @@ export function registerExplore(server) {
215
216
  }, async ({ project_root, query, file_path, symbol_path, kinds, file_filter, detail, include_source, include_references, reference_detail, reference_limit, offset, limit, max_bytes, call_spines, omission_detail_limit, }, extra) => {
216
217
  const requestContext = createRequestContext(extra.signal);
217
218
  try {
219
+ ExploreInputSchema.parse({ project_root, query, file_path, symbol_path, call_spines });
218
220
  const output = await withProject(project_root, (context, operationContext) => buildExploreContext(context, {
219
221
  query,
220
222
  filePath: file_path,
@@ -73,7 +73,6 @@ export function registerGetImpact(server) {
73
73
  title: "Get bounded compiler-backed impact",
74
74
  description: "Traverses exact compiler-backed relationships around a symbol with explicit direction, depth, node and edge budgets. Returns bounded session freshness metadata and fails closed when exact relationships are not fresh. Read-only evidence only; it never prepares or applies mutations.",
75
75
  inputSchema: AstGetImpactInputSchema,
76
- outputSchema: ImpactOutputSchema,
77
76
  annotations: {
78
77
  readOnlyHint: true,
79
78
  destructiveHint: false,
@@ -2,10 +2,15 @@ import { Buffer } from "node:buffer";
2
2
  import { isDeepStrictEqual } from "node:util";
3
3
  import { decode, encode } from "@toon-format/toon";
4
4
  import { z } from "zod";
5
+ import { COMPILER_WORKER_MAX_RESULT_BYTES, fitsCompilerWorkerResponseResult, } from "../services/compiler-worker-protocol.js";
5
6
  import { createProjectIdentity } from "../services/project-status.js";
6
7
  import { renderPublicError } from "../services/public-errors.js";
7
8
  import { emitToolFailureEvent } from "../services/runtime-logger.js";
8
9
  export const MAX_TOON_RESULT_BYTES = 10 * 1024 * 1024;
10
+ // Leave room for the unchanged structured value plus JSON-RPC framing under
11
+ // the supervised worker's 256 KiB line limit.
12
+ export const MAX_TEXT_PROJECTION_BYTES = 112 * 1024;
13
+ export const MAX_PROJECTED_RESULT_BYTES = COMPILER_WORKER_MAX_RESULT_BYTES;
9
14
  export const ToolOutputFormatSchema = z.enum(["json", "toon"]).default("json");
10
15
  export const ToolOutputFormatInputSchema = {
11
16
  output_format: ToolOutputFormatSchema.describe("Result representation. TOON wraps one compact encoded value in structuredContent."),
@@ -24,6 +29,49 @@ export function createToolErrorContext(toolName, projectRoot) {
24
29
  return { toolName };
25
30
  }
26
31
  }
32
+ /**
33
+ * Add a deterministic model-visible JSON projection without replacing the
34
+ * canonical structured value. Existing content wins, and oversized values get
35
+ * an explicit bounded marker when the complete framed result has room for it;
36
+ * otherwise the unchanged structured-only result remains authoritative.
37
+ */
38
+ export function projectStructuredContentAsText(result, enabled, maxBytes = MAX_TEXT_PROJECTION_BYTES) {
39
+ if (!enabled ||
40
+ result.isError === true ||
41
+ result.content.length > 0 ||
42
+ result.structuredContent === undefined) {
43
+ return result;
44
+ }
45
+ let text;
46
+ try {
47
+ text =
48
+ JSON.stringify(result.structuredContent) ??
49
+ "(structured result is not JSON-serializable for model-visible projection)";
50
+ }
51
+ catch {
52
+ text = "(structured result is not JSON-serializable for model-visible projection)";
53
+ }
54
+ const byteLength = Buffer.byteLength(text, "utf8");
55
+ if (byteLength > maxBytes) {
56
+ text = `(structured result exceeds the ${maxBytes}-byte model-visible projection limit; canonical structuredContent remains available)`;
57
+ }
58
+ let projected = {
59
+ ...result,
60
+ content: [{ type: "text", text }],
61
+ };
62
+ if (fitsCompilerWorkerResponseResult(projected))
63
+ return projected;
64
+ projected = {
65
+ ...result,
66
+ content: [
67
+ {
68
+ type: "text",
69
+ text: `(structured result exceeds the ${MAX_PROJECTED_RESULT_BYTES}-byte complete projection limit; canonical structuredContent remains available)`,
70
+ },
71
+ ],
72
+ };
73
+ return fitsCompilerWorkerResponseResult(projected) ? projected : result;
74
+ }
27
75
  export function structuredResult(structuredContent) {
28
76
  return { content: [], structuredContent };
29
77
  }
@@ -14,11 +14,16 @@ export async function runStdioServer(options = {}) {
14
14
  prepareProjectRuntimeForStartup();
15
15
  const runtimeActivity = options.runtimeActivity ?? new RuntimeActivityTracker();
16
16
  runtimeActivity.prepareForStartup();
17
- const server = options.server ?? createServer({ runtimeActivity });
17
+ const runtimePolicy = options.runtimePolicy ?? readRuntimePolicy();
18
+ const server = options.server ??
19
+ createServer({
20
+ runtimeActivity,
21
+ denyApply: runtimePolicy.denyApply,
22
+ projectStructuredContentAsText: runtimePolicy.projectStructuredContentAsText,
23
+ });
18
24
  const transport = options.transport ?? new StdioServerTransport();
19
25
  const send = transport.send.bind(transport);
20
26
  transport.send = (message, sendOptions) => runtimeActivity.trackSend(() => send(message, sendOptions));
21
- const runtimePolicy = options.runtimePolicy ?? readRuntimePolicy();
22
27
  const installProcessHandlers = options.installProcessHandlers ?? true;
23
28
  const exit = options.exit ?? ((code) => process.exit(code));
24
29
  const protocol = server.server;
package/docs/support.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # Support policy
2
2
 
3
- This document defines the supported platform, runtime, persistence, and operational boundary for published `ast-mcp-server` v0.11.2 and the local `0.12.0` release candidate.
3
+ This document defines the supported platform, runtime, persistence, and operational boundary for published `ast-mcp-server` v0.12.0.
4
4
 
5
5
  ## Supported release target
6
6
 
7
7
  | Environment | Status | Contract |
8
8
  | ----------------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------- |
9
9
  | Linux x64 with required GNU coreutils and procfs, Node.js 22.5.0 | Historical | Immutable v0.8.1 release evidence; not the runtime floor of the published or candidate lines. |
10
- | Linux x64 with required GNU coreutils and procfs, exact Node.js 22.13.0 | Supported | Published v0.11.2 and local 0.12.0 matrices, each bound to its own package and tree bytes. |
11
- | Linux x64 with required GNU coreutils and procfs, current Node.js 24 line | Supported | Published v0.11.2 and local 0.12.0 matrices, each bound to its own package and tree bytes. |
10
+ | Linux x64 with required GNU coreutils and procfs, exact Node.js 22.13.0 | Supported | Published v0.12.0 matrix bound to its immutable package and tree bytes. |
11
+ | Linux x64 with required GNU coreutils and procfs, current Node.js 24 line | Supported | Published v0.12.0 matrix bound to its immutable package and tree bytes. |
12
12
  | Other Linux architectures or systems without the required filesystem features | Unverified | Not supported until equivalent architecture, mutation, and filesystem-publication gates pass. |
13
13
  | macOS | Unverified | Not supported until equivalent filesystem, process, package, mutation, and canary gates pass. |
14
14
  | Windows | Unverified | Not supported until equivalent filesystem, process, package, mutation, and canary gates pass. |
15
15
  | Remote, untrusted, or multi-tenant service use | Unsupported | No network authentication, sandbox, or tenant-isolation boundary is provided. |
16
16
 
17
- The local `0.12.0` release candidate requires Node.js `>=22.13.0`; its matrix targets exact Node.js 22.13.0 and the governed Node.js 24 major. Published v0.11.2 retains its immutable `>=22.13.0` metadata and exact Node.js 22.13.0/24 release evidence. The earlier v0.8.1 Node.js 22.5.0/24 matrix remains historical evidence for those bytes only. A future runtime satisfying an engine range is not automatically a verified release target.
17
+ Published v0.12.0 requires Node.js `>=22.13.0`; its immutable matrix targets exact Node.js 22.13.0 and the governed Node.js 24 major. The earlier v0.8.1 Node.js 22.5.0/24 matrix remains historical evidence for those bytes only. A future runtime satisfying an engine range is not automatically a verified release target.
18
18
 
19
19
  The checked-evidence freezer requires GNU coreutils 9.7 `mv` with `--update=none-fail`, `--no-copy`, and `--no-target-directory`. Managed setup-file mutation additionally requires that same `mv` with `--exchange`, GNU coreutils `ln -L -T`, procfs descriptor paths at `/proc/self/fd`, `O_DIRECTORY`, and `O_NOFOLLOW`. It fails closed when any verified Linux primitive is unavailable. Equivalent publication, exchange, descriptor-link, and descriptor-relative mutation semantics have not been verified on other operating systems or architectures.
20
20
 
@@ -50,7 +50,7 @@ The scoped Linux evidence passed on exact Node.js 22.13.0 and the governed Node.
50
50
 
51
51
  ## Symbol-index persistence
52
52
 
53
- Published v0.11.2 and the local `0.12.0` release candidate select native SQLite when the persistence setting is absent or explicitly `enabled`; operators requiring no persistent index state must set `disabled` explicitly:
53
+ Published v0.12.0 selects native SQLite when the persistence setting is absent or explicitly `enabled`; operators requiring no persistent index state must set `disabled` explicitly:
54
54
 
55
55
  ```bash
56
56
  AST_SYMBOL_INDEX_PERSISTENCE=disabled \
@@ -76,11 +76,11 @@ ast-tool cache inspect
76
76
  ast-tool cache clear --yes
77
77
  ```
78
78
 
79
- Both commands are bounded and path-free. Clear preflights the tree, refuses unsafe or active SQLite artifacts, rechecks identity before unlink and preserves unknown regular files/directories. There is no automatic garbage collection in this candidate.
79
+ Both commands are bounded and path-free. Clear preflights the tree, refuses unsafe or active SQLite artifacts, rechecks identity before unlink and preserves unknown regular files/directories. There is no automatic garbage collection in this release.
80
80
 
81
81
  ## Production-readiness acceptance
82
82
 
83
- The four retained Linux x64 production-readiness reports cover `ast-mcp-server` and `x-scraper` under Node.js 22.5.0 and Node.js 24 for package version 0.6.0, commit `2d0b21bbb80fae1acfca6a85d5891d87e68b59c1`, and tree `af931d49769fabdf06f623965a6cfe1f9afb8a81`. They are historical integration evidence only: they are not reattributed to v0.8.1, published-next v0.9.0 or v0.9.1, the local 0.9.2 candidate, published v0.10.0, published-next v0.11.0 or v0.11.1, published v0.11.2, or the local v0.12.0 release candidate. The exact 0.9.0 and 0.9.1 release matrices remain historical evidence for their immutable published-next bytes, the exact 0.9.2 matrix remains historical local-candidate evidence, the exact 0.10.0 matrix remains historical published-release evidence, the exact 0.11.0 and 0.11.1 matrices remain historical evidence for their immutable published-next bytes before public-registry verification exposed their distinct verifier defects, and the exact 0.11.2 matrix remains historical published-release evidence. A separate exact 0.12.0 release matrix is the release-candidate gate for current repository bytes under both supported runtime lines, including bounded diagnostic aggregates, catalog-derived tool capability projections, and their independent release oracles; none of these matrices rebinds the older retained reports. MCP-PROD-404 remains normative for admission:
83
+ The four retained Linux x64 production-readiness reports cover `ast-mcp-server` and `x-scraper` under Node.js 22.5.0 and Node.js 24 for package version 0.6.0, commit `2d0b21bbb80fae1acfca6a85d5891d87e68b59c1`, and tree `af931d49769fabdf06f623965a6cfe1f9afb8a81`. They are historical integration evidence only: they are not reattributed to v0.8.1, published-next v0.9.0 or v0.9.1, the local 0.9.2 candidate, published v0.10.0, published-next v0.11.0 or v0.11.1, published v0.11.2, or published v0.12.0. The exact 0.9.0 and 0.9.1 release matrices remain historical evidence for their immutable published-next bytes, the exact 0.9.2 matrix remains historical local-candidate evidence, the exact 0.10.0 matrix remains historical published-release evidence, the exact 0.11.0 and 0.11.1 matrices remain historical evidence for their immutable published-next bytes before public-registry verification exposed their distinct verifier defects, and the exact 0.11.2 matrix remains historical published-release evidence. The exact 0.12.0 matrix is current published-release evidence under both supported runtime lines, including bounded diagnostic aggregates, catalog-derived tool capability projections, and their independent release oracles; none of these matrices rebinds the older retained reports. MCP-PROD-404 remains normative for admission:
84
84
 
85
85
  - zero semantic mismatches across disabled, cold, warm, restart, and rollback reads;
86
86
  - byte-identical real-repository status and worktree trees;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ast-mcp-server",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "Structural code MCP server and batch CLI for compact TypeScript/JavaScript reads and hash-bound AST edits.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -26,6 +26,22 @@
26
26
  },
27
27
  "type": "module",
28
28
  "packageManager": "yarn@4.15.0",
29
+ "dsh": {
30
+ "bundle": {
31
+ "patch": "./cordis.patch.yml"
32
+ }
33
+ },
34
+ "deepseekHarness": {
35
+ "revision": "cd5ef8148158c3a752a658978873241fdf8e2bbc",
36
+ "tag": "dsh-v0.1.2-alpha.1",
37
+ "mcpClientVersion": "0.1.2-alpha.1",
38
+ "timeoutBudget": {
39
+ "queueWaitMs": 30000,
40
+ "executionDeadlineMs": 120000,
41
+ "marginMs": 15000,
42
+ "outerToolCallMs": 180000
43
+ }
44
+ },
29
45
  "main": "dist/index.js",
30
46
  "bin": {
31
47
  "ast-mcp-server": "dist/index.js",
@@ -34,6 +50,7 @@
34
50
  "files": [
35
51
  "dist",
36
52
  "skills",
53
+ "cordis.patch.yml",
37
54
  "README.md",
38
55
  "CHANGELOG.md",
39
56
  "SECURITY.md",
@@ -56,6 +73,7 @@
56
73
  "test:cli": "yarn build && node scripts/cli-smoke.mjs",
57
74
  "test:errors": "yarn build && node scripts/public-error-smoke.mjs",
58
75
  "test:package": "node scripts/package-smoke.mjs",
76
+ "test:dsh-adapter": "node scripts/dsh-adapter-smoke.mjs",
59
77
  "test:local-registry": "node scripts/local-registry-consumer-smoke.mjs",
60
78
  "test:installed-agents": "yarn build && node scripts/installed-agent-guidance-smoke.mjs",
61
79
  "test:agent-fixtures": "node scripts/admit-agent-fixtures.mjs --check",
@@ -95,7 +113,8 @@
95
113
  "prettier": "^3.9.6",
96
114
  "typescript": "^5.6.0",
97
115
  "typescript-eslint": "^8.65.0",
98
- "vitest": "^4.1.10"
116
+ "vitest": "^4.1.10",
117
+ "yaml": "^2.9.0"
99
118
  },
100
- "gitHead": "3991d0a74e672c6c4d3fbd1c8bbb1a60009515ec"
119
+ "gitHead": "27b80a3da169b473a3b5c5dfea69ed52903ed4c7"
101
120
  }
@@ -18,7 +18,7 @@ Cargar este skill antes de navegar semánticamente, analizar impacto o referenci
18
18
 
19
19
  No forzar un roundtrip AST para Markdown, configuración, comentarios ni una edición textual trivial en un archivo ya conocido. Si las tools `ast_*` no están disponibles, declarar el fallback y no presentar búsquedas textuales como evidencia compiler-backed.
20
20
 
21
- The local 0.12.0 release candidate requires Node.js `>=22.13.0` and is verified with exact Node.js 22.13.0 plus the governed Node.js 24 line. Published v0.11.2 retains its immutable Node.js 22.13.0/24 release evidence.
21
+ Published v0.12.0 requires Node.js `>=22.13.0` and retains immutable release evidence from exact Node.js 22.13.0 plus the governed Node.js 24 line.
22
22
 
23
23
  ## Hard Rules
24
24
 
@@ -6,7 +6,7 @@
6
6
  "files": [
7
7
  {
8
8
  "path": "SKILL.md",
9
- "sha256": "d0048ffd9a585d00791540c6fa5e0bec91ff95b1448479678f85702e6b09be8a"
9
+ "sha256": "df2ebc3f3903cf5abf4eb6612da527cad97a92f29f1a9a475ea6e8b4cf47abfb"
10
10
  },
11
11
  {
12
12
  "path": "references/operations.md",
@@ -94,6 +94,11 @@
94
94
  "version": "4.5.0",
95
95
  "sha256": "18132b4b747d135e4ccfbca9e2190a9afb41e144cc06c31c5e6bc0f1571e11da",
96
96
  "npm_versions": ["0.11.2"]
97
+ },
98
+ {
99
+ "version": "4.6.0",
100
+ "sha256": "d0048ffd9a585d00791540c6fa5e0bec91ff95b1448479678f85702e6b09be8a",
101
+ "npm_versions": ["0.12.0"]
97
102
  }
98
103
  ]
99
104
  }