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.
@@ -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, skip the hard block entirely.
163
- // The fill % is still computed above for advisory purposes.
164
- if (sessionId) {
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
- console.log(JSON.stringify({
270
- decision: 'block',
271
- reason: '[COMPANY] Context at ' + pct + '% (>= ' + threshPct + '% threshold). ' +
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "company-skill",
3
- "version": "4.6.5",
3
+ "version": "4.6.6",
4
4
  "description": "Goal-driven multi-employee company for Claude Code. Give it a goal, it runs until done.",
5
5
  "bin": {
6
6
  "company-skill": "./bin/install.js"