soturail 0.2.1 → 0.2.2

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.
@@ -0,0 +1,323 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { PassThrough } from "node:stream";
5
+ import { promisify } from "node:util";
6
+ import { runBenchmarks, summarizeBenchmarkResults } from "../commands/bench.js";
7
+ import { executeRunCommand } from "../commands/run.js";
8
+ import { ensureWorkspace, getWorkspacePaths, loadConfig } from "./config.js";
9
+ import { scanRepository, writeRepoMap } from "./file-scanner.js";
10
+ import { getCurrentGitCommit } from "./git.js";
11
+ import { estimateTokens } from "./token-estimator.js";
12
+ const execFileAsync = promisify(execFile);
13
+ const REQUIRED_SOTURAIL_PATHS = [
14
+ "package.json",
15
+ "README.md",
16
+ "CHANGELOG.md",
17
+ "ROADMAP.md",
18
+ path.join("src", "cli.ts"),
19
+ path.join("src", "commands"),
20
+ path.join("src", "core"),
21
+ "tests",
22
+ "docs"
23
+ ];
24
+ export function createEmptySelfState() {
25
+ return { errors: [] };
26
+ }
27
+ export async function selfDoctor(root = process.cwd()) {
28
+ const resolvedRoot = path.resolve(root);
29
+ const missing = [];
30
+ for (const required of REQUIRED_SOTURAIL_PATHS) {
31
+ const absolute = path.resolve(resolvedRoot, required);
32
+ try {
33
+ await fs.access(absolute);
34
+ }
35
+ catch {
36
+ missing.push(path.normalize(required));
37
+ }
38
+ }
39
+ const packageJson = await readPackageJson(resolvedRoot);
40
+ if (packageJson.name !== "soturail") {
41
+ missing.push("package.json:name=soturail");
42
+ }
43
+ return {
44
+ ok: missing.length === 0,
45
+ root: resolvedRoot,
46
+ package_name: typeof packageJson.name === "string" ? packageJson.name : null,
47
+ package_version: typeof packageJson.version === "string" ? packageJson.version : null,
48
+ missing
49
+ };
50
+ }
51
+ export async function assertSotuRailRepository(root = process.cwd()) {
52
+ const doctor = await selfDoctor(root);
53
+ if (!doctor.ok) {
54
+ throw new Error(`This directory does not look like the SotuRail repository. Missing: ${doctor.missing.join(", ")}`);
55
+ }
56
+ return doctor;
57
+ }
58
+ export async function selfIndex(root = process.cwd()) {
59
+ await assertSotuRailRepository(root);
60
+ await ensureWorkspace(root);
61
+ const config = await loadConfig(root);
62
+ const repoMap = await scanRepository(root, config);
63
+ await writeRepoMap(root, repoMap);
64
+ return {
65
+ indexed_files_count: repoMap.total_files,
66
+ ignored_files_count: repoMap.stats.ignored_files,
67
+ ignored_directories_count: repoMap.stats.ignored_directories
68
+ };
69
+ }
70
+ export async function selfBuild(root = process.cwd(), terminalStdout, terminalStderr) {
71
+ return selfRunCommand(["npm", "run", "build"], root, terminalStdout, terminalStderr);
72
+ }
73
+ export async function selfTest(root = process.cwd(), terminalStdout, terminalStderr) {
74
+ return selfRunCommand(["npm", "test"], root, terminalStdout, terminalStderr);
75
+ }
76
+ export async function selfBench(root = process.cwd(), terminalStdout, terminalStderr) {
77
+ await assertSotuRailRepository(root);
78
+ const cliPath = path.resolve(root, "dist", "cli.js");
79
+ let runResult = null;
80
+ try {
81
+ await fs.access(cliPath);
82
+ runResult = await executeRunCommand([`"${process.execPath}" "${cliPath}" bench run --engine ts`], {
83
+ terminalStdout: terminalStdout ?? drainedStream(),
84
+ terminalStderr: terminalStderr ?? drainedStream(),
85
+ engine: "ts"
86
+ }, root);
87
+ }
88
+ catch {
89
+ // If the built CLI is unavailable, the in-process benchmark path still gives a real report.
90
+ }
91
+ const results = runResult ? await readLatestBenchmarkResults(root) : await runBenchmarks({ engine: "ts" }, root);
92
+ return {
93
+ ok: runResult ? runResult.exitCode === 0 : true,
94
+ raw_id: runResult?.rawId ?? null,
95
+ cases_count: results.length,
96
+ summary: summarizeBenchmarkResults(results),
97
+ results
98
+ };
99
+ }
100
+ export async function writeSelfReport(input) {
101
+ const root = path.resolve(input.root ?? process.cwd());
102
+ await ensureWorkspace(root);
103
+ const paths = getWorkspacePaths(root);
104
+ const reportsDir = path.resolve(paths.workspace, "reports");
105
+ await fs.mkdir(reportsDir, { recursive: true });
106
+ const reportPath = path.resolve(reportsDir, "self-dogfood.md");
107
+ const packageJson = await readPackageJson(root);
108
+ const commit = await getCurrentGitCommit(root);
109
+ const branch = await getCurrentGitBranch(root);
110
+ const accounting = selfTokenAccounting(input);
111
+ const report = [
112
+ "# SotuRail Self-Dogfood Report",
113
+ "",
114
+ "## Stable Project Description",
115
+ "",
116
+ "SotuRail aims to unify terminal compression, progressive repo reading, Spec-Driven workflows, local memory, rules extraction, agent hooks, benchmarks and cache-friendly payloads into one local-first workflow.",
117
+ "",
118
+ `- package_name: ${stringOrUnknown(packageJson.name)}`,
119
+ `- package_version: ${stringOrUnknown(packageJson.version)}`,
120
+ "- report_schema: self-dogfood-v1",
121
+ "",
122
+ "## Stable Quality Rails",
123
+ "",
124
+ "- Build, test and benchmark commands should run through SotuRail so raw logs are recoverable.",
125
+ "- Token counts are deterministic estimates unless provider metadata is explicitly imported.",
126
+ "- Dynamic raw IDs, timestamps, logs and volatile command status stay below this stable section.",
127
+ "",
128
+ "## Dynamic Execution Data",
129
+ "",
130
+ `- repository_path: ${path.normalize(root)}`,
131
+ `- current_git_commit_hash: ${commit ?? "unknown"}`,
132
+ `- current_branch: ${branch ?? "unknown"}`,
133
+ `- doctor_ok: ${input.doctor?.ok ?? false}`,
134
+ `- indexed_files_count: ${input.index?.indexed_files_count ?? 0}`,
135
+ `- ignored_files_directories_count: ${(input.index?.ignored_files_count ?? 0) + (input.index?.ignored_directories_count ?? 0)}`,
136
+ `- build_result: ${formatStep(input.build)}`,
137
+ `- test_result: ${formatStep(input.test)}`,
138
+ `- benchmark_summary: ${input.bench?.summary.replace(/\r?\n/g, " | ") ?? "not run"}`,
139
+ `- build_raw_id: ${input.build?.raw_id ?? "n/a"}`,
140
+ `- test_raw_id: ${input.test?.raw_id ?? "n/a"}`,
141
+ `- benchmark_raw_id: ${input.bench?.raw_id ?? "n/a"}`,
142
+ `- estimated_raw_tokens: ${accounting.estimated_raw_tokens}`,
143
+ `- estimated_reduced_tokens: ${accounting.estimated_reduced_tokens}`,
144
+ `- estimated_metadata_overhead_tokens: ${accounting.estimated_metadata_overhead_tokens}`,
145
+ `- compression_effective: ${accounting.compression_effective}`,
146
+ "",
147
+ "## Known Limitations",
148
+ "",
149
+ "- Native benchmark rows are marked unavailable when the optional native binary is not built.",
150
+ "- Self-dogfood reports are local evidence, not provider cache-hit evidence.",
151
+ "- Small command outputs may cost more after metadata, but recovery and audit paths remain valuable.",
152
+ "",
153
+ "## Recommended Next Action",
154
+ "",
155
+ input.errors.length > 0
156
+ ? `Review partial failures: ${input.errors.join("; ")}`
157
+ : "Keep running `soturail self all` before release-oriented commits.",
158
+ ""
159
+ ].join("\n");
160
+ await fs.writeFile(reportPath, report, "utf8");
161
+ return reportPath;
162
+ }
163
+ export async function selfAll(root = process.cwd(), terminalStdout, terminalStderr) {
164
+ const state = createEmptySelfState();
165
+ try {
166
+ state.doctor = await selfDoctor(root);
167
+ if (!state.doctor.ok) {
168
+ state.errors.push(`doctor failed: ${state.doctor.missing.join(", ")}`);
169
+ state.report_path = await writeSelfReport({ ...state, root });
170
+ return state;
171
+ }
172
+ state.index = await selfIndex(root);
173
+ state.build = await selfBuild(root, terminalStdout, terminalStderr);
174
+ if (!state.build.ok) {
175
+ state.errors.push(`build failed: raw_id=${state.build.raw_id ?? "n/a"}`);
176
+ state.report_path = await writeSelfReport({ ...state, root });
177
+ return state;
178
+ }
179
+ state.test = await selfTest(root, terminalStdout, terminalStderr);
180
+ if (!state.test.ok) {
181
+ state.errors.push(`test failed: raw_id=${state.test.raw_id ?? "n/a"}`);
182
+ state.report_path = await writeSelfReport({ ...state, root });
183
+ return state;
184
+ }
185
+ state.bench = await selfBench(root, terminalStdout, terminalStderr);
186
+ if (!state.bench.ok) {
187
+ state.errors.push(`bench failed: raw_id=${state.bench.raw_id ?? "n/a"}`);
188
+ }
189
+ }
190
+ catch (error) {
191
+ state.errors.push(error instanceof Error ? error.message : String(error));
192
+ }
193
+ state.report_path = await writeSelfReport({ ...state, root });
194
+ return state;
195
+ }
196
+ export function formatSelfDoctor(result) {
197
+ return [
198
+ "SotuRail self doctor",
199
+ `ok: ${result.ok}`,
200
+ `root: ${path.normalize(result.root)}`,
201
+ `package_name: ${result.package_name ?? "unknown"}`,
202
+ `package_version: ${result.package_version ?? "unknown"}`,
203
+ `missing: ${result.missing.length === 0 ? "none" : result.missing.join(", ")}`
204
+ ].join("\n") + "\n";
205
+ }
206
+ export function formatSelfIndex(result) {
207
+ return [
208
+ "SotuRail self index",
209
+ `indexed_files_count: ${result.indexed_files_count}`,
210
+ `ignored_files_count: ${result.ignored_files_count}`,
211
+ `ignored_directories_count: ${result.ignored_directories_count}`
212
+ ].join("\n") + "\n";
213
+ }
214
+ export function formatSelfRunStep(label, result) {
215
+ return [
216
+ `SotuRail self ${label}`,
217
+ `ok: ${result.ok}`,
218
+ `exit_code: ${result.exit_code ?? "n/a"}`,
219
+ `raw_id: ${result.raw_id ?? "n/a"}`
220
+ ].join("\n") + "\n";
221
+ }
222
+ export function formatSelfBench(result) {
223
+ return [
224
+ "SotuRail self bench",
225
+ `ok: ${result.ok}`,
226
+ `raw_id: ${result.raw_id ?? "n/a"}`,
227
+ `cases_count: ${result.cases_count}`,
228
+ result.summary
229
+ ].join("\n") + "\n";
230
+ }
231
+ function selfTokenAccounting(input) {
232
+ const estimatedRaw = (input.build?.raw_tokens ?? 0) + (input.test?.raw_tokens ?? 0);
233
+ const estimatedReduced = (input.build?.reduced_tokens ?? 0) + (input.test?.reduced_tokens ?? 0);
234
+ const metadata = estimateTokens(JSON.stringify({
235
+ doctor: input.doctor?.ok,
236
+ index: input.index,
237
+ build_raw_id: input.build?.raw_id,
238
+ test_raw_id: input.test?.raw_id,
239
+ bench_raw_id: input.bench?.raw_id
240
+ }));
241
+ return {
242
+ estimated_raw_tokens: estimatedRaw,
243
+ estimated_reduced_tokens: estimatedReduced,
244
+ estimated_metadata_overhead_tokens: metadata,
245
+ compression_effective: estimatedReduced + metadata <= estimatedRaw
246
+ };
247
+ }
248
+ async function selfRunCommand(commandParts, root, terminalStdout, terminalStderr) {
249
+ await assertSotuRailRepository(root);
250
+ try {
251
+ const result = await executeRunCommand(commandParts, {
252
+ terminalStdout: terminalStdout ?? drainedStream(),
253
+ terminalStderr: terminalStderr ?? drainedStream(),
254
+ engine: "ts"
255
+ }, root);
256
+ return {
257
+ ok: result.exitCode === 0,
258
+ exit_code: result.exitCode,
259
+ raw_id: result.rawId,
260
+ raw_tokens: result.record.raw_tokens_estimated,
261
+ reduced_tokens: result.record.compressed_tokens_estimated,
262
+ summary: result.summary
263
+ };
264
+ }
265
+ catch (error) {
266
+ return {
267
+ ok: false,
268
+ exit_code: null,
269
+ raw_id: null,
270
+ raw_tokens: 0,
271
+ reduced_tokens: 0,
272
+ summary: "",
273
+ error: error instanceof Error ? error.message : String(error)
274
+ };
275
+ }
276
+ }
277
+ async function readPackageJson(root) {
278
+ try {
279
+ return JSON.parse(await fs.readFile(path.resolve(root, "package.json"), "utf8"));
280
+ }
281
+ catch {
282
+ return {};
283
+ }
284
+ }
285
+ async function readLatestBenchmarkResults(root) {
286
+ const filePath = path.resolve(root, "benchmarks", "results", "latest.json");
287
+ try {
288
+ const parsed = JSON.parse(await fs.readFile(filePath, "utf8"));
289
+ return Array.isArray(parsed.results) ? parsed.results : [];
290
+ }
291
+ catch {
292
+ return [];
293
+ }
294
+ }
295
+ async function getCurrentGitBranch(root) {
296
+ try {
297
+ const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
298
+ cwd: root,
299
+ timeout: 3000,
300
+ windowsHide: true
301
+ });
302
+ const branch = stdout.trim();
303
+ return branch.length > 0 ? branch : null;
304
+ }
305
+ catch {
306
+ return null;
307
+ }
308
+ }
309
+ function drainedStream() {
310
+ const stream = new PassThrough();
311
+ stream.resume();
312
+ return stream;
313
+ }
314
+ function formatStep(step) {
315
+ if (!step) {
316
+ return "not run";
317
+ }
318
+ return step.ok ? `pass exit_code=${step.exit_code}` : `fail exit_code=${step.exit_code ?? "n/a"}`;
319
+ }
320
+ function stringOrUnknown(value) {
321
+ return typeof value === "string" && value.length > 0 ? value : "unknown";
322
+ }
323
+ //# sourceMappingURL=self-dogfood.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-dogfood.js","sourceRoot":"","sources":["../../src/core/self-dogfood.ts"],"names":[],"mappings":"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"}
@@ -18,9 +18,11 @@ The suite groups results as:
18
18
 
