speclock 5.2.5 → 5.3.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/README.md +144 -24
- package/package.json +242 -67
- package/src/cli/index.js +137 -7
- package/src/core/auth.js +341 -341
- package/src/core/compliance.js +1 -1
- package/src/core/engine.js +63 -1
- package/src/core/lock-author.js +487 -487
- package/src/core/replay.js +236 -0
- package/src/core/rules-sync.js +548 -0
- package/src/core/semantics.js +33 -0
- package/src/core/templates.js +69 -0
- package/src/dashboard/index.html +2 -2
- package/src/mcp/http-server.js +3 -3
- package/src/mcp/server.js +130 -1
package/src/mcp/http-server.js
CHANGED
|
@@ -113,7 +113,7 @@ import { fileURLToPath } from "url";
|
|
|
113
113
|
import _path from "path";
|
|
114
114
|
|
|
115
115
|
const PROJECT_ROOT = process.env.SPECLOCK_PROJECT_ROOT || process.cwd();
|
|
116
|
-
const VERSION = "5.
|
|
116
|
+
const VERSION = "5.3.0";
|
|
117
117
|
const AUTHOR = "Sandeep Roy";
|
|
118
118
|
const START_TIME = Date.now();
|
|
119
119
|
|
|
@@ -901,8 +901,8 @@ app.get("/", (req, res) => {
|
|
|
901
901
|
name: "speclock",
|
|
902
902
|
version: VERSION,
|
|
903
903
|
author: AUTHOR,
|
|
904
|
-
description: "AI Constraint Engine — AI Patch Firewall. Patch Gateway (ALLOW/WARN/BLOCK verdicts), diff-native review (interface breaks, protected symbols, dependency drift, schema changes, API impact). Spec Compiler (NL→constraints), Code Graph (blast radius, lock-to-file mapping), Typed constraints, REST API v2, Python SDK + ROS2 integration. Policy-as-Code, RBAC, AES-256-GCM encryption, HMAC audit chain, SOC 2/HIPAA compliance.
|
|
905
|
-
tools:
|
|
904
|
+
description: "AI Constraint Engine — Universal Rules Sync + AI Patch Firewall. Syncs constraints to Cursor, Claude Code, Copilot, Windsurf, Gemini, Aider, AGENTS.md. Patch Gateway (ALLOW/WARN/BLOCK verdicts), diff-native review (interface breaks, protected symbols, dependency drift, schema changes, API impact). Spec Compiler (NL→constraints), Code Graph (blast radius, lock-to-file mapping), Typed constraints, REST API v2, Python SDK + ROS2 integration. Policy-as-Code, RBAC, AES-256-GCM encryption, HMAC audit chain, SOC 2/HIPAA compliance. 46 MCP tools. 929 tests, 100% accuracy.",
|
|
905
|
+
tools: 46,
|
|
906
906
|
mcp_endpoint: "/mcp",
|
|
907
907
|
health_endpoint: "/health",
|
|
908
908
|
npm: "https://www.npmjs.com/package/speclock",
|
package/src/mcp/server.js
CHANGED
|
@@ -65,6 +65,8 @@ import {
|
|
|
65
65
|
parseUnifiedDiff,
|
|
66
66
|
} from "../core/engine.js";
|
|
67
67
|
import { generateContext, generateContextPack } from "../core/context.js";
|
|
68
|
+
import { syncRules, getSyncFormats } from "../core/rules-sync.js";
|
|
69
|
+
import { getReplay, listSessions, formatReplay } from "../core/replay.js";
|
|
68
70
|
import {
|
|
69
71
|
readBrain,
|
|
70
72
|
readEvents,
|
|
@@ -120,7 +122,7 @@ const PROJECT_ROOT =
|
|
|
120
122
|
args.project || process.env.SPECLOCK_PROJECT_ROOT || process.cwd();
|
|
121
123
|
|
|
122
124
|
// --- MCP Server ---
|
|
123
|
-
const VERSION = "5.
|
|
125
|
+
const VERSION = "5.3.0";
|
|
124
126
|
const AUTHOR = "Sandeep Roy";
|
|
125
127
|
|
|
126
128
|
const server = new McpServer(
|
|
@@ -1895,6 +1897,133 @@ server.tool(
|
|
|
1895
1897
|
}
|
|
1896
1898
|
);
|
|
1897
1899
|
|
|
1900
|
+
// --- Universal Rules Sync (v5.3) ---
|
|
1901
|
+
|
|
1902
|
+
// Tool 36: speclock_sync_rules
|
|
1903
|
+
server.tool(
|
|
1904
|
+
"speclock_sync_rules",
|
|
1905
|
+
"Sync SpecLock constraints to AI tool rules files. Generates .cursorrules, CLAUDE.md, AGENTS.md, .windsurfrules, copilot-instructions.md, GEMINI.md, and .aider.conf.yml from your SpecLock constraints. One source of truth for all AI tools. Use --format for a specific tool, or sync all at once.",
|
|
1906
|
+
{
|
|
1907
|
+
format: z.enum(["cursor", "claude", "agents", "windsurf", "copilot", "gemini", "codex", "aider", "all"]).optional().default("all").describe("Target format. 'all' syncs to every supported AI tool."),
|
|
1908
|
+
dryRun: z.boolean().optional().default(false).describe("Preview output without writing files"),
|
|
1909
|
+
append: z.boolean().optional().default(false).describe("Append to existing CLAUDE.md instead of overwriting (only for claude format)"),
|
|
1910
|
+
},
|
|
1911
|
+
async ({ format, dryRun, append }) => {
|
|
1912
|
+
const options = { dryRun };
|
|
1913
|
+
if (format && format !== "all") options.format = format;
|
|
1914
|
+
if (append) options.append = true;
|
|
1915
|
+
|
|
1916
|
+
const result = syncRules(PROJECT_ROOT, options);
|
|
1917
|
+
|
|
1918
|
+
if (result.errors.length > 0 && result.synced.length === 0) {
|
|
1919
|
+
return { content: [{ type: "text", text: `Sync failed: ${result.errors.join(", ")}` }], isError: true };
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
const lines = [
|
|
1923
|
+
`## Rules Sync ${dryRun ? "(Preview)" : "Complete"}`,
|
|
1924
|
+
``,
|
|
1925
|
+
`Constraints synced: ${result.lockCount} lock(s), ${result.decisionCount || 0} decision(s)`,
|
|
1926
|
+
``,
|
|
1927
|
+
];
|
|
1928
|
+
|
|
1929
|
+
for (const s of result.synced) {
|
|
1930
|
+
if (dryRun && s.content) {
|
|
1931
|
+
lines.push(`### ${s.name} → ${s.file}`);
|
|
1932
|
+
lines.push("```");
|
|
1933
|
+
lines.push(s.content);
|
|
1934
|
+
lines.push("```");
|
|
1935
|
+
lines.push("");
|
|
1936
|
+
} else {
|
|
1937
|
+
lines.push(`- **${s.name}** → \`${s.file}\` (${s.size} bytes)`);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
if (!dryRun && result.synced.length > 0) {
|
|
1942
|
+
lines.push(``, `${result.synced.length} file(s) written. Your AI tools will now see SpecLock constraints.`);
|
|
1943
|
+
lines.push(``, `Tip: Commit these files to git so they're always in sync.`);
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
if (result.errors.length > 0) {
|
|
1947
|
+
lines.push(``, `Warnings: ${result.errors.join(", ")}`);
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1951
|
+
}
|
|
1952
|
+
);
|
|
1953
|
+
|
|
1954
|
+
// Tool 37: speclock_replay
|
|
1955
|
+
server.tool(
|
|
1956
|
+
"speclock_replay",
|
|
1957
|
+
"Replay a session's activity log — shows exactly what AI agents tried and what SpecLock caught. Returns chronological event list with ALLOW/WARN/BLOCK verdicts, changes logged, locks added/removed, and session stats. Like a flight recorder for your AI coding sessions.",
|
|
1958
|
+
{
|
|
1959
|
+
sessionId: z.string().optional().describe("Specific session ID to replay. Omit to replay most recent session."),
|
|
1960
|
+
limit: z.number().optional().default(50).describe("Max events to return"),
|
|
1961
|
+
},
|
|
1962
|
+
async ({ sessionId, limit }) => {
|
|
1963
|
+
const replay = getReplay(PROJECT_ROOT, { sessionId, limit });
|
|
1964
|
+
|
|
1965
|
+
if (!replay.found) {
|
|
1966
|
+
return { content: [{ type: "text", text: replay.error }], isError: true };
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
const formatted = formatReplay(replay);
|
|
1970
|
+
return { content: [{ type: "text", text: `## Incident Replay\n\n\`\`\`\n${formatted}\n\`\`\`` }] };
|
|
1971
|
+
}
|
|
1972
|
+
);
|
|
1973
|
+
|
|
1974
|
+
// Tool 38: speclock_list_sessions
|
|
1975
|
+
server.tool(
|
|
1976
|
+
"speclock_list_sessions",
|
|
1977
|
+
"List available sessions for replay. Shows session IDs, tools used, timestamps, and event counts.",
|
|
1978
|
+
{
|
|
1979
|
+
limit: z.number().optional().default(10).describe("Max sessions to list"),
|
|
1980
|
+
},
|
|
1981
|
+
async ({ limit }) => {
|
|
1982
|
+
const result = listSessions(PROJECT_ROOT, limit);
|
|
1983
|
+
|
|
1984
|
+
if (result.sessions.length === 0) {
|
|
1985
|
+
return { content: [{ type: "text", text: "No sessions recorded yet." }] };
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
const lines = [`## Sessions (${result.total} total)`, ""];
|
|
1989
|
+
for (const s of result.sessions) {
|
|
1990
|
+
const current = s.isCurrent ? " **[ACTIVE]**" : "";
|
|
1991
|
+
lines.push(`- **${s.id}** — ${s.tool} — ${s.startedAt.substring(0, 16)} — ${s.events} events${current}`);
|
|
1992
|
+
if (s.summary && s.summary !== "(no summary)") {
|
|
1993
|
+
lines.push(` _${s.summary.substring(0, 80)}_`);
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
lines.push("", "Use `speclock_replay` with a session ID to see full activity log.");
|
|
1997
|
+
|
|
1998
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1999
|
+
}
|
|
2000
|
+
);
|
|
2001
|
+
|
|
2002
|
+
// Tool 39: speclock_list_sync_formats
|
|
2003
|
+
server.tool(
|
|
2004
|
+
"speclock_list_sync_formats",
|
|
2005
|
+
"List all available AI tool formats that SpecLock can sync constraints to. Shows format key, tool name, output file path, and description.",
|
|
2006
|
+
{},
|
|
2007
|
+
async () => {
|
|
2008
|
+
const formats = getSyncFormats();
|
|
2009
|
+
const lines = [
|
|
2010
|
+
`## Available Sync Formats`,
|
|
2011
|
+
``,
|
|
2012
|
+
`| Format | Tool | Output File | Description |`,
|
|
2013
|
+
`|--------|------|-------------|-------------|`,
|
|
2014
|
+
];
|
|
2015
|
+
|
|
2016
|
+
for (const f of formats) {
|
|
2017
|
+
lines.push(`| ${f.key} | ${f.name} | \`${f.file}\` | ${f.description} |`);
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
lines.push(``);
|
|
2021
|
+
lines.push(`Use \`speclock_sync_rules\` with a specific format or "all" to sync.`);
|
|
2022
|
+
|
|
2023
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
2024
|
+
}
|
|
2025
|
+
);
|
|
2026
|
+
|
|
1898
2027
|
// --- Smithery sandbox export ---
|
|
1899
2028
|
export default function createSandboxServer() {
|
|
1900
2029
|
return server;
|