soturail 0.2.2 → 0.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.
Files changed (76) hide show
  1. package/README.md +55 -10
  2. package/dist/cli.js +11 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/bench.d.ts +1 -1
  5. package/dist/commands/bench.js +126 -2
  6. package/dist/commands/bench.js.map +1 -1
  7. package/dist/commands/context.d.ts +2 -0
  8. package/dist/commands/context.js +27 -0
  9. package/dist/commands/context.js.map +1 -0
  10. package/dist/commands/hooks.d.ts +3 -0
  11. package/dist/commands/hooks.js +32 -8
  12. package/dist/commands/hooks.js.map +1 -1
  13. package/dist/commands/mcp.d.ts +2 -0
  14. package/dist/commands/mcp.js +21 -0
  15. package/dist/commands/mcp.js.map +1 -0
  16. package/dist/commands/memory.d.ts +1 -0
  17. package/dist/commands/memory.js +2 -1
  18. package/dist/commands/memory.js.map +1 -1
  19. package/dist/commands/release.d.ts +3 -0
  20. package/dist/commands/release.js +227 -0
  21. package/dist/commands/release.js.map +1 -0
  22. package/dist/commands/skills.d.ts +2 -0
  23. package/dist/commands/skills.js +43 -0
  24. package/dist/commands/skills.js.map +1 -0
  25. package/dist/core/config.d.ts +5 -0
  26. package/dist/core/config.js +12 -2
  27. package/dist/core/config.js.map +1 -1
  28. package/dist/core/context-pack.d.ts +13 -0
  29. package/dist/core/context-pack.js +102 -0
  30. package/dist/core/context-pack.js.map +1 -0
  31. package/dist/core/mcp-resources.d.ts +13 -0
  32. package/dist/core/mcp-resources.js +46 -0
  33. package/dist/core/mcp-resources.js.map +1 -0
  34. package/dist/core/mcp-server.d.ts +14 -0
  35. package/dist/core/mcp-server.js +81 -0
  36. package/dist/core/mcp-server.js.map +1 -0
  37. package/dist/core/mcp-tools.d.ts +7 -0
  38. package/dist/core/mcp-tools.js +73 -0
  39. package/dist/core/mcp-tools.js.map +1 -0
  40. package/dist/core/release-preflight.d.ts +22 -0
  41. package/dist/core/release-preflight.js +201 -0
  42. package/dist/core/release-preflight.js.map +1 -0
  43. package/dist/core/skill-exporter.d.ts +3 -0
  44. package/dist/core/skill-exporter.js +72 -0
  45. package/dist/core/skill-exporter.js.map +1 -0
  46. package/dist/core/skill-schema.d.ts +55 -0
  47. package/dist/core/skill-schema.js +84 -0
  48. package/dist/core/skill-schema.js.map +1 -0
  49. package/dist/core/skill-store.d.ts +4 -0
  50. package/dist/core/skill-store.js +92 -0
  51. package/dist/core/skill-store.js.map +1 -0
  52. package/dist/core/skill-validator.d.ts +12 -0
  53. package/dist/core/skill-validator.js +94 -0
  54. package/dist/core/skill-validator.js.map +1 -0
  55. package/dist/core/version.d.ts +1 -0
  56. package/dist/core/version.js +3 -0
  57. package/dist/core/version.js.map +1 -0
  58. package/docs/benchmarking.md +6 -1
  59. package/docs/comparisons.md +35 -0
  60. package/docs/context-packs.md +29 -0
  61. package/docs/examples/skills/README.md +11 -0
  62. package/docs/hooks/claude.md +6 -4
  63. package/docs/hooks/codex.md +4 -3
  64. package/docs/hooks/cursor.md +4 -3
  65. package/docs/hooks/gemini.md +4 -3
  66. package/docs/hooks/mcp.md +10 -0
  67. package/docs/hooks.md +12 -16
  68. package/docs/mcp.md +18 -0
  69. package/docs/release-checklist.md +44 -1
  70. package/docs/release-workflow.md +41 -18
  71. package/docs/security-model.md +6 -0
  72. package/docs/skill-rail.md +14 -20
  73. package/docs/usage.md +15 -0
  74. package/docs/windows.md +22 -1
  75. package/docs/workflow-rail.md +1 -1
  76. package/package.json +8 -6