19
19
  - terminal compression;
20
20
  - agent response compression;
21
- - JSON/tool payload compression;
22
21
  - knowledge structuring;
23
- - native performance when available.
22
+ - cache stability;
23
+ - native engine availability/performance when available.
24
+
25
+ Terminal compression includes npm install noise, Vitest failures, TypeScript diagnostics, git diff/status noise and JSON/tool payload output.
24
26
 
25
27
  Knowledge-to-Rules is not judged as pure compression. It creates reusable structured rules, citations and validator metadata.
26
28
 
@@ -5,6 +5,8 @@ SotuRail v0.2.1 includes a conservative Claude Code hook template.
5
5
  ```bash
6
6
  soturail hooks install claude --dry-run
7
7
  soturail hooks install claude
8
+ soturail hooks uninstall claude
9
+ soturail hooks prompt-only claude
8
10
  ```
9
11
 
10
12
  Generated files:
@@ -19,6 +21,8 @@ The pre-tool hook inspects incoming tool payload text when Claude Code provides
19
21
 
20
22
  The hook never routes `git push` through `soturail run`.
21
23
 
24
+ Review generated settings and scripts before relying on them. SotuRail should never auto-install unreviewed third-party skills, hooks or scripts.
25
+
22
26
  ## Limitation
23
27
 
