ast-mcp-server 0.7.1 → 0.8.0

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.
package/CHANGELOG.md CHANGED
@@ -4,13 +4,56 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [0.7.1] — release candidate (unreleased, 2026-08-12)
7
+ ## [Unreleased]
8
+
9
+ ## [0.8.0] — release candidate (unreleased, 2026-08-14)
10
+
11
+ ### Fixed
12
+
13
+ - OpenCode effective-config discovery and verification now run against disposable routed copies because the client normalizes both configured files even for diagnostic commands; the real planned destination remains snapshot-protected.
14
+
15
+ ### Added
16
+
17
+ - Added managed `structural-code-editing` activation guidance for the verified Claude, OpenCode, Codex, and Gemini global instruction surfaces; Hermes and Copilot remain explicitly skill-only.
18
+ - Added an exact SHA-256 release manifest for safe upgrades from registry-proven skill bytes and packaged the canonical marker-free guidance payload.
19
+
20
+ ### Changed
21
+
22
+ - Setup now preflights MCP, skill, and guidance across every selected client before mutation, preserves user-owned instruction bytes, applies snapshot-checked descriptor-bound file writes, and reports schema v2 with logical outcomes plus completed, possibly committed, rolled-back, rollback-failed, pending, and successful physical asset states.
23
+ - `install-skill` uses the same official-byte manifest but remains skill-only; explicit force never bypasses guidance ownership, route, or race checks.
24
+ - Managed file writes hold staged and preimage inodes through publication, use no-clobber descriptor links for creation and atomic exchange with exact-pair rollback for replacement, reject same-inode content or mode races before cleanup, then reauthenticate unchanged/completed postimages before later asset or MCP writes.
25
+
26
+ ### Release status
27
+
28
+ - This version is bound to exact-SHA CI and the repository's staged `next` publication, public-registry verification, `latest` promotion, annotated-tag, and hosted-release sequence. npm registry and GitHub readbacks remain authoritative for those external transitions.
29
+
30
+ ## [0.7.2] — published to `latest` and `next`, registry verified (2026-08-13)
31
+
32
+ ### Fixed
33
+
34
+ - Promotion preflight now validates raw npm registry metadata exactly once, compares live integrity with the verified artifact before and after mutation, and classifies the normalized readback without reinterpreting its field schema.
35
+ - Added a composed regression covering eligible, already-promoted, and integrity-drift promotion readbacks.
36
+
37
+ ### Added
38
+
39
+ - Expanded convergent setup to Claude Code, Hermes, OpenCode, Codex CLI, Gemini CLI, and GitHub Copilot CLI with fail-closed versioned contracts.
40
+ - Added native checkbox selection, shared `.agents/skills` planning, routed JSONC-safe OpenCode configuration, bounded correlated diagnostics, and fixture admission gates.
41
+
42
+ ### Release status
43
+
44
+ - npm exposes the immutable published `0.7.2` bytes under both `latest` and `next`. The `0.8.0` section above describes distinct release bytes and cannot be attributed to that package version.
45
+
46
+ ## [0.7.1] — published to `next`, verified, not promoted (2026-08-12)
8
47
 
9
48
  ### Fixed
10
49
 
11
50
  - Public-registry verification now creates physical fake Claude Code and Hermes executables, preserving each agent identity after executable canonicalization.
12
51
  - Added a regression through the real agent detector so future consumer smokes cannot reintroduce identity-collapsing symlinks.
13
52
 
53
+ ### Release status
54
+
55
+ - The package was published under the `next` dist-tag with valid npm provenance and passed its exact-SHA public-consumer verification. Promotion was rejected before mutation because the preflight passed a normalized registry record back into the raw-record validator. It was never promoted to `latest`, tagged, or released on GitHub; `0.7.2` supersedes it.
56
+
14
57
  ## [0.7.0] — published to `next`, not promoted (2026-08-12)
15
58
 
16
59
  ### Added
package/README.md CHANGED
@@ -82,7 +82,7 @@ The included batch benchmark records a 50% reduction in model round-trips and a
82
82
 
83
83
  ## Supported environment and trust boundary
84
84
 