@@ -0,0 +1,102 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { ensureWorkspace, getWorkspacePaths, loadConfig, readJsonl } from "./config.js";
4
+ import { getCurrentGitCommit } from "./git.js";
5
+ import { readSkills } from "./skill-store.js";
6
+ export async function buildContextPack(target, root = process.cwd(), options = {}) {
7
+ await ensureWorkspace(root);
8
+ const paths = getWorkspacePaths(root);
9
+ const now = options.now ?? new Date().toISOString();
10
+ const sections = [
11
+ ["Static SotuRail Header", staticHeader(target)],
12
+ ["Governance Files Summary", await governanceSummary(root)],
13
+ ["Project Config", JSON.stringify(await loadConfig(root), null, 2)],
14
+ ["Repo Map Summary", await readOptional(path.join(paths.indexesDir, "repo-map.json"), "No repo map found. Run soturail index.")],
15
+ ["Approved Rules", await readOptional(paths.rulesFile, "No approved rules found.")],
16
+ ["Approved Specs", await approvedSpecs(root)],
17
+ ["Approved Memory", await approvedMemory(root)],
18
+ ["Skills Summary", await skillsSummary(root)]
19
+ ];
20
+ const stable = sections.map(([title, content]) => `## ${title}\n\n${content.trim()}\n`).join("\n");
21
+ const dynamic = [
22
+ "<!-- soturail:dynamic-footer -->",
23
+ "## Dynamic Footer",
24
+ "",
25
+ `generated_at: ${now}`,
26
+ `git_commit: ${await getCurrentGitCommit(root) ?? "unknown"}`,
27
+ "raw_ids: dynamic; expand only when compressed summaries are insufficient",
28
+ "last_commands: dynamic local session state is intentionally kept after stable blocks",
29
+ ""
30
+ ].join("\n");
31
+ const payload = `${stable}\n${dynamic}`;
32
+ const filePath = path.join(paths.contextDir, `${target}-context.md`);
33
+ await fs.mkdir(paths.contextDir, { recursive: true });
34
+ await fs.writeFile(filePath, payload, "utf8");
35
+ return { target, path: filePath, payload, stablePrefix: stable };
36
+ }
37
+ export async function contextDoctor(root = process.cwd()) {
38
+ await ensureWorkspace(root);
39
+ const paths = getWorkspacePaths(root);
40
+ const existing = await fs.readdir(paths.contextDir).catch(() => []);
41
+ return [
42
+ "SotuRail context doctor",
43
+ "stable_order: header, governance, config, repo_map, approved_rules, approved_specs, approved_memory, skills, dynamic_footer",
44
+ `context_dir: ${path.normalize(path.relative(root, paths.contextDir))}`,
45
+ `existing_packs: ${existing.length}`
46
+ ].join("\n") + "\n";
47
+ }
48
+ export function explainContextPacks() {
49
+ return [
50
+ "SotuRail context packs keep stable content before dynamic session data.",
51
+ "Order: static header -> governance -> config -> repo map -> approved rules -> approved specs -> approved memory -> skills -> dynamic footer.",
52
+ "Timestamps, raw_ids, recent command status and transient logs stay in the dynamic footer."
53
+ ].join("\n") + "\n";
54
+ }
55
+ async function governanceSummary(root) {
56
+ const files = ["AGENTS.md", "CLAUDE.md", "GEMINI.md", "README.md"];
57
+ const lines = [];
58
+ for (const file of files) {
59
+ const text = await readOptional(path.join(root, file), "");
60
+ if (text)
61
+ lines.push(`### ${file}\n\n${text.split(/\r?\n/).slice(0, 20).join("\n")}`);
62
+ }
63
+ return lines.join("\n\n") || "No governance files found.";
64
+ }
65
+ async function approvedSpecs(root) {
66
+ const paths = getWorkspacePaths(root);
67
+ const out = [];
68
+ const entries = await fs.readdir(paths.specsDir).catch(() => []);
69
+ for (const entry of entries) {
70
+ const spec = await readOptional(path.join(paths.specsDir, entry, "spec.md"), "");
71
+ if (spec)
72
+ out.push(`### ${entry}\n\n${spec.slice(0, 4000)}`);
73
+ }
74
+ return out.join("\n\n") || "No approved specs found.";
75
+ }
76
+ async function approvedMemory(root) {
77
+ const paths = getWorkspacePaths(root);
78
+ const approved = await readJsonl(paths.memoryApprovedFile);
79
+ const legacy = (await readJsonl(paths.memoryFile)).filter((item) => item.approved);
80
+ const records = [...approved, ...legacy];
81
+ return records.length > 0
82
+ ? records.map((item) => `- ${item.id ?? "legacy"}: ${item.text ?? item.content ?? ""}`).join("\n")
83
+ : "No approved memory found.";
84
+ }
85
+ async function skillsSummary(root) {
86
+ const skills = await readSkills(root);
87
+ return skills.length > 0
88
+ ? skills.map((skill) => `- ${skill.metadata.id}: ${skill.metadata.description} [${skill.metadata.risk_level}]`).join("\n")
89
+ : "No skills found.";
90
+ }
91
+ async function readOptional(filePath, fallback) {
92
+ return fs.readFile(filePath, "utf8").catch(() => fallback);
93
+ }
94
+ function staticHeader(target) {
95
+ return [
96
+ "SotuRail context pack.",
97
+ `target: ${target}`,
98
+ "Local-first, cache-friendly, stable project context appears before dynamic session data.",
99
+ "Do not claim provider cache hits unless provider metadata is explicitly imported."
100
+ ].join("\n");
101
+ }
102
+ //# sourceMappingURL=context-pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-pack.js","sourceRoot":"","sources":["../../src/core/context-pack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface McpResourceInfo {
2
+ uri: string;
3
+ name: string;
4
+ mimeType: string;
5
+ description: string;
6
+ }
7
+ export declare const mcpResources: McpResourceInfo[];
8
+ export declare function listMcpResources(): Promise<McpResourceInfo[]>;
9
+ export declare function readMcpResource(uri: string, root?: string): Promise<{
10
+ uri: string;
11
+ mimeType: string;
12
+ text: string;
13
+ }>;
@@ -0,0 +1,46 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { getWorkspacePaths, readJsonl } from "./config.js";
4
+ export const mcpResources = [
5
+ { uri: "soturail://repo-map", name: "Heuristic Repo Map", mimeType: "application/json", description: "Stable repository map generated by soturail index." },
6
+ { uri: "soturail://tree", name: "Repository Tree", mimeType: "text/plain", description: "Stable tree output generated by soturail index." },
7
+ { uri: "soturail://rules", name: "Rules", mimeType: "text/yaml", description: "Extracted local rules." },
8
+ { uri: "soturail://approved-memory", name: "Approved Memory", mimeType: "application/jsonl", description: "Approved local memory records." },
9
+ { uri: "soturail://self-report", name: "Self Dogfood Report", mimeType: "text/markdown", description: "Latest self-dogfooding report." },
10
+ { uri: "soturail://benchmarks/latest", name: "Latest Benchmarks", mimeType: "application/json", description: "Latest benchmark JSON results." },
11
+ { uri: "soturail://roadmap", name: "Roadmap", mimeType: "text/markdown", description: "Project roadmap." }
12
+ ];
13
+ export async function listMcpResources() {
14
+ return mcpResources;
15
+ }
16
+ export async function readMcpResource(uri, root = process.cwd()) {
17
+ const paths = getWorkspacePaths(root);
18
+ const stableFirstNotice = "SotuRail resource: stable project content first; dynamic metadata appears last when present.\n\n";
19
+ switch (uri) {
20
+ case "soturail://repo-map":
21
+ return resource(uri, "application/json", stableFirstNotice + await readOptional(path.join(paths.indexesDir, "repo-map.json"), "{}"));
22
+ case "soturail://tree":
23
+ return resource(uri, "text/plain", stableFirstNotice + await readOptional(path.join(paths.indexesDir, "tree.txt"), "No tree found. Run soturail index."));
24
+ case "soturail://rules":
25
+ return resource(uri, "text/yaml", stableFirstNotice + await readOptional(paths.rulesFile, "No rules found."));
26
+ case "soturail://approved-memory": {
27
+ const approved = await readJsonl(paths.memoryApprovedFile);
28
+ return resource(uri, "application/jsonl", stableFirstNotice + approved.map((item) => JSON.stringify(item)).join("\n"));
29
+ }
30
+ case "soturail://self-report":
31
+ return resource(uri, "text/markdown", await readOptional(path.join(paths.workspace, "reports", "self-dogfood.md"), "No self report found."));
32
+ case "soturail://benchmarks/latest":
33
+ return resource(uri, "application/json", await readOptional(path.join(root, "benchmarks", "results", "latest.json"), "{}"));
34
+ case "soturail://roadmap":
35
+ return resource(uri, "text/markdown", await readOptional(path.join(root, "ROADMAP.md"), "No roadmap found."));
36
+ default:
37
+ throw new Error(`Unknown MCP resource: ${uri}`);
38
+ }
39
+ }
40
+ function resource(uri, mimeType, text) {
41
+ return { uri, mimeType, text };
42
+ }
43
+ async function readOptional(filePath, fallback) {
44
+ return fs.readFile(filePath, "utf8").catch(() => fallback);
45
+ }
46
+ //# sourceMappingURL=mcp-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-resources.js","sourceRoot":"","sources":["../../src/core/mcp-resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { listMcpResources } from "./mcp-resources.js";
2
+ import { listMcpTools } from "./mcp-tools.js";
3
+ export interface McpManifest {
4
+ name: string;
5
+ version: string;
6
+ protocol: string;
7
+ transports: string[];
8
+ resources: Awaited<ReturnType<typeof listMcpResources>>;
9
+ tools: ReturnType<typeof listMcpTools>;
10
+ }
11
+ export declare function mcpManifest(version: string): Promise<McpManifest>;
12
+ export declare function mcpDoctor(version: string): Promise<string>;
13
+ export declare function handleMcpMessage(message: any, root?: string, version?: string): Promise<any>;
14
+ export declare function serveMcpStdio(root?: string, version?: string): Promise<void>;
@@ -0,0 +1,81 @@
1
+ import readline from "node:readline";
2
+ import { stdin as input, stdout as output } from "node:process";
3
+ import { listMcpResources, readMcpResource } from "./mcp-resources.js";
4
+ import { callMcpTool, listMcpTools } from "./mcp-tools.js";
5
+ export async function mcpManifest(version) {
6
+ return {
7
+ name: "soturail",
8
+ version,
9
+ protocol: "json-rpc-2.0-mcp-compatible-stdio",
10
+ transports: ["stdio"],
11
+ resources: await listMcpResources(),
12
+ tools: listMcpTools()
13
+ };
14
+ }
15
+ export async function mcpDoctor(version) {
16
+ const manifest = await mcpManifest(version);
17
+ return [
18
+ "SotuRail MCP doctor",
19
+ `version: ${version}`,
20
+ `resources: ${manifest.resources.length}`,
21
+ `tools: ${manifest.tools.length}`,
22
+ "transport_stdio: available",
23
+ "arbitrary_shell_execution: disabled"
24
+ ].join("\n") + "\n";
25
+ }
26
+ export async function handleMcpMessage(message, root = process.cwd(), version = "0.0.0") {
27
+ const id = message?.id ?? null;
28
+ try {
29
+ switch (message?.method) {
30
+ case "initialize":
31
+ return rpcResult(id, {
32
+ protocolVersion: "2024-11-05",
33
+ serverInfo: { name: "soturail", version },
34
+ capabilities: { resources: {}, tools: {} }
35
+ });
36
+ case "resources/list":
37
+ return rpcResult(id, { resources: await listMcpResources() });
38
+ case "resources/read": {
39
+ const uri = message?.params?.uri;
40
+ if (typeof uri !== "string")
41
+ throw new Error("resources/read requires params.uri");
42
+ const resource = await readMcpResource(uri, root);
43
+ return rpcResult(id, { contents: [{ uri: resource.uri, mimeType: resource.mimeType, text: resource.text }] });
44
+ }
45
+ case "tools/list":
46
+ return rpcResult(id, { tools: listMcpTools().map((tool) => ({ name: tool.name, description: tool.description, inputSchema: { type: "object" } })) });
47
+ case "tools/call": {
48
+ const name = message?.params?.name;
49
+ if (typeof name !== "string")
50
+ throw new Error("tools/call requires params.name");
51
+ const text = await callMcpTool(name, message?.params?.arguments ?? {}, root);
52
+ return rpcResult(id, { content: [{ type: "text", text }] });
53
+ }
54
+ default:
55
+ throw new Error(`Unsupported MCP method: ${String(message?.method)}`);
56
+ }
57
+ }
58
+ catch (error) {
59
+ return { jsonrpc: "2.0", id, error: { code: -32000, message: error instanceof Error ? error.message : String(error) } };
60
+ }
61
+ }
62
+ export async function serveMcpStdio(root = process.cwd(), version = "0.0.0") {
63
+ const rl = readline.createInterface({ input });
64
+ for await (const line of rl) {
65
+ if (!line.trim())
66
+ continue;
67
+ let message;
68
+ try {
69
+ message = JSON.parse(line);
70
+ }
71
+ catch {
72
+ output.write(`${JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } })}\n`);
73
+ continue;
74
+ }
75
+ output.write(`${JSON.stringify(await handleMcpMessage(message, root, version))}\n`);
76
+ }
77
+ }
78
+ function rpcResult(id, result) {
79
+ return { jsonrpc: "2.0", id, result };
80
+ }
81
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/core/mcp-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface McpToolInfo {
2
+ name: string;
3
+ description: string;
4
+ }
5
+ export declare const mcpTools: McpToolInfo[];
6
+ export declare function callMcpTool(name: string, args?: Record<string, unknown>, root?: string): Promise<string>;
7
+ export declare function listMcpTools(): McpToolInfo[];
@@ -0,0 +1,73 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { reduceAgentResponse } from "../compressors/agent-response-reducer.js";
4
+ import { expandRawLog } from "../commands/expand.js";
5
+ import { readCommand } from "../commands/read.js";
6
+ import { checkRules } from "../commands/rules.js";
7
+ import { runIndex } from "../commands/index.js";
8
+ import { buildContextPack } from "./context-pack.js";
9
+ import { MetricsStore } from "./metrics-store.js";
10
+ import { readSkills, renderSkillList } from "./skill-store.js";
11
+ export const mcpTools = [
12
+ { name: "soturail.index", description: "Run the heuristic repository indexer." },
13
+ { name: "soturail.read", description: "Read a file progressively." },
14
+ { name: "soturail.format", description: "Compress agent response text deterministically." },
15
+ { name: "soturail.rules.check", description: "Run local rule validators." },
16
+ { name: "soturail.skills.list", description: "List local Skill Rail skills." },
17
+ { name: "soturail.context.pack", description: "Build a cache-friendly context pack." },
18
+ { name: "soturail.expand", description: "Expand a raw log with redaction unless allow_raw=true." }
19
+ ];
20
+ export async function callMcpTool(name, args = {}, root = process.cwd()) {
21
+ switch (name) {
22
+ case "soturail.index":
23
+ return runIndex(root);
24
+ case "soturail.read": {
25
+ const file = requiredString(args.file, "file");
26
+ const query = stringArg(args.query);
27
+ return readCommand(file, query ? { query, full: args.full === true } : { full: args.full === true }, root);
28
+ }
29
+ case "soturail.format": {
30
+ const text = typeof args.text === "string"
31
+ ? args.text
32
+ : await fs.readFile(path.resolve(root, requiredString(args.file, "file")), "utf8");
33
+ const mode = stringArg(args.mode) ?? "concise";
34
+ return reduceAgentResponse(text, mode).output;
35
+ }
36
+ case "soturail.rules.check":
37
+ return checkRules(root);
38
+ case "soturail.skills.list":
39
+ return renderSkillList(await readSkills(root));
40
+ case "soturail.context.pack": {
41
+ const target = (stringArg(args.target) ?? "generic");
42
+ const pack = await buildContextPack(target, root);
43
+ return `Context pack written: ${path.normalize(path.relative(root, pack.path))}\n`;
44
+ }
45
+ case "soturail.expand": {
46
+ const rawId = requiredString(args.raw_id, "raw_id");
47
+ const allowRaw = args.allow_raw === true;
48
+ const raw = (await expandRawLog(rawId, root)).toString("utf8");
49
+ await new MetricsStore(root).append({ type: "expand", raw_id: rawId, details: { source: "mcp", allow_raw: allowRaw } });
50
+ return allowRaw ? raw : redactSecrets(raw);
51
+ }
52
+ default:
53
+ throw new Error(`Unknown MCP tool: ${name}`);
54
+ }
55
+ }
56
+ export function listMcpTools() {
57
+ return mcpTools;
58
+ }
59
+ function requiredString(value, name) {
60
+ if (typeof value !== "string" || value.length === 0)
61
+ throw new Error(`Missing required argument: ${name}`);
62
+ return value;
63
+ }
64
+ function stringArg(value) {
65
+ return typeof value === "string" ? value : undefined;
66
+ }
67
+ function redactSecrets(text) {
68
+ return text
69
+ .replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-[REDACTED]")
70
+ .replace(/AKIA[0-9A-Z]{16}/g, "AKIA[REDACTED]")
71
+ .replace(/(password|api[_-]?key|secret)\s*[:=]\s*["']?[^"'\s]+/gi, "$1=[REDACTED]");
72
+ }
73
+ //# sourceMappingURL=mcp-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../../src/core/mcp-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface ReleaseGateResult {
2
+ id: string;
3
+ label: string;
4
+ ok: boolean;
5
+ required: boolean;
6
+ details: string;
7
+ }
8
+ export interface ReleasePreflightResult {
9
+ ok: boolean;
10
+ version: string | null;
11
+ packageName: string | null;
12
+ fullAuditDevOnly: boolean;
13
+ fullAuditFindings: string[];
14
+ gates: ReleaseGateResult[];
15
+ }
16
+ export interface ReleasePreflightOptions {
17
+ runAudit?: boolean;
18
+ runPack?: boolean;
19
+ cliCommand?: string[];
20
+ }
21
+ export declare function runReleasePreflight(root?: string, options?: ReleasePreflightOptions): Promise<ReleasePreflightResult>;
22
+ export declare function formatReleasePreflight(result: ReleasePreflightResult): string;
@@ -0,0 +1,201 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { promises as fs } from "node:fs";
4
+ import path from "node:path";
5
+ const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
6
+ export async function runReleasePreflight(root = process.cwd(), options = {}) {
7
+ const resolvedRoot = path.resolve(root);
8
+ const runAudit = options.runAudit ?? true;
9
+ const runPack = options.runPack ?? true;
10
+ const gates = [];
11
+ const packageJson = await readOptionalJson(path.join(resolvedRoot, "package.json"));
12
+ const packageName = typeof packageJson?.name === "string" ? packageJson.name : null;
13
+ const version = typeof packageJson?.version === "string" ? packageJson.version : null;
14
+ addGate(gates, "package_version", "package.json version", Boolean(version && SEMVER_PATTERN.test(version)), version ?? "missing");
15
+ const packageLock = await readOptionalJson(path.join(resolvedRoot, "package-lock.json"));
16
+ const lockVersion = typeof packageLock?.version === "string" ? packageLock.version : null;
17
+ const lockRootVersion = packageLock && typeof packageLock === "object"
18
+ && "packages" in packageLock
19
+ && packageLock.packages
20
+ && typeof packageLock.packages === "object"
21
+ && "" in packageLock.packages
22
+ && packageLock.packages[""]
23
+ && typeof packageLock.packages[""] === "object"
24
+ && "version" in packageLock.packages[""]
25
+ && typeof packageLock.packages[""].version === "string"
26
+ ? packageLock.packages[""].version
27
+ : null;
28
+ addGate(gates, "package_lock_version", "package-lock version sync", Boolean(version && lockVersion === version && lockRootVersion === version), `package-lock.version=${lockVersion ?? "missing"}, packages[\"\"].version=${lockRootVersion ?? "missing"}`);
29
+ const cliVersion = await readCliVersion(resolvedRoot, options.cliCommand);
30
+ addGate(gates, "cli_version", "CLI runtime version sync", Boolean(version && cliVersion.code === 0 && cliVersion.stdout.trim() === version), cliVersion.code === 0 ? `cli=${cliVersion.stdout.trim() || "empty"}, package=${version ?? "missing"}` : cliVersion.stderr.trim());
31
+ if (runPack) {
32
+ const pack = await runProcess("npm", ["pack", "--dry-run"], resolvedRoot, true);
33
+ const combined = `${pack.stdout}\n${pack.stderr}`;
34
+ const expectedTarball = packageName && version ? `${packageName}-${version}.tgz` : null;
35
+ addGate(gates, "npm_pack_metadata", "npm pack metadata", Boolean(pack.code === 0 && expectedTarball && combined.includes(expectedTarball)), expectedTarball ? `expected ${expectedTarball}` : "missing package name or version");
36
+ addGate(gates, "npm_pack_no_raw_logs", "npm pack excludes raw logs", !combined.includes(".soturail/raw") && !combined.includes("benchmarks/results/latest.json"), "pack output must not include .soturail/raw or generated benchmark JSON");
37
+ }
38
+ else {
39
+ addGate(gates, "npm_pack_metadata", "npm pack metadata", true, "skipped by test options", false);
40
+ addGate(gates, "npm_pack_no_raw_logs", "npm pack excludes raw logs", true, "skipped by test options", false);
41
+ }
42
+ const readme = await readOptionalText(path.join(resolvedRoot, "README.md"));
43
+ addGate(gates, "readme_install", "README install instructions", Boolean(readme && /npx\s+soturail/.test(readme) && readme.includes("npm install -g soturail") && readme.includes("soturail --version")), readme ? "README.md contains npm/npx/global install guidance" : "README.md missing");
44
+ const changelog = await readOptionalText(path.join(resolvedRoot, "CHANGELOG.md"));
45
+ addGate(gates, "changelog_entry", "CHANGELOG version entry", Boolean(version && changelog?.includes(`## [${version}]`)), version ? `expected ## [${version}]` : "missing version");
46
+ const releaseNotesPath = version ? path.join(resolvedRoot, `RELEASE_NOTES_v${version}.md`) : "";
47
+ addGate(gates, "release_notes", "release notes file", Boolean(version && existsSync(releaseNotesPath)), version ? path.relative(resolvedRoot, releaseNotesPath) : "missing version");
48
+ addGate(gates, "license", "LICENSE file", existsSync(path.join(resolvedRoot, "LICENSE")), "LICENSE");
49
+ let fullAudit = { total: 0, names: [] };
50
+ let runtimeAudit = { total: 0, names: [] };
51
+ if (runAudit) {
52
+ const runtime = await runProcess("npm", ["audit", "--omit=dev", "--json"], resolvedRoot, true);
53
+ runtimeAudit = parseAudit(runtime.stdout);
54
+ addGate(gates, "runtime_audit", "runtime npm audit", runtime.code === 0 && runtimeAudit.total === 0, runtimeAudit.total === 0 ? "0 runtime vulnerabilities" : `${runtimeAudit.total} runtime findings: ${runtimeAudit.names.join(", ")}`);
55
+ const full = await runProcess("npm", ["audit", "--json"], resolvedRoot, true);
56
+ fullAudit = parseAudit(full.stdout);
57
+ }
58
+ else {
59
+ addGate(gates, "runtime_audit", "runtime npm audit", true, "skipped by test options", false);
60
+ }
61
+ const fullAuditDevOnly = fullAudit.total === 0 || (runtimeAudit.total === 0 && fullAudit.total >= runtimeAudit.total);
62
+ addGate(gates, "full_audit_explained", "full npm audit explanation", fullAuditDevOnly, fullAudit.total === 0
63
+ ? "0 full audit findings"
64
+ : `${fullAudit.total} full audit findings treated as dev-only: ${fullAudit.names.join(", ")}`);
65
+ return {
66
+ ok: gates.every((gate) => !gate.required || gate.ok),
67
+ version,
68
+ packageName,
69
+ fullAuditDevOnly,
70
+ fullAuditFindings: fullAudit.names,
71
+ gates
72
+ };
73
+ }
74
+ export function formatReleasePreflight(result) {
75
+ const lines = [
76
+ `Release preflight: ${result.ok ? "passed" : "failed"}`,
77
+ `package: ${result.packageName ?? "unknown"}`,
78
+ `version: ${result.version ?? "unknown"}`,
79
+ `full_audit_dev_only: ${result.fullAuditDevOnly}`,
80
+ "gates:"
81
+ ];
82
+ for (const gate of result.gates) {
83
+ lines.push(`- ${gate.ok ? "PASS" : "FAIL"} ${gate.id}: ${gate.details}`);
84
+ }
85
+ return lines.join("\n");
86
+ }
87
+ async function readCliVersion(root, cliCommand) {
88
+ if (cliCommand && cliCommand.length > 0) {
89
+ const command = cliCommand[0];
90
+ const args = cliCommand.slice(1);
91
+ if (!command)
92
+ return { code: 1, stdout: "", stderr: "empty CLI command" };
93
+ return runProcess(command, args, root, true);
94
+ }
95
+ const cliPath = path.join(root, "dist", "cli.js");
96
+ if (!existsSync(cliPath)) {
97
+ return { code: 1, stdout: "", stderr: "dist/cli.js is missing; run npm run build first" };
98
+ }
99
+ return runProcess(process.execPath, [cliPath, "--version"], root, true);
100
+ }
101
+ async function readOptionalText(filePath) {
102
+ try {
103
+ return await fs.readFile(filePath, "utf8");
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ async function readOptionalJson(filePath) {
110
+ const text = await readOptionalText(filePath);
111
+ if (!text)
112
+ return null;
113
+ try {
114
+ return JSON.parse(text);
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ function addGate(gates, id, label, ok, details, required = true) {
121
+ gates.push({ id, label, ok, details, required });
122
+ }
123
+ function parseAudit(text) {
124
+ try {
125
+ const parsed = JSON.parse(text);
126
+ return {
127
+ total: parsed.metadata?.vulnerabilities?.total ?? 0,
128
+ names: Object.keys(parsed.vulnerabilities ?? {})
129
+ };
130
+ }
131
+ catch {
132
+ return { total: -1, names: [] };
133
+ }
134
+ }
135
+ async function runProcess(command, args, cwd, allowFailure = false) {
136
+ return new Promise((resolve, reject) => {
137
+ const spawnSpec = resolveSpawn(command, args);
138
+ const child = spawn(spawnSpec.command, spawnSpec.args, {
139
+ cwd,
140
+ shell: false,
141
+ windowsHide: true,
142
+ env: process.env
143
+ });
144
+ let stdout = "";
145
+ let stderr = "";
146
+ child.stdout?.on("data", (chunk) => {
147
+ stdout += chunk.toString();
148
+ });
149
+ child.stderr?.on("data", (chunk) => {
150
+ stderr += chunk.toString();
151
+ });
152
+ child.on("error", reject);
153
+ child.on("close", (code) => {
154
+ const result = { code: code ?? 1, stdout, stderr };
155
+ if ((code ?? 1) !== 0 && !allowFailure) {
156
+ reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code ?? 1}`));
157
+ }
158
+ else {
159
+ resolve(result);
160
+ }
161
+ });
162
+ });
163
+ }
164
+ function resolveSpawn(command, args) {
165
+ if (process.platform !== "win32")
166
+ return { command, args };
167
+ if (command === "npm" || command === "npx") {
168
+ const cli = npmCliPath(command);
169
+ if (cli)
170
+ return { command: process.execPath, args: [cli, ...args] };
171
+ }
172
+ if (command === "node")
173
+ return { command: process.execPath, args };
174
+ return { command: resolveWindowsCommand(command), args };
175
+ }
176
+ function npmCliPath(command) {
177
+ const npmExecPath = process.env.npm_execpath;
178
+ const candidates = [];
179
+ if (npmExecPath) {
180
+ const dir = path.dirname(npmExecPath);
181
+ candidates.push(path.resolve(dir, command === "npm" ? "npm-cli.js" : "npx-cli.js"));
182
+ }
183
+ const nodeDir = path.dirname(process.execPath);
184
+ candidates.push(path.resolve(nodeDir, "node_modules", "npm", "bin", command === "npm" ? "npm-cli.js" : "npx-cli.js"));
185
+ return candidates.find((candidate) => existsSync(candidate));
186
+ }
187
+ function resolveWindowsCommand(command) {
188
+ if (path.isAbsolute(command) && existsSync(command))
189
+ return command;
190
+ const extensions = path.extname(command) ? [""] : [".exe", ".cmd", ".bat", ""];
191
+ const entries = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
192
+ for (const entry of entries) {
193
+ for (const extension of extensions) {
194
+ const candidate = path.resolve(entry, `${command}${extension}`);
195
+ if (existsSync(candidate))
196
+ return candidate;
197
+ }
198
+ }
199
+ return command;
200
+ }
201
+ //# sourceMappingURL=release-preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-preflight.js","sourceRoot":"","sources":["../../src/core/release-preflight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type SkillTarget } from "./skill-schema.js";
2
+ export declare function exportSkills(target: SkillTarget, root?: string): Promise<string>;
3
+ export declare function packSkills(format: "json" | "markdown", root?: string): Promise<string>;