24
28
  Claude Code hook schemas may vary by installed version. SotuRail writes a conservative documented template; if your Claude Code release expects a different schema, copy the generated command into the supported hook slot manually.
@@ -3,3 +3,14 @@
3
3
  Codex prompt-only integration uses `AGENTS.md`.
4
4
 
5
5
  SotuRail does not assume private Codex host hook APIs. The fallback rules describe when to index, read progressively, run through SotuRail and avoid `git push`.
6
+
7
+ Useful commands:
8
+
9
+ ```bash
10
+ soturail hooks install codex --dry-run
11
+ soturail hooks install codex
12
+ soturail hooks uninstall codex
13
+ soturail hooks prompt-only codex
14
+ ```
15
+
16
+ Existing `AGENTS.md` content is backed up before install. Review generated prompt rules before enabling them. SotuRail should never auto-install unreviewed third-party skills, hooks or scripts.
@@ -3,3 +3,14 @@
3
3
  Cursor prompt-only integration writes `.cursor/rules/soturail.mdc` when installed.
4
4
 
5
5
  Existing files are backed up before SotuRail adds its rules.
6
+
7
+ Useful commands:
8
+
9
+ ```bash
10
+ soturail hooks install cursor --dry-run
11
+ soturail hooks install cursor
12
+ soturail hooks uninstall cursor
13
+ soturail hooks prompt-only cursor
14
+ ```
15
+
16
+ Review generated prompt rules before enabling them. SotuRail should never auto-install unreviewed third-party skills, hooks or scripts.
@@ -3,3 +3,14 @@
3
3
  Gemini prompt-only integration uses `GEMINI.md`.
