chati-dev 4.1.2 → 4.1.3

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.
@@ -156,14 +156,14 @@ WHILE tasks_pending:
156
156
  → If no architecture.md → proceed with best practices
157
157
  3. Implement code
158
158
  -> Output: "T{X} implementation done. Self-critique (5.5)..."
159
- 3. Run self-critique (Step 5.5) — 1 fix pass, then proceed
159
+ 4. Run self-critique (Step 5.5) — 1 fix pass, then proceed
160
160
  -> Output: "T{X} critique done. Running tests..."
161
- 4. Run tests (once)
161
+ 5. Run tests (once)
162
162
  -> Output: "T{X} tests: {N}/{total} passed. Post-test review (6.5)..."
163
- 5. Run post-test critique (Step 6.5) — 1 fix pass, then score
163
+ 6. Run post-test critique (Step 6.5) — 1 fix pass, then score
164
164
  -> Output: "T{X} review done. Scoring..."
165
- 6. Self-validate against acceptance criteria
166
- 7. Calculate score
165
+ 7. Self-validate against acceptance criteria
166
+ 8. Calculate score
167
167
 
168
168
  IF score >= 95:
169
169
  mark_complete(task)
@@ -1,8 +1,8 @@
1
1
  # chati.dev Configuration
2
- version: "4.1.2"
2
+ version: "4.1.3"
3
3
  installed_at: "2026-02-07T10:00:00Z"
4
- updated_at: "2026-04-04T00:00:00Z"
5
- installer_version: "4.1.2"
4
+ updated_at: "2026-04-06T00:00:00Z"
5
+ installer_version: "4.1.3"
6
6
  project_type: greenfield
7
7
  language: en
8
8
  ides: [claude-code]
@@ -276,11 +276,11 @@ The pipeline operates in three execution modes that control agent permissions. M
276
276
 
277
277
  1. The orchestrator SHALL calculate the context bracket (FRESH, MODERATE, DEPLETED, CRITICAL) before every agent interaction.
278
278
 
279
- 2. Context injection layers SHALL be reduced according to bracket level:
280
- - FRESH: All 6 layers (L0-L5)
281
- - MODERATE: L0 + L1 + L2 + L3 + L5 (skip L4 task detail)
282
- - DEPLETED: L0 (Constitution) + L1 (Mode) + L2 (Agent) only
283
- - CRITICAL: L0 (Constitution) + L1 (Mode) only
279
+ 2. Context injection layers SHALL INCREASE as context depletes (Progressive Reinforcement):
280
+ - FRESH: L0 (Constitution) + L1 (Global) only — model has full memory, minimal reinforcement
281
+ - MODERATE: L0 + L1 + L2 (Agent) + L3 (Workflow) model starting to forget
282
+ - DEPLETED: All 6 layers (L0-L5) significant context loss, full reinforcement
283
+ - CRITICAL: All 6 layers (L0-L5) + forced handoff — maximum reinforcement, do not accept degraded output
284
284
 
285
285
  3. Context recovery uses a two-level autonomous strategy:
286
286
  a. Level 1 (Smart Continuation): When context is compacted, the orchestrator SHALL automatically capture a digest, persist memories, and rebuild context post-compact. The user experiences zero interruption.
@@ -424,11 +424,13 @@ The system SHALL support two execution modes that govern the degree of human inv
424
424
  - **brief**: Requirements extraction requires human validation
425
425
  - **orchestrator (deviation protocol)**: Deviations from the plan always need human approval
426
426
 
427
- 5. Safety net triggers SHALL pause autonomous execution when dangerous conditions are detected: consecutive failures, circular approaches, resource limits, or destructive operations.
427
+ 5. **Terminology Note:** "Autonomous" in this article controls WHO evaluates gates (system vs human). Article XVIII's "autonomous" profile controls WHETHER confirmation is required for writes. Both must be satisfied for fully autonomous operation: this article's mode active AND Article XVIII cumulative gate score >= 95%.
428
428
 
429
- 6. Circuit breaker pattern: After 3 consecutive gate failures at the same pipeline point, the system SHALL pause and escalate to human review regardless of mode.
429
+ 6. Safety net triggers SHALL pause autonomous execution when dangerous conditions are detected: consecutive failures, circular approaches, resource limits, or destructive operations.
430
430
 
