soturail 0.2.2 → 0.2.3
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 +14 -2
- package/dist/cli.js +4 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/release.d.ts +3 -0
- package/dist/commands/release.js +59 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/core/release-preflight.d.ts +22 -0
- package/dist/core/release-preflight.js +199 -0
- package/dist/core/release-preflight.js.map +1 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/version.js +3 -0
- package/dist/core/version.js.map +1 -0
- package/docs/release-checklist.md +41 -1
- package/docs/release-workflow.md +31 -1
- package/docs/skill-rail.md +1 -1
- package/docs/windows.md +22 -1
- package/docs/workflow-rail.md +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -57,6 +57,17 @@ npm run release:full -- --version X.Y.Z
|
|
|
57
57
|
|
|
58
58
|
The release script never runs `npm audit fix --force`, never publishes when build/tests/runtime audit fail and never creates a GitHub release before npm publish succeeds. See [docs/release-workflow.md](docs/release-workflow.md).
|
|
59
59
|
|
|
60
|
+
## Release Reliability
|
|
61
|
+
|
|
62
|
+
SotuRail includes a release preflight check to prevent stale package metadata, broken npm CLI binaries, missing release notes, and changelog/version mismatches.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm run build
|
|
66
|
+
npm test
|
|
67
|
+
npm run release:check
|
|
68
|
+
npm pack --dry-run
|
|
69
|
+
```
|
|
70
|
+
|
|
60
71
|
## 2. Why SotuRail Exists
|
|
61
72
|
|
|
62
73
|
AI coding agents often receive too much unstable context: full files, noisy test logs, repeated terminal output and long conversational summaries. SotuRail is designed to unify those workflows into one independent local-first tool without sending telemetry or inventing provider metrics.
|
|
@@ -88,7 +99,7 @@ Use directly with npx:
|
|
|
88
99
|
|
|
89
100
|
```bash
|
|
90
101
|
npx soturail --help
|
|
91
|
-
npx soturail@0.2.
|
|
102
|
+
npx soturail@0.2.3 --help
|
|
92
103
|
```
|
|
93
104
|
|
|
94
105
|
Install globally:
|
|
@@ -96,6 +107,7 @@ Install globally:
|
|
|
96
107
|
```bash
|
|
97
108
|
npm install -g soturail
|
|
98
109
|
soturail --help
|
|
110
|
+
soturail --version
|
|
99
111
|
```
|
|
100
112
|
|
|
101
113
|
For local development from source:
|
|
@@ -255,7 +267,7 @@ Windows users should see [docs/windows.md](docs/windows.md) for CMD vs PowerShel
|
|
|
255
267
|
|
|
256
268
|
## Road To Skill Rail
|
|
257
269
|
|
|
258
|
-
Skill Rail and Workflow Rail are planned, not implemented in v0.2.
|
|
270
|
+
Skill Rail and Workflow Rail are planned, not implemented in v0.2.x. See [docs/skill-rail.md](docs/skill-rail.md) and [docs/workflow-rail.md](docs/workflow-rail.md) for the security-first roadmap.
|
|
259
271
|
|
|
260
272
|
## Comparison Philosophy
|
|
261
273
|
|
package/dist/cli.js
CHANGED
|
@@ -19,12 +19,14 @@ import { registerRulesCommand } from "./commands/rules.js";
|
|
|
19
19
|
import { registerSelfCommand } from "./commands/self.js";
|
|
20
20
|
import { registerSpecCommand } from "./commands/spec.js";
|
|
21
21
|
import { registerStatsCommand } from "./commands/stats.js";
|
|
22
|
+
import { registerReleaseCommand } from "./commands/release.js";
|
|
23
|
+
import { SOTURAIL_VERSION } from "./core/version.js";
|
|
22
24
|
export function buildProgram() {
|
|
23
25
|
const program = new Command();
|
|
24
26
|
program
|
|
25
27
|
.name("soturail")
|
|
26
28
|
.description("Local-first Context OS rails for AI coding agents.")
|
|
27
|
-
.version(
|
|
29
|
+
.version(SOTURAIL_VERSION)
|
|
28
30
|
.showHelpAfterError();
|
|
29
31
|
registerInitCommand(program);
|
|
30
32
|
registerIndexCommand(program);
|
|
@@ -40,6 +42,7 @@ export function buildProgram() {
|
|
|
40
42
|
registerMemoryCommand(program);
|
|
41
43
|
registerNativeCommand(program);
|
|
42
44
|
registerRulesCommand(program);
|
|
45
|
+
registerReleaseCommand(program);
|
|
43
46
|
registerSelfCommand(program);
|
|
44
47
|
registerDoctorCommand(program);
|
|
45
48
|
registerStatsCommand(program);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { formatReleasePreflight, runReleasePreflight } from "../core/release-preflight.js";
|
|
4
|
+
export function registerReleaseCommand(program) {
|
|
5
|
+
const release = program
|
|
6
|
+
.command("release")
|
|
7
|
+
.description("Run local release reliability checks and release-note helpers.");
|
|
8
|
+
release
|
|
9
|
+
.command("check")
|
|
10
|
+
.description("Validate package, CLI, changelog, release notes, pack metadata and runtime audit.")
|
|
11
|
+
.action(async () => {
|
|
12
|
+
const result = await runReleasePreflight(process.cwd());
|
|
13
|
+
process.stdout.write(`${formatReleasePreflight(result)}\n`);
|
|
14
|
+
if (!result.ok)
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
});
|
|
17
|
+
release
|
|
18
|
+
.command("notes")
|
|
19
|
+
.description("Create a release notes skeleton for a version.")
|
|
20
|
+
.requiredOption("--version <version>", "Release version, for example X.Y.Z")
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
const filePath = await writeReleaseNotesSkeleton(options.version, process.cwd());
|
|
23
|
+
process.stdout.write(`Release notes written: ${path.relative(process.cwd(), filePath)}\n`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export async function writeReleaseNotesSkeleton(version, root = process.cwd()) {
|
|
27
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
28
|
+
throw new Error(`Invalid version: ${version}`);
|
|
29
|
+
}
|
|
30
|
+
const filePath = path.join(path.resolve(root), `RELEASE_NOTES_v${version}.md`);
|
|
31
|
+
const contents = `# SotuRail v${version} - Release Notes
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
npx soturail@${version} --help
|
|
36
|
+
npm install -g soturail
|
|
37
|
+
soturail --help
|
|
38
|
+
|
|
39
|
+
## Highlights
|
|
40
|
+
|
|
41
|
+
- Update this section before publishing.
|
|
42
|
+
|
|
43
|
+
## Validation
|
|
44
|
+
|
|
45
|
+
- \`npm run build\`
|
|
46
|
+
- \`npm test\`
|
|
47
|
+
- \`npm audit --omit=dev\`
|
|
48
|
+
- \`npm pack --dry-run\`
|
|
49
|
+
- \`node dist/cli.js --version\`
|
|
50
|
+
|
|
51
|
+
## Links
|
|
52
|
+
|
|
53
|
+
- npm: https://www.npmjs.com/package/soturail
|
|
54
|
+
- GitHub: https://github.com/Soturine/soturail
|
|
55
|
+
`;
|
|
56
|
+
await fs.writeFile(filePath, contents, "utf8");
|
|
57
|
+
return filePath;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=release.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release.js","sourceRoot":"","sources":["../../src/commands/release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAE3F,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,gEAAgE,CAAC,CAAC;IAEjF,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,mFAAmF,CAAC;SAChG,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,cAAc,CAAC,qBAAqB,EAAE,oCAAoC,CAAC;SAC3E,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,QAAQ,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7F,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,OAAe,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACnF,IAAI,CAAC,qCAAqC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,kBAAkB,OAAO,KAAK,CAAC,CAAC;IAC/E,MAAM,QAAQ,GAAG,eAAe,OAAO;;;;mBAItB,OAAO;;;;;;;;;;;;;;;;;;;;CAoBzB,CAAC;IACA,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -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,199 @@
|
|
|
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
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
addGate(gates, "npm_pack_metadata", "npm pack metadata", true, "skipped by test options", false);
|
|
39
|
+
}
|
|
40
|
+
const readme = await readOptionalText(path.join(resolvedRoot, "README.md"));
|
|
41
|
+
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");
|
|
42
|
+
const changelog = await readOptionalText(path.join(resolvedRoot, "CHANGELOG.md"));
|
|
43
|
+
addGate(gates, "changelog_entry", "CHANGELOG version entry", Boolean(version && changelog?.includes(`## [${version}]`)), version ? `expected ## [${version}]` : "missing version");
|
|
44
|
+
const releaseNotesPath = version ? path.join(resolvedRoot, `RELEASE_NOTES_v${version}.md`) : "";
|
|
45
|
+
addGate(gates, "release_notes", "release notes file", Boolean(version && existsSync(releaseNotesPath)), version ? path.relative(resolvedRoot, releaseNotesPath) : "missing version");
|
|
46
|
+
addGate(gates, "license", "LICENSE file", existsSync(path.join(resolvedRoot, "LICENSE")), "LICENSE");
|
|
47
|
+
let fullAudit = { total: 0, names: [] };
|
|
48
|
+
let runtimeAudit = { total: 0, names: [] };
|
|
49
|
+
if (runAudit) {
|
|
50
|
+
const runtime = await runProcess("npm", ["audit", "--omit=dev", "--json"], resolvedRoot, true);
|
|
51
|
+
runtimeAudit = parseAudit(runtime.stdout);
|
|
52
|
+
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(", ")}`);
|
|
53
|
+
const full = await runProcess("npm", ["audit", "--json"], resolvedRoot, true);
|
|
54
|
+
fullAudit = parseAudit(full.stdout);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
addGate(gates, "runtime_audit", "runtime npm audit", true, "skipped by test options", false);
|
|
58
|
+
}
|
|
59
|
+
const fullAuditDevOnly = fullAudit.total === 0 || (runtimeAudit.total === 0 && fullAudit.total >= runtimeAudit.total);
|
|
60
|
+
addGate(gates, "full_audit_explained", "full npm audit explanation", fullAuditDevOnly, fullAudit.total === 0
|
|
61
|
+
? "0 full audit findings"
|
|
62
|
+
: `${fullAudit.total} full audit findings treated as dev-only: ${fullAudit.names.join(", ")}`);
|
|
63
|
+
return {
|
|
64
|
+
ok: gates.every((gate) => !gate.required || gate.ok),
|
|
65
|
+
version,
|
|
66
|
+
packageName,
|
|
67
|
+
fullAuditDevOnly,
|
|
68
|
+
fullAuditFindings: fullAudit.names,
|
|
69
|
+
gates
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function formatReleasePreflight(result) {
|
|
73
|
+
const lines = [
|
|
74
|
+
`Release preflight: ${result.ok ? "passed" : "failed"}`,
|
|
75
|
+
`package: ${result.packageName ?? "unknown"}`,
|
|
76
|
+
`version: ${result.version ?? "unknown"}`,
|
|
77
|
+
`full_audit_dev_only: ${result.fullAuditDevOnly}`,
|
|
78
|
+
"gates:"
|
|
79
|
+
];
|
|
80
|
+
for (const gate of result.gates) {
|
|
81
|
+
lines.push(`- ${gate.ok ? "PASS" : "FAIL"} ${gate.id}: ${gate.details}`);
|
|
82
|
+
}
|
|
83
|
+
return lines.join("\n");
|
|
84
|
+
}
|
|
85
|
+
async function readCliVersion(root, cliCommand) {
|
|
86
|
+
if (cliCommand && cliCommand.length > 0) {
|
|
87
|
+
const command = cliCommand[0];
|
|
88
|
+
const args = cliCommand.slice(1);
|
|
89
|
+
if (!command)
|
|
90
|
+
return { code: 1, stdout: "", stderr: "empty CLI command" };
|
|
91
|
+
return runProcess(command, args, root, true);
|
|
92
|
+
}
|
|
93
|
+
const cliPath = path.join(root, "dist", "cli.js");
|
|
94
|
+
if (!existsSync(cliPath)) {
|
|
95
|
+
return { code: 1, stdout: "", stderr: "dist/cli.js is missing; run npm run build first" };
|
|
96
|
+
}
|
|
97
|
+
return runProcess(process.execPath, [cliPath, "--version"], root, true);
|
|
98
|
+
}
|
|
99
|
+
async function readOptionalText(filePath) {
|
|
100
|
+
try {
|
|
101
|
+
return await fs.readFile(filePath, "utf8");
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function readOptionalJson(filePath) {
|
|
108
|
+
const text = await readOptionalText(filePath);
|
|
109
|
+
if (!text)
|
|
110
|
+
return null;
|
|
111
|
+
try {
|
|
112
|
+
return JSON.parse(text);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function addGate(gates, id, label, ok, details, required = true) {
|
|
119
|
+
gates.push({ id, label, ok, details, required });
|
|
120
|
+
}
|
|
121
|
+
function parseAudit(text) {
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(text);
|
|
124
|
+
return {
|
|
125
|
+
total: parsed.metadata?.vulnerabilities?.total ?? 0,
|
|
126
|
+
names: Object.keys(parsed.vulnerabilities ?? {})
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return { total: -1, names: [] };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function runProcess(command, args, cwd, allowFailure = false) {
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const spawnSpec = resolveSpawn(command, args);
|
|
136
|
+
const child = spawn(spawnSpec.command, spawnSpec.args, {
|
|
137
|
+
cwd,
|
|
138
|
+
shell: false,
|
|
139
|
+
windowsHide: true,
|
|
140
|
+
env: process.env
|
|
141
|
+
});
|
|
142
|
+
let stdout = "";
|
|
143
|
+
let stderr = "";
|
|
144
|
+
child.stdout?.on("data", (chunk) => {
|
|
145
|
+
stdout += chunk.toString();
|
|
146
|
+
});
|
|
147
|
+
child.stderr?.on("data", (chunk) => {
|
|
148
|
+
stderr += chunk.toString();
|
|
149
|
+
});
|
|
150
|
+
child.on("error", reject);
|
|
151
|
+
child.on("close", (code) => {
|
|
152
|
+
const result = { code: code ?? 1, stdout, stderr };
|
|
153
|
+
if ((code ?? 1) !== 0 && !allowFailure) {
|
|
154
|
+
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code ?? 1}`));
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
resolve(result);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
function resolveSpawn(command, args) {
|
|
163
|
+
if (process.platform !== "win32")
|
|
164
|
+
return { command, args };
|
|
165
|
+
if (command === "npm" || command === "npx") {
|
|
166
|
+
const cli = npmCliPath(command);
|
|
167
|
+
if (cli)
|
|
168
|
+
return { command: process.execPath, args: [cli, ...args] };
|
|
169
|
+
}
|
|
170
|
+
if (command === "node")
|
|
171
|
+
return { command: process.execPath, args };
|
|
172
|
+
return { command: resolveWindowsCommand(command), args };
|
|
173
|
+
}
|
|
174
|
+
function npmCliPath(command) {
|
|
175
|
+
const npmExecPath = process.env.npm_execpath;
|
|
176
|
+
const candidates = [];
|
|
177
|
+
if (npmExecPath) {
|
|
178
|
+
const dir = path.dirname(npmExecPath);
|
|
179
|
+
candidates.push(path.resolve(dir, command === "npm" ? "npm-cli.js" : "npx-cli.js"));
|
|
180
|
+
}
|
|
181
|
+
const nodeDir = path.dirname(process.execPath);
|
|
182
|
+
candidates.push(path.resolve(nodeDir, "node_modules", "npm", "bin", command === "npm" ? "npm-cli.js" : "npx-cli.js"));
|
|
183
|
+
return candidates.find((candidate) => existsSync(candidate));
|
|
184
|
+
}
|
|
185
|
+
function resolveWindowsCommand(command) {
|
|
186
|
+
if (path.isAbsolute(command) && existsSync(command))
|
|
187
|
+
return command;
|
|
188
|
+
const extensions = path.extname(command) ? [""] : [".exe", ".cmd", ".bat", ""];
|
|
189
|
+
const entries = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean);
|
|
190
|
+
for (const entry of entries) {
|
|
191
|
+
for (const extension of extensions) {
|
|
192
|
+
const candidate = path.resolve(entry, `${command}${extension}`);
|
|
193
|
+
if (existsSync(candidate))
|
|
194
|
+
return candidate;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return command;
|
|
198
|
+
}
|
|
199
|
+
//# 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 @@
|
|
|
1
|
+
export declare const SOTURAIL_VERSION = "0.2.3";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC"}
|
|
@@ -11,10 +11,22 @@ Before publishing:
|
|
|
11
11
|
- [ ] `node dist/cli.js self all`
|
|
12
12
|
- [ ] `npm pack --dry-run`
|
|
13
13
|
- [ ] `npm run release:check`
|
|
14
|
+
- [ ] `node dist/cli.js --version` matches `package.json`.
|
|
14
15
|
- [ ] Confirm docs mention limitations honestly.
|
|
15
16
|
- [ ] Confirm no telemetry exists.
|
|
16
17
|
- [ ] Confirm no `git push` is routed through `soturail run`.
|
|
17
18
|
|
|
19
|
+
## Version Sync
|
|
20
|
+
|
|
21
|
+
Check four separate release identifiers before publishing:
|
|
22
|
+
|
|
23
|
+
- npm package version: `package.json` and `package-lock.json`.
|
|
24
|
+
- CLI runtime version: `node dist/cli.js --version`.
|
|
25
|
+
- Git tag: created only when the release process calls for it.
|
|
26
|
+
- GitHub release: created only after npm publish succeeds.
|
|
27
|
+
|
|
28
|
+
The package version and CLI runtime version must match. `npm run build` regenerates the CLI version source from `package.json`, and `npm run release:check` verifies the built CLI before publication.
|
|
29
|
+
|
|
18
30
|
## Audit Distinction
|
|
19
31
|
|
|
20
32
|
`npm audit` checks all dependencies, including dev dependencies used for local tests and builds.
|
|
@@ -23,7 +35,35 @@ Before publishing:
|
|
|
23
35
|
|
|
24
36
|
Runtime audit is clean with `npm audit --omit=dev`. Remaining audit findings, if any, are development dependency findings and should be upgraded safely without `--force`.
|
|
25
37
|
|
|
26
|
-
For v0.2.
|
|
38
|
+
For v0.2.x, the full audit findings are in the Vitest/Vite development test stack when present. npm's suggested fix may be a semver-major Vitest upgrade, so do not run `npm audit fix --force` blindly.
|
|
39
|
+
|
|
40
|
+
## npm Login And 2FA
|
|
41
|
+
|
|
42
|
+
Use browser-based npm login before publishing:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm login --auth-type=web
|
|
46
|
+
npm whoami
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If npm requires a one-time password during publish, provide a fresh authenticator code through `NPM_CONFIG_OTP` or `--otp`. Do not commit tokens, OTPs or npm credentials.
|
|
50
|
+
|
|
51
|
+
PowerShell example:
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
$env:NPM_CONFIG_OTP="<code>"
|
|
55
|
+
npm run release:publish -- --version X.Y.Z
|
|
56
|
+
Remove-Item Env:NPM_CONFIG_OTP
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
After npm publish succeeds, verify:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm view soturail version
|
|
63
|
+
npx --yes soturail@X.Y.Z --version
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Create or update the GitHub release only after those npm checks pass.
|
|
27
67
|
|
|
28
68
|
## Windows Paste Safety
|
|
29
69
|
|
package/docs/release-workflow.md
CHANGED
|
@@ -10,6 +10,14 @@ npm run release:check
|
|
|
10
10
|
|
|
11
11
|
Runs install, build, tests, runtime audit, self-dogfooding, pack dry-run and npm version checks. It also reports whether full audit findings are development-only.
|
|
12
12
|
|
|
13
|
+
The check also verifies:
|
|
14
|
+
|
|
15
|
+
- `package.json` and `package-lock.json` version sync;
|
|
16
|
+
- `node dist/cli.js --version` matches the package version;
|
|
17
|
+
- npm pack dry-run emits the matching tarball name;
|
|
18
|
+
- `CHANGELOG.md` and `RELEASE_NOTES_vX.Y.Z.md` exist for the local version;
|
|
19
|
+
- README install instructions and `LICENSE` exist.
|
|
20
|
+
|
|
13
21
|
## Prepare
|
|
14
22
|
|
|
15
23
|
```bash
|
|
@@ -33,7 +41,22 @@ Prepare mode:
|
|
|
33
41
|
npm run release:publish -- --version X.Y.Z
|
|
34
42
|
```
|
|
35
43
|
|
|
36
|
-
Publish mode refuses to publish if build, tests or runtime audit fail, if the git tree is dirty, or if the version already exists on npm.
|
|
44
|
+
Publish mode refuses to publish if build, tests, release preflight or runtime audit fail, if the git tree is dirty, or if the version already exists on npm.
|
|
45
|
+
|
|
46
|
+
For browser-based npm login:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm login --auth-type=web
|
|
50
|
+
npm whoami
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If npm asks for 2FA during publish, use a fresh authenticator code:
|
|
54
|
+
|
|
55
|
+
```powershell
|
|
56
|
+
$env:NPM_CONFIG_OTP="<code>"
|
|
57
|
+
npm run release:publish -- --version X.Y.Z
|
|
58
|
+
Remove-Item Env:NPM_CONFIG_OTP
|
|
59
|
+
```
|
|
37
60
|
|
|
38
61
|
## Full
|
|
39
62
|
|
|
@@ -43,6 +66,13 @@ npm run release:full -- --version X.Y.Z
|
|
|
43
66
|
|
|
44
67
|
Full mode runs prepare, publish and then creates or updates the GitHub release using `gh` when available. If the npm version already exists, full mode skips npm publish and only creates or updates the GitHub release.
|
|
45
68
|
|
|
69
|
+
Only create or update the GitHub release after npm publish succeeds and these checks pass:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm view soturail version
|
|
73
|
+
npx --yes soturail@X.Y.Z --version
|
|
74
|
+
```
|
|
75
|
+
|
|
46
76
|
Safety rules:
|
|
47
77
|
|
|
48
78
|
- Never run `npm audit fix --force`.
|
package/docs/skill-rail.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Skill Rail
|
|
2
2
|
|
|
3
|
-
Skill Rail is planned for v0.3.0. It is not implemented in v0.2.
|
|
3
|
+
Skill Rail is planned for v0.3.0. It is not implemented in v0.2.x.
|
|
4
4
|
|
|
5
5
|
The goal is to turn approved SotuRail specs, rules and workflows into portable, reviewable agent skills without installing untrusted marketplace content automatically.
|
|
6
6
|
|
package/docs/windows.md
CHANGED
|
@@ -26,7 +26,7 @@ From a source checkout:
|
|
|
26
26
|
npm run build
|
|
27
27
|
npm pack --dry-run
|
|
28
28
|
npm pack
|
|
29
|
-
npm install -g .\soturail-0.2.
|
|
29
|
+
npm install -g .\soturail-0.2.3.tgz
|
|
30
30
|
soturail --version
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -74,3 +74,24 @@ npx soturail --help
|
|
|
74
74
|
## Safety
|
|
75
75
|
|
|
76
76
|
SotuRail blocks destructive command shapes through `soturail run`, including `rm -rf`, `sudo`, `del /s`, downloaded script piping and automatic `git push`.
|
|
77
|
+
|
|
78
|
+
## Release Checks On Windows
|
|
79
|
+
|
|
80
|
+
Before publishing from Windows, run:
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
npm run build
|
|
84
|
+
node .\dist\cli.js --version
|
|
85
|
+
npm run release:check
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`package.json`, `package-lock.json`, `node dist/cli.js --version`, the npm tarball name, the changelog and the release notes must all agree on the same version.
|
|
89
|
+
|
|
90
|
+
Use browser-based npm login when needed:
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
npm login --auth-type=web
|
|
94
|
+
npm whoami
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Only create the GitHub release after npm publish succeeds and `npx --yes soturail@X.Y.Z --version` prints the published version.
|
package/docs/workflow-rail.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Workflow Rail
|
|
2
2
|
|
|
3
|
-
Workflow Rail is planned for v0.4.0. It is not implemented in v0.2.
|
|
3
|
+
Workflow Rail is planned for v0.4.0. It is not implemented in v0.2.x.
|
|
4
4
|
|
|
5
5
|
The goal is to describe repeatable engineering workflows as local, auditable artifacts that can later export into Skill Rail or an MCP server.
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "soturail",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Local-first context rails for AI coding agents: reversible terminal compression, progressive repo reading, SDD workflows, hooks, benchmarks, memory and cache-friendly payloads.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"docs"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"
|
|
19
|
+
"sync:version": "node scripts/sync-version.mjs",
|
|
20
|
+
"build": "npm run sync:version && tsc -p tsconfig.json",
|
|
20
21
|
"prepack": "npm run build",
|
|
21
22
|
"test": "vitest run",
|
|
22
23
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|