85
- The supported v0.7.1 target is Linux x64 with GNU coreutils `mv` supporting `--update=none-fail`, under Node.js 22.5.0 and the current Node.js 24 line. The production-readiness matrix covers both runtimes on that target; the Node 22.5 persistence canary requires `--experimental-sqlite`. Other Linux architectures or systems without the required GNU `mv`, macOS, and Windows are unverified until they pass equivalent filesystem, process, MCP/CLI/package, and mutation gates.
85
+ The package engine floor remains Node.js `>=22.5.0`. The v0.8.0 release matrix covers Linux x64 under exact Node.js 22.5.0 and the current Node.js 24 line, including managed setup-file publication. That mutation additionally requires GNU coreutils 9.7 `mv` supporting `--update=none-fail`, `--exchange`, `--no-copy`, and `--no-target-directory`, GNU coreutils `ln -L -T`, procfs descriptor paths at `/proc/self/fd`, and `O_DIRECTORY`/`O_NOFOLLOW`. Other Linux architectures or systems without those filesystem primitives, macOS, and Windows remain unverified until equivalent exact-tree gates pass.
86
86
 
87
87
  This is a local stdio server. It runs with the invoking user's filesystem permissions, and clients may request any `project_root` that user can access. It does not provide HTTP authentication, sandboxing, tenant isolation, or a remote-service security boundary. Remote, untrusted, and multi-tenant operation is unsupported.
88
88
 
@@ -134,24 +134,44 @@ From a source checkout, use the Yarn script; it builds first and then opens the
134
134
  yarn setup
135
135
  ```
136
136
 
137
- The wizard detects Claude Code and Hermes from `PATH`, shows their executable and version, selects every detected agent by default, and lets you deselect agents before confirmation. For each selected agent it:
137
+ The wizard supports exactly six CLI clients in this order: Claude Code, Hermes, OpenCode, Codex CLI, Gemini CLI, and GitHub Copilot CLI. Cursor, Windsurf, Cline, and other editor-integrated clients are intentionally excluded. Compatible detected clients start checked; unavailable or incompatible clients are disabled with a reason. Use Up/Down to move, Space to toggle, Enter to submit, or Escape/Ctrl-C to cancel.
138
138
 
139
- 1. preflights any existing `ast` MCP registration;
140
- 2. installs the bundled `structural-code-editing` skill;
141
- 3. registers this package's MCP server through the agent's official CLI;
142
- 4. reconnects and verifies the expected tools.
139
+ 1. preflights every selected client's existing `ast` MCP registration, skill destination, and effective managed-guidance destination;
140
+ 2. installs or safely upgrades the bundled `structural-code-editing` skill;
141
+ 3. adds one marker-owned activation block to each verified global instruction surface while preserving all user-owned bytes;
142
+ 4. registers this package's MCP server through the agent's official CLI;
143
+ 5. reconnects and verifies the expected tools.
143
144
 
144
- Existing matching registrations and skill files are unchanged. Conflicting MCP registrations fail before any write; remove or rename them explicitly instead of letting a setup script guess. Conflicting skill content also fails closed unless `--force-skill` is explicit.
145
+ Existing matching registrations, skill files, and managed blocks are unchanged. Conflicting MCP registrations or malformed/unknown managed guidance fail before any write; resolve them explicitly instead of letting a setup script guess. Skill upgrades are automatic only when the installed bytes match an exact SHA-256 admitted from a published npm tarball. Unknown or customized skill bytes fail closed unless `--force-skill` is explicit. That flag applies only to the skill and cannot override guidance conflicts, unsafe routes, or filesystem races.
146
+
147
+ Guidance uses each client's verified global instruction contract rather than one universal filename:
148
+
149
+ | Client | Managed guidance destination |
150
+ | -------- | --------------------------------------------------------------------------------------------------------------------- |
151
+ | Claude | `$CLAUDE_CONFIG_DIR/CLAUDE.md`, or `~/.claude/CLAUDE.md` |
152
+ | OpenCode | Effective native `AGENTS.md`; an existing Claude fallback may be shared or preserved when OpenCode has no native file |
153
+ | Codex | Non-empty `$CODEX_HOME/AGENTS.override.md`, otherwise `$CODEX_HOME/AGENTS.md`; `CODEX_HOME` defaults to `~/.codex` |
154
+ | Gemini | The one supported safe `context.fileName` from `~/.gemini/settings.json`, otherwise `~/.gemini/GEMINI.md` |
155
+ | Hermes | `skill_only`; setup does not modify `SOUL.md` or invent a global instruction destination |
156
+ | Copilot | `skill_only`; setup does not invent a personal global instruction destination |
157
+
158
+ The managed range is delimited by `ast-tool:structural-code-editing guidance v1` begin/end markers. Setup updates only that range, preserves the file's UTF-8 BOM, newline style, mode, and all content outside the range, and rejects duplicate, partial, reordered, unknown, symlinked, or non-regular destinations. Writes pin the parent chain, preimage, held temporary inode, and destination. New files use descriptor-bound no-clobber publication; replacements use an atomic same-directory exchange, validate both exchanged identities plus the pinned preimage bytes and mode, and roll the exact pair back when an in-call substitution or same-inode edit is detected. Every completed postimage is reauthenticated before later asset or MCP mutation. Cross-client setup is convergent rather than globally transactional.
159
+
160
+ Successful setup output uses schema `version: 2`. Each agent reports `mcp`, `skill`, and `guidance`; physical writes include an `asset` of `skill`, `guidance`, or `mcp_config`. A complete replay returns every applicable item as `unchanged`/`skill_only` and an empty `physical_writes` array. A failed managed publication separates `completed_writes`, `possibly_committed`, `rolled_back`, `rollback_failed`, and `pending`; an uncertain commit or failed rollback is never reported as untouched and requires inspection plus a fresh replan.
145
161
 
146
162
  For automation, make the target set and confirmation explicit:
147
163
 
148
164
  ```bash