431
- 7. Mode transitions are logged in session.yaml under `mode_transitions[]` for audit trail.
431
+ 7. Circuit breaker pattern: After 3 consecutive gate failures at the same pipeline point, the system SHALL pause and escalate to human review regardless of mode.
432
+
433
+ 8. Mode transitions are logged in session.yaml under `mode_transitions[]` for audit trail.
432
434
 
433
435
  **Enforcement: STRICT** — Autonomous mode MUST NOT bypass quality gates. All agents MUST respect the configured thresholds.
434
436
 
@@ -487,5 +489,5 @@ When multiple CLI providers are enabled, the system SHALL coordinate agent execu
487
489
 
488
490
  ---
489
491
 
490
- *Chati.dev Constitution v4.1.2 — 19 Articles + Preamble*
492
+ *Chati.dev Constitution v4.1.3 — 19 Articles + Preamble*
491
493
  *All agents are bound by this Constitution. Violations are enforced per article.*
@@ -1,7 +1,7 @@
1
1
  # Chati.dev System Context
2
2
 
3
3
  ## Framework
4
- - **Version**: 4.1.2
4
+ - **Version**: 4.1.3
5
5
  - **Agents**: Specialized agents across DISCOVER, PLAN, BUILD, DEPLOY phases
6
6
  - **Constitution**: 19 Articles + Preamble
7
7
  - **Quality**: 5 pipeline gates + 3-tier verdicts (APPROVED / NEEDS_REVISION / BLOCKED)
@@ -3,7 +3,7 @@
3
3
  # and by the Health Check for system integrity validation.
4
4
 
5
5
  metadata:
6
- version: "4.1.2"
6
+ version: "4.1.3"
7
7
  last_updated: "2026-04-06T00:00:00Z"
8
8
  entity_count: 62
9
9
  checksum_algorithm: sha256
@@ -79,10 +79,10 @@ modes:
79
79
 
80
80
  brackets:
81
81
  FRESH:
82
- behavior: "Moderate context injection. All layers active but model is warming up. Budget lower than MODERATE."
82
+ behavior: "Minimal reinforcement. L0+L1 only. Model has full memory, no need to re-inject context."
83
83
  MODERATE:
84
- behavior: "Peak context injection. Maximum token budget. Model has context and needs maximum reinforcement."
84
+ behavior: "Growing reinforcement. L0-L3 active. Model starting to forget initial instructions."
85
85
  DEPLETED:
86
- behavior: "Reduced injection. Only L0+L1+L2. Use rule IDs instead of full text."
86
+ behavior: "Full reinforcement. All 6 layers (L0-L5) active. Significant context loss, compensate with maximum injection."
87
87
  CRITICAL:
88
- behavior: "Emergency. L0+L1 only. Trigger handoff advisory. Preserve essential state."
88
+ behavior: "Emergency reinforcement. All 6 layers (L0-L5) active. Trigger handoff. Do not accept degraded output."
@@ -140,7 +140,7 @@ const SHELL_INJECTION_CHECKS = [
140
140
  { id: 'JQ_SYSTEM_FUNCTION', pattern: /jq\b.*\bsystem\s*\(/i, severity: 'critical' },
141
141
  { id: 'JQ_FILE_ARGUMENTS', pattern: /jq\b.*--from-file|jq\b.*-f\s+[^|&;]+/i, severity: 'high' },
142
142
  { id: 'OBFUSCATED_FLAGS', pattern: /\$[({].*[)}].*-/, severity: 'high' },
143
- { id: 'SHELL_METACHARACTERS', pattern: /[`]|(?:\$\((?!.*\becho\b))/, severity: 'critical' },
143
+ { id: 'SHELL_METACHARACTERS', pattern: /[`]|\$\(/, severity: 'critical' },
144
144
  { id: 'DANGEROUS_VARIABLES', pattern: /(?:^|\s)(?:PATH|LD_PRELOAD|LD_LIBRARY_PATH|DYLD_INSERT_LIBRARIES|PYTHONPATH|NODE_PATH|RUBYLIB|PERL5LIB)\s*=/, severity: 'critical' },
145
145
  { id: 'NEWLINES', pattern: /(?<!\\)\n.*(?:rm|curl|wget|chmod|chown|sudo|eval|exec)/, severity: 'high' },
146
146
  { id: 'BACKSLASH_ESCAPED_WHITESPACE', pattern: /\\\s+(?:-|\/)/,severity: 'medium' },
@@ -79,16 +79,17 @@ async function main() {
79
79
  return 200_000;
80
80
  }
81
81
 
82
+ // Primary: turn-count tracks cumulative context consumption across the session.
83
+ // Fallback: prompt-length for first turn or missing session data.
82
84
  let remainingPercent;
83
- const promptText = event.prompt || '';
84
- if (promptText.length > 0) {
85
+ const maxTurns = 40;
86
+ if (session.turnCount > 0) {
87
+ remainingPercent = Math.max(0, Math.round((1 - session.turnCount / maxTurns) * 100));
88
+ } else {
89
+ const promptText = event.prompt || '';
85
90
  const estimatedTokens = Math.ceil(promptText.length / 4);
86
91
  const contextLimit = hookResolveLimit(inferredModel, session.provider);
87
92
  remainingPercent = Math.max(0, Math.round((1 - estimatedTokens / contextLimit) * 100));
88
- } else {
89
- // Fallback to turn-count heuristic when prompt text unavailable
90
- const maxTurns = 40;
91
- remainingPercent = Math.max(0, Math.round((1 - session.turnCount / maxTurns) * 100));
92
93
  }
93
94
 
94
95
  // Determine bracket
@@ -12,10 +12,10 @@ Four brackets define behavior based on remaining context:
12
12
 
13
13
  | Bracket | Context Remaining | Behavior |
14
14
  |---------|-------------------|----------|
15
- | **FRESH** | 60-100% | All 6 layers active. Minimal reinforcement (1.5%) — context is plentiful. No memory injection. |
16
- | **MODERATE** | 40-60% | 5 layers (skip L4). Growing reinforcement (2.5%) — model starting to forget. Metadata memory. |
17
- | **DEPLETED** | 25-40% | 3 layers (L0-L2). Heavy reinforcement (4.0%) — significant context loss. Chunk memory recovery. |
18
- | **CRITICAL** | <25% | 2 layers (L0-L1). Maximum reinforcement (5.0%) — last interactions before handoff. Full memory dump. |
15
+ | **FRESH** | 60-100% | 2 layers (L0-L1). Minimal reinforcement (1.5%) — model has full memory, no need to re-inject. |
16
+ | **MODERATE** | 40-60% | 4 layers (L0-L3). Growing reinforcement (2.5%) — model starting to forget. |
17
+ | **DEPLETED** | 25-40% | All 6 layers (L0-L5). Heavy reinforcement (4.0%) — significant context loss, full re-injection. |
18
+ | **CRITICAL** | <25% | All 6 layers (L0-L5). Maximum reinforcement (5.0%) — forced handoff, do not accept degraded output. |
19
19
 
20
20
  ### Static/Dynamic PRISM Boundary
21
21
 
@@ -38,18 +38,18 @@ The orchestrator injects context through 6 hierarchical layers:
38
38
  | **L2** | Agent Scope | `chati.dev/agents/{agent}/` — mission, inputs, outputs, criteria | When agent is active |
39
39
  | **L3** | Pipeline State | `.chati/session.yaml` — pipeline position, scores, backlog | When session is active |
40
40
  | **L4** | Task Context | Active artifact + previous agent's handoff | When task is active |
41
- | **L5** | Keywords | `chati.dev/domains/keywords/` — dynamic rules from user prompt | FRESH + MODERATE only |
41
+ | **L5** | Keywords | `chati.dev/domains/keywords/` — dynamic rules from user prompt | DEPLETED + CRITICAL only |
42
42
 
43
43
  ### Layer Activation by Bracket
44
44
 
45
45
  | Bracket | Active Layers | Budget Ratio | Claude (200K) | Gemini (1M) | Codex (128K) |
46
46
  |---------|--------------|-------------|---------------|-------------|--------------|
47
- | FRESH | L0, L1, L2, L3, L4, L5 | 1.5% | 3,000 | 15,000 | 1,920 |
48
- | MODERATE | L0, L1, L2, L3, L5 | 2.5% | 5,000 | 25,000 | 3,200 |
49
- | DEPLETED | L0, L1, L2 | 4.0% | 8,000 | 40,000 | 5,120 |
50
- | CRITICAL | L0, L1 | 5.0% | 10,000 | 50,000 | 6,400 |
47
+ | FRESH | L0, L1 | 1.5% | 3,000 | 15,000 | 1,920 |
48
+ | MODERATE | L0, L1, L2, L3 | 2.5% | 5,000 | 25,000 | 3,200 |
49
+ | DEPLETED | L0, L1, L2, L3, L4, L5 | 4.0% | 8,000 | 40,000 | 5,120 |
50
+ | CRITICAL | L0, L1, L2, L3, L4, L5 | 5.0% | 10,000 | 50,000 | 6,400 |
51
51
 
52
- Budgets are proportional to the provider's context window. As context degrades, fewer layers are active (focus) but each active layer receives MORE reinforcement tokens (strength).
52
+ Progressive Reinforcement: as context depletes, BOTH budget AND layers increase. The model forgets initial instructions and needs more reinforcement, not less.
53
53
 
54
54
  ---
55
55
 
@@ -182,7 +182,7 @@ Memory injection follows the same progressive reinforcement principle: as contex
182
182
 
183
183
  ## Constitution Reference
184
184
 
185
- **Article XII: Context Bracket Governance** — Brackets are calculated automatically. In CRITICAL, only L0+L1 are injected. Handoff is mandatory when context < 15%.
185
+ **Article XII: Context Bracket Governance** — Brackets are calculated automatically. In CRITICAL, all 6 layers (L0-L5) are injected for maximum reinforcement. Handoff is mandatory when context < 15%.
186
186
 
187
187
  ---
188
188
 
@@ -429,6 +429,8 @@ interactive (default):
429
429
  → All 8 universal protocols apply.
430
430
 
431
431
  autonomous (Ralph Wiggum mode):
432
+ → Requires: most recent QA gate score >= 95% (Article XVIII prerequisite).
433
+ → If quality gate not met, inform user and suggest guided mode instead.
432
434
  → Agent executes without asking unless blocker encountered.
433
435
  → Primarily for Dev agent during BUILD phase.
434
436
  → QA gates always run regardless of mode.
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "agent": {
21
21
  "type": "object",
22
- "description": "Active agent scope information (L2 layer, active when bracket >= DEPLETED)",
22
+ "description": "Active agent scope information (L2 layer, active when bracket >= MODERATE)",
23
23
  "required": ["name", "mission"],
24
24
  "properties": {
25
25
  "name": { "type": "string", "description": "Agent identifier" },
@@ -32,14 +32,15 @@
32
32
  "pipeline": {
33
33
  "type": "string",
34
34
  "description": "Pipeline state string showing agent progression (L3 layer, active when bracket >= MODERATE)"
35
+
35
36
  },
36
37
  "task": {
37
38
  "type": "string",
38
- "description": "Current task description (L4 layer, active when bracket >= MODERATE)"
39
+ "description": "Current task description (L4 layer, active when bracket = DEPLETED or CRITICAL)"
39
40
  },
40
41
  "handoff": {
41
42
  "type": "object",
42
- "description": "Previous agent handoff summary (L4 layer, active when bracket >= MODERATE)",
43
+ "description": "Previous agent handoff summary (L4 layer, active when bracket = DEPLETED or CRITICAL)",
43
44
  "properties": {
44
45
  "from": { "type": "string", "description": "Source agent name" },
45
46
  "score": { "type": "number", "minimum": 0, "maximum": 100, "description": "Source agent final score" },
@@ -83,7 +84,7 @@
83
84
  "injection_budget": {
84
85
  "type": "integer",
85
86
  "minimum": 0,
86
- "description": "Token budget for context injection (FRESH: 2500, MODERATE: 2000, DEPLETED: 1500, CRITICAL: 800)"
87
+ "description": "Token budget for context injection — Progressive Reinforcement: FRESH 1.5%, MODERATE 2.5%, DEPLETED 4.0%, CRITICAL 5.0% of provider context window"
87
88
  }
88
89
  }
89
90
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chati-dev",
3
- "version": "4.1.2",
3
+ "version": "4.1.3",
4
4
  "description": "AI-Powered Multi-Agent Orchestration System — Structured vibe coding for Full Stack Development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,21 +1,20 @@
1
1
  /**
2
2
  * Bracket Tracker — Pure arithmetic for context window management.
3
3
  *
4
- * Brackets determine how much context to inject:
5
- * FRESH (60-100%) → All 6 layers active (L0-L5)
6
- * MODERATE (40-60%) → L0 + L1 + L2 + L3 + L5 (skip L4 task detail)
7
- * DEPLETED (25-40%) → L0 + L1 + L2 only
8
- * CRITICAL (<25%) → L0 + L1 only (handoff mandatory)
4
+ * Brackets determine how much context to inject (Progressive Reinforcement):
5
+ * FRESH (60-100%) → L0 + L1 only (model has full memory, minimal reinforcement)
6
+ * MODERATE (40-60%) → L0 + L1 + L2 + L3 (model starting to forget)
7
+ * DEPLETED (25-40%) → All 6 layers L0-L5 (significant context loss, full reinforcement)
8
+ * CRITICAL (<25%) → All 6 layers L0-L5 + handoff mandatory (maximum reinforcement)
9
9
  *
10
- * Progressive Reinforcement Model (v4.0):
11
- * As context window depletes, the model forgets initial instructions
12
- * and needs MORE reinforcement, not less. Budget expressed as percentage
13
- * of the provider's total context window — proportional across providers.
10
+ * Progressive Reinforcement Model (v4.1.2):
11
+ * As context depletes, BOTH budget AND layers INCREASE.
12
+ * The model forgets initial instructions and needs MORE reinforcement.
14
13
  *
15
- * FRESH = 1.5% minimal reinforcement (context is plentiful)
16
- * MODERATE = 2.5% → growing reinforcement (model starting to forget)
17
- * DEPLETED = 4.0% → heavy reinforcement (significant context loss)
18
- * CRITICAL = 5.0% → maximum reinforcement (last interactions before handoff)
14
+ * FRESH = 1.5% budget, 2 layers context intact, no need to re-inject
15
+ * MODERATE = 2.5% budget, 4 layers → growing reinforcement
16
+ * DEPLETED = 4.0% budget, 6 layers full layer injection to compensate loss
17
+ * CRITICAL = 5.0% budget, 6 layers → maximum reinforcement + forced handoff
19
18
  */
20
19
 
21
20
  import { resolveContextLimit } from '../utils/provider-limits.js';
@@ -54,8 +54,9 @@ export function formatContext(options) {
54
54
 
55
55
  // Insert STATIC_BOUNDARY between static (L0+L1) and dynamic (L2-L5) sections.
56
56
  // This enables prompt cache reuse for the stable prefix (Claude Code pattern).
57
- const staticSections = sections.slice(0, l1 ? 2 : (l0 ? 1 : 0));
58
- const dynamicSections = sections.slice(staticSections.length);
57
+ const staticCount = l1 ? 2 : (l0 ? 1 : 0);
58
+ const staticSections = sections.slice(0, staticCount);
59
+ const dynamicSections = sections.slice(staticCount);
59
60
 
60
61
  let body;
61
62
  if (dynamicSections.length > 0) {
@@ -69,7 +70,7 @@ export function formatContext(options) {
69
70
  // Truncate if over budget (rough estimate: 1 token ≈ 4 chars)
70
71
  const maxChars = tokenBudget * 4;
71
72
  if (body.length > maxChars) {
72
- body = truncateByPriority(sections, maxChars);
73
+ body = truncateByPriority(sections, maxChars, staticCount);
73
74
  }
74
75
 
75
76
  return `<chati-context bracket="${bracket}">\n${body}\n</chati-context>`;
@@ -190,14 +191,28 @@ function formatKeywords(l5) {
190
191
  * Truncate sections by removing lower-priority layers first (L4 → L3 → L2).
191
192
  * L0 and L1 are never truncated.
192
193
  */
193
- function truncateByPriority(sections, maxChars) {
194
- let result = sections.join('\n\n');
195
- // Remove from end (lowest priority) until within budget
194
+ function truncateByPriority(sections, maxChars, staticCount = 2) {
195
+ const boundaryMarker = '\n\n <!-- STATIC_BOUNDARY -->\n\n';
196
196
  const trimmed = [...sections];
197
- while (trimmed.length > 2 && result.length > maxChars) {
197
+ const hasDynamic = () => trimmed.length > staticCount;
198
+ const overhead = hasDynamic() ? boundaryMarker.length : 0;
199
+ const adjustedMax = maxChars - overhead;
200
+
201
+ // Remove from end (lowest priority) until within budget
202
+ while (trimmed.length > staticCount && trimmed.join('\n\n').length > adjustedMax) {
198
203
  trimmed.pop();
204
+ }
205
+
206
+ // Re-insert boundary if we still have both static and dynamic sections
207
+ let result;
208
+ if (hasDynamic()) {
209
+ result = trimmed.slice(0, staticCount).join('\n\n') +
210
+ boundaryMarker +
211
+ trimmed.slice(staticCount).join('\n\n');
212
+ } else {
199
213
  result = trimmed.join('\n\n');
200
214
  }
215
+
201
216
  // If still over, hard truncate
202
217
  if (result.length > maxChars) {
203
218
  result = result.slice(0, maxChars) + '\n <!-- truncated -->';
@@ -6,7 +6,7 @@
6
6
  * L0-L4 handle WHO (agent) and WHERE (workflow/task)
7
7
  * L5 handles WHAT (topic detection from user prompt)
8
8
  *
9
- * Only active in FRESH and MODERATE brackets (expensive layer).
9
+ * Only active in DEPLETED and CRITICAL brackets (reinforcement layer).
10
10
  */
11
11
 
12
12
  import { loadKeywordDomains } from '../domain-loader.js';
@@ -45,6 +45,14 @@ export function runDreamConsolidation(projectDir) {
45
45
  // Phase 4: Prune
46
46
  report.phase4 = prune(projectDir, report.phase3.consolidated);
47
47
 
48
+ // Write consolidated memories to disk
49
+ try {
50
+ const sharedDir = join(projectDir, '.chati', 'memories', 'shared');
51
+ mkdirSync(sharedDir, { recursive: true });
52
+ const consolidatedPath = join(sharedDir, 'consolidated.json');
53
+ writeFileSync(consolidatedPath, JSON.stringify(report.phase4.entries, null, 2), 'utf-8');
54
+ } catch (err) { process.stderr.write(`[chati] dream write consolidated: ${err.message}\n`); }
55
+
48
56
  // Summary
49
57
  report.summary = {
50
58
  merged: report.phase3.mergedCount,
@@ -198,6 +206,7 @@ function prune(projectDir, consolidated) {
198
206
  prunedCount: 0,
199
207
  archivedCount: 0,
200
208
  remaining: consolidated.length,
209
+ entries: consolidated,
201
210
  };
202
211
  }
203
212
 
@@ -238,6 +247,7 @@ function prune(projectDir, consolidated) {
238
247
  prunedCount: toRemove.length,
239
248
  archivedCount,
240
249
  remaining: toKeep.length,
250
+ entries: toKeep,
241
251
  };
242
252
  }
243
253
 
@@ -115,7 +115,7 @@ export function extractMemories(text, context = {}) {
115
115
  // Build memory entries following memory.schema.json
116
116
  const now = new Date().toISOString();
117
117
  return selected.map((candidate, i) => ({
118
- id: `mem-${now.split('T')[0]}-${String(i + 1).padStart(3, '0')}`,
118
+ id: `mem-${now.replace(/[:.]/g, '-')}-${String(i + 1).padStart(3, '0')}`,
119
119
  type: candidate.type,
120
120
  agent: context.agent || 'unknown',
121
121
  content: candidate.content,
@@ -178,7 +178,8 @@ function resolveAgentModel(agent, projectDir) {
178
178
  if (existsSync(configPath)) {
179
179
  const configRaw = readFileSync(configPath, 'utf-8');
180
180
  // Simple YAML parsing for agent_overrides section
181
- const overrideMatch = configRaw.match(new RegExp(`${agent}:\\s*\\n\\s+provider:\\s*(\\w+)`, 'm'));
181
+ const escapedAgent = agent.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
182
+ const overrideMatch = configRaw.match(new RegExp(`${escapedAgent}:\\s*\\n\\s+provider:\\s*(\\w+)`, 'm'));
182
183
  if (overrideMatch) {
183
184
  return { ...defaults, provider: overrideMatch[1] };
184
185
  }
@@ -13,7 +13,9 @@ const TECH_NAMES = [
13
13
  /\bExpress\b/g, /\bFastify\b/g, /\bDjango\b/g, /\bFlask\b/g, /\bLaravel\b/g,
14
14
  /\bAWS\b/g, /\bVercel\b/g, /\bNetlify\b/g, /\bRailway\b/g, /\bCloudflare\b/g,
15
15
  /\bDocker\b/g, /\bKubernetes\b/g, /\bRedis\b/g, /\bGraphQL\b/gi,
16
- /\bTypeScript\b/gi, /\bJavaScript\b/gi, /\bPython\b/g, /\bRust\b/g, /\bGo\b/g,
16
+ /\bTypeScript\b/gi, /\bJavaScript\b/gi, /\bPython\b/g,
17
+ /\bRustlang\b|\bRust\s+(?:lang|crate|cargo|tokio|async|compiler)\b/gi,
18
+ /\bGolang\b|\bGo\s+(?:module|package|routine|channel|func|goroutine)\b/g,
17
19
  /\bZod\b/g, /\bJoi\b/g, /\bZustand\b/g, /\bRedux\b/g, /\bJotai\b/g,
18
20
  ];
19
21
 
@@ -62,9 +62,9 @@ export const SECURITY_CHECKS = [
62
62
  {
63
63
  id: 'SHELL_METACHARACTERS',
64
64
  name: 'Shell metacharacter injection',
65
- pattern: /[`]|(?:\$\((?!.*\becho\b))/,
65
+ pattern: /[`]|\$\(/,
66
66
  severity: 'critical',
67
- description: 'Backticks or $() command substitution (excluding safe echo patterns)',
67
+ description: 'Backticks or $() command substitution',
68
68
  },
69
69
  {
70
70
  id: 'DANGEROUS_VARIABLES',
@@ -4,8 +4,10 @@
4
4
  * Single source of truth for bracket thresholds, layer configurations,
5
5
  * and budget ratios. Consumers import from here to avoid duplication.
6
6
  *
7
- * Progressive Reinforcement Model (v4.0):
8
- * As context depletes, budget INCREASES (model needs MORE reinforcement).
7
+ * Progressive Reinforcement Model (v4.1.2):
8
+ * As context depletes, both budget AND layers INCREASE.
9
+ * FRESH = model has full memory, minimal reinforcement needed.
10
+ * CRITICAL = model forgot initial instructions, maximum reinforcement + handoff.
9
11
  * Budget expressed as ratio of provider's total context window.
10
12
  */
11
13
 
@@ -14,10 +16,10 @@
14
16
  * @type {Record<string, {min: number, max: number, layers: string[], budgetRatio: number}>}
15
17
  */
16
18
  export const BRACKETS = {
17
- FRESH: { min: 60, max: 100, layers: ['L0', 'L1', 'L2', 'L3', 'L4', 'L5'], budgetRatio: 0.015 },
18
- MODERATE: { min: 40, max: 60, layers: ['L0', 'L1', 'L2', 'L3', 'L5'], budgetRatio: 0.025 },
19
- DEPLETED: { min: 25, max: 40, layers: ['L0', 'L1', 'L2'], budgetRatio: 0.040 },
20
- CRITICAL: { min: 0, max: 25, layers: ['L0', 'L1'], budgetRatio: 0.050 },
19
+ FRESH: { min: 60, max: 100, layers: ['L0', 'L1'], budgetRatio: 0.015 },
20
+ MODERATE: { min: 40, max: 60, layers: ['L0', 'L1', 'L2', 'L3'], budgetRatio: 0.025 },
21
+ DEPLETED: { min: 25, max: 40, layers: ['L0', 'L1', 'L2', 'L3', 'L4', 'L5'], budgetRatio: 0.040 },
22
+ CRITICAL: { min: 0, max: 25, layers: ['L0', 'L1', 'L2', 'L3', 'L4', 'L5'], budgetRatio: 0.050 },
21
23
  };
22
24
 
23
25
  /**