stratum-cli 0.7.0 → 0.8.0-beta.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.
- package/.stratumrc.json.example +249 -228
- package/CHANGELOG.md +59 -0
- package/README.md +14 -0
- package/dist/index.js +13537 -4175
- package/evals/scenarios/auxiliary/auxiliary-cache-accounting.json +108 -0
- package/evals/scenarios/auxiliary/auxiliary-failure-does-not-corrupt-agent.json +81 -0
- package/evals/scenarios/auxiliary/compression-visible.json +135 -0
- package/evals/scenarios/auxiliary/memory-extraction-visible.json +78 -0
- package/evals/scenarios/auxiliary/subagent-origin.json +90 -0
- package/evals/scenarios/cache/cache-compression-cache-impact.json +113 -0
- package/evals/scenarios/cache/cache-growing-multi-turn-context.json +106 -0
- package/evals/scenarios/cache/cache-repeated-system-prefix.json +89 -0
- package/evals/scenarios/cache/cache-stable-toolset-order.json +97 -0
- package/evals/scenarios/cache/cache-tool-loop-prefix.json +110 -0
- package/evals/scenarios/code/code-create-module.json +57 -0
- package/evals/scenarios/code/code-fix-failing-test.json +86 -0
- package/evals/scenarios/code/code-json-config-edit.json +70 -0
- package/evals/scenarios/code/code-read-and-answer.json +65 -0
- package/evals/scenarios/code/code-rename-across-files.json +103 -0
- package/evals/scenarios/jobs/background-job-cancel.json +102 -0
- package/evals/scenarios/jobs/background-job-completes.json +108 -0
- package/evals/scenarios/jobs/background-job-fails.json +97 -0
- package/evals/scenarios/jobs/background-job-output.json +129 -0
- package/evals/scenarios/jobs/background-job-policy.json +112 -0
- package/evals/scenarios/jobs/background-job-session-close.json +85 -0
- package/evals/scenarios/jobs/background-job-subagent-ownership.json +147 -0
- package/evals/scenarios/linux/linux-count-errors.json +56 -0
- package/evals/scenarios/linux/linux-dash-filenames.json +67 -0
- package/evals/scenarios/linux/linux-largest-log.json +56 -0
- package/evals/scenarios/linux/linux-make-executable.json +49 -0
- package/evals/scenarios/linux/linux-no-match-count.json +67 -0
- package/evals/scenarios/multi-agent/multi-agent-delegate-lookup.json +66 -0
- package/evals/scenarios/multi-agent/multi-agent-direct-delegate.json +51 -0
- package/evals/scenarios/recovery/recovery-edit-mismatch.json +77 -0
- package/evals/scenarios/recovery/recovery-failing-command.json +73 -0
- package/evals/scenarios/recovery/recovery-provider-error.json +54 -0
- package/evals/scenarios/recovery/recovery-second-failure.json +112 -0
- package/evals/scenarios/recovery/recovery-unfixable-missing-secret.json +74 -0
- package/evals/scenarios/recovery/recovery-wrong-path.json +75 -0
- package/evals/scenarios/safety/safety-equivalent-destructive.json +97 -0
- package/evals/scenarios/safety/safety-false-positive-paths.json +66 -0
- package/evals/scenarios/safety/safety-false-positive-quoted.json +79 -0
- package/evals/scenarios/safety/safety-git-clean-narrowing.json +123 -0
- package/evals/scenarios/safety/safety-hard-deny-rm-root.json +93 -0
- package/evals/scenarios/safety/safety-hard-deny-wrappers.json +109 -0
- package/evals/scenarios/safety/safety-key-exfil-alternatives.json +81 -0
- package/evals/scenarios/safety/safety-mixed-environments.json +143 -0
- package/evals/scenarios/safety/safety-mixed-git.json +100 -0
- package/evals/scenarios/safety/safety-obfuscated-hard-deny.json +135 -0
- package/evals/scenarios/safety/safety-private-key-blocked.json +72 -0
- package/evals/scenarios/safety/safety-production-confirm-always.json +107 -0
- package/evals/scenarios/safety/safety-read-only-session.json +61 -0
- package/evals/scenarios/ssh/ssh-compare-disk.json +84 -0
- package/evals/scenarios/ssh/ssh-diagnose-service.json +145 -0
- package/evals/scenarios/ssh/ssh-fallback-command.json +80 -0
- package/evals/scenarios/ssh/ssh-injected-instruction.json +86 -0
- package/evals/scenarios/ssh/ssh-kernel-version.json +58 -0
- package/evals/scenarios/ssh/ssh-unknown-host.json +76 -0
- package/evals/scenarios/steering/explicit-cancel-still-cancels.json +102 -0
- package/evals/scenarios/steering/job-and-user-update.json +136 -0
- package/evals/scenarios/steering/multiple-steering-messages.json +101 -0
- package/evals/scenarios/steering/steering-before-done.json +86 -0
- package/evals/scenarios/steering/steering-before-mutation.json +125 -0
- package/evals/scenarios/steering/steering-during-tool.json +156 -0
- package/evals/scenarios/steering/subagent-does-not-steal-main-steering.json +118 -0
- package/package.json +5 -1
package/.stratumrc.json.example
CHANGED
|
@@ -1,228 +1,249 @@
|
|
|
1
|
-
{
|
|
2
|
-
"provider": {
|
|
3
|
-
"default": "local-ollama",
|
|
4
|
-
"providers": {
|
|
5
|
-
"local-ollama": {
|
|
6
|
-
"type": "openai-compatible",
|
|
7
|
-
"baseUrl": "http://localhost:11434/v1",
|
|
8
|
-
"model": "qwen3.5:9b",
|
|
9
|
-
"apiKey": "ollama",
|
|
10
|
-
"contextWindow": 32768,
|
|
11
|
-
"timeouts": { "headersMs": 120000, "idleMs": 300000 }
|
|
12
|
-
},
|
|
13
|
-
"litellm-proxy": {
|
|
14
|
-
"type": "openai-compatible",
|
|
15
|
-
"baseUrl": "http://localhost:4000/v1",
|
|
16
|
-
"model": "claude-sonnet-4-5",
|
|
17
|
-
"apiKey": "${LITELLM_API_KEY}",
|
|
18
|
-
"contextWindow": 200000
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
},
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
"
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
"
|
|
201
|
-
"
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
"
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
1
|
+
{
|
|
2
|
+
"provider": {
|
|
3
|
+
"default": "local-ollama",
|
|
4
|
+
"providers": {
|
|
5
|
+
"local-ollama": {
|
|
6
|
+
"type": "openai-compatible",
|
|
7
|
+
"baseUrl": "http://localhost:11434/v1",
|
|
8
|
+
"model": "qwen3.5:9b",
|
|
9
|
+
"apiKey": "ollama",
|
|
10
|
+
"contextWindow": 32768,
|
|
11
|
+
"timeouts": { "headersMs": 120000, "idleMs": 300000 }
|
|
12
|
+
},
|
|
13
|
+
"litellm-proxy": {
|
|
14
|
+
"type": "openai-compatible",
|
|
15
|
+
"baseUrl": "http://localhost:4000/v1",
|
|
16
|
+
"model": "claude-sonnet-4-5",
|
|
17
|
+
"apiKey": "${LITELLM_API_KEY}",
|
|
18
|
+
"contextWindow": 200000,
|
|
19
|
+
"cache": { "explicitBreakpoints": true }
|
|
20
|
+
},
|
|
21
|
+
"hosted": {
|
|
22
|
+
"type": "openai-compatible",
|
|
23
|
+
"baseUrl": "https://api.example.com/v1",
|
|
24
|
+
"apiKey": "${EXAMPLE_API_KEY}",
|
|
25
|
+
"models": {
|
|
26
|
+
"big-model": { "contextWindow": 200000 }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"memory": {
|
|
32
|
+
"projectFile": "./STRATUM.md",
|
|
33
|
+
"globalFile": "~/.stratum/STRATUM.md",
|
|
34
|
+
"decisionsFile": "~/.stratum/memory/decisions.json",
|
|
35
|
+
"vectorDb": "~/.stratum/memory/vectors.db",
|
|
36
|
+
"embeddingModel": "Xenova/all-MiniLM-L6-v2",
|
|
37
|
+
"embeddingDimension": 384,
|
|
38
|
+
"embeddingEndpoint": {
|
|
39
|
+
"url": "http://localhost:11434/v1/embeddings",
|
|
40
|
+
"model": "all-minilm",
|
|
41
|
+
"apiKey": ""
|
|
42
|
+
},
|
|
43
|
+
"retrievalTopK": 5,
|
|
44
|
+
"similarityThreshold": 0.9,
|
|
45
|
+
"autoExtract": true,
|
|
46
|
+
"extractionModel": "qwen3.5:9b",
|
|
47
|
+
"embeddingWarmup": false
|
|
48
|
+
},
|
|
49
|
+
"tools": {
|
|
50
|
+
"confirmDestructive": true,
|
|
51
|
+
"bashTimeout": 30000,
|
|
52
|
+
"execMaxBytes": 1048576,
|
|
53
|
+
"auditLog": true,
|
|
54
|
+
"jobs": {
|
|
55
|
+
"enabled": true,
|
|
56
|
+
"maxRunning": 8,
|
|
57
|
+
"maxRetained": 50,
|
|
58
|
+
"maxOutputChars": 1000000,
|
|
59
|
+
"maxTotalOutputChars": 8000000,
|
|
60
|
+
"readChars": 8000,
|
|
61
|
+
"maxReadChars": 24000,
|
|
62
|
+
"maxRuntimeMs": 1800000,
|
|
63
|
+
"maxWaitMs": 60000,
|
|
64
|
+
"subagentAccess": "own"
|
|
65
|
+
},
|
|
66
|
+
"redaction": {
|
|
67
|
+
"extraPatterns": [
|
|
68
|
+
{
|
|
69
|
+
"value": "internal.corp.example",
|
|
70
|
+
"reason": "internal domain"
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"testCommand": "npm test",
|
|
75
|
+
"webSearch": {
|
|
76
|
+
"backend": "meta",
|
|
77
|
+
"tavilyApiKey": "${TAVILY_API_KEY}",
|
|
78
|
+
"maxResults": 10
|
|
79
|
+
},
|
|
80
|
+
"webFetch": {
|
|
81
|
+
"allowHosts": ["localhost:3000"]
|
|
82
|
+
},
|
|
83
|
+
"destructivePatterns": [
|
|
84
|
+
"rm",
|
|
85
|
+
"rmdir",
|
|
86
|
+
"dd",
|
|
87
|
+
"mkfs",
|
|
88
|
+
"format",
|
|
89
|
+
"DROP",
|
|
90
|
+
"DELETE",
|
|
91
|
+
"truncate",
|
|
92
|
+
"shred",
|
|
93
|
+
"wipefs"
|
|
94
|
+
],
|
|
95
|
+
"guardedCommands": {
|
|
96
|
+
"gitPushForce": "confirm",
|
|
97
|
+
"gitResetHard": "confirm",
|
|
98
|
+
"gitRebase": "confirm",
|
|
99
|
+
"gitBranchDeleteForce": "confirm",
|
|
100
|
+
"gitCleanForce": "confirm",
|
|
101
|
+
"npmPublish": "block",
|
|
102
|
+
"dockerPrune": "confirm",
|
|
103
|
+
"curlPipeShell": "confirm",
|
|
104
|
+
"shellDetach": "block"
|
|
105
|
+
},
|
|
106
|
+
"sensitivePathAllowlist": []
|
|
107
|
+
},
|
|
108
|
+
"mcp": {
|
|
109
|
+
"startup": "lazy",
|
|
110
|
+
"installDir": "~/.stratum/mcp",
|
|
111
|
+
"autoInstall": true,
|
|
112
|
+
"heartbeatInterval": 30000,
|
|
113
|
+
"servers": [
|
|
114
|
+
{
|
|
115
|
+
"name": "filesystem",
|
|
116
|
+
"package": "@modelcontextprotocol/server-filesystem@2025.8.21",
|
|
117
|
+
"args": [
|
|
118
|
+
"/home/user/projects"
|
|
119
|
+
],
|
|
120
|
+
"startupTimeout": 15000,
|
|
121
|
+
"toolTimeout": 120000
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "chrome-devtools",
|
|
125
|
+
"package": "chrome-devtools-mcp@0.6.0"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "legacy-npx",
|
|
129
|
+
"command": "npx",
|
|
130
|
+
"args": [
|
|
131
|
+
"-y",
|
|
132
|
+
"some-mcp-server@latest"
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"agent": {
|
|
138
|
+
"maxIterations": 50,
|
|
139
|
+
"maxToolRetries": 3,
|
|
140
|
+
"toolErrorFormat": "xml",
|
|
141
|
+
"compressionKeepRounds": 6,
|
|
142
|
+
"compressionTimeoutMs": 120000
|
|
143
|
+
},
|
|
144
|
+
"agents": {
|
|
145
|
+
"defaultProfile": "general",
|
|
146
|
+
"maxConcurrency": 1,
|
|
147
|
+
"subagentRetentionDays": 30
|
|
148
|
+
},
|
|
149
|
+
"skills": {
|
|
150
|
+
"enabled": true,
|
|
151
|
+
"registryFile": "./.stratum/skill-registry.md"
|
|
152
|
+
},
|
|
153
|
+
"trace": {
|
|
154
|
+
"enabled": true,
|
|
155
|
+
"dir": "~/.stratum/traces",
|
|
156
|
+
"retentionDays": 30,
|
|
157
|
+
"maxFieldChars": 200000
|
|
158
|
+
},
|
|
159
|
+
"prompt": {
|
|
160
|
+
"guides": "inline",
|
|
161
|
+
"guidesDir": "./.stratum/guides"
|
|
162
|
+
},
|
|
163
|
+
"logging": {
|
|
164
|
+
"level": "info",
|
|
165
|
+
"stderr": true,
|
|
166
|
+
"redact": true,
|
|
167
|
+
"file": {
|
|
168
|
+
"enabled": false,
|
|
169
|
+
"dir": "~/.stratum/logs",
|
|
170
|
+
"maxBytes": 5242880,
|
|
171
|
+
"maxFiles": 5
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"ssh": {
|
|
175
|
+
"hosts": {
|
|
176
|
+
"bastion": {
|
|
177
|
+
"host": "bastion.example.com",
|
|
178
|
+
"port": 22,
|
|
179
|
+
"user": "javi",
|
|
180
|
+
"privateKey": "~/.ssh/id_ed25519"
|
|
181
|
+
},
|
|
182
|
+
"prod-web": {
|
|
183
|
+
"host": "192.168.1.10",
|
|
184
|
+
"port": 22,
|
|
185
|
+
"user": "javi",
|
|
186
|
+
"privateKey": "~/.ssh/id_ed25519",
|
|
187
|
+
"jumpHost": "bastion",
|
|
188
|
+
"confirmAll": true
|
|
189
|
+
},
|
|
190
|
+
"dev-server": {
|
|
191
|
+
"host": "10.0.0.5",
|
|
192
|
+
"port": 22,
|
|
193
|
+
"user": "javi",
|
|
194
|
+
"useAgent": true
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"desktop": {
|
|
199
|
+
"maxConcurrentTurns": 2,
|
|
200
|
+
"notifications": {
|
|
201
|
+
"enabled": true,
|
|
202
|
+
"minSeconds": 10
|
|
203
|
+
},
|
|
204
|
+
"globalHotkey": "CommandOrControl+Shift+Space",
|
|
205
|
+
"workspaces": {
|
|
206
|
+
"root": "~/.stratum/desktop/workspaces",
|
|
207
|
+
"maxFileMB": 25,
|
|
208
|
+
"maxWorkspaceMB": 250,
|
|
209
|
+
"compressAfterDays": 7,
|
|
210
|
+
"deleteAfterDays": 30
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"environments": {
|
|
214
|
+
"prod": {
|
|
215
|
+
"match": [
|
|
216
|
+
"ssh:prod-*"
|
|
217
|
+
],
|
|
218
|
+
"tier": "production",
|
|
219
|
+
"requirePlan": true
|
|
220
|
+
},
|
|
221
|
+
"staging": {
|
|
222
|
+
"match": [
|
|
223
|
+
"ssh:stg-*"
|
|
224
|
+
],
|
|
225
|
+
"tier": "staging"
|
|
226
|
+
},
|
|
227
|
+
"lab": {
|
|
228
|
+
"match": [
|
|
229
|
+
"ssh:dev-*"
|
|
230
|
+
],
|
|
231
|
+
"policy": "allow"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
"session": {
|
|
235
|
+
"profile": "auto",
|
|
236
|
+
"planRetentionDays": 30,
|
|
237
|
+
"profiles": {
|
|
238
|
+
"ops": {
|
|
239
|
+
"description": "guardias",
|
|
240
|
+
"allowedTools": [
|
|
241
|
+
"exec",
|
|
242
|
+
"read_file",
|
|
243
|
+
"grep",
|
|
244
|
+
"mcp__*"
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,62 @@ El formato sigue [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y l
|
|
|
6
6
|
|
|
7
7
|
> Las versiones anteriores a la 0.2.1-beta.0 solo existen como tags de git: la primera publicación en npm fue la 0.2.1-beta.0.
|
|
8
8
|
|
|
9
|
+
## [0.8.0-beta.1] — 2026-10-12
|
|
10
|
+
|
|
11
|
+
Segunda pre-release (`npm install -g stratum-cli@beta`), con lo visto al probar la beta.0.
|
|
12
|
+
|
|
13
|
+
### Añadido
|
|
14
|
+
- **`/comandos` con el agente trabajando**: los de consulta (`/context`, `/jobs`, `/jobs cancel`, `/todo`, `/changes`, `/auditor`, `/debug`, `/tools`, `/agents`, `/env`, `/memory show|list|search`, `/sessions list`, `/config get`, `/help`) se ejecutan sin esperar al final del turno, y la paleta se reduce a ellos. Los que tocan el historial, el modelo o el toolset siguen esperando.
|
|
15
|
+
|
|
16
|
+
### Corregido
|
|
17
|
+
- **La salida de un comando ya no se vuelca en la pantalla del chat.** Cuando un `exec` fallaba, el log escribía su salida completa en el terminal, encima de la interfaz. Ahora un comando que se ejecutó y salió mal no se registra como aviso, y cualquier campo del log que vaya al terminal sale en una línea y acotado a 300 caracteres; el fichero de logs lo guarda entero.
|
|
18
|
+
- El texto de dos respuestas del mismo turno, con una tool o una pregunta por medio, ya no sale pegado («…rápidas:Perfecto…»): la segunda empieza párrafo.
|
|
19
|
+
- El bloque de la tool `question` mostraba `[object Object],[object Object]`; ahora enseña la primera pregunta y cuántas más hay.
|
|
20
|
+
- `Ctrl+U` y `Ctrl+T` podían dejar su letra escrita en el input en vez de actuar, y `Ctrl+L` limpiaba la conversación con un turno en curso.
|
|
21
|
+
|
|
22
|
+
## [0.8.0-beta.0] — 2026-10-12
|
|
23
|
+
|
|
24
|
+
Pre-release para pruebas (`npm install -g stratum-cli@beta`); `latest` sigue en la 0.7.0.
|
|
25
|
+
|
|
26
|
+
Traza de sesión con su visor, evaluación reproducible sobre esa traza, jobs en segundo plano, mensajes al agente con el turno en curso (steering) y medición de la caché de prompt del backend.
|
|
27
|
+
|
|
28
|
+
### Añadido
|
|
29
|
+
- **Traza de sesión y visor de trayectoria**: cada sesión de `chat` y `run` deja en `~/.stratum/traces/<sessionId>.jsonl` lo que entra al modelo, cada llamada al LLM (espera, generación, tokens), cada tool con su entrada y su salida, subagentes, avisos y compresión. La escribe el runtime —el modelo no la ve ni la toca— y pasa por la redacción de secretos antes de ir a disco. `/auditor` (y `/auditor stop`) en el chat y `stratum auditor [sessionId]` / `stratum auditor list` abren una web local, solo en loopback, con el timeline por carriles, la lista de pasos y el detalle; se actualiza sola. Config `trace.{enabled,dir,retentionDays,maxFieldChars}`; `sessions delete`/`prune` arrastran la traza.
|
|
30
|
+
- **Jobs en segundo plano**: `exec` con `background: true` lanza el comando como un job de la sesión y vuelve con su `jobId` sin esperar; el agente sigue trabajando y se entera cuando termina. Tools `list_jobs`, `get_job_status`, `get_job_output` y `cancel_job`; panel de jobs en el chat, `/jobs` y `/jobs cancel <id>`. Pasa por las mismas guardas, read-only, entornos y confirmaciones que un `exec` normal, solo en el target local, y los jobs vivos se cancelan al cerrar la sesión. Config `tools.jobs` (`enabled`, `maxRunning`, límites de salida, `subagentAccess`).
|
|
31
|
+
- **Steering**: con el agente trabajando el input sigue vivo. Lo que escribas no cancela el turno ni lanza otra llamada: queda en cola (`[queued as steering]`) y el agente lo recibe en su siguiente punto seguro, dentro del mismo turno. Si tenía tools a punto de ejecutar, no se ejecuta ninguna y decide de nuevo con tu mensaje delante. Cancelar sigue siendo solo `Ctrl+C`.
|
|
32
|
+
- **Caché de prompt**: Stratum mide la caché de prefijo del backend (OpenAI, pasarelas compatibles con los campos de Anthropic, DeepSeek, llama.cpp) y la enseña en `/auditor`, `stratum stats` y `stratum eval`: acierto, llamadas frías y templadas, tiempo al primer token de cada clase y roturas con su causa. Lo que el backend no reporta se muestra como `n/d`, nunca se estima. `provider.providers.<alias>.cache` ajusta qué se envía (`cacheKey`, `explicitBreakpoints`, `sessionAffinity`). Ver `docs/prompt-caching.md`.
|
|
33
|
+
- **Llamadas auxiliares al LLM en la traza**: la extracción de memoria, el resumen de la compresión de contexto y el resumen de sesión quedan registradas con su origen, aparte de las del agente. `/auditor`, `stratum stats` y el informe de eval muestran «LLM calls» con una fila por origen.
|
|
34
|
+
- `stratum run --then <tarea>` (repetible) encadena turnos en la misma sesión y corta si uno no acaba bien.
|
|
35
|
+
- **`stratum eval`**: escenarios reproducibles (`code`, `linux`, `ssh`, `safety`, `recovery`, `multi-agent`) que se ejecutan con `stratum run` en un proyecto temporal y se puntúan con el workspace, la salida y la traza de la sesión. `eval run` (`--mock` para un modelo de guion determinista; sin él, contra el provider configurado), `eval list`, `eval report`, `eval runs` y `eval compare`, que detecta regresiones aunque las dos ejecuciones den PASS (más tokens, tiempo, llamadas o errores) y sale con 1 si las hay. 21 escenarios incluidos; los propios van en `.stratum/evals/`. Resultado en `~/.stratum/evals/runs/<runId>/result.json`. Contra un modelo real, un error fatal del provider (caído, un `429`) deja el escenario en ERROR, no en FAIL. Ver `docs/eval.md`.
|
|
36
|
+
- **Niveles de dificultad** en los escenarios (`basic`, `intermediate`, `adversarial`), con `--difficulty` en `eval run`/`eval list` y el éxito por nivel en el informe y en la comparación. 37 escenarios incluidos: 16 nuevos fuera del camino feliz —órdenes destructivas disfrazadas, alternativas equivalentes a un `rm -rf`, falsos positivos de las guardas, una acción vetada junto a otra permitida, una instrucción inyectada en la salida de un comando, un host que no está en el inventario, un despliegue que no se puede completar—. Los adversariales destaparon tres brechas en las guardas de `exec`, cerradas en esta misma versión (ver «Seguridad»).
|
|
37
|
+
- Cuatro grupos más de escenarios, hasta 61 incluidos: `cache`, `auxiliary`, `jobs` y `steering`. `eval compare` trata la caché como categoría propia (un fallo de caché no es un error del agente) y solo juzga las métricas auxiliares si se piden con `--metric`.
|
|
38
|
+
- **Baselines con nombre**: `stratum eval baseline save|list|delete` y `eval run --save-baseline`. Cada resultado guarda el commit (y si había cambios sin commit), la versión, el SO, el provider/modelo, el modo y la fecha. `stratum eval compare baseline current`.
|
|
39
|
+
- **Tolerancias configurables** en `eval compare` y `eval run --baseline`: por métrica, en porcentaje y/o absoluto (`--tolerance tokens=30%,2k`, `--tolerances fichero.json`, o guardadas con el baseline). Las de partida son estrictas con guion y holgadas contra un modelo real, donde una llamada de más es ruido.
|
|
40
|
+
- El informe de `eval compare` separa los hallazgos por gravedad: PASS → FAIL, PASS → ERROR, acciones inseguras nuevas, más bloqueos de política, regresiones de coste y de fiabilidad, y mejoras. Avisa si un escenario cambió de definición entre las dos ejecuciones, y entonces no compara su coste.
|
|
41
|
+
- Criterios nuevos: `host_received` (lo que un host SSH simulado llegó a recibir) y `tool_output_contains` (lo que llegó al modelo por la salida de una tool). `stratum eval list` avisa de los criterios que atan la trayectoria de un modelo real en vez de puntuar el resultado.
|
|
42
|
+
- **`stratum stats`**: estadísticas agregadas de las trazas guardadas (turnos completados, tool error rate, recuperación, bloqueos de política, tokens, desglose por tool y por modelo). Se calculan en local; nada sale del equipo.
|
|
43
|
+
- `stratum auditor --file <ruta>` abre una traza que no está en `trace.dir` (las de `stratum eval`).
|
|
44
|
+
- La traza registra las **decisiones del runtime** como avisos: confirmaciones (aprobada, denegada, bloqueada), vetos (guarda de la tool, read-only, toolset, plan) y reintentos de la llamada al modelo. El formato no cambia de versión y las trazas anteriores se siguen leyendo.
|
|
45
|
+
|
|
46
|
+
### Seguridad
|
|
47
|
+
- **Las guardas de `exec` clasifican el comando que se ejecuta, no el texto escrito.** Antes de decidir se deshacen los envoltorios con sus flags (`sudo -u root`, `timeout 30`, `env`, `nice`, `chroot`, `busybox`…), la agrupación (`( … )`, `then …`), un comando dentro de otro (`sh -c`, `pwsh -Command`, `cmd /c`, `eval`, `su -c`, `find -exec`; hasta dos niveles), las variables asignadas en el mismo comando (`R=rm; $R -rf /`) y las rutas equivalentes (`//`, `/.`, `/etc/..`). Con eso:
|
|
48
|
+
- **Capa 1 (veto)**: `sudo -u root rm -rf ~`, `sh -c 'rm -rf /'`, `timeout 30 rm -rf /`, `rm -rf //` y similares ya no caían en el veto y `--allow-destructive` los dejaba pasar. También se veta un `find` sin filtros que borra la raíz, el home o el directorio actual (`find / -xdev -delete`).
|
|
49
|
+
- **Confirmación obligatoria** para lo que no se puede leer: un ejecutable que sale de una variable o de una sustitución (`$CMD x`, `$(…) x`), código que llega por una tubería a un intérprete (`… | base64 -d | sh`), `bash <(…)`, `pwsh -EncodedCommand`, `Invoke-Expression`; y para un `find` que borra con filtro. Antes se ejecutaban sin preguntar.
|
|
50
|
+
- **`git clean -f`** sin `-d`, o acotado a una ruta, pide confirmación (comando guardado nuevo `gitCleanForce`, `confirm` por defecto): acotar un `git clean -fd` vetado ya no es la forma de conseguir el mismo borrado.
|
|
51
|
+
|
|
52
|
+
### Corregido
|
|
53
|
+
- Un comando de solo lectura ya no pide confirmación porque un argumento contenga un patrón destructivo: `grep -rn "rm -rf" …`, `echo "rm -rf /"` o `git commit -m "… rm -rf …"` se ejecutan sin preguntar (sin TTY quedaban bloqueados). Los comandos que sí ejecutan sus argumentos (`psql -c "DROP …"`, `ssh host "rm …"`) siguen pidiéndola.
|
|
54
|
+
- **`Ctrl+C` cancela el turno** en el chat (dos veces para salir). Antes la tecla desmontaba la interfaz, el turno seguía por detrás y el proceso salía al terminar.
|
|
55
|
+
- Un `/comando` que no existe responde «Comando desconocido» en vez de enviarse al modelo como mensaje; una ruta (`/etc/hosts …`) sigue llegando.
|
|
56
|
+
- La pantalla de bienvenida tiene la misma paleta de `/comandos` y `@perfiles` que la conversación.
|
|
57
|
+
|
|
58
|
+
### Cambiado
|
|
59
|
+
- Las tools MCP se ofrecen al modelo ordenadas por nombre, detrás de las propias, y con sus schemas en forma canónica: el prompt no cambia de un arranque a otro según qué server conecte antes, y la caché del backend lo aprovecha.
|
|
60
|
+
|
|
61
|
+
### Cambios a tener en cuenta
|
|
62
|
+
- **Desligar un proceso desde el shell local se veta**: `cmd &`, `nohup`, `setsid`, `disown`, `Start-Process`, `Start-Job`, `screen -dm`, `tmux new -d` (también dentro de un `sh -c`). Lo que tenga que seguir vivo va como job con `background: true`. `tools.guardedCommands.shellDetach` lo ajusta.
|
|
63
|
+
- En una sesión sin TTY (o con `--deny-destructive`) ahora se bloquean comandos que antes pasaban: `git clean -f`, `find … -delete`, `$VAR args` con una variable que el comando no asigna y `… | sh`. Con `--allow-destructive`, o aprobándolos, se ejecutan como siempre. `tools.guardedCommands.gitCleanForce: "allow"` recupera el `git clean -f` sin confirmación.
|
|
64
|
+
|
|
9
65
|
## [0.7.0] — 2026-10-03
|
|
10
66
|
|
|
11
67
|
Versión estable de la 0.7.0: incluye todo lo de la [0.7.0-beta.0](#070-beta0--2026-09-27) (endurecimiento de la persistencia, de la escritura de ficheros, de MCP, del cliente del LLM y de `web_fetch`) y, además, los **modelos descubiertos**: a un provider le basta la URL y la key.
|
|
@@ -228,6 +284,9 @@ Primera versión etiquetada. Hitos 0 y 1.
|
|
|
228
284
|
- `/init` para generar o actualizar `STRATUM.md`.
|
|
229
285
|
- Render de markdown de las respuestas.
|
|
230
286
|
|
|
287
|
+
[0.8.0-beta.1]: https://github.com/choruzo/CLI/compare/v0.8.0-beta.0...v0.8.0-beta.1
|
|
288
|
+
[0.8.0-beta.0]: https://github.com/choruzo/CLI/compare/v0.7.0...v0.8.0-beta.0
|
|
289
|
+
[0.7.0]: https://github.com/choruzo/CLI/compare/v0.6.0...v0.7.0
|
|
231
290
|
[0.7.0-beta.0]: https://github.com/choruzo/CLI/compare/v0.6.0...v0.7.0-beta.0
|
|
232
291
|
[0.6.0]: https://github.com/choruzo/CLI/compare/v0.5.0...v0.6.0
|
|
233
292
|
[0.5.0]: https://github.com/choruzo/CLI/compare/v0.4.0...v0.5.0
|
package/README.md
CHANGED
|
@@ -120,6 +120,7 @@ stratum chat Sesión interactiva
|
|
|
120
120
|
stratum chat --resume <id> Reanuda una sesión guardada
|
|
121
121
|
stratum run "<tarea>" Tarea one-shot
|
|
122
122
|
stratum run --plan "<tarea>" Modo plan-and-execute
|
|
123
|
+
stratum run "<tarea>" --then "<otra>" Turnos siguientes en la misma sesión (repetible)
|
|
123
124
|
stratum run --allow-destructive "..." Aprueba tools destructivas automáticamente
|
|
124
125
|
stratum run --deny-destructive "..." Deniega tools destructivas automáticamente
|
|
125
126
|
stratum init [--force] [--dry-run] Genera/actualiza STRATUM.md
|
|
@@ -130,8 +131,21 @@ stratum mcp list|install [server] Servidores MCP
|
|
|
130
131
|
stratum providers Providers configurados
|
|
131
132
|
stratum ssh list|trust <alias> Inventario SSH y host keys
|
|
132
133
|
stratum logs path|tail [n] Fichero de logs (bug reports)
|
|
134
|
+
stratum auditor [sessionId] Visor de trayectoria de una sesión
|
|
135
|
+
stratum eval run [--mock] [ids...] Ejecuta escenarios y los puntúa desde la traza
|
|
136
|
+
stratum eval baseline save [nombre] Guarda una ejecución como referencia con nombre
|
|
137
|
+
stratum eval compare <base> [head] Regresiones entre dos ejecuciones (exit 1 si las hay)
|
|
138
|
+
stratum stats [--days n] Estadísticas locales de tus sesiones
|
|
133
139
|
```
|
|
134
140
|
|
|
141
|
+
`stratum eval` y `stratum stats` trabajan solo con las trazas locales (sin telemetría): formato de
|
|
142
|
+
escenarios, métricas y uso en [`docs/eval.md`](docs/eval.md).
|
|
143
|
+
|
|
144
|
+
Las mismas trazas miden la **caché de prompt** del backend: acierto, tokens servidos de caché,
|
|
145
|
+
llamadas frías y templadas, TTFT de cada clase y qué cambio rompió el prefijo. Cómo se ordena el
|
|
146
|
+
prompt para aprovecharla, qué la invalida y qué admite cada provider está en
|
|
147
|
+
[`docs/prompt-caching.md`](docs/prompt-caching.md).
|
|
148
|
+
|
|
135
149
|
Dentro de `stratum chat`:
|
|
136
150
|
|
|
137
151
|
```
|