compact-agent 1.29.0 → 1.29.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/bin/ecc-hooks.cjs +62 -23
- package/package.json +1 -1
package/bin/ecc-hooks.cjs
CHANGED
|
@@ -178,15 +178,35 @@ const checks = {
|
|
|
178
178
|
},
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* elaborate session state, destructive-bash detection, and quote-aware
|
|
184
|
-
* SQL pattern matching. We port the highest-leverage mechanism: a
|
|
185
|
-
* per-session per-file flag that demands investigation on first touch.
|
|
181
|
+
* GateGuard — surface "first Edit/Write to this file" as a hint or a
|
|
182
|
+
* block, depending on COMPACT_AGENT_GATEGUARD_MODE.
|
|
186
183
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
184
|
+
* Modes:
|
|
185
|
+
* warn (default) — print the investigation hint, allow the edit.
|
|
186
|
+
* The agent reads the hint as conversational
|
|
187
|
+
* context but isn't forced to retry. Zero
|
|
188
|
+
* round-trip cost on the happy path.
|
|
189
|
+
* block — the original behavior: block once per file,
|
|
190
|
+
* allow on retry. Use this when you actively
|
|
191
|
+
* want to force the agent to re-investigate
|
|
192
|
+
* every existing file before its first edit.
|
|
193
|
+
* off — silent no-op.
|
|
194
|
+
*
|
|
195
|
+
* Why warn is the new default (changed in v1.29.1):
|
|
196
|
+
* - The block-first-allow-on-retry pattern wasted a round-trip on
|
|
197
|
+
* every first edit to every existing file.
|
|
198
|
+
* - The investigation hint is just as useful when delivered as a
|
|
199
|
+
* warning the agent observes — it doesn't need a forced retry
|
|
200
|
+
* to be acted on.
|
|
201
|
+
* - User reports across three sessions showed agents always
|
|
202
|
+
* succeeded on retry, so the block was friction without
|
|
203
|
+
* proportional safety benefit.
|
|
204
|
+
* - Strict users who actually want block-first can opt back in
|
|
205
|
+
* via COMPACT_AGENT_GATEGUARD_MODE=block.
|
|
206
|
+
*
|
|
207
|
+
* State lives at ~/.compact-agent/state/gateguard/<sessionId>.json
|
|
208
|
+
* even in warn mode — tracking per-file means we only emit the hint
|
|
209
|
+
* once per file per session (don't nag).
|
|
190
210
|
*
|
|
191
211
|
* Auto-cleanup: state files older than 24h are deleted on next run.
|
|
192
212
|
*
|
|
@@ -194,10 +214,9 @@ const checks = {
|
|
|
194
214
|
*/
|
|
195
215
|
'gateguard': () => {
|
|
196
216
|
// ── Disable knob ─────────────────────────────────────
|
|
197
|
-
// Documented in the block message below. Accepts the
|
|
217
|
+
// Documented in the hint/block message below. Accepts the
|
|
198
218
|
// COMPACT_AGENT_GATEGUARD env var primarily, with the legacy
|
|
199
|
-
// CROWCODER_GATEGUARD
|
|
200
|
-
// muscle memory still work.
|
|
219
|
+
// CROWCODER_GATEGUARD as alias.
|
|
201
220
|
const disableEnv = (
|
|
202
221
|
process.env.COMPACT_AGENT_GATEGUARD ||
|
|
203
222
|
process.env.CROWCODER_GATEGUARD ||
|
|
@@ -205,6 +224,16 @@ const checks = {
|
|
|
205
224
|
).trim();
|
|
206
225
|
if (/^(off|false|0|no|disabled?)$/i.test(disableEnv)) return ok();
|
|
207
226
|
|
|
227
|
+
// ── Mode selection ───────────────────────────────────
|
|
228
|
+
// Pick warn (new default) vs block (legacy strict) vs off.
|
|
229
|
+
const modeEnv = (
|
|
230
|
+
process.env.COMPACT_AGENT_GATEGUARD_MODE ||
|
|
231
|
+
process.env.CROWCODER_GATEGUARD_MODE ||
|
|
232
|
+
'warn'
|
|
233
|
+
).toLowerCase().trim();
|
|
234
|
+
if (modeEnv === 'off') return ok();
|
|
235
|
+
const strict = modeEnv === 'block' || modeEnv === 'strict';
|
|
236
|
+
|
|
208
237
|
// ── yolo bypass ──────────────────────────────────────
|
|
209
238
|
// Permission mode 'yolo' is the user's explicit "trust the agent,
|
|
210
239
|
// skip the speed bumps" contract. GateGuard's investigate-first
|
|
@@ -273,24 +302,34 @@ const checks = {
|
|
|
273
302
|
}
|
|
274
303
|
} catch { /* corrupt state: treat as empty */ }
|
|
275
304
|
|
|
276
|
-
if (touched.has(targetPath)) return ok(); // already
|
|
305
|
+
if (touched.has(targetPath)) return ok(); // already seen this file this session
|
|
277
306
|
|
|
278
|
-
// First touch — record
|
|
307
|
+
// First touch — record. In strict (block) mode we block here; in
|
|
308
|
+
// warn (default) mode we print the hint as a one-line warning and
|
|
309
|
+
// exit ok() so the edit proceeds. Persist either way so the next
|
|
310
|
+
// edit to the same file doesn't re-emit the hint.
|
|
279
311
|
touched.add(targetPath);
|
|
280
312
|
try {
|
|
281
313
|
fs.mkdirSync(stateDir, { recursive: true });
|
|
282
314
|
fs.writeFileSync(stateFile, JSON.stringify([...touched]), 'utf-8');
|
|
283
|
-
} catch { /* if we can't persist, still
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
315
|
+
} catch { /* if we can't persist, still emit the hint this one time */ }
|
|
316
|
+
|
|
317
|
+
if (strict) {
|
|
318
|
+
return block(
|
|
319
|
+
`First Edit/Write to ${targetPath} this session. Before proceeding, ` +
|
|
320
|
+
`investigate: (1) Read the file. (2) Grep for importers. ` +
|
|
321
|
+
`(3) If schema/type, check existing data. After investigating, ` +
|
|
322
|
+
`retry the edit. Set COMPACT_AGENT_GATEGUARD_MODE=warn to switch ` +
|
|
323
|
+
`to non-blocking hints, or =off to disable. /perm yolo also bypasses.`,
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
// Warn mode (default): one-line hint, exit 0 so the edit proceeds.
|
|
327
|
+
process.stderr.write(
|
|
328
|
+
`[ECC hint] first edit to ${targetPath} this session — make sure ` +
|
|
329
|
+
`you've read it + checked for callers. (set ` +
|
|
330
|
+
`COMPACT_AGENT_GATEGUARD_MODE=block to enforce, =off to silence)\n`,
|
|
293
331
|
);
|
|
332
|
+
return ok();
|
|
294
333
|
},
|
|
295
334
|
|
|
296
335
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "compact-agent",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1",
|
|
4
4
|
"description": "Terminal AI coding CLI. Speaks any OpenAI-compatible API (OpenRouter, OpenAI, NVIDIA, Ollama, LM Studio, DeepSeek). Modes, slash commands, multi-agent swarming, key-rotation pool, optional voice + screen-reader, sandbox + permission gates, persistent input box, bundled everything-claude-code skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|