soturail 0.2.1

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 (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.js +54 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/bench.d.ts +31 -0
  7. package/dist/commands/bench.js +387 -0
  8. package/dist/commands/bench.js.map +1 -0
  9. package/dist/commands/dedupe.d.ts +2 -0
  10. package/dist/commands/dedupe.js +16 -0
  11. package/dist/commands/dedupe.js.map +1 -0
  12. package/dist/commands/doctor.d.ts +14 -0
  13. package/dist/commands/doctor.js +122 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/expand.d.ts +3 -0
  16. package/dist/commands/expand.js +23 -0
  17. package/dist/commands/expand.js.map +1 -0
  18. package/dist/commands/format.d.ts +6 -0
  19. package/dist/commands/format.js +48 -0
  20. package/dist/commands/format.js.map +1 -0
  21. package/dist/commands/hooks.d.ts +11 -0
  22. package/dist/commands/hooks.js +248 -0
  23. package/dist/commands/hooks.js.map +1 -0
  24. package/dist/commands/index.d.ts +3 -0
  25. package/dist/commands/index.js +28 -0
  26. package/dist/commands/index.js.map +1 -0
  27. package/dist/commands/ingest.d.ts +6 -0
  28. package/dist/commands/ingest.js +52 -0
  29. package/dist/commands/ingest.js.map +1 -0
  30. package/dist/commands/init.d.ts +7 -0
  31. package/dist/commands/init.js +179 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/memory.d.ts +39 -0
  34. package/dist/commands/memory.js +184 -0
  35. package/dist/commands/memory.js.map +1 -0
  36. package/dist/commands/native.d.ts +2 -0
  37. package/dist/commands/native.js +17 -0
  38. package/dist/commands/native.js.map +1 -0
  39. package/dist/commands/read.d.ts +8 -0
  40. package/dist/commands/read.js +87 -0
  41. package/dist/commands/read.js.map +1 -0
  42. package/dist/commands/rules.d.ts +5 -0
  43. package/dist/commands/rules.js +62 -0
  44. package/dist/commands/rules.js.map +1 -0
  45. package/dist/commands/run.d.ts +22 -0
  46. package/dist/commands/run.js +200 -0
  47. package/dist/commands/run.js.map +1 -0
  48. package/dist/commands/spec.d.ts +11 -0
  49. package/dist/commands/spec.js +217 -0
  50. package/dist/commands/spec.js.map +1 -0
  51. package/dist/commands/stats.d.ts +15 -0
  52. package/dist/commands/stats.js +82 -0
  53. package/dist/commands/stats.js.map +1 -0
  54. package/dist/compressors/agent-response-reducer.d.ts +13 -0
  55. package/dist/compressors/agent-response-reducer.js +160 -0
  56. package/dist/compressors/agent-response-reducer.js.map +1 -0
  57. package/dist/compressors/generic-stream.d.ts +6 -0
  58. package/dist/compressors/generic-stream.js +63 -0
  59. package/dist/compressors/generic-stream.js.map +1 -0
  60. package/dist/compressors/git-reducer.d.ts +2 -0
  61. package/dist/compressors/git-reducer.js +78 -0
  62. package/dist/compressors/git-reducer.js.map +1 -0
  63. package/dist/compressors/index.d.ts +10 -0
  64. package/dist/compressors/index.js +84 -0
  65. package/dist/compressors/index.js.map +1 -0
  66. package/dist/compressors/json-toon.d.ts +14 -0
  67. package/dist/compressors/json-toon.js +149 -0
  68. package/dist/compressors/json-toon.js.map +1 -0
  69. package/dist/compressors/test-reducer.d.ts +2 -0
  70. package/dist/compressors/test-reducer.js +50 -0
  71. package/dist/compressors/test-reducer.js.map +1 -0
  72. package/dist/core/cache-normalizer.d.ts +23 -0
  73. package/dist/core/cache-normalizer.js +170 -0
  74. package/dist/core/cache-normalizer.js.map +1 -0
  75. package/dist/core/config.d.ts +104 -0
  76. package/dist/core/config.js +186 -0
  77. package/dist/core/config.js.map +1 -0
  78. package/dist/core/dedupe-store.d.ts +17 -0
  79. package/dist/core/dedupe-store.js +44 -0
  80. package/dist/core/dedupe-store.js.map +1 -0
  81. package/dist/core/document-ingest.d.ts +15 -0
  82. package/dist/core/document-ingest.js +45 -0
  83. package/dist/core/document-ingest.js.map +1 -0
  84. package/dist/core/file-scanner.d.ts +47 -0
  85. package/dist/core/file-scanner.js +248 -0
  86. package/dist/core/file-scanner.js.map +1 -0
  87. package/dist/core/git.d.ts +2 -0
  88. package/dist/core/git.js +29 -0
  89. package/dist/core/git.js.map +1 -0
  90. package/dist/core/metrics-store.d.ts +20 -0
  91. package/dist/core/metrics-store.js +19 -0
  92. package/dist/core/metrics-store.js.map +1 -0
  93. package/dist/core/native-engine.d.ts +25 -0
  94. package/dist/core/native-engine.js +137 -0
  95. package/dist/core/native-engine.js.map +1 -0
  96. package/dist/core/native-runner-adapter.d.ts +18 -0
  97. package/dist/core/native-runner-adapter.js +60 -0
  98. package/dist/core/native-runner-adapter.js.map +1 -0
  99. package/dist/core/raw-store.d.ts +28 -0
  100. package/dist/core/raw-store.js +57 -0
  101. package/dist/core/raw-store.js.map +1 -0
  102. package/dist/core/response-policy.d.ts +11 -0
  103. package/dist/core/response-policy.js +14 -0
  104. package/dist/core/response-policy.js.map +1 -0
  105. package/dist/core/rule-extractor.d.ts +18 -0
  106. package/dist/core/rule-extractor.js +116 -0
  107. package/dist/core/rule-extractor.js.map +1 -0
  108. package/dist/core/rule-validator.d.ts +9 -0
  109. package/dist/core/rule-validator.js +85 -0
  110. package/dist/core/rule-validator.js.map +1 -0
  111. package/dist/core/safety-policy.d.ts +10 -0
  112. package/dist/core/safety-policy.js +69 -0
  113. package/dist/core/safety-policy.js.map +1 -0
  114. package/dist/core/token-estimator.d.ts +2 -0
  115. package/dist/core/token-estimator.js +7 -0
  116. package/dist/core/token-estimator.js.map +1 -0
  117. package/dist/types/index.d.ts +4 -0
  118. package/dist/types/index.js +2 -0
  119. package/dist/types/index.js.map +1 -0
  120. package/docs/architecture.md +47 -0
  121. package/docs/assets/screenshots/README.md +18 -0
  122. package/docs/assets/screenshots/init.svg +13 -0
  123. package/docs/assets/screenshots/run-expand.svg +13 -0
  124. package/docs/assets/screenshots/stats.svg +11 -0
  125. package/docs/assets/soturail-fox.svg +17 -0
  126. package/docs/assets/soturail-icon.svg +10 -0
  127. package/docs/benchmarking.md +34 -0
  128. package/docs/branding.md +14 -0
  129. package/docs/hooks/claude.md +24 -0
  130. package/docs/hooks/codex.md +5 -0
  131. package/docs/hooks/cursor.md +5 -0
  132. package/docs/hooks/gemini.md +5 -0
  133. package/docs/hooks/host-capabilities.json +22 -0
  134. package/docs/hooks.md +15 -0
  135. package/docs/knowledge-to-rules.md +23 -0
  136. package/docs/metrics.md +35 -0
  137. package/docs/mvp.md +21 -0
  138. package/docs/native-runner.md +52 -0
  139. package/docs/prompt-caching.md +27 -0
  140. package/docs/pt-BR/visao-geral.md +26 -0
  141. package/docs/public-roadmap.md +20 -0
  142. package/docs/reducers.md +19 -0
  143. package/docs/release-checklist.md +13 -0
  144. package/docs/response-compression.md +15 -0
  145. package/docs/rules.md +23 -0
  146. package/docs/security-model.md +32 -0
  147. package/docs/spec-driven-workflow.md +22 -0
  148. package/docs/usage.md +64 -0
  149. package/package.json +71 -0
@@ -0,0 +1,200 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { DedupeStore, sha256Text } from "../core/dedupe-store.js";
3
+ import { ensureWorkspace } from "../core/config.js";
4
+ import { MetricsStore } from "../core/metrics-store.js";
5
+ import { NativeRunnerAdapter } from "../core/native-runner-adapter.js";
6
+ import { RawStore } from "../core/raw-store.js";
7
+ import { validateCommand } from "../core/safety-policy.js";
8
+ import { estimateTokens } from "../core/token-estimator.js";
9
+ import { detectNativeEngine, runWithNative } from "../core/native-engine.js";
10
+ import { compressOutputWithEngine } from "../compressors/index.js";
11
+ function commandFromParts(parts) {
12
+ if (parts.length === 1) {
13
+ return parts[0]?.trim() ?? "";
14
+ }
15
+ return parts.map(shellQuoteIfNeeded).join(" ").trim();
16
+ }
17
+ function shellQuoteIfNeeded(part) {
18
+ if (!/\s/.test(part)) {
19
+ return part;
20
+ }
21
+ if ((part.startsWith("\"") && part.endsWith("\"")) || (part.startsWith("'") && part.endsWith("'"))) {
22
+ return part;
23
+ }
24
+ return `"${part.replace(/(["\\$`])/g, "\\$1")}"`;
25
+ }
26
+ function normalizeEngine(value) {
27
+ if (value === undefined) {
28
+ return "auto";
29
+ }
30
+ if (["auto", "ts", "native"].includes(value)) {
31
+ return value;
32
+ }
33
+ throw new Error(`Unknown reducer engine "${value}". Use auto, ts, or native.`);
34
+ }
35
+ export async function executeRunCommand(commandParts, options = {}, root = process.cwd()) {
36
+ await ensureWorkspace(root);
37
+ const command = commandFromParts(commandParts);
38
+ if (command.length === 0) {
39
+ throw new Error("No command provided. Example: soturail run npm test");
40
+ }
41
+ const validation = validateCommand(command, options.unsafeConfirm);
42
+ if (!validation.ok) {
43
+ throw new Error(validation.reason ?? "Command blocked by SotuRail safety policy.");
44
+ }
45
+ if (validation.bypassed) {
46
+ options.terminalStderr?.write(`SotuRail safety bypass accepted for ${validation.matchedPattern ?? "dangerous command"}.\n`);
47
+ }
48
+ if (options.interactive) {
49
+ options.terminalStderr?.write("Interactive mode: stdin is forwarded when possible; compression may be partial for watch/TTY sessions.\n");
50
+ }
51
+ const requestedEngine = options.native ? "native" : normalizeEngine(options.engine);
52
+ const nativeInfo = requestedEngine === "ts" ? { available: false } : await detectNativeEngine(root);
53
+ if (requestedEngine === "native" && !nativeInfo.available) {
54
+ throw new Error("Native engine requested but soturail-native was not found. Run npm run build:native or use --engine ts.");
55
+ }
56
+ const rawStore = new RawStore(root);
57
+ const metrics = new MetricsStore(root);
58
+ const dedupe = new DedupeStore(root);
59
+ const log = await rawStore.createLog(command);
60
+ const result = nativeInfo.available
61
+ ? await runNativePath(commandParts, log, options, root)
62
+ : await runTypeScriptPath(command, log.stream, options, root);
63
+ const outputHash = sha256Text(result.rawText);
64
+ const previous = await dedupe.findReusable(outputHash, result.exitCode);
65
+ const compression = previous
66
+ ? {
67
+ compressor: "dedupe",
68
+ summary: `Output identical to previous raw_id ${previous.raw_id}; use soturail expand ${previous.raw_id} for full output.\nCurrent raw log is still preserved as ${log.rawId}.\n`,
69
+ compressed_tokens_estimated: estimateTokens(`Output identical to previous raw_id ${previous.raw_id}.`),
70
+ engine: "ts"
71
+ }
72
+ : await compressOutputWithEngine(command, result.rawText, log.rawId, nativeInfo.available ? requestedEngine : "ts", root);
73
+ const record = {
74
+ raw_id: log.rawId,
75
+ path: log.relativePath,
76
+ command,
77
+ exit_code: result.exitCode,
78
+ created_at: log.createdAt,
79
+ compressor: compression.compressor,
80
+ raw_tokens_estimated: estimateTokens(result.rawText),
81
+ compressed_tokens_estimated: compression.compressed_tokens_estimated
82
+ };
83
+ await rawStore.appendRunRecord(record);
84
+ await dedupe.append({
85
+ output_sha256: outputHash,
86
+ raw_id: log.rawId,
87
+ command,
88
+ exit_code: result.exitCode,
89
+ raw_path: log.relativePath,
90
+ created_at: log.createdAt
91
+ });
92
+ if (previous) {
93
+ await metrics.append({
94
+ type: "dedupe_hit",
95
+ raw_id: log.rawId,
96
+ details: { previous_raw_id: previous.raw_id, output_sha256: outputHash }
97
+ });
98
+ }
99
+ await metrics.append({
100
+ type: "command_run",
101
+ raw_id: log.rawId,
102
+ command,
103
+ exit_code: result.exitCode,
104
+ raw_tokens_estimated: record.raw_tokens_estimated,
105
+ compressed_tokens_estimated: record.compressed_tokens_estimated
106
+ });
107
+ const summary = [
108
+ "",
109
+ "SotuRail run complete.",
110
+ `Exit code: ${result.exitCode}`,
111
+ `Compressor: ${compression.compressor}`,
112
+ `Engine: ${compression.engine}`,
113
+ `raw_id: ${log.rawId}`,
114
+ `Recovery: soturail expand ${log.rawId}`,
115
+ "",
116
+ compression.summary
117
+ ].join("\n");
118
+ return {
119
+ rawId: log.rawId,
120
+ exitCode: result.exitCode,
121
+ summary,
122
+ record
123
+ };
124
+ }
125
+ async function runTypeScriptPath(command, rawLogStream, options, root) {
126
+ const adapter = new NativeRunnerAdapter();
127
+ const runnerOptions = {
128
+ command,
129
+ cwd: root,
130
+ interactive: options.interactive === true,
131
+ rawLogStream
132
+ };
133
+ if (options.terminalStdout) {
134
+ runnerOptions.terminalStdout = options.terminalStdout;
135
+ }
136
+ if (options.terminalStderr) {
137
+ runnerOptions.terminalStderr = options.terminalStderr;
138
+ }
139
+ return adapter.run(runnerOptions);
140
+ }
141
+ async function runNativePath(commandParts, log, options, root) {
142
+ await closeLogStream(log.stream);
143
+ const summaryJsonPath = `${log.absolutePath}.summary.json`;
144
+ const nativeOptions = {
145
+ commandParts,
146
+ rawLogPath: log.absolutePath,
147
+ summaryJsonPath,
148
+ cwd: root,
149
+ interactive: options.interactive === true
150
+ };
151
+ if (options.terminalStdout) {
152
+ nativeOptions.terminalStdout = options.terminalStdout;
153
+ }
154
+ if (options.terminalStderr) {
155
+ nativeOptions.terminalStderr = options.terminalStderr;
156
+ }
157
+ const native = await runWithNative(nativeOptions, root);
158
+ if (!native) {
159
+ throw new Error("Native engine was detected but native run failed to start.");
160
+ }
161
+ const rawText = await fs.readFile(log.absolutePath, "utf8");
162
+ return { exitCode: native.exitCode, rawText };
163
+ }
164
+ async function closeLogStream(stream) {
165
+ await new Promise((resolve) => stream.end(resolve));
166
+ }
167
+ export function registerRunCommand(program) {
168
+ program
169
+ .command("run")
170
+ .description("Run a command through the safe tee-stream runner.")
171
+ .allowUnknownOption(true)
172
+ .allowExcessArguments(true)
173
+ .option("--interactive", "Forward stdin/TTY behavior when possible")
174
+ .option("--native", "Prefer the optional native reducer engine")
175
+ .option("--engine <engine>", "Reducer engine: auto, ts, or native", "auto")
176
+ .option("--unsafe-confirm <phrase>", "Exact phrase required to bypass dangerous-command blocking")
177
+ .argument("[command...]", "Command and arguments to execute")
178
+ .action(async (commandParts = [], options) => {
179
+ const runOptions = {
180
+ terminalStdout: process.stdout,
181
+ terminalStderr: process.stderr
182
+ };
183
+ if (options.interactive !== undefined) {
184
+ runOptions.interactive = options.interactive;
185
+ }
186
+ if (options.unsafeConfirm !== undefined) {
187
+ runOptions.unsafeConfirm = options.unsafeConfirm;
188
+ }
189
+ if (options.native !== undefined) {
190
+ runOptions.native = options.native;
191
+ }
192
+ if (options.engine !== undefined) {
193
+ runOptions.engine = options.engine;
194
+ }
195
+ const result = await executeRunCommand(commandParts, runOptions);
196
+ process.stdout.write(result.summary);
197
+ process.exitCode = result.exitCode;
198
+ });
199
+ }
200
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Command } from "commander";
2
+ export declare function createSpec(featureIdea: string, root?: string): Promise<{
3
+ folder: string;
4
+ files: string[];
5
+ }>;
6
+ export declare function registerSpecCommand(program: Command): void;
7
+ export declare function specStatus(root?: string): Promise<string>;
8
+ export declare function validateSpecs(specFolder?: string, root?: string): Promise<string>;
9
+ export declare function addSpecTask(specFolder: string, text: string, root?: string): Promise<string>;
10
+ export declare function listSpecTasks(specFolder: string, root?: string): Promise<string>;
11
+ export declare function markSpecTaskDone(specFolder: string, index: number, root?: string): Promise<string>;
@@ -0,0 +1,217 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { ensureWorkspace, getWorkspacePaths, relativeToRoot, writeFileIfMissing } from "../core/config.js";
4
+ function slugify(input) {
5
+ const slug = input
6
+ .toLowerCase()
7
+ .replace(/[^a-z0-9]+/g, "-")
8
+ .replace(/^-+|-+$/g, "")
9
+ .slice(0, 50);
10
+ return slug || "feature";
11
+ }
12
+ async function nextSpecNumber(specsDir) {
13
+ try {
14
+ const entries = await fs.readdir(specsDir, { withFileTypes: true });
15
+ const numbers = entries
16
+ .filter((entry) => entry.isDirectory())
17
+ .map((entry) => Number(entry.name.match(/^(\d{3})-/)?.[1] ?? 0))
18
+ .filter((value) => Number.isFinite(value));
19
+ return Math.max(0, ...numbers) + 1;
20
+ }
21
+ catch {
22
+ return 1;
23
+ }
24
+ }
25
+ function specTemplates(featureIdea) {
26
+ const title = featureIdea.trim();
27
+ return {
28
+ "constitution.md": `# Constitution: ${title}
29
+
30
+ Status: Draft
31
+
32
+ ## Principles
33
+
34
+ - Local-first behavior is mandatory.
35
+ - Raw evidence must remain recoverable.
36
+ - Safety gates must be explicit and reversible.
37
+ - Metrics must distinguish estimates from provider-reported facts.
38
+ `,
39
+ "spec.md": `# Spec: ${title}
40
+
41
+ Status: Draft
42
+
43
+ ## User Need
44
+
45
+ Describe the user-facing problem and the smallest verifiable outcome.
46
+
47
+ ## Functional Requirements
48
+
49
+ - The implementation must be testable locally.
50
+ - The behavior must preserve user data.
51
+ - Any compression must point back to raw evidence.
52
+
53
+ ## Acceptance Criteria
54
+
55
+ - Given the feature is used, then the user can inspect the result.
56
+ - Given a failure occurs, then the user receives a recoverable explanation.
57
+ `,
58
+ "plan.md": `# Plan: ${title}
59
+
60
+ ## Technical Approach
61
+
62
+ 1. Define boundaries and storage format.
63
+ 2. Implement the smallest reversible path.
64
+ 3. Add tests for safety, failure and recovery.
65
+ 4. Update docs after behavior is verified.
66
+ `,
67
+ "tasks.md": `# Tasks: ${title}
68
+
69
+ - [ ] Confirm scope and non-goals.
70
+ - [ ] Add focused tests.
71
+ - [ ] Implement behavior.
72
+ - [ ] Run build and tests.
73
+ - [ ] Document usage and limitations.
74
+ `,
75
+ "verification.md": `# Verification: ${title}
76
+
77
+ ## Verification Plan
78
+
79
+ - Build succeeds locally.
80
+ - Tests cover the expected behavior.
81
+ - CLI examples are exercised when applicable.
82
+ `,
83
+ "context-budget.md": `# Context Budget: ${title}
84
+
85
+ ## Context Budget
86
+
87
+ - Prefer repo maps and targeted reads.
88
+ - Keep raw logs recoverable through soturail expand.
89
+ - Place stable spec content before dynamic run output.
90
+ `,
91
+ "security-impact.md": `# Security Impact: ${title}
92
+
93
+ ## Security Impact
94
+
95
+ - Identify destructive command risks.
96
+ - Identify secret-bearing raw logs.
97
+ - Confirm no automatic remote push is introduced.
98
+ `
99
+ };
100
+ }
101
+ export async function createSpec(featureIdea, root = process.cwd()) {
102
+ await ensureWorkspace(root);
103
+ const paths = getWorkspacePaths(root);
104
+ const number = await nextSpecNumber(paths.specsDir);
105
+ const folder = path.resolve(paths.specsDir, `${String(number).padStart(3, "0")}-${slugify(featureIdea)}`);
106
+ await fs.mkdir(folder, { recursive: true });
107
+ const files = [];
108
+ const templates = specTemplates(featureIdea);
109
+ for (const [fileName, content] of Object.entries(templates)) {
110
+ const filePath = path.resolve(folder, fileName);
111
+ await writeFileIfMissing(filePath, content, undefined, root);
112
+ files.push(relativeToRoot(root, filePath));
113
+ }
114
+ return { folder: relativeToRoot(root, folder), files };
115
+ }
116
+ export function registerSpecCommand(program) {
117
+ const spec = program.command("spec").description("Manage Spec-Driven Development artifacts.");
118
+ spec
119
+ .command("new")
120
+ .description("Create a new local SDD spec folder.")
121
+ .argument("<feature idea>", "Feature idea")
122
+ .action(async (featureIdea) => {
123
+ const result = await createSpec(featureIdea);
124
+ process.stdout.write(`Created spec folder: ${result.folder}\n${result.files.map((file) => ` + ${file}`).join("\n")}\n`);
125
+ });
126
+ spec.command("status").description("List local spec folders and task progress.").action(async () => {
127
+ process.stdout.write(await specStatus());
128
+ });
129
+ spec.command("validate").description("Validate spec folders for required SDD sections.").argument("[spec-folder]", "Optional spec folder").action(async (folder) => {
130
+ process.stdout.write(await validateSpecs(folder));
131
+ });
132
+ const task = spec.command("task").description("Manage tasks in a spec folder.");
133
+ task.command("add").argument("<spec-folder>", "Spec folder").argument("<text>", "Task text").action(async (folder, text) => {
134
+ process.stdout.write(await addSpecTask(folder, text));
135
+ });
136
+ task.command("list").argument("<spec-folder>", "Spec folder").action(async (folder) => {
137
+ process.stdout.write(await listSpecTasks(folder));
138
+ });
139
+ task.command("done").argument("<spec-folder>", "Spec folder").argument("<index>", "1-based task index").action(async (folder, index) => {
140
+ process.stdout.write(await markSpecTaskDone(folder, Number(index)));
141
+ });
142
+ }
143
+ async function specFolders(root = process.cwd()) {
144
+ const paths = getWorkspacePaths(root);
145
+ try {
146
+ const entries = await fs.readdir(paths.specsDir, { withFileTypes: true });
147
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => path.resolve(paths.specsDir, entry.name)).sort();
148
+ }
149
+ catch {
150
+ return [];
151
+ }
152
+ }
153
+ async function readFileOrEmpty(filePath) {
154
+ return fs.readFile(filePath, "utf8").catch(() => "");
155
+ }
156
+ export async function specStatus(root = process.cwd()) {
157
+ await ensureWorkspace(root);
158
+ const folders = await specFolders(root);
159
+ if (folders.length === 0) {
160
+ return "No specs found. Run soturail spec new \"feature idea\".\n";
161
+ }
162
+ const lines = ["SotuRail spec status"];
163
+ for (const folder of folders) {
164
+ const tasks = await readFileOrEmpty(path.resolve(folder, "tasks.md"));
165
+ const done = (tasks.match(/^- \[x\]/gim) ?? []).length;
166
+ const total = (tasks.match(/^- \[[ x]\]/gim) ?? []).length;
167
+ lines.push(`${relativeToRoot(root, folder)}: ${done}/${total} tasks done`);
168
+ }
169
+ return `${lines.join("\n")}\n`;
170
+ }
171
+ export async function validateSpecs(specFolder, root = process.cwd()) {
172
+ await ensureWorkspace(root);
173
+ const folders = specFolder ? [path.resolve(root, specFolder)] : await specFolders(root);
174
+ const checks = [
175
+ { file: "spec.md", label: "problem statement", pattern: /problem|user need/i },
176
+ { file: "spec.md", label: "acceptance criteria", pattern: /acceptance criteria/i },
177
+ { file: "verification.md", label: "verification plan", pattern: /verification plan/i },
178
+ { file: "context-budget.md", label: "context budget", pattern: /context budget/i },
179
+ { file: "security-impact.md", label: "security impact", pattern: /security impact/i }
180
+ ];
181
+ const lines = ["SotuRail spec validate"];
182
+ for (const folder of folders) {
183
+ lines.push(relativeToRoot(root, folder));
184
+ for (const check of checks) {
185
+ const content = await readFileOrEmpty(path.resolve(folder, check.file));
186
+ lines.push(` ${check.pattern.test(content) ? "OK" : "FAIL"} ${check.label}`);
187
+ }
188
+ }
189
+ return `${lines.join("\n")}\n`;
190
+ }
191
+ export async function addSpecTask(specFolder, text, root = process.cwd()) {
192
+ const tasksFile = path.resolve(root, specFolder, "tasks.md");
193
+ await fs.appendFile(tasksFile, `- [ ] ${text}\n`, "utf8");
194
+ return `Added task to ${path.normalize(specFolder).replace(/\\/g, "/")}\n`;
195
+ }
196
+ export async function listSpecTasks(specFolder, root = process.cwd()) {
197
+ const tasks = await readFileOrEmpty(path.resolve(root, specFolder, "tasks.md"));
198
+ const lines = tasks.split(/\r?\n/).filter((line) => /^- \[[ x]\]/i.test(line));
199
+ return lines.length > 0 ? `${lines.map((line, index) => `${index + 1}. ${line}`).join("\n")}\n` : "No tasks found.\n";
200
+ }
201
+ export async function markSpecTaskDone(specFolder, index, root = process.cwd()) {
202
+ const tasksFile = path.resolve(root, specFolder, "tasks.md");
203
+ const content = await fs.readFile(tasksFile, "utf8");
204
+ let seen = 0;
205
+ const next = content.split(/\r?\n/).map((line) => {
206
+ if (/^- \[[ x]\]/i.test(line)) {
207
+ seen += 1;
208
+ if (seen === index) {
209
+ return line.replace(/^- \[[ x]\]/i, "- [x]");
210
+ }
211
+ }
212
+ return line;
213
+ }).join("\n");
214
+ await fs.writeFile(tasksFile, next, "utf8");
215
+ return `Marked task ${index} done in ${path.normalize(specFolder).replace(/\\/g, "/")}\n`;
216
+ }
217
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { Command } from "commander";
2
+ export interface StatsReport {
3
+ estimated_raw_tokens: number;
4
+ estimated_compressed_tokens: number;
5
+ compression_ratio: number | null;
6
+ command_count: number;
7
+ expansion_count: number;
8
+ manual_omission_or_failure_count: number;
9
+ estimated_cache_stability_score: number;
10
+ provider_cache_hits: number | null;
11
+ provider_cache_source: string | null;
12
+ }
13
+ export declare function collectStats(root?: string): Promise<StatsReport>;
14
+ export declare function formatStats(report: StatsReport): string;
15
+ export declare function registerStatsCommand(program: Command): void;
@@ -0,0 +1,82 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { readCacheBlocks } from "../core/cache-normalizer.js";
4
+ import { getWorkspacePaths } from "../core/config.js";
5
+ import { MetricsStore } from "../core/metrics-store.js";
6
+ import { RawStore } from "../core/raw-store.js";
7
+ async function readProviderCacheMetadata(root) {
8
+ const paths = getWorkspacePaths(root);
9
+ const filePath = path.resolve(paths.metricsDir, "provider-cache.json");
10
+ try {
11
+ const parsed = JSON.parse(await fs.readFile(filePath, "utf8"));
12
+ const hits = parsed.provider_cache_hits;
13
+ if (typeof hits === "number" && Number.isFinite(hits)) {
14
+ return { hits, source: path.normalize(path.relative(root, filePath)).replace(/\\/g, "/") };
15
+ }
16
+ return null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ export async function collectStats(root = process.cwd()) {
23
+ const rawStore = new RawStore(root);
24
+ const metrics = new MetricsStore(root);
25
+ const records = await rawStore.readManifest();
26
+ const events = await metrics.readAll();
27
+ const blocks = await readCacheBlocks(root);
28
+ const rawTokens = records.reduce((sum, record) => sum + record.raw_tokens_estimated, 0);
29
+ const compressedTokens = records.reduce((sum, record) => sum + record.compressed_tokens_estimated, 0);
30
+ const expansionCount = events.filter((event) => event.type === "expand").length;
31
+ const omissionCount = events.filter((event) => event.type === "omission_report").length;
32
+ const failureCount = records.filter((record) => record.exit_code !== 0).length;
33
+ const lastDoctorCache = [...events]
34
+ .reverse()
35
+ .find((event) => event.type === "doctor_cache" && typeof event.estimated_cache_stability_score === "number");
36
+ const stableTokens = blocks.reduce((sum, block) => sum + block.token_estimate, 0);
37
+ const cacheScore = typeof lastDoctorCache?.estimated_cache_stability_score === "number"
38
+ ? lastDoctorCache.estimated_cache_stability_score
39
+ : stableTokens > 0
40
+ ? Number((stableTokens / (stableTokens + 800)).toFixed(4))
41
+ : 0;
42
+ const provider = await readProviderCacheMetadata(root);
43
+ return {
44
+ estimated_raw_tokens: rawTokens,
45
+ estimated_compressed_tokens: compressedTokens,
46
+ compression_ratio: compressedTokens > 0 ? Number((rawTokens / compressedTokens).toFixed(2)) : null,
47
+ command_count: records.length,
48
+ expansion_count: expansionCount,
49
+ manual_omission_or_failure_count: omissionCount + failureCount,
50
+ estimated_cache_stability_score: cacheScore,
51
+ provider_cache_hits: provider?.hits ?? null,
52
+ provider_cache_source: provider?.source ?? null
53
+ };
54
+ }
55
+ export function formatStats(report) {
56
+ const providerLine = report.provider_cache_hits === null
57
+ ? "real_provider_cache_hits: not imported"
58
+ : `real_provider_cache_hits: ${report.provider_cache_hits} (source: ${report.provider_cache_source})`;
59
+ return [
60
+ "SotuRail local stats",
61
+ `estimated_raw_tokens: ${report.estimated_raw_tokens}`,
62
+ `estimated_compressed_tokens: ${report.estimated_compressed_tokens}`,
63
+ `compression_ratio: ${report.compression_ratio === null ? "n/a" : `${report.compression_ratio}:1`}`,
64
+ `command_count: ${report.command_count}`,
65
+ `expansion_count: ${report.expansion_count}`,
66
+ `manual_omission_or_failure_count: ${report.manual_omission_or_failure_count}`,
67
+ `estimated_cache_stability_score: ${report.estimated_cache_stability_score}`,
68
+ providerLine,
69
+ "",
70
+ "Token counts and cache stability are local estimates unless provider metadata is explicitly imported."
71
+ ].join("\n");
72
+ }
73
+ export function registerStatsCommand(program) {
74
+ program
75
+ .command("stats")
76
+ .description("Print honest local metrics from raw and metrics manifests.")
77
+ .action(async () => {
78
+ const report = await collectStats();
79
+ process.stdout.write(`${formatStats(report)}\n`);
80
+ });
81
+ }
82
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type ResponseMode } from "../core/response-policy.js";
2
+ export interface ResponseReductionResult {
3
+ mode: ResponseMode;
4
+ output: string;
5
+ raw_tokens: number;
6
+ compressed_tokens: number;
7
+ reduction_percent: number;
8
+ preserved_commands_count: number;
9
+ preserved_paths_count: number;
10
+ preserved_code_blocks_count: number;
11
+ preserved_security_warnings_count: number;
12
+ }
13
+ export declare function reduceAgentResponse(input: string, mode: ResponseMode): ResponseReductionResult;