Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/gittensory-miner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ This completes the read-only AMS MCP tool surface (status, portfolio, claims, ev
}
```

`gittensory` exposes ORB's hosted contributor-workflow tools (issue ranking, PR packet prep, decision packs). `gittensory-miner` exposes AMS's own local state-visibility tools listed above (portfolio dashboard, claims, audit feed, run state, plans) — a fully separate, 100% local tool surface with no shared code or network calls between the two.
`gittensory` exposes ORB's hosted contributor-workflow tools (issue ranking, PR packet prep, decision packs). `gittensory-miner` exposes AMS's own local state-visibility tools listed above (portfolio dashboard, claims, audit feed, run state, plans) — a fully separate, 100% local tool surface with no shared code or network calls between the two. Both follow the same `gittensory_*` tool-naming convention (`gittensory_...` vs. `gittensory_miner_...`), but back onto different stores: ORB's tools read the hosted gittensory backend, AMS's tools read this machine's own local SQLite files (see [Local storage](#local-storage)) — a handful of AMS tools even name the ORB tool they mirror (e.g. `gittensory_miner_get_run_state` is the read-only analog of `gittensory_get_automation_state`) so the relationship is explicit at the point of use, not just here.

## Version check

Expand Down
1 change: 1 addition & 0 deletions packages/gittensory-miner/docs/coding-agent-driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,4 @@ between loop cycles -- an after-the-fact, cross-cycle total, not the per-iterati
- [`env-reference.md`](env-reference.md) — env vars including ledger path overrides.
- [`../DEPLOYMENT.md`](../DEPLOYMENT.md) — laptop vs fleet deployment and state directory layout.
- [`miner-goal-spec.md`](miner-goal-spec.md) — per-repo `.gittensory-miner.yml` targeting policy.
- [`../README.md#mcp-server`](../README.md#mcp-server) — the `gittensory-miner-mcp` read-only tool surface for querying this driver's resolved status (provider, model env-var name, CLI presence) and the rest of AMS's local state over MCP.
55 changes: 55 additions & 0 deletions test/unit/miner-mcp-tool-docs-parity.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";

const MCP_BIN_PATH = join(process.cwd(), "packages/gittensory-miner/bin/gittensory-miner-mcp.js");
const README_PATH = join(process.cwd(), "packages/gittensory-miner/README.md");
const CODING_AGENT_DRIVER_DOC_PATH = join(process.cwd(), "packages/gittensory-miner/docs/coding-agent-driver.md");

/** Every `server.registerTool("gittensory_miner_...", ...)` name in the real MCP bin -- the source of truth
* this test pins the README's "MCP server" section against, so the two can never silently drift (#5162). */
function registeredMinerMcpToolNames(): string[] {
const source = readFileSync(MCP_BIN_PATH, "utf8");
const names = [...source.matchAll(/server\.registerTool\(\s*\n?\s*"(gittensory_miner_\w+)"/g)]
.map((m) => m[1])
.filter((name): name is string => name !== undefined);
expect(names.length).toBeGreaterThan(0);
return names;
}

describe("miner MCP tool documentation parity (#5162)", () => {
it("documents every registered tool in the README, and documents nothing else", () => {
const registered = registeredMinerMcpToolNames();
const readme = readFileSync(README_PATH, "utf8");
const mcpSection = readme.slice(readme.indexOf("## MCP server"), readme.indexOf("## Version check"));

for (const name of registered) {
expect(mcpSection).toContain(`\`${name}\``);
}

const documented = [...mcpSection.matchAll(/`(gittensory_miner_\w+)`/g)]
.map((m) => m[1])
.filter((name): name is string => name !== undefined);
for (const name of documented) {
expect(registered).toContain(name);
}
});

it("documents the excluded-column safety property for the ledger/governor tools", () => {
const readme = readFileSync(README_PATH, "utf8");
const mcpSection = readme.slice(readme.indexOf("## MCP server"), readme.indexOf("## Version check"));
expect(mcpSection).toContain("payload_json");
});

it("relates AMS's local MCP tools to the hosted gittensory-mcp tools", () => {
const readme = readFileSync(README_PATH, "utf8");
const mcpSection = readme.slice(readme.indexOf("## MCP server"), readme.indexOf("## Version check"));
expect(mcpSection).toContain("local SQLite");
expect(mcpSection).toContain("hosted");
});

it("is cross-referenced from the coding-agent-driver doc", () => {
const doc = readFileSync(CODING_AGENT_DRIVER_DOC_PATH, "utf8");
expect(doc).toContain("../README.md#mcp-server");
});
});