149
165
  ast-tool setup --agents all --yes
150
- ast-tool setup --agents claude --yes
166
+ ast-tool setup --agents claude,codex --yes
151
167
  ```
152
168
 
153
169
  From a source checkout, replace `ast-tool` with `yarn setup` in those commands.
154
170
 
171
+ `--agents all` is resolved only after detection and means every detected compatible client. If any detected client has unknown or incompatible output, setup fails before writes. Explicit IDs are strict and reject unavailable clients. Non-interactive setup requires both `--agents` and `--yes`.
172
+
173
+ OpenCode 1.18.18 or newer is required. Because `opencode mcp add` ignores custom config routing, setup updates only `mcp.ast` in `OPENCODE_CONFIG`, then `OPENCODE_CONFIG_DIR/opencode.json`, then `~/.config/opencode/opencode.json`. JSONC comments, unrelated keys, and file mode are preserved. OpenCode's nominally diagnostic config command normalizes both routed config files, so setup runs discovery and verification against disposable copies while retaining the selected config bytes and fails closed if the planned real destination changes. Gemini setup may require trusting the current folder before registration. Diagnostics use a correlation ID and omit command arguments, environment, credentials, and raw provider output; setup failures may include a bounded destination path so the operator can inspect an uncertain or pending write.
174
+
155
175
  ## Install the agent skill
156
176
 
157
177
  The package bundles a `structural-code-editing` skill that teaches an agent when to use the AST tools, how to minimize context, and how to review mutations safely. Install it for both Claude Code and Hermes with one command:
@@ -169,10 +189,11 @@ ast-tool install-skill hermes
169
189
 
170
190
  The default is user scope. It writes to Claude Code's personal skill directory and to the active `HERMES_HOME`:
171
191
 
172
- | Target | Destination |
173
- | ----------- | ---------------------------------------------------------------------------------------------------------- |
174
- | Claude Code | `$CLAUDE_CONFIG_DIR/skills/structural-code-editing/SKILL.md`, or `~/.claude/skills/...` by default |
175
- | Hermes | `$HERMES_HOME/skills/software-development/structural-code-editing/SKILL.md`, or `~/.hermes/...` by default |
192
+ | Target | Destination |
193
+ | -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
194
+ | Claude Code | `$CLAUDE_CONFIG_DIR/skills/structural-code-editing/SKILL.md`, or `~/.claude/skills/...` by default |
195
+ | Hermes | `$HERMES_HOME/skills/software-development/structural-code-editing/SKILL.md`, or `~/.hermes/...` by default |
196
+ | OpenCode, Codex, Gemini, Copilot | `~/.agents/skills/structural-code-editing/SKILL.md` (one physical write, four logical outcomes) |
176
197
 
177
198
  To commit the skill into one project for Claude Code, use project scope:
178
199
 
@@ -182,7 +203,7 @@ ast-tool install-skill claude --scope project --project-root /absolute/project
182
203
 
183
204
  This writes `.claude/skills/structural-code-editing/SKILL.md` below that project. Project scope is intentionally rejected for Hermes because Hermes skills belong to a profile, not a source repository.
184
205
 
185
- Installation is idempotent. Existing identical content is left untouched; different content fails closed unless `--force` is explicit. From an unlinked source checkout, replace `ast-tool` with `yarn node /absolute/path/to/ast-mcp-server/dist/cli.js`.
206
+ Installation is idempotent. Existing current bytes are left untouched; exact predecessor bytes admitted by the bundled npm-provenance manifest are upgraded safely. Unknown or customized bytes fail closed unless `--force` is explicit. `install-skill` never writes global guidance or configures MCP. From an unlinked source checkout, replace `ast-tool` with `yarn node /absolute/path/to/ast-mcp-server/dist/cli.js`.
186
207
 
187
208
  Claude Code detects changes in an existing skill directory live; restart it if the top-level skills directory did not exist when the session started. In Hermes, run `/reload-skills` or start a new session, then verify with `hermes skills list`.
188
209
 
@@ -421,11 +442,12 @@ yarn build
421
442
  yarn test:mcp
422
443
  yarn test:cli
423
444
  yarn test:package
445
+ yarn test:installed-agents
424
446
  yarn npm audit --all --recursive
425
447
  yarn pack --dry-run
426
448
  ```
427
449
 
428
- `test:mcp` exercises the built stdio server. `test:cli` runs a read pipeline and a prepare/apply/replay workflow across separate Node processes.
450
+ `test:mcp` exercises the built stdio server. `test:cli` runs a read pipeline and a prepare/apply/replay workflow across separate Node processes. `test:installed-agents` is a host-dependent manual gate: it builds first, detects locally installed supported clients, uses only disposable homes/config roots, verifies deterministic effective discovery without model calls, reports unavailable clients, and removes the disposable state. It is not a portable CI requirement because CI does not install every external client.
429
451
 
430
452
  ## Benchmarks
431
453
 
package/SECURITY.md CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  ## Supported versions
4
4
 
5
- Security fixes are provided for the latest published minor release and the current `main` development line. During the v0.7.1 release-candidate cycle, the support window is:
5
+ Security fixes are provided for the exact version currently identified by the npm registry's `latest` dist-tag and for the current `main` development line. The support window is registry-authoritative:
6
6
 
7
- | Version | Supported |
8
- | ---------------------------------- | ---------------------------------- |
9
- | `main` / v0.7.1 release candidates | Yes |
10
- | 0.6.x | Yes, until v0.7.1 becomes `latest` |
11
- | 0.5.x and earlier | No |
7
+ | Release state | Supported |
8
+ | ------------------------------------------- | --------- |
9
+ | `main` / `Unreleased` | Yes |
10
+ | Exact npm version currently tagged `latest` | Yes |
11
+ | Earlier npm versions | No |
12
+ | Unpublished release candidates | No |
12
13
 
13
- This project supports trusted single-user local stdio use. The current v0.7.1 target supports Linux x64 only when GNU coreutils `mv` provides `--update=none-fail`, with Node.js 22.5.0 or the current Node.js 24 line. Other Linux architectures, systems without that primitive, macOS and Windows are unverified. Remote, untrusted and multi-tenant use is outside the supported security boundary.
14
+ This project supports trusted single-user local stdio use; the supported operating-system and architecture boundary remains Linux x64 only. The package engine floor is Node.js `>=22.5.0`, and the v0.8.0 release matrix covers Linux x64 under exact Node.js 22.5.0 and the current Node.js 24 line, including managed setup-file publication. That mutation requires GNU coreutils 9.7 `mv --update=none-fail --exchange --no-copy --no-target-directory`, GNU coreutils `ln -L -T`, and procfs descriptor-relative paths at `/proc/self/fd` with `O_DIRECTORY`/`O_NOFOLLOW`. Other Linux architectures and systems without those primitives are unverified, as are macOS and Windows. Remote, untrusted, and multi-tenant use is outside the supported security boundary.
14
15
 
15
16
  ## Reporting a vulnerability
16
17
 
package/dist/cli.js CHANGED
@@ -1,15 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFile } from "node:fs/promises";
3
3
  import process from "node:process";
4
- import { createInterface } from "node:readline/promises";
5
4
  import { ZodError } from "zod";
6
5
  import { BatchExecutionError, parseBatchDocument, runBatchDocument } from "./batch/runner.js";
7
6
  import { MAX_BATCH_INPUT_BYTES, isPrepareBatchTool } from "./batch/schema.js";
8
7
  import { CliOutputError, serializeCliSuccess } from "./cli-output.js";
9
8
  import { applyPersistedOperation, persistOperationPlan } from "./services/operation-plan-file.js";
10
9
  import { AgentSetupError, detectInstalledAgents, resolveServerEntryPath, runAgentSetup, } from "./services/agent-setup.js";
11
- import { installBundledSkill, resolveBundledSkillPath, } from "./services/skill-installer.js";
12
- import { parseAgentsArgument, promptForAgentSelection, } from "./services/setup-wizard.js";
10
+ import { installBundledSkill, resolveBundledSkillAssets, } from "./services/skill-installer.js";
11
+ import { parseAgentsArgument, promptForAgentSelection, resolveAgentSelection, } from "./services/setup-wizard.js";
13
12
  class CliError extends Error {
14
13
  code;
15
14
  exitCode;
@@ -241,30 +240,33 @@ export async function runCli(args) {
241
240
  const options = parseSetupArgs(commandArgs);
242
241
  try {
243
242
  const detections = await detectInstalledAgents();
244
- let agents = options.agents;
245
- if (agents === undefined) {
243
+ let agents;
244
+ if (options.agents === undefined) {
246
245
  if (process.stdin.isTTY !== true || process.stderr.isTTY !== true) {
247
246
  throw new CliError("Interactive setup requires a TTY. Use --agents claude,hermes --yes for automation.", "USAGE", 2, command);
248
247
  }
249
- const prompt = createInterface({ input: process.stdin, output: process.stderr });
250
- try {
251
- agents = await promptForAgentSelection(detections, (question) => prompt.question(question));
252
- }
253
- finally {
254
- prompt.close();
255
- }
248
+ agents = await promptForAgentSelection(detections, {
249
+ input: process.stdin,
250
+ output: process.stderr,
251
+ signals: process,
252
+ });
256
253
  if (agents.length === 0) {
257
254
  return { status: "cancelled", command: "setup", agents: [] };
258
255
  }
259
256
  }
257
+ else
258
+ agents = resolveAgentSelection(options.agents, detections);
260
259
  const executablePath = process.argv[1];
261
260
  if (!executablePath) {
262
261
  throw new Error("Cannot resolve the ast-tool executable path.");
263
262
  }
263
+ const assets = await resolveBundledSkillAssets(executablePath);
264
264
  return await runAgentSetup({
265
265
  agents,
266
266
  detections,
267
- sourceSkillPath: await resolveBundledSkillPath(executablePath),
267
+ sourceSkillPath: assets.skillPath,
268
+ sourceGuidancePath: assets.guidancePath,
269
+ releaseManifestPath: assets.releasesPath,
268
270
  serverEntryPath: await resolveServerEntryPath(executablePath),
269
271
  forceSkill: options.forceSkill,
270
272
  });
@@ -286,9 +288,11 @@ export async function runCli(args) {
286
288
  if (!executablePath) {
287
289
  throw new Error("Cannot resolve the ast-tool executable path.");
288
290
  }
291
+ const assets = await resolveBundledSkillAssets(executablePath);
289
292
  return await installBundledSkill({
290
293
  ...options,
291
- sourceSkillPath: await resolveBundledSkillPath(executablePath),
294
+ sourceSkillPath: assets.skillPath,
295
+ releaseManifestPath: assets.releasesPath,
292
296
  });
293
297
  }
294
298
  catch (error) {