company-skill 4.6.5 → 4.6.6
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/hooks/context-guard.js +33 -9
- package/package.json +1 -1
package/hooks/context-guard.js
CHANGED
|
@@ -48,6 +48,20 @@ function parseThreshold() {
|
|
|
48
48
|
return v > 1 ? v / 100 : v;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// Hard ceiling: the toggle CANNOT suppress a block at or above this level.
|
|
52
|
+
// Default 0.80. Overridable via COMPANY_CONTEXT_HARD_CEILING (fraction or percent).
|
|
53
|
+
// If the parsed value is below the soft threshold, it is clamped up to the threshold.
|
|
54
|
+
function parseHardCeiling(threshold) {
|
|
55
|
+
const raw = process.env.COMPANY_CONTEXT_HARD_CEILING;
|
|
56
|
+
if (!raw) return 0.80;
|
|
57
|
+
const v = parseFloat(raw);
|
|
58
|
+
if (isNaN(v)) return 0.80;
|
|
59
|
+
// accept either fraction (0.8) or percent (80)
|
|
60
|
+
const frac = v > 1 ? v / 100 : v;
|
|
61
|
+
// hard ceiling must be >= soft threshold
|
|
62
|
+
return frac >= threshold ? frac : threshold;
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
// Read stdin synchronously (fd 0). Fail-open on any error.
|
|
52
66
|
let stdinData = null;
|
|
53
67
|
try {
|
|
@@ -152,6 +166,7 @@ const used =
|
|
|
152
166
|
|
|
153
167
|
const contextWindow = detectWindow(lastModelId);
|
|
154
168
|
const threshold = parseThreshold();
|
|
169
|
+
const hardCeiling = parseHardCeiling(threshold);
|
|
155
170
|
const fill = used / contextWindow;
|
|
156
171
|
|
|
157
172
|
if (fill < threshold) process.exit(0);
|
|
@@ -159,9 +174,10 @@ if (fill < threshold) process.exit(0);
|
|
|
159
174
|
// Per-session toggle: read .company/context-guard-config.json for this session.
|
|
160
175
|
// Shape: { "sessions": { "<id>": { "enforceRestart": true|false } } }
|
|
161
176
|
// Default (no file, no entry, parse error) = enforceRestart: true (safe default).
|
|
162
|
-
// If enforceRestart === false for this session,
|
|
163
|
-
//
|
|
164
|
-
|
|
177
|
+
// If enforceRestart === false for this session, and fill is BELOW the hard ceiling,
|
|
178
|
+
// the toggle suppresses the soft-threshold block. At or above the hard ceiling the
|
|
179
|
+
// toggle has no effect and we fall through to block unconditionally.
|
|
180
|
+
if (sessionId && fill < hardCeiling) {
|
|
165
181
|
const cfgPath = path.join(companyDir, 'context-guard-config.json');
|
|
166
182
|
try {
|
|
167
183
|
const cfgRaw = fs.readFileSync(cfgPath, 'utf8');
|
|
@@ -170,7 +186,7 @@ if (sessionId) {
|
|
|
170
186
|
cfg.sessions && typeof cfg.sessions === 'object' &&
|
|
171
187
|
cfg.sessions[sessionId] && typeof cfg.sessions[sessionId] === 'object' &&
|
|
172
188
|
cfg.sessions[sessionId].enforceRestart === false) {
|
|
173
|
-
// Toggle is OFF: allow through without blocking
|
|
189
|
+
// Toggle is OFF and below the hard ceiling: allow through without blocking
|
|
174
190
|
process.exit(0);
|
|
175
191
|
}
|
|
176
192
|
// Any other value (true, missing, or unknown) falls through to block
|
|
@@ -264,13 +280,21 @@ try {
|
|
|
264
280
|
|
|
265
281
|
const pct = Math.round(fill * 100);
|
|
266
282
|
const threshPct = Math.round(threshold * 100);
|
|
283
|
+
const ceilPct = Math.round(hardCeiling * 100);
|
|
267
284
|
const sessionTag = sessionId ? ' [session ' + sessionId + ']' : '';
|
|
268
285
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
286
|
+
// Emit a distinct reason when the hard ceiling is what's enforcing the block.
|
|
287
|
+
const atHardCeiling = fill >= hardCeiling;
|
|
288
|
+
const reason = atHardCeiling
|
|
289
|
+
? '[COMPANY] Context at ' + pct + '% (>= ' + ceilPct + '% HARD CEILING). ' +
|
|
290
|
+
'The per-session enforceRestart toggle CANNOT suppress this restart. ' +
|
|
291
|
+
'Run /company restart NOW: quiesce in-flight agents, commit their work as draft PRs, ' +
|
|
292
|
+
'refresh STATUS/NEXT, run the restart debate gate, and emit the verified continuation prompt.' +
|
|
293
|
+
sessionTag
|
|
294
|
+
: '[COMPANY] Context at ' + pct + '% (>= ' + threshPct + '% threshold). ' +
|
|
272
295
|
'Run /company restart NOW: quiesce in-flight agents, commit their work as draft PRs, ' +
|
|
273
296
|
'refresh STATUS/NEXT, run the restart debate gate, and emit the verified continuation prompt. ' +
|
|
274
|
-
'This is enforced, not advisory - do not continue new work.' + sessionTag
|
|
275
|
-
|
|
297
|
+
'This is enforced, not advisory - do not continue new work.' + sessionTag;
|
|
298
|
+
|
|
299
|
+
console.log(JSON.stringify({ decision: 'block', reason: reason }));
|
|
276
300
|
process.exit(0);
|