4
4
 
5
5
  The generated rules keep repository scans, progressive file reads and raw log recovery visible to Gemini CLI sessions.
6
+
7
+ Useful commands:
8
+
9
+ ```bash
10
+ soturail hooks install gemini --dry-run
11
+ soturail hooks install gemini
12
+ soturail hooks uninstall gemini
13
+ soturail hooks prompt-only gemini
14
+ ```
15
+
16
+ Existing `GEMINI.md` content is backed up before install. Review generated prompt rules before enabling them. SotuRail should never auto-install unreviewed third-party skills, hooks or scripts.
package/docs/hooks.md CHANGED
@@ -6,6 +6,8 @@ SotuRail hook support is cautious. Claude gets a conservative hook template firs
6
6
  soturail hooks list
7
7
  soturail hooks doctor
8
8
  soturail hooks install claude --dry-run
9
+ soturail hooks install claude
10
+ soturail hooks uninstall claude
9
11
  soturail hooks install all --dry-run
10
12
  soturail hooks prompt-only codex
11
13
  ```
@@ -13,3 +15,12 @@ soturail hooks prompt-only codex
13
15
  Installers create backups before modifying existing files. If a host config location is uncertain, SotuRail generates prompt-only guidance instead of guessing.
14
16
 
15
17
  Claude install writes `.claude/settings.json` and hook scripts under `.claude/hooks/`. Dry-run prints every file that would change.
18
+
19
+ Always review generated hooks before enabling them. SotuRail should never auto-install unreviewed third-party skills, hooks or scripts. Prompt-only fallback remains available for every host:
20
+
21
+ ```bash
22
+ soturail hooks prompt-only claude
23
+ soturail hooks prompt-only codex
24
+ soturail hooks prompt-only gemini
25
+ soturail hooks prompt-only cursor
26
+ ```
@@ -2,12 +2,42 @@
2
2
 
3
3
  Before publishing:
4
4
 
5
+ - [ ] Confirm `npm whoami` works for the publishing account.
6
+ - [ ] Confirm npm 2FA requirements and have the authenticator ready.
5
7
  - [ ] `npm install`
6
8
  - [ ] `npm run build`
7
9
  - [ ] `npm test`
8
- - [ ] Verify `soturail --help`
9
- - [ ] Verify `soturail init` in a clean temp repo
10
- - [ ] Confirm docs mention limitations honestly
11
- - [ ] Confirm no telemetry exists
12
- - [ ] Confirm no `git push` was run automatically
13
- - [ ] Tag release manually after review
10
+ - [ ] `npm audit --omit=dev`
11
+ - [ ] `node dist/cli.js self all`
12
+ - [ ] `npm pack --dry-run`
13
+ - [ ] `npm run release:check`
14
+ - [ ] Confirm docs mention limitations honestly.
15
+ - [ ] Confirm no telemetry exists.
16
+ - [ ] Confirm no `git push` is routed through `soturail run`.
17
+
18
+ ## Audit Distinction
19
+
20
+ `npm audit` checks all dependencies, including dev dependencies used for local tests and builds.
21
+
22
+ `npm audit --omit=dev` checks runtime/public dependency risk for published package users.
23
+
24
+ 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
+
26
+ For v0.2.2, the full audit findings are in the Vitest/Vite development test stack. npm's suggested fix is a semver-major Vitest upgrade, so do not run `npm audit fix --force` blindly.
27
+
28
+ ## Windows Paste Safety
29
+
30
+ Do not paste Markdown prose or code-fence labels directly into `cmd.exe` as commands. For example, do not paste ```` ```bat ````. Copy only the command lines themselves.
31
+
32
+ See [docs/windows.md](windows.md) for CMD and PowerShell quoting notes.
33
+
34
+ ## Automation
35
+
36
+ Use:
37
+
38
+ ```bash
39
+ npm run release:check
40
+ npm run release:prepare -- --version X.Y.Z
41
+ npm run release:publish -- --version X.Y.Z
42
+ npm run release:full -- --version X.Y.Z
43
+ ```
@@ -0,0 +1,54 @@
1
+ # Release Workflow
2
+
3
+ SotuRail releases should be repeatable and evidence-backed. The release helper lives at `scripts/release.mjs`.
4
+
5
+ ## Check
6
+
7
+ ```bash
8
+ npm run release:check
9
+ ```
10
+
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
+
13
+ ## Prepare
14
+
15
+ ```bash
16
+ npm run release:prepare -- --version X.Y.Z
17
+ ```
18
+
19
+ Prepare mode:
20
+
21
+ - validates the version argument;
22
+ - updates `package.json`, `package-lock.json` and CLI version text;
23
+ - updates `CHANGELOG.md`;
24
+ - creates `RELEASE_NOTES_vX.Y.Z.md`;
25
+ - runs validation;
26
+ - commits `chore(release): prepare vX.Y.Z`;
27
+ - pushes `main`;
28
+ - never publishes to npm.
29
+
30
+ ## Publish
31
+
32
+ ```bash
33
+ npm run release:publish -- --version X.Y.Z
34
+ ```
35
+
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. If npm asks for 2FA or authentication, rerun the same command after completing the auth step.
37
+
38
+ ## Full
39
+
40
+ ```bash
41
+ npm run release:full -- --version X.Y.Z
42
+ ```
43
+
44
+ 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
+
46
+ Safety rules:
47
+
48
+ - Never run `npm audit fix --force`.
49
+ - Never publish if tests fail.
50
+ - Never publish if build fails.
51
+ - Never publish if runtime audit fails.
52
+ - Never publish if the requested package version already exists on npm.
53
+ - Never create a GitHub release before npm publish succeeds.
54
+ - Never hide errors.
@@ -0,0 +1,28 @@
1
+ # Skill Rail
2
+
3
+ Skill Rail is planned for v0.3.0. It is not implemented in v0.2.2.
4
+
5
+ The goal is to turn approved SotuRail specs, rules and workflows into portable, reviewable agent skills without installing untrusted marketplace content automatically.
6
+
7
+ Planned commands:
8
+
9
+ ```bash
10
+ soturail skills init <name>
11
+ soturail skills from-spec <spec-id>
12
+ soturail skills from-rules <rules-file>
13
+ soturail skills validate <path>
14
+ soturail skills export claude|codex|gemini|cursor
15
+ ```
16
+
17
+ ## Security Requirements
18
+
19
+ - No automatic marketplace install.
20
+ - Validate `SKILL.md` before use.
21
+ - Scan for prompt injection.
22
+ - Scan for destructive shell commands.
23
+ - Scan for secret exfiltration language.
24
+ - Scan for `curl`/`wget` pipe execution.
25
+ - Warn about untrusted scripts.
26
+ - Require human approval before enabling generated skills.
27
+
28
+ Skill Rail should preserve SotuRail's local-first evidence model: generated skills must cite the spec, rule or workflow that produced them.
@@ -0,0 +1,76 @@
1
+ # Windows Notes
2
+
3
+ SotuRail supports Windows through Node.js and uses cross-platform path handling internally. The main practical differences are shell quoting and how commands are pasted.
4
+
5
+ ## Install Globally
6
+
7
+ PowerShell and CMD:
8
+
9
+ ```powershell
10
+ npm install -g soturail
11
+ soturail --help
12
+ ```
13
+
14
+ ## Run With npx
15
+
16
+ ```powershell
17
+ npx soturail --help
18
+ npx soturail init
19
+ ```
20
+
21
+ ## Test a Local Tarball
22
+
23
+ From a source checkout:
24
+
25
+ ```powershell
26
+ npm run build
27
+ npm pack --dry-run
28
+ npm pack
29
+ npm install -g .\soturail-0.2.1.tgz
30
+ soturail --version
31
+ ```
32
+
33
+ If the tarball name changes, use the exact file that `npm pack` created.
34
+
35
+ ## CMD vs PowerShell
36
+
37
+ PowerShell accepts commands like:
38
+
39
+ ```powershell
40
+ node .\dist\cli.js read ".\README.md" --query "quick start"
41
+ ```
42
+
43
+ CMD uses similar quoting, but it does not understand Markdown code-fence labels. Do not paste the literal fence label:
44
+
45
+ ```text
46
+ ```bat
47
+ ```
48
+
49
+ into CMD. CMD will try to execute it and report an error.
50
+
51
+ ## Paths With Spaces
52
+
53
+ Quote paths that contain spaces:
54
+
55
+ ```powershell
56
+ soturail read "C:\Users\rafael\Documents\My Project\README.md" --query "install"
57
+ ```
58
+
59
+ ## Avoid Accidental Command Concatenation
60
+
61
+ When copying examples, keep commands on separate lines. This is wrong:
62
+
63
+ ```text
64
+ node app.jsnpx soturail --help
65
+ ```
66
+
67
+ Run them separately:
68
+
69
+ ```powershell
70
+ node app.js
71
+ npx soturail --help
72
+ ```
73
+
74
+ ## Safety
75
+
76
+ SotuRail blocks destructive command shapes through `soturail run`, including `rm -rf`, `sudo`, `del /s`, downloaded script piping and automatic `git push`.