Reading additional input from stdin...
OpenAI Codex v0.125.0 (research preview)
--------
workdir: /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
model: gpt-5.5
provider: openai
approval: never
sandbox: read-only
reasoning effort: medium
reasoning summaries: none
session id: 019dcf6c-82c9-78f0-a7d3-022d17fce65e
--------
user
Find all token-budget enforcement code paths under .opencode/skills/system-spec-kit/mcp_server/. Identify the function responsible for truncation behavior with file:line reference.
hook: SessionStart
hook: SessionStart
hook: SessionStart Completed
hook: SessionStart Completed
hook: UserPromptSubmit
hook: UserPromptSubmit
hook: UserPromptSubmit Completed
hook: UserPromptSubmit Completed
codex
I’ll treat this as read-only code archaeology. The advisor points at `system-spec-kit`/`sk-code-opencode`, so I’m going to use the local instructions lightly, then trace exact token-budget references with `rg` and read the relevant files for line-accurate paths.
exec
/bin/zsh -lc "sed -n '1,220p' /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/SKILL.md" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
---
name: system-spec-kit
description: "Unified documentation and context preservation: spec folder workflow (levels 1-3+), CORE + ADDENDUM template architecture (v2.2), validation, and Spec Kit Memory for context preservation. Mandatory for all file modifications."
allowed-tools: [Bash, Edit, Glob, Grep, Read, Task, Write]
version: 3.3.1.0
---

<!-- Keywords: spec-kit, speckit, documentation-workflow, spec-folder, template-enforcement, context-preservation, progressive-documentation, validation, spec-kit-memory, vector-search, hybrid-search, bm25, rrf-fusion, fsrs-decay, constitutional-tier, checkpoint, importance-tiers, cognitive-memory, co-activation, tiered-injection -->

# Spec Kit - Mandatory Conversation Documentation

Orchestrates mandatory spec folder creation for all conversations involving file modifications. Ensures proper documentation level selection (1-3+), template usage, and context preservation through AGENTS.md-enforced workflows.


<!-- ANCHOR:when-to-use -->
## 1. WHEN TO USE

### What is a Spec Folder?

A **spec folder** is a numbered directory (e.g., `007-auth-feature/`) that contains documentation for a single feature/task or a coordinated packet of related phase work:

Spec folders may also be nested as coordination-root packets with direct-child phase folders (e.g., `specs/02--track/022-feature/011-phase/002-child/`).

- **Purpose**: Track specifications, plans, tasks, and decisions for one unit of work
- **Location**: Under `specs/` using either `###-short-name/` at the root or nested packet paths for phased coordination
- **Contents**: Markdown files (spec.md, plan.md, tasks.md, and implementation-summary.md when work is complete) plus optional support folders such as `scratch/`, `research/`, or `review/`

Think of it as a "project folder" for AI-assisted development - it keeps context organized and enables session continuity.

### Activation Triggers

**MANDATORY for ALL file modifications:**
- Code files: JS, TS, Python, CSS, HTML
- Documentation: Markdown, README, guides
- Configuration: JSON, YAML, TOML, env templates
- Templates, knowledge base, build/tooling files

**Request patterns that trigger activation:**
- "Add/implement/create [feature]"
- "Fix/update/refactor [code]"
- "Modify/change [configuration]"
- Any keyword: add, implement, fix, update, create, modify, rename, delete, configure, analyze, phase

**Example triggers:**
- "Add email validation to the signup form" → Level 1-2
- "Refactor the authentication module" → Level 2-3
- "Fix the button alignment bug" → Level 1
- "Implement user dashboard with analytics" → Level 3

### When NOT to Use

- Pure exploration/reading (no file modifications)
- Single typo fixes (<5 characters in one file)
- Whitespace-only changes
- Auto-generated file updates (package-lock.json)
- User explicitly selects Option D (skip documentation)

**Rule of thumb:** If modifying ANY file content → Activate this skill.
Status: ✅ This requirement applies immediately once file edits are requested.

### Distributed Governance Rule

Any agent writing authored spec folder docs (`spec.md`, `plan.md`, `tasks.md`, `checklist.md`, `implementation-summary.md`, `decision-record.md`, `handover.md`, `review-report.md`, `debug-delegation.md`, `resource-map.md` (optional)) MUST use templates from .opencode/skills/system-spec-kit/templates/level_N/ for level-owned docs and the root cross-cutting templates where applicable, run `bash .opencode/skills/system-spec-kit/scripts/spec/validate.sh [spec_folder] --strict` after each file write, and route continuity updates through /memory:save. Deep-research workflow-owned packet markdown (`research/iterations/*.md`, `research/deep-research-*.md`, and progressive `research/research.md` loop updates) is exempt from that generic per-write rule; `/spec_kit:deep-research` must instead run targeted strict validation after every `spec.md` mutation it performs. @deep-research retains exclusive write access for `research/research.md`; @debug retains exclusive write access for `debug-delegation.md`.

- `handover.md` stays in the canonical recovery ladder and is maintained through `/memory:save` handover_state routing using `.opencode/skills/system-spec-kit/templates/handover.md` for initial creation.
- `review-report.md` remains owned by `@deep-review` when deep review workflows synthesize findings.
- `resource-map.md` is a peer cross-cutting template under `.opencode/skills/system-spec-kit/templates/`; it remains optional at any level and gives reviewers a lean file ledger alongside `implementation-summary.md`.

### Utility Template Triggers

| Template              | Trigger Keywords                                                                                                              | Action                    |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `handover.md`         | "handover", "next session", "continue later", "pass context", "ending session", "save state", "multi-session", "for next AI"  | Suggest `/memory:save` handover maintenance |
| `debug-delegation.md` | "stuck", "can't fix", "tried everything", "same error", "fresh eyes", "hours on this", "still failing", "need help debugging" | Suggest Task-tool debug delegation |

**Rule:** When detected, proactively suggest the appropriate action.

---

<!-- /ANCHOR:when-to-use -->
<!-- ANCHOR:smart-routing -->
## 2. SMART ROUTING

### Resource Domains

The router discovers markdown resources recursively from `references/` and `assets/` and then applies intent scoring from `RESOURCE_MAP`. Keep this section domain-focused rather than static file inventories.

- `references/memory/` for context retrieval, save workflows, trigger behavior, and indexing.
- `references/templates/` for level selection, template composition, and structure guides.
- `references/validation/` for checklist policy, verification rules, decision formats, and template compliance contracts.
- `references/structure/` for folder organization and sub-folder versioning.
- `references/workflows/` for command workflows and worked examples.
- `references/debugging/` for troubleshooting and root-cause methodology.
- `references/config/` for runtime environment configuration.

### Template and Script Sources of Truth

- Level definitions and template size guidance: [level_specifications.md](./references/templates/level_specifications.md)
- Template usage and composition rules: [template_guide.md](./references/templates/template_guide.md)
- Use `templates/level_N/` for operational templates; `core/` and `addendum/` remain composition inputs.
- Use `templates/changelog/` for packet-local nested changelog generation at completion time.
- Script architecture, build outputs, and runtime entrypoints: [scripts/README.md](./scripts/README.md)
- Memory save JSON schema and workflow contracts: [save_workflow.md](./references/memory/save_workflow.md)
- Nested packet changelog workflow: [nested_changelog.md](./references/workflows/nested_changelog.md)

Primary operational scripts:
- `spec/validate.sh`
- `spec/create.sh`
- `spec/archive.sh`
- `spec/check-completion.sh`
- `spec/recommend-level.sh`
- `templates/compose.sh`

### Resource Loading Levels

| Level       | When to Load               | Resources                    |
| ----------- | -------------------------- | ---------------------------- |
| ALWAYS      | Every skill invocation     | Shared patterns + SKILL.md   |
| CONDITIONAL | If intent signals match   | Intent-mapped references     |
| ON_DEMAND   | Only on explicit request   | Deep-dive quality standards  |

`references/workflows/quick_reference.md` is the primary first-touch command surface. Keep the compact `spec_kit` and `memory` command map there, including `/spec_kit:plan --intake-only` as the standalone intake entry, `/spec_kit:plan` and `/spec_kit:complete` smart delegation notes, and the pointer from `/spec_kit:deep-research` to `../sk-deep-research/references/spec_check_protocol.md`, and use this file only to point readers to it rather than duplicating the full matrix.

### Smart Router Pseudocode

The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling.

```python
from pathlib import Path

SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/workflows/quick_reference.md"

INTENT_SIGNALS = {
    "PLAN": {"weight": 3, "keywords": ["plan", "design", "new spec", "level selection", "option b"]},
    "RESEARCH": {"weight": 3, "keywords": ["investigate", "explore", "analyze", "prior work", "evidence"]},
    "IMPLEMENT": {"weight": 3, "keywords": ["implement", "build", "execute", "workflow"]},
    "DEBUG": {"weight": 4, "keywords": ["stuck", "error", "not working", "failed", "debug"]},
    "COMPLETE": {"weight": 4, "keywords": ["done", "complete", "finish", "verify", "checklist"]},
    "MEMORY": {"weight": 4, "keywords": ["memory", "save context", "resume", "checkpoint", "context"]},
    "HANDOVER": {"weight": 4, "keywords": ["handover", "continue later", "next session", "pause"]},
    "PHASE": {"weight": 4, "keywords": ["phase", "decompose", "split", "workstream", "multi-phase", "phased approach", "phased", "multi-session"]},
    "RETRIEVAL_TUNING": {"weight": 3, "keywords": ["retrieval", "search tuning", "fusion", "scoring", "pipeline"]},
    "EVALUATION": {"weight": 3, "keywords": ["evaluate", "ablation", "benchmark", "baseline", "metrics"]},
    "SCORING_CALIBRATION": {"weight": 3, "keywords": ["calibration", "scoring", "normalization", "decay", "interference"]},
    "ROLLOUT_FLAGS": {"weight": 3, "keywords": ["feature flag", "rollout", "toggle", "enable", "disable"]},
    "GOVERNANCE": {"weight": 3, "keywords": ["governance", "tenant", "retention", "audit"]},
}

RESOURCE_MAP = {
    "PLAN": [
        "references/templates/level_specifications.md",
        "references/templates/template_guide.md",
        "references/validation/template_compliance_contract.md",
    ],
    "RESEARCH": [
        "references/workflows/quick_reference.md",
        "references/workflows/worked_examples.md",
        "references/memory/epistemic_vectors.md",
    ],
    "IMPLEMENT": [
        "references/validation/validation_rules.md",
        "references/validation/template_compliance_contract.md",
        "references/templates/template_guide.md",
    ],
    "DEBUG": [
        "references/debugging/troubleshooting.md",
        "references/workflows/quick_reference.md",
        "manual_testing_playbook/manual_testing_playbook.md",
    ],
    "COMPLETE": [
        "references/validation/validation_rules.md",
        "references/workflows/nested_changelog.md",
    ],
    "MEMORY": [
        "references/memory/memory_system.md",
        "references/memory/save_workflow.md",
        "references/memory/trigger_config.md",
    ],
    "HANDOVER": [
        "references/workflows/quick_reference.md",
    ],
    "PHASE": [
        "references/structure/phase_definitions.md",
        "references/structure/sub_folder_versioning.md",
        "references/validation/phase_checklists.md",
    ],
    "RETRIEVAL_TUNING": [
        "references/memory/embedding_resilience.md",
        "references/memory/trigger_config.md",
    ],
    "EVALUATION": [
        "references/memory/epistemic_vectors.md",
        "references/config/environment_variables.md",
        "manual_testing_playbook/manual_testing_playbook.md",
    ],
    "SCORING_CALIBRATION": [
        "references/config/environment_variables.md",
    ],
    "ROLLOUT_FLAGS": [
        "references/config/environment_variables.md",
        "feature_catalog/19--feature-flag-reference/",
    ],
    "GOVERNANCE": [
        "references/config/environment_variables.md",
    ],
}

COMMAND_BOOSTS = {
    "/spec_kit:plan": "PLAN",
    "/spec_kit:implement": "IMPLEMENT",
    "/spec_kit:complete": "COMPLETE",
    "/spec_kit:plan :with-phases": "PHASE",
    "/memory:search": "MEMORY",
    "/memory:save": "MEMORY",
    "/memory:manage": "MEMORY",
    "/memory:learn": "MEMORY",
    "/spec_kit:resume": "MEMORY",
}

exec
/bin/zsh -lc 'rg -n "token|budget|truncate|truncat|limit|tokens" .opencode/skills/system-spec-kit/mcp_server' in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:750:      limit: 100,
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1109:    // SK-004: Inject auto-surface hints before token-budget enforcement so
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1115:    // Token Budget Hybrid: Inject tokenBudget into response metadata (CHK-072)
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1116:    // T205: Enforce per-layer token budgets with actual truncation
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1139:          const budget = getTokenBudget(name);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1140:          meta.tokenBudget = budget;
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1143:          if (typeof meta.tokenCount === 'number' && meta.tokenCount > budget) {
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1144:            console.error(`[token-budget] ${name} response (${meta.tokenCount} tokens) exceeds budget (${budget})`);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1146:            // T205: Attempt to truncate results array to fit within budget
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1151:              // Remove from end (lowest-scored) until within budget
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1154:                // P1-06 FIX: Recalculate token count from the full envelope
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1155:                // (not just results) so trace metadata is included in the budget.
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1157:                if (typeof meta.tokenCount === 'number' && meta.tokenCount <= budget) break;
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1163:                envelope.hints.push(`Token budget enforced: truncated ${originalCount} → ${innerResults.length} results to fit ${budget} token budget`);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1165:              meta.tokenBudgetTruncated = true;
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1169:              // No truncatable results array — add warning hint only
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1171:                envelope.hints.push(`Response exceeds token budget (${meta.tokenCount}/${budget})`);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1178:        // Non-JSON response, skip token budget injection
.opencode/skills/system-spec-kit/mcp_server/ENV_REFERENCE.md:35:- Headline multipliers stay blocked unless prompt, completion, cache-read, and cache-write token fields all have `provider_counted` authority. Later packets should reuse `canPublishMultiplier()` instead of inventing packet-local gates.
.opencode/skills/system-spec-kit/mcp_server/ENV_REFERENCE.md:122:| `SPECKIT_CONFIDENCE_TRUNCATION` | `true` | boolean | Confidence-gap truncation for low-confidence result tails. Graduated ON. | `lib/search/search-flags.ts` |
.opencode/skills/system-spec-kit/mcp_server/ENV_REFERENCE.md:124:| `SPECKIT_DYNAMIC_TOKEN_BUDGET` | `true` | boolean | Dynamic token budget allocation by query complexity. Graduated ON. | `lib/search/search-flags.ts` |
.opencode/skills/system-spec-kit/mcp_server/ENV_REFERENCE.md:305:| `SPECKIT_DASHBOARD_LIMIT` | `10000` | number | Maximum row limit for reporting dashboard queries. | `lib/eval/reporting-dashboard.ts` |
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:59:): { count: number; maxMtimeMs: number; truncated: boolean } {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:60:  if (!existsSync(skillRoot)) return { count: 0, maxMtimeMs: 0, truncated: false };
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:64:  let truncated = false;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:76:          truncated = true;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:77:          return { count, maxMtimeMs: newest, truncated };
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:82:  return { count, maxMtimeMs: newest, truncated };
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/handlers/advisor-status.ts:97:    if (sourceScan.truncated) {
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:143:  const tokenCap = positiveInt(maxTokens, 80);
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:144:  return parts.join(' ').slice(0, tokenCap * 4).trim();
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:241:      tokenCap: maxTokens,
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:250:    tokenCap: maxTokens,
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:265:      tokenCap: maxTokens,
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:290:    tokenCap: maxTokens,
.opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs:307:      tokenCap: result.metrics.tokenCap,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:32:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:170:   * subject vs limit reached vs empty source) without parsing free-form
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:189:  | 'limit_reached'
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:329:  const truncated = matchResult.count > matchResult.candidates.length;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:331:  const countLabel = truncated
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:480:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:494:    if (resolvedEntries.length < limit) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:541:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:551:  while (frontier.length > 0 && results.length < limit) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:578:            if (results.length >= limit) break;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:603:            if (results.length >= limit) break;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:609:      if (results.length >= limit) break;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:614:  const truncated = results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:616:    return { nodes: truncated };
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:621:    nodes: truncated,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:969:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1016:  // against `limit` BEFORE slicing. Previously `affectedFiles.length >= limit`
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1017:  // false-positived whenever the reachable set happened to equal `limit`
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1018:  // exactly. We over-collect (`limit + 1` semantically — here the whole
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1025:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1026:  const overflowed = totalAffectedBeforeSlice > limit;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1064:          reason: 'limit_reached',
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1065:          code: 'limit_reached',
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1123:  const { operation, subject, limit = 50 } = args;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1160:    const limited = nodes.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1161:    const outlineNodes: OutlineQueryNode[] = limited.map(n => ({
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1320:      blastRadius = computeBlastRadius(sourceFiles, maxDepth, limit, minConfidence, ambiguityCandidates);
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1405:      limit,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1440:        limit,
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/query.ts:1462:        limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-types.ts:34:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-types.ts:47:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-types.ts:53:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/INSTALL_GUIDE.md:636:- `tokenUsage`: Optional float (0.0-1.0) to override pressure-aware mode selection
.opencode/skills/system-spec-kit/mcp_server/INSTALL_GUIDE.md:646:- `limit`: Max results (default 10)
.opencode/skills/system-spec-kit/mcp_server/INSTALL_GUIDE.md:999:`code_graph_context` can refuse broad repair on the read path. In that case it returns `status: "blocked"` with `requiredAction: "code_graph_scan"` and `blockReason: "full_scan_required"` instead of attempting a full scan inline. Successful context responses still include `readiness`, `trustState`, `graphMetadata.detectorProvenance`, and `metadata.partialOutput`, which is the operator-facing signal that budget or deadline limits trimmed sections or anchors.
.opencode/skills/system-spec-kit/mcp_server/INSTALL_GUIDE.md:1163:| v1.7.x | 2026-02-20 | Cross-encoder reranking enabled by default. Co-activation score boost fix. Query expansion on deep mode. Evidence gap warnings. MMR reranking with intent-mapped lambda. Phase system support (recursive validation, phase detection scoring). Feature flag updates. `memory_context` tokenUsage parameter. 28-tool surface area. |
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/README.md:48:| Watcher limits | Chokidar narrow scope, ≤ 1% idle CPU, < 20 MB RSS (measured 0.031% / 5.516 MB) |
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/README.md:142:| `lexical` | 0.30 | IDF-weighted token overlap on the active corpus. |
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:302:  it('never persists a transient zero transcript offset during stop-hook token snapshot writes', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:310:          input_tokens: 120,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:311:          output_tokens: 45,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:312:          cache_creation_input_tokens: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:313:          cache_read_input_tokens: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:382:          input_tokens: 50,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:383:          output_tokens: 25,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:384:          cache_creation_input_tokens: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:385:          cache_read_input_tokens: 2,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:465:          input_tokens: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:466:          output_tokens: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:467:          cache_creation_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:468:          cache_read_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:510:      const appendedLine = `${JSON.stringify({ type: 'assistant', message: { role: 'assistant', usage: { input_tokens: 1, output_tokens: 1 } } })}\n`;
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:578:          input_tokens: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:579:          output_tokens: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:580:          cache_creation_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:581:          cache_read_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:649:          input_tokens: 30,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:650:          output_tokens: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:651:          cache_creation_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts:652:          cache_read_input_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-manager.ts:66:    tokenSavingsEstimate?: string;
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-manager.ts:651:    // Transaction ensures atomic insert + limit enforcement, preventing concurrent race past entry limit.
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-manager.ts:733:    console.warn(`[session-manager] enforce_entry_limit failed: ${message}`);
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-manager.ts:933:      tokenSavingsEstimate: filteredCount > 0 ? `~${filteredCount * 200} tokens` : '0',
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:6:// Basic truncation, minimum result count, no-truncation, flag disabled,
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:11:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:19:} from '../lib/search/confidence-truncation';
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:114:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:115:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:117:    expect(out.truncatedCount).toBe(4);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:123:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:124:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:138:  it('T8: truncates at clear gap above threshold', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:147:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:148:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:149:    expect(out.truncatedCount).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:154:  it('T9: truncation result preserves original data of kept results', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:162:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:163:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:168:  it('T10: originalCount reflects pre-truncation count', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:170:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:172:    expect(out.truncatedCount).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:175:  it('T11: cutoffGap reflects the gap that triggered truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:178:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:185:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:198:  it('T13: does not truncate below minResults (default 3)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:211:    // No truncation
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:212:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:213:    // With the actual numbers the large gap at 0 is not searched; no truncation
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:217:  it('T14: custom minResults=2 allows earlier truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:225:    const out = truncateByConfidence(results, { minResults: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:226:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:227:    expect(out.truncatedCount).toBe(2);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:233:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:234:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:235:    expect(out.truncatedCount).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:255:  it('T18: no truncation when all gaps are equal', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:260:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:261:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:262:    expect(out.truncatedCount).toBe(5);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:265:  it('T19: no truncation when all results have same score', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:267:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:268:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:269:    expect(out.truncatedCount).toBe(4);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:272:  it('T20: no truncation returned with correct metadata when no gap found', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:274:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:275:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:290:  it('T21: empty array returns unchanged with truncated=false', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:291:    const out = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:292:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:295:    expect(out.truncatedCount).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:300:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:301:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:302:    expect(out.truncatedCount).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:308:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:309:    expect(out.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:310:    expect(out.truncatedCount).toBe(2);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:317:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:318:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:342:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:344:    // Verify truncation happened
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:345:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:348:    const reductionRatio = (out.originalCount - out.truncatedCount) / out.originalCount;
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:358:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:360:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:362:    const reductionRatio = (out.originalCount - out.truncatedCount) / out.originalCount;
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:364:    expect(out.truncatedCount).toBe(4);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:414:  it('T33: NaN scores are filtered out before truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:418:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:424:  it('T34: Infinity scores are filtered out before truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:428:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:433:  it('T35: -Infinity scores are filtered out before truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:437:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:442:  it('T36: unsorted input is sorted internally before truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:447:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:449:    expect(out.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:450:    expect(out.truncatedCount).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/code-graph-parse-latency.bench.ts:35:    f('.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts', 'typescript'),
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:101:function tokenize(prompt: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:107:function meaningfulTokens(tokens: string[]): string[] {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:108:  return tokens.filter((token) => token.length > 0 && !STOP_WORDS.has(token));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:117:function hasWorkIntentVerb(tokens: string[]): boolean {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:118:  return tokens.some((token) => WORK_INTENT_VERBS.has(token));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:131:  const tokens = tokenize(canonicalPrompt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:132:  const meaningful = meaningfulTokens(tokens);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:159:  const workIntent = hasWorkIntentVerb(tokens);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:187:      reason: 'work_intent_with_meaningful_tokens',
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/prompt-policy.ts:198:      reason: 'length_and_token_threshold',
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:49:    .map((candidate) => readNumericField(candidate, ['promptTokens', 'prompt_tokens', 'inputTokens', 'input_tokens']))
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:52:    .map((candidate) => readNumericField(candidate, ['completionTokens', 'completion_tokens', 'outputTokens', 'output_tokens']))
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:57:      'cache_creation_tokens',
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:59:      'cache_creation_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:65:      'cache_read_tokens',
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:67:      'cache_read_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:71:    .map((candidate) => readNumericField(candidate, ['totalTokens', 'total_tokens']))
.opencode/skills/system-spec-kit/mcp_server/hooks/response-hints.ts:127:      ...(typeof surfacedTokenCount === 'number' ? { tokenCount: surfacedTokenCount } : {}),
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:101:  tokenMetrics: TokenMetrics;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:107:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:167:    // WARM tier returns truncated summary
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:187:    limit: rawLimit = 3,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:231:  const limit = (typeof rawLimit === 'number' && Number.isFinite(rawLimit) && rawLimit > 0)
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:287:  const triggerMatchResult = triggerMatcher.matchTriggerPhrasesWithStats(prompt, limit * 2);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:441:    const tieredResults = tierClassifier.filterAndLimitByState(enrichedResults, null, limit);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:472:      tokenMetrics: calculateTokenMetrics(results, formattedResults)
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:476:    formattedResults = results.slice(0, limit).map((r: TriggerMatch) => ({
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-triggers.ts:501:    hints.push(`${coldCount} COLD-tier memories excluded for token efficiency`);
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/context.ts:32:  budgetTokens?: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/handlers/context.ts:219:      budgetTokens: args.budgetTokens ?? 1200,
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-session-dedup.vitest.ts:101:    expect(dedupStats.tokenSavingsEstimate).toBe('~400 tokens');
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:10:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:95:// Token budgets for dual-scope lifecycle hooks (TM-05)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:252:  tokenBudget: number,
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:262:  const budgetLimit = Number.isFinite(tokenBudget) && tokenBudget > 0
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:263:    ? tokenBudget
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:267:  let tokenCount = measureTokens(boundedResult);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:269:  if (tokenCount <= budgetLimit) {
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:274:  while (triggered.length > 0 && tokenCount > budgetLimit) {
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:277:    tokenCount = measureTokens(boundedResult);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:281:  while (constitutional.length > 0 && tokenCount > budgetLimit) {
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:284:    tokenCount = measureTokens(boundedResult);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:287:  if (tokenCount > budgetLimit) {
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:289:      `[SK-004] Auto-surface output exceeded ${hookName} token budget ` +
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:290:      `(${tokenCount} > ${budgetLimit}); dropping payload`
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:296:    `[SK-004] Auto-surface output truncated to fit ${hookName} token budget ` +
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:297:    `(${tokenCount}/${budgetLimit})`
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:307: * @param limit - Maximum number of memory IDs to return
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:310:function getAttentionWeightedMemoryIds(limit: number = 5): Set<number> {
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:327:    `).all(workingMemory.DECAY_FLOOR, oneHourAgo, limit) as Array<{ memory_id: number }>;
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:367:  tokenBudget: number = TOOL_DISPATCH_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:411:    }, tokenBudget, hookName);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:587: * Token budget: TOOL_DISPATCH_TOKEN_BUDGET (4000 max)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:614:  // Delegate to the core surface function; token budget is explicitly
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:634: * Token budget: COMPACTION_TOKEN_BUDGET (4000 max)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:654:  // Delegate to the core surface function; token budget is explicitly
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:33:The session layer provides all session-related operations for the Spec Kit Memory MCP server. It prevents duplicate context injection (saving ~50% tokens on follow-up queries) and enables crash recovery with immediate SQLite persistence.
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:84:**Purpose**: Prevent sending the same spec-doc record content twice in a session, saving tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:88:| **Hash-based** | SHA-256 hash of memory content (truncated to 16 chars) |
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:91:| **Token Savings** | ~200 tokens per duplicate avoided |
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:145:console.log(`Token savings: ${dedupStats.tokenSavingsEstimate}`);
.opencode/skills/system-spec-kit/mcp_server/lib/session/README.md:181:  pendingWork: 'Need to add traversal depth limit'
.opencode/skills/system-spec-kit/mcp_server/README.md:78:| **Sessions** | Stateless | Working memory with attention decay, ~50% token savings via deduplication |
.opencode/skills/system-spec-kit/mcp_server/README.md:79:| **Section retrieval** | Returns full documents | ANCHOR-based chunking with ~93% token savings |
.opencode/skills/system-spec-kit/mcp_server/README.md:270:**Confidence truncation** cuts off results at 2x the median score gap so you never get a long tail of irrelevant items.
.opencode/skills/system-spec-kit/mcp_server/README.md:315:| Simple | 2 | 800 tokens | Quick lookups, single-topic questions |
.opencode/skills/system-spec-kit/mcp_server/README.md:316:| Moderate | 4 | 1,500 tokens | Multi-factor questions, debugging |
.opencode/skills/system-spec-kit/mcp_server/README.md:317:| Complex | All 5 | 2,000 tokens | Research, architecture decisions |
.opencode/skills/system-spec-kit/mcp_server/README.md:356:**Auto-promotion** -- memories earn their way up. After 5 positive validation marks, a normal memory promotes to important. After 10, important promotes to critical. Rate-limited to prevent bulk promotion during busy sessions.
.opencode/skills/system-spec-kit/mcp_server/README.md:372:The system tracks how decisions relate to each other. Think of it like a corkboard with sticky notes connected by string. One note says "we chose JWT tokens." A string connects it to "because the session store was too slow." Another string connects that to "the Redis outage on March 5th."
.opencode/skills/system-spec-kit/mcp_server/README.md:448:**Session deduplication** -- pushes down results you already saw. If you got a result 3 turns ago, new searches rank it lower. Saves approximately 50% of tokens on follow-up queries.
.opencode/skills/system-spec-kit/mcp_server/README.md:466:**Learned relevance feedback** -- watches when you mark results as useful or not. Helpful results get a boost in future queries. 10 safeguards prevent noise: denylist, rate limits, 30-day decay, per-cycle caps, minimum session thresholds, one-week trial period before boosts go live.
.opencode/skills/system-spec-kit/mcp_server/README.md:494:**ANCHOR-based section retrieval** -- indexed packet docs and generated continuity artifacts can include `<!-- ANCHOR:name -->` markers. The search system indexes individual sections separately, allowing retrieval of just "decisions" or "next-steps" from a large document (~93% token savings). Files above 50K characters are always chunk-split.
.opencode/skills/system-spec-kit/mcp_server/README.md:542:**Architecture:** CocoIndex (semantic, external MCP) finds code by concept. Code Graph (structural, this server) maps imports, calls and hierarchy. Memory (session, this server) preserves decisions. The compact-merger combines all three under a 4000-token budget for compaction injection. Code-graph source is self-contained under `code-graph/` with `handlers/`, `lib/`, `tools/`, and `tests/`.
.opencode/skills/system-spec-kit/mcp_server/README.md:586:**Affordance evidence:** `advisor_recommend` accepts structured tool/resource hints as a sanitized affordance lane wired into the existing `derived_generated` and `graph_causal` lanes — no new scoring lane, no new `entity_kind`, no new relation type. The allowlist normalizer at `skill_advisor/lib/affordance-normalizer.ts` accepts only `skillId`/`skill_id`, `name`, `triggers[]`, `category`, and the existing relation fields (`dependsOn[]`/`depends_on[]`, `enhances[]`, `siblings[]`, `prerequisiteFor[]`/`prerequisite_for[]`, `conflictsWith[]`/`conflicts_with[]`). Free-form `description` text is intentionally ignored as a trigger source. URLs, email addresses, token-shaped fragments, control characters, and instruction-shaped strings are stripped or dropped before scoring. Sanitized triggers contribute through the existing `derived_generated` lane (`scorer/lanes/derived.ts`) with reduced weight, and normalized relations become temporary edges in the existing `graph_causal` lane (`scorer/lanes/graph-causal.ts`) reusing the existing `enhances` / `siblings` / `depends_on` / `prerequisite_for` / `conflicts_with` `EDGE_MULTIPLIER` values. Recommendation payloads cite stable `affordance:<skillId>:<index>` identifiers — never raw matched phrases. The Python graph compiler (`skill_advisor/scripts/skill_graph_compiler.py`) compiles `derived.affordances[]` into existing `signals` and sparse adjacency without changing `ALLOWED_ENTITY_KINDS` (`{"skill", "agent", "script", "config", "reference"}`).
.opencode/skills/system-spec-kit/mcp_server/README.md:631:| `limit` | number | Max results to return (default varies by mode) |
.opencode/skills/system-spec-kit/mcp_server/README.md:634:| `tokenUsage` | number | Current token budget fraction (0.0-1.0) for adaptive depth |
.opencode/skills/system-spec-kit/mcp_server/README.md:643:    "input": "implement JWT refresh token rotation",
.opencode/skills/system-spec-kit/mcp_server/README.md:688:| `limit` | number | 1-100 results (default 10) |
.opencode/skills/system-spec-kit/mcp_server/README.md:704:    "limit": 5
.opencode/skills/system-spec-kit/mcp_server/README.md:722:| `limit` | number | 1-100 results (default 10) |
.opencode/skills/system-spec-kit/mcp_server/README.md:733:| `limit` | number | Max matches to return |
.opencode/skills/system-spec-kit/mcp_server/README.md:742:    "prompt": "fix the token refresh bug in auth service",
.opencode/skills/system-spec-kit/mcp_server/README.md:792:| `limit` | number | Max 100 per page |
.opencode/skills/system-spec-kit/mcp_server/README.md:810:| `limit` | number | Max folders to return |
.opencode/skills/system-spec-kit/mcp_server/README.md:821:| `limit` | number | Max items to report |
.opencode/skills/system-spec-kit/mcp_server/README.md:916:| `limit` | number | Max checkpoints to return |
.opencode/skills/system-spec-kit/mcp_server/README.md:1038:The MCP handler scores chunk-backed hits against `parentMemoryId ?? row.id`, so eval rows stay attached to canonical parent memories. Before comparing runs after a DB rebuild or import, preview or refresh the live ground-truth mapping with `scripts/evals/map-ground-truth-ids.ts`; if token-budget overflow collapses a run below `recallK`, treat that run as investigation-only rather than a clean benchmark.
.opencode/skills/system-spec-kit/mcp_server/README.md:1051:| `limit` | number | Max records to include |
.opencode/skills/system-spec-kit/mcp_server/README.md:1067:| `limit` | number | Max results (1-200, default 50) |
.opencode/skills/system-spec-kit/mcp_server/README.md:1075:Get LLM-oriented compact graph neighborhoods. Accepts CocoIndex search results as seeds for structural expansion. Modes: `neighborhood` (1-hop calls plus imports), `outline` (file symbols), `impact` (reverse callers). Successful responses return `status: "ok"` plus readiness/trust metadata, resolved anchors, graph context, and `data.metadata.partialOutput` so callers can see whether deadline or token-budget pressure produced partial output. When the read path determines the graph needs a full scan, the tool returns an explicit `status: "blocked"` payload with `data.blocked`, `graphAnswersOmitted`, `requiredAction: "code_graph_scan"`, and the same readiness/trust metadata instead of partial graph answers.
.opencode/skills/system-spec-kit/mcp_server/README.md:1083:| `budgetTokens` | number | Token budget for response (100-4000, default 1200) |
.opencode/skills/system-spec-kit/mcp_server/README.md:1087:`data.metadata.partialOutput` is structured and stable: `isPartial`, `reasons`, `omittedSections`, `omittedAnchors`, and `truncatedText`. Use it to distinguish a complete answer from one shortened by deadline or token-budget limits. `data.metadata.deadlineMs` exposes the effective per-call deadline so callers can correlate `partialOutput.reasons` with the budget that produced them.
.opencode/skills/system-spec-kit/mcp_server/README.md:1115:| `limit` | number | Max records to return |
.opencode/skills/system-spec-kit/mcp_server/README.md:1237:├── formatters/                # Search-result and token-metric formatting
.opencode/skills/system-spec-kit/mcp_server/README.md:1239:├── hooks/                     # Session-start/compaction surfacing, mutation feedback, token-count sync
.opencode/skills/system-spec-kit/mcp_server/README.md:1271:| `lib/enrichment/retry-budget.ts` | Retry exhaustion budget that stops repeated post-insert enrichment failures from looping forever |
.opencode/skills/system-spec-kit/mcp_server/README.md:1291:Token budgets control how much content each tool can return per call. The budget prevents any single tool from flooding the AI's context window. When a response exceeds its budget, results are truncated from the bottom up until they fit.
.opencode/skills/system-spec-kit/mcp_server/README.md:1354:    "input": "add rate limiting to the auth API",
.opencode/skills/system-spec-kit/mcp_server/README.md:1633:| Embedding API rate limit | Set `SPECKIT_EMBEDDING_RETRY_DELAY_MS=1000` |
.opencode/skills/system-spec-kit/mcp_server/README.md:1650:{ "tool": "memory_health", "arguments": { "reportMode": "divergent_aliases", "limit": 20 } }
.opencode/skills/system-spec-kit/mcp_server/README.md:1704:A dry run validates the file against the quality gate, estimates the token budget, checks for duplicates and returns a report, all without writing anything to the database. Use it to verify a file will pass before committing.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/metrics.ts:348:  limit = MAX_DURABLE_DIAGNOSTIC_RECORDS,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/metrics.ts:351:    .slice(-limit)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/metrics.ts:422:  limit = MAX_DURABLE_OUTCOME_RECORDS,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/metrics.ts:425:    .slice(-limit)
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:36: * Token budget: 250-400 tokens (hard ceiling 500 including guidance).
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:69:function truncateTextToTokenBudget(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:115:    fittedSummary = truncateTextToTokenBudget(fittedSummary, summaryBudget);
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:121:    fittedRecommendedAction = truncateTextToTokenBudget(fittedRecommendedAction, actionBudget);
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:208: * Keeps output compact (targets 250-400 tokens, ceiling 500).
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:34:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:49:    const limit = clamp(args.limit, 1, 200, 50);
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:58:          relationships: sliceResults(skillGraphQueries.dependsOn(skillId), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:65:          relationships: sliceResults(skillGraphQueries.dependents(skillId), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:72:          relationships: sliceResults(skillGraphQueries.enhances(skillId), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:79:          relationships: sliceResults(skillGraphQueries.enhancedBy(skillId), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:92:          members: sliceResults(skillGraphQueries.familyMembers(args.family), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:99:          relationships: sliceResults(skillGraphQueries.conflicts(skillId), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:120:          skills: sliceResults(skillGraphQueries.hubSkills(minInbound), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:126:          skills: sliceResults(skillGraphQueries.orphans(), limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:182:function sliceResults<T>(results: T, limit: number): T {
.opencode/skills/system-spec-kit/mcp_server/handlers/skill-graph/query.ts:184:  return results.slice(0, limit) as T;
.opencode/skills/system-spec-kit/mcp_server/tests/reranker-eval-comparison.vitest.ts:328:      { limit: 5, useCache: false, applyLengthPenalty: false },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:76:  readonly tokenCap: number;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:105:  tokenCap: DEFAULT_TOKEN_CAP,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:166:  tokenCap: number,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:173:    metrics: { tokenCap },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:177:    tokenCap,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:205:  const tokenCap = clampTokenCap(args.maxTokens, hasAmbiguitySignal(filteredRecommendations));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:209:    tokenCap,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:221:      tokenCap,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:310:  const tokenCap = args.metrics?.tokenCap ?? DEFAULT_TOKEN_CAP;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:316:    tokenCap,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:503:    const tokenCap = clampTokenCap(options.maxTokens, hasAmbiguitySignal(recommendations));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:507:      tokenCap,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/skill-advisor-brief.ts:525:        tokenCap,
.opencode/skills/system-spec-kit/mcp_server/hooks/README.md:73:- `response-hints.ts`: auto-surface hint injection plus MCP JSON envelope metadata and token-count synchronization.
.opencode/skills/system-spec-kit/mcp_server/tests/smart-router-measurement.vitest.ts:53:      tokenCap: 80,
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:167:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:172:  tokenUsage: boundedNumber(0, 1).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:185:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:216:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:229:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:299:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:311:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:316:  limit: positiveIntMax(200).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:336:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:412:  limit: positiveIntMax(200).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:427:  limit: positiveIntMax(100).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:458:  limit: positiveIntMax(200).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:489:  budgetTokens: boundedNumber(100, 4000).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:511:  limit: positiveIntMax(200).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:563:  limit: positiveIntMax(200).optional(),
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:646:  memory_context: ['input', 'mode', 'intent', 'specFolder', 'tenantId', 'userId', 'agentId', 'limit', 'sessionId', 'enableDedup', 'includeContent', 'includeTrace', 'tokenUsage', 'anchors', 'profile'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:647:  memory_search: ['cursor', 'query', 'concepts', 'specFolder', 'tenantId', 'userId', 'agentId', 'limit', 'sessionId', 'enableDedup', 'tier', 'contextType', 'useDecay', 'includeContiguity', 'includeConstitutional', 'enableSessionBoost', 'enableCausalBoost', 'includeContent', 'anchors', 'min_quality_score', 'minQualityScore', 'bypassCache', 'rerank', 'applyLengthPenalty', 'applyStateLimits', 'minState', 'intent', 'autoDetectIntent', 'trackAccess', 'includeArchived', 'mode', 'includeTrace', 'profile'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:648:  memory_quick_search: ['query', 'limit', 'specFolder', 'tenantId', 'userId', 'agentId'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:649:  memory_match_triggers: ['prompt', 'specFolder', 'tenantId', 'userId', 'agentId', 'limit', 'session_id', 'turnNumber', 'include_cognitive'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:651:  memory_list: ['limit', 'offset', 'specFolder', 'sortBy', 'includeChunks'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:652:  memory_stats: ['folderRanking', 'excludePatterns', 'includeScores', 'includeArchived', 'limit'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:653:  memory_health: ['reportMode', 'limit', 'specFolder', 'autoRepair', 'confirmed'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:659:  checkpoint_list: ['specFolder', 'tenantId', 'userId', 'agentId', 'limit'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:669:  eval_reporting_dashboard: ['sprintFilter', 'channelFilter', 'metricFilter', 'limit', 'format'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:671:  memory_get_learning_history: ['specFolder', 'sessionId', 'limit', 'onlyComplete', 'includeSummary'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:676:  code_graph_query: ['operation', 'subject', 'subjects', 'unionMode', 'edgeType', 'limit', 'includeTransitive', 'maxDepth', 'minConfidence'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:678:  code_graph_context: ['input', 'queryMode', 'subject', 'seeds', 'budgetTokens', 'profile', 'includeTrace'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:681:  skill_graph_query: ['queryType', 'skillId', 'sourceSkillId', 'targetSkillId', 'family', 'minInbound', 'depth', 'limit'],
.opencode/skills/system-spec-kit/mcp_server/schemas/tool-input-schemas.ts:691:  deep_loop_graph_query: ['specFolder', 'loopType', 'queryType', 'nodeId', 'sessionId', 'limit', 'maxDepth'],
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:47:    metrics: { tokenCap: 80 },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:54:    { status: 'ok', freshness: 'absent', recommendations: buildRecommendations('codex'), metrics: { tokenCap: 80 }, sharedPayload: null },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:55:    { status: 'skipped', freshness: 'live', recommendations: buildRecommendations('codex'), metrics: { tokenCap: 80 }, sharedPayload: null },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:56:    { status: 'ok', freshness: 'live', recommendations: [], metrics: { tokenCap: 80 }, sharedPayload: null },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:61:      metrics: { tokenCap: 80 },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:105:      const brief = renderAdvisorBrief(renderable, { tokenCap: 80 });
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/bench/hook-brief-signal-noise.bench.ts:118:      expect(renderAdvisorBrief(renderable, { tokenCap: 80 })).toBeNull();
.opencode/skills/system-spec-kit/mcp_server/tests/pe-gating.vitest.ts:39:        expect(options.limit).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/pe-gating.vitest.ts:47:        expect(options.limit).toBe(6);
.opencode/skills/system-spec-kit/mcp_server/tests/pe-gating.vitest.ts:64:      limit: 1,
.opencode/skills/system-spec-kit/mcp_server/tests/pe-gating.vitest.ts:83:        expect(options.limit).toBe(6);
.opencode/skills/system-spec-kit/mcp_server/tests/pe-gating.vitest.ts:92:      limit: 2,
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-hierarchy.vitest.ts:465:  it('respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:13:  readonly tokenCap?: number;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:26:    readonly tokenCap?: number;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:52:function clampTokenCap(tokenCap: number | undefined): number {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:53:  if (typeof tokenCap !== 'number' || Number.isNaN(tokenCap)) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:56:  return Math.min(Math.max(1, Math.floor(tokenCap)), MAX_TOKEN_CAP);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:59:function capText(text: string, tokenCap: number): string {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:60:  const charCap = tokenCap * TOKEN_TO_CHAR_ESTIMATE;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:64:  const truncated = text.slice(0, Math.max(1, charCap - 3)).trimEnd();
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:65:  return `${truncated}...`;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:122:  const tokenCap = clampTokenCap(result.metrics?.tokenCap ?? options.tokenCap);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:144:  if (tokenCap > DEFAULT_TOKEN_CAP && second && isAmbiguous(recommendations)) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:151:      Math.min(tokenCap, AMBIGUOUS_TOKEN_CAP),
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/render.ts:157:    Math.min(tokenCap, DEFAULT_TOKEN_CAP),
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:4:// Distributes a total token budget across multiple context sources
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:7:/** Per-source budget configuration */
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:31:/** Default floor layout for the 4000-token compact brief budget */
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:44: * Allocate token budget across sources.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:50: * 4. Enforce total budget cap with deterministic trim
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:94:  // Step 3: Enforce total budget cap (trim in reverse priority order)
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:119:/** Create source budgets with default floors */
.opencode/skills/system-spec-kit/mcp_server/tests/reconsolidation-bridge.vitest.ts:278:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:15:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:33:  readonly context_window_tokens?: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:114:    input?.context_window_tokens,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:160:    const additionalContext = truncateToTokenBudget(
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/structural-indexer.ts:228:function splitTopLevel(text: string, delimiter: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/structural-indexer.ts:238:      ch === delimiter &&
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/structural-indexer.ts:267:function splitTopLevelOnce(text: string, delimiter: string): [string, string | undefined] {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/structural-indexer.ts:276:      ch === delimiter &&
.opencode/skills/system-spec-kit/mcp_server/tests/intent-routing.vitest.ts:15:    for (const token of text.toLowerCase().split(/[^a-z0-9_]+/).filter(Boolean)) {
.opencode/skills/system-spec-kit/mcp_server/tests/intent-routing.vitest.ts:16:      const digest = createHash('sha256').update(token).digest();
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:80:    source_field: 'cache_creation_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:81:    description: 'Normalized cache-write tier sourced from Claude transcript cache creation tokens.',
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:85:    source_field: 'cache_read_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:86:    description: 'Normalized cache-read tier sourced from Claude transcript cache read tokens.',
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:100:    prompt_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:101:    completion_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:102:    cache_creation_input_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:103:    cache_read_input_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:104:    total_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:125:    prompt_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:126:    completion_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:127:    cache_creation_input_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:128:    cache_read_input_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:129:    total_tokens INTEGER NOT NULL DEFAULT 0,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:175:  prompt_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:176:  completion_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:177:  cache_creation_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:178:  cache_read_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:179:  total_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:200:  prompt_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:201:  completion_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:202:  cache_creation_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:203:  cache_read_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:204:  total_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:409:      COALESCE(SUM(prompt_tokens), 0) AS prompt_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:410:      COALESCE(SUM(completion_tokens), 0) AS completion_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:411:      COALESCE(SUM(cache_creation_input_tokens), 0) AS cache_creation_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:412:      COALESCE(SUM(cache_read_input_tokens), 0) AS cache_read_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:413:      COALESCE(SUM(total_tokens), 0) AS total_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:424:    prompt_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:425:    completion_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:426:    cache_creation_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:427:    cache_read_input_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:428:    total_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:440:    SET prompt_tokens = ?,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:441:        completion_tokens = ?,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:442:        cache_creation_input_tokens = ?,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:443:        cache_read_input_tokens = ?,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:444:        total_tokens = ?,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:455:    aggregate.prompt_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:456:    aggregate.completion_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:457:    aggregate.cache_creation_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:458:    aggregate.cache_read_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:459:    aggregate.total_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:488:      prompt_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:489:      completion_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:490:      cache_creation_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:491:      cache_read_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:492:      total_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:541:      prompt_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:542:      completion_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:543:      cache_creation_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:544:      cache_read_input_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/analytics/session-analytics-db.ts:545:      total_tokens,
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/README.md:53:| **ModeMetrics** | Search mode selection, override flag, pressure level, and optional token usage ratio |
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/README.md:150:| `tokenUsageRatio` | `number \| undefined` | Optional normalized token usage ratio (0-1) |
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/README.md:259:| `caveat` | `string \| undefined` | Optional caveat when forecast quality is limited or unavailable |
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/README.md:267:| `limit` | `number \| undefined` | Maximum number of sampled payloads to return |
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/README.md:357:  tokenUsageRatio: 0.2,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/gold-query-verifier.ts:64:    limit?: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/gold-query-verifier.ts:89:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/gold-query-verifier.ts:290:      limit: 200,
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/livePassingSkill.json:21:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/storage/checkpoints.ts:1500:  limit: number = 50,
.opencode/skills/system-spec-kit/mcp_server/lib/storage/checkpoints.ts:1508:    params.push(limit);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:100:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:112:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:123:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:137:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:149:    const results = searchFn('memory', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:165:    const results = searchFn('memory', { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:181:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:192:    const results = searchFn('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:205:    searchFn('spec', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:219:    expect(searchFn('memory', { limit: 10 })).toEqual([]);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:240:    const results = searchFn('memory', { limit: 5, specFolder: '003-root/007-child' });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:254:    const results = searchFn('memory', { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:270:    const results = searchFn('memory', { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-search-fn.vitest.ts:285:    const results = searchFn('memory', { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:66:  tokenUsageRatio?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:145:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:253:  tokenUsageRatio?: number,
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:259:  if (typeof tokenUsageRatio === 'number' && Number.isFinite(tokenUsageRatio)) {
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:260:    t.mode.tokenUsageRatio = Math.max(0, Math.min(1, tokenUsageRatio));
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:575:  const limit = typeof options.limit === 'number' && Number.isFinite(options.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:576:    ? Math.max(0, Math.floor(options.limit))
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:583:  if (limit === 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:620:  return sampled.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:639:  if (typeof t.mode.tokenUsageRatio === 'number' && Number.isFinite(t.mode.tokenUsageRatio)) {
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/retrieval-telemetry.ts:640:    modePayload.tokenUsageRatio = Math.max(0, Math.min(1, t.mode.tokenUsageRatio));
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/diff-parser.ts:249:        // `-` with no remaining old-side budget: this is NOT a
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/diff-parser.ts:261:        // Same reasoning as `-`: out-of-budget `+` is the next
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/subprocess.ts:278:      const budgetRemaining = timeoutMs - (performance.now() - startedAt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/subprocess.ts:279:      if (busy && attempt === 0 && budgetRemaining >= 500) {
.opencode/skills/system-spec-kit/mcp_server/utils/README.md:51:- Input limits align with core constants (`MAX_QUERY_LENGTH`, `INPUT_LIMITS`).
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/promptPoisoningAdversarial.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/entity-extractor.vitest.ts:115:  it('keeps dotted technology names inside a single key phrase token', () => {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/reconsolidation.ts:133:  options: { limit: number; specFolder?: string }
.opencode/skills/system-spec-kit/mcp_server/lib/storage/reconsolidation.ts:174: * @param limit - Maximum number of results (default: 3)
.opencode/skills/system-spec-kit/mcp_server/lib/storage/reconsolidation.ts:181:  limit: number = SIMILAR_MEMORY_LIMIT
.opencode/skills/system-spec-kit/mcp_server/lib/storage/reconsolidation.ts:184:    return findSimilar(embedding, { limit, specFolder });
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/consumption-logger.ts:74:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/telemetry/consumption-logger.ts:279:  const exampleLimit = options.limit ?? 5;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:3:description: "Pre-flight quality gates for memory operations: anchor validation, duplicate detection and token budget verification."
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:12:> Pre-flight quality gates for memory operations: anchor validation, duplicate detection, token budget verification and content size checks.
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:39:| Pre-flight Checks | 4 | Anchors, duplicates, tokens, content size |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:50:| **Token Budget** | Estimates tokens and enforces limits before API calls |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:70:| `preflight.ts` | All validation logic: anchors, duplicates, tokens, content size, unified preflight |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:100:Prevents exceeding embedding API limits:
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:104:| Chars per token | 4 | `MCP_CHARS_PER_TOKEN` |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:105:| Max tokens | 8000 | `MCP_MAX_MEMORY_TOKENS` |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:130:| PF020 | TOKEN_BUDGET_EXCEEDED | Over token limit |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:131:| PF021 | TOKEN_BUDGET_WARNING | Approaching limit |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:144:| `estimateTokens` | `(content: string \| unknown) => number` | Estimate token count |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:145:| `checkTokenBudget` | `(content: string, options?) => TokenBudgetResult` | Check against token limit |
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:206:  check_tokens: true,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:231:const tokens = estimateTokens(content);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:232:console.log(`Estimated: ${tokens} tokens`);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:234:const budget = checkTokenBudget(content, { maxTokens: 4000 });
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:235:if (!budget.within_budget) {
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:236:  console.log(`Over budget: ${budget.estimated_tokens}/${budget.maxTokens}`);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:302:# Token budget
.opencode/skills/system-spec-kit/mcp_server/lib/validation/README.md:307:# Content limits
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/index.ts:9:export * from './budget-allocator.js';
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:120:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:121:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:149:  truncated?: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:150:  truncationLimit?: number | null;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:516:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:517:  truncated: boolean,
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:520:  result.truncated = truncated;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:521:  result.limit = limit;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:525:function getEdgesFrom(sourceId: string, limit: number = MAX_EDGES_LIMIT): EdgeQueryResult {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:526:  if (!db) return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:534:    `) as Database.Statement).all(sourceId, limit + 1) as CausalEdgeRow[];
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:535:    const truncated = rows.length > limit;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:536:    const edges = (truncated ? rows.slice(0, limit) : rows).map(normalizeCausalEdgeRow);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:542:    return createEdgeQueryResult(edges, limit, truncated);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:546:    return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:550:function getEdgesTo(targetId: string, limit: number = MAX_EDGES_LIMIT): EdgeQueryResult {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:551:  if (!db) return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:559:    `) as Database.Statement).all(targetId, limit + 1) as CausalEdgeRow[];
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:560:    const truncated = rows.length > limit;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:561:    const edges = (truncated ? rows.slice(0, limit) : rows).map(normalizeCausalEdgeRow);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:567:    return createEdgeQueryResult(edges, limit, truncated);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:571:    return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:575:function getAllEdges(limit: number = MAX_EDGES_LIMIT): EdgeQueryResult {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:576:  if (!db) return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:583:    `) as Database.Statement).all(limit + 1) as CausalEdgeRow[];
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:584:    const truncated = rows.length > limit;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:585:    const edges = (truncated ? rows.slice(0, limit) : rows).map(normalizeCausalEdgeRow);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:586:    return createEdgeQueryResult(edges, limit, truncated);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:590:    return createEdgeQueryResult([], limit, false);
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:610:    truncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:611:    truncationLimit: null,
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:623:    if (edges.truncated) {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:624:      root.truncated = true;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:625:      root.truncationLimit = edgeLimit;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:917:function getWeightHistory(edgeId: number, limit: number = 50): WeightHistoryEntry[] {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/causal-edges.ts:925:    `) as Database.Statement).all(edgeId, limit) as WeightHistoryEntry[];
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:74:   * the limit-pre-filter window or scope filter has starved otherwise-relevant
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:347:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:352:    limit: args.limit * (args.overfetchMultiplier ?? 1),
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:397:    if (candidates.length >= args.limit) {
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:544:                  limit: opts.limit ?? 3,
.opencode/skills/system-spec-kit/mcp_server/handlers/save/reconsolidation-bridge.ts:785:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/ambiguousTopTwo.json:26:    "tokenCap": 120
.opencode/skills/system-spec-kit/mcp_server/lib/validation/spec-doc-structure.ts:219:      error: 'frontmatter opening delimiter is missing a closing ---',
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:11:  parseHookStdin, hookLog, formatHookOutput, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:355:  let budget: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:362:      budget = COMPACTION_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:366:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:370:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:374:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:378:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:381:  // Apply token pressure awareness — reduce budget when context window is filling up
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:383:    input.context_window_tokens as number | undefined,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:385:    budget,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:387:  if (adjustedBudget !== budget) {
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:388:    hookLog('info', 'session-prime', `Token pressure: budget ${budget} → ${adjustedBudget} (window ${input.context_window_tokens}/${input.context_window_max})`);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:391:  const output = truncateToTokenBudget(formatHookOutput(sections), adjustedBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-session-resume.vitest.ts:133:  it('keeps the 3-level happy-path resume ladder under the Gate D latency budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/formatters/index.ts:13:} from './token-metrics.js';
.opencode/skills/system-spec-kit/mcp_server/lib/storage/mutation-ledger.ts:47:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/storage/mutation-ledger.ts:205:  const limit = opts.limit ? `LIMIT ${Math.max(1, Math.floor(opts.limit))}` : '';
.opencode/skills/system-spec-kit/mcp_server/lib/storage/mutation-ledger.ts:207:  // When offset is set but limit is not, emit LIMIT -1 (all rows) before OFFSET.
.opencode/skills/system-spec-kit/mcp_server/lib/storage/mutation-ledger.ts:209:  const effectiveLimit = !limit && offset ? 'LIMIT -1' : limit;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/save-quality-gate.ts:94:  options: { limit: number; specFolder?: string }
.opencode/skills/system-spec-kit/mcp_server/lib/validation/save-quality-gate.ts:536:  // Check for YAML frontmatter (--- delimited block at start)
.opencode/skills/system-spec-kit/mcp_server/lib/validation/save-quality-gate.ts:705:      limit: 1,
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/unicodeInstructionalSkillLabel.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:4:// Parses Claude Code transcript JSONL files to extract token usage,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:21:/** Aggregated token usage for an entire transcript */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:50:  input_tokens?: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:51:  output_tokens?: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:52:  cache_creation_input_tokens?: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:53:  cache_read_input_tokens?: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:122:  const promptTokens = usage.input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:123:  const completionTokens = usage.output_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:124:  const cacheCreationTokens = usage.cache_creation_input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:125:  const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:143:/** Parse a transcript JSONL file and extract token usage.
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:185:          const prompt = u.input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:186:          const completion = u.output_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:187:          const cacheCreation = u.cache_creation_input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:188:          const cacheRead = u.cache_read_input_tokens ?? 0;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:268:/** Estimate cost in USD based on model and token counts */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/claude-transcript.ts:272:  // Pricing per 1M tokens (approximate)
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:11://   - 250ms latency budget (aborts if exceeded)
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:12://   - 200 token max for injected content
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:15:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:24:  /** Total estimated tokens added */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:25:  tokenCount: number;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:36:  /** Max tokens to inject (default: 200) */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:37:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:78:  tokenBudget: number,
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:107:    if (estimateTokenCount(hint) > tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:108:      // Trim to fit budget
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:110:      return estimateTokenCount(trimmed) <= tokenBudget ? [trimmed] : [];
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:148: * @param options      - Deadline and token budget overrides
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:157:  const tokenBudget = options?.tokenBudget ?? DEFAULT_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:161:    return { hints: [], tokenCount: 0, latencyMs: 0, skipped: true, skipReason: 'recursion_guard' };
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:167:    let tokensUsed = 0;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:172:      const graphHints = await enrichWithCodeGraphSymbols(paths, tokenBudget - tokensUsed);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:175:        if (tokensUsed + cost > tokenBudget) break;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:177:        tokensUsed += cost;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:182:    if (Date.now() - startTime < deadlineMs && tokensUsed < tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:186:        if (tokensUsed + cost > tokenBudget) break;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:188:        tokensUsed += cost;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:199:    return { hints, tokenCount: tokensUsed, latencyMs, skipped: false };
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:205:      tokenCount: 0,
.opencode/skills/system-spec-kit/mcp_server/handlers/save/post-insert.ts:30:} from '../../lib/enrichment/retry-budget.js';
.opencode/skills/system-spec-kit/mcp_server/handlers/save/post-insert.ts:447:      `[memory-save] Retry budget exhausted for memory #${id} step=causal_links reason=partial_causal_link_unresolved attempts=${attempts}`,
.opencode/skills/system-spec-kit/mcp_server/tests/stage2-fusion.vitest.ts:73:      limit: candidates.length,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:33:  max_tokens_per_memory: number;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:77:/** Result of token budget check */
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:79:  within_budget: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:80:  estimated_tokens: number;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:134:  check_tokens?: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:196:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:234:  // Token budget estimation (~4 chars/token — harmonized with quality-loop.ts)
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:236:  max_tokens_per_memory: parseInt(process.env.MCP_MAX_MEMORY_TOKENS || '8000', 10),
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:239:  // Content size limits
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:557:        limit: 1,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:615:    maxTokens = PREFLIGHT_CONFIG.max_tokens_per_memory,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:621:    within_budget: true,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:622:    estimated_tokens: 0,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:630:    result.warnings.push('No content provided for token budget check');
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:634:  // Estimate tokens for content
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:643:  result.estimated_tokens = estimated;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:646:  // Check if over budget
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:648:    result.within_budget = false;
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:651:      message: `Content exceeds token budget: ${estimated} tokens (max: ${maxTokens})`,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:652:      suggestion: `Reduce content by approximately ${estimated - maxTokens} tokens (${Math.ceil((estimated - maxTokens) * PREFLIGHT_CONFIG.charsPerToken)} characters)`,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:655:  // Check if approaching budget
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:659:      message: `Content is ${Math.round(result.percentage_used * 100)}% of token budget (${estimated}/${maxTokens} tokens)`,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:754:    check_tokens = true,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:777:  // 010-index-large-files: token-budget overages can be warnings when chunking can safely handle them.
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:815:  // 3. Token budget estimation
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:816:  if (check_tokens && content) {
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:817:    const tokenResult = checkTokenBudget(content);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:818:    addCheck('token_budget', tokenResult);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:820:    if (!tokenResult.within_budget) {
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:823:        result.warnings.push(...tokenResult.errors);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:826:        result.errors.push(...tokenResult.errors);
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:829:    if (tokenResult.warnings.length > 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:830:      result.warnings.push(...tokenResult.warnings);
.opencode/skills/system-spec-kit/mcp_server/formatters/README.md:7:  - "token metrics"
.opencode/skills/system-spec-kit/mcp_server/formatters/README.md:31:- `token-metrics.ts`: token estimation and savings metrics.
.opencode/skills/system-spec-kit/mcp_server/formatters/README.md:40:- Result payloads include content-level token metrics when anchor filtering is active.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/README.md:3:Core implementation for the structural code graph system. Provides file parsing, SQLite storage, graph queries, CocoIndex bridge, budget allocation, and compaction merging.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/README.md:16:| `budget-allocator.ts` | Token budget distribution with floor allocations + overflow pool |
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/README.md:28:The compact-merger combines all three under a 4000-token budget for compaction injection.
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/skipPolicyEmptyPrompt.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/storage/history.ts:344:export function getHistory(memoryId: number, limit?: number): HistoryEntry[] {
.opencode/skills/system-spec-kit/mcp_server/lib/storage/history.ts:347:  const sql = limit != null
.opencode/skills/system-spec-kit/mcp_server/lib/storage/history.ts:351:  const params: (number)[] = limit != null ? [memoryId, limit] : [memoryId];
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/feature_catalog/02--auto-indexing/03-provenance-and-trust-lanes.md:25:Make derived entries inspectable and weighted by source. Every derived token carries a provenance fingerprint (so operators can tell when an entry truly changed) and a trust lane (so the scorer knows whether evidence came from author-declared signals, body prose, examples, or local docs).
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/README.md:3:description: "Passive response enrichment with bounded latency and token budgets."
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/README.md:15:The enrichment path can attach nearby code-graph symbols and degraded-continuity warnings, while staying inside a latency deadline and token budget.
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/README.md:12:| `session-stop.ts` | Stop (async) | Parses transcript for token usage, stores snapshots |
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/README.md:13:| `claude-transcript.ts` | (library) | JSONL transcript parser, token counting, cost estimation |
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/README.md:23:Stop → parse transcript, save token snapshot
.opencode/skills/system-spec-kit/mcp_server/tests/ground-truth-feedback.vitest.ts:126:    it('respects the limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/handlers/save/pe-orchestration.ts:58:      limit: 5,
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:9:import { estimateTokens } from './token-metrics.js';
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:104:  tokenMetrics?: AnchorTokenMetrics;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:137:  budgetTruncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:639:  let budgetTruncated = false;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:669:    if (meta.budgetTruncated === true || meta.truncated === true) {
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:670:      budgetTruncated = true;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:725:    budgetTruncated,
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:920:          // BUG-017 FIX: Capture original tokens BEFORE any content reassignment
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:959:            formattedResult.tokenMetrics = {
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:969:            formattedResult.tokenMetrics = {
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:1037:    hints.push('Anchor filtering applied for token efficiency');
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:8: * @invariant ephemeral — budget entries do not persist across process restarts.
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:58:/** Return whether the retry budget still permits another attempt. */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:64:/** Return the current retry-budget entry for one memory/step/reason tuple. */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:73:/** Record a failed enrichment attempt and return the updated budget entry. */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:75:  const budgetKey = buildRetryBudgetKey(memoryId, step, reason);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:77:  const existing = retryBudget.get(budgetKey);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:92:  retryBudget.set(budgetKey, entry);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:103:  for (const budgetKey of retryBudget.keys()) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:104:    const entry = retryBudget.get(budgetKey);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:106:      retryBudget.delete(budgetKey);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:111:/** Clear every retry budget entry in the current process. */
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts:116:/** Expose the current retry-budget size for diagnostics and tests. */
.opencode/skills/system-spec-kit/mcp_server/tests/retry-manager.vitest.ts:355:      it('T30: getRetryQueue() respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-manager.vitest.ts:357:          insertTestMemory(2020 + i, `/tmp/limit${i}.md`, 'pending');
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:10:/** Token budget for compaction context injection */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:12:/** Token budget for session priming (startup/resume) */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:95:/** Estimate token count (rough: 1 token ≈ 4 chars) and truncate if over budget */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96:export function truncateToTokenBudget(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:100:  return text.slice(0, maxChars) + '\n[...truncated to fit token budget]';
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:114:/** Calculate pressure-adjusted budget based on context window usage */
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/feature_catalog/02--auto-indexing/06-df-idf-corpus.md:25:Feed the lexical lane with corpus-aware statistics so common tokens are discounted and skill-distinctive tokens dominate scoring. The corpus is restricted to active skills to avoid polluting routing with archived or future content.
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/noPassingSkill.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:10:/** Tiered search result for token metric calculation */
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:35:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:44:  // Estimate tokens if ALL matches returned full content
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:49:  // Actual tokens returned
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:59:  // Hot tokens (full content)
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:64:  // Warm tokens (summaries)
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts:81:    note: 'Token estimates use ~4 chars/token approximation'
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/feedback-ledger.ts:66:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/feedback-ledger.ts:271:    const limit = opts.limit ? `LIMIT ${Math.max(1, Math.floor(opts.limit))}` : '';
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/feedback-ledger.ts:273:    const effectiveLimit = !limit && offset ? 'LIMIT -1' : limit;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:86:function tokenize(query: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:90:function countKeywordHits(tokens: string[], keywords: Set<string>): { count: number; matched: string[] } {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:92:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:93:    if (keywords.has(token)) matched.push(token);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:96:  const lowerQuery = tokens.join(' ');
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:128:  const tokens = tokenize(query);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:129:  const structuralHits = countKeywordHits(tokens, STRUCTURAL_KEYWORDS);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/query-intent-classifier.ts:130:  const semanticHits = countKeywordHits(tokens, SEMANTIC_KEYWORDS);
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:11:  it('uses caller tokenUsage when provided (55%, 65%, 85%, 95%)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:30:  it('clamps out-of-range caller tokenUsage to [0,1]', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:35:  it('derives pressure from runtimeContextStats when caller tokenUsage is missing', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:36:    const result = getPressureLevel(undefined, { tokenCount: 1300, tokenBudget: 2000 });
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:43:    const result = getPressureLevel(undefined, { tokenCount: 2000 });
.opencode/skills/system-spec-kit/mcp_server/handlers/session-resume.ts:345:      'Producer metadata was missing required transcript identity or cache token fields.',
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/explicit.ts:6:import { matchesPhraseBoundary, phraseSpecificity, skillNameVariants, tokenize } from '../text.js';
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/explicit.ts:146:  const tokens = tokenize(prompt, true);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/explicit.ts:156:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/explicit.ts:157:    for (const [skillId, amount] of TOKEN_BOOSTS[token] ?? []) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/explicit.ts:158:      push(scores, skillId, amount, `token:${token}`);
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/shadow-evaluation-runtime.ts:227:    limit: searchLimit,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:6:// token usage, stores a snapshot, and updates lightweight session state.
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:223:  // No good sentence boundary — hard truncate at 200
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:227:/** Log token snapshot details after transcript parsing succeeds. */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:241: * metadata pointing at a later state than the tokens/offset reflect.
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:318:  // Parse transcript for token usage
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-stop.ts:385:          `Parsed ${usage.messageCount} messages: ${usage.promptTokens} prompt + ${usage.completionTokens} completion = ${usage.totalTokens} total tokens`);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/feature_catalog/02--auto-indexing/05-anti-stuffing.md:34:2. Repetition-density demotion when the same token appears with abnormally high frequency.
.opencode/skills/system-spec-kit/mcp_server/lib/extraction/redaction-gate.ts:27:  { category: 'bearer_token', expression: /\bBearer\s+[A-Za-z0-9._\-]{20,}\b/gi },
.opencode/skills/system-spec-kit/mcp_server/lib/ops/job-queue.ts:370:    const truncationNotice: IngestJobError = {
.opencode/skills/system-spec-kit/mcp_server/lib/ops/job-queue.ts:372:      message: `error log truncated (${trimmedCount} older entries removed)`,
.opencode/skills/system-spec-kit/mcp_server/lib/ops/job-queue.ts:375:    const truncatedTail = tailLength > 0 ? errors.slice(-tailLength) : [];
.opencode/skills/system-spec-kit/mcp_server/lib/ops/job-queue.ts:376:    errors = [truncationNotice, ...truncatedTail];
.opencode/skills/system-spec-kit/mcp_server/lib/ops/job-queue.ts:600:  // Track actual failure count independently of the truncated errors array.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:26:  budgetTokens?: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:42:    budgetUsed: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:43:    budgetLimit: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:47:      reasons: Array<'deadline' | 'budget'>;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:50:      truncatedText: boolean;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:86:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:105:  const budgetTokens = args.budgetTokens ?? 1200;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:123:    return buildEmptyFallback(queryMode, budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:134:  const partialReasons = new Set<'deadline' | 'budget'>();
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:136:  // Profile-based limits
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:142:    // Deadline check: stop processing further anchors if over budget
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:177:  const formattedTextBrief = formatTextBrief(sections, budgetTokens, resolvedAnchors);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:178:  if (formattedTextBrief.omittedSections > 0 || formattedTextBrief.truncated) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:179:    partialReasons.add('budget');
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:199:      budgetUsed: Math.ceil(formattedTextBrief.text.length / 4),
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:200:      budgetLimit: budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:207:        truncatedText: formattedTextBrief.truncated,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:215:function buildEmptyFallback(queryMode: QueryMode, budgetTokens: number): ContextResult {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:226:      budgetUsed: 0,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:227:      budgetLimit: budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:234:        truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:324:  const budgetMs = remainingMs ?? 400; // 400ms default latency budget
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:340:  const budgetExpired = (): boolean => performance.now() - startTime > budgetMs;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:375:        if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:383:          if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:405:          if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:430:        if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:442:          if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:460:      // Latency guard: break early if queries exceed budget (400ms default)
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:463:        if (elapsed > budgetMs) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:464:          console.warn(`[code-graph-context] impact query exceeded ${budgetMs}ms budget (${Math.round(elapsed)}ms elapsed), breaking early`);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:472:          if (budgetExpired()) {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:531: * Format sections into compact text brief within token budget.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:534:function formatTextBrief(sections: GraphContextSection[], budgetTokens: number, _anchors?: ArtifactRef[]): FormattedTextBrief {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:535:  const maxChars = budgetTokens * 4;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:575:    // Budget check: stop adding sections if we're over budget (but first section always included)
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:578:      lines.push(`[${omittedSections} more sections omitted — budget limit]`);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:584:  let truncated = false;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:586:    truncated = true;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:587:    result = result.slice(0, maxChars) + '\n[...truncated]';
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:592:    truncated,
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/skipPolicyCommandOnly.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/handlers/session-bootstrap.ts:302:      limit: 5,
.opencode/skills/system-spec-kit/mcp_server/handlers/session-bootstrap.ts:459:        `Cache tokens: create=${cachedSummary.cachedSummary.cacheCreationInputTokens}; read=${cachedSummary.cachedSummary.cacheReadInputTokens}`,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-triggers.vitest.ts:124:    it('T517-7: invalid limit values fall back to the default match cap', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-triggers.vitest.ts:132:        limit: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-triggers.vitest.ts:252:  it('enforces caller limit on cognitive path responses', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-triggers.vitest.ts:300:      .mockImplementation((memories, _state, limit = 20) => memories.slice(0, limit));
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-triggers.vitest.ts:308:      limit: requestedLimit,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:13:  parseHookStdin, hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:212: * Extracts session state from transcript, then delegates budget allocation
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:290:    hookLog('warn', 'compact-inject', `Merge pipeline took ${elapsed.toFixed(0)}ms (budget: ${HOOK_TIMEOUT_MS}ms)`);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:292:    hookLog('info', 'compact-inject', `Merge pipeline completed in ${elapsed.toFixed(0)}ms (${merged.metadata.sourceCount} sections, ~${merged.metadata.totalTokenEstimate} tokens)`);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:396:    payload = truncateToTokenBudget(mergedContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:425:    payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:14:  hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:142:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:6:import { matchesPhraseBoundary, scoreTokenOverlap, tokenize } from '../text.js';
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:42:  const tokens = tokenize(prompt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:43:  const expanded = new Set(tokens);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:44:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:45:    for (const synonym of SYNONYMS[token] ?? []) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:54:  const tokens = expandedTokens(prompt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:59:    let score = scoreTokenOverlap(tokens, [
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:75:    const tokenHits = tokens.filter((token) => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:77:      return haystack.includes(token);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/lexical.ts:79:    evidence.push(...tokenHits.map((token) => `token:${token}`));
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:26:// Similarity thresholds (Jaccard on normalized tokens)
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:36:  tokens: Set<string>;
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:72:function tokenize(query: string): Set<string> {
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:85:  for (const token of a) {
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:86:    if (b.has(token)) intersection++;
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:102:  tokens: Set<string>,
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:117:  const similarity = jaccardSimilarity(tokens, previous.tokens);
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:169:  const tokens = tokenize(query);
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:175:  const detection = detectFlow(sessionId, tokens, timestamp);
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/query-flow-tracker.ts:179:  entries.push({ tokens, timestamp, queryId, shownMemoryIds });
.opencode/skills/system-spec-kit/mcp_server/lib/ops/README.md:54:- Bounded concurrency: A semaphore limits parallel re-index operations to 2.
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:19:  hookLog, formatHookOutput, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:271:  let budget: number;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:280:      budget = COMPACTION_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:288:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:292:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:296:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:304:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:307:  const rawOutput = truncateToTokenBudget(formatHookOutput(sections), budget);
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/staleHighConfidenceSkill.json:22:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/semantic-shadow.ts:6:import { scoreTokenOverlap, tokenize } from '../text.js';
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/semantic-shadow.ts:9:  const tokens = tokenize(prompt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/semantic-shadow.ts:14:      score: Math.min(scoreTokenOverlap(tokens, [
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/semantic-shadow.ts:21:      evidence: ['shadow:token-overlap'],
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget-telemetry.vitest.ts:3:import { clearAllBudgets } from '../lib/enrichment/retry-budget.js';
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget-telemetry.vitest.ts:13:describe('retry-budget telemetry', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget-telemetry.vitest.ts:82:  it('emits give_up when the unresolved causal-link retry budget is exhausted', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget-telemetry.vitest.ts:140:  it('emits resolved after a later successful post-insert run clears the budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:29:import { estimateTokens } from '../formatters/token-metrics.js';
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:76:  readonly tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:85:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:110:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:121:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:126:  tokenUsage?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:132:/** T205: Token budget enforcement metadata */
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:133:type DroppedAllResultsReason = 'impossible_budget' | 'parse_failed' | 'no_survivor_fits';
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:136:  budgetTokens: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:142:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:330:function convertResumeLadderToRows(result: ResumeLadderResult, limit: number): ResumeRow[] {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:344:  return preferredDocuments.slice(0, limit).map((document) => {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:451:   Enforces per-layer/per-mode token budgets by estimating the
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:452:   token count of strategy results and truncating when exceeded.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:453:   Uses character-based estimation: 1 token ≈ 4 chars.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:457: * T205: Enforce token budget on strategy results.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:459: * Estimates the token count of the serialized result. If over budget,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:461: * until within budget. Higher-scored results are preserved.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:463:function enforceTokenBudget(result: ContextResult, budgetTokens: number): { result: ContextResult; enforcement: TokenBudgetEnforcement } {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:467:  // Under budget — no enforcement needed
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:468:  if (preEnforcementTokens <= budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:472:        budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:477:        truncated: false,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:482:  // REQ-002 (Cluster 1) Sanity guard: when reported usage is far below budget but
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:483:  // we somehow entered enforcement (e.g. estimator ran twice on already-truncated
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:484:  // payload, or budget was passed in as a tiny number), short-circuit and return
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:486:  // 71-token payload against a 3000-token budget was nuked to count:0,results:[].
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:487:  if (budgetTokens > 0 && preEnforcementTokens / budgetTokens < 0.50) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:491:        budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:496:        truncated: false,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:501:  // Over budget — attempt to truncate embedded results
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:503:  // That JSON has a .data.results array we can truncate
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:504:  const truncatedResult = { ...result };
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:534:    // REQ-002 (Cluster 1): When structural truncation already produced a non-empty
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:558:          summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:565:            truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:570:          summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:577:            truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:587:        summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:594:          truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:605:          truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:639:      if (estimateTokens(JSON.stringify(fallbackResult)) <= budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:641:          droppedAllResultsReason = 'impossible_budget';
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:647:    droppedAllResultsReason = 'impossible_budget';
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:663:    const truncateKeys = ['content', 'snippet', 'summary', 'text'] as const;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:675:    for (const key of truncateKeys) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:704:          ...truncatedResult,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:709:        if (candidateTokens <= budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:729:  // Try to find and truncate the inner results array
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:730:  const contentArr = (truncatedResult as Record<string, unknown>).content as Array<{ type: string; text: string }> | undefined;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:744:        // Remove items from the end until we fit within budget
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:748:        // Phase 1: Adaptive content truncation — truncate content fields before dropping results
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:756:        // Re-estimate after content truncation
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:761:        // Phase 2: Drop lowest-scored results if still over budget
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:762:        while (currentResults.length > 1 && currentTokens > budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:783:          if (currentTokens + metadataTokens <= budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:800:        (truncatedResult as Record<string, unknown>).content = contentArr;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:802:        // Recalculate actual tokens after truncation
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:803:        const newSerializedTokens = estimateTokens(JSON.stringify(truncatedResult));
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:805:        if (newSerializedTokens <= budgetTokens) {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:807:            result: truncatedResult,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:809:              budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:814:              truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:826:              budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:831:              truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:841:      // JSON parse failed — fall through to structural truncation
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:845:  // Fallback when parsing fails or a structured response still exceeds budget.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:848:  // truncation so it can keep them instead of silently zero-filling.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:850:    parseFailed ? result : truncatedResult,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:862:    droppedAllResultsReason = 'impossible_budget';
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:868:      budgetTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:873:      truncated: true,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:898:    tokenBudget: 800
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:906:    tokenBudget: 3500
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:914:    tokenBudget: 3000
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:922:    tokenBudget: 2000
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:951:    limit: options.limit || 5,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:971:    limit: options.limit || 10,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1001:    limit: options.limit || 8,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1034:  const resumeRows = convertResumeLadderToRows(ladder, options.limit || 5);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1306:    tokenUsageSource: pressurePolicy.source,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1307:    tokenUsagePressure: pressurePolicy.ratio,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1316:    tokenBudget: effectiveBudget,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1317:    tokenBudgetEnforcement: enforcement,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1382:    limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1385:    tokenUsage,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1426:      // F050: Extract a symbol-like token from the query instead of passing
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1429:      // Heuristic: pick the first token that looks like a code identifier
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1521:  const tokenBudget = layerInfo?.tokenBudget ?? 2000;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1524:    tokenBudget,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1527:    runtimeContextStats.tokenCount = estimateTokens(normalizedInput);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1529:    runtimeContextStats.tokenCount = undefined;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1532:  // Resolve token pressure (caller -> estimator -> unavailable)
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1537:    ? getPressureLevel(tokenUsage, runtimeContextStats)
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1554:    limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1691:  // T205: Determine effective token budget from mode or layer definitions
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1692:  const modeTokenBudget = CONTEXT_MODES[effectiveMode]?.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1693:  const effectiveBudget = modeTokenBudget || tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1695:  // M1 FIX: Inject auto-resume context BEFORE budget enforcement
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1696:  // so the final response respects the advertised token budget.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1718:  // T205: Enforce token budget AFTER all context injection
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1719:  const { result: budgetedResult, enforcement } = enforceTokenBudget(tracedResult0, effectiveBudget);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1720:  const tracedResult = budgetedResult;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1761:    summary: enforcement.truncated
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1762:      ? `Context retrieved via ${effectiveMode} mode (${tracedResult.strategy} strategy) [truncated${enforcement.originalResultCount !== undefined ? `: ${enforcement.originalResultCount} → ${enforcement.returnedResultCount} results` : ''} to fit ${effectiveBudget} token budget]`
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1768:      `Token budget: ${effectiveBudget} (${effectiveMode} mode)`,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1853:      const strategy = typeof budgetedResult?.strategy === 'string' && budgetedResult.strategy.length > 0
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1854:        ? budgetedResult.strategy
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:13:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:230:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/derived.ts:8:import { matchesPhraseBoundary, phraseSpecificity, scoreTokenOverlap, tokenize } from '../text.js';
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/derived.ts:24:  const tokens = tokenize(prompt);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/derived.ts:48:    score += scoreTokenOverlap(tokens, phrases) * 0.45;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/lanes/derived.ts:49:    score += scoreTokenOverlap(tokens, affordancePhrases) * 0.25;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/startup-brief.ts:54:function truncateInline(text: string, maxChars: number): string {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/startup-brief.ts:222:    // Keep startup highlights small by default so graph context stays useful without crowding the token budget.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/startup-brief.ts:295:    parts.push(`Summary: ${truncateInline(state.sessionSummary.text, SUMMARY_MAX_CHARS)}`);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-list.ts:48:    limit: rawLimit = 20,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-list.ts:76:      error: 'limit must be a finite number',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-list.ts:172:      limit: safeLimit,
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/failOpenTimeout.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/extraction/README.md:49:| **Secret Detection** | Pattern-based scanning for API keys, tokens, and credentials |
.opencode/skills/system-spec-kit/mcp_server/lib/extraction/README.md:106:| **Secret Patterns** | API keys, bearer tokens, private keys, connection strings, `.env`-style assignments |
.opencode/skills/system-spec-kit/mcp_server/lib/extraction/README.md:171:const content = 'User token: sk-abc123xyz, email: user@example.com';
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/shared.ts:5:// ../claude/shared.js for budget, logging, and formatting.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:7:import { allocateBudget, createDefaultSources, type AllocationResult } from './budget-allocator.js';
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:36:    tokenEstimate: number;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:52:/** Estimate tokens from string (4 chars ≈ 1 token) */
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:57:/** Truncate text to fit within a token budget */
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:58:function truncateToTokens(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:62:  const marker = '\n[...truncated]';
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:107:      section.tokenEstimate = estimateTokens(section.content);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:117: * 1. Allocate budget across sources (floor + overflow)
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:118: * 2. Truncate each source to its granted budget
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:145:  // Build sections with granted budgets
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:159:    const content = truncateToTokens(inputText, granted);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:165:      tokenEstimate: estimateTokens(content),
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:184:  const totalTokenEstimate = sections.reduce((sum, s) => sum + s.tokenEstimate, 0);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:205:      summary: `Compaction payload merged ${sections.length} sections within ${totalBudget} tokens`,
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:212:        sourceRefs: ['budget-allocator', 'compact-merger'],
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:33:/** Strip absolute paths, stack traces, and truncate for safe user-facing hints. */
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:150:function getDivergentAliasGroups(rows: AliasConflictDbRow[], limit: number): DivergentAliasGroup[] {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:215:  return groups.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:243:    limit: rawLimit = DEFAULT_DIVERGENT_ALIAS_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:288:      error: 'limit must be a positive number',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:355:      hints.push(`More divergent alias groups available: increase limit above ${safeLimit}`);
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-health.ts:367:        limit: safeLimit,
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/shadow-scoring.ts:381:  opts: { queryId?: string; cycleId?: string; limit?: number } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/shadow-scoring.ts:399:    const limit = opts.limit ? `LIMIT ${Math.max(1, Math.floor(opts.limit))}` : '';
.opencode/skills/system-spec-kit/mcp_server/lib/feedback/shadow-scoring.ts:401:    const sql = `SELECT * FROM shadow_scoring_log ${where} ORDER BY evaluated_at DESC ${limit}`;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:29:export function tokenize(value: string, includeStopWords = false): string[] {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:30:  const tokens = Array.from(value.toLowerCase().matchAll(/\b\w+\b/g), (match) => match[0]);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:32:    ? tokens
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:33:    : tokens.filter((token) => token.length > 2 && !STOP_WORDS.has(token));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:71:  const count = Math.max(1, tokenize(phrase, true).length);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:76:  const candidateTokens = new Set(candidateText.flatMap((entry) => tokenize(entry)));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:79:  for (const token of promptTokens) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:80:    if (candidateTokens.has(token)) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/scorer/text.ts:85:      if (token.length >= 4 && candidate.length >= 4 && (token.includes(candidate) || candidate.includes(token))) {
.opencode/skills/system-spec-kit/mcp_server/tests/advisor-fixtures/skippedShortCasual.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-stop.ts:9:// token usage — the format differs and isn't documented yet.
.opencode/skills/system-spec-kit/mcp_server/handlers/checkpoints.ts:53:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/checkpoints.ts:365:  const { specFolder: spec_folder, limit: raw_limit = 50 } = args;
.opencode/skills/system-spec-kit/mcp_server/handlers/checkpoints.ts:375:  const limit = (typeof raw_limit === 'number' && Number.isFinite(raw_limit) && raw_limit > 0)
.opencode/skills/system-spec-kit/mcp_server/handlers/checkpoints.ts:376:    ? Math.min(Math.floor(raw_limit), 100)
.opencode/skills/system-spec-kit/mcp_server/handlers/checkpoints.ts:379:  const results = checkpoints.listCheckpoints(spec_folder ?? null, limit, scope);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-db.ts:510:export function queryStartupHighlights(limit: number = 5): StartupHighlight[] {
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-db.ts:512:  const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(Math.trunc(limit), 20)) : 5;
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-db.ts:871:/** Compute token usage ratio (completion / total) for budget allocator consumption */
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/content-normalizer.ts:18://   - bm25-index.ts     ~line 245  : where `content_text` is used for token building
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/content-normalizer.ts:81: * tokens like "typescript" or "json" carry no semantic signal about
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/content-normalizer.ts:138: * Normalize markdown list notation to clean prose tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/content-normalizer.ts:239: * but the code body is preserved so that exact identifier tokens
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/content-normalizer.ts:253: *   bm25-index.ts ~line 245 where `content_text` is used for token building.
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:16:  hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:92:  const rawOutput = truncateToTokenBudget(sections.join('\n'), COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:234:  // CJK text often appears in continuous sentence flow without whitespace-delimited
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:256:function isSignificantIndexToken(token: string): boolean {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:257:  if (!token) {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:261:  return token.length >= CONFIG.MIN_PHRASE_LENGTH && !COMMON_TRIGGER_STOPWORDS.has(token);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:271:  const tokens = rawTokens.filter(isSignificantIndexToken);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:272:  const basis = tokens.length > 0 ? tokens : rawTokens;
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:275:  for (const token of basis) {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:276:    if (token) {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:277:      keys.add(token);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:430:  const tokens = normalized.split(/\s+/).filter(Boolean);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:431:  if (tokens.length === 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:435:  if (tokens.length === 1) {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:436:    return !COMMON_TRIGGER_STOPWORDS.has(tokens[0]);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:439:  return tokens.some((token) => token.length >= CONFIG.MIN_PHRASE_LENGTH);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:750:export function matchTriggerPhrases(userPrompt: string, limit: number = CONFIG.DEFAULT_LIMIT): TriggerMatch[] {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:807:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:823:export function matchTriggerPhrasesWithStats(userPrompt: string, limit: number = CONFIG.DEFAULT_LIMIT): TriggerMatchWithStats {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/trigger-matcher.ts:826:  let matches = matchTriggerPhrases(userPrompt, limit);
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:49:  inputSchema: { type: 'object', additionalProperties: false, properties: { input: { type: 'string', minLength: 1, description: 'The query, prompt, or context description (required)' }, mode: { type: 'string', enum: ['auto', 'quick', 'deep', 'focused', 'resume'], default: 'auto', description: 'Context retrieval mode: auto (detect intent), quick (fast triggers), deep (comprehensive search), focused (intent-optimized), resume (session recovery)' }, intent: { type: 'string', enum: ['add_feature', 'fix_bug', 'refactor', 'security_audit', 'understand', 'find_spec', 'find_decision'], description: 'Explicit task intent. If not provided and mode=auto, intent is auto-detected from input.' }, specFolder: { type: 'string', description: 'Limit context to specific spec folder' }, tenantId: { type: 'string', description: 'Tenant boundary for governed retrieval when memory_context routes to memory_search.' }, userId: { type: 'string', description: 'User boundary for governed retrieval when memory_context routes to memory_search.' }, agentId: { type: 'string', description: 'Agent boundary for governed retrieval when memory_context routes to memory_search.' }, limit: { type: 'number', minimum: 1, maximum: 100, description: 'Maximum results (mode-specific defaults apply)' }, sessionId: { type: 'string', description: 'Optional server-issued session identifier for working-memory continuity. When provided, it must match an existing server-managed session or the call is rejected. Omit it to let the server generate a new session for this request.' }, enableDedup: { type: 'boolean', default: true, description: 'Enable session deduplication' }, includeContent: { type: 'boolean', default: false, description: 'Include full file content in results' }, includeTrace: { type: 'boolean', default: false, description: 'Include provenance-rich trace data (scores, source, trace) in results when underlying memory_search is called' }, tokenUsage: { type: 'number', minimum: 0.0, maximum: 1.0, description: "Optional caller token usage ratio (0.0-1.0)" }, anchors: { type: 'array', items: { type: 'string' }, description: 'Filter content to specific anchors (e.g., ["state", "next-steps"] for resume mode)' }, profile: { type: 'string', enum: ['quick', 'research', 'resume', 'debug'], description: 'Optional response profile formatter. Returns a reduced or mode-aware response shape when profile formatting is enabled.' } }, required: ['input'] },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:55:  description: '[L2:Core] Search indexed spec-doc continuity semantically using vector similarity. Returns ranked results with similarity scores. Constitutional tier rules are ALWAYS included at the top of results (~2000 tokens max), regardless of query. Requires query (string), concepts (array of 2-5 strings), or cursor (string) for continuation pagination. Supports intent-aware retrieval (REQ-006) with task-specific weight adjustments. When implicit feedback logging is enabled, searches also emit shadow-only feedback signals such as search_shown and, for includeContent runs, result_cited. Token Budget: 3500. For code search by concept/intent, prefer mcp__cocoindex_code__search (CocoIndex). For structural code queries (callers, imports), prefer code_graph_query.',
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:78:      limit: { type: 'number', default: 10, minimum: 1, maximum: 100, description: 'Maximum number of results to return (1-100)' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:81:        description: 'Session identifier for working memory and session deduplication (REQ-001). When provided with enableDedup=true, prevents duplicate spec-doc records from being returned in the same session (~50% token savings on follow-up queries).'
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:150:        description: 'Apply per-tier quantity limits to results. When true, enforces maximum counts per state tier to balance result diversity.'
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:197:  description: '[L2:Core] Simplified search — query + optional limit + optional spec folder. Delegates to memory_search with sensible defaults (intent auto-detect ON, dedup ON, content included, limit 10). Use this when you want fast search without configuring 31 parameters.',
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:203:      limit: { type: 'number', default: 10, minimum: 1, maximum: 100, description: 'Maximum results (default 10)' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:216:  inputSchema: { type: 'object', additionalProperties: false, properties: { prompt: { type: 'string', minLength: 1, description: 'User prompt or text to match against trigger phrases' }, specFolder: { type: 'string', description: 'Limit trigger matches to a specific spec folder' }, tenantId: { type: 'string', description: 'Tenant boundary for governed trigger matching.' }, userId: { type: 'string', description: 'User boundary for governed trigger matching.' }, agentId: { type: 'string', description: 'Agent boundary for governed trigger matching.' }, limit: { type: 'number', default: 3, minimum: 1, maximum: 100, description: 'Maximum number of matching spec-doc records to return (default: 3)' }, session_id: { type: 'string', description: 'Session identifier for cognitive features. When provided, enables attention decay and tiered content injection.' }, turnNumber: { type: 'number', minimum: 1, description: 'Current conversation turn number. Used with session_id for decay calculations.' }, include_cognitive: { type: 'boolean', default: true, description: 'Enable cognitive features (decay, tiers, co-activation). Requires session_id.' } }, required: ['prompt'] },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:222:  description: '[L2:Core] Index a spec document or constitutional file into the spec kit memory database. Reads the file, extracts metadata (title, trigger phrases), generates embedding, and stores in the index. Routed saves write continuity into canonical spec documents (decision-record.md, implementation-summary.md, handover.md). Includes pre-flight validation (T067-T070) for anchor format, duplicate detection, and token budget estimation. Token Budget: 3500.',
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:223:  inputSchema: { type: 'object', additionalProperties: false, properties: { filePath: { type: 'string', minLength: 1, description: 'Absolute path to a spec document under specs/**/ or .opencode/specs/**/ (spec.md, plan.md, tasks.md, checklist.md, decision-record.md, implementation-summary.md, handover.md, research.md, resource-map.md, description.json, graph-metadata.json) or a constitutional memory under .opencode/skills/*/constitutional/' }, force: { type: 'boolean', default: false, description: 'Force re-index even if content hash unchanged' }, dryRun: { type: 'boolean', default: false, description: 'Validate only without saving. Returns validation results including anchor format, duplicate check, and token budget estimation (CHK-160)' }, skipPreflight: { type: 'boolean', default: false, description: 'Skip pre-flight validation checks (not recommended)' }, asyncEmbedding: { type: 'boolean', default: false, description: 'When true, embedding generation is deferred for non-blocking saves. The spec-doc record is immediately saved with pending status and an async background attempt is triggered. Default false preserves synchronous embedding behavior.' }, routeAs: { type: 'string', enum: ['narrative_progress', 'narrative_delivery', 'decision', 'handover_state', 'research_finding', 'task_update', 'metadata_only', 'drop'], description: 'Optional routing override hint for canonical continuity saves.' }, mergeModeHint: { type: 'string', enum: ['append-as-paragraph', 'insert-new-adr', 'append-table-row', 'update-in-place', 'append-section'], description: 'Optional merge-mode hint for routed canonical continuity saves.' }, tenantId: { type: 'string', description: 'Tenant boundary for governed ingest.' }, userId: { type: 'string', description: 'User boundary for governed ingest.' }, agentId: { type: 'string', description: 'Agent boundary for governed ingest.' }, sessionId: { type: 'string', description: 'Session boundary for governed ingest.' }, provenanceSource: { type: 'string', description: 'Required provenance source when governed ingest validation applies.' }, provenanceActor: { type: 'string', description: 'Required provenance actor when governed ingest validation applies.' }, governedAt: { type: 'string', description: 'ISO timestamp for governed ingest. Defaults to now when omitted.' }, retentionPolicy: { type: 'string', enum: ['keep', 'ephemeral'], description: 'Retention class applied to the saved spec-doc record.' }, deleteAfter: { type: 'string', description: 'Optional ISO timestamp after which retention sweep may delete the spec-doc record.' } }, required: ['filePath'] },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:230:  inputSchema: { type: 'object', additionalProperties: false, properties: { limit: { type: 'number', default: 20, minimum: 1, maximum: 100, description: 'Maximum results to return (max 100)' }, offset: { type: 'number', default: 0, minimum: 0, description: 'Number of results to skip (for pagination)' }, specFolder: { type: 'string', description: 'Filter by spec folder' }, sortBy: { type: 'string', enum: ['created_at', 'updated_at', 'importance_weight'], description: 'Sort order (default: created_at DESC)' }, includeChunks: { type: 'boolean', default: false, description: 'Include chunk child rows. Default false returns parent spec-doc records only for cleaner browsing.' } } },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:236:  inputSchema: { type: 'object', additionalProperties: false, properties: { folderRanking: { type: 'string', enum: ['count', 'recency', 'importance', 'composite'], description: 'How to rank folders: count (default, by indexed record count), recency (most recent first), importance (by tier), composite (weighted multi-factor score)', default: 'count' }, excludePatterns: { type: 'array', items: { type: 'string' }, description: 'Regex patterns to exclude folders (e.g., ["z_archive", "scratch"])' }, includeScores: { type: 'boolean', description: 'Include score breakdown for each folder', default: false }, includeArchived: { type: 'boolean', description: 'Include archived/test/scratch folders in results', default: false }, limit: { type: 'number', minimum: 1, maximum: 100, description: 'Maximum number of folders to return', default: 10 } } },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:252:      limit: {
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:358:      limit: { type: 'number', default: 50, minimum: 1, maximum: 100 }
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:485:      limit: { type: 'number', minimum: 1, maximum: 200, description: 'Maximum sprint groups to return (most recent).' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:502:  inputSchema: { type: 'object', additionalProperties: false, properties: { specFolder: { type: 'string', minLength: 1, description: 'Spec folder path to get learning history for (required)' }, sessionId: { type: 'string', description: 'Filter by session ID (optional)' }, limit: { type: 'number', default: 10, minimum: 1, maximum: 100, description: 'Maximum records to return (default: 10, max: 100)' }, onlyComplete: { type: 'boolean', default: false, description: 'Only return records with both PREFLIGHT and POSTFLIGHT (complete learning cycles)' }, includeSummary: { type: 'boolean', default: true, description: 'Include summary statistics (averages, trends) in response' } }, required: ['specFolder'] },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:583:      limit: { type: 'number', minimum: 1, maximum: 200, default: 50, description: 'Max results' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:600:  description: '[L6:Analysis] Get LLM-oriented compact graph neighborhoods. Accepts CocoIndex search results as seeds — use CocoIndex (mcp__cocoindex_code__search) for semantic search first, then pass results here for structural expansion. Supports manual seeds (provider: manual) and graph seeds (provider: graph). Modes: neighborhood (1-hop calls+imports), outline (file symbols), impact (reverse callers). When readiness requires a full scan, returns an explicit blocked payload with requiredAction `code_graph_scan`, readiness metadata, and lastPersistedAt instead of degraded graph answers. Successful responses include metadata.partialOutput for deadline/budget truncation details (reasons, omittedSections, omittedAnchors, truncatedText). Token Budget: 1200.',
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:630:      budgetTokens: { type: 'number', minimum: 100, maximum: 4000, default: 1200, description: 'Token budget for response' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:698:      limit: { type: 'number', minimum: 1, maximum: 200, default: 50, description: 'Maximum results to return for list queries' },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:855:      limit: { type: 'number', minimum: 1, maximum: 200, default: 50, description: 'Max results to return' },
.opencode/skills/system-spec-kit/mcp_server/tests/history.vitest.ts:173:    it('T508-03: getHistory respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/history.vitest.ts:174:      const limited = mod.getHistory(1, 2);
.opencode/skills/system-spec-kit/mcp_server/tests/history.vitest.ts:175:      expect(Array.isArray(limited)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/history.vitest.ts:176:      expect(limited.length).toBeLessThanOrEqual(2);
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/interference-scoring.ts:80:  const tokenize = (text: string): Set<string> => {
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/interference-scoring.ts:89:  const setA = tokenize(textA);
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/interference-scoring.ts:90:  const setB = tokenize(textB);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/error-diagnostics.ts:61:  if (/\b(parse|json|syntaxerror|unexpected token)\b/.test(lowered)) {
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:3:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:63:  it('appendAutoSurfaceHints injects hints and sets tokenCount from the final serialized envelope JSON', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:66:        prompt_tokens: 100,
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:67:        completion_tokens: 50,
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:68:        cache_creation_tokens: 25,
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:69:        cache_read_tokens: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:78:            meta: { tokenCount: 12 },
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:99:      tokenCount: 185,
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:102:    expect(parsed.meta.tokenCount).not.toBe(12);
.opencode/skills/system-spec-kit/mcp_server/tests/hooks-ux-feedback.vitest.ts:103:    expect(parsed.meta.tokenCount).toBe(estimateTokenCount(finalText));
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:182:    const sharedTriggers = 'authentication, login, session, token, validation, handler, middleware, security, user, access';
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:184:      title: 'authentication login session token validation handler middleware security user access primary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:189:      title: 'authentication login session token validation handler middleware security user access secondary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:194:      title: 'authentication login session token validation handler middleware security user access tertiary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:239:    const sharedTriggers = 'authentication, login, session, token, validation, handler, middleware, security, user, access';
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:241:      title: 'authentication login session token validation handler middleware security user access primary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:246:      title: 'authentication login session token validation handler middleware security user access archived',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:253:      title: 'authentication login session token validation handler middleware security user access deprecated',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:340:    const sharedTriggers = 'authentication, login, session, token, validation, handler, middleware, security, user, access';
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:342:      title: 'authentication login session token validation handler middleware security user access primary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:347:      title: 'authentication login session token validation handler middleware security user access secondary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:365:    const sharedTriggers = 'authentication, login, session, token, validation, handler, middleware, security, user, access';
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:367:      title: 'authentication login session token validation handler middleware security user access primary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:372:      title: 'authentication login session token validation handler middleware security user access secondary',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:377:      title: 'authentication login session token validation handler middleware security user access archived',
.opencode/skills/system-spec-kit/mcp_server/tests/interference.vitest.ts:384:      title: 'authentication login session token validation handler middleware security user access deprecated',
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/README.md:49:- `content-normalizer.ts` is the shared normalization path for both embedding generation and BM25 token building.
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:57:| **Budget allocation** | Token budget enforcement on context payloads (`lib/budget-allocator.ts`) |
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:82:│   ├── budget-allocator.ts         # Context size budgets
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:155:| `metadata.partialOutput` | `isPartial`, `reasons`, `omittedSections`, `omittedAnchors`, `truncatedText` | Explains whether deadline or budget pressure trimmed the response |
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:156:| `metadata.deadlineMs` | Effective per-call deadline (ms) | Makes the bounded-work deadline explicit so callers can correlate `partialOutput.reasons` with the budget that produced them |
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:169:| **OpenCode plugin compact-code-graph `--minimal` resume** | Yes | Yes (including stale graphs) | Reuses the shared snapshot payload while keeping `RESUME_MODE = 'minimal'` for token economy | OpenCode TUI session compaction |
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:186:| Partial-output metadata | `lib/code-graph-context.ts` | `metadata.partialOutput` tracks deadline/budget truncation with omitted section/anchor counts |
.opencode/skills/system-spec-kit/mcp_server/code_graph/README.md:192:| Compact plugin resume mode | `.opencode/plugins/spec-kit-compact-code-graph.js` | `RESUME_MODE = 'minimal'` is intentional, kept for token economy |
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/composite-scoring.ts:881:  // Larger than ~100K elements (exceeds JS call-stack argument limit).
.opencode/skills/system-spec-kit/mcp_server/handlers/session-learning.ts:47:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/session-learning.ts:664:    limit = 10,
.opencode/skills/system-spec-kit/mcp_server/handlers/session-learning.ts:676:  const safeLimit = Math.min(Math.max(1, limit), 100);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:585:function truncateTitle(title: string, maxLength: number = MAX_MEMORY_TITLE_LENGTH): string {
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:590:  const truncated = title.slice(0, maxLength).trim();
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:591:  const lastSpace = truncated.lastIndexOf(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:593:    return `${truncated.slice(0, lastSpace)}...`;
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:596:  return `${truncated}...`;
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:615:  return truncateTitle(cleaned);
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:991:  const tokenPattern = /<!--\s*(\/)?(?:ANCHOR|anchor):\s*([^>\s]+)\s*-->/gi;
.opencode/skills/system-spec-kit/mcp_server/lib/parsing/memory-parser.ts:995:  while ((match = tokenPattern.exec(content)) !== null) {
.opencode/skills/system-spec-kit/mcp_server/lib/MODULE_MAP.md:56:- Purpose: Owns the 7-layer MCP architecture metadata and token-budget guidance used to group tools into orchestration, core, discovery, mutation, lifecycle, analysis, and maintenance layers. It is the canonical place for layer definitions and layer-to-tool lookup behavior.
.opencode/skills/system-spec-kit/mcp_server/lib/MODULE_MAP.md:58:  - `layer-definitions.ts` — canonical L1-L7 definitions, token budgets, tool-to-layer map, and recommendation helpers.
.opencode/skills/system-spec-kit/mcp_server/lib/MODULE_MAP.md:274:  - `envelope.ts` — response-envelope construction and token-aware metadata helpers.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/affordance-normalizer.test.ts:85:        'token: abc123 should not survive',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:312:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:628:    limit: rawLimit = 10,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:706:  // Validate numeric limit parameter
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:707:  const limit = (typeof rawLimit === 'number' && Number.isFinite(rawLimit) && rawLimit > 0)
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:865:    limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:919:      limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:1268:      const tokensSaved = filteredCount * 200;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:1282:        tokensSaved: tokensSaved,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:1284:        tokenSavingsEstimate: tokensSaved > 0 ? `~${tokensSaved} tokens` : '0'
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-search.ts:1293:        resultsData.summary += ` (${filteredCount} duplicates filtered, ~${tokensSaved} tokens saved)`;
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/importance-tiers.ts:158:// Get maximum token budget for tier (null = unlimited)
.opencode/skills/system-spec-kit/mcp_server/tests/reconsolidation.vitest.ts:371:    it('FS3: Passes limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/reconsolidation.vitest.ts:374:        capturedLimit = (opts as { limit: number }).limit;
.opencode/skills/system-spec-kit/mcp_server/tests/reconsolidation.vitest.ts:381:    it('FS4: Default limit is SIMILAR_MEMORY_LIMIT', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/reconsolidation.vitest.ts:384:        capturedLimit = (opts as { limit: number }).limit;
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:55:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:56:  truncation_limit: number | null;
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:69:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:70:  truncationLimit: number | null;
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:224:    truncated: Boolean(root.truncated),
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:225:    truncation_limit: root.truncationLimit ?? null,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:248:      // T006 — Only flag max_depth_reached when a node exists at the depth limit.
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:292:    truncated: a.truncated || b.truncated,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:293:    truncation_limit: a.truncation_limit ?? b.truncation_limit ?? null,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:358:    truncated: chain.truncated,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:359:    truncation_limit: chain.truncation_limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:376:    truncated: false,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:377:    truncation_limit: null,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:392:    truncated: chain.truncated,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:393:    truncationLimit: chain.truncation_limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:588:    if (combinedChain.truncated) {
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:590:        `Traversal truncated after ${combinedChain.truncation_limit ?? causalEdges.MAX_EDGES_LIMIT} edges per node - results may be incomplete`
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:610:        truncated: combinedChain.truncated,
.opencode/skills/system-spec-kit/mcp_server/handlers/causal-graph.ts:611:        truncationLimit: combinedChain.truncation_limit,
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:24:  const tokens = new Set<string>();
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:27:    const tokenName = match[1];
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:28:    if (promptPackVariableNameSchema.safeParse(tokenName).success) {
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:29:      tokens.add(tokenName);
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:33:  return [...tokens];
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:40:  const rendered = template.replace(PROMPT_PACK_TOKEN_PATTERN, (_, tokenName: string) => {
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:41:    if (!(tokenName in variables)) {
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:42:      missingVariables.add(tokenName);
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:43:      return `{${tokenName}}`;
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:46:    return String(variables[tokenName]);
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:63:  const expectedTokenSet = new Set(expectedVariables.filter((token) => promptPackVariableNameSchema.safeParse(token).success));
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:66:    present: expectedVariables.filter((token) => expectedTokenSet.has(token) && templateTokenSet.has(token)),
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:67:    missing: expectedVariables.filter((token) => expectedTokenSet.has(token) && !templateTokenSet.has(token)),
.opencode/skills/system-spec-kit/mcp_server/lib/deep-loop/prompt-pack.ts:68:    extra: templateTokens.filter((token) => !expectedTokenSet.has(token)),
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/affordance-normalizer.ts:129://     - URL / email / token-shaped strings (privacy strip)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/affordance-normalizer.ts:151:const TOKEN_PATTERN = /\b(?:bearer|token|secret|apikey|api_key)\s*[:=]\s*\S+/gi;
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:31:const { tokenize, keywordOverlap, MAX_SURROGATE_QUESTIONS, MIN_SURROGATE_QUESTIONS, MAX_SUMMARY_LENGTH, MIN_MATCH_THRESHOLD } = __testables;
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:269:  it('falls back to truncation for long content without clear paragraphs', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:672:describe('tokenize', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:674:    const tokens = tokenize('Hello World Test');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:675:    expect(tokens).toEqual(['hello', 'world', 'test']);
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:679:    const tokens = tokenize('Hello, world! How are you?');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:680:    expect(tokens).toContain('hello');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:681:    expect(tokens).toContain('world');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:682:    expect(tokens).not.toContain(',');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:685:  it('filters short tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:686:    const tokens = tokenize('I am a big test');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:687:    expect(tokens).not.toContain('i');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:688:    expect(tokens).not.toContain('a');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:689:    expect(tokens).toContain('am');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:690:    expect(tokens).toContain('big');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:691:    expect(tokens).toContain('test');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:695:    expect(tokenize('')).toEqual([]);
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:701:    const queryTokens = tokenize('hello world');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:706:    const queryTokens = tokenize('hello world');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:711:    const queryTokens = tokenize('hello world');
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:715:  it('returns 0 for empty query tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-surrogates.vitest.ts:720:    const queryTokens = tokenize('hello world');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:911:  it('EXT-L4: List with limit/offset returns data', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:915:    const result = await handler.handleMemoryList({ limit: 10, offset: 0 });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:923:    const result = await handler.handleMemoryList({ limit: 500 });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:925:    expect(parsed?.data?.limit).toBeLessThanOrEqual(100);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:1344:    const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:1367:    const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:1388:    const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:1399:  it('EXT-H11: divergent_aliases mode respects limit', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-crud-extended.vitest.ts:1411:    const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:34:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:64:    const limit = Math.min(Math.max(args.limit ?? 50, 1), 200);
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:76:	          gaps: gaps.slice(0, limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:87:	          gaps: gaps.slice(0, limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:98:          claims: claims.slice(0, limit).map(c => ({
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:115:          contradictions: contradictions.slice(0, limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:131:          chain: chain.slice(0, limit),
.opencode/skills/system-spec-kit/mcp_server/handlers/coverage-graph/query.ts:138:        const hotNodes = rankHotNodes(ns, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/governance/scope-governance.ts:80:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/governance/scope-governance.ts:525: * @param filters - Optional audit filters and row limit.
.opencode/skills/system-spec-kit/mcp_server/lib/governance/scope-governance.ts:549:  const limit = Number.isInteger(filters.limit) && (filters.limit ?? 0) > 0
.opencode/skills/system-spec-kit/mcp_server/lib/governance/scope-governance.ts:550:    ? Math.trunc(filters.limit as number)
.opencode/skills/system-spec-kit/mcp_server/lib/governance/scope-governance.ts:571:  `).all(...params, limit) as Array<{
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor_runtime.py:118:    """Normalize free-form text into comparable lowercase term tokens."""
.opencode/skills/system-spec-kit/mcp_server/lib/cache/embedding-cache.ts:130:  // Auto-evict oldest entries when cache exceeds size limit
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-query-handler.vitest.ts:708:      limit: 10,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-query-handler.vitest.ts:794:      limit: 1,
.opencode/skills/system-spec-kit/mcp_server/lib/coverage-graph/coverage-graph-query.ts:404:export function rankHotNodes(ns: Namespace, limit: number = 10): HotNode[] {
.opencode/skills/system-spec-kit/mcp_server/lib/coverage-graph/coverage-graph-query.ts:435:    limit,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/routing-fixtures.affordance.test.ts:70:    const result = scoreAdvisorPrompt('run the primary explicit workflow and component token inspector', {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/routing-fixtures.affordance.test.ts:76:        triggers: ['component token inspector'],
.opencode/skills/system-spec-kit/mcp_server/tests/p0-b-reconsolidation-composite.vitest.ts:158:      limit: 1,
.opencode/skills/system-spec-kit/mcp_server/tests/p0-b-reconsolidation-composite.vitest.ts:175:        limit: 1,
.opencode/skills/system-spec-kit/mcp_server/tests/p0-b-reconsolidation-composite.vitest.ts:256:      limit: 2,
.opencode/skills/system-spec-kit/mcp_server/lib/cache/README.md:235:| [../architecture/](../architecture/) | Layer definitions and token budgets |
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-siblings-readiness.vitest.ts:189:        budgetUsed: 10,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-siblings-readiness.vitest.ts:190:        budgetLimit: 1200,
.opencode/skills/system-spec-kit/mcp_server/lib/errors/core.ts:276:    /rate limit/i,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:38:function tokenDensity(values: readonly string[]): number {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:39:  const tokens = values.flatMap((value) => value.toLowerCase().split(/[^a-z0-9]+/).filter((token) => token.length > 2));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:40:  if (tokens.length === 0) return 0;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:42:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:43:    counts.set(token, (counts.get(token) ?? 0) + 1);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:45:  return Math.max(...counts.values()) / tokens.length;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/anti-stuffing.ts:71:  const density = tokenDensity([...cleanTriggerPhrases, ...cleanKeywords]);
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:37:      tokenCap: 80,
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:184:      query: { directory: process.cwd(), limit: 20 },
.opencode/skills/system-spec-kit/mcp_server/lib/cache/tool-cache.ts:76: * Clears the entire map when the limit is exceeded.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/fixtures/skill_advisor_regression_cases.jsonl:17:{"id":"P1-SEARCH-002","priority":"P1","prompt":"semantic code search for rate limiting","confidence_only":false,"expect_result":true,"expected_top_any":["mcp-coco-index"],"expect_kind":"skill","allow_command_bridge":false}
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:80:        budgetUsed: 10,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:81:        budgetLimit: 1200,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:88:          truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:201:        budgetUsed: 10,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:202:        budgetLimit: 1200,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:209:          truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:255:      truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:284:        budgetUsed: 10,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:285:        budgetLimit: 1200,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:292:          truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:412:        truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/code_graph/tests/code-graph-context-handler.vitest.ts:555:        truncatedText: false,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:16:  tokenBudget: number;
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:35:   - Token efficiency: Higher layers = fewer tokens, more targeted
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:47:    tokenBudget: 3500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:56:    tokenBudget: 3500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:65:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:74:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:83:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:92:    tokenBudget: 1500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:114:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:177:   CHK-072: Token budgets assigned per layer.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:181: * Get the token budget for a tool.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:185:  if (!layerId) return 1000; // Default budget
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:187:  return LAYER_DEFINITIONS[layerId].tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:191: * Get the token budget for a tool.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:247:    lines.push(`**Token Budget:** ${layer.tokenBudget}`);
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:165:    lower.includes('rate limit') ||
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:190:    lower.includes('embedding_rate_limit') ||
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:191:    lower.includes('rate limit') ||
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:197:      errorType: explicitType ?? 'rate_limit',
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:441:function getRetryQueue(limit = 10): RetryMemoryRow[] {
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:459:  `).all(MAX_RETRIES, limit * 2) as RetryMemoryRow[];
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:465:      if (eligible.length >= limit) break;
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:776:async function processRetryQueue(limit = 3, contentLoader: ContentLoader | null = null): Promise<BatchResult> {
.opencode/skills/system-spec-kit/mcp_server/lib/providers/retry-manager.ts:777:  const queue = getRetryQueue(limit);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:28:  budget: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:77:  budget: 0.20,
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:81:/** Rough token-to-char ratio: 1 token ~ 4 chars (env-configurable via MCP_CHARS_PER_TOKEN) */
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:214: * Compute token budget quality sub-score.
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:216: * Approximates token count from character length using the constant ratio
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:217: * `CHARS_PER_TOKEN` (4 chars ≈ 1 token) and compares the result against
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:218: * `charBudget`. Memories that exceed the budget are penalised proportionally
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:222: *   - `content.length <= charBudget` → score 1.0 (within budget)
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:229: *   i.e. 2000 tokens × 4 = 8000 characters).
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:232: *   - `issues` — A single message describing the overage when the budget is
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:233: *     exceeded, including the approximate token count.
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:244:  const tokenBudget = Math.floor(charBudget / CHARS_PER_TOKEN);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:245:  issues.push(`Content exceeds token budget: ~${Math.ceil(charCount / CHARS_PER_TOKEN)} tokens (budget: ${tokenBudget})`);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:375: *   - budget    × 0.20
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:388: *     `budget`, `coherence`), each in [0, 1].
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:390: *     in order: triggers → anchors → budget → coherence.
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:398:  const budgetResult = scoreTokenBudget(content);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:404:    budgetResult.score * QUALITY_WEIGHTS.budget +
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:412:      budget: budgetResult.score,
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:418:      ...budgetResult.issues,
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:430: * - Trim content to token budget
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:460:  // Fix #3 : Trim content to budget
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:461:  const hasBudgetIssue = issues.some(i => /token budget/i.test(i));
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:464:      // Trim to budget, preserving the last newline boundary
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/extract.ts:127:  const tokens = normalizePhrase(text)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/extract.ts:129:    .filter((token) => token.length >= 3 && !STOP_WORDS.has(token));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/extract.ts:132:    for (let index = 0; index <= tokens.length - size; index += 1) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/lib/derived/extract.ts:133:      phrases.push(tokens.slice(index, index + size).join(' '));
.opencode/skills/system-spec-kit/mcp_server/lib/errors/README.md:93:| E050-E059 | API/Auth | Key invalid, rate limited |
.opencode/skills/system-spec-kit/mcp_server/lib/errors/README.md:97:| E090-E099 | Validation | Anchor format, token budget exceeded |
.opencode/skills/system-spec-kit/mcp_server/lib/errors/README.md:99:| E429, E503 | Rate Limiting | Rate limited, service unavailable |
.opencode/skills/system-spec-kit/mcp_server/lib/errors/README.md:115:| Transient (retry) | SQLITE_BUSY, ECONNRESET, ETIMEDOUT, rate limit |
.opencode/skills/system-spec-kit/mcp_server/tests/trigger-matcher.vitest.ts:90:function runFullScan(prompt: string, limit: number = CONFIG.DEFAULT_LIMIT) {
.opencode/skills/system-spec-kit/mcp_server/tests/trigger-matcher.vitest.ts:125:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:145:function parseDelimitedValues(raw: string | null | undefined): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:265:  const keyTopics = parseDelimitedValues(readLegacyValue(values, ['key topics'])).slice(0, GRAPH_METADATA_KEY_TOPIC_LIMIT);
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:266:  const triggerPhrasesFromLegacy = parseDelimitedValues(readLegacyValue(values, ['trigger phrases']));
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:272:  const sourceDocs = parseDelimitedValues(readLegacyValue(values, ['source docs']));
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:274:    return parseDelimitedValues(raw).map((packet) => ({
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:287:      children_ids: parseDelimitedValues(readLegacyValue(values, ['children', 'children ids'])),
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-metadata-parser.ts:298:        key_files: parseDelimitedValues(readLegacyValue(values, ['key files'])).slice(0, GRAPH_METADATA_KEY_FILE_LIMIT),
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:10://              Minimal response for fast decision-making. Best token savings.
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:23:import { estimateTokens } from '../../formatters/token-metrics.js';
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:78:  tokenReduction: {
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:101:/** Output of the `debug` profile formatter — passthrough + tokenStats. */
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:107:  tokenStats: {
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:301: * omitted count. Maximises token reduction.
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:313:      tokenReduction: {
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:335:    tokenReduction: {
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:382: * Passthrough — all data preserved. Adds token statistics.
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:386:  const tokenStats = computeTokenStats(JSON.stringify(input), results.length);
.opencode/skills/system-spec-kit/mcp_server/lib/response/profile-formatters.ts:396:    tokenStats,
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:64:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:71:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:150:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:156:      limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:169:  const ftsResults = ftsSearch(query, { limit });
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:177:  const bm25Results = bm25Search(query, { limit });
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:185:  const graphResults = graphSearchFn(query, { limit });
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:231:      limit: args.recallK,
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:271:        limit: recallK,
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:363:  const limit = typeof args.limit === 'number' && Number.isFinite(args.limit)
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:364:    ? Math.max(1, Math.floor(args.limit))
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:370:    queryLists.push(buildRawFusionLists(db, graphSearchFn, query, embedding, limit));
.opencode/skills/system-spec-kit/mcp_server/handlers/eval-reporting.ts:395:    limit: args.limit,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/hooks/settings-driven-invocation-parity.vitest.ts:52:// NON-GOALS (intentional brittleness budget)
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:3:description: "7-layer MCP architecture with token budgets and document-aware routing."
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:7:  - "token budgets"
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:12:> 7-layer MCP architecture with token budgets and document-aware routing.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:41:| **Token Efficiency** | Higher layers = fewer tokens, more targeted |
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:66:├── layer-definitions.ts  # 7-layer hierarchy with token budgets (~8KB)
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:74:| `layer-definitions.ts` | Layer constants, tool-to-layer mapping, token budget helpers, documentation generator |
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:89:- **tokenBudget**: Maximum tokens for responses
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:100:| `getTokenBudget` | `(toolName: string) => number` | Get token budget for a tool (default: 1000) |
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:134:const budget = getTokenBudget('memory_search');
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/README.md:135:// Returns: 1500 (L2: Core layer budget)
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:118:  // Rate limiting (HTTP-style codes)
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:175:    hint: 'No embedding provider available. Search limited to text matching.',
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:194:    toolTip: 'memory_list({ limit: 20 })'
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:215:    hint: 'File exceeds maximum size limit for indexing.',
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:316:      'Use memory_health() to see current system limits'
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:412:    hint: 'Rate limited by embedding provider. Retry after delay.',
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:416:      'Check provider rate limits documentation'
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:566:    hint: 'Memory file exceeds token budget limit.',
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:647:    hint: 'Operation rate limited. Please wait before retrying.',
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:696:      hint: 'Semantic search unavailable. Results limited to keyword matching.',
.opencode/skills/system-spec-kit/mcp_server/lib/providers/README.md:118:| `getRetryQueue` | `(limit?: number) => RetryMemoryRow[]` | Get items eligible for retry |
.opencode/skills/system-spec-kit/mcp_server/lib/providers/README.md:125:| `processRetryQueue` | `(limit?: number, contentLoader?) => Promise<BatchResult>` | Process batch of retries |
.opencode/skills/system-spec-kit/mcp_server/lib/providers/README.md:192:| Process retries | `processRetryQueue(limit)` | Manual retry trigger |
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-index.ts:208:      error: 'Rate limited',
.opencode/skills/system-spec-kit/mcp_server/lib/graph/graph-signals.ts:40: * Clears the entire cache when the limit is exceeded, since Map
.opencode/skills/system-spec-kit/mcp_server/tests/extraction-adapter.vitest.ts:68:  it('T033/T037: summarizers enforce expected truncation behavior', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/extraction-adapter.vitest.ts:102:    // The bash-git-commit rule matches this content, redaction fires on the token,
.opencode/skills/system-spec-kit/mcp_server/tests/extraction-adapter.vitest.ts:110:      { content: [{ type: 'text', text: 'git commit && token sk-abcdefghijklmnopqrstuvwxyz123456' }] }
.opencode/skills/system-spec-kit/mcp_server/lib/response/README.md:7:  - "token count sync"
.opencode/skills/system-spec-kit/mcp_server/lib/response/README.md:34:| `envelope.ts` | Envelope factories, MCP wrappers, default hints, and serialized token-count synchronization |
.opencode/skills/system-spec-kit/mcp_server/LICENSE:7:in the Software without restriction, including without limitation the rights
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-stats.ts:64:    limit: rawLimit = 10,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-stats.ts:117:      error: 'limit must be a finite number',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-crud-stats.ts:311:      limit: safeLimit,
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:4:import { estimateTokens } from '../../formatters/token-metrics.js';
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:18:  tokenCount: number;
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:19:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:96:  rate_limited: string[];
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:118:  const currentTokenCount = meta.tokenCount;
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:126:    meta.tokenCount = nextTokenCount;
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:133:  return typeof meta.tokenCount === 'number' ? meta.tokenCount : 0;
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:155:  rate_limited: [
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:185:    tokenCount: 0,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/__shared__/affordance-injection-fixtures.json:57:      "input": "token: abc123 should not survive",
.opencode/skills/system-spec-kit/mcp_server/lib/graph/README.md:94:- `key_files` are sanitized before dedupe and truncation so shell commands, version literals, title-shaped values, and other non-path noise do not occupy the 20-slot cap.
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:63:| **Batch Processing** | Utilities for batch operations, retry logic and rate limiting |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:68:| **Dynamic Token Budget** | Tier-aware budgets (1500/2500/4000) for result delivery |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:139:│   ├── hybrid-search.ts        # Combined semantic + keyword search + token budget
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:157:│   ├── confidence-truncation.ts # Confidence truncation (2x median gap, min 3 results)
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:158:│   ├── dynamic-token-budget.ts # Dynamic token budget (1500/2500/4000 by tier)
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:336:| `search/confidence-truncation.ts` | Low-confidence tail removal (2x median gap) |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:337:| `search/dynamic-token-budget.ts` | Per-tier token budgets (1500/2500/4000) |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:361:| **Options** | `limit`, `threshold`, `specFolder`, `anchors` |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:435:| **Capacity** | Configurable limit (default: 7 items, inspired by Miller's Law) |
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:533:  limit: 5,
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:579:  limit: 10
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:659:**Cause**: Missing API key or rate limit exceeded
.opencode/skills/system-spec-kit/mcp_server/lib/README.md:676:| API rate limits | Check `VOYAGE_API_KEY` environment variable |
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/working-memory.ts:325:function getSessionPromptContext(sessionId: string, floor: number = DECAY_FLOOR, limit: number = 5): SessionPromptContextEntry[] {
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/working-memory.ts:329:  const safeLimit = Math.max(1, Math.min(20, Math.floor(limit)));
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/working-memory.ts:514: * Enforce working memory capacity limit by LRU eviction.
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:122:    const result = await searchWithFallback('test query', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:131:    const result = await searchWithFallback('test query', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:167:    const results = structuralSearch({ limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:179:    const results = structuralSearch({ specFolder: 'specs/auth', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:186:    const results = structuralSearch({ specFolder: 'specs/nonexistent', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:191:    const results = structuralSearch({ limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:201:    const results = structuralSearch({ limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:207:    const results = structuralSearch({ limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:233:    const results = await searchWithFallback('obscure query no results', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:246:    const results = await searchWithFallback('xyzzy nonsense query', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:262:    const results = await searchWithFallback('test degradation metadata', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:280:    const results = structuralSearch({ limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:365:    const limited = __testables.applyResultLimit(rows, 3);
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:366:    expect(limited).toHaveLength(3);
.opencode/skills/system-spec-kit/mcp_server/tests/search-fallback-tiered.vitest.ts:367:    expect(limited.map(r => r.id)).toEqual([1, 2, 3]);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/labeled-prompts.jsonl:32:{"id":"rr-iter2-032","bucket":"mixed_ambiguous","source_type":"synthetic-edge","prompt":"Decompose the routing work into phases and update `tasks.md` with the result.","gate3_triggers":"yes","gate3_reason_category":"mixed_ambiguous","skill_top_1":"system-spec-kit","skill_correct":"yes","notes":"false-positive token plus concrete write target"}
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/labeled-prompts.jsonl:33:{"id":"rr-iter2-033","bucket":"mixed_ambiguous","source_type":"synthetic-edge","prompt":"Phase 2 should only review the reducer output and explain the drift.","gate3_triggers":"no","gate3_reason_category":"mixed_ambiguous","skill_top_1":"sk-code-review","skill_correct":"yes","notes":"contains phase token but no write intent"}
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/labeled-prompts.jsonl:40:{"id":"rr-iter2-040","bucket":"mixed_ambiguous","source_type":"synthetic-edge","prompt":"Decompose the research plan only; do not touch packet files.","gate3_triggers":"no","gate3_reason_category":"mixed_ambiguous","skill_top_1":"none","skill_correct":"no","notes":"decompose token without write intent"}
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/labeled-prompts.jsonl:91:{"id":"rr-iter3-091","bucket":"true_read_only","source_type":"synthetic-edge","prompt":"Analyze how often `create` appears in prompts that should stay below Gate 3.","gate3_triggers":"no","gate3_reason_category":"read_only","skill_top_1":"none","skill_correct":"no","notes":"token-frequency analysis"}
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:31:/** Parse integer limit from env var with validation */
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:341:  limit: number = 20
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:349:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:359: * T210: Per-tier limit map used by filterAndLimitByState.
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:361: * If a tier has fewer results than its limit, the surplus slots are
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:376: * Filter memories by state and apply limits.
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:380: * T210: When no targetState is specified, enforces per-tier quantity limits
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:382: * If a tier has fewer results than its limit, surplus slots are redistributed
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:388:  limit: number = 20
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:403:  // Apply per-tier limits with overflow redistribution
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:424:    // Apply limits, distributing surplus to over-filled tiers in priority order
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/tier-classifier.ts:444:  return classified.slice(0, limit).map((entry) => entry.memory);
.opencode/skills/system-spec-kit/mcp_server/core/config.ts:17:/** Input validation limits configuration */
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/scorer/native-scorer.vitest.ts:99:        description: 'semantic token overlap only',
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/scorer/native-scorer.vitest.ts:102:    const result = scoreAdvisorPrompt('semantic token overlap only', {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/score-routing-corpus.py:115:        has_historical_token = any(
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/score-routing-corpus.py:116:            re.search(rf"\b{re.escape(token)}\b", prompt_lower)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/score-routing-corpus.py:117:            for token in HISTORICAL_FALSE_POSITIVE_TOKENS
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/routing-accuracy/score-routing-corpus.py:119:        if has_historical_token and not expected and predicted:
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:23:// T006: Confidence truncation
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:25:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:30:} from '../lib/search/confidence-truncation';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:32:// T007: Dynamic token budget
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:37:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:79:    const query = 'how does the authentication system handle OAuth token refresh in production';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:216:  it('T006-01: scores [0.9, 0.85, 0.8, 0.3, 0.1] truncates after 0.8 (large gap)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:225:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:230:    // Gap at index 2 (between 0.8 and 0.3) = 0.50 > 0.25 → truncate after index 2
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:231:    expect(output.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:244:    const output = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:260:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:280:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:282:    expect(output.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:294:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:296:    expect(output.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:310:  it('T007-01: simple tier returns 1500 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:312:    expect(result.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:316:  it('T007-02: moderate tier returns 2500 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:318:    expect(result.budget).toBe(2500);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:322:  it('T007-03: complex tier returns 4000 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:324:    expect(result.budget).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:328:  it('T007-04: feature flag disabled returns default 4000 budget with applied=false', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:332:    expect(result.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/lib/routing/routing-prototypes.json:138:        "chunk": "Current blockers are limited to runtime restart verification, but there is still risk that removing sessionId from scope enforcement has an unintended side effect in consumers that expected session-scoped filtering. Estimated remaining effort is about thirty minutes for verification, documentation closure, memory save, and commit."
.opencode/skills/system-spec-kit/mcp_server/core/index.ts:22:  // Rate limiting
.opencode/skills/system-spec-kit/mcp_server/core/index.ts:53:  // Persistent rate limiting
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:6:  tokenCount?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:7:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:22:const INACTIVE_POLICY_WARNING = 'tokenUsage not provided and estimator unavailable; pressure policy inactive';
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:45:  const { tokenCount, tokenBudget } = runtimeContextStats;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:47:    typeof tokenCount !== 'number' ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:48:    !Number.isFinite(tokenCount) ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:49:    typeof tokenBudget !== 'number' ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:50:    !Number.isFinite(tokenBudget) ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:51:    tokenBudget <= 0
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:56:  return clampToRatio(tokenCount / tokenBudget);
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:61: * 1) caller-provided tokenUsage
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:66:  tokenUsage: number | undefined,
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:69:  if (typeof tokenUsage === 'number' && Number.isFinite(tokenUsage)) {
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:70:    const ratio = clampToRatio(tokenUsage);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:38:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:42:} from './confidence-truncation.js';
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:47:} from './dynamic-token-budget.js';
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:67:import type { TruncationResult } from './confidence-truncation.js';
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:77:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:89:   * truncation and token-budget truncation without changing live defaults.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:171:  /** Confidence truncation result (SPECKIT_CONFIDENCE_TRUNCATION). */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:172:  truncation?: {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:173:    truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:175:    truncatedCount: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:183:  /** Dynamic token budget result (SPECKIT_DYNAMIC_TOKEN_BUDGET). */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:184:  tokenBudget?: {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:186:    budget: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:233:/** Default result limit when none is specified by the caller. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:255:/** Reserved token overhead per contextual header, calibrated to max header length. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:324: * @param options - Optional limit and specFolder filter.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:329:  options: { limit?: number; specFolder?: string } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:336:  const { limit = DEFAULT_LIMIT, specFolder } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:340:    const results = index.search(query, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:448: * @param options - Optional limit, specFolder filter, and includeArchived flag.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:453:  options: { limit?: number; specFolder?: string; includeArchived?: boolean } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:460:  const { limit = DEFAULT_LIMIT, specFolder, includeArchived = false } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:467:    const bm25Results = fts5Bm25Search(db, query, { limit, specFolder, includeArchived });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:487: * @param options - Optional limit, specFolder filter, and includeArchived flag.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:492:  options: { limit?: number; specFolder?: string; includeArchived?: boolean } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:515:    .slice(0, options.limit || DEFAULT_LIMIT);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:614:  limit?: number
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:656:    limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:663:  limit?: number
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:678:    limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:740:  budgetResult: ReturnType<typeof getDynamicTokenBudget>;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:813:    ? applyResultLimit(primaryExecution.fusedResults, primaryOptions.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:835:      ? applyResultLimit(retryExecution.fusedResults, retryOptions.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:855:      ? applyResultLimit(retryExecution.fusedResults, retryOptions.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:886:    limit = DEFAULT_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:902:        limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:924:    const ftsResults = ftsSearch(query, { limit, specFolder, includeArchived });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:930:    const bm25Results = bm25Search(query, { limit, specFolder });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:937:      const graphResults = graphSearchFn(query, { limit, specFolder });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:996:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1012:      return applyResultLimit(execution.fusedResults, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1063:    // Compute tier-aware budget early so it's available for downstream truncation.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1064:    // When disabled, getDynamicTokenBudget returns the default 4000 budget with applied=false.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1065:    const budgetResult = getDynamicTokenBudget(routeResult.tier);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1066:    if (budgetResult.applied && !evaluationMode) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1067:      s3meta.tokenBudget = {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1068:        tier: budgetResult.tier,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1069:        budget: budgetResult.budget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1070:        applied: budgetResult.applied,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1075:        adjustedBudget: budgetResult.budget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1092:          limit: options.limit || DEFAULT_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1147:          limit: options.limit || DEFAULT_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1220:        budgetResult,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1225:          options.limit ?? DEFAULT_LIMIT
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1328:      budgetResult,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1351:    budgetResult,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1356:  const limit = options.limit || DEFAULT_LIMIT;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1419:      limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1444:  let reranked: HybridSearchResult[] = fusedHybridResults.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1449:    const localReranked = await rerankLocal(query, reranked, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1495:          const diversified = applyMMR(mmrCandidates, { lambda: mmrLambda, limit });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1592:      const truncationResult: TruncationResult = truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1596:      if (truncationResult.truncated) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1597:        reranked = truncationResult.results.map(r => r as HybridSearchResult);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1598:        s3meta.truncation = {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1599:          truncated: true,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1600:          originalCount: truncationResult.originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1601:          truncatedCount: truncationResult.truncatedCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1602:          medianGap: truncationResult.medianGap,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1603:          cutoffGap: truncationResult.cutoffGap,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1604:          cutoffIndex: truncationResult.cutoffIndex,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1611:      // Non-critical — truncation failure does not block pipeline
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1612:      console.warn('[hybrid-search] confidence truncation failed:', err instanceof Error ? err.message : String(err));
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1636:          // Wire confidence truncation metadata into per-result trace (036)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1637:          ...(s3meta.truncation ? {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1639:              truncated: s3meta.truncation.truncated,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1640:              originalCount: s3meta.truncation.originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1641:              truncatedCount: s3meta.truncation.truncatedCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1642:              medianGap: s3meta.truncation.medianGap,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1643:              cutoffGap: s3meta.truncation.cutoffGap,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1644:              cutoffIndex: s3meta.truncation.cutoffIndex,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1645:              thresholdMultiplier: s3meta.truncation.thresholdMultiplier,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1646:              minResultsGuaranteed: s3meta.truncation.minResultsGuaranteed,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1661:  let budgetTruncated = false;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1662:  let budgetLimit: number | undefined;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1664:    reranked = applyResultLimit(reranked, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1666:    // Apply token budget truncation after trace/header enrichment so token
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1671:    const adjustedBudget = Math.max(budgetResult.budget - headerOverhead, 200);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1673:    if (s3meta.tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1674:      s3meta.tokenBudget.headerOverhead = headerOverhead;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1675:      s3meta.tokenBudget.adjustedBudget = adjustedBudget;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1678:    const budgeted = truncateToBudget(reranked, adjustedBudget, {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1682:    reranked = budgeted.results;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1683:    budgetTruncated = budgeted.truncated;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1684:    budgetLimit = budgetResult.budget;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1698:          budgetTruncated,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1699:          ...(budgetLimit !== undefined ? { budgetLimit } : {}),
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1759:      ? mergeRawCandidateSets(primaryResults, retryResults, options.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1761:    if (mergedResults.length > 0) return applyResultLimit(mergedResults, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1764:    if (stagedResults.length > 0) return applyResultLimit(stagedResults, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1770:      options.limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1778:      options.limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1850: * @param options - Search options (specFolder for filtering, limit for cap).
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1854:  options: Pick<HybridSearchOptions, 'specFolder' | 'limit'> = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1861:  const limit = options.limit ?? DEFAULT_LIMIT;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1895:    params.push(limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1938:function truncateChars(input: string, maxChars: number): string {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2044:  const description = truncateChars(descriptionRaw, 60);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2047:  const header = truncateChars(withDesc, CONTEXT_HEADER_MAX_CHARS);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2055:/** Apply caller limit after merges that can expand result count. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2056:function applyResultLimit(results: HybridSearchResult[], limit?: number): HybridSearchResult[] {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2057:  if (typeof limit !== 'number' || !Number.isFinite(limit) || limit <= 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2060:  return results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2190:      : applyResultLimit(results, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2218:      : applyResultLimit(results, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2232:  const tier3Results = structuralSearch({ specFolder: options.specFolder, limit: options.limit });
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2244:    : applyResultLimit(results, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2257:/** Default token budget — configurable via SPECKIT_TOKEN_BUDGET env var. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2260:/** Maximum characters for a summary fallback when a single result overflows the budget. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2263:/** Overflow log entry recording budget truncation events for eval infrastructure. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2268:  budgetLimit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2269:  truncatedToCount: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2273:/** Result of budget-aware truncation. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2276:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2281: * Estimate token count for a text string using a chars/4 heuristic.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2282: * @param text - The text to estimate tokens for.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2283: * @returns Approximate token count (ceiling of length / 4).
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2318: * Estimate the token footprint of a single HybridSearchResult.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2320: * @returns Approximate token count based on serialized key-value lengths.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2359: * Read the configured token budget from SPECKIT_TOKEN_BUDGET env var,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2361: * @returns The effective token budget for result truncation.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2373: * Create a summary fallback for a single result whose content exceeds the token budget.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2375:function createSummaryFallback(result: HybridSearchResult, budget: number): HybridSearchResult {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2379:  const maxSummaryChars = Math.min(SUMMARY_MAX_CHARS, budget * 4);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2380:  const truncatedContent = content.length > maxSummaryChars
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2386:    content: `[Summary] ${title}: ${truncatedContent}`,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2392: * Truncate a result set to fit within a token budget using greedy highest-scoring-first strategy.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2393: * @param results - The full result set to truncate.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2394: * @param budget - Optional token budget override (defaults to SPECKIT_TOKEN_BUDGET env / 2000).
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2396: * @returns Object with truncated results, truncation flag, and optional overflow log entry.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2398:function truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2400:  budget?: number,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2403:  const effectiveBudget = (budget && budget > 0) ? budget : getTokenBudget();
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2408:    return { results: [], truncated: false };
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2412:  const tokenEstimateCache = new Map<string, number>();
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2415:    const cached = tokenEstimateCache.get(cacheKey);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2421:    tokenEstimateCache.set(cacheKey, estimate);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2428:    return { results: sorted, truncated: false };
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2441:      budgetLimit: effectiveBudget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2442:      truncatedToCount: 1,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2446:      `[hybrid-search] Token budget overflow (single-result fallback): ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2447:      `${totalTokens} tokens > ${effectiveBudget} budget`
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2449:    return { results: [outputResult], truncated: true, overflow };
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2452:  // Greedy accumulation: take highest-scoring results until budget exhausted
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2457:    const tokens = getTokenEstimate(result);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2458:    if (accumulated + tokens > effectiveBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2465:    accumulated += tokens;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2477:      budgetLimit: effectiveBudget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2478:      truncatedToCount: 1,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2483:      `[hybrid-search] Token budget overflow (top-result fallback): ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2484:      `${totalTokens} tokens > ${effectiveBudget} budget`
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2487:    return { results: [outputResult], truncated: true, overflow };
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2494:    budgetLimit: effectiveBudget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2495:    truncatedToCount: accepted.length,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2500:    `[hybrid-search] Token budget overflow: ${totalTokens} tokens > ${effectiveBudget} budget, ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2501:    `truncated ${results.length} → ${accepted.length} results`
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2504:  return { results: accepted, truncated: true, overflow };
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2511:  truncateChars,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2534:  // Token budget validation
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2537:  truncateToBudget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2555:  // Token budget types
.opencode/skills/system-spec-kit/mcp_server/lib/routing/content-router.ts:404:      /recovery scenarios|diagnostic commands|table of contents|placeholder|auto-truncated/.test(normalized),
.opencode/skills/system-spec-kit/mcp_server/lib/routing/content-router.ts:1239:  const tokens = text.toLowerCase().split(/[^a-z0-9_]+/).filter(Boolean);
.opencode/skills/system-spec-kit/mcp_server/lib/routing/content-router.ts:1241:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/routing/content-router.ts:1242:    const digest = createHash('sha256').update(token).digest();
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:923:    token_count = max(1, len(re.findall(r'\b\w+\b', signal_phrase)))
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:924:    return min(0.9 + 0.35 * (token_count - 1), 1.8)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1418:# Phrase-level intent boosters for high-signal multi-token requests
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1420:# NOTE: INTENT_BOOSTERS only matches single-word tokens after
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1421:# `all_tokens = re.findall(r'\b\w+\b', prompt_lower)` tokenizes the raw prompt.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1423:# before tokenization via `if phrase in prompt_lower`.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1424:# NEVER add keys containing spaces or hyphens to INTENT_BOOSTERS - the tokenizer
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1630:    # FOLLOW-UP: Hyphenated-token migrations from INTENT_BOOSTERS
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1631:    # (tokenizer splits on hyphen via \b\w+\b — same bug as whitespace keys)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1861:        "tokens": {"review", "audit", "regression", "findings", "readiness", "vulnerability"},
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1866:        "tokens": {"implement", "fix", "refactor", "build", "bug", "feature"},
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1871:        "tokens": {"documentation", "document", "readme", "markdown", "guide", "flowchart", "diagram"},
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1876:        "tokens": {"memory", "context", "checkpoint", "remember", "restore", "session", "preserve"},
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1881:        "tokens": {"mcp", "devtools", "chrome", "figma", "webflow", "clickup", "notion", "toolchain"},
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:1923:    """Return True when a keyword phrase appears on token boundaries."""
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2007:    limit: int = COCOINDEX_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2026:            [ccc_bin, "search", query, "--limit", str(limit * 2)],
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2035:        return _parse_ccc_output(result.stdout, limit)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2046:def _parse_ccc_output(stdout: str, limit: int = COCOINDEX_LIMIT) -> List[Dict[str, Any]]:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2088:        if len(hits) >= limit:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2091:    return hits[:limit]
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2136:def is_exact_match_prompt(prompt_lower: str, tokens: List[str]) -> bool:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2140:    exact_tokens = {"exact", "identifier", "identifiers", "literal", "regex", "regexp", "symbol", "symbols"}
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2141:    return bool(exact_tokens.intersection(tokens))
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2147:    tokens = re.findall(r'\b\w+\b', prompt_lower)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2151:    if is_exact_match_prompt(prompt_lower, tokens):
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2159:    token_set = set(tokens)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2160:    return bool(AUTO_SEMANTIC_TRIGGER_TOKENS.intersection(token_set)) and bool(
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2161:        AUTO_SEMANTIC_DISCOVERY_TOKENS.intersection(token_set)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2165:def expand_query(prompt_tokens: List[str]) -> List[str]:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2166:    """Expand user tokens with synonyms for better matching."""
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2167:    expanded = set(prompt_tokens)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2168:    for token in prompt_tokens:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2169:        if token in SYNONYM_MAP:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2170:            expanded.update(SYNONYM_MAP[token])
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2293:    tokens: List[str],
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2299:    token_set = set(tokens)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2302:        matched = any(phrase in prompt_lower for phrase in config["phrases"]) or bool(token_set.intersection(config["tokens"]))
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2550:# tokens must not steal a deep-research prompt back into the generic review
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2569:# covered by explicit multi-token PHRASE_INTENT_BOOSTERS entries that win
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2590:    T-SAP-02 (R45-002): audit/review-token overlap between deep-research prompts
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2702:    all_tokens = re.findall(r'\b\w+\b', prompt_lower)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2713:        tokens=all_tokens,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2726:    for token in all_tokens:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2727:        if token in INTENT_BOOSTERS:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2728:            skill, boost = INTENT_BOOSTERS[token]
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2732:            boost_reasons[skill].append(f"!{token}")
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2734:        if token in MULTI_SKILL_BOOSTERS:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2735:            for skill, boost in MULTI_SKILL_BOOSTERS[token]:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2739:                boost_reasons[skill].append(f"!{token}(multi)")
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2788:    tokens = [t for t in all_tokens if t not in STOP_WORDS and len(t) > 2]
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2790:    if not tokens and not skill_boosts:
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2793:    search_terms = expand_query(tokens) if tokens else []
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_advisor.py:2866:    # primary-slot selection is stable on audit/review-token prompts.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-save.ts:358:      const rejectScore = { total: 0, breakdown: { triggers: 0, anchors: 0, budget: 0, coherence: 0 }, issues: [`V-rule hard block: ${failedRuleIds.join(', ')}`] };
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-save.ts:1098:        max_tokens: contract.maxOutputTokens,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-save.ts:2194:              limit: gateOptions.limit,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-save.ts:2414:          limit: 1,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-save.ts:2883:        check_tokens: true,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:97:        '{"message":{"role":"assistant","usage":{"input_tokens":120,"output_tokens":60,"cache_creation_input_tokens":40,"cache_read_input_tokens":20},"model":"claude-sonnet-4-6","content":"Updated the producer-side continuity packet."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:98:        '{"message":{"role":"assistant","usage":{"input_tokens":80,"output_tokens":40},"content":"Next I will wire replay isolation and idempotency coverage."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:99:        '{"message":{"role":"assistant","usage":{"input_tokens":30,"output_tokens":10},"model":"claude-sonnet-4-6","content":"Appended replay-ready metrics."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:127:      prompt_tokens: 200,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:128:      completion_tokens: 100,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:129:      cache_creation_input_tokens: 40,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:130:      cache_read_input_tokens: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:131:      total_tokens: 300,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:155:      prompt_tokens: 120,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:156:      completion_tokens: 60,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:157:      cache_creation_input_tokens: 40,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:158:      cache_read_input_tokens: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:164:      prompt_tokens: 80,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:165:      completion_tokens: 40,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:178:        source_field: 'cache_read_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:179:        description: 'Normalized cache-read tier sourced from Claude transcript cache read tokens.',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:183:        source_field: 'cache_creation_input_tokens',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:184:        description: 'Normalized cache-write tier sourced from Claude transcript cache creation tokens.',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:196:    expect(secondReplay.session.prompt_tokens).toBe(firstReplay.session.prompt_tokens);
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:197:    expect(secondReplay.session.completion_tokens).toBe(firstReplay.session.completion_tokens);
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:205:        '{"message":{"role":"assistant","usage":{"input_tokens":120,"output_tokens":60,"cache_creation_input_tokens":40,"cache_read_input_tokens":20},"model":"claude-sonnet-4-6","content":"Updated the producer-side continuity packet."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:206:        '{"message":{"role":"assistant","usage":{"input_tokens":80,"output_tokens":40},"content":"Next I will wire replay isolation and idempotency coverage."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:207:        '{"message":{"role":"assistant","usage":{"input_tokens":30,"output_tokens":10},"model":"claude-sonnet-4-6","content":"Appended replay-ready metrics."}}',
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:217:    expect(thirdReplay.session.prompt_tokens).toBe(230);
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:218:    expect(thirdReplay.session.completion_tokens).toBe(110);
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:219:    expect(thirdReplay.session.total_tokens).toBe(340);
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:228:      prompt_tokens: 30,
.opencode/skills/system-spec-kit/mcp_server/tests/session-analytics-db.vitest.ts:229:      completion_tokens: 10,
.opencode/skills/system-spec-kit/mcp_server/lib/learning/corrections.ts:693:  options: { include_undone?: boolean; limit?: number } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/learning/corrections.ts:703:  const { include_undone = false, limit = MAX_CORRECTIONS_HISTORY } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/learning/corrections.ts:722:    return db.prepare(query).all(memory_id, memory_id, limit) as CorrectionWithTitles[];
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:859:function truncateInline(text: string, maxChars: number = SUMMARY_MAX_CHARS): string {
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:873:    return truncateInline(value, maxChars);
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:877:    return truncateInline(JSON.stringify(value), maxChars);
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:879:    return truncateInline(String(value), maxChars);
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:960:    ? truncateInline(input.summary)
.opencode/skills/system-spec-kit/mcp_server/lib/context/shared-payload.ts:961:    : truncateInline(
.opencode/skills/system-spec-kit/mcp_server/lib/search/auto-promotion.ts:229:    // BEGIN IMMEDIATE transaction so concurrent calls cannot exceed the rate limit.
.opencode/skills/system-spec-kit/mcp_server/lib/search/auto-promotion.ts:241:          reason: `promotion_window_rate_limited: ${recentPromotions}/${MAX_PROMOTIONS_PER_WINDOW} in ${PROMOTION_WINDOW_HOURS}h`,
.opencode/skills/system-spec-kit/mcp_server/core/README.md:29:- `config.ts` - runtime path resolution, input limits, batch settings, allowed-path policy, and lazy cognitive config access.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-schema.ts:392:    ? process.env.MEMORY_ALLOWED_PATHS.split(path.delimiter)
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:410:  options: { limit?: number; useCache?: boolean; applyLengthPenalty?: boolean } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:412:  const { limit = 10, useCache = true, applyLengthPenalty: shouldApplyLengthPenalty = true } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:419:    return documents.slice(0, limit).map((d, i) => ({
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:432:    return documents.slice(0, limit).map((d, i) => ({
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:450:        return cached.results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:494:    // Phase C: enforceCacheBound() ensures MAX_CACHE_ENTRIES limit.
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:502:    return results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/cross-encoder.ts:508:    return documents.slice(0, limit).map((d, i) => ({
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:69:    limit?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:80:    limit = 5,
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:107:    let fetchLimit = Math.max(limit * 3, limit);
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:109:    while (scopedMatches.length < limit) {
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:112:        limit: fetchLimit,
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:154:        if (scopedMatches.length >= limit) {
.opencode/skills/system-spec-kit/mcp_server/handlers/pe-gating.ts:168:    return scopedMatches.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:173:function tokenizeForJudge(text: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:177:    .map((token) => token.trim())
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:178:    .filter((token) => token.length >= JUDGE_MIN_TERM_LENGTH)
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:179:    .filter((token) => !JUDGE_STOP_WORDS.has(token));
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:265: * @param limit - Maximum number of results. Default 100.
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:270:  limit: number = 100,
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:277:    const params = queryId ? [queryId, limit] : [limit];
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:332: * Scoring bands (query token overlap):
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:348:      const queryTokens = [...new Set(tokenizeForJudge(queryText))];
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:349:      const memoryTokenSet = new Set(tokenizeForJudge(memoryContent));
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:357:          reasoning: 'Heuristic judge: insufficient lexical signal (empty query or content tokens)',
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ground-truth-feedback.ts:361:      const matchedTerms = queryTokens.filter((token) => memoryTokenSet.has(token));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/scripts/skill_graph_compiler.py:112:AFFORDANCE_TOKEN_PATTERN = re.compile(r"\b(?:bearer|token|secret|apikey|api_key)\s*[:=]\s*\S+", re.IGNORECASE)
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-subprocess.vitest.ts:150:  it('retries SQLITE_BUSY once when timeout budget remains', async () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-subprocess.vitest.ts:175:  it('reports SQLITE_BUSY retry exhaustion after the retry budget is spent', async () => {
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:153: * 3. Return top `limit` results sorted by similarity descending
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:158: * @param limit - Maximum number of results to return
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:164:  limit: number
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:168:    // Over-fetch by a factor so that after cosine ranking we can still return `limit` results.
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:169:    const fetchCap = Math.max(limit * 10, 1000);
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:190:    // Sort by similarity descending, take top `limit`
.opencode/skills/system-spec-kit/mcp_server/lib/search/memory-summaries.ts:192:    return results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/learned-feedback.ts:627: * @param limit - Maximum entries to return (default 50)
.opencode/skills/system-spec-kit/mcp_server/lib/search/learned-feedback.ts:633:  limit: number = 50
.opencode/skills/system-spec-kit/mcp_server/lib/search/learned-feedback.ts:643:      params = [memoryId, limit];
.opencode/skills/system-spec-kit/mcp_server/lib/search/learned-feedback.ts:646:      params = [limit];
.opencode/skills/system-spec-kit/mcp_server/tests/memory-tools.vitest.ts:47:      limit: 7,
.opencode/skills/system-spec-kit/mcp_server/tests/memory-tools.vitest.ts:55:      limit: 7,
.opencode/skills/system-spec-kit/mcp_server/lib/search/folder-discovery.ts:539: * - Return top `limit` folders with score > 0, sorted descending
.opencode/skills/system-spec-kit/mcp_server/lib/search/folder-discovery.ts:545: * @param limit  - Maximum number of results to return (default 3).
.opencode/skills/system-spec-kit/mcp_server/lib/search/folder-discovery.ts:551:  limit = 3,
.opencode/skills/system-spec-kit/mcp_server/lib/search/folder-discovery.ts:590:  return results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/folder-discovery.ts:1027: * across all base paths using recursive depth-limited scan.
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:96:| **Pressure-Aware Mode**      | `SPECKIT_PRESSURE_POLICY` enables token pressure monitoring for context window management | Prevents context overflow          |
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:362:// Filter with tier-specific limits (max 5 HOT + max 10 WARM)
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:532:  20           // limit (default: 20)
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:569:**Purpose**: Session-scoped attention tracking with capacity limits
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:938:5. Results sorted by activation score, limited to `maxSpreadResults` (20)
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/README.md:990:| `SPECKIT_PRESSURE_POLICY` | false   | Enable pressure-aware mode for token budget monitoring and context window management |
.opencode/skills/system-spec-kit/mcp_server/lib/search/causal-boost.ts:386: * Deduplicate and validate a list of numeric IDs, truncating to integers
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-prompt-policy.vitest.ts:37:  it('fires for work-intent verbs with at least three meaningful tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-prompt-policy.vitest.ts:40:      reason: 'work_intent_with_meaningful_tokens',
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-prompt-policy.vitest.ts:44:  it('fires for length plus meaningful-token thresholds', () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-prompt-policy.vitest.ts:45:    expect(shouldFireAdvisor('please examine routing behavior today').reason).toBe('length_and_token_threshold');
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:7:// - Quality score computation (trigger phrases, anchors, budget, coherence)
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:8:// - Auto-fix strategies (re-extract triggers, normalize anchors, trim budget)
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:93:/** Content that exceeds token budget */
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:184:  it('returns 1.0 for content under budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:190:  it('returns proportional score for content over budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:197:    expect(result.issues[0]).toMatch(/exceeds token budget/i);
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:200:  it('respects custom char budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:291:    // BAD_CONTENT = 'short': triggers=0, anchors=0.5 (neutral), budget=1.0, coherence=0.25
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:301:      QUALITY_WEIGHTS.budget + QUALITY_WEIGHTS.coherence;
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:308:        score.breakdown.budget === 1.0 && score.breakdown.coherence === 1.0) {
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:413:  it('trims content exceeding budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:416:    const result = attemptAutoFix(oversized, metadata, ['Content exceeds token budget']);
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:505:    // Has no anchors (0.5 neutral), no triggers (0), budget ok (1.0), coherence (1.0).
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:540:    // But coherence gives 0.25 for non-empty, budget gives 1.0, anchors 0.5 (neutral)
.opencode/skills/system-spec-kit/mcp_server/lib/search/community-search.ts:98: * @param limit - Maximum communities to return (default 5)
.opencode/skills/system-spec-kit/mcp_server/lib/search/community-search.ts:104:  limit: number = 5,
.opencode/skills/system-spec-kit/mcp_server/lib/search/community-search.ts:158:    const topResults = scored.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:182: * Dynamic token budget allocation by query complexity.
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:190: * Confidence-gap truncation for low-confidence tails.
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:540: * Replaces hard tail-truncation with summary layer + snippet + cursor pagination.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/INSTALL_GUIDE.md:165:| `degraded` | Runtime can only provide limited trust | Follow OP-001 in the manual playbook. |
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/attention-decay.ts:297:  limit: number = 20
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/attention-decay.ts:311:    `) as Database.Statement).all(limit) as Array<Record<string, unknown>>;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-privacy.vitest.ts:53:  for (const token of ['SECRET_ABC123', 'hunter2']) {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-privacy.vitest.ts:54:    expect(serialized, `${surfaceName} leaked ${token}`).not.toContain(token);
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:32:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:37:  tokenUsage?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:51:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:81:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:106:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:119:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:127:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:216:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:264:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/tools/types.ts:322:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-brief-producer.vitest.ts:144:    expect(result.metrics.tokenCap).toBe(120);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-brief-producer.vitest.ts:243:      throw new SyntaxError('Unexpected token <\nwhile probing freshness');
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-brief-producer.vitest.ts:252:    expect(result.diagnostics?.errorMessage).toBe('Unexpected token < while probing freshness');
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-brief-producer.vitest.ts:316:  it('AS10 enforces the hard 120 token cap regardless of advisor output', async () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-brief-producer.vitest.ts:338:    expect(result.metrics.tokenCap).toBe(120);
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:70:/** Minimum token overlap ratio to consider a surrogate matched. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:240:      const truncated = text.slice(0, MAX_SUMMARY_LENGTH);
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:241:      const lastSpace = truncated.lastIndexOf(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:243:        ? truncated.slice(0, lastSpace).trim()
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:244:        : truncated.trim();
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:253:  const truncated = rawText.slice(0, MAX_SUMMARY_LENGTH);
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:254:  const lastSpace = truncated.lastIndexOf(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:256:    ? truncated.slice(0, lastSpace).trim()
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:257:    : truncated.trim();
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:395: * Strips punctuation and filters tokens shorter than 2 characters.
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:397:function tokenize(text: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:417:  const targetTokens = new Set(tokenize(target));
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:434: *   - Alias match (exact token overlap): weight 0.3
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:447:  const queryTokens = tokenize(query);
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-surrogates.ts:536:  tokenize,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:45: *   Max 200 tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:53:  /** Maximum token count for the pseudo-document. Default: MAX_HYDE_TOKENS. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:78: * Maximum token count hint for pseudo-document generation.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:79: * Roughly 200 tokens ≈ 150 words at English density.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:177: * @param maxTokens - Maximum token count.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:197:    `Keep the response under ${maxTokens} tokens.`,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:218: * @param maxTokens - Token budget passed to the LLM.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:236:    max_tokens: maxTokens,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:297: * @param options - Optional token limit override.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:362: * @param limit     - Maximum number of results.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:368:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:372:    limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:390: * @param limit    - Result limit.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:397:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:412:    const candidates = vectorOnly(hydeResult.embedding, limit, specFolder);
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:115:function truncateContent(content: string | null | undefined, maxLength: number = 200): string {
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:221:        truncateContent(newContent), '',
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:244:        truncateContent(newContent), '',
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:299:      truncateContent(newContent),
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:300:      truncateContent(existingContent),
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:434:function getRecentConflicts(limit: number = 10): Array<Record<string, unknown>> {
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:442:    `) as Database.Statement).all(limit) as Array<Record<string, unknown>>;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/prediction-error-gate.ts:551:  truncateContent,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-renderer.vitest.ts:45:  it('renders top-two ambiguity when the producer result carries the 120-token mode', () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-renderer.vitest.ts:51:        tokenCap: 80,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:4:// Feature catalog: Confidence-based result truncation
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:9:/** Generic scored result for truncation — supports both numeric and string IDs. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:16:/** Result of a truncation operation with full audit metadata. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:19:  truncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:21:  truncatedCount: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:28:/** Options for truncation behaviour. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:37:/** Gap multiplier: gap must exceed this multiple of the median gap to trigger truncation.
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:99: * @param options - Optional truncation options (minResults).
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:102:function truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:120:      truncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:122:      truncatedCount: originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:129:  // Not enough results to truncate
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:133:      truncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:135:      truncatedCount: originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:151:      truncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:153:      truncatedCount: originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:178:      truncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:180:      truncatedCount: originalCount,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:188:  const truncatedResults = validResults.slice(0, cutoffIndex + 1);
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:191:    results: truncatedResults,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:192:    truncated: true,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:194:    truncatedCount: truncatedResults.length,
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:214:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:23:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:155: * @param options - Search options (limit, specFolder, includeArchived)
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:159: * const rows = fts5Bm25Search(db, 'memory search', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:167:  const { limit = 20, specFolder, includeArchived = false } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:170:  // Sanitize via shared tokenizer, then wrap each token in quotes and join with OR for recall
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:171:  const tokens = normalizeLexicalQueryTokens(query).fts;
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:172:  const sanitized = tokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:188:    ? [sanitized, specFolder, specFolder, limit]
.opencode/skills/system-spec-kit/mcp_server/lib/search/sqlite-fts.ts:189:    : [sanitized, limit];
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-decomposer.ts:26: * We look for these as standalone tokens (word-boundary matched).
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-decomposer.ts:55: * Minimum token count to consider a split fragment valid.
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-decomposer.ts:89: *      each with at least MIN_FRAGMENT_TOKEN_COUNT tokens
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:86: * Clears the entire cache when the limit is exceeded, since Map iteration order
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:191:  limit: number = CO_ACTIVATION_CONFIG.maxRelated
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:198:  const cacheKey = `${memoryId}:${limit}`;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:215:    const related = parseRelatedMemoryReferences(memory.related_memories).slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:239:  limit: number = CO_ACTIVATION_CONFIG.maxRelated,
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:262:    parseRelatedMemoryReferences(row.related_memories).slice(0, limit).length,
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:296:      limit: 2 * CO_ACTIVATION_CONFIG.maxRelated,
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:326:  limit: number = CO_ACTIVATION_CONFIG.maxRelated
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:355:    `) as Database.Statement).all(memIdStr, memIdStr, memIdStr, limit, memoryId) as RelatedMemory[];
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:372:  limit: number = CO_ACTIVATION_CONFIG.maxSpreadResults
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/co-activation.ts:393:  while (queue.length > 0 && results.length < limit) {
.opencode/skills/system-spec-kit/mcp_server/tools/memory-tools.ts:84:        limit: typeof validated.limit === 'number' ? validated.limit : 10,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/livePassingSkill.json:21:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-prompt-cache.vitest.ts:55:    const rawPrompt = ['secret', 'customer', 'token', 'prompt'].join(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:85:      "query": "memory_context returns wrong results when token pressure is high",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:100:      "expectedResultDescription": "Should surface system-spec-kit spec documents and memories about the L1/L2/L3/L4/L5/L6/L7 layer design, token budgets per layer, and original design rationale.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:195:      "query": "OAuth 2.0 token refresh endpoint implementation",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:200:      "expectedResultDescription": "Should return NO relevant results. There is no OAuth, no HTTP server endpoints, no token auth in this system. API key validation is the only auth mechanism.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:265:      "query": "what rationale drove the token budget assignments per MCP layer",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:270:      "expectedResultDescription": "Should surface system-spec-kit SKILL.md section on L1-L7 token budgets (2000, 1500, 800, 500, 600, 1200, 1000) and any decision record explaining their sizing.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:655:      "query": "BM25 tokenization stemming",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:660:      "expectedResultDescription": "Should surface bm25-index.ts tokenize() and simpleStem() functions and any spec documentation about the text normalization approach.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:695:      "query": "SPECKIT_PRESSURE_POLICY token budget downgrade",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:890:      "expectedResultDescription": "Should surface the memory_list handler code (offset/limit parameters that already exist) and the tool schema definition.",
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:97:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:105:      graphResults.push(...queryCausalEdgesFTS5(database, query, limit));
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:108:      graphResults.push(...queryCausalEdgesLikeFallback(database, query, limit));
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:113:      const hierarchyRows = queryHierarchyMemories(database, specFolder, Math.max(5, Math.ceil(limit / 2)));
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:141:      .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:157:  limit: number
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:161:  const oversampleLimit = limit * 3;
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:252:  return candidates.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:261:  limit: number
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:265:  const oversampleLimit = limit * 3;
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:668:    const limit = typeof options['limit'] === 'number' ? options['limit'] : 20;
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-search-fn.ts:672:    return queryCausalEdges(database, query, limit, specFolder)
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-types.ts:134:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/temporal-contiguity.ts:198:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/temporal-contiguity.ts:212:      `) as Database.Statement).all(specFolder, limit) as Array<{ created_at: string; [key: string]: unknown }>;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/temporal-contiguity.ts:219:    `) as Database.Statement).all(limit) as Array<{ created_at: string; [key: string]: unknown }>;
.opencode/skills/system-spec-kit/mcp_server/lib/search/spec-folder-hierarchy.ts:264:  limit: number = 50,
.opencode/skills/system-spec-kit/mcp_server/lib/search/spec-folder-hierarchy.ts:289:  `) as Database.Statement).all(...relatedFolders, limit) as Array<{
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:6:// PURPOSE: Replace hard tail-truncation with a multi-layer response:
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:9:// 3. Continuation cursors — opaque tokens for paginated retrieval
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:23:/** Maximum snippet length in characters before truncation. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:117: * @returns Base64-encoded cursor token.
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:120: * const token = encodeCursor({ offset: 5, queryHash: 'abc', timestamp: Date.now() });
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:132: * @param cursor - Opaque base64 cursor token.
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:133: * @returns Decoded cursor payload, or `null` when the token is invalid.
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:276:    const truncated = content.length > SNIPPET_MAX_LENGTH
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:281:      snippet: truncated,
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:295: * @returns CursorInfo with opaque cursor token and remaining count, or null if no more results.
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:348: * @param cursor - Opaque cursor token from createCursor.
.opencode/skills/system-spec-kit/mcp_server/lib/search/progressive-disclosure.ts:419: * Replaces hard tail-truncation with summary layer + snippets + cursor.
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-classifier.ts:55: * @param query - Raw query string to tokenize.
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-classifier.ts:56: * @returns Array of non-empty whitespace-delimited terms.
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:16:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:106:    expect(result.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:107:    expect(result.budget).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:113:    expect(result.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:119:    expect(result.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:137:  it('T10: simple tier returns 1500 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:140:    expect(result.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:144:  it('T11: moderate tier returns 2500 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:147:    expect(result.budget).toBe(2500);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:151:  it('T12: complex tier returns 4000 tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:154:    expect(result.budget).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:158:  it('T13: budgets increase with tier complexity', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:159:    const simple = getDynamicTokenBudget('simple').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:160:    const moderate = getDynamicTokenBudget('moderate').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:161:    const complex = getDynamicTokenBudget('complex').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:180:  it('T15: custom config overrides default budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:187:    expect(getDynamicTokenBudget('simple', customConfig).budget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:188:    expect(getDynamicTokenBudget('moderate', customConfig).budget).toBe(1600);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:189:    expect(getDynamicTokenBudget('complex', customConfig).budget).toBe(3200);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-store.ts:295:  ...(process.env.MEMORY_ALLOWED_PATHS ? process.env.MEMORY_ALLOWED_PATHS.split(path.delimiter) : [])
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-store.ts:933:      limit: topK,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/001-derived-extraction.md:71:- Extracted tokens are scoped to the configured inputs: frontmatter, body, examples, `references/**`, `assets/**`, `intent_signals`, `source_docs`, and `derived.key_files`.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/promptPoisoningAdversarial.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:159: * caller-supplied tokens and avoid inventing packet IDs or paths.
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:178:  const tokens = rawTokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:179:    .map((token) => token.replace(/^[^\w-]+|[^\w-]+$/g, '').toLowerCase())
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:180:    .filter((token) => token.length > 0 && !stopWords.has(token));
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:182:  if (tokens.length === 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:185:  if (tokens.length === 1) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:186:    return [`${tokens[0]} context`, `${tokens[0]} implementation`];
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:189:  const firstPair = tokens.slice(0, 2).join(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:190:  const firstTriple = tokens.slice(0, 3).join(' ');
.opencode/skills/system-spec-kit/mcp_server/lib/search/recovery-payload.ts:194:    tokens.join(' '),
.opencode/skills/system-spec-kit/mcp_server/lib/eval/bm25-baseline.ts:117: * The function receives the query text and a limit and must return results
.opencode/skills/system-spec-kit/mcp_server/lib/eval/bm25-baseline.ts:124:  limit: number,
.opencode/skills/system-spec-kit/mcp_server/lib/eval/bm25-baseline.ts:505:  // Retrieval limit: fetch enough results for all metric cutoffs
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:94: * @param query - Raw query string to tokenize and match against graph nodes.
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:103:  const tokens = query
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:109:  if (tokens.length === 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:113:  // Find graph nodes whose id or labels match any query token.
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:117:    const labelMatch = node.labels.some(l => tokens.some(t => l.toLowerCase().includes(t)));
.opencode/skills/system-spec-kit/mcp_server/lib/search/evidence-gap-detector.ts:118:    const idMatch = tokens.some(t => idLower.includes(t));
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:48: * each field's token scores by the appropriate weight before
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:99: * Apply lightweight stemming to a token for BM25 indexing and matching.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:102: * @returns A lowercased token with simple suffix normalization applied.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:148: * @param text - Input text to tokenize.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:152: * tokenize('The memory indexing pipeline');
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:156:function tokenize(text: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:163: * Count token frequency occurrences for BM25 scoring.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:165: * @param tokens - Normalized tokens produced by {@link tokenize}.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:166: * @returns A frequency map keyed by token text.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:173:function getTermFrequencies(tokens: string[]): Map<string, number> {
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:175:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:176:    freq.set(token, (freq.get(token) || 0) + 1);
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:241:  private documents: Map<string, { tokens: string[]; termFreq: Map<string, number> }>;
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:258:    const tokens = tokenize(text);
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:259:    const termFreq = getTermFrequencies(tokens);
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:266:    this.documents.set(id, { tokens, termFreq });
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:267:    this.totalDocLength += tokens.length;
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:279:    this.totalDocLength -= doc.tokens.length;
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:306:    const dl = doc.tokens.length;
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:322:  search(query: string, limit: number = 10): BM25SearchResult[] {
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:337:      .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:520: * the individual tokens as an array. This is the shared tokenization
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:522: * use this array to ensure consistent tokenization.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:525: * the remaining non-empty tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:528: * @returns Sanitized query tokens safe to reuse for lexical search paths.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:536:  // Input length guard: truncate overly long queries to prevent DoS
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:565:    .flatMap((token) => splitLexicalFragments(token));
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:573:      .filter((token) => token.length >= 2 && !STOP_WORDS.has(token))
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:580: * Delegates to `sanitizeQueryTokens` for tokenization, then wraps
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:581: * each token in quotes for FTS5 safety.
.opencode/skills/system-spec-kit/mcp_server/lib/search/bm25-index.ts:605:  tokenize,
.opencode/skills/system-spec-kit/mcp_server/lib/search/query-expander.ts:28:  token: ['jwt', 'session-key'],
.opencode/skills/system-spec-kit/mcp_server/lib/continuity/README.md:15:- `thin-continuity-record.ts` validates bounded continuity fields, enforces byte limits, and reads or writes the compact continuity record used by packet-local recovery.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/005-anti-stuffing.md:3:description: "Manual validation that derived lane anti-stuffing enforces cardinality caps, demotes repetition-dense tokens, and rejects adversarial fixtures."
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/005-anti-stuffing.md:26:Validate that `lib/derived/anti-stuffing.ts` enforces cardinality caps on derived entries, demotes tokens with suspicious repetition density, and rejects adversarial fixtures designed to stuff the routing surface.
.opencode/skills/system-spec-kit/mcp_server/lib/search/retrieval-directives.ts:104: * Truncate text to at most `max` characters, appending "…" if truncated.
.opencode/skills/system-spec-kit/mcp_server/lib/search/retrieval-directives.ts:288: * Output format (pipe-delimited for easy parsing):
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:50:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:92: * latency minimal and the ≤2 LLM calls per deep query budget intact.
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:93: * Returns up to `limit` (default 3) results.
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:99: * @param options - Optional limit override.
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:106:  const limit = options?.limit ?? SEED_LIMIT;
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:110:    const rawResults = fts5Bm25Search(db, query, { limit });
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:112:    return rawResults.slice(0, limit).map((row): SeedResult => ({
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:141: *   - Seeds bounded to avoid token bloat (first 200 chars each)
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:194: *   - max_tokens capped at 256 (no streaming)
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:215:    max_tokens: 256,
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:332:   * LLM call budget: exactly 1 call per cache miss (0 on hit).
.opencode/skills/system-spec-kit/mcp_server/lib/search/llm-reformulation.ts:333:   * Combined with HyDE this stays within the ≤2 calls per deep query budget.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/ambiguousTopTwo.json:26:    "tokenCap": 120
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:45:// --- T007: Token budget ---
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:50:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:292:  it('T002.2 — degree channel weight matches the capped contribution budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:585:describe('T007: Token budget estimation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:604:    expect(simple.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:605:    expect(moderate.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:606:    expect(complex.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:610:  it('T007.2 — when enabled, tiers map to correct budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:617:    expect(simple.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:618:    expect(moderate.budget).toBe(2500);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:619:    expect(complex.budget).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:623:  it('T007.3 — budget boundaries are respected: simple < moderate < complex', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:630:    expect(s.budget).toBeLessThan(m.budget);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:631:    expect(m.budget).toBeLessThan(c.budget);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:634:  it('T007.4 — custom config overrides default budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:640:    expect(result.budget).toBe(500);
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:24:// Configurable limit prevents silent data loss at scale (was hardcoded 1000)
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:40:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:103:  /** Total eval runs included in this report after filters/limit. */
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:105:  /** Total metric snapshots included in this report after filters/limit. */
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:573: * @param config - Optional filters and limits.
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:600:  const limitedSprintEntries = (config.limit && config.limit > 0
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:601:    ? rankedSprintEntries.slice(0, config.limit)
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:611:    limitedSprintEntries.flatMap(({ groupSnapshots }) => groupSnapshots.map((snapshot) => snapshot.eval_run_id))
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:614:  const totalSnapshots = limitedSprintEntries.reduce(
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:619:  // Query channel results only for included runs so row limits cannot starve kept groups.
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:622:  const limitedSprints = limitedSprintEntries.map(({ label, groupSnapshots }) =>
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:627:  const trends = computeTrends(limitedSprints);
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:630:  const summary = buildSummary(limitedSprints, trends, totalEvalRuns);
.opencode/skills/system-spec-kit/mcp_server/lib/eval/reporting-dashboard.ts:636:    sprints: limitedSprints,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:220:    // Fall back to comma-delimited parsing for legacy callers/tests.
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:552:    limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:568:    limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:671:      limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:791:          // F1: Wrap parallel variant searches with latency budget.
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:878:            limit: DEFAULT_EXPANSION_CANDIDATE_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:965:            limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:1005:      limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:1101:            limit: CONSTITUTIONAL_INJECT_LIMIT,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:1153:      const seeds = cheapSeedRetrieve(query, { limit: 3 });
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:1241:      const rawHydeCandidates = await runHyDE(query, candidates, limit, specFolder);
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage1-candidate-gen.ts:1290:          const summaryResults = querySummaryEmbeddings(db, summaryEmbedding, limit);
.opencode/skills/system-spec-kit/mcp_server/database/README.md:58:- Rate-limit timestamp is persisted in DB `config` table (`last_index_scan`).
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:52:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:71:/** Minimum token length — short tokens (≤2 chars) add noise, not signal. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:114: *   3. Remove stop-words and tokens shorter than MIN_TERM_LENGTH.
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:115: *   4. Remove tokens that already appear in the original query (case-insensitive).
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:120: * @param queryTokens - Set of lowercased tokens from the original query.
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:133:    const tokens = text.toLowerCase().match(/\b[a-z][a-z0-9_-]*\b/g) ?? [];
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:134:    for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:135:      if (token.length < MIN_TERM_LENGTH) continue;
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:136:      if (EXPANSION_STOP_WORDS.has(token)) continue;
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:137:      if (queryTokens.has(token)) continue;
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:138:      freq.set(token, (freq.get(token) ?? 0) + 1);
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:176: * @param options   - Optional tuning parameters (limit, maxTerms).
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:207:  const limit = options?.limit ?? DEFAULT_CANDIDATE_LIMIT;
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:216:      limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:250:    // Build the set of tokens already present in the original query so we
.opencode/skills/system-spec-kit/mcp_server/lib/search/embedding-expansion.ts:267:    // FTS and embedding re-encoding without requiring a separator token.
.opencode/skills/system-spec-kit/mcp_server/lib/continuity/thin-continuity-record.ts:152:function tokenize(value: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/continuity/thin-continuity-record.ts:503:  if (candidate.length > 96 || tokenize(candidate).length > 16 || looksCompactNarrativeViolation(candidate)) {
.opencode/skills/system-spec-kit/mcp_server/lib/continuity/thin-continuity-record.ts:509:    const firstToken = tokenize(candidate)[0]?.toLowerCase() ?? '';
.opencode/skills/system-spec-kit/mcp_server/lib/continuity/thin-continuity-record.ts:553:        tokenize(compact).length > 10 ||
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:121:**Score immutability invariant**: Stage 4 MUST NOT modify scores. Enforced via compile-time `Stage4ReadonlyRow` readonly fields and runtime `captureScoreSnapshot` / `verifyScoreInvariant` defence-in-depth. Applies memory-state filtering, per-tier limits, evidence gap detection (Z-score confidence check), quality floor (`QUALITY_FLOOR=0.005`), and token budget truncation. Lowest-priority retained-history rows remain fallback evidence only when filters allow them.
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:252:| **TypeScript**       | `channel-representation.ts`, `channel-enforcement.ts`, `confidence-truncation.ts` (quality)   |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:253:| **TypeScript**       | `dynamic-token-budget.ts`, `folder-discovery.ts`, `folder-relevance.ts` (budget & discovery)  |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:297:| `reranker.ts`              | -      | TypeScript | Score-based reranking utility (sort + truncate)     |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:302:| `query-classifier.ts`      | -      | TypeScript | Routes queries by complexity tier (simple <=3 tokens, moderate, complex >8) (Sprint 3) |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:307:| `confidence-truncation.ts` | -      | TypeScript | Removes low-confidence tail using 2x median gap heuristic (min 3 results) (Sprint 3) |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:308:| `dynamic-token-budget.ts`  | -      | TypeScript | Per-tier token budgets: simple=3500, moderate=3500, complex=4000 (Sprint 3) |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:582:| **Algorithm** | TF-IDF sentence scoring with markdown stripping and tokenization |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:609:| `querySummaryEmbeddings` | `(db, queryEmbedding, limit?) => SummarySearchResult[]` | Search summaries by embedding similarity |
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:715:NER + key-phrase rules extract entities at save time and populate the `memory_entities` table. Density guard limits extraction volume. Gated via `SPECKIT_AUTO_ENTITIES`. Upstream dependency for S5 entity linking.
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:718:Pre-save check validates content fits within tier-specific token budgets. Greedy truncation strategy applied when content overflows.
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:792:  limit: 10,
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:818:  limit: 10,
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:828:const initial = await unifiedSearch('user authentication', { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:851:    limit: 10,
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:888:- FTS5 double-tokenization fix in learned feedback isolation (D2)
.opencode/skills/system-spec-kit/mcp_server/lib/search/README.md:975:- Query pipeline additions: query complexity routing, channel representation, confidence truncation, dynamic token budgets, folder discovery
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:189: * @param limit - The requested result limit.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:193:export function get_cache_key(query: string, limit: number, options: Record<string, unknown>): string {
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:195:  hash.update(JSON.stringify({ query, limit, options }));
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:203: * @param limit - The maximum number of results to return.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:207:export async function cached_search(query: string, limit = 20, options: Record<string, unknown> = {}): Promise<EnrichedSearchResult[]> {
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:209:  const key = get_cache_key(query, limit, options);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:219:  const results = await vector_search_enriched(query, limit, options);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:347:      limit: 6,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:401: * @param limit - The maximum number of results to return.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:407:  limit = 20,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:413:  const fetch_limit = Math.min(limit * 2, 100);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:415:  const results = await vector_search_enriched(query, fetch_limit, {
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-aliases.ts:425:  const final_results = diverse.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-index-cooldown.vitest.ts:175:  it('does not set cooldown timestamp when request is rate-limited', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-index-cooldown.vitest.ts:194:    expect(envelope.error).toBe('Rate limited');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-index-cooldown.vitest.ts:349:        errorDetail: '429 rate limit',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-index-cooldown.vitest.ts:368:          errorDetail: '429 rate limit',
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage3-rerank.ts:149:    limit: config.limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage3-rerank.ts:211:          const diversified = applyMMR(mmrCandidates, { lambda: mmrLambda, limit: config.limit });
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage3-rerank.ts:312:    limit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage3-rerank.ts:336:      const localReranked = await rerankLocal(query, results, options.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage3-rerank.ts:387:        limit: options.limit,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints.vitest.ts:252:        await handler.handleCheckpointList({ limit: 0 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints.vitest.ts:253:        await handler.handleCheckpointList({ limit: -1 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints.vitest.ts:254:        await handler.handleCheckpointList({ limit: 999 });
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:6:// Descending and optionally truncates to a limit.
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:21:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:33: * @param options - Optional config (limit: max results to return)
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:34: * @returns Sorted (and optionally truncated) results
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:47:  // Apply limit if provided
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:48:  if (options?.limit !== undefined && options.limit >= 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts:49:    return sorted.slice(0, options.limit);
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/003-provenance-and-trust-lanes.md:56:- Lane assignment matches the source of the extracted token (frontmatter terms → `frontmatter`, fenced code → `examples`, references/assets docs → `local_docs`, n-grams from SKILL.md body → `body` or `derived_local`).
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/003-provenance-and-trust-lanes.md:58:- Author-tier tokens (intent_signals in frontmatter) resolve to the `author` lane.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/06--auto-indexing/003-provenance-and-trust-lanes.md:67:| Wrong lane tag | Body token shows `author` or vice versa | Audit `trust-lanes.ts` classification rules. |
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage2-fusion.ts:32:// 7.  Artifact limiting       — result count cap from routing strategy
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage2-fusion.ts:944: *   7.  Artifact limiting  (trim to strategy.maxResults if routing active)
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage2-fusion.ts:1310:  // -- 7. Artifact-based result limiting --
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage2-fusion.ts:1312:  // Overall pipeline limit. Apply it here so Stage 3 reranks a pre-trimmed set.
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/unicodeInstructionalSkillLabel.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-utils.ts:36:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-utils.ts:149:  limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-utils.ts:191:    limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:5:// ADVISORY-ONLY: This module computes a token budget for a query
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:6:// Based on its complexity tier, but does NOT enforce that budget
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:9:// Result sets or truncating content before sending to the LLM).
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:13:// Feature catalog: Dynamic token budget allocation
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:18:/** Budget (in tokens) allocated per complexity tier. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:20:  /** Simple query budget: 1500 tokens. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:22:  /** Moderate query budget: 2500 tokens. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:24:  /** Complex query budget: 4000 tokens. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:28:/** Result of a token budget lookup. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:30:  /** The complexity tier that determined the budget. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:32:  /** The allocated token budget. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:33:  budget: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:38:/** Default budget when the feature flag is disabled — treat everything as complex. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:41:/** Default tier-to-budget mapping when dynamic allocation is enabled.
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:43: * simple queries need fewer tokens, complex queries need the full budget. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:55: * Get the token budget for a given query complexity tier.
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:60: * When enabled, maps tier to the configured budget:
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:61: *   simple   → 1500 tokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:62: *   moderate → 2500 tokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:63: *   complex  → 4000 tokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:66: * @param config - Optional custom budget config (overrides DEFAULT_TOKEN_BUDGET_CONFIG)
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:67: * @returns BudgetResult with tier, budget, and applied flag
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:77:      budget: DEFAULT_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:83:  const budget = effectiveConfig[tier] ?? DEFAULT_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:87:    budget,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/10--python-compat/005-bench-runner.md:3:description: "Manual validation that scripts/skill_advisor_bench.py runs the performance bench and emits latency measurements within documented limits."
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/manual_testing_playbook/10--python-compat/005-bench-runner.md:65:| p95 exceeds budget | Summary shows latency over threshold | Investigate regression; block release if repeatable. |
.opencode/skills/system-spec-kit/mcp_server/lib/eval/eval-quality-proxy.ts:52:   * Expected / desired number of results (e.g. the limit parameter
.opencode/skills/system-spec-kit/mcp_server/tests/graph-signals.vitest.ts:877:      const first = search('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/graph-signals.vitest.ts:878:      const second = search('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/types.ts:128:  limit: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:25:// 2. Per-tier hard limits        — STATE_LIMITS caps applied when applyStateLimits=true
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:44:// Feature catalog: Confidence-based result truncation
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:65: * Per-tier hard limits applied when `applyStateLimits` is true.
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:130: * optionally, enforce per-tier result limits via `STATE_LIMITS`.
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:163:  // -- 3c. Per-tier limits (optional) --
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:166:    const limitPassing: Stage4ReadonlyRow[] = [];
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:170:      const limit = STATE_LIMITS[state] ?? Infinity;
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:173:      if (count < limit) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:175:        limitPassing.push(row);
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:177:      // Rows exceeding the per-tier limit are silently dropped (no score change).
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:180:    passing = limitPassing;
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:305:  // -- Step 4b: Final limit cap --
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:306:  // Enforce caller's limit after all filtering to prevent degraded paths exceeding requested count
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:307:  if (typeof config.limit === 'number' && config.limit > 0 && workingResults.length > config.limit) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/stage4-filter.ts:308:    workingResults = workingResults.slice(0, config.limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/graph-lifecycle.ts:215: * from the dirty set within that edge budget.
.opencode/skills/system-spec-kit/mcp_server/tests/provenance-envelope.vitest.ts:211:      limit: candidates.length,
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:149: * Minimum number of characters a noun phrase token must have to be considered.
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:150: * Avoids single-letter tokens matching alias table entries.
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:160: * Extract candidate noun phrase tokens from a query string using simple
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:162: * very short tokens, and return unique lowercase tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:168: * @returns Array of candidate noun phrase tokens (lowercase, deduplicated).
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:185:  // Filter out stop-words and short tokens
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:201:  const tokens: string[] = [];
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:203:  for (const token of raw) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:204:    if (token.length < MIN_NOUN_PHRASE_TOKEN_LENGTH) continue;
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:205:    if (stopWords.has(token)) continue;
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:206:    if (!seen.has(token)) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:207:      seen.add(token);
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:208:      tokens.push(token);
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:212:  return tokens;
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:216: * Match noun phrase tokens against a concept alias table, returning the
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:222: * @param tokens - Noun phrase tokens (from `nounPhrases()`).
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:232:  tokens: string[],
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:241:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:243:    const canonical = combined[token];
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:356:    const tokens = nounPhrases(query);
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:357:    if (tokens.length === 0) return empty;
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:360:    const concepts = matchAliases(tokens, extraAliases);
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:377: * original query tokens to avoid redundancy). Returns unique expansion terms.
.opencode/skills/system-spec-kit/mcp_server/lib/search/entity-linker.ts:380: * @param originalTokens - Query tokens to exclude from expansion (avoid echo).
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/skipPolicyEmptyPrompt.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:54: * Returns array of cleaned tokens.
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:56:function tokenize(sentence: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:61:    .map(token => token.replace(/[^\w]/g, ''))
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:62:    .filter(token => token.length > 0);
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:111:  const tokenizedSentences = sentences.map(s => tokenize(s));
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:116:  for (const tokens of tokenizedSentences) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:117:    const unique = new Set(tokens);
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:125:    const tokens = tokenizedSentences[index];
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:126:    if (tokens.length === 0) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:132:    for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:133:      termFreq.set(token, (termFreq.get(token) ?? 0) + 1);
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:139:      const tf = count / tokens.length;
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:149:  // Use reduce-based max to avoid RangeError when scored is large (spread exceeds call-stack limit)
.opencode/skills/system-spec-kit/mcp_server/lib/search/tfidf-summarizer.ts:246:  tokenize,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:44:type UsageStatsOptions = { sortBy?: string; order?: string; limit?: number };
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:49:  limit?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:165: * const rows = vector_search(queryEmbedding, { limit: 5, specFolder: 'specs/001-demo' });
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:180:    limit = 10,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:249:  // M8 FIX: If constitutional results already satisfy limit, return them directly
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:250:  if (constitutional_results.length >= limit) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:251:    return constitutional_results.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:253:  const adjusted_limit = Math.max(1, limit - constitutional_results.length);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:254:  params.push(max_distance, adjusted_limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:313: * const rows = multi_concept_search([embA, embB], { limit: 8, specFolder: 'specs/001-demo' });
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:318:  options: { limit?: number; specFolder?: string | null; minSimilarity?: number } = {}
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:343:  const { limit = 10, specFolder = null, minSimilarity = 50 } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:388:    limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:612:  options: { limit?: number; specFolder?: string | null } = {},
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:615:  const { limit = 20, specFolder = null } = options;
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:624:    console.warn('[vector-index] keyword_search: no valid search terms after tokenization');
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:673:    .slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:689: * @param limit - The maximum number of results to return.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:700:  limit = 20,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:715:      limit,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:722:    raw_results = keyword_search(query, { limit, specFolder }, database);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:772: * @param limit - The maximum number of results to return.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:783:  limit = 20,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:800:        return await multi_concept_keyword_search(concepts.filter(c => typeof c === 'string'), limit, options);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:811:    return await multi_concept_keyword_search(concepts.filter(c => typeof c === 'string'), limit, options);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:814:  const raw_results = multi_concept_search(concept_embeddings, { limit, specFolder, minSimilarity });
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:854: * @param limit - The maximum number of results to return.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:860:  limit = 20,
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:871:    keyword_search(concept, { limit: 100, specFolder })
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:894:  const limited_ids = matching_ids.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:895:  const rows = limited_ids.map(id => id_to_row.get(id)).filter((row): row is MemoryRow => Boolean(row));
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1081: * @param options - Sorting and limit options.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1088:    limit = 20
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1104:  `).all(limit) as Array<{
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1124: * @param options - Cleanup thresholds and limits.
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1134:    limit = 50
.opencode/skills/system-spec-kit/mcp_server/lib/search/vector-index-queries.ts:1172:      limit
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/README.md:49:| `stage2-fusion.ts` | Stage 2: Fusion + Signal Integration. The single authoritative scoring point. Applies 9 signal steps in fixed order: session boost, causal boost, co-activation spreading, community co-retrieval, graph signals, FSRS testing effect, intent weights (non-hybrid only, G2 prevention), artifact routing, feedback signals, artifact limiting, anchor metadata and validation metadata scoring. |
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/README.md:51:| `stage4-filter.ts` | Stage 4: Filter + Annotate. Removes results below minimum memory state priority, enforces per-tier limits, runs TRM evidence-gap detection and attaches annotation metadata. Enforces the score immutability invariant at runtime. |
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/README.md:73:      |  state filter, per-tier limits, TRM evidence gap, annotations
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/README.md:99:- Per-tier hard limits prevent any single tier from dominating results.
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:227: * tokenizer collisions. The canonical command spec at
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:360:  const tokens = text.toLowerCase().match(/[a-z0-9_]+/g) ?? [];
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:361:  for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:362:    const idx = hashToken(token) % CENTROID_EMBED_DIM;
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:390: * Hash a token into a stable non-negative integer.
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:393: * @param token - Single lowercase token to hash
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:396:function hashToken(token: string): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:398:  for (let i = 0; i < token.length; i++) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:399:    h ^= token.charCodeAt(i);
.opencode/skills/system-spec-kit/mcp_server/lib/search/intent-classifier.ts:615:    .filter((token) => token.length > 1 && !PARAPHRASE_STOPWORDS.has(token))
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:155:  'token_usage': AblationMetricEntry;
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:487:  baselinePerQuery: Map<number, { metrics: ReturnType<typeof computeQueryMetrics>; latencyMs: number; tokenUsage?: number }>,
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:488:  ablatedPerQuery: Map<number, { metrics: ReturnType<typeof computeQueryMetrics>; latencyMs: number; tokenUsage?: number }>,
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:505:  // L2 FIX: Filter out zero/undefined token usage since runAblation does not
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:506:  // currently populate tokenUsage — avoids reporting synthetic zeroes.
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:508:    .map(m => m.tokenUsage)
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:511:    .map(m => m.tokenUsage)
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:531:    'token_usage': entry(bTokenUsage, aTokenUsage),
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:590:    const baselineMetricsPerQuery: Map<number, { metrics: ReturnType<typeof computeQueryMetrics>; latencyMs: number; tokenUsage?: number }> = new Map();
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:617:      const ablatedMetricsPerQuery: Map<number, { metrics: ReturnType<typeof computeQueryMetrics>; latencyMs: number; tokenUsage?: number }> = new Map();
.opencode/skills/system-spec-kit/mcp_server/lib/eval/ablation-framework.ts:808:              metricName === 'token_usage'
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/noPassingSkill.json:20:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/tier-classifier.vitest.ts:247:     Production: getStateContent(memories[], targetState, limit) returns { state, memories, count }
.opencode/skills/system-spec-kit/mcp_server/tests/tier-classifier.vitest.ts:269:    it('T243: Respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tier-classifier.vitest.ts:334:     Production: filterAndLimitByState(memories, targetState?, limit?)
.opencode/skills/system-spec-kit/mcp_server/tests/tier-classifier.vitest.ts:356:    it('T253: limit=1 limits results', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tier-classifier.vitest.ts:361:    it('T254: Default returns within total limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-index.vitest.ts:1215:        const isServerDep = /database|getDb|Rate limited|vector_index|null|not initialized|Database/.test(message);
.opencode/skills/system-spec-kit/mcp_server/lib/search/pipeline/orchestrator.ts:12:// Input:  PipelineConfig (query, embedding, limits, flags, intent, session)
.opencode/skills/system-spec-kit/mcp_server/tests/trace-propagation.vitest.ts:34:    content: 'Security guidance for OAuth refresh handling and token lifecycle coordination across systems.',
.opencode/skills/system-spec-kit/mcp_server/tests/trace-propagation.vitest.ts:61:  const limit = typeof options.limit === 'number' ? options.limit : 10;
.opencode/skills/system-spec-kit/mcp_server/tests/trace-propagation.vitest.ts:62:  return MOCK_DOCS.slice(0, limit).map((doc, index) => ({
.opencode/skills/system-spec-kit/mcp_server/tests/trace-propagation.vitest.ts:70:    limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/trace-propagation.vitest.ts:120:      'explain how the authentication module integrates with the external OAuth provider and handles token refresh',
.opencode/skills/system-spec-kit/mcp_server/tests/session-bootstrap.vitest.ts:178:      limit: 5,
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/skipPolicyCommandOnly.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:39:  const limit = typeof options.limit === 'number' ? options.limit : 10;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:47:  return results.slice(0, limit).map((doc, i) => ({
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:55:  const limit = typeof options.limit === 'number' ? options.limit : 10;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:56:  return MOCK_DOCS.filter(d => d.content !== query).slice(0, limit).map((doc, i) => ({
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:278:      const results = hybridSearch.bm25Search('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:288:      const results = hybridSearch.bm25Search('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:293:    it('T031-BM25-05: bm25_search() respects limit option', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:298:      const results = hybridSearch.bm25Search('authentication', { limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:307:      const results = hybridSearch.bm25Search('module', { limit: 10, specFolder: 'specs/auth' });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:353:      const results = hybridSearch.bm25Search('module', { limit: 10, specFolder: 'specs/auth' });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:378:      const results = hybridSearch.combinedLexicalSearch('authentication', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:384:      const results = hybridSearch.combinedLexicalSearch('authentication', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:390:      const results = hybridSearch.combinedLexicalSearch('authentication', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:400:      const results = hybridSearch.combinedLexicalSearch('authentication module', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:407:      const results = hybridSearch.combinedLexicalSearch('authentication module', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:416:      const results = hybridSearch.combinedLexicalSearch('authentication', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:446:      const result = hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5 }) as MaybeAsyncHybridResults;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:453:      const result = hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5 }) as MaybeAsyncHybridResults;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:460:        hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5, useBm25: true });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:466:        hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5, useBm25: false });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:471:      const result = hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5 }) as MaybeAsyncHybridResults;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:484:      const results = await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:493:    it('T031-HYB-07: hybridSearchEnhanced() respects limit option', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:494:      const results = await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:502:      const results = await hybridSearch.hybridSearchEnhanced('module', mockEmbedding, { limit: 10, specFolder: 'specs/auth' });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:513:      const results = await hybridSearch.hybridSearchEnhanced('test query', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:520:        hybridSearch.hybridSearchEnhanced('test', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:529:        const results = await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:573:        hybridSearch.hybridSearchEnhanced('test', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:591:      const result = hybridSearch.hybridSearch('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:596:      const result = hybridSearch.hybridSearch('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:602:        hybridSearch.hybridSearch('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:614:        limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:639:      const result = hybridSearch.searchWithFallback('authentication', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:645:        hybridSearch.searchWithFallback('authentication', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:665:      const results = hybridSearch.ftsSearch('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:670:      const results = hybridSearch.ftsSearch('authentication', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:679:      const results = hybridSearch.ftsSearch('test*:query()', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:684:      const results = hybridSearch.ftsSearch('test AND query OR something NOT here', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:721:        hybridSearch.hybridSearchEnhanced('test', mockEmbedding, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:727:      const results = hybridSearch.bm25Search('test', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:734:      const results = hybridSearch.ftsSearch('', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:740:      const results = hybridSearch.combinedLexicalSearch('xyzzy123nonexistent', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:808:    await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:813:    await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 10, useGraph: false });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:818:    const results = await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:825:    await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:834:    const results = await hybridSearch.hybridSearchEnhanced('authentication', mockEmbedding, { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:849:    const results = await hybridSearch.searchWithFallback('authentication', null, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:881:      await hybridSearch.searchWithFallback('auth', embedding, { limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:929:      { limit: 5, useFts: false, useBm25: false, useGraph: false }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:950:      { limit: 5, useFts: false, useBm25: false, useGraph: false }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:970:      { limit: 5, useFts: false, useBm25: false, useGraph: false }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:994:      { limit: 5, useFts: false, useBm25: false, useGraph: false }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1018:        { limit: 1, useFts: false, useBm25: false, useGraph: false }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1124:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1150:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1179:      { limit: 10, intent: 'understand' }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1239:          limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1265:describe('P1 post-ranking truncation and token budget regressions', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1287:  it('T024: co-activation promotion happens before confidence truncation drops tail candidates', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1316:      { limit: 10, useFts: false, useBm25: true, useGraph: false, intent: 'understand' }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1343:  it('T025: truncateToBudget skips an oversized first result and keeps the best fitting candidate', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1360:    const budget = hybridSearch.estimateResultTokens(compact) + 5;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1362:    const truncated = hybridSearch.truncateToBudget([oversized, compact], budget, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1364:      queryId: 'p1-token-skip',
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1367:    expect(truncated.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1368:    expect(truncated.results.map((result) => result.id)).toEqual([2]);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1371:  it('T025: truncateToBudget keeps a summarized top result when every candidate exceeds the budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1393:    const truncated = hybridSearch.truncateToBudget([oversizedSecond, oversizedTop], 50, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1395:      queryId: 'p1-token-fallback',
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1398:    expect(truncated.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1399:    expect(truncated.results).toHaveLength(1);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1400:    expect(truncated.results[0]?.id).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1401:    expect(truncated.results[0]?.content).toContain('[Summary] Oversized top match:');
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1402:    expect(truncated.results[0]?._summarized).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1403:    expect(truncated.overflow?.truncatedToCount).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1406:  it('T311: truncateToBudget reuses the per-result token estimate during total and greedy passes', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1419:    const truncated = hybridSearch.truncateToBudget([resultWithGetter], 1, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1424:    expect(truncated.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1452:    const longTrigger = 'explain authentication token refresh integration details now please';
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1455:      limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1473:    const results = await hybridSearch.hybridSearchEnhanced('authentication module', embedding, { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1483:  it('S1-FIX-03: dynamic token budget is applied to live hybrid results', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1488:      const limit = (options.limit as number) || 20;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1489:      return Array.from({ length: limit }, (_v, idx) => ({
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1501:    const results = await hybridSearch.hybridSearchEnhanced('fix bug', embedding, { limit: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1504:      | { tokenBudget?: { budget?: number; applied?: boolean } }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1507:    expect(s3meta?.tokenBudget?.applied).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1508:    expect(s3meta?.tokenBudget?.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1512:  it('S1-FIX-04: evaluationMode bypasses token-budget truncation for benchmark calls', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1517:      const limit = (options.limit as number) || 20;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1518:      return Array.from({ length: limit }, (_v, idx) => ({
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1531:      limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1541:      budgetTruncated: false,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1571:    await hybridSearch.hybridSearchEnhanced('authentication', embedding, { limit: 10, useVector: false });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1577:    await hybridSearch.hybridSearchEnhanced('authentication', embedding, { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1583:    const results = await hybridSearch.hybridSearchEnhanced('authentication', embedding, { limit: 10, useFts: false });
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1590:    const results = await hybridSearch.hybridSearchEnhanced('authentication', embedding, { limit: 10, useBm25: false });
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context-session-state.vitest.ts:25:      getLayerInfo: vi.fn(() => ({ tokenBudget: 2000 })),
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context-session-state.vitest.ts:80:    vi.doMock('../formatters/token-metrics', () => ({
.opencode/skills/system-spec-kit/mcp_server/lib/chunking/anchor-chunker.ts:54:/** Target chunk size in characters (~1000 tokens at 4 chars/token) */
.opencode/skills/system-spec-kit/mcp_server/lib/chunking/anchor-chunker.ts:57:/** Maximum chunk size — hard cap to stay under embedding token budget */
.opencode/skills/system-spec-kit/mcp_server/tests/memory-save-integration.vitest.ts:511:        predictionErrorGate.truncateContent('x'.repeat(250)),
.opencode/skills/system-spec-kit/mcp_server/tests/memory-save-integration.vitest.ts:512:        predictionErrorGate.truncateContent('y'.repeat(40)),
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-ablation-drift.vitest.ts:338:      limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:289:describe('memory_search limit contract', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:292:      validateToolInputSchema('memory_search', { cursor: 'opaque-cursor-token' }, TOOL_DEFINITIONS);
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:298:      validateToolArgs('memory_search', { cursor: 'opaque-cursor-token' });
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:314:  it('accepts limit up to 100', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:316:      validateToolArgs('memory_search', { query: 'ab', limit: 100 });
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:320:  it('rejects limit above 100', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:322:      validateToolArgs('memory_search', { query: 'ab', limit: 101 });
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:326:  it('public schema rejects limit above 100', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:328:      validateToolInputSchema('memory_search', { query: 'ab', limit: 101 }, TOOL_DEFINITIONS);
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:452:  it('public schema rejects divergent_aliases limit above 200', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:454:      validateToolInputSchema('memory_health', { reportMode: 'divergent_aliases', limit: 201 }, TOOL_DEFINITIONS);
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:471:  it('public checkpoint_list schema rejects limit above 100', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:473:      validateToolInputSchema('checkpoint_list', { limit: 101 }, TOOL_DEFINITIONS);
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:510:        limit: 25,
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:563:        budgetTokens: 1200,
.opencode/skills/system-spec-kit/mcp_server/tests/tool-input-schema.vitest.ts:655:        limit: 25,
.opencode/skills/system-spec-kit/mcp_server/tests/graph-regression-flag-off.vitest.ts:162:      expect(graphFnSpy).toHaveBeenCalledWith('test query', expect.objectContaining({ limit: 20 }));
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/staleHighConfidenceSkill.json:22:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-trigger-perf-benchmark.vitest.ts:252:      limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-trigger-perf-benchmark.vitest.ts:265:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-trigger-perf-benchmark.vitest.ts:276:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/community-search.vitest.ts:107:  it('respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:9:import { truncateToTokenBudget, COMPACTION_TOKEN_BUDGET } from '../hooks/claude/shared.js';
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:56:  describe('token budget enforcement', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:57:    it('truncates payload exceeding budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:59:      const truncated = truncateToTokenBudget(largePayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:60:      expect(truncated.length).toBeLessThan(largePayload.length);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:61:      expect(truncated).toContain('[...truncated');
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:64:    it('keeps payload within budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:66:      const result = truncateToTokenBudget(smallPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/lib/chunking/README.md:46:| 4,000-char target, 12,000-char max | Target of ~1,000 tokens (at 4 chars/token) fits embedding model budgets. Hard cap prevents single chunks from exceeding token limits. |
.opencode/skills/system-spec-kit/mcp_server/lib/chunking/README.md:116:| `TARGET_CHUNK_CHARS` | 4,000 chars | Target chunk size (~1,000 tokens) |
.opencode/skills/system-spec-kit/mcp_server/tests/causal-boost.vitest.ts:126:  it('seed cap limits number of seed nodes used for graph walk', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/content-router.vitest.ts:17:    for (const token of text.toLowerCase().split(/[^a-z0-9_]+/).filter(Boolean)) {
.opencode/skills/system-spec-kit/mcp_server/tests/content-router.vitest.ts:18:      const digest = createHash('sha256').update(token).digest();
.opencode/skills/system-spec-kit/mcp_server/tests/archive/coverage-graph-db.vitest.ts:123:  describe('latency budget contract', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/archive/coverage-graph-db.vitest.ts:124:    it('defines 500ms budget for upsert batches', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/archive/coverage-graph-db.vitest.ts:129:    it('defines 200ms budget for queries', () => {
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/failOpenTimeout.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:392:        limit: -5,
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:406:        limit: 500,
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:411:      // Should succeed (limit clamped to 100)
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:421:        limit: 100,
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:456:    it('T013-O4: Default limit returns records without error', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/learning-stats-filters.vitest.ts:466:      // Default limit is 10 per handler code
.opencode/skills/system-spec-kit/mcp_server/tests/token-snapshot-store.vitest.ts:13:describe('hook-state token persistence', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-snapshot-store.vitest.ts:19:  it('stores token metrics in hook state', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/stage1-expansion.vitest.ts:119:  (_db?: unknown, _embedding?: Float32Array | number[], _limit?: number): Array<{ memoryId: number; similarity: number }> => []
.opencode/skills/system-spec-kit/mcp_server/tests/stage1-expansion.vitest.ts:123:  querySummaryEmbeddings: (db: unknown, embedding: Float32Array | number[], limit: number) =>
.opencode/skills/system-spec-kit/mcp_server/tests/stage1-expansion.vitest.ts:124:    mockQuerySummaryEmbeddings(db, embedding, limit),
.opencode/skills/system-spec-kit/mcp_server/tests/stage1-expansion.vitest.ts:176:    limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/reporting-dashboard.vitest.ts:769:    it('limit applies after sprint grouping and report totals match the included scope', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/reporting-dashboard.vitest.ts:780:      const report = await generateDashboardReport({ limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/reporting-dashboard.vitest.ts:944:    it('limit keeps the most recently active sprint even when it started earlier', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/reporting-dashboard.vitest.ts:969:      const report = await generateDashboardReport({ limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/response-profile-formatters.vitest.ts:11:      truncated: true,
.opencode/skills/system-spec-kit/mcp_server/tests/response-profile-formatters.vitest.ts:35:      tokenCount: 42,
.opencode/skills/system-spec-kit/mcp_server/tests/response-profile-formatters.vitest.ts:44:    expect(profiled.data.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/response-profile-formatters.vitest.ts:65:    expect(profiled.data.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:473:        truncated: false,
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:474:        truncationLimit: null,
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:512:    it('T015-DW7: traversal surfaces truncation when a node exceeds the per-node edge limit', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:538:        expect(envelope.data.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:539:        expect(envelope.data.truncationLimit).toBe(causalEdges.MAX_EDGES_LIMIT);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-causal-graph.vitest.ts:542:          expect.arrayContaining([expect.stringContaining('Traversal truncated after 100 edges per node')])
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/tests/legacy/advisor-fixtures/skippedShortCasual.json:15:    "tokenCap": 80
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-crud.vitest.ts:197:      expect(parsed.data?.limit).toBe(20);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-crud.vitest.ts:230:      expect(parsed.data?.limit).toBe(10);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-crud.vitest.ts:259:    it('T519-H4: Invalid limit returns error response', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-crud.vitest.ts:260:      const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 0 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-crud.vitest.ts:263:      expect(parsed.data?.error).toMatch(/limit must be a positive number/);
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:21:    it('T210-CFG1: TIER_CONFIG has limits for all 5 tiers', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:29:    it('T210-CFG2: Default limits match spec', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:85:    it('T210-FL2: Mixed tiers balanced with limits', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:87:        // 8 HOT (limit 5)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:89:        // 15 WARM (limit 10)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:91:        // 6 COLD (limit 3)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:93:        // 5 DORMANT (limit 2)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:107:        // 2 HOT (under limit of 5 → 3 surplus)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:109:        // 5 COLD (over limit of 3 → 2 overflow)
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:125:    it('T210-FL5: Overall limit parameter still respected', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:224:    it('T211-HI1: rerankResults respects the caller limit in fallback mode', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:232:        limit: 2,
.opencode/skills/system-spec-kit/mcp_server/tests/search-limits-scoring.vitest.ts:247:        limit: 2,
.opencode/skills/system-spec-kit/mcp_server/tests/cli.vitest.ts:5:import { delimiter, join, resolve } from 'node:path';
.opencode/skills/system-spec-kit/mcp_server/tests/cli.vitest.ts:39:      MEMORY_ALLOWED_PATHS: [workspaceDir, repoRoot].join(delimiter),
.opencode/skills/system-spec-kit/mcp_server/tests/trigger-extractor.vitest.ts:118:  describe('Max triggers limit (T515-04)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/trigger-extractor.vitest.ts:130:        'load balancing', 'circuit breaking', 'rate limiting',
.opencode/skills/system-spec-kit/mcp_server/tests/trigger-extractor.vitest.ts:131:        'authentication tokens', 'session management', 'permission checking',
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-stress.vitest.ts:44:describe('T014: interleaved session entry-limit stress', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:22:  it('renderPromptPack substitutes a single {topic} token with the variable value', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:28:  it('substitutes multiple different tokens in one render', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:34:  it('substitutes the same token appearing multiple times', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:40:  it('throws PromptPackError with the missing variable listed when a token lacks a binding', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:79:  it('tokens with invalid variable-name syntax are not matched and are treated as literal text', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:80:    withTempTemplate('Literal {foo.bar} token and valid {topic}', (templatePath) => {
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:81:      expect(renderPromptPack(templatePath, { topic: 'bound' })).toBe('Literal {foo.bar} token and valid bound');
.opencode/skills/system-spec-kit/mcp_server/tests/deep-loop/prompt-pack.vitest.ts:91:  it('template with no tokens renders unchanged', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:28:  tokenSavingsEstimate: string;
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:331:  describe('T008: dedup_savings_tokens calculation accuracy', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:352:      expect(dedupStats.tokenSavingsEstimate).toBeTruthy();
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:354:      // 3 filtered * 200 = ~600 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:355:      expect(dedupStats.tokenSavingsEstimate).toBe('~600 tokens');
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager.vitest.ts:367:      expect(noSavingsStats.tokenSavingsEstimate).toBe('0');
.opencode/skills/system-spec-kit/mcp_server/tests/budget-allocator.vitest.ts:9:} from '../code_graph/lib/budget-allocator.js';
.opencode/skills/system-spec-kit/mcp_server/tests/budget-allocator.vitest.ts:11:describe('budget allocator', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/budget-allocator.vitest.ts:40:    it('enforces total budget cap', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/budget-allocator.vitest.ts:46:    it('uses caller budgets above the default 4000-token layout', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:96:    'token_usage': entry(0, 0),
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1207:    'hit_rate', 'latency_p50', 'latency_p95', 'token_usage',
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1235:  it('token_usage defaults to 0', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1238:      expect(result.metrics!['token_usage'].baseline).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1239:      expect(result.metrics!['token_usage'].ablated).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1240:      expect(result.metrics!['token_usage'].delta).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/ablation-framework.vitest.ts:1305:      expect(metricNames).not.toContain('ablation_token_usage_delta');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-ingest-edge.vitest.ts:131:  it('T005a-I4c: MAX_INGEST_PATHS+1 paths throws the shared limit error', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:119:    limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:309:        concepts: ['authentication', 'token'],
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:511:    const results = structuralSearch({ specFolder: 'specs/001-auth', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:518:    const results = structuralSearch({ limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:527:    const results = structuralSearch({ specFolder: 'specs/999-nonexistent', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:534:    const scoped = structuralSearch({ specFolder: 'specs/001-auth', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/spec-folder-prefilter.vitest.ts:535:    const unscoped = structuralSearch({ limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-reconsolidation.vitest.ts:158:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:185:  it('S1-T-01: converts a pipe table header row to space-joined tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:431:      'The system uses JWT tokens for session management.',
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:438:      '- [x] Use refresh token rotation',
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:443:      'function refreshToken(token: string): Promise<string> {',
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:474:    expect(result).toContain('Use refresh token rotation');
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:528:  it('S1-B-05: keeps code body for identifier token search', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:537:    const input = '<!-- prettier-ignore -->\nSearchable token.';
.opencode/skills/system-spec-kit/mcp_server/tests/content-normalizer.vitest.ts:539:    expect(normalizeContentForBM25(input)).toContain('Searchable token.');
.opencode/skills/system-spec-kit/mcp_server/tests/attention-decay.vitest.ts:181:     Production: getActiveMemories(limit?: number): Array<Record<string, unknown>>
.opencode/skills/system-spec-kit/mcp_server/tests/recovery-hints.vitest.ts:78:  it('T008: HTTP-style rate limiting codes (E429, E503) exist', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-expansion.vitest.ts:333:  it('T11b: combinedQuery === original when all content tokens already appear in query', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-expansion.vitest.ts:337:    // The query contains all possible expansion tokens. We mock vectorSearch
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-expansion.vitest.ts:343:        // Content and title both use only tokens present in the query
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-expansion.vitest.ts:351:    // Query contains all the same tokens → no new terms can be extracted
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:36:  overrides: Partial<AtomicIndexDependencies<{ token: string }>> = {},
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:37:): AtomicIndexDependencies<{ token: string }> {
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:43:      prepared: { token: 'prepared' },
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:77:        prepared: { token: 'ready' },
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:104:        prepared: { token: 'routed-target' },
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:182:      prepared: { token: 'retryable' },
.opencode/skills/system-spec-kit/mcp_server/tests/atomic-index-memory.vitest.ts:253:        prepared: { token: params.content },
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:354:  it('quick tokenBudget is 800', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:356:    expect(memoryContext.CONTEXT_MODES.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:359:  it('deep tokenBudget is 3500', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:361:    expect(memoryContext.CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:364:  it('focused tokenBudget is 3000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:366:    expect(memoryContext.CONTEXT_MODES.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:369:  it('resume tokenBudget is 2000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:371:    expect(memoryContext.CONTEXT_MODES.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:374:  it('auto has no tokenBudget (delegates to sub-strategy)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:376:    expect(memoryContext.CONTEXT_MODES.auto.tokenBudget).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:451:    const result = peGating.findSimilarMemories(null, { limit: 3, specFolder: 'specs/test' });
.opencode/skills/system-spec-kit/mcp_server/tests/co-activation.vitest.ts:275:    // Production signature: spreadActivation(seedIds: number[], maxHops?, limit?)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-governance.vitest.ts:165:      limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/memory-governance.vitest.ts:252:    const allowed = reviewGovernanceAudit(db, { allowUnscoped: true, limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges-unit.vitest.ts:288:    it('GF3: getEdgesFrom respects limit=1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges-unit.vitest.ts:309:    it('GT3: getEdgesTo respects limit=1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges-unit.vitest.ts:341:    it('GA3: getAllEdges respects limit=2', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges-unit.vitest.ts:409:    it('CC4: Depth limit=2 returns 3 nodes', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges-unit.vitest.ts:467:    describe('T007: Natural leaf vs truncated chain', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-comparison.vitest.ts:66:  'audit API endpoints for rate limits',
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-comparison.vitest.ts:77:  'explain how the authentication module integrates with the external OAuth provider and handles token refresh',
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-comparison.vitest.ts:86:  'implement rate limiting and request throttling with configurable policies per endpoint user role and time window',
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:3:import { __testables, truncateToBudget, estimateResultTokens } from '../lib/search/hybrid-search';
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:58:  it('T065: preserves post-truncation ordering after contextual headers are injected', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:84:    const budgetForTopTwo =
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:86:    const truncated = truncateToBudget(rows, budgetForTopTwo, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:91:    expect(truncated.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:92:    expect(truncated.results.map((row) => row.id)).toEqual([11, 22]);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:99:    const injected = truncated.results.map((row) => __testables.injectContextualTree(row, cache));
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:106:  it('T066: adjusted token budget reserves header overhead and avoids overflow after injection', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:126:    const truncated = truncateToBudget(rows, adjustedBudget, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:128:      queryId: 'ctx-budget-overhead',
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:135:    const injected = truncated.results.map((row) => __testables.injectContextualTree(row, cache));
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:186:  it('T069: special characters in description → header properly formatted and within limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-metadata-schema.vitest.ts:504:  it('limits canonical entity preference to the current spec-folder path prefix', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/content-hash-dedup.vitest.ts:797:        limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/content-hash-dedup.vitest.ts:817:        limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/content-hash-dedup.vitest.ts:835:      limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/content-hash-dedup.vitest.ts:841:      limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/channel-enforcement.vitest.ts:10:// T3:  topK parameter limits the inspection window
.opencode/skills/system-spec-kit/mcp_server/tests/channel-enforcement.vitest.ts:140:  // ---- T3: topK parameter limits the inspection window ----
.opencode/skills/system-spec-kit/mcp_server/tests/channel-enforcement.vitest.ts:141:  it('T3: topK parameter limits the inspection window to the first N results', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/channel-enforcement.vitest.ts:164:    // The key guarantee: window size was limited to 3 for analysis.
.opencode/skills/system-spec-kit/mcp_server/tests/thin-continuity-record.vitest.ts:101:  it('fails budget enforcement after normalization when the fragment remains oversized', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/thin-continuity-record.vitest.ts:109:      recent_action: 'Completed canonical continuity budget verification',
.opencode/skills/system-spec-kit/mcp_server/tests/memory-search-quality-filter.vitest.ts:105:  it('includes deep-mode and archival/quality/state-limit controls in cache args', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-search-quality-filter.vitest.ts:111:      limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/memory-search-quality-filter.vitest.ts:144:      limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/query-router.vitest.ts:273:      'explain how the authentication module integrates with the external OAuth provider and handles token refresh gracefully'
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-memory-search.vitest.ts:170:  it('keeps canonical memory-search across 7 intents under the Gate D latency budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-memory-search.vitest.ts:181:          limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:8:  tokenize,
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:287:    it('S43: Very long input truncated at 2000 chars', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:292:      // Input is 3499 chars, truncated to 2000 → ~286 terms (2000/7 ≈ 285.7 + partial)
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:341:    it('TF02: Single token count=1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:346:    it('TF03: Repeated tokens counted', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-security.vitest.ts:352:    it('TF04: All unique tokens count=1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:316:   * return the first result's content and tokenMetrics.
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:358:    expect(res.tokenMetrics.anchorsFound).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:359:    expect(res.tokenMetrics.anchorsRequested).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:370:    expect(res.tokenMetrics.anchorsFound).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:380:    expect(res.tokenMetrics.anchorsFound).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:381:    expect(res.tokenMetrics.savingsPercent).toBe(100);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:396:    expect(res.tokenMetrics.anchorsFound).toBe(2);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:397:    expect(res.tokenMetrics.anchorsRequested).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:400:  it('I05: token metrics show savings when filtering to subset', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:409:    expect(res.tokenMetrics.anchorsFound).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:410:    expect(res.tokenMetrics.savingsPercent).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:411:    expect(res.tokenMetrics.returnedTokens).toBeLessThan(res.tokenMetrics.originalTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/anchor-prefix-matching.vitest.ts:431:    expect(firstResult.tokenMetrics).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:9:} from '../lib/enrichment/retry-budget.js';
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:11:describe('retry budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:42:  it('isolates budgets by memoryId', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:51:  it('isolates budgets by step', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:60:  it('isolates budgets by reason', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts:92:  it('reports the current budget size accurately', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-decomposer.vitest.ts:130:  it('each facet contains meaningful tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/query-decomposer.vitest.ts:133:      const tokens = facet.split(/\s+/).filter(Boolean);
.opencode/skills/system-spec-kit/mcp_server/tests/query-decomposer.vitest.ts:134:      expect(tokens.length).toBeGreaterThanOrEqual(MIN_FRAGMENT_TOKEN_COUNT);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:159:    it('token estimation correct', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:160:      const content = 'a'.repeat(400); // 400 chars ~ 100 tokens at 4 chars/token
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:161:      const tokens = preflight.estimateTokens(content);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:162:      expect(tokens).toBeGreaterThanOrEqual(90);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:163:      expect(tokens).toBeLessThanOrEqual(110);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:166:    it('token budget within limits', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:170:      expect(result.within_budget).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:171:      expect(result.estimated_tokens).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:175:    it('token budget exceeded detected', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:179:      expect(result.within_budget).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:184:    it('token budget warning generated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:185:      const content = 'a'.repeat(2800); // ~800 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:190:      expect(result.within_budget).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:238:        { check_anchors: true, check_tokens: true, check_size: true }
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:247:        { check_anchors: true, check_tokens: true, check_size: true }
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:256:        { dry_run: true, check_anchors: true, check_tokens: true, check_size: true }
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:266:        { check_anchors: false, check_tokens: true, check_size: true }
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:336:    it('token-related codes (PF020-PF021)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:640:    it('T165: token estimation ~4 chars/token ratio', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:643:      // 400 characters should yield 100 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:644:      const tokens400 = preflight.estimateTokens('a'.repeat(400));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:645:      expect(tokens400).toBe(Math.ceil(400 / charsPerToken));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:647:      // 800 characters should yield 200 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:648:      const tokens800 = preflight.estimateTokens('b'.repeat(800));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:649:      expect(tokens800).toBe(Math.ceil(800 / charsPerToken));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:651:      // 40 characters should yield 10 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:652:      const tokens40 = preflight.estimateTokens('c'.repeat(40));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:653:      expect(tokens40).toBe(Math.ceil(40 / charsPerToken));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:655:      // Verify the ratio: tokens * 4 should approximately equal chars
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:656:      const tokens1000 = preflight.estimateTokens('d'.repeat(1000));
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:657:      const inferredRatio = 1000 / tokens1000;
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:662:    it('T166: token budget warning at 80% threshold', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:663:      // 2800 chars → ~700 tokens + 150 overhead = ~850 tokens = 85% of 1000
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:671:      expect(result.within_budget).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:685:      const content = 'y'.repeat(1000); // ~286 tokens + 150 overhead = ~436 tokens = 43.6% of 1000
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:692:      expect(result.within_budget).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:721:          check_tokens: true,
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:729:      expect(result.details.checks_run).toContain('token_budget');
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:734:      expect(result.details.token_budget).toBeTruthy();
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:749:          check_tokens: true,
.opencode/skills/system-spec-kit/mcp_server/tests/query-classifier.vitest.ts:73:  'explain how the authentication module integrates with the external OAuth provider and handles token refresh',
.opencode/skills/system-spec-kit/mcp_server/tests/query-classifier.vitest.ts:82:  'implement rate limiting and request throttling with configurable policies per endpoint user role and time window',
.opencode/skills/system-spec-kit/mcp_server/tests/query-classifier.vitest.ts:338:        'explain how the authentication module integrates with the external OAuth provider and handles token refresh gracefully'
.opencode/skills/system-spec-kit/mcp_server/tests/query-classifier.vitest.ts:348:        'implement rate limiting request throttling configurable policies endpoint user role'
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/graph-metadata.json:65:    "causal_summary": "The skill advisor is the Gate 2 routing engine that scores user requests against all 20 skill descriptions using token normalization, synonym expansion, intent boosting, graph-derived transitive boosts, and confidence calibration. It returns ranked recommendations with dual-threshold filtering so the calling AI can invoke the right skill with measured certainty.",
.opencode/skills/system-spec-kit/mcp_server/tests/memory-save-pipeline-enforcement.vitest.ts:457:    //   triggers=0*0.25 + anchors=0.5*0.30 + budget=1.0*0.20 + coherence=0.75*0.25
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:10:// P1-9  Fetch limit — search results respect the limit parameter
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:115:    it('sanitizeFTS5Query truncates input at 2000 characters', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:121:      // After truncation at 2000 chars, there should be fewer terms
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:210:     P1-9: Fetch Limit — search results respect limit parameter
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:213:  describe('P1-9: Fetch limit respected', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:230:    it('BM25 search respects the limit parameter', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:234:      // Add more documents than the limit
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:239:      const limit = 5;
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:240:      const results = index.search('memory search', limit);
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:242:      expect(results.length).toBeLessThanOrEqual(limit);
.opencode/skills/system-spec-kit/mcp_server/tests/regression-suite.vitest.ts:245:    it('BM25 search with limit=0 returns empty array', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-trace.vitest.ts:249:      token: 'secret-token',
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-trace.vitest.ts:264:    expect(sanitizedRecord.token).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/folder-discovery.vitest.ts:70:  it('truncates description to 150 characters maximum', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/folder-discovery.vitest.ts:97:  it('truncates long title to exactly 150 characters', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/folder-discovery.vitest.ts:224:  it('respects the limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/folder-discovery.vitest.ts:230:  it('defaults limit to 3 when not specified', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/folder-discovery.vitest.ts:299:    fs.writeFileSync(path.join(specA, 'spec.md'), '# Authentication System\n\nHandles login and tokens.', 'utf-8');
.opencode/skills/system-spec-kit/mcp_server/tests/structural-contract.vitest.ts:226:            `very_long_symbol_kind_name_${index}_with_extra_budget_pressure`,
.opencode/skills/system-spec-kit/mcp_server/tests/adaptive-ranking.vitest.ts:102:      limit: candidates.length,
.opencode/skills/system-spec-kit/mcp_server/tests/tool-cache.vitest.ts:81:      const args = { query: 'authentication', limit: 10 };
.opencode/skills/system-spec-kit/mcp_server/tests/tool-cache.vitest.ts:241:    it('should enforce max entries limit (1000 default)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/tool-cache.vitest.ts:629:        options: { limit: 10, offset: 0 },
.opencode/skills/system-spec-kit/mcp_server/skill_advisor/SET-UP_GUIDE.md:200:| `degraded` | Hook or daemon can run only in limited trust | Follow OP-001 in the playbook. |
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:38:import { expectReturnedCountMatchesPayload } from './_support/token-budget-assertions';
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:48:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:108:  it('T003: quick mode has triggers strategy and 800 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:111:    expect(quickMode.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:114:  it('T004: deep mode has search strategy and 3500 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:117:    expect(deepMode.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:120:  it('T005: focused mode has intent-search strategy and 3000 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:123:    expect(focusedMode.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:126:  it('T006: resume mode has resume strategy and 2000 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:129:    expect(resumeMode.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:151:  it('T009: Non-auto modes have token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:154:        expect(typeof mode.tokenBudget).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:155:        expect(mode.tokenBudget!).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:160:  it('T010: Token budgets are reasonable (500-4000 range)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:162:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:163:        expect(mode.tokenBudget).toBeGreaterThanOrEqual(500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:164:        expect(mode.tokenBudget).toBeLessThanOrEqual(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:405:  it('T034: Quick mode token budget is 800', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:406:    expect(CONTEXT_MODES.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:416:  it('T036: Quick mode has smallest token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:417:    const budgets: number[] = Object.entries(CONTEXT_MODES)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:418:      .filter(([_k, v]: [string, ContextMode]) => v.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:419:      .map(([_k, v]: [string, ContextMode]) => v.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:420:    const minBudget: number = Math.min(...budgets);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:421:    expect(CONTEXT_MODES.quick.tokenBudget).toBe(minBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:451:    expect(quick.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:473:  it('T044: Deep mode token budget is 3500', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:474:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:477:  it('T045: Deep mode has highest token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:478:    const budgets: number[] = Object.entries(CONTEXT_MODES)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:479:      .filter(([_k, v]: [string, ContextMode]) => v.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:480:      .map(([_k, v]: [string, ContextMode]) => v.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:481:    const maxBudget: number = Math.max(...budgets);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:482:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(maxBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:506:    expect(deep.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:528:  it('T054: Focused mode token budget is 3000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:529:    expect(CONTEXT_MODES.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:532:  it('T055: Focused mode budget is between quick and deep', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:533:    const focusedBudget: number = CONTEXT_MODES.focused.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:534:    const quickBudget: number = CONTEXT_MODES.quick.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:535:    const deepBudget: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:563:    expect(focused.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:587:  it('T064: Resume mode token budget is 2000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:588:    expect(CONTEXT_MODES.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:591:  it('T065: Resume mode budget is less than deep', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:592:    const resumeBudget: number = CONTEXT_MODES.resume.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:593:    const deepBudget: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:624:    expect(resume.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:648:  it('T074: Auto mode has no fixed token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:649:    const autoBudget: number | undefined = CONTEXT_MODES.auto.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:719:  it('T084: CHK-072 - L1 token budget is 3500 (from layer-definitions)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:720:    // Deep mode has 3500 which aligns with L1 Orchestration budget
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:721:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:730:  it('T086: Token budgets follow expected hierarchy', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:731:    const quick: number = CONTEXT_MODES.quick.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:732:    const resume: number = CONTEXT_MODES.resume.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:733:    const focused: number = CONTEXT_MODES.focused.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:734:    const deep: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:741:  it('T087: Total defined token budgets are reasonable', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:742:    const budgets: number[] = Object.values(CONTEXT_MODES)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:743:      .filter((m: ContextMode) => m.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:744:      .map((m: ContextMode) => m.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:745:    const sum: number = budgets.reduce((a: number, b: number) => a + b, 0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:750:  it('T088: Each non-auto mode has explicit token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:753:        expect(typeof mode.tokenBudget).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:758:  it('T089: Token budgets are whole numbers', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:760:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:761:        expect(Number.isInteger(mode.tokenBudget)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:766:  it('T090: Token budgets are positive', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:768:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:769:        expect(mode.tokenBudget).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:883:  it('T202: Small result under budget is not truncated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:887:    expect(enforcement.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:888:    expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:891:  it('T203: Result with embedded content array over budget is truncated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:893:    // Each "result" item is ~100 chars = ~25 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:911:    // Use a small budget to force truncation
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:912:    const { result: truncated, enforcement } = enforceTokenBudget(mockResult, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:914:    expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:917:    expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:919:    expectReturnedCountMatchesPayload(truncated as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:939:    const { result: truncated } = enforceTokenBudget(mockResult, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:940:    // Parse the truncated inner results to verify order
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:941:    const contentArr = (truncated as Record<string, unknown>).content as Array<{ type: string; text: string }>;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:951:  it('T205: Budget enforcement reports accurate token count', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:954:    const expectedTokens = Math.ceil(serialized.length / 4); // 1 token ≈ 4 chars
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:960:  it('T206: Budget of 0 forces truncation on any non-empty result', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:969:    const { result: truncated, enforcement } = enforceTokenBudget(mockResult, 0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:971:    expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:975:    expect(enforcement.droppedAllResultsReason).toBe('impossible_budget');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:976:    expectReturnedCountMatchesPayload(truncated as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:979:  it('T207: Result without content array reports truncated when over budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:983:    expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:998:    const { result: truncated, enforcement } = enforceTokenBudget(mockResult, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:999:    expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1001:    const contentArr = (truncated as Record<string, unknown>).content as Array<{ type: string; text: string }>;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1007:  it('T209: Each mode token budget matches CONTEXT_MODES definition', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1008:    // Verify that enforcement uses the correct budget per mode
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1015:    for (const [modeName, budget] of Object.entries(expectedBudgets)) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1017:      expect(mode.tokenBudget).toBe(budget);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1021:  it('T210: Large budget allows all results through', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1034:    expect(enforcement.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1035:    expect(enforcement.budgetTokens).toBe(100000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1045:    const { result: truncated, enforcement } = enforceTokenBudget(malformedNestedResult, 5);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1046:    const contentArr = (truncated as Record<string, unknown>).content as Array<{ type: string; text: string }>;
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-save.vitest.ts:2555:        findSimilar: (embedding: Float32Array, options: { limit: number; specFolder: string }) => unknown;
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-save.vitest.ts:2557:        params.findSimilar(params.embedding, { limit: 3, specFolder: 'specs/999-atomic-save-fi' });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-save.vitest.ts:2654:          limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:138:    .run(2, 'specs/001-auth', 'auth/tokens.md', 'Token Validation');
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:232:middleware implements OAuth 2.0 with "refresh tokens" via Express Router.
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:272:      const tokenMatch = matches.find(m => m.canonicalName.includes('token'));
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:273:      expect(tokenMatch).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:274:      expect(tokenMatch!.specFolders.length).toBeGreaterThanOrEqual(2);
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:417:against the database and issues JWT tokens. The token refresh mechanism ensures
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:418:seamless session continuity. Error handling covers expired tokens, invalid
.opencode/skills/system-spec-kit/mcp_server/tests/deferred-features-integration.vitest.ts:419:signatures, and rate limiting scenarios.
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:27:    const tokens = nounPhrases('what is the memory retrieval system');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:28:    expect(tokens).not.toContain('what');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:29:    expect(tokens).not.toContain('is');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:30:    expect(tokens).not.toContain('the');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:33:  it('filters out tokens shorter than MIN_NOUN_PHRASE_TOKEN_LENGTH', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:34:    const tokens = nounPhrases('the ai system at the db level');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:35:    for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:36:      expect(token.length).toBeGreaterThanOrEqual(MIN_NOUN_PHRASE_TOKEN_LENGTH);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:40:  it('returns lowercase tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:41:    const tokens = nounPhrases('Memory Retrieval Pipeline');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:42:    for (const token of tokens) {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:43:      expect(token).toBe(token.toLowerCase());
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:47:  it('deduplicates repeated tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:48:    const tokens = nounPhrases('memory memory retrieval retrieval');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:49:    const unique = new Set(tokens);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:50:    expect(unique.size).toBe(tokens.length);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:53:  it('extracts meaningful tokens from a real query', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:54:    const tokens = nounPhrases('how does the embedding retrieval pipeline work');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:55:    expect(tokens).toContain('embedding');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:56:    expect(tokens).toContain('retrieval');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:57:    expect(tokens).toContain('pipeline');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:61:    const tokens = nounPhrases('memory-search: find embeddings!');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:62:    // Should not crash and should return tokens
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:63:    expect(Array.isArray(tokens)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:66:  it('includes known alias tokens in output', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:67:    const tokens = nounPhrases('show me sessions checkpoints and graph edges');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:68:    expect(tokens).toContain('sessions');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:69:    expect(tokens).toContain('checkpoints');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:70:    expect(tokens).toContain('graph');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:71:    expect(tokens).toContain('edges');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:80:  it('returns empty array for no tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:84:  it('returns empty array when no tokens match any alias', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:85:    const tokens = nounPhrases('zebra unicorn dragon');
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:86:    expect(matchAliases(tokens)).toEqual([]);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-routing.vitest.ts:141:    // Provide many tokens that all match different concepts
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:52:  it('T006-L3: Negative limit clamped to 1', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:53:    const result = await handler.handleMemoryList({ limit: -5 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:55:    expect(parsed.data.limit).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:60:    const result = await handler.handleMemoryList({ limit: 500 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:62:    expect(parsed.data.limit).toBe(100);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:72:    const result = await handler.handleMemoryList({ limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:74:    expect(parsed.data.limit).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:107:    expect(parsed.data.limit).toBe(20);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:130:   sort/limit/offset/specFolder behavior, missing filter interactions
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:131:   like combined specFolder + sortBy, specFolder + limit, and
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:159:    const allResults = parseResponse(await handler.handleMemoryList({ limit: 100 }));
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:161:      await handler.handleMemoryList({ specFolder: 'specs/001-auth', limit: 100 }),
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:173:  it('T245-FI2: specFolder + limit combined respects both constraints', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:175:      await handler.handleMemoryList({ specFolder: 'specs/001-auth', limit: 1 }),
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:178:    expect(result.data.limit).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:196:      await handler.handleMemoryList({ specFolder: 'specs/001-auth', limit: 1, offset: 0 }),
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-list-edge.vitest.ts:199:      await handler.handleMemoryList({ specFolder: 'specs/001-auth', limit: 1, offset: 1 }),
.opencode/skills/system-spec-kit/mcp_server/tests/graph-roadmap-finalization.vitest.ts:164:      { limit: 2, minGraphInjected: 2, killSwitchOnly: true },
.opencode/skills/system-spec-kit/mcp_server/tests/graph-roadmap-finalization.vitest.ts:190:  it('keeps unified graph retrieval within a local microbenchmark budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-roadmap-finalization.vitest.ts:210:      const results = searchFn('graph latency probe', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:78:  // ---- T4: Chunk size limits respected for text ----
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:79:  it('T4: text chunks respect maxTokens limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:80:    // Create a long text that exceeds 500 tokens (2000 chars)
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:133:  it('T8: token estimates use ~4 chars per token', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:134:    const md = 'A'.repeat(400); // 400 chars → ~100 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:139:    expect(chunks[0].tokenEstimate).toBeGreaterThanOrEqual(100);
.opencode/skills/system-spec-kit/mcp_server/tests/structure-aware-chunker.vitest.ts:140:    expect(chunks[0].tokenEstimate).toBeLessThanOrEqual(101);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:50:  it('T007b-H2: Zero limit returns error response with requestId', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:51:    const result = await handler.handleMemoryHealth({ reportMode: 'divergent_aliases', limit: 0 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:55:    expect(error).toMatch(/limit must be a positive number/);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:59:  it('T007b-H3: Negative limit returns error response', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:60:    const result = await handler.handleMemoryHealth({ limit: -5 } as HealthArgs);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:64:    expect(error).toMatch(/limit must be a positive number/);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-health-edge.vitest.ts:102:    expect(parsed.data.limit).toBe(20);
.opencode/skills/system-spec-kit/mcp_server/tests/concept-extraction.vitest.ts:35:    it('returns expansion terms excluding original tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/concept-extraction.vitest.ts:46:    it('respects maxTerms limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-store.vitest.ts:83:    process.env.MEMORY_ALLOWED_PATHS = [firstDbPaths.dir, secondDbPaths.dir].join(path.delimiter);
.opencode/skills/system-spec-kit/mcp_server/tests/reranker.vitest.ts:24:  it('T512-05: rerankResults respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/pipeline-v2.vitest.ts:262:      // UNKNOWN_STATE_PRIORITY=6 means all pass, but STATE_LIMITS for UNKNOWN is unlimited (Infinity)
.opencode/skills/system-spec-kit/mcp_server/tests/orchestrator-error-cascade.vitest.ts:72:    limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:233:    it('truncates long content to maxLength', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:372:    it('produces different keys for different limits', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:678:      const results = mod.keywordSearch('alpha', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:935:      const stats = mod.getUsageStats({ sortBy: 'access_count', order: 'DESC', limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1046:        limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1340:      const searchResults = vectorMod.vectorSearch(query, { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1351:      const filtered = vectorMod.vectorSearch(query, { limit: 10, specFolder: 'specs/test-vec' });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1357:      const strict = vectorMod.vectorSearch(query, { limit: 10, minSimilarity: 99 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1388:      const mcResults = vectorMod.multiConceptSearch([emb1, emb2], { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1394:        vectorMod.multiConceptSearch([makeEmbedding(1)], { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1546:    it('respects maxLines truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-impl.vitest.ts:1553:      // Should have 3 content lines + possible truncation message
.opencode/skills/system-spec-kit/mcp_server/tests/tiered-injection-turnNumber.vitest.ts:187:  describe('T201: filterAndLimitByState tier limits', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/codex-pre-tool-use.vitest.ts:71:  it('uses full-word matching rather than partial token matching', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-intent-routing.vitest.ts:368:          limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:26:  truncateToBudget,
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:209:// D. Token Budget with Results (S1 — PI-A3 token budget)
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:215:  it('D1: truncateToBudget respects budget limit — returns fewer results when over budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:216:    // Build many results that would individually be small but together exceed budget
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:221:      title: `Memory title number ${i + 1} with some content to pad the token count`,
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:225:    const { results: truncated, truncated: wasTruncated } = truncateToBudget(results, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:227:    expect(truncated.length).toBeLessThan(results.length);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:232:    const text = 'a'.repeat(40); // exactly 40 chars → 10 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:235:    const text2 = 'b'.repeat(41); // 41 chars → ceil(41/4) = 11 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:241:  it('D3: truncateToBudget returns all results when they fit within budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:247:    const { results: out, truncated } = truncateToBudget(results, 2000);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:250:    expect(truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:346:    const tokens = estimateResultTokens(result);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:347:    expect(tokens).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:350:  it('T-budget-boundary: exact budget fit handled correctly', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:355:    const budget = results.reduce((sum, result) => sum + estimateResultTokens(result), 0);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:357:    const { results: output, truncated } = truncateToBudget(results, budget);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:359:    expect(truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/feedback-ledger.vitest.ts:348:  it('respects limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feedback-ledger.vitest.ts:353:    const limited = getFeedbackEvents(db, { limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/feedback-ledger.vitest.ts:354:    expect(limited).toHaveLength(2);
.opencode/skills/system-spec-kit/mcp_server/tests/sqlite-fts.vitest.ts:133:  it('T8: limit parameter caps result count', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/sqlite-fts.vitest.ts:134:    const results = fts5Bm25Search(db, 'login', { limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/learned-feedback.vitest.ts:680:  it('R11-AL02: getAuditLog supports limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/learned-feedback.vitest.ts:828:    expect(r4.reason).toContain('promotion_window_rate_limited');
.opencode/skills/system-spec-kit/mcp_server/tests/stage3-rerank-regression.vitest.ts:46:  limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/stage3-rerank-regression.vitest.ts:221:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/stage3-rerank-regression.vitest.ts:251:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/stage3-rerank-regression.vitest.ts:272:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/README.md:85:| Search and ranking | `hybrid-search.vitest.ts`, `bm25-index.vitest.ts`, `query-router.vitest.ts`, `dynamic-token-budget.vitest.ts`, `result-confidence-scoring.vitest.ts` | Retrieval, ranking, and profile/trace behavior |
.opencode/skills/system-spec-kit/mcp_server/tests/post-insert-deferred.vitest.ts:4:import { clearBudget } from '../lib/enrichment/retry-budget.js';
.opencode/skills/system-spec-kit/mcp_server/tests/post-insert-deferred.vitest.ts:383:  it('stops scheduling runEnrichmentBackfill after the unresolved causal-link retry budget is exhausted', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:10:describe('stop hook token tracking', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:24:    it('extracts token usage from assistant messages', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:26:        JSON.stringify({ message: { role: 'assistant', usage: { input_tokens: 100, output_tokens: 50 }, model: 'claude-sonnet-4-6' } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:27:        JSON.stringify({ message: { role: 'assistant', usage: { input_tokens: 200, output_tokens: 100 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:38:          JSON.stringify({ message: { role: 'assistant', usage: { input_tokens: 100, output_tokens: 50 }, model: 'claude-sonnet-4-6' } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:39:          JSON.stringify({ message: { role: 'assistant', usage: { input_tokens: 200, output_tokens: 100 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:55:        JSON.stringify({ message: { role: 'assistant', usage: { input_tokens: 50, output_tokens: 25 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:67:        JSON.stringify({ message: { usage: { input_tokens: 100, output_tokens: 50 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:68:        JSON.stringify({ message: { usage: { input_tokens: 200, output_tokens: 100 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:76:        JSON.stringify({ message: { usage: { input_tokens: 100, output_tokens: 50 } } }) + '\n',
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:84:          JSON.stringify({ message: { usage: { input_tokens: 100, output_tokens: 50 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:85:          JSON.stringify({ message: { usage: { input_tokens: 200, output_tokens: 100 } } }),
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:91:    it('handles cache tokens', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:96:              input_tokens: 100,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:97:              output_tokens: 50,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:98:              cache_creation_input_tokens: 500,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts:99:              cache_read_input_tokens: 300,
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-extended.vitest.ts:746:      // Temporarily set a small limit
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-extended.vitest.ts:749:        // Insert 5 memories (exceeds limit of 3)
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-extended.vitest.ts:761:    it('no trimming when under limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-extended.vitest.ts:767:        // Insert exactly 3 (under limit of 5)
.opencode/skills/system-spec-kit/mcp_server/tests/session-manager-extended.vitest.ts:799:        // After inserting 4 rows with limit 2, the 2 oldest should be trimmed
.opencode/skills/system-spec-kit/mcp_server/tests/progressive-disclosure.vitest.ts:176:  it('truncates content at SNIPPET_MAX_LENGTH and adds "..."', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/progressive-disclosure.vitest.ts:185:  it('does not truncate content shorter than SNIPPET_MAX_LENGTH', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoints-storage.vitest.ts:384:    it('T503-07: Max checkpoints limit enforced', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints-edge.vitest.ts:142:  it('T010-C4: List with limit=1 returns at most 1 result', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints-edge.vitest.ts:146:    const result = await handler.handleCheckpointList({ limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-checkpoints-edge.vitest.ts:163:    const result = await handler.handleCheckpointList({ specFolder: matchingFolder, limit: 50 });
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-embedding-semantic-search.vitest.ts:42:        title: 'Legacy memory exact-token bait',
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-regression-embedding-semantic-search.vitest.ts:168:      limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/memory-summaries.vitest.ts:169:  it('handles punctuation correctly by stripping it during tokenization', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-summaries.vitest.ts:176:    // Should not crash; punctuation-stripped tokens are used
.opencode/skills/system-spec-kit/mcp_server/tests/memory-summaries.vitest.ts:356:      'Each document is tokenized and embedded before storage.',
.opencode/skills/system-spec-kit/mcp_server/tests/memory-summaries.vitest.ts:472:  it('respects the limit parameter', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:87:  it('T007a-S1: Zero limit falls back to 10', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:88:    const result = await handler.handleMemoryStats({ limit: 0 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:90:    expect(parsed.data.limit).toBe(10);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:95:    const result = await handler.handleMemoryStats({ limit: 999 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:97:    expect(parsed.data.limit).toBe(100);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:102:    const result = await handler.handleMemoryStats({ limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:104:    expect(parsed.data.limit).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:115:    const result = await handler.handleMemoryStats({ folderRanking: 'count', includeArchived: true, limit: 100 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:130:      limit: 100,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:191:    expect(parsed.data.limit).toBe(10);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:197:  it('T007a-S13: totalSpecFolders remains greater than topFolders length when limit truncates', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:201:    const result = await handler.handleMemoryStats({ folderRanking: 'count', limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-stats-edge.vitest.ts:203:    expect(parsed.data.limit).toBe(2);
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:30:    token?: unknown;
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:195:    expect(t.mode.tokenUsageRatio).toBe(0.85);
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:198:  it('T04b: recordMode clamps tokenUsageRatio to 0-1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:201:    expect(t.mode.tokenUsageRatio).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:204:    expect(t.mode.tokenUsageRatio).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:407:      token: 'sensitive-token',
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:419:    expect(tracePayload.token).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/retrieval-telemetry.vitest.ts:428:    t.fallback.authorization = 'Bearer token';
.opencode/skills/system-spec-kit/mcp_server/tests/compact-merger.vitest.ts:28:    it('respects total token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/compact-merger.vitest.ts:55:    it('keeps sessionState inside the caller budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/compact-merger.vitest.ts:69:    it('skips zero-budget sections instead of rendering headers only', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/compact-merger.vitest.ts:81:      expect(result.sections.every(section => section.tokenEstimate > 0)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:214:        limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:221:    it('rerankResults respects limit', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:229:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:237:        limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:247:        limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-encoder.vitest.ts:257:        limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:3:// Verifies dedup, lambda tuning, N-cap, performance, and limits.
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:44:  it('T1: reduces identical candidates to limit=1', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:46:    const result = applyMMR(candidates, { lambda: 0.5, limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:63:    const result = applyMMR(candidates, { lambda: 0.5, limit: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:75:    const result = applyMMR(candidates, { lambda: 0.85, limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:88:    const result = applyMMR(candidates, { lambda: 0.7, limit: 5, maxCandidates: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:104:    applyMMR(candidates, { lambda: 0.7, limit: 5, maxCandidates: 20 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:110:  // ---- T6: Output respects limit ----
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:111:  it('T6: never returns more than limit results', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:113:    const result = applyMMR(candidates, { lambda: 0.7, limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:120:    const result = applyMMR([], { lambda: 0.7, limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:127:    const result = applyMMR(candidates, { lambda: 0.7, limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts:156:    const config: MMRConfig = { lambda: 0.6, limit: 4 };
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-input-validation.vitest.ts:39:    invalidArgs: { query: 12345, limit: 'not-a-number' },
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-input-validation.vitest.ts:40:    description: 'wrong types for query and limit',
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-input-validation.vitest.ts:58:    invalidArgs: { limit: 'not-a-number', specFolder: 123 },
.opencode/skills/system-spec-kit/mcp_server/tests/modularization.vitest.ts:111:    'formatters/token-metrics.js',
.opencode/skills/system-spec-kit/mcp_server/tests/modularization.vitest.ts:127:    it(`${mod} is within line limit`, () => {
.opencode/skills/system-spec-kit/mcp_server/tests/modularization.vitest.ts:136:      const limit = EXTENDED_LIMITS[mod] || MAX_MODULE_LINES;
.opencode/skills/system-spec-kit/mcp_server/tests/modularization.vitest.ts:137:      expect(lines).toBeLessThanOrEqual(limit);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:8:import { expectReturnedCountMatchesPayload } from './_support/token-budget-assertions';
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:17:    it('T205-A1: All layer token budgets correct', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:18:      const budgets: Record<string, number> = {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:39:      for (const [tool, expected] of Object.entries(budgets)) {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:41:        expect(actual, `${tool} budget`).toBe(expected);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:45:    it('T205-A2: Unknown tool gets default budget (1000)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:46:      const budget = layerDefs.getTokenBudget('nonexistent_tool');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:47:      expect(budget).toBe(1000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:50:    it('T205-A3: All 7 layers have positive token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:53:        expect((layer as { tokenBudget: number }).tokenBudget, `${id} should have positive budget`).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:62:    it('T205-B1: Small result under budget is not truncated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:70:      expect(enforcement.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:73:      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:77:    it('T205-B2: Large result over budget IS truncated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:95:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:99:      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:101:      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:121:      const { result: truncatedResult, enforcement } = memoryContext.enforceTokenBudget(mockResult, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:122:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:124:      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:125:      expectReturnedCountMatchesPayload(truncatedResult as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:126:      const content = truncatedResult.content as Array<{ text: string }>;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:132:    it('T205-B4: Non-envelope payload over budget reports truncated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:140:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:141:      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:144:    it('T205-B5: Single structured result is compacted to fit within budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:162:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:165:      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:167:      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:177:    it('T205-B6: Under-budget payload exposes equal token telemetry', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:194:      expect(enforcement.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:201:    it('T205-B7: Over-budget resolvable payload separates pre and returned tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:220:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:221:      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:222:      expect(enforcement.returnedTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:227:    it('T205-B8: Impossible budget reports droppedAllResultsReason', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:246:      expect(enforcement.truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:248:      expect(enforcement.droppedAllResultsReason).toBe('impossible_budget');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:258:    it('T205-C1: Dispatch-level truncation logic present', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:266:    it('T205-C2: Dispatch reports truncation metadata', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:271:      expect(serverSrc).toContain('tokenBudgetTruncated');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:284:    it('T205-C4: Uses getTokenBudget for layer-specific budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:297:    it('T205-D1: Mode budgets correct', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:301:      expect(modes.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:302:      expect(modes.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:303:      expect(modes.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:304:      expect(modes.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:307:    it('T205-D2: Auto mode delegates budget (undefined)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:311:      expect(modes.auto.tokenBudget).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:318:      const quickBudget = modes.quick.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:319:      const resumeBudget = modes.resume.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:320:      const focusedBudget = modes.focused.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:321:      const deepBudget = modes.deep.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:327:        throw new Error('Expected all non-auto mode budgets to be defined');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:6:  tokenize,
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:89:      const tokens = tokenize('hello world test');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:90:      expect(tokens).toContain('hello');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:91:      expect(tokens).toContain('world');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:92:      expect(tokens).toContain('test');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:96:      const tokens = tokenize('HELLO World TEST');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:97:      expect(tokens).toContain('hello');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:98:      expect(tokens).toContain('world');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:99:      expect(tokens).toContain('test');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:103:      const tokens = tokenize('hello, world! test.');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:104:      expect(tokens.some((t: string) => t.includes(',') || t.includes('!') || t.includes('.'))).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:108:      const tokens = tokenize('the quick brown fox is a test');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:109:      expect(tokens).not.toContain('the');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:110:      expect(tokens).not.toContain('is');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:111:      expect(tokens).not.toContain('a');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:115:      const tokens = tokenize('I a am we go');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:116:      expect(tokens).not.toContain('i');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:117:      expect(tokens).not.toContain('a');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:121:      const tokens = tokenize('hello_world test_function');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:122:      expect(tokens.some((t: string) => t.includes('_'))).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:126:      const tokens = tokenize('');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:127:      expect(Array.isArray(tokens)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:128:      expect(tokens.length).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:133:      const tokens = tokenize(null);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:134:      expect(Array.isArray(tokens)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:135:      expect(tokens.length).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:140:      const tokens = tokenize(12345);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:141:      expect(Array.isArray(tokens)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:142:      expect(tokens.length).toBe(0);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:359:      const multiQuery = tokenize('memory search');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:377:    it('T036.7: search() respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:486:      const results = hybridSearch!.bm25Search('memory search', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:508:      const results = hybridSearch!.combinedLexicalSearch('test query', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:517:      const results = hybridSearch!.combinedLexicalSearch('memory search', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:525:      const results = hybridSearch!.combinedLexicalSearch('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:534:      const results = hybridSearch!.combinedLexicalSearch('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:545:      const results = hybridSearch!.combinedLexicalSearch('memory', { limit: 5 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:552:    it.skipIf(!hybridSearch || !isBm25Enabled())('T039.7: Respects limit parameter', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:557:      const results = hybridSearch!.combinedLexicalSearch('memory', { limit: 1 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:566:      const results = hybridSearch!.combinedLexicalSearch('memory', { limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:592:  it('C138-T4: tokenize handles multi-field input', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:593:    const titleTokens = tokenize('AuthGuard Module');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:594:    const bodyTokens = tokenize('The AuthGuard module handles authentication for the application system');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:596:    // Title has fewer tokens than body
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:604:    const tokens = tokenize('auth auth auth login login');
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:605:    const tf = getTermFrequencies(tokens);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:614:      content_text: '---\ntitle: Hidden frontmatter\n---\nSearchable body token',
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-index.vitest.ts:620:    expect(text).toContain('Searchable body token');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-eval-reporting.vitest.ts:408:      expect(graphSearch).toHaveBeenCalledWith('hybrid retrieval graph diagnosis', { limit: 7 });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-eval-reporting.vitest.ts:461:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-eval-reporting.vitest.ts:469:        limit: 5,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-eval-reporting.vitest.ts:493:        limit: undefined,
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-trigger-fast-path.vitest.ts:171:  // Deep-review benchmark coverage for the Gate D trigger fast path latency budget.
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-trigger-fast-path.vitest.ts:172:  it('keeps the canonical trigger fast path under the Gate D latency budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/gate-d-benchmark-trigger-fast-path.vitest.ts:181:        limit: 3,
.opencode/skills/system-spec-kit/mcp_server/tests/mutation-ledger.vitest.ts:129:  it('respects limit and offset in queries', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/mutation-ledger.vitest.ts:134:    const limited = getEntries(db, { limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/mutation-ledger.vitest.ts:135:    expect(limited).toHaveLength(2);
.opencode/skills/system-spec-kit/mcp_server/tests/mutation-ledger.vitest.ts:136:    expect(limited[0].reason).toBe('entry-0');
.opencode/skills/system-spec-kit/mcp_server/tests/mutation-ledger.vitest.ts:138:    const offsetted = getEntries(db, { limit: 2, offset: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:12:type TruncateInput = Parameters<typeof peGate.truncateContent>[0];
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:322:    it('T151: truncateContent truncates + adds "..."', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:324:      const truncated = peGate.truncateContent(longContent, 100);
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:325:      expect(truncated).toHaveLength(103);
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:326:      expect(truncated.endsWith('...')).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:329:    it('T152: truncateContent preserves short strings', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:331:      expect(peGate.truncateContent(shortContent, 100)).toBe(shortContent);
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:334:    it('T153: truncateContent handles null/undefined', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:335:      expect(peGate.truncateContent(null as unknown as TruncateInput, 100)).toBe('');
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:336:      expect(peGate.truncateContent(undefined as unknown as TruncateInput, 100)).toBe('');
.opencode/skills/system-spec-kit/mcp_server/tests/prediction-error-gate.vitest.ts:525:      'filterRelevantCandidates', 'getActionPriority', 'truncateContent',
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:44:      const requiredFields = ['id', 'name', 'description', 'tokenBudget', 'priority', 'useCase', 'tools'];
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:72:    it('T06: Token budgets are positive numbers', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:74:        const budget = layer.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:75:        expect(typeof budget).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:76:        expect(budget).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:88:    it('T08: Specific token budget values match', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:93:        expect(LD[layerId]?.tokenBudget).toBe(expected);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:262:    it('T20: Known tools return correct token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:277:    it('T21: Unknown tool returns default budget 1000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:296:      expect(info.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:314:      const requiredFields = ['id', 'name', 'description', 'tokenBudget', 'priority', 'useCase', 'tools'];
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:430:      const budgetPatterns = [
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:435:      for (const pattern of budgetPatterns) {
.opencode/skills/system-spec-kit/mcp_server/tests/coverage-graph-signals.vitest.ts:111:      limit: 10,
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:7:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate'
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:98:      const input = { query: 'test', limit: 10 }
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:99:      const result = actualParseArgs<{ query: string; limit: number }>(input)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:101:      expect(result.limit).toBe(10)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:134:      const nullInput = { query: null, limit: null }
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:135:      const nullResult = actualParseArgs<{ query: string | null; limit: number | null }>(nullInput)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:137:      expect(nullResult.limit).toBeNull()
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1693:            meta: { tool: 'checkpoint_list', tokenCount: 10, cacheHit: false, tokenBudget: 1000 },
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1712:      expect(parsed.meta.tokenBudget).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1713:      expect(parsed.meta.tokenCount).toBeGreaterThan(0)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1716:    it('T000j: final tokenCount matches the serialized envelope after hints and tokenBudget injection', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1719:        triggered: [{ memory_id: 2, matched_phrases: ['budget'] }],
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1730:            meta: { tool: 'memory_list', tokenCount: 1, tokenBudget: 1000, cacheHit: false },
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1741:      expect(finalText).toContain('"tokenBudget": 1000')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1744:      expect(parsed.meta.tokenCount).toBe(estimateTokenCount(finalText))
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1794:      const originalText = '{"summary":"ok","data":{"status":"success"},"hints":[],"meta":{"tokenCount":1}}'
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2129:    // T26: Source injects tokenBudget into response metadata
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2130:    it('T26: Token budget injection exists', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2135:    it('T27: Token budget overflow detection', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2136:      expect(sourceCode).toMatch(/tokenCount\s*>\s*budget/)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2140:    it('T28: L1 budget = 3500 (memory_context)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2148:    it('T28b: L2 budget = 3500 (memory_search)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2156:    it('T28c: L3 budget = 1000 (memory_list)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2164:    it('T28d: Unknown tool budget = 1000 (default)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2172:    it('T28e: L4 budget = 1000 (memory_delete)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2180:    it('T28f: L5 budget = 1000 (checkpoint_create)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2188:    it('T28g: L6 budget = 1500 (memory_drift_why)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2196:    it('T28h: L7 budget = 1000 (memory_index_scan)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2650:    it('T62: Token budgets in descriptions', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2651:      const budgetPattern = /Token Budget:\s*\d+/g
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2652:      const budgetMatches = toolSchemasCode.match(budgetPattern)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2653:      expect(budgetMatches).not.toBeNull()
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2654:      expect(budgetMatches!.length).toBeGreaterThanOrEqual(20)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2657:    it('T000e: memory_context supports optional tokenUsage (0.0-1.0)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2658:      expect(toolSchemasCode).toMatch(/name:\s*'memory_context'[\s\S]*?tokenUsage:\s*\{\s*type:\s*'number'/)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2659:      expect(toolSchemasCode).toMatch(/tokenUsage:[\s\S]*?minimum:\s*0\.0/)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2660:      expect(toolSchemasCode).toMatch(/tokenUsage:[\s\S]*?maximum:\s*1\.0/)
.opencode/skills/system-spec-kit/mcp_server/tests/redaction-gate.vitest.ts:11:      'token=sk-1234567890abcdefghijklmnopqrstuv',
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:4:// Verifies token estimation, greedy truncation, single-result
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:11:  truncateToBudget,
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:48:  it('estimates tokens as ceil(chars / 4)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:68:    const tokens = estimateResultTokens(result);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:70:    expect(tokens).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:71:    expect(tokens).toBeLessThan(100);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:98:  it('reads budget from SPECKIT_TOKEN_BUDGET env var', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:115:describe('truncateToBudget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:124:  it('returns all results when total tokens fit within budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:130:    const { results: output, truncated, overflow } = truncateToBudget(results, 10000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:132:    expect(truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:137:  it('returns empty results without truncation for empty input', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:138:    const { results, truncated, overflow } = truncateToBudget([], 100);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:141:    expect(truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:145:  it('truncates to highest-scoring results (greedy, not round-robin)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:146:    // Create results where total exceeds a small budget
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:148:      makeLargeResult(1, 0.5, 200),   // ~60 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:149:      makeLargeResult(2, 0.9, 200),   // ~60 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:150:      makeLargeResult(3, 0.7, 200),   // ~60 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:151:      makeLargeResult(4, 0.3, 200),   // ~60 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:155:    const budget = 120;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:156:    const { results: output, truncated, overflow } = truncateToBudget(results, budget);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:158:    expect(truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:169:    expect(overflow!.truncatedToCount).toBe(output.length);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:170:    expect(overflow!.budgetLimit).toBe(budget);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:174:    const bigContent = 'x'.repeat(40000); // ~10000 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:179:    const budget = 200;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:180:    const { results: output, truncated, overflow } = truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:182:      budget,
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:186:    expect(truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:200:    expect(overflow!.truncatedToCount).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:209:    const budget = 200;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:210:    const { results: output, truncated, overflow } = truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:212:      budget,
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:216:    expect(truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:229:    const { overflow } = truncateToBudget(results, 100, { queryId: 'eval-test' });
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:237:    expect(log.budgetLimit).toBe(100);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:238:    expect(typeof log.truncatedToCount).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:239:    expect(log.truncatedToCount).toBeLessThanOrEqual(log.candidateCount);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:252:    const { results: output } = truncateToBudget(results, 10000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:260:  it('uses default budget when budget param is 0 or undefined', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:263:    // With undefined budget — should use getTokenBudget()
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:264:    const r1 = truncateToBudget(results);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:265:    expect(r1.truncated).toBe(false); // tiny result fits in 2000
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:267:    // With 0 budget — should also use default
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:268:    const r2 = truncateToBudget(results, 0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:269:    expect(r2.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:291:    // 2500 budget, 10 results → 2500 - 260 = 2240
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:293:    // 4000 budget, 20 results → 4000 - 520 = 3480
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:295:    // 1500 budget, 5 results → 1500 - 130 = 1370
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:299:  it('T2: budget never goes below 200 (the floor)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:300:    // 500 budget, 100 results → 500 - 2600 = -2100 → clamped to 200
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:302:    // 200 budget, 1 result → 200 - 26 = 174 → clamped to 200
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:304:    // 0 budget, 0 results → 0 - 0 = 0 → clamped to 200
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:309:    // 4000 budget, 500 results → 4000 - 13000 = -9000 → clamped to 200
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:311:    // 1500 budget, 200 results → 1500 - 5200 = -3700 → clamped to 200
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:320:  it('T5: truncateToBudget respects the adjusted budget when passed', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:321:    // Simulate what hybrid-search.ts does: compute adjusted budget, pass to truncateToBudget
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:328:    // Create results that exceed 980 tokens when combined.
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:330:      makeLargeResult(1, 0.9, 2000),  // ~500 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:331:      makeLargeResult(2, 0.8, 2000),  // ~500 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:334:    const { truncated } = truncateToBudget(results, adjusted);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:335:    // Two ~500-token results should truncate under 980 budget
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:336:    expect(truncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/entity-linker.vitest.ts:288:    it('limits incremental matching to entities attached to the target memory', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/entity-linker.vitest.ts:496:    it('respects MAX_EDGES_PER_NODE limit (20)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/entity-linker.vitest.ts:511:        canonicalName: 'over limit entity',
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-scoring-holdout.vitest.ts:787:    it('respects limit option', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-scoring-holdout.vitest.ts:802:      const limited = getShadowScoringHistory(db, { limit: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/shadow-scoring-holdout.vitest.ts:803:      expect(limited).toHaveLength(2);
.opencode/skills/system-spec-kit/mcp_server/tests/vector-index-store-remediation.vitest.ts:241:    process.env.MEMORY_ALLOWED_PATHS = [storeAPaths.dir, storeBPaths.dir].join(path.delimiter);
.opencode/skills/system-spec-kit/mcp_server/tests/db-dimension-integrity.vitest.ts:24:  process.env.MEMORY_ALLOWED_PATHS = paths.join(path.delimiter);
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-weighting.vitest.ts:9:function tokenize(text: string): string[] {
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-weighting.vitest.ts:17:  const indexByToken = new Map(vocabulary.map((token, index) => [token, index]));
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-weighting.vitest.ts:21:    for (const token of tokenize(text)) {
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-weighting.vitest.ts:22:      const index = indexByToken.get(token);
.opencode/skills/system-spec-kit/mcp_server/tests/embedding-weighting.vitest.ts:92:  it('truncates general content before outcomes and decisions, preserving word boundaries', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/description/fixtures/017-002-cluster-consumers.description.json:44:    "thirty-hour-effort-budget",
.opencode/skills/system-spec-kit/mcp_server/tests/encoding-intent.vitest.ts:164:      '    const results = this.index.query(embedding, { limit: 10 });',
.opencode/skills/system-spec-kit/mcp_server/tests/encoding-intent.vitest.ts:326:      '  async search(embedding: number[], limit: number): Promise<Row[]> {',
.opencode/skills/system-spec-kit/mcp_server/tests/encoding-intent.vitest.ts:328:      '    return stmt.all(limit) as Row[];',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:73:    tokenUsageSource?: string;
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:74:    tokenUsagePressure?: number | null;
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:309:    it('T524-5: Each mode has correct token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:321:        expect(mode.tokenBudget).toBe(expectedBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:326:  // SUITE: tokenUsage Fallback Contract + Pressure Policy (T000f/T000g, T018-T020)
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:327:  describe('tokenUsage fallback contract and pressure policy lane', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:332:          tokenUsage: 0.55,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:340:      expect(parsed.meta.tokenUsageSource).toBe('caller');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:341:      expect(parsed.meta.tokenUsagePressure).toBe(0.55);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:350:          input: 'implement OAuth state and token refresh flow with threat model and rollout plan',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:351:          tokenUsage: 0.65,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:360:      expect(parsed.meta.tokenUsageSource).toBe('caller');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:361:      expect(parsed.meta.tokenUsagePressure).toBe(0.65);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:372:          tokenUsage: 0.85,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:380:      expect(parsed.meta.tokenUsageSource).toBe('caller');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:381:      expect(parsed.meta.tokenUsagePressure).toBe(0.85);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:388:    it('T018/T019: out-of-range caller tokenUsage clamps to [0,1] and maps to quick', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:392:          tokenUsage: 2.7,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:400:      expect(parsed.meta.tokenUsageSource).toBe('caller');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:401:      expect(parsed.meta.tokenUsagePressure).toBe(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:405:    it('T017: absent tokenUsage uses estimator fallback from runtime stats', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:406:      // L1 token budget is 3500 — need ~0.8*3500=2800 tokens (~11200 chars) for quick pressure
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:419:      expect(parsed.meta.tokenUsageSource).toBe('estimator');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:420:      expect(parsed.meta.tokenUsagePressure).toBeGreaterThanOrEqual(0.8);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:421:      expect(parsed.meta.tokenUsagePressure).toBeLessThanOrEqual(1);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:429:        description: 'Unavailable token estimator for test coverage',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:430:        tokenBudget: 0,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:447:      expect(parsed.meta.tokenUsageSource).toBe('unavailable');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:448:      expect(parsed.meta.tokenUsagePressure).toBeNull();
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:452:        'tokenUsage not provided and estimator unavailable; pressure policy inactive'
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:461:          tokenUsage: 0.95,
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:469:      expect(parsed.meta.tokenUsageSource).toBe('caller');
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:470:      expect(parsed.meta.tokenUsagePressure).toBe(0.95);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:479:          input: 'implement OAuth state and token refresh flow with threat model and rollout plan',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:480:          tokenUsage: 0.95,
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-baseline.vitest.ts:77:function makeMockSearchFn(count: number = 5): (query: string, limit: number) => BM25SearchResult[] {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-baseline.vitest.ts:78:  return (_query: string, limit: number) => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-baseline.vitest.ts:79:    const actual = Math.min(count, limit);
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-baseline.vitest.ts:445:    const trackingSearch = (query: string, limit: number): BM25SearchResult[] => {
.opencode/skills/system-spec-kit/mcp_server/tests/bm25-baseline.vitest.ts:477:    const mockSearch = (query: string, _limit: number): BM25SearchResult[] => {
.opencode/skills/system-spec-kit/mcp_server/tests/errors-comprehensive.vitest.ts:245:  it('E3: "rate limit" is transient', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/errors-comprehensive.vitest.ts:246:    expect(isTransientError(new Error('rate limit exceeded'))).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/causal-edges.vitest.ts:389:    it('should limit depth', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:47:describe('edge-cases: token pressure budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:65:    const budget = calculatePressureAdjustedBudget(80000, 100000, 2000);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:66:    expect(budget).toBeLessThan(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:76:    const budget = calculatePressureAdjustedBudget(95000, 100000, 2000);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:77:    expect(budget).toBeGreaterThanOrEqual(200);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:78:    expect(budget).toBeLessThanOrEqual(400);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:98:describe('edge-cases: truncateToTokenBudget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:99:  it('returns original text when under budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:100:    const { truncateToTokenBudget } = await import('../hooks/claude/shared.js');
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:102:    expect(truncateToTokenBudget(short, 1000)).toBe(short);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:105:  it('truncates text exceeding budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:106:    const { truncateToTokenBudget } = await import('../hooks/claude/shared.js');
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:108:    const result = truncateToTokenBudget(long, 100);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:109:    expect(result.length).toBeLessThanOrEqual(500); // 100 tokens * 4 chars + truncation message
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:110:    expect(result).toContain('[...truncated');
.opencode/skills/system-spec-kit/mcp_server/tests/error-sanitization.vitest.ts:21:  it('redacts bearer tokens', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts:19:const applyMMRMock = vi.fn((candidates: readonly VectorCandidate[], options?: { limit?: number }) => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts:20:  const limit = options?.limit ?? candidates.length;
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts:21:  return candidates.slice(0, limit);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts:67:    await hybridSearch.hybridSearchEnhanced('test query', embedding, { limit: 3 } satisfies HybridSearchOptions);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts:74:    await hybridSearch.hybridSearchEnhanced('test query', embedding, { limit: 3 } satisfies HybridSearchOptions);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:17:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:205:    it('formats startup sections within budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:209:      const truncated = truncateToTokenBudget(output, SESSION_PRIME_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:210:      expect(truncated).toContain('Session Priming');
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:211:      expect(truncated.length / 4).toBeLessThanOrEqual(SESSION_PRIME_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:214:    it('compact output uses larger budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:216:      const truncated = truncateToTokenBudget(longPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:217:      expect(truncated.length / 4).toBeLessThanOrEqual(COMPACTION_TOKEN_BUDGET + 50);
.opencode/skills/system-spec-kit/mcp_server/tests/api-validation.vitest.ts:140:    mockFetch(429, { error: { message: 'Rate limit exceeded' } });
.opencode/skills/system-spec-kit/mcp_server/tests/api-validation.vitest.ts:145:    expect(result.warning).toContain('rate limited');
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:5:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:251:  describe('T153: meta.tokenCount estimation accuracy', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:252:    it('should estimate token count from the final serialized envelope', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:259:      expect(typeof envelope.meta.tokenCount).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:260:      expect(envelope.meta.tokenCount).toBe(estimateTokenCount(JSON.stringify(envelope, null, 2)));
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:264:      const testText = 'a'.repeat(100); // 100 chars = ~25 tokens
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:272:      expect(envelope.meta.tokenCount).toBeGreaterThan(dataOnlyEstimate);
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:273:      expect(envelope.meta.tokenCount).toBe(estimateTokenCount(JSON.stringify(envelope, null, 2)));
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:283:      expect(typeof envelope.meta.tokenCount).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:284:      expect(envelope.meta.tokenCount).toBe(estimateTokenCount(JSON.stringify(envelope, null, 2)));
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts:300:      expect(envelope.meta.tokenCount).toBe(estimateTokenCount(JSON.stringify(envelope, null, 2)));
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-response-envelope.vitest.ts:125:                budgetTruncated: true,
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-response-envelope.vitest.ts:167:    expect(result.trace?.budgetTruncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:294:    // enforces the limit via `candidates.slice(0, MAX_RERANK_CANDIDATES)`.
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:313:// ── Test 8: MAX_PROMPT_BYTES=10KB truncation ─────────────────
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:315:describe('local-reranker MAX_PROMPT_BYTES truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:316:  it('truncates prompts exceeding 10KB', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:319:    // Simulate the truncation logic from rerankLocal (lines 298-304)
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:325:    // Apply the same truncation algorithm as the source
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:350:    // Apply same truncation logic
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:359:    // Verify result is valid UTF-8 and within budget
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:362:    // The truncated string should decode cleanly — re-encode and compare
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:5:// - Token budget constants (4000 max per point)
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:11:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:67:  it('Both budgets are numeric', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:72:  it('Both budgets are positive', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:542:describe('TM-05: Token budget enforcement (4000 max per point)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:551:  it('trigger-matcher is limited to 5 results per surface call (per-budget control)', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:560:    await autoSurfaceAtToolDispatch('bash', { query: 'test budget enforcement query' });
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:562:    // The second argument to matchTriggerPhrases is the limit
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:564:      const limitArg = matchSpy.mock.calls[0][1];
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:565:      expect(limitArg).toBe(5);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:569:  it('compaction hook also enforces result limit via matchTriggerPhrases', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:578:    await autoSurfaceAtCompaction('Session context to verify budget enforcement');
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:581:      const limitArg = matchSpy.mock.calls[0][1];
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:582:      expect(limitArg).toBe(5);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:586:  it('tool-dispatch output boundary enforces estimated token budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:599:    const result = await autoSurfaceAtToolDispatch('bash', { query: 'explicit budget enforcement' });
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:609:  it('compaction output boundary enforces estimated token budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:622:    const result = await autoSurfaceAtCompaction('compaction context for budget enforcement');
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:761:      expect(typeof section.tokenEstimate).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/adaptive-fallback.vitest.ts:66:    const results = await executeWithFallback(mockScatter, 'auth token', metadata);
.opencode/skills/system-spec-kit/mcp_server/tests/adaptive-fallback.vitest.ts:71:    expect(mockScatter).toHaveBeenCalledWith('auth token', { min_similarity: 0.3 });
.opencode/skills/system-spec-kit/mcp_server/tests/pipeline-integration.vitest.ts:351:  it('hybridSearch respects the limit option', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/pipeline-integration.vitest.ts:352:    const limit = 2;
.opencode/skills/system-spec-kit/mcp_server/tests/pipeline-integration.vitest.ts:353:    const results = await hybridSearch('test query', null, { useGraph: true, limit });
.opencode/skills/system-spec-kit/mcp_server/tests/pipeline-integration.vitest.ts:355:    expect(results.length).toBeLessThanOrEqual(limit);
.opencode/skills/system-spec-kit/mcp_server/tests/skill-graph-schema.vitest.ts:146:      limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/skill-graph-schema.vitest.ts:152:        limit: 20,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:17:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:69:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:74:} from '../lib/search/confidence-truncation';
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:161:      // Token budget returns default
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:162:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:163:      expect(budget.budget).toBe(DEFAULT_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:164:      expect(budget.applied).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:177:      // Confidence truncation passes through
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:183:      const truncated = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:184:      expect(truncated.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:185:      expect(truncated.results.length).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:201:      // Token budget resolves correctly
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:202:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:203:      expect(budget.applied).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:204:      expect(budget.budget).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:221:      // Confidence truncation active
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:226:      const truncResult = truncateByConfidence(scoredResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:273:    it('4. Query classifier feeds token budget: simple → 1500, complex → 4000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:282:      expect(simpleBudget.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:292:      expect(complexBudget.budget).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:347:    it('7. Confidence truncation respects minimum: even with large gaps, min 3 results remain', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:360:      const truncResult = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:447:      // Confidence truncation with empty
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:448:      const emptyTrunc = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:450:      expect(emptyTrunc.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:482:      // Confidence truncation with 1 result
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:483:      const singleTrunc = truncateByConfidence([{ id: 1, score: 0.9 }]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:485:      expect(singleTrunc.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:504:    it('14. Duplicate scores: truncation and normalization handle ties', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:513:      const truncResult = truncateByConfidence(tiedResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:514:      // When all scores are equal, median gap is 0, so no truncation
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:515:      expect(truncResult.truncated).toBe(false);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:572:    it('16. Full pipeline: query → classify → budget → fusion → score → truncate', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:582:      // Step 2: Get token budget
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:583:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:584:      expect(budget.budget).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:626:      const truncated = truncateByConfidence(scored);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:627:      expect(truncated.results.length).toBeGreaterThanOrEqual(DEFAULT_MIN_RESULTS);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:628:      expect(truncated.results.length).toBeLessThanOrEqual(fused.length);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:19:    tmpDbPath = path.join(os.tmpdir(), `t212-checkpoint-limit-${Date.now()}.db`);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:82:        const cp = mod.createCheckpoint({ name: `limit-test-cp-${i}` });
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:88:      const limited = mod.listCheckpoints(null, 5);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:89:      expect(Array.isArray(limited)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:90:      expect(limited.length).toBe(5);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:99:    it('T212-04: listCheckpoints(null) returns all (default limit=50 > 10)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:120:        mod.createCheckpoint({ name: `folder-limit-${i}`, specFolder: 'spec-a' });
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:123:        mod.createCheckpoint({ name: `folder-limit-b-${i}`, specFolder: 'spec-b' });
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:128:      const limitedA = mod.listCheckpoints('spec-a', 3);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:129:      expect(Array.isArray(limitedA)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:130:      expect(limitedA.length).toBe(3);
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:131:      const allCorrectFolder = limitedA.every((cp) => cp.specFolder === 'spec-a');
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:135:    it('T212-07: specFolder without limit returns all matching', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:142:  // SUITE: listCheckpoints signature accepts limit
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:143:  describe('listCheckpoints signature accepts limit', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/checkpoint-limit.vitest.ts:144:    it('T212-08: listCheckpoints(specFolder, limit) accepted', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/runtime-routing.vitest.ts:12:    for (const token of text.toLowerCase().split(/[^a-z0-9_]+/).filter(Boolean)) {
.opencode/skills/system-spec-kit/mcp_server/tests/runtime-routing.vitest.ts:13:      const digest = createHash('sha256').update(token).digest();
.opencode/skills/system-spec-kit/mcp_server/tests/runtime-routing.vitest.ts:63:    it('what is the purpose of the budget allocator', () => { expect(classifyQueryIntent('what is the purpose of the budget allocator').intent).toBe('semantic'); });
.opencode/skills/system-spec-kit/mcp_server/tests/runtime-routing.vitest.ts:79:    it('what is the purpose of the token budget', () => { expect(classifyQueryIntent('what is the purpose of the token budget').intent).toBe('semantic'); });
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-ingest.vitest.ts:205:          message: 'queue truncated',
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-ingest.vitest.ts:236:        message: 'queue truncated',
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:3:// Validates latency ceiling, token budget, feature flag regression.
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:40:    tokensConsumed: number;
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:93:function applyMMRLocal(results: SearchResult[], lambda: number, limit: number): SearchResult[] {
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:101:  const selected = applyMMR(candidates, { lambda, limit });
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:163:      tokensConsumed: Math.ceil(payload.length / 4),
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:190:    const response = hybridSearchEnhanced('fix auth token error', 'auto', ALL_FLAGS_ON);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:195:  // ---- T2: Token budget respected ----
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:196:  it('T2: payload respects 2000-token (8000 char) budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:200:    expect(response.metrics.tokensConsumed).toBeLessThanOrEqual(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:280:    expect(response.metrics).toHaveProperty('tokensConsumed');
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:342:    const selected = applyMMR(candidates, { lambda: 0.7, limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:344:    // And return at most limit=10
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:353:    const selected = applyMMR([], { lambda: 0.7, limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:363:    const selected = applyMMR(candidates, { lambda: 0.7, limit: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:375:    applyMMR(candidates, { lambda: 0.7, limit: 10 });
.opencode/skills/system-spec-kit/mcp_server/tests/fixtures/hooks/session-stop-replay.jsonl:2:{"message":{"role":"assistant","usage":{"input_tokens":120,"output_tokens":60,"cache_creation_input_tokens":40,"cache_read_input_tokens":20},"model":"claude-sonnet-4-6","content":"Updated the producer-side continuity packet."}}
.opencode/skills/system-spec-kit/mcp_server/tests/fixtures/hooks/session-stop-replay.jsonl:3:{"message":{"role":"assistant","usage":{"input_tokens":80,"output_tokens":40},"content":"Next I will wire replay isolation and idempotency coverage."}}

codex
The first pass found one central MCP response wrapper and several narrower budget helpers. I’m tightening the search now so the answer separates actual enforcement paths from tests/docs and generic `limit` handling.
exec
/bin/zsh -lc "rg -n \"getTokenBudget|tokenBudget|Token budget|token budget|budgetTruncated|truncateToTokenBudget|SESSION_PRIME_TOKEN_BUDGET|COMPACTION_TOKEN_BUDGET|DYNAMIC_TOKEN_BUDGET|dynamic-token-budget|confidence truncation|truncateByConfidence|MAX_PROMPT_BYTES|tokensConsumed\" .opencode/skills/system-spec-kit/mcp_server --glob '"'!tests/**'"' --glob '"'!**/*.md'"'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:65:import { getTokenBudget } from './lib/architecture/layer-definitions.js';
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1115:    // Token Budget Hybrid: Inject tokenBudget into response metadata (CHK-072)
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1116:    // T205: Enforce per-layer token budgets with actual truncation
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1139:          const budget = getTokenBudget(name);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1140:          meta.tokenBudget = budget;
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1163:                envelope.hints.push(`Token budget enforced: truncated ${originalCount} → ${innerResults.length} results to fit ${budget} token budget`);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1165:              meta.tokenBudgetTruncated = true;
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1171:                envelope.hints.push(`Response exceeds token budget (${meta.tokenCount}/${budget})`);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1178:        // Non-JSON response, skip token budget injection
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:222:  description: '[L2:Core] Index a spec document or constitutional file into the spec kit memory database. Reads the file, extracts metadata (title, trigger phrases), generates embedding, and stores in the index. Routed saves write continuity into canonical spec documents (decision-record.md, implementation-summary.md, handover.md). Includes pre-flight validation (T067-T070) for anchor format, duplicate detection, and token budget estimation. Token Budget: 3500.',
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:223:  inputSchema: { type: 'object', additionalProperties: false, properties: { filePath: { type: 'string', minLength: 1, description: 'Absolute path to a spec document under specs/**/ or .opencode/specs/**/ (spec.md, plan.md, tasks.md, checklist.md, decision-record.md, implementation-summary.md, handover.md, research.md, resource-map.md, description.json, graph-metadata.json) or a constitutional memory under .opencode/skills/*/constitutional/' }, force: { type: 'boolean', default: false, description: 'Force re-index even if content hash unchanged' }, dryRun: { type: 'boolean', default: false, description: 'Validate only without saving. Returns validation results including anchor format, duplicate check, and token budget estimation (CHK-160)' }, skipPreflight: { type: 'boolean', default: false, description: 'Skip pre-flight validation checks (not recommended)' }, asyncEmbedding: { type: 'boolean', default: false, description: 'When true, embedding generation is deferred for non-blocking saves. The spec-doc record is immediately saved with pending status and an async background attempt is triggered. Default false preserves synchronous embedding behavior.' }, routeAs: { type: 'string', enum: ['narrative_progress', 'narrative_delivery', 'decision', 'handover_state', 'research_finding', 'task_update', 'metadata_only', 'drop'], description: 'Optional routing override hint for canonical continuity saves.' }, mergeModeHint: { type: 'string', enum: ['append-as-paragraph', 'insert-new-adr', 'append-table-row', 'update-in-place', 'append-section'], description: 'Optional merge-mode hint for routed canonical continuity saves.' }, tenantId: { type: 'string', description: 'Tenant boundary for governed ingest.' }, userId: { type: 'string', description: 'User boundary for governed ingest.' }, agentId: { type: 'string', description: 'Agent boundary for governed ingest.' }, sessionId: { type: 'string', description: 'Session boundary for governed ingest.' }, provenanceSource: { type: 'string', description: 'Required provenance source when governed ingest validation applies.' }, provenanceActor: { type: 'string', description: 'Required provenance actor when governed ingest validation applies.' }, governedAt: { type: 'string', description: 'ISO timestamp for governed ingest. Defaults to now when omitted.' }, retentionPolicy: { type: 'string', enum: ['keep', 'ephemeral'], description: 'Retention class applied to the saved spec-doc record.' }, deleteAfter: { type: 'string', description: 'Optional ISO timestamp after which retention sweep may delete the spec-doc record.' } }, required: ['filePath'] },
.opencode/skills/system-spec-kit/mcp_server/tool-schemas.ts:630:      budgetTokens: { type: 'number', minimum: 100, maximum: 4000, default: 1200, description: 'Token budget for response' },
.opencode/skills/system-spec-kit/mcp_server/lib/session/session-snapshot.ts:36: * Token budget: 250-400 tokens (hard ceiling 500 including guidance).
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:4:// Distributes a total token budget across multiple context sources
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:44: * Allocate token budget across sources.
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:95:// Token budgets for dual-scope lifecycle hooks (TM-05)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:97:const COMPACTION_TOKEN_BUDGET = 4000;
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:252:  tokenBudget: number,
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:262:  const budgetLimit = Number.isFinite(tokenBudget) && tokenBudget > 0
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:263:    ? tokenBudget
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:289:      `[SK-004] Auto-surface output exceeded ${hookName} token budget ` +
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:296:    `[SK-004] Auto-surface output truncated to fit ${hookName} token budget ` +
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:367:  tokenBudget: number = TOOL_DISPATCH_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:411:    }, tokenBudget, hookName);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:587: * Token budget: TOOL_DISPATCH_TOKEN_BUDGET (4000 max)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:614:  // Delegate to the core surface function; token budget is explicitly
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:634: * Token budget: COMPACTION_TOKEN_BUDGET (4000 max)
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:654:  // Delegate to the core surface function; token budget is explicitly
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:656:  return autoSurfaceMemories(sessionContext.trim(), COMPACTION_TOKEN_BUDGET, 'compaction');
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:668:  COMPACTION_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:137:  budgetTruncated: boolean;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:639:  let budgetTruncated = false;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:669:    if (meta.budgetTruncated === true || meta.truncated === true) {
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:670:      budgetTruncated = true;
.opencode/skills/system-spec-kit/mcp_server/formatters/search-results.ts:725:    budgetTruncated,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:14:  SESSION_PRIME_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:15:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:116:    SESSION_PRIME_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:160:    const additionalContext = truncateToTokenBudget(
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:77:/** Result of token budget check */
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:234:  // Token budget estimation (~4 chars/token — harmonized with quality-loop.ts)
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:630:    result.warnings.push('No content provided for token budget check');
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:651:      message: `Content exceeds token budget: ${estimated} tokens (max: ${maxTokens})`,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:659:      message: `Content is ${Math.round(result.percentage_used * 100)}% of token budget (${estimated}/${maxTokens} tokens)`,
.opencode/skills/system-spec-kit/mcp_server/lib/validation/preflight.ts:815:  // 3. Token budget estimation
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:11:  parseHookStdin, hookLog, formatHookOutput, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:12:  withTimeout, HOOK_TIMEOUT_MS, COMPACTION_TOKEN_BUDGET, SESSION_PRIME_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:362:      budget = COMPACTION_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:366:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:370:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:374:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:378:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:391:  const output = truncateToTokenBudget(formatHookOutput(sections), adjustedBudget);
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/startup-brief.ts:222:    // Keep startup highlights small by default so graph context stays useful without crowding the token budget.
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:57:/** Truncate text to fit within a token budget */
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:531: * Format sections into compact text brief within token budget.
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:10:/** Token budget for compaction context injection */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:11:export const COMPACTION_TOKEN_BUDGET = 4000;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:12:/** Token budget for session priming (startup/resume) */
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:13:export const SESSION_PRIME_TOKEN_BUDGET = 2000;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96:export function truncateToTokenBudget(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:100:  return text.slice(0, maxChars) + '\n[...truncated to fit token budget]';
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:13:  parseHookStdin, hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:14:  withTimeout, HOOK_TIMEOUT_MS, COMPACTION_TOKEN_BUDGET, getRequiredSessionId,
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:286:  const merged = mergeCompactBrief(mergeInput, COMPACTION_TOKEN_BUDGET, undefined, selection);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:371:  return mergeCompactBrief(mergeInput, COMPACTION_TOKEN_BUDGET, undefined, selection).payloadContract;
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:396:    payload = truncateToTokenBudget(mergedContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:425:    payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:11:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:114:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:123:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:147:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:162:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:170:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:178:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:185:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:212:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:225:    const out = truncateByConfidence(results, { minResults: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:233:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:260:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:267:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:274:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:291:    const out = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:300:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:308:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:317:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:342:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:358:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:418:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:428:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:437:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:447:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:13:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:16:  COMPACTION_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:230:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:14:  hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:15:  withTimeout, HOOK_TIMEOUT_MS, COMPACTION_TOKEN_BUDGET, getRequiredSessionId,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:142:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:14:const DEFAULT_MAX_PROMPT_BYTES = 64 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:534:    expect(Buffer.byteLength(payload, 'utf8')).toBeLessThanOrEqual(DEFAULT_MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:19:  hookLog, formatHookOutput, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:21:  withTimeout, HOOK_TIMEOUT_MS, COMPACTION_TOKEN_BUDGET, SESSION_PRIME_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:280:      budget = COMPACTION_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:288:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:292:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:296:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:304:      budget = SESSION_PRIME_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:307:  const rawOutput = truncateToTokenBudget(formatHookOutput(sections), budget);
.opencode/skills/system-spec-kit/mcp_server/lib/errors/recovery-hints.ts:566:    hint: 'Memory file exceeds token budget limit.',
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:16:  hookLog, truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:17:  withTimeout, HOOK_TIMEOUT_MS, COMPACTION_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:92:  const rawOutput = truncateToTokenBudget(sections.join('\n'), COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1265:describe('P1 post-ranking truncation and token budget regressions', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1271:    SPECKIT_DYNAMIC_TOKEN_BUDGET: process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1287:  it('T024: co-activation promotion happens before confidence truncation drops tail candidates', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1292:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'false';
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1432:    SPECKIT_DYNAMIC_TOKEN_BUDGET: process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1483:  it('S1-FIX-03: dynamic token budget is applied to live hybrid results', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1485:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1504:      | { tokenBudget?: { budget?: number; applied?: boolean } }
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1507:    expect(s3meta?.tokenBudget?.applied).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1508:    expect(s3meta?.tokenBudget?.budget).toBe(1500);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1514:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1541:      budgetTruncated: false,
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:100:      "expectedResultDescription": "Should surface system-spec-kit spec documents and memories about the L1/L2/L3/L4/L5/L6/L7 layer design, token budgets per layer, and original design rationale.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:265:      "query": "what rationale drove the token budget assignments per MCP layer",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:270:      "expectedResultDescription": "Should surface system-spec-kit SKILL.md section on L1-L7 token budgets (2000, 1500, 800, 500, 600, 1200, 1000) and any decision record explaining their sizing.",
.opencode/skills/system-spec-kit/mcp_server/lib/eval/data/ground-truth.json:695:      "query": "SPECKIT_PRESSURE_POLICY token budget downgrade",
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:214: * Compute token budget quality sub-score.
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:244:  const tokenBudget = Math.floor(charBudget / CHARS_PER_TOKEN);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:245:  issues.push(`Content exceeds token budget: ~${Math.ceil(charCount / CHARS_PER_TOKEN)} tokens (budget: ${tokenBudget})`);
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:430: * - Trim content to token budget
.opencode/skills/system-spec-kit/mcp_server/handlers/quality-loop.ts:461:  const hasBudgetIssue = issues.some(i => /token budget/i.test(i));
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:354:  it('quick tokenBudget is 800', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:356:    expect(memoryContext.CONTEXT_MODES.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:359:  it('deep tokenBudget is 3500', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:361:    expect(memoryContext.CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:364:  it('focused tokenBudget is 3000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:366:    expect(memoryContext.CONTEXT_MODES.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:369:  it('resume tokenBudget is 2000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:371:    expect(memoryContext.CONTEXT_MODES.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:374:  it('auto has no tokenBudget (delegates to sub-strategy)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-helpers.vitest.ts:376:    expect(memoryContext.CONTEXT_MODES.auto.tokenBudget).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/pressure-monitor.vitest.ts:36:    const result = getPressureLevel(undefined, { tokenCount: 1300, tokenBudget: 2000 });
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:9:import { truncateToTokenBudget, COMPACTION_TOKEN_BUDGET } from '../hooks/claude/shared.js';
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:56:  describe('token budget enforcement', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:59:      const truncated = truncateToTokenBudget(largePayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:66:      const result = truncateToTokenBudget(smallPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:166:    it('token budget within limits', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:175:    it('token budget exceeded detected', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:184:    it('token budget warning generated', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/preflight.vitest.ts:662:    it('T166: token budget warning at 80% threshold', () => {
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:76:  readonly tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:110:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:132:/** T205: Token budget enforcement metadata */
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:451:   Enforces per-layer/per-mode token budgets by estimating the
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:457: * T205: Enforce token budget on strategy results.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:486:  // 71-token payload against a 3000-token budget was nuked to count:0,results:[].
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:558:          summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:570:          summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:587:        summary: 'Context truncated to fit token budget',
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:898:    tokenBudget: 800
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:906:    tokenBudget: 3500
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:914:    tokenBudget: 3000
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:922:    tokenBudget: 2000
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1316:    tokenBudget: effectiveBudget,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1317:    tokenBudgetEnforcement: enforcement,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1521:  const tokenBudget = layerInfo?.tokenBudget ?? 2000;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1524:    tokenBudget,
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1691:  // T205: Determine effective token budget from mode or layer definitions
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1692:  const modeTokenBudget = CONTEXT_MODES[effectiveMode]?.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1693:  const effectiveBudget = modeTokenBudget || tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1696:  // so the final response respects the advertised token budget.
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1718:  // T205: Enforce token budget AFTER all context injection
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1762:      ? `Context retrieved via ${effectiveMode} mode (${tracedResult.strategy} strategy) [truncated${enforcement.originalResultCount !== undefined ? `: ${enforcement.originalResultCount} → ${enforcement.returnedResultCount} results` : ''} to fit ${effectiveBudget} token budget]`
.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:1768:      `Token budget: ${effectiveBudget} (${effectiveMode} mode)`,
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:106:  it('T066: adjusted token budget reserves header overhead and avoids overflow after injection', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:3:// Validates latency ceiling, token budget, feature flag regression.
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:40:    tokensConsumed: number;
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:163:      tokensConsumed: Math.ceil(payload.length / 4),
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:195:  // ---- T2: Token budget respected ----
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:200:    expect(response.metrics.tokensConsumed).toBeLessThanOrEqual(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/integration-138-pipeline.vitest.ts:280:    expect(response.metrics).toHaveProperty('tokensConsumed');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:17:    it('T205-A1: All layer token budgets correct', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:40:        const actual = layerDefs.getTokenBudget(tool);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:46:      const budget = layerDefs.getTokenBudget('nonexistent_tool');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:50:    it('T205-A3: All 7 layers have positive token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:53:        expect((layer as { tokenBudget: number }).tokenBudget, `${id} should have positive budget`).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:271:      expect(serverSrc).toContain('tokenBudgetTruncated');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:284:    it('T205-C4: Uses getTokenBudget for layer-specific budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:289:      expect(serverSrc).toContain('getTokenBudget(name)');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:301:      expect(modes.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:302:      expect(modes.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:303:      expect(modes.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:304:      expect(modes.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:311:      expect(modes.auto.tokenBudget).toBeUndefined();
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:318:      const quickBudget = modes.quick.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:319:      const resumeBudget = modes.resume.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:320:      const focusedBudget = modes.focused.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:321:      const deepBudget = modes.deep.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/runtime-routing.vitest.ts:79:    it('what is the purpose of the token budget', () => { expect(classifyQueryIntent('what is the purpose of the token budget').intent).toBe('semantic'); });
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:37:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:78:  tokenBudget: number,
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:107:    if (estimateTokenCount(hint) > tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:110:      return estimateTokenCount(trimmed) <= tokenBudget ? [trimmed] : [];
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:148: * @param options      - Deadline and token budget overrides
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:157:  const tokenBudget = options?.tokenBudget ?? DEFAULT_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:172:      const graphHints = await enrichWithCodeGraphSymbols(paths, tokenBudget - tokensUsed);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:175:        if (tokensUsed + cost > tokenBudget) break;
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:182:    if (Date.now() - startTime < deadlineMs && tokensUsed < tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:186:        if (tokensUsed + cost > tokenBudget) break;
.opencode/skills/system-spec-kit/mcp_server/tests/compact-merger.vitest.ts:28:    it('respects total token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:41:  getTokenBudget?: (toolName: string) => number
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:745:        getTokenBudget: vi.fn(() => 1000),
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:748:        getTokenBudget: vi.fn(() => 1000),
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1693:            meta: { tool: 'checkpoint_list', tokenCount: 10, cacheHit: false, tokenBudget: 1000 },
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1712:      expect(parsed.meta.tokenBudget).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1716:    it('T000j: final tokenCount matches the serialized envelope after hints and tokenBudget injection', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1730:            meta: { tool: 'memory_list', tokenCount: 1, tokenBudget: 1000, cacheHit: false },
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:1741:      expect(finalText).toContain('"tokenBudget": 1000')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2129:    // T26: Source injects tokenBudget into response metadata
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2130:    it('T26: Token budget injection exists', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2131:      expect(sourceCode).toMatch(/getTokenBudget\(name\)/)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2135:    it('T27: Token budget overflow detection', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2139:    // T28: getTokenBudget direct tests
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2144:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2145:      expect(layerDefs!.getTokenBudget!('memory_context')).toBe(3500)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2152:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2153:      expect(layerDefs!.getTokenBudget!('memory_search')).toBe(3500)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2160:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2161:      expect(layerDefs!.getTokenBudget!('memory_list')).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2168:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2169:      expect(layerDefs!.getTokenBudget!('nonexistent_tool')).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2176:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2177:      expect(layerDefs!.getTokenBudget!('memory_delete')).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2184:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2185:      expect(layerDefs!.getTokenBudget!('checkpoint_create')).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2192:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2193:      expect(layerDefs!.getTokenBudget!('memory_drift_why')).toBe(1500)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2200:      expect(layerDefs?.getTokenBudget).toBeTypeOf('function')
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2201:      expect(layerDefs!.getTokenBudget!('memory_index_scan')).toBe(1000)
.opencode/skills/system-spec-kit/mcp_server/tests/context-server.vitest.ts:2650:    it('T62: Token budgets in descriptions', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:209:// D. Token Budget with Results (S1 — PI-A3 token budget)
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:12:  getTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:81:describe('getTokenBudget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:94:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:95:    expect(getTokenBudget()).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:100:    expect(getTokenBudget()).toBe(5000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:105:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:108:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:111:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:263:    // With undefined budget — should use getTokenBudget()
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:5:// - Token budget constants (4000 max per point)
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:27:  COMPACTION_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:63:  it('COMPACTION_TOKEN_BUDGET is 4000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:64:    expect(COMPACTION_TOKEN_BUDGET).toBe(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:69:    expect(typeof COMPACTION_TOKEN_BUDGET).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:74:    expect(COMPACTION_TOKEN_BUDGET).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:542:describe('TM-05: Token budget enforcement (4000 max per point)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:547:  it('COMPACTION_TOKEN_BUDGET does not exceed 4000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:548:    expect(COMPACTION_TOKEN_BUDGET).toBeLessThanOrEqual(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:586:  it('tool-dispatch output boundary enforces estimated token budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:609:  it('compaction output boundary enforces estimated token budget', async () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:629:    expect(estimatedTokens).toBeLessThanOrEqual(COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:715:  it('COMPACTION_TOKEN_BUDGET is exported', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/dual-scope-hooks.vitest.ts:716:    expect(COMPACTION_TOKEN_BUDGET).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:19:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:44:      const requiredFields = ['id', 'name', 'description', 'tokenBudget', 'priority', 'useCase', 'tools'];
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:72:    it('T06: Token budgets are positive numbers', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:74:        const budget = layer.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:88:    it('T08: Specific token budget values match', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:93:        expect(LD[layerId]?.tokenBudget).toBe(expected);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:258:  // 4.5 getTokenBudget()
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:260:  describe('getTokenBudget()', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:262:    it('T20: Known tools return correct token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:273:        expect(mod.getTokenBudget(tool)).toBe(expected);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:278:      expect(mod.getTokenBudget('nonexistent_tool')).toBe(1000);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:282:      expect(typeof mod.getTokenBudget('memory_context')).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:283:      expect(typeof mod.getTokenBudget('fake_tool')).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:296:      expect(info.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:314:      const requiredFields = ['id', 'name', 'description', 'tokenBudget', 'priority', 'useCase', 'tools'];
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:17:  truncateToTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:18:  SESSION_PRIME_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:19:  COMPACTION_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:209:      const truncated = truncateToTokenBudget(output, SESSION_PRIME_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:211:      expect(truncated.length / 4).toBeLessThanOrEqual(SESSION_PRIME_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:216:      const truncated = truncateToTokenBudget(longPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:217:      expect(truncated.length / 4).toBeLessThanOrEqual(COMPACTION_TOKEN_BUDGET + 50);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:16:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:22:const FLAG = 'SPECKIT_DYNAMIC_TOKEN_BUDGET';
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:50:describe('T030-01: Feature Flag (SPECKIT_DYNAMIC_TOKEN_BUDGET)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:48:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:108:  it('T003: quick mode has triggers strategy and 800 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:111:    expect(quickMode.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:114:  it('T004: deep mode has search strategy and 3500 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:117:    expect(deepMode.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:120:  it('T005: focused mode has intent-search strategy and 3000 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:123:    expect(focusedMode.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:126:  it('T006: resume mode has resume strategy and 2000 token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:129:    expect(resumeMode.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:151:  it('T009: Non-auto modes have token budgets', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:154:        expect(typeof mode.tokenBudget).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:155:        expect(mode.tokenBudget!).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:160:  it('T010: Token budgets are reasonable (500-4000 range)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:162:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:163:        expect(mode.tokenBudget).toBeGreaterThanOrEqual(500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:164:        expect(mode.tokenBudget).toBeLessThanOrEqual(4000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:405:  it('T034: Quick mode token budget is 800', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:406:    expect(CONTEXT_MODES.quick.tokenBudget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:416:  it('T036: Quick mode has smallest token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:418:      .filter(([_k, v]: [string, ContextMode]) => v.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:419:      .map(([_k, v]: [string, ContextMode]) => v.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:421:    expect(CONTEXT_MODES.quick.tokenBudget).toBe(minBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:451:    expect(quick.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:473:  it('T044: Deep mode token budget is 3500', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:474:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:477:  it('T045: Deep mode has highest token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:479:      .filter(([_k, v]: [string, ContextMode]) => v.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:480:      .map(([_k, v]: [string, ContextMode]) => v.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:482:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(maxBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:506:    expect(deep.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:528:  it('T054: Focused mode token budget is 3000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:529:    expect(CONTEXT_MODES.focused.tokenBudget).toBe(3000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:533:    const focusedBudget: number = CONTEXT_MODES.focused.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:534:    const quickBudget: number = CONTEXT_MODES.quick.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:535:    const deepBudget: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:563:    expect(focused.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:587:  it('T064: Resume mode token budget is 2000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:588:    expect(CONTEXT_MODES.resume.tokenBudget).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:592:    const resumeBudget: number = CONTEXT_MODES.resume.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:593:    const deepBudget: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:624:    expect(resume.tokenBudget).toBeDefined();
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:648:  it('T074: Auto mode has no fixed token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:649:    const autoBudget: number | undefined = CONTEXT_MODES.auto.tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:719:  it('T084: CHK-072 - L1 token budget is 3500 (from layer-definitions)', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:721:    expect(CONTEXT_MODES.deep.tokenBudget).toBe(3500);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:730:  it('T086: Token budgets follow expected hierarchy', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:731:    const quick: number = CONTEXT_MODES.quick.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:732:    const resume: number = CONTEXT_MODES.resume.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:733:    const focused: number = CONTEXT_MODES.focused.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:734:    const deep: number = CONTEXT_MODES.deep.tokenBudget!;
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:741:  it('T087: Total defined token budgets are reasonable', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:743:      .filter((m: ContextMode) => m.tokenBudget !== undefined)
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:744:      .map((m: ContextMode) => m.tokenBudget!);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:750:  it('T088: Each non-auto mode has explicit token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:753:        expect(typeof mode.tokenBudget).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:758:  it('T089: Token budgets are whole numbers', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:760:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:761:        expect(Number.isInteger(mode.tokenBudget)).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:766:  it('T090: Token budgets are positive', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:768:      if (mode.tokenBudget !== undefined) {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:769:        expect(mode.tokenBudget).toBeGreaterThan(0);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1007:  it('T209: Each mode token budget matches CONTEXT_MODES definition', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context.vitest.ts:1017:      expect(mode.tokenBudget).toBe(budget);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:313:// ── Test 8: MAX_PROMPT_BYTES=10KB truncation ─────────────────
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:315:describe('local-reranker MAX_PROMPT_BYTES truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:317:    const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:323:    expect(Buffer.byteLength(prompt, 'utf8')).toBeGreaterThan(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:327:    let end = MAX_PROMPT_BYTES;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:331:    expect(Buffer.byteLength(boundedPrompt, 'utf8')).toBeLessThanOrEqual(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:340:    const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:344:    const asciiPadding = 'a'.repeat(MAX_PROMPT_BYTES - 8); // 8 bytes short
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:348:    expect(Buffer.byteLength(prompt, 'utf8')).toBeGreaterThan(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:352:    let end = MAX_PROMPT_BYTES;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:360:    expect(Buffer.byteLength(boundedPrompt, 'utf8')).toBeLessThanOrEqual(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:45:// --- T007: Token budget ---
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:50:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:585:describe('T007: Token budget estimation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:586:  const originalEnv = process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:591:      delete process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET;
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:593:      process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = originalEnv;
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:598:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'false';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:611:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:624:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:635:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:309:    it('T524-5: Each mode has correct token budget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:321:        expect(mode.tokenBudget).toBe(expectedBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:406:      // L1 token budget is 3500 — need ~0.8*3500=2800 tokens (~11200 chars) for quick pressure
.opencode/skills/system-spec-kit/mcp_server/tests/handler-memory-context.vitest.ts:430:        tokenBudget: 0,
.opencode/skills/system-spec-kit/mcp_server/lib/scoring/importance-tiers.ts:158:// Get maximum token budget for tier (null = unlimited)
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:17:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:69:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:150:      setEnv('SPECKIT_DYNAMIC_TOKEN_BUDGET', 'false');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:161:      // Token budget returns default
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:183:      const truncated = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:190:      setEnv('SPECKIT_DYNAMIC_TOKEN_BUDGET', 'true');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:201:      // Token budget resolves correctly
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:226:      const truncResult = truncateByConfidence(scoredResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:236:      clearEnv('SPECKIT_DYNAMIC_TOKEN_BUDGET');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:273:    it('4. Query classifier feeds token budget: simple → 1500, complex → 4000', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:275:      setEnv('SPECKIT_DYNAMIC_TOKEN_BUDGET', 'true');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:360:      const truncResult = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:448:      const emptyTrunc = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:483:      const singleTrunc = truncateByConfidence([{ id: 1, score: 0.9 }]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:513:      const truncResult = truncateByConfidence(tiedResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:574:      setEnv('SPECKIT_DYNAMIC_TOKEN_BUDGET', 'true');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:582:      // Step 2: Get token budget
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:626:      const truncated = truncateByConfidence(scored);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:98:describe('edge-cases: truncateToTokenBudget', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:100:    const { truncateToTokenBudget } = await import('../hooks/claude/shared.js');
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:102:    expect(truncateToTokenBudget(short, 1000)).toBe(short);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:106:    const { truncateToTokenBudget } = await import('../hooks/claude/shared.js');
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:108:    const result = truncateToTokenBudget(long, 100);
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:7:  tokenBudget?: number;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:45:  const { tokenCount, tokenBudget } = runtimeContextStats;
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:49:    typeof tokenBudget !== 'number' ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:50:    !Number.isFinite(tokenBudget) ||
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:51:    tokenBudget <= 0
.opencode/skills/system-spec-kit/mcp_server/lib/cognitive/pressure-monitor.ts:56:  return clampToRatio(tokenCount / tokenBudget);
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-response-envelope.vitest.ts:125:                budgetTruncated: true,
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-response-envelope.vitest.ts:167:    expect(result.trace?.budgetTruncated).toBe(true);
.opencode/skills/system-spec-kit/mcp_server/tests/memory-context-session-state.vitest.ts:25:      getLayerInfo: vi.fn(() => ({ tokenBudget: 2000 })),
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:25:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:32:// T007: Dynamic token budget
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:37:} from '../lib/search/dynamic-token-budget';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:49:    SPECKIT_DYNAMIC_TOKEN_BUDGET: process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET,
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:225:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:244:    const output = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:260:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:280:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:294:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:307:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'true';
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:329:    process.env.SPECKIT_DYNAMIC_TOKEN_BUDGET = 'false';
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:16:  tokenBudget: number;
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:47:    tokenBudget: 3500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:56:    tokenBudget: 3500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:65:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:74:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:83:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:92:    tokenBudget: 1500,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:114:    tokenBudget: 1000,
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:177:   CHK-072: Token budgets assigned per layer.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:181: * Get the token budget for a tool.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:187:  return LAYER_DEFINITIONS[layerId].tokenBudget;
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:191: * Get the token budget for a tool.
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:193:export function getTokenBudget(toolName: string): number {
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:247:    lines.push(`**Token Budget:** ${layer.tokenBudget}`);
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:93:/** Content that exceeds token budget */
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:197:    expect(result.issues[0]).toMatch(/exceeds token budget/i);
.opencode/skills/system-spec-kit/mcp_server/tests/quality-loop.vitest.ts:416:    const result = attemptAutoFix(oversized, metadata, ['Content exceeds token budget']);
.opencode/skills/system-spec-kit/mcp_server/lib/chunking/anchor-chunker.ts:57:/** Maximum chunk size — hard cap to stay under embedding token budget */
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:182: * Dynamic token budget allocation by query complexity.
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:183: * Default: TRUE (graduated). Set SPECKIT_DYNAMIC_TOKEN_BUDGET=false to disable.
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts:186:  return isFeatureEnabled('SPECKIT_DYNAMIC_TOKEN_BUDGET');
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:38:  truncateByConfidence,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:47:} from './dynamic-token-budget.js';
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:183:  /** Dynamic token budget result (SPECKIT_DYNAMIC_TOKEN_BUDGET). */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:184:  tokenBudget?: {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1062:    // -- Stage E: Dynamic Token Budget (SPECKIT_DYNAMIC_TOKEN_BUDGET) --
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1067:      s3meta.tokenBudget = {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1592:      const truncationResult: TruncationResult = truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1612:      console.warn('[hybrid-search] confidence truncation failed:', err instanceof Error ? err.message : String(err));
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1636:          // Wire confidence truncation metadata into per-result trace (036)
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1661:  let budgetTruncated = false;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1666:    // Apply token budget truncation after trace/header enrichment so token
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1673:    if (s3meta.tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1674:      s3meta.tokenBudget.headerOverhead = headerOverhead;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1675:      s3meta.tokenBudget.adjustedBudget = adjustedBudget;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1683:    budgetTruncated = budgeted.truncated;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1698:          budgetTruncated,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2257:/** Default token budget — configurable via SPECKIT_TOKEN_BUDGET env var. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2359: * Read the configured token budget from SPECKIT_TOKEN_BUDGET env var,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2361: * @returns The effective token budget for result truncation.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2363:function getTokenBudget(): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2373: * Create a summary fallback for a single result whose content exceeds the token budget.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2392: * Truncate a result set to fit within a token budget using greedy highest-scoring-first strategy.
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2394: * @param budget - Optional token budget override (defaults to SPECKIT_TOKEN_BUDGET env / 2000).
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2403:  const effectiveBudget = (budget && budget > 0) ? budget : getTokenBudget();
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2446:      `[hybrid-search] Token budget overflow (single-result fallback): ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2483:      `[hybrid-search] Token budget overflow (top-result fallback): ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2500:    `[hybrid-search] Token budget overflow: ${totalTokens} tokens > ${effectiveBudget} budget, ` +
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2534:  // Token budget validation
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2538:  getTokenBudget,
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2555:  // Token budget types
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:50:const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:298:          if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:300:            let end = MAX_PROMPT_BYTES;
.opencode/skills/system-spec-kit/mcp_server/lib/search/hyde.ts:218: * @param maxTokens - Token budget passed to the LLM.
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:5:// ADVISORY-ONLY: This module computes a token budget for a query
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:13:// Feature catalog: Dynamic token budget allocation
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:28:/** Result of a token budget lookup. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:32:  /** The allocated token budget. */
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:55: * Get the token budget for a given query complexity tier.
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:57: * When SPECKIT_DYNAMIC_TOKEN_BUDGET is disabled (default), returns the DEFAULT_BUDGET
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:102:function truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:214:  truncateByConfidence,

exec
/bin/zsh -lc "rg -n \"function getTokenBudget|const getTokenBudget|export function getTokenBudget|function truncateToTokenBudget|export function truncateToTokenBudget|export function truncateByConfidence|export function getDynamicTokenBudget|MAX_PROMPT_BYTES\" .opencode/skills/system-spec-kit/mcp_server --glob '"'!tests/**'"' --glob '"'!**/*.md'"'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:14:const DEFAULT_MAX_PROMPT_BYTES = 64 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/spec-kit-skill-advisor-plugin.vitest.ts:534:    expect(Buffer.byteLength(payload, 'utf8')).toBeLessThanOrEqual(DEFAULT_MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96:export function truncateToTokenBudget(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:313:// ── Test 8: MAX_PROMPT_BYTES=10KB truncation ─────────────────
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:315:describe('local-reranker MAX_PROMPT_BYTES truncation', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:317:    const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:323:    expect(Buffer.byteLength(prompt, 'utf8')).toBeGreaterThan(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:327:    let end = MAX_PROMPT_BYTES;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:331:    expect(Buffer.byteLength(boundedPrompt, 'utf8')).toBeLessThanOrEqual(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:340:    const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:344:    const asciiPadding = 'a'.repeat(MAX_PROMPT_BYTES - 8); // 8 bytes short
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:348:    expect(Buffer.byteLength(prompt, 'utf8')).toBeGreaterThan(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:352:    let end = MAX_PROMPT_BYTES;
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts:360:    expect(Buffer.byteLength(boundedPrompt, 'utf8')).toBeLessThanOrEqual(MAX_PROMPT_BYTES);
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:193:export function getTokenBudget(toolName: string): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2363:function getTokenBudget(): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:50:const MAX_PROMPT_BYTES = 10 * 1024;
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:298:          if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:300:            let end = MAX_PROMPT_BYTES;

exec
/bin/zsh -lc "rg --files .opencode/skills/system-spec-kit/mcp_server | rg '(token|budget|truncat|envelope|hook-session|reranker|search-flags)'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/formatters/token-metrics.ts
.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/reranker-eval-comparison.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-stop-replay.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/retry-budget.ts
.opencode/skills/system-spec-kit/mcp_server/tests/provenance-envelope.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/token-snapshot-store.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/search-flags.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/context-server-error-envelope.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/budget-allocator.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/session-token-resume.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/mmr-reranker.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/hook-stop-token-tracking.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/reranker.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/_support/token-budget-assertions.ts
.opencode/skills/system-spec-kit/mcp_server/tests/envelope.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-flags.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/local-reranker.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/mcp-response-envelope.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts
.opencode/skills/system-spec-kit/mcp_server/lib/search/search-flags.ts
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts
.opencode/skills/system-spec-kit/mcp_server/lib/search/reranker.ts
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts
.opencode/skills/system-spec-kit/mcp_server/tests/retry-budget-telemetry.vitest.ts

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts | sed -n '1,215p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Layer Definitions
     3	// ───────────────────────────────────────────────────────────────
     4	// Feature catalog: 7-layer tool architecture metadata
     5	// LIB: LAYER DEFINITIONS
     6	// 7-Layer MCP Architecture with Token Budgets
     7	// ───────────────────────────────────────────────────────────────
     8	// 1. LAYER TYPES
     9	
    10	// ───────────────────────────────────────────────────────────────
    11	/** Individual layer definition in the 7-layer architecture */
    12	export interface LayerDefinition {
    13	  id: string;
    14	  name: string;
    15	  description: string;
    16	  tokenBudget: number;
    17	  priority: number;
    18	  useCase: string;
    19	  tools: string[];
    20	}
    21	
    22	/** Layer ID string literal union */
    23	export type LayerId = 'L1' | 'L2' | 'L3' | 'L4' | 'L5' | 'L6' | 'L7';
    24	
    25	/** Task type for layer recommendations */
    26	export type TaskType = 'search' | 'browse' | 'modify' | 'checkpoint' | 'analyze' | 'maintenance' | 'default';
    27	
    28	/* ───────────────────────────────────────────────────────────────
    29	   2. LAYER CONSTANTS
    30	
    31	   REQ-020: Layered Tool Organization (L1-L7 structure)
    32	
    33	   Design Principles:
    34	   - Progressive disclosure: Start with high-level, drill down as needed
    35	   - Token efficiency: Higher layers = fewer tokens, more targeted
    36	   - Cognitive load: Reduce choices at each decision point
    37	   ──────────────────────────────────────────────────────────────── */
    38	
    39	/**
    40	 * Defines the LAYER_DEFINITIONS constant.
    41	 */
    42	export const LAYER_DEFINITIONS: Record<LayerId, LayerDefinition> = {
    43	  L1: {
    44	    id: 'L1',
    45	    name: 'Orchestration',
    46	    description: 'Unified entry points with intent-aware routing. Start here for most tasks.',
    47	    tokenBudget: 3500,
    48	    priority: 1,
    49	    useCase: 'Default entry point for context retrieval. Automatically routes based on intent.',
    50	    tools: ['memory_context', 'session_resume', 'session_bootstrap']
    51	  },
    52	  L2: {
    53	    id: 'L2',
    54	    name: 'Core',
    55	    description: 'Primary memory operations. Use when you need specific search or save functionality.',
    56	    tokenBudget: 3500,
    57	    priority: 2,
    58	    useCase: 'Direct access to search, save, and trigger matching when L1 routing is not needed.',
    59	    tools: ['memory_search', 'memory_quick_search', 'memory_save', 'memory_match_triggers']
    60	  },
    61	  L3: {
    62	    id: 'L3',
    63	    name: 'Discovery',
    64	    description: 'Browse and explore the memory system. Use to understand what exists.',
    65	    tokenBudget: 1000,
    66	    priority: 3,
    67	    useCase: 'Explore available memories, check system health, view statistics.',
    68	    tools: ['memory_list', 'memory_stats', 'memory_health', 'session_health']
    69	  },
    70	  L4: {
    71	    id: 'L4',
    72	    name: 'Mutation',
    73	    description: 'Modify existing memories. Use to update, delete, or validate memories.',
    74	    tokenBudget: 1000,
    75	    priority: 4,
    76	    useCase: 'Make changes to existing memories when corrections or updates are needed.',
    77	    tools: ['memory_update', 'memory_delete', 'memory_validate', 'memory_bulk_delete']
    78	  },
    79	  L5: {
    80	    id: 'L5',
    81	    name: 'Lifecycle',
    82	    description: 'Checkpoint and version management. Use for state preservation and recovery.',
    83	    tokenBudget: 1000,
    84	    priority: 5,
    85	    useCase: 'Create checkpoints before major changes, restore previous states.',
    86	    tools: ['checkpoint_create', 'checkpoint_list', 'checkpoint_restore', 'checkpoint_delete']
    87	  },
    88	  L6: {
    89	    id: 'L6',
    90	    name: 'Analysis',
    91	    description: 'Deep inspection and causal analysis. Use to understand relationships and lineage.',
    92	    tokenBudget: 1500,
    93	    priority: 6,
    94	    useCase: 'Trace decision history, understand memory relationships, measure learning.',
    95	    tools: [
    96	      'memory_drift_why',
    97	      'memory_causal_link',
    98	      'memory_causal_stats',
    99	      'memory_causal_unlink',
   100	      'task_preflight',
   101	      'task_postflight',
   102	      'eval_run_ablation',
   103	      'eval_reporting_dashboard',
   104	      'code_graph_query',
   105	      'code_graph_context',
   106	      'detect_changes',
   107	      'skill_graph_query'
   108	    ]
   109	  },
   110	  L7: {
   111	    id: 'L7',
   112	    name: 'Maintenance',
   113	    description: 'System maintenance and bulk operations. Use for indexing and diagnostics.',
   114	    tokenBudget: 1000,
   115	    priority: 7,
   116	    useCase: 'Re-index memories, view learning history, perform bulk operations.',
   117	    tools: ['memory_index_scan', 'memory_get_learning_history', 'memory_ingest_start', 'memory_ingest_status', 'memory_ingest_cancel', 'code_graph_scan', 'code_graph_status', 'code_graph_verify', 'skill_graph_scan', 'skill_graph_status', 'skill_graph_validate', 'ccc_status', 'ccc_reindex', 'ccc_feedback']
   118	  }
   119	} as const;
   120	
   121	/* ───────────────────────────────────────────────────────────────
   122	   3. TOOL-TO-LAYER MAPPING
   123	
   124	   Maps each tool to its layer for quick lookup.
   125	   ──────────────────────────────────────────────────────────────── */
   126	
   127	/**
   128	 * Defines the TOOL_LAYER_MAP constant.
   129	 */
   130	export const TOOL_LAYER_MAP: Record<string, LayerId> = {} as Record<string, LayerId>;
   131	for (const [layerId, layer] of Object.entries(LAYER_DEFINITIONS)) {
   132	  for (const tool of layer.tools) {
   133	    (TOOL_LAYER_MAP as Record<string, string>)[tool] = layerId;
   134	  }
   135	}
   136	
   137	/* ───────────────────────────────────────────────────────────────
   138	   4. LAYER PREFIX GENERATOR
   139	
   140	   Generates description prefixes for tool descriptions.
   141	   Format: "[L#:Name] Original description..."
   142	   ──────────────────────────────────────────────────────────────── */
   143	
   144	/**
   145	 * Get the layer ID for a tool.
   146	 */
   147	export function getLayerForTool(toolName: string): LayerId | null {
   148	  return TOOL_LAYER_MAP[toolName] ?? null;
   149	}
   150	
   151	/**
   152	 * Get the layer prefix for a tool's description.
   153	 * CHK-073: Tool descriptions include layer prefix.
   154	 */
   155	export function getLayerPrefix(toolName: string): string {
   156	  const layerId = getLayerForTool(toolName);
   157	  if (!layerId) return '';
   158	
   159	  const layer = LAYER_DEFINITIONS[layerId];
   160	  return `[${layerId}:${layer.name}]`;
   161	}
   162	
   163	/**
   164	 * Enhance a tool description with layer information.
   165	 * CHK-073: Adds layer prefix to description.
   166	 */
   167	export function enhanceDescription(toolName: string, description: string): string {
   168	  const prefix = getLayerPrefix(toolName);
   169	  if (!prefix) return description;
   170	
   171	  return `${prefix} ${description}`;
   172	}
   173	
   174	/* ───────────────────────────────────────────────────────────────
   175	   5. TOKEN BUDGET HELPERS
   176	
   177	   CHK-072: Token budgets assigned per layer.
   178	   ──────────────────────────────────────────────────────────────── */
   179	
   180	/**
   181	 * Get the token budget for a tool.
   182	 */
   183	export function getLayerTokenBudget(toolName: string): number {
   184	  const layerId = getLayerForTool(toolName);
   185	  if (!layerId) return 1000; // Default budget
   186	
   187	  return LAYER_DEFINITIONS[layerId].tokenBudget;
   188	}
   189	
   190	/**
   191	 * Get the token budget for a tool.
   192	 */
   193	export function getTokenBudget(toolName: string): number {
   194	  return getLayerTokenBudget(toolName);
   195	}
   196	
   197	/**
   198	 * Get layer information for a tool.
   199	 */
   200	export function getLayerInfo(toolName: string): LayerDefinition | null {
   201	  const layerId = getLayerForTool(toolName);
   202	  if (!layerId) return null;
   203	
   204	  return { ...LAYER_DEFINITIONS[layerId] };
   205	}
   206	
   207	/**
   208	 * Get all layers in priority order.
   209	 */
   210	export function getLayersByPriority(): LayerDefinition[] {
   211	  return Object.values(LAYER_DEFINITIONS).sort((a, b) => a.priority - b.priority);
   212	}
   213	
   214	/**
   215	 * Get layer usage guidance based on task.

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/context-server.ts | sed -n '1100,1188p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
  1100	          }
  1101	        }
  1102	      } catch (enrichErr: unknown) {
  1103	        // Passive enrichment is strictly non-fatal
  1104	        const msg = enrichErr instanceof Error ? enrichErr.message : String(enrichErr);
  1105	        console.warn(`[context-server] Passive enrichment failed (non-fatal): ${msg}`);
  1106	      }
  1107	    }
  1108	
  1109	    // SK-004: Inject auto-surface hints before token-budget enforcement so
  1110	    // The final envelope metadata reflects the fully decorated response.
  1111	    if (autoSurfacedContext && result && !result.isError) {
  1112	      appendAutoSurfaceHints(result, autoSurfacedContext);
  1113	    }
  1114	
  1115	    // Token Budget Hybrid: Inject tokenBudget into response metadata (CHK-072)
  1116	    // T205: Enforce per-layer token budgets with actual truncation
  1117	    if (result && result.content && result.content[0]?.text) {
  1118	      try {
  1119	        const envelope = JSON.parse(result.content[0].text) as Record<string, unknown>;
  1120	        if (envelope && typeof envelope === 'object' && !Array.isArray(envelope)) {
  1121	          const metaValue = envelope.meta;
  1122	          const meta = isRecord(metaValue)
  1123	            ? metaValue as Record<string, unknown>
  1124	            : {};
  1125	          const dataValue = envelope.data;
  1126	          const data = isRecord(dataValue)
  1127	            ? dataValue as Record<string, unknown>
  1128	            : null;
  1129	          envelope.meta = meta;
  1130	          if (sessionPrimeContext && !result.isError) {
  1131	            injectSessionPrimeHints(envelope, meta, sessionPrimeContext);
  1132	          }
  1133	          if (autoSurfacedContext && !result.isError) {
  1134	            meta.autoSurfacedContext = autoSurfacedContext;
  1135	          }
  1136	          if (dispatchGraphContext && !result.isError) {
  1137	            meta.graphContext = dispatchGraphContext;
  1138	          }
  1139	          const budget = getTokenBudget(name);
  1140	          meta.tokenBudget = budget;
  1141	          syncEnvelopeTokenCount(envelope);
  1142	
  1143	          if (typeof meta.tokenCount === 'number' && meta.tokenCount > budget) {
  1144	            console.error(`[token-budget] ${name} response (${meta.tokenCount} tokens) exceeds budget (${budget})`);
  1145	
  1146	            // T205: Attempt to truncate results array to fit within budget
  1147	            const innerResults = data?.results;
  1148	            if (Array.isArray(innerResults) && innerResults.length > 1) {
  1149	              const originalCount = innerResults.length;
  1150	              // Results are typically sorted by score (highest first)
  1151	              // Remove from end (lowest-scored) until within budget
  1152	              while (innerResults.length > 1) {
  1153	                innerResults.pop();
  1154	                // P1-06 FIX: Recalculate token count from the full envelope
  1155	                // (not just results) so trace metadata is included in the budget.
  1156	                syncEnvelopeTokenCount(envelope);
  1157	                if (typeof meta.tokenCount === 'number' && meta.tokenCount <= budget) break;
  1158	              }
  1159	              if (data && data.count !== undefined) {
  1160	                data.count = innerResults.length;
  1161	              }
  1162	              if (Array.isArray(envelope.hints)) {
  1163	                envelope.hints.push(`Token budget enforced: truncated ${originalCount} → ${innerResults.length} results to fit ${budget} token budget`);
  1164	              }
  1165	              meta.tokenBudgetTruncated = true;
  1166	              meta.originalResultCount = originalCount;
  1167	              meta.returnedResultCount = innerResults.length;
  1168	            } else {
  1169	              // No truncatable results array — add warning hint only
  1170	              if (Array.isArray(envelope.hints)) {
  1171	                envelope.hints.push(`Response exceeds token budget (${meta.tokenCount}/${budget})`);
  1172	              }
  1173	            }
  1174	          }
  1175	          result.content[0].text = serializeEnvelopeWithTokenCount(envelope);
  1176	        }
  1177	      } catch (_parseErr: unknown) {
  1178	        // Non-JSON response, skip token budget injection
  1179	      }
  1180	    }
  1181	
  1182	    return result;
  1183	  } catch (error: unknown) {
  1184	    // REQ-004: Include recovery hints in all error responses
  1185	    const err = error instanceof Error ? error : new Error(String(error));
  1186	    try {
  1187	      const errorResponse = buildErrorResponse(name, err, args);
  1188	      // eslint-disable-next-line @typescript-eslint/no-explicit-any

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts | sed -n '1048,1708p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
  1048	
  1049	    const skippedChannels = allPossibleChannels.filter(ch => !activeChannels.has(ch));
  1050	
  1051	    if (skippedChannels.length > 0) {
  1052	      s3meta.routing = {
  1053	        tier: routeResult.tier,
  1054	        channels: routeResult.channels,
  1055	        skippedChannels,
  1056	        featureFlagEnabled: isComplexityRouterEnabled(),
  1057	        confidence: routeResult.classification.confidence,
  1058	        features: routeResult.classification.features as Record<string, unknown>,
  1059	      };
  1060	    }
  1061	
  1062	    // -- Stage E: Dynamic Token Budget (SPECKIT_DYNAMIC_TOKEN_BUDGET) --
  1063	    // Compute tier-aware budget early so it's available for downstream truncation.
  1064	    // When disabled, getDynamicTokenBudget returns the default 4000 budget with applied=false.
  1065	    const budgetResult = getDynamicTokenBudget(routeResult.tier);
  1066	    if (budgetResult.applied && !evaluationMode) {
  1067	      s3meta.tokenBudget = {
  1068	        tier: budgetResult.tier,
  1069	        budget: budgetResult.budget,
  1070	        applied: budgetResult.applied,
  1071	        featureFlagEnabled: isDynamicTokenBudgetEnabled(),
  1072	        configValues: DEFAULT_TOKEN_BUDGET_CONFIG as unknown as Record<string, number>,
  1073	        // headerOverhead and adjustedBudget are patched in below after they are computed
  1074	        headerOverhead: 0,
  1075	        adjustedBudget: budgetResult.budget,
  1076	      };
  1077	    }
  1078	
  1079	    // Channel results collected independently, merged after all complete
  1080	    let semanticResults: Array<{ id: number | string; source: string; [key: string]: unknown }> = [];
  1081	    let ftsChannelResults: HybridSearchResult[] = [];
  1082	    let bm25ChannelResults: HybridSearchResult[] = [];
  1083	    const vectorEmbeddingCache = new Map<number, Float32Array>();
  1084	
  1085	    // All channels use synchronous better-sqlite3; sequential execution
  1086	    // Is correct — Promise.all adds overhead without parallelism.
  1087	
  1088	    // Vector channel — gated by query-complexity routing
  1089	    if (activeChannels.has('vector') && embedding && vectorSearchFn) {
  1090	      try {
  1091	        const vectorResults = vectorSearchFn(embedding, {
  1092	          limit: options.limit || DEFAULT_LIMIT,
  1093	          specFolder: options.specFolder,
  1094	          minSimilarity: options.minSimilarity || 0,
  1095	          includeConstitutional: false,
  1096	          includeArchived: options.includeArchived || false,
  1097	          includeEmbeddings: true,
  1098	        });
  1099	        semanticResults = vectorResults.map((r: Record<string, unknown>): { id: number | string; source: string; [key: string]: unknown } => ({
  1100	          ...r,
  1101	          id: r.id as number | string,
  1102	          source: 'vector',
  1103	        }));
  1104	        for (const result of semanticResults) {
  1105	          if (typeof result.id !== 'number') continue;
  1106	          const embeddingCandidate = toEmbeddingBufferView(
  1107	            (result as Record<string, unknown>).embedding
  1108	            ?? (result as Record<string, unknown>).embeddingBuffer
  1109	          );
  1110	          if (embeddingCandidate) {
  1111	            vectorEmbeddingCache.set(result.id, embeddingCandidate);
  1112	          }
  1113	        }
  1114	        lists.push({ source: 'vector', results: semanticResults, weight: 1.0 });
  1115	      } catch (_err: unknown) {
  1116	        // Non-critical — vector channel failure does not block pipeline
  1117	        console.warn('[hybrid-search] Channel error:', _err instanceof Error ? _err.message : String(_err));
  1118	      }
  1119	    }
  1120	
  1121	    // FTS channel (internal error handling in ftsSearch) — gated by query-complexity routing
  1122	    if (activeChannels.has('fts')) {
  1123	      ftsChannelResults = ftsSearch(query, options);
  1124	      if (ftsChannelResults.length > 0) {
  1125	        // FTS weight reduced to 0.3 after ablation showed 0.8 was harmful,
  1126	        // flooding top-K with noisy lexical matches despite its exact-match value.
  1127	        lists.push({ source: 'fts', results: ftsChannelResults, weight: 0.3 });
  1128	      }
  1129	    }
  1130	
  1131	    // BM25 channel (internal error handling in bm25Search) — gated by query-complexity routing
  1132	    if (activeChannels.has('bm25')) {
  1133	      bm25ChannelResults = bm25Search(query, options);
  1134	      if (bm25ChannelResults.length > 0) {
  1135	        // BM25 weight 0.6 is lowest lexical channel — in-memory BM25 index
  1136	        // Has less precise scoring than SQLite FTS5 BM25; kept for coverage breadth.
  1137	        lists.push({ source: 'bm25', results: bm25ChannelResults, weight: 0.6 });
  1138	      }
  1139	    }
  1140	
  1141	    // Graph channel — gated by query-complexity routing
  1142	    const useGraph = (options.useGraph !== false) && activeChannels.has('graph');
  1143	    if (useGraph && graphSearchFn) {
  1144	      try {
  1145	        graphMetrics.totalQueries++; // counted only if channel executes
  1146	        const graphResults = graphSearchFn(query, {
  1147	          limit: options.limit || DEFAULT_LIMIT,
  1148	          specFolder: options.specFolder,
  1149	          intent: options.intent,
  1150	        });
  1151	        if (graphResults.length > 0) {
  1152	          graphMetrics.graphHits++;
  1153	          lists.push({ source: 'graph', results: graphResults.map((r: Record<string, unknown>) => ({
  1154	            ...r,
  1155	            id: r.id as number | string,
  1156	          })), weight: 0.5 });
  1157	        }
  1158	      } catch (_err: unknown) {
  1159	        // Non-critical — graph channel failure does not block pipeline
  1160	        console.warn('[hybrid-search] Channel error:', _err instanceof Error ? _err.message : String(_err));
  1161	      }
  1162	    }
  1163	
  1164	    // Degree channel re-ranks based on causal-edge connectivity.
  1165	    // Graduated: default-ON. Set SPECKIT_DEGREE_BOOST=false to disable.
  1166	    // Degree channel — also gated by query-complexity routing
  1167	    if (activeChannels.has('degree') && db && isDegreeBoostEnabled()) {
  1168	      try {
  1169	        // Collect all numeric IDs from existing channels
  1170	        const allResultIds = new Set<number>();
  1171	        for (const list of lists) {
  1172	          for (const r of list.results) {
  1173	            const id = r.id;
  1174	            if (typeof id === 'number') allResultIds.add(id);
  1175	          }
  1176	        }
  1177	
  1178	        if (allResultIds.size > 0) {
  1179	          const degreeScores = computeDegreeScores(db, Array.from(allResultIds));
  1180	
  1181	          // Build a ranked list sorted by degree score (highest first)
  1182	          const degreeItems: Array<{ id: number; degreeScore: number }> = [];
  1183	          for (const [idStr, score] of degreeScores) {
  1184	            const numId = Number(idStr);
  1185	            if (score > 0 && !isNaN(numId)) {
  1186	              degreeItems.push({ id: numId, degreeScore: score });
  1187	            }
  1188	          }
  1189	          degreeItems.sort((a, b) => b.degreeScore - a.degreeScore);
  1190	
  1191	          if (degreeItems.length > 0) {
  1192	            lists.push({
  1193	              source: 'degree',
  1194	              results: degreeItems.map(item => ({
  1195	                id: item.id,
  1196	                degreeScore: item.degreeScore,
  1197	              })),
  1198	              weight: DEGREE_CHANNEL_WEIGHT,
  1199	            });
  1200	          }
  1201	        }
  1202	      } catch (_err: unknown) {
  1203	        // Non-critical — degree channel failure does not block pipeline
  1204	        console.warn('[hybrid-search] Channel error:', _err instanceof Error ? _err.message : String(_err));
  1205	      }
  1206	    }
  1207	
  1208	    // Merge keyword results after all channels complete
  1209	    const keywordResults: Array<{ id: number | string; source: string; [key: string]: unknown }> = [
  1210	      ...ftsChannelResults,
  1211	      ...bm25ChannelResults,
  1212	    ];
  1213	
  1214	    if (options.skipFusion) {
  1215	      return {
  1216	        evaluationMode,
  1217	        intent: options.intent || classifyIntent(query).intent,
  1218	        lists,
  1219	        routeResult,
  1220	        budgetResult,
  1221	        s3meta,
  1222	        vectorEmbeddingCache,
  1223	        fusedResults: collectCandidatesFromLists(
  1224	          lists.filter((list) => list.source !== 'degree'),
  1225	          options.limit ?? DEFAULT_LIMIT
  1226	        ),
  1227	      };
  1228	    }
  1229	
  1230	    if (lists.length === 0) {
  1231	      return null;
  1232	    }
  1233	
  1234	    // Track multi-source and graph-only results
  1235	    const sourceMap = new Map<string, Set<string>>();
  1236	    for (const list of lists) {
  1237	      for (const r of list.results) {
  1238	        const key = canonicalResultId(r.id);
  1239	        if (!sourceMap.has(key)) sourceMap.set(key, new Set());
  1240	        sourceMap.get(key)!.add(list.source); // non-null safe: has() guard above guarantees entry exists
  1241	      }
  1242	    }
  1243	    for (const [, sources] of sourceMap) {
  1244	      if (sources.size > 1) graphMetrics.multiSourceResults++;
  1245	      if (sources.size === 1 && sources.has('graph')) graphMetrics.graphOnlyResults++;
  1246	    }
  1247	
  1248	    // C138/T315: Build weighted fusion lists once from lightweight adaptive
  1249	    // weights, avoiding the heavier hybridAdaptiveFuse() standard-first path.
  1250	    const detectedIntent = classifyIntent(query).intent;
  1251	    const intent = resolveFusionIntentContract({
  1252	      detectedIntent,
  1253	      adaptiveFusionIntent: options.intent ?? null,
  1254	      query,
  1255	    })
  1256	      ?? detectedIntent;
  1257	    const adaptiveEnabled = isAdaptiveFusionEnabled();
  1258	    const documentType = resolveAdaptiveDocumentType(lists.map((list) => ({
  1259	      results: list.results as Array<Record<string, unknown>>,
  1260	    })));
  1261	    const fusionWeights = adaptiveEnabled
  1262	      ? getAdaptiveWeights(intent, documentType)
  1263	      : { semanticWeight: 1.0, keywordWeight: 1.0, recencyWeight: 0 };
  1264	    const { semanticWeight, keywordWeight, graphWeight: adaptiveGraphWeight } = fusionWeights;
  1265	    const keywordFusionResults = keywordResults.map((result) => ({
  1266	      ...result,
  1267	      source: 'keyword',
  1268	    }));
  1269	    const fusionLists = lists
  1270	      .filter((list) => list.source !== 'fts' && list.source !== 'bm25')
  1271	      .map((list) => {
  1272	        if (list.source === 'vector') {
  1273	          return { ...list, weight: semanticWeight };
  1274	        }
  1275	        if (list.source === 'graph' && typeof adaptiveGraphWeight === 'number') {
  1276	          return { ...list, weight: adaptiveGraphWeight };
  1277	        }
  1278	        return { ...list };
  1279	      });
  1280	
  1281	    if (keywordFusionResults.length > 0 && keywordWeight > 0) {
  1282	      fusionLists.push({
  1283	        source: 'keyword',
  1284	        results: keywordFusionResults,
  1285	        weight: keywordWeight,
  1286	      });
  1287	    }
  1288	
  1289	    const graphList = fusionLists.find((list) => list.source === 'graph');
  1290	    const vectorList = fusionLists.find((list) => list.source === 'vector');
  1291	    const passthroughLists = fusionLists.filter((list) => list.source !== 'graph' && list.source !== 'vector' && list.source !== 'keyword');
  1292	    const fused = adaptiveEnabled
  1293	      ? (adaptiveFuse as unknown as (
  1294	        semanticResults: Array<Record<string, unknown>>,
  1295	        keywordResults: Array<Record<string, unknown>>,
  1296	        weights: typeof fusionWeights,
  1297	        options: {
  1298	          graphResults?: Array<Record<string, unknown>>;
  1299	          additionalLists?: typeof passthroughLists;
  1300	        },
  1301	      ) => FusionResult[])(
  1302	        (vectorList?.results ?? []) as Array<Record<string, unknown>>,
  1303	        keywordFusionResults,
  1304	        fusionWeights,
  1305	        {
  1306	          graphResults: (graphList?.results ?? []) as Array<Record<string, unknown>>,
  1307	          additionalLists: passthroughLists,
  1308	        },
  1309	      )
  1310	      : fuseResultsMulti(fusionLists);
  1311	
  1312	    const fusedResults = fused.map(toHybridResult).map((row) => {
  1313	      const rowRecord = row as Record<string, unknown>;
  1314	      if (rowRecord.parentMemoryId !== undefined) return row;
  1315	      const normalizedParentMemoryId = rowRecord.parent_id ?? rowRecord.parentId;
  1316	      if (normalizedParentMemoryId === undefined) return row;
  1317	      return {
  1318	        ...row,
  1319	        parentMemoryId: normalizedParentMemoryId,
  1320	      };
  1321	    });
  1322	
  1323	    return {
  1324	      evaluationMode,
  1325	      intent,
  1326	      lists,
  1327	      routeResult,
  1328	      budgetResult,
  1329	      s3meta,
  1330	      vectorEmbeddingCache,
  1331	      fusedResults,
  1332	    };
  1333	  } catch (error: unknown) {
  1334	    const msg = error instanceof Error ? error.message : String(error);
  1335	    console.warn(`[hybrid-search] Enhanced search failed, falling back: ${msg}`);
  1336	    return null;
  1337	  }
  1338	}
  1339	
  1340	async function enrichFusedResults(
  1341	  query: string,
  1342	  execution: HybridFusionExecution,
  1343	  options: HybridSearchOptions = {},
  1344	  initialResults: HybridSearchResult[] = execution.fusedResults
  1345	): Promise<HybridSearchResult[]> {
  1346	  const {
  1347	    evaluationMode,
  1348	    intent,
  1349	    lists,
  1350	    routeResult,
  1351	    budgetResult,
  1352	    s3meta,
  1353	    vectorEmbeddingCache,
  1354	  } = execution;
  1355	  let fusedHybridResults = initialResults;
  1356	  const limit = options.limit || DEFAULT_LIMIT;
  1357	
  1358	  // -- Aggregation stage: MPAB chunk-to-memory aggregation (after fusion, before state filter) --
  1359	  // When enabled, collapses chunk-level results back to their parent memory
  1360	  // Documents using MPAB scoring (sMax + 0.3 * sum(remaining) / sqrt(N)). This prevents
  1361	  // Multiple chunks from the same document dominating the result list.
  1362	  // MINOR-1 fix: isMpabEnabled() and isDocscoreAggregationEnabled() check the same env var
  1363	  if (isDocscoreAggregationEnabled()) {
  1364	    try {
  1365	      const chunkResults = fusedHybridResults.filter(
  1366	        r => (r as Record<string, unknown>).parentMemoryId != null && (r as Record<string, unknown>).chunkIndex != null
  1367	      );
  1368	      if (chunkResults.length > 0) {
  1369	        const nonChunkResults = fusedHybridResults.filter(
  1370	          r => (r as Record<string, unknown>).parentMemoryId == null || (r as Record<string, unknown>).chunkIndex == null
  1371	        );
  1372	        const collapsed = collapseAndReassembleChunkResults(
  1373	          chunkResults.map(r => ({
  1374	            id: r.id,
  1375	            parentMemoryId: (r as Record<string, unknown>).parentMemoryId as number | string,
  1376	            chunkIndex: (r as Record<string, unknown>).chunkIndex as number,
  1377	            score: r.score,
  1378	          }))
  1379	        );
  1380	        // Merge collapsed chunk results with non-chunk results
  1381	        fusedHybridResults = [
  1382	          ...collapsed.map(c => ({
  1383	            id: c.parentMemoryId,
  1384	            score: c.mpabScore,
  1385	            source: 'mpab' as string,
  1386	            _chunkHits: c._chunkHits,
  1387	          } as HybridSearchResult)),
  1388	          ...nonChunkResults,
  1389	        ];
  1390	      }
  1391	    } catch (_mpabErr: unknown) {
  1392	      // Non-critical — MPAB failure does not block pipeline
  1393	      const msg = _mpabErr instanceof Error ? _mpabErr.message : String(_mpabErr);
  1394	      console.error('[hybrid-search] MPAB error (non-fatal):', msg);
  1395	    }
  1396	  }
  1397	
  1398	  // -- Stage C: Channel Enforcement (SPECKIT_CHANNEL_MIN_REP) --
  1399	  // Ensures every channel that returned results has at least one representative
  1400	  // In the top-k window. Prevents single-channel dominance in fusion output.
  1401	  // When disabled, passes results through unchanged.
  1402	  try {
  1403	    const channelResultSets = new Map<string, Array<{ id: number | string; score: number; [key: string]: unknown }>>();
  1404	    for (const list of lists) {
  1405	      channelResultSets.set(list.source, list.results.map(r => ({
  1406	        ...r,
  1407	        id: r.id,
  1408	        score: typeof (r as Record<string, unknown>).score === 'number'
  1409	          ? (r as Record<string, unknown>).score as number
  1410	          : typeof (r as Record<string, unknown>).similarity === 'number'
  1411	            ? ((r as Record<string, unknown>).similarity as number) / 100
  1412	            : 0,
  1413	      })));
  1414	    }
  1415	
  1416	    const enforcementResult: EnforcementResult = enforceChannelRepresentation(
  1417	      fusedHybridResults.map(r => ({ ...r, source: r.source || 'hybrid' })),
  1418	      channelResultSets,
  1419	      limit,
  1420	    );
  1421	
  1422	    if (enforcementResult.enforcement.applied) {
  1423	      fusedHybridResults = enforcementResult.results as HybridSearchResult[];
  1424	      s3meta.enforcement = {
  1425	        applied: true,
  1426	        promotedCount: enforcementResult.enforcement.promotedCount,
  1427	        underRepresentedChannels: enforcementResult.enforcement.underRepresentedChannels,
  1428	      };
  1429	    }
  1430	  } catch (err: unknown) {
  1431	    // Non-critical — enforcement failure does not block pipeline
  1432	    console.warn('[hybrid-search] channel enforcement failed:', err instanceof Error ? err.message : String(err));
  1433	  }
  1434	
  1435	  // Preserve non-enumerable eval metadata across later array reallocations.
  1436	  const shadowMeta = initialResults as HybridSearchResult[] & ShadowMetaArray;
  1437	  const s4shadowMeta = shadowMeta._s4shadow;
  1438	  const s4attributionMeta = shadowMeta._s4attribution;
  1439	  const degradationMeta = shadowMeta._degradation;
  1440	
  1441	  // C138/T316: MMR reranking with request-scoped embedding cache.
  1442	  // Reuse embeddings already returned by the vector channel when present and
  1443	  // only query vec_memories for missing IDs.
  1444	  let reranked: HybridSearchResult[] = fusedHybridResults.slice(0, limit);
  1445	
  1446	  // P1-5: Optional local GGUF reranking path (RERANKER_LOCAL=true).
  1447	  // Preserve cross-encoder gate semantics: when SPECKIT_CROSS_ENCODER=false, skip reranking.
  1448	  if (isCrossEncoderEnabled() && isLocalRerankerEnabled() && reranked.length >= MMR_MIN_CANDIDATES) {
  1449	    const localReranked = await rerankLocal(query, reranked, limit);
  1450	    if (localReranked !== reranked) {
  1451	      reranked = localReranked as HybridSearchResult[];
  1452	    }
  1453	  }
  1454	
  1455	  if (db && isMMREnabled()) {
  1456	    const numericIds = reranked
  1457	      .map(r => r.id)
  1458	      .filter((id): id is number => typeof id === 'number');
  1459	
  1460	    if (numericIds.length >= MMR_MIN_CANDIDATES) {
  1461	      try {
  1462	        const embeddingMap = new Map<number, Float32Array>(vectorEmbeddingCache);
  1463	        const missingIds = numericIds.filter((id) => !embeddingMap.has(id));
  1464	
  1465	        if (missingIds.length > 0) {
  1466	          const placeholders = missingIds.map(() => '?').join(', ');
  1467	          const embRows = (db.prepare(
  1468	            `SELECT rowid, embedding FROM vec_memories WHERE rowid IN (${placeholders})`
  1469	          ) as Database.Statement).all(...missingIds) as Array<{ rowid: number; embedding: Buffer }>;
  1470	
  1471	          for (const row of embRows) {
  1472	            if (Buffer.isBuffer(row.embedding)) {
  1473	              embeddingMap.set(
  1474	                row.rowid,
  1475	                new Float32Array(row.embedding.buffer, row.embedding.byteOffset, row.embedding.byteLength / 4)
  1476	              );
  1477	            }
  1478	          }
  1479	        }
  1480	
  1481	        const mmrCandidates: MMRCandidate[] = [];
  1482	        for (const r of reranked) {
  1483	          const emb = embeddingMap.get(r.id as number);
  1484	          if (emb) {
  1485	            mmrCandidates.push({
  1486	              id: r.id as number,
  1487	              score: (r.score as number) ?? 0,
  1488	              embedding: emb,
  1489	            });
  1490	          }
  1491	        }
  1492	
  1493	        if (mmrCandidates.length >= MMR_MIN_CANDIDATES) {
  1494	          const mmrLambda = INTENT_LAMBDA_MAP[intent] ?? MMR_DEFAULT_LAMBDA;
  1495	          const diversified = applyMMR(mmrCandidates, { lambda: mmrLambda, limit });
  1496	
  1497	          // FIX #6: Same fix as stage3-rerank FIX #5 — MMR can only diversify
  1498	          // rows that have embeddings. Non-embedded rows (lexical-only hits,
  1499	          // graph injections) must be preserved and merged back in their
  1500	          // original relative order instead of being silently dropped.
  1501	          const embeddedIdSet = new Set(mmrCandidates.map(c => c.id));
  1502	          const nonEmbeddedRows = reranked.filter(r => !embeddedIdSet.has(r.id as number));
  1503	          const rerankedById = new Map<string, HybridSearchResult>(
  1504	            reranked.map((result) => [canonicalResultId(result.id), result])
  1505	          );
  1506	
  1507	          const diversifiedRows = diversified.map((candidate): HybridSearchResult => {
  1508	            const existing = rerankedById.get(canonicalResultId(candidate.id));
  1509	            if (existing) {
  1510	              return existing;
  1511	            }
  1512	
  1513	            return {
  1514	              id: candidate.id,
  1515	              score: candidate.score,
  1516	              source: 'vector',
  1517	            };
  1518	          });
  1519	
  1520	          // Merge: diversified embedded rows first (MMR-ordered), then
  1521	          // non-embedded rows in their original relative order.
  1522	          reranked = [...diversifiedRows, ...nonEmbeddedRows];
  1523	        }
  1524	      } catch (embErr: unknown) {
  1525	        const msg = embErr instanceof Error ? embErr.message : String(embErr);
  1526	        console.warn(`[hybrid-search] MMR embedding retrieval failed: ${msg}`);
  1527	      }
  1528	    }
  1529	  }
  1530	
  1531	  // C138: Co-activation spreading — enrich with temporal neighbors
  1532	  const topIds = reranked
  1533	    .slice(0, SPREAD_ACTIVATION_TOP_N)
  1534	    .map(r => r.id)
  1535	    .filter((id): id is number => typeof id === 'number');
  1536	  if (topIds.length > 0) {
  1537	    try {
  1538	      const spreadResults: SpreadResult[] = spreadActivation(topIds);
  1539	      // Boost scores of results that appear in co-activation graph
  1540	      if (spreadResults.length > 0) {
  1541	        const spreadMap = new Map(spreadResults.map(sr => [sr.id, sr.activationScore]));
  1542	        for (const result of reranked) {
  1543	          const boost = spreadMap.get(result.id as number);
  1544	          if (boost !== undefined) {
  1545	            // M10 FIX: Update all score aliases so downstream consumers see the boost
  1546	            const boostedScore = ((result.score as number) ?? 0) + boost * CO_ACTIVATION_CONFIG.boostFactor;
  1547	            (result as Record<string, unknown>).score = boostedScore;
  1548	            if ('rrfScore' in result) (result as Record<string, unknown>).rrfScore = boostedScore;
  1549	            if ('intentAdjustedScore' in result) (result as Record<string, unknown>).intentAdjustedScore = boostedScore;
  1550	          }
  1551	        }
  1552	      }
  1553	      // P1-2 FIX: Re-sort after co-activation boost to ensure boosted results
  1554	      // Are promoted to their correct position in the ranking
  1555	      reranked.sort((a, b) => ((b.score as number) ?? 0) - ((a.score as number) ?? 0));
  1556	    } catch (err: unknown) {
  1557	      // Non-critical enrichment — co-activation failure does not affect core ranking
  1558	      console.warn('[hybrid-search] co-activation enrichment failed:', err instanceof Error ? err.message : String(err));
  1559	    }
  1560	  }
  1561	
  1562	  // Folder relevance / two-pass retrieval (SPECKIT_FOLDER_SCORING)
  1563	  if (db && isFolderScoringEnabled() && reranked.length > 0) {
  1564	    try {
  1565	      const numericIds = reranked
  1566	        .map(r => r.id)
  1567	        .filter((id): id is number => typeof id === 'number');
  1568	
  1569	      if (numericIds.length > 0) {
  1570	        const folderMap = lookupFolders(db, numericIds);
  1571	        if (folderMap.size > 0) {
  1572	          const folderScores = computeFolderRelevanceScores(reranked, folderMap);
  1573	          const rawTopK = process.env.SPECKIT_FOLDER_TOP_K;
  1574	          const parsedTopK = rawTopK ? parseInt(rawTopK, 10) : NaN;
  1575	          const topK = Number.isFinite(parsedTopK) && parsedTopK > 0 ? parsedTopK : 5;
  1576	
  1577	          const twoPhaseResults = twoPhaseRetrieval(reranked, folderScores, folderMap, topK);
  1578	          const postFolderResults = twoPhaseResults.length > 0 ? twoPhaseResults : reranked;
  1579	          reranked = enrichResultsWithFolderScores(postFolderResults, folderScores, folderMap) as HybridSearchResult[];
  1580	        }
  1581	      }
  1582	    } catch (_folderErr: unknown) {
  1583	      // Folder scoring is optional and must not break retrieval
  1584	    }
  1585	  }
  1586	
  1587	  // -- Stage D: Confidence Truncation (SPECKIT_CONFIDENCE_TRUNCATION) --
  1588	  // Run after the ranking pipeline so later boosts/promotions can rescue
  1589	  // candidates before low-confidence tails are trimmed.
  1590	  if (!evaluationMode) {
  1591	    try {
  1592	      const truncationResult: TruncationResult = truncateByConfidence(
  1593	        reranked.map(r => ({ ...r, id: r.id, score: r.score })),
  1594	      );
  1595	
  1596	      if (truncationResult.truncated) {
  1597	        reranked = truncationResult.results.map(r => r as HybridSearchResult);
  1598	        s3meta.truncation = {
  1599	          truncated: true,
  1600	          originalCount: truncationResult.originalCount,
  1601	          truncatedCount: truncationResult.truncatedCount,
  1602	          medianGap: truncationResult.medianGap,
  1603	          cutoffGap: truncationResult.cutoffGap,
  1604	          cutoffIndex: truncationResult.cutoffIndex,
  1605	          thresholdMultiplier: GAP_THRESHOLD_MULTIPLIER,
  1606	          minResultsGuaranteed: DEFAULT_MIN_RESULTS,
  1607	          featureFlagEnabled: isConfidenceTruncationEnabled(),
  1608	        };
  1609	      }
  1610	    } catch (err: unknown) {
  1611	      // Non-critical — truncation failure does not block pipeline
  1612	      console.warn('[hybrid-search] confidence truncation failed:', err instanceof Error ? err.message : String(err));
  1613	    }
  1614	  }
  1615	
  1616	  // Preserve routing and Stage 4 trace metadata as explicit result fields so downstream
  1617	  // Formatters can opt-in to provenance-rich envelopes without relying on
  1618	  // Non-enumerable array shadow properties.
  1619	  if (reranked.length > 0) {
  1620	    reranked = reranked.map((row): HybridSearchResult => {
  1621	      const existingTraceMetadata =
  1622	        typeof row.traceMetadata === 'object' && row.traceMetadata !== null && !Array.isArray(row.traceMetadata)
  1623	          ? row.traceMetadata
  1624	          : {};
  1625	
  1626	      return {
  1627	        ...row,
  1628	        traceMetadata: {
  1629	          ...existingTraceMetadata,
  1630	          ...(s4shadowMeta !== undefined ? { stage4: s4shadowMeta } : {}),
  1631	          ...(s4attributionMeta !== undefined ? { attribution: s4attributionMeta } : {}),
  1632	          ...(degradationMeta !== undefined ? { degradation: degradationMeta } : {}),
  1633	          evaluationMode,
  1634	          // Wire queryComplexity from router classification into trace
  1635	          queryComplexity: routeResult.tier,
  1636	          // Wire confidence truncation metadata into per-result trace (036)
  1637	          ...(s3meta.truncation ? {
  1638	            confidenceTruncation: {
  1639	              truncated: s3meta.truncation.truncated,
  1640	              originalCount: s3meta.truncation.originalCount,
  1641	              truncatedCount: s3meta.truncation.truncatedCount,
  1642	              medianGap: s3meta.truncation.medianGap,
  1643	              cutoffGap: s3meta.truncation.cutoffGap,
  1644	              cutoffIndex: s3meta.truncation.cutoffIndex,
  1645	              thresholdMultiplier: s3meta.truncation.thresholdMultiplier,
  1646	              minResultsGuaranteed: s3meta.truncation.minResultsGuaranteed,
  1647	            },
  1648	          } : {}),
  1649	        },
  1650	      };
  1651	    });
  1652	  }
  1653	
  1654	  if (isContextHeadersEnabled() && reranked.length > 0) {
  1655	    const descriptionCache = buildDescriptionTailMap();
  1656	    if (descriptionCache.size > 0) {
  1657	      reranked = reranked.map((row) => injectContextualTree(row, descriptionCache));
  1658	    }
  1659	  }
  1660	
  1661	  let budgetTruncated = false;
  1662	  let budgetLimit: number | undefined;
  1663	  if (evaluationMode) {
  1664	    reranked = applyResultLimit(reranked, options.limit);
  1665	  } else {
  1666	    // Apply token budget truncation after trace/header enrichment so token
  1667	    // estimates reflect the actual returned payload shape.
  1668	    const headerOverhead = isContextHeadersEnabled()
  1669	      ? reranked.length * CONTEXT_HEADER_TOKEN_OVERHEAD
  1670	      : 0;
  1671	    const adjustedBudget = Math.max(budgetResult.budget - headerOverhead, 200);
  1672	
  1673	    if (s3meta.tokenBudget) {
  1674	      s3meta.tokenBudget.headerOverhead = headerOverhead;
  1675	      s3meta.tokenBudget.adjustedBudget = adjustedBudget;
  1676	    }
  1677	
  1678	    const budgeted = truncateToBudget(reranked, adjustedBudget, {
  1679	      includeContent: options.includeContent ?? false,
  1680	      queryId: `hybrid-${Date.now()}`,
  1681	    });
  1682	    reranked = budgeted.results;
  1683	    budgetTruncated = budgeted.truncated;
  1684	    budgetLimit = budgetResult.budget;
  1685	  }
  1686	
  1687	  if (reranked.length > 0) {
  1688	    reranked = reranked.map((row): HybridSearchResult => {
  1689	      const existingTraceMetadata =
  1690	        typeof row.traceMetadata === 'object' && row.traceMetadata !== null && !Array.isArray(row.traceMetadata)
  1691	          ? row.traceMetadata
  1692	          : {};
  1693	
  1694	      return {
  1695	        ...row,
  1696	        traceMetadata: {
  1697	          ...existingTraceMetadata,
  1698	          budgetTruncated,
  1699	          ...(budgetLimit !== undefined ? { budgetLimit } : {}),
  1700	        },
  1701	      };
  1702	    });
  1703	  }
  1704	
  1705	  if (s4shadowMeta !== undefined && reranked.length > 0) {
  1706	    Object.defineProperty(reranked, '_s4shadow', {
  1707	      value: s4shadowMeta,
  1708	      enumerable: false,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts | sed -n '2250,2558p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
  2250	  });
  2251	
  2252	  return finalResults;
  2253	}
  2254	
  2255	// 14. PRE-FLIGHT TOKEN BUDGET VALIDATION (T007)
  2256	
  2257	/** Default token budget — configurable via SPECKIT_TOKEN_BUDGET env var. */
  2258	const DEFAULT_TOKEN_BUDGET = 2000;
  2259	
  2260	/** Maximum characters for a summary fallback when a single result overflows the budget. */
  2261	const SUMMARY_MAX_CHARS = 400;
  2262	
  2263	/** Overflow log entry recording budget truncation events for eval infrastructure. */
  2264	interface OverflowLogEntry {
  2265	  queryId: string;
  2266	  candidateCount: number;
  2267	  totalTokens: number;
  2268	  budgetLimit: number;
  2269	  truncatedToCount: number;
  2270	  timestamp: string;
  2271	}
  2272	
  2273	/** Result of budget-aware truncation. */
  2274	interface TruncateToBudgetResult {
  2275	  results: HybridSearchResult[];
  2276	  truncated: boolean;
  2277	  overflow?: OverflowLogEntry;
  2278	}
  2279	
  2280	/**
  2281	 * Estimate token count for a text string using a chars/4 heuristic.
  2282	 * @param text - The text to estimate tokens for.
  2283	 * @returns Approximate token count (ceiling of length / 4).
  2284	 */
  2285	function estimateTokenCount(text: string): number {
  2286	  if (!text) return 0;
  2287	  return Math.ceil(text.length / 4);
  2288	}
  2289	
  2290	function estimateStructuredValueChars(value: unknown, seen: WeakSet<object>): number {
  2291	  if (value == null) return 4;
  2292	
  2293	  if (typeof value === 'string') return value.length + 2;
  2294	  if (typeof value === 'number' || typeof value === 'bigint') return String(value).length;
  2295	  if (typeof value === 'boolean') return value ? 4 : 5;
  2296	
  2297	  if (Array.isArray(value)) {
  2298	    let chars = 2;
  2299	    for (const item of value) {
  2300	      chars += estimateStructuredValueChars(item, seen) + 1;
  2301	    }
  2302	    return chars;
  2303	  }
  2304	
  2305	  if (typeof value !== 'object') return 0;
  2306	  if (seen.has(value)) return 8;
  2307	  seen.add(value);
  2308	
  2309	  let chars = 2;
  2310	  for (const [key, nestedValue] of Object.entries(value as Record<string, unknown>)) {
  2311	    chars += key.length + 3;
  2312	    chars += estimateStructuredValueChars(nestedValue, seen) + 1;
  2313	  }
  2314	  return chars;
  2315	}
  2316	
  2317	/**
  2318	 * Estimate the token footprint of a single HybridSearchResult.
  2319	 * @param result - The search result to measure.
  2320	 * @returns Approximate token count based on serialized key-value lengths.
  2321	 */
  2322	function estimateResultTokens(result: HybridSearchResult): number {
  2323	  const record = result as Record<string, unknown>;
  2324	  const seen = new WeakSet<object>();
  2325	  const handledKeys = new Set([
  2326	    'id',
  2327	    'score',
  2328	    'source',
  2329	    'title',
  2330	    'content',
  2331	    'sources',
  2332	    'spec_folder',
  2333	    'file_path',
  2334	    'traceMetadata',
  2335	    'parentMemoryId',
  2336	    'chunkIndex',
  2337	    'similarity',
  2338	    'combined_lexical_score',
  2339	  ]);
  2340	
  2341	  let chars = 0;
  2342	  for (const key of handledKeys) {
  2343	    if (!(key in record)) continue;
  2344	    chars += key.length + 3;
  2345	    chars += estimateStructuredValueChars(record[key], seen) + 1;
  2346	  }
  2347	
  2348	  for (const key of Object.keys(record)) {
  2349	    if (handledKeys.has(key)) continue;
  2350	    const value = record[key];
  2351	    chars += key.length + 3;
  2352	    chars += estimateStructuredValueChars(value, seen) + 1;
  2353	  }
  2354	
  2355	  return Math.ceil(chars / 4);
  2356	}
  2357	
  2358	/**
  2359	 * Read the configured token budget from SPECKIT_TOKEN_BUDGET env var,
  2360	 * falling back to DEFAULT_TOKEN_BUDGET (2000).
  2361	 * @returns The effective token budget for result truncation.
  2362	 */
  2363	function getTokenBudget(): number {
  2364	  const envVal = process.env['SPECKIT_TOKEN_BUDGET'];
  2365	  if (envVal) {
  2366	    const parsed = parseInt(envVal, 10);
  2367	    if (!isNaN(parsed) && parsed > 0) return parsed;
  2368	  }
  2369	  return DEFAULT_TOKEN_BUDGET;
  2370	}
  2371	
  2372	/**
  2373	 * Create a summary fallback for a single result whose content exceeds the token budget.
  2374	 */
  2375	function createSummaryFallback(result: HybridSearchResult, budget: number): HybridSearchResult {
  2376	  const content = typeof result['content'] === 'string' ? result['content'] as string : '';
  2377	  const title = typeof result['title'] === 'string' ? result['title'] : 'Untitled';
  2378	
  2379	  const maxSummaryChars = Math.min(SUMMARY_MAX_CHARS, budget * 4);
  2380	  const truncatedContent = content.length > maxSummaryChars
  2381	    ? content.slice(0, maxSummaryChars) + '...'
  2382	    : content;
  2383	
  2384	  return {
  2385	    ...result,
  2386	    content: `[Summary] ${title}: ${truncatedContent}`,
  2387	    _summarized: true,
  2388	  };
  2389	}
  2390	
  2391	/**
  2392	 * Truncate a result set to fit within a token budget using greedy highest-scoring-first strategy.
  2393	 * @param results - The full result set to truncate.
  2394	 * @param budget - Optional token budget override (defaults to SPECKIT_TOKEN_BUDGET env / 2000).
  2395	 * @param options - Optional includeContent flag and queryId for overflow logging.
  2396	 * @returns Object with truncated results, truncation flag, and optional overflow log entry.
  2397	 */
  2398	function truncateToBudget(
  2399	  results: HybridSearchResult[],
  2400	  budget?: number,
  2401	  options?: { includeContent?: boolean; queryId?: string }
  2402	): TruncateToBudgetResult {
  2403	  const effectiveBudget = (budget && budget > 0) ? budget : getTokenBudget();
  2404	  const includeContent = options?.includeContent ?? false;
  2405	  const queryId = options?.queryId ?? `q-${Date.now()}`;
  2406	
  2407	  if (results.length === 0) {
  2408	    return { results: [], truncated: false };
  2409	  }
  2410	
  2411	  const sorted = [...results].sort((a, b) => b.score - a.score);
  2412	  const tokenEstimateCache = new Map<string, number>();
  2413	  const getTokenEstimate = (result: HybridSearchResult): number => {
  2414	    const cacheKey = canonicalResultId(result.id);
  2415	    const cached = tokenEstimateCache.get(cacheKey);
  2416	    if (cached !== undefined) {
  2417	      return cached;
  2418	    }
  2419	
  2420	    const estimate = estimateResultTokens(result);
  2421	    tokenEstimateCache.set(cacheKey, estimate);
  2422	    return estimate;
  2423	  };
  2424	
  2425	  const totalTokens = sorted.reduce((sum, result) => sum + getTokenEstimate(result), 0);
  2426	
  2427	  if (totalTokens <= effectiveBudget) {
  2428	    return { results: sorted, truncated: false };
  2429	  }
  2430	
  2431	  // Single-result overflow: summarize when content is included, otherwise keep
  2432	  // the lone result and mark the overflow for callers.
  2433	  if (sorted.length === 1) {
  2434	    const outputResult = includeContent
  2435	      ? createSummaryFallback(sorted[0]!, effectiveBudget)
  2436	      : sorted[0]!;
  2437	    const overflow: OverflowLogEntry = {
  2438	      queryId,
  2439	      candidateCount: 1,
  2440	      totalTokens,
  2441	      budgetLimit: effectiveBudget,
  2442	      truncatedToCount: 1,
  2443	      timestamp: new Date().toISOString(),
  2444	    };
  2445	    console.warn(
  2446	      `[hybrid-search] Token budget overflow (single-result fallback): ` +
  2447	      `${totalTokens} tokens > ${effectiveBudget} budget`
  2448	    );
  2449	    return { results: [outputResult], truncated: true, overflow };
  2450	  }
  2451	
  2452	  // Greedy accumulation: take highest-scoring results until budget exhausted
  2453	  const accepted: HybridSearchResult[] = [];
  2454	  let accumulated = 0;
  2455	
  2456	  for (const result of sorted) {
  2457	    const tokens = getTokenEstimate(result);
  2458	    if (accumulated + tokens > effectiveBudget) {
  2459	      if (accepted.length > 0) {
  2460	        break;
  2461	      }
  2462	      continue;
  2463	    }
  2464	    accepted.push(result);
  2465	    accumulated += tokens;
  2466	    if (accumulated >= effectiveBudget) break;
  2467	  }
  2468	
  2469	  if (accepted.length === 0 && sorted.length > 0) {
  2470	    const outputResult = includeContent
  2471	      ? createSummaryFallback(sorted[0]!, effectiveBudget)
  2472	      : sorted[0]!;
  2473	    const overflow: OverflowLogEntry = {
  2474	      queryId,
  2475	      candidateCount: results.length,
  2476	      totalTokens,
  2477	      budgetLimit: effectiveBudget,
  2478	      truncatedToCount: 1,
  2479	      timestamp: new Date().toISOString(),
  2480	    };
  2481	
  2482	    console.warn(
  2483	      `[hybrid-search] Token budget overflow (top-result fallback): ` +
  2484	      `${totalTokens} tokens > ${effectiveBudget} budget`
  2485	    );
  2486	
  2487	    return { results: [outputResult], truncated: true, overflow };
  2488	  }
  2489	
  2490	  const overflow: OverflowLogEntry = {
  2491	    queryId,
  2492	    candidateCount: results.length,
  2493	    totalTokens,
  2494	    budgetLimit: effectiveBudget,
  2495	    truncatedToCount: accepted.length,
  2496	    timestamp: new Date().toISOString(),
  2497	  };
  2498	
  2499	  console.warn(
  2500	    `[hybrid-search] Token budget overflow: ${totalTokens} tokens > ${effectiveBudget} budget, ` +
  2501	    `truncated ${results.length} → ${accepted.length} results`
  2502	  );
  2503	
  2504	  return { results: accepted, truncated: true, overflow };
  2505	}
  2506	
  2507	// 15. EXPORTS
  2508	
  2509	export const __testables = {
  2510	  canonicalResultId,
  2511	  truncateChars,
  2512	  extractSpecSegments,
  2513	  injectContextualTree,
  2514	  applyResultLimit,
  2515	  calibrateTier3Scores,
  2516	  checkDegradation,
  2517	  mergeResults,
  2518	  mergeRawCandidate,
  2519	};
  2520	
  2521	export {
  2522	  init,
  2523	  bm25Search,
  2524	  isBm25Available,
  2525	  combinedLexicalSearch,
  2526	  collectRawCandidates,
  2527	  isFtsAvailable,
  2528	  ftsSearch,
  2529	  hybridSearch,
  2530	  hybridSearchEnhanced,
  2531	  searchWithFallback,
  2532	  getGraphMetrics,
  2533	  resetGraphMetrics,
  2534	  // Token budget validation
  2535	  estimateTokenCount,
  2536	  estimateResultTokens,
  2537	  truncateToBudget,
  2538	  getTokenBudget,
  2539	  DEFAULT_TOKEN_BUDGET,
  2540	  SUMMARY_MAX_CHARS,
  2541	  // Re-exported module functions for caller access
  2542	  routeQuery,
  2543	  getDynamicTokenBudget,
  2544	  isDynamicTokenBudgetEnabled,
  2545	  // PI-A2: Tiered fallback exports
  2546	  structuralSearch,
  2547	  DEGRADATION_QUALITY_THRESHOLD,
  2548	  DEGRADATION_MIN_RESULTS,
  2549	};
  2550	
  2551	export type {
  2552	  HybridSearchOptions,
  2553	  HybridSearchResult,
  2554	  VectorSearchFn,
  2555	  // Token budget types
  2556	  OverflowLogEntry,
  2557	  TruncateToBudgetResult,
  2558	  // Pipeline metadata type

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts | sed -n '1,235p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Confidence Truncation
     3	// ───────────────────────────────────────────────────────────────
     4	// Feature catalog: Confidence-based result truncation
     5	import { isConfidenceTruncationEnabled } from './search-flags.js';
     6	
     7	/* --- 1. TYPES & CONSTANTS --- */
     8	
     9	/** Generic scored result for truncation — supports both numeric and string IDs. */
    10	interface ScoredResult {
    11	  id: number | string;
    12	  score: number;
    13	  [key: string]: unknown;
    14	}
    15	
    16	/** Result of a truncation operation with full audit metadata. */
    17	interface TruncationResult {
    18	  results: ScoredResult[];
    19	  truncated: boolean;
    20	  originalCount: number;
    21	  truncatedCount: number;
    22	  /** Inclusive index of the last kept result (0-based). */
    23	  cutoffIndex: number;
    24	  medianGap: number;
    25	  cutoffGap: number;
    26	}
    27	
    28	/** Options for truncation behaviour. */
    29	interface TruncationOptions {
    30	  /** Minimum number of results to always return, regardless of gap. Default: 3. */
    31	  minResults?: number;
    32	}
    33	
    34	/** Default minimum result count. */
    35	const DEFAULT_MIN_RESULTS = 3;
    36	
    37	/** Gap multiplier: gap must exceed this multiple of the median gap to trigger truncation.
    38	 * 2x median is the elbow heuristic — a gap twice the typical spread signals a relevance cliff. */
    39	const GAP_THRESHOLD_MULTIPLIER = 2;
    40	
    41	/* --- 2. GAP ANALYSIS HELPERS --- */
    42	
    43	/**
    44	 * Compute consecutive score gaps for a sorted (descending) score array.
    45	 * gap[i] = scores[i] - scores[i+1]   for i in [0, n-2]
    46	 * NaN and Infinity scores are filtered out before gap computation.
    47	 * Returns empty array when fewer than 2 finite scores.
    48	 *
    49	 * @param scores - Descending-sorted array of raw scores.
    50	 * @returns Array of consecutive score gaps (length = scores.length - 1).
    51	 */
    52	function computeGaps(scores: number[]): number[] {
    53	  // NaN/Infinity from upstream bugs would corrupt gap statistics — filter them first
    54	  const finite = scores.filter(s => Number.isFinite(s));
    55	  if (finite.length < 2) return [];
    56	  const gaps: number[] = [];
    57	  for (let i = 0; i < finite.length - 1; i++) {
    58	    gaps.push(finite[i] - finite[i + 1]);
    59	  }
    60	  return gaps;
    61	}
    62	
    63	/**
    64	 * Compute the median of an array of numbers.
    65	 * Returns 0 for an empty array.
    66	 *
    67	 * @param values - Array of numeric values.
    68	 * @returns Median value, or 0 for empty input.
    69	 */
    70	function computeMedian(values: number[]): number {
    71	  if (values.length === 0) return 0;
    72	  const sorted = [...values].sort((a, b) => a - b);
    73	  const mid = Math.floor(sorted.length / 2);
    74	  if (sorted.length % 2 === 1) {
    75	    return sorted[mid];
    76	  }
    77	  return (sorted[mid - 1] + sorted[mid]) / 2;
    78	}
    79	
    80	/* --- 3. CORE TRUNCATION LOGIC --- */
    81	
    82	/**
    83	 * Truncate results based on confidence gap analysis.
    84	 *
    85	 * Algorithm:
    86	 * 1. If fewer than minResults results, return unchanged.
    87	 * 2. Compute consecutive score gaps.
    88	 * 3. Compute median gap.
    89	 * 4. Find first index >= (minResults - 1) where gap > 2 * medianGap.
    90	 * 5. Truncate at that index + 1 (keep results 0..cutoffIndex inclusive).
    91	 * 6. If no threshold-exceeding gap found, return all results unchanged.
    92	 *
    93	 * When SPECKIT_CONFIDENCE_TRUNCATION is disabled, passes results through unchanged.
    94	 *
    95	 * Results are expected to be pre-sorted by score descending. This function
    96	 * does NOT sort; it operates on the input order.
    97	 *
    98	 * @param results - Array of scored results (expected descending by score).
    99	 * @param options - Optional truncation options (minResults).
   100	 * @returns TruncationResult with the (possibly shortened) result array and audit metadata.
   101	 */
   102	function truncateByConfidence(
   103	  results: ScoredResult[],
   104	  options?: TruncationOptions,
   105	): TruncationResult {
   106	  const minResults = options?.minResults ?? DEFAULT_MIN_RESULTS;
   107	
   108	  // Defensive: filter out results with NaN/Infinity scores
   109	  const validResults = results.filter(r => Number.isFinite(r.score));
   110	
   111	  // Defensive: sort descending by score. Callers should pre-sort for efficiency.
   112	  validResults.sort((a, b) => b.score - a.score);
   113	
   114	  const originalCount = validResults.length;
   115	
   116	  // Feature flag gate: pass through when disabled
   117	  if (!isConfidenceTruncationEnabled()) {
   118	    return {
   119	      results: [...validResults],
   120	      truncated: false,
   121	      originalCount,
   122	      truncatedCount: originalCount,
   123	      cutoffIndex: originalCount - 1,
   124	      medianGap: 0,
   125	      cutoffGap: 0,
   126	    };
   127	  }
   128	
   129	  // Not enough results to truncate
   130	  if (validResults.length <= minResults) {
   131	    return {
   132	      results: [...validResults],
   133	      truncated: false,
   134	      originalCount,
   135	      truncatedCount: originalCount,
   136	      cutoffIndex: originalCount - 1,
   137	      medianGap: 0,
   138	      cutoffGap: 0,
   139	    };
   140	  }
   141	
   142	  const scores = validResults.map(r => r.score);
   143	  const gaps = computeGaps(scores);
   144	  const medianGap = computeMedian(gaps);
   145	  const threshold = GAP_THRESHOLD_MULTIPLIER * medianGap;
   146	
   147	  // When medianGap is 0 (all same scores), no meaningful gap exists — return all
   148	  if (medianGap === 0) {
   149	    return {
   150	      results: [...validResults],
   151	      truncated: false,
   152	      originalCount,
   153	      truncatedCount: originalCount,
   154	      cutoffIndex: originalCount - 1,
   155	      medianGap: 0,
   156	      cutoffGap: 0,
   157	    };
   158	  }
   159	
   160	  // Search for the first gap that exceeds the threshold, starting from minResults - 1.
   161	  // Gap[i] is the gap between result i and result i+1.
   162	  // If gap[i] > threshold, we keep results 0..i (cutoffIndex = i).
   163	  let cutoffIndex = -1;
   164	  let cutoffGap = 0;
   165	
   166	  for (let i = minResults - 1; i < gaps.length; i++) {
   167	    if (gaps[i] > threshold) {
   168	      cutoffIndex = i;
   169	      cutoffGap = gaps[i];
   170	      break;
   171	    }
   172	  }
   173	
   174	  // No significant gap found — return all results
   175	  if (cutoffIndex === -1) {
   176	    return {
   177	      results: [...validResults],
   178	      truncated: false,
   179	      originalCount,
   180	      truncatedCount: originalCount,
   181	      cutoffIndex: originalCount - 1,
   182	      medianGap,
   183	      cutoffGap: 0,
   184	    };
   185	  }
   186	
   187	  // Truncate: keep validResults[0..cutoffIndex] inclusive
   188	  const truncatedResults = validResults.slice(0, cutoffIndex + 1);
   189	
   190	  return {
   191	    results: truncatedResults,
   192	    truncated: true,
   193	    originalCount,
   194	    truncatedCount: truncatedResults.length,
   195	    cutoffIndex,
   196	    medianGap,
   197	    cutoffGap,
   198	  };
   199	}
   200	
   201	/* --- 5. EXPORTS --- */
   202	
   203	export {
   204	  // Types
   205	  type ScoredResult,
   206	  type TruncationResult,
   207	  type TruncationOptions,
   208	
   209	  // Constants
   210	  DEFAULT_MIN_RESULTS,
   211	  GAP_THRESHOLD_MULTIPLIER,
   212	
   213	  // Functions
   214	  truncateByConfidence,
   215	  isConfidenceTruncationEnabled,
   216	
   217	  // Internal helpers (exported for testing)
   218	  computeGaps,
   219	  computeMedian,
   220	};

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts | sed -n '1,120p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Dynamic Token Budget
     3	// ───────────────────────────────────────────────────────────────
     4	//
     5	// ADVISORY-ONLY: This module computes a token budget for a query
     6	// Based on its complexity tier, but does NOT enforce that budget
     7	// Downstream. The returned BudgetResult is handed to callers who
     8	// Are solely responsible for respecting it (e.g. by trimming
     9	// Result sets or truncating content before sending to the LLM).
    10	import { type QueryComplexityTier } from './query-classifier.js';
    11	import { isDynamicTokenBudgetEnabled } from './search-flags.js';
    12	
    13	// Feature catalog: Dynamic token budget allocation
    14	
    15	
    16	/* --- 1. TYPES & CONSTANTS --- */
    17	
    18	/** Budget (in tokens) allocated per complexity tier. */
    19	interface TokenBudgetConfig {
    20	  /** Simple query budget: 1500 tokens. */
    21	  simple: number;
    22	  /** Moderate query budget: 2500 tokens. */
    23	  moderate: number;
    24	  /** Complex query budget: 4000 tokens. */
    25	  complex: number;
    26	}
    27	
    28	/** Result of a token budget lookup. */
    29	interface BudgetResult {
    30	  /** The complexity tier that determined the budget. */
    31	  tier: QueryComplexityTier;
    32	  /** The allocated token budget. */
    33	  budget: number;
    34	  /** Whether the dynamic flag was active (false = default fallback used). */
    35	  applied: boolean;
    36	}
    37	
    38	/** Default budget when the feature flag is disabled — treat everything as complex. */
    39	const DEFAULT_BUDGET = 4000;
    40	
    41	/** Default tier-to-budget mapping when dynamic allocation is enabled.
    42	 * 1500/2500/4000 tiers balance context window cost vs. recall —
    43	 * simple queries need fewer tokens, complex queries need the full budget. */
    44	const DEFAULT_TOKEN_BUDGET_CONFIG: TokenBudgetConfig = {
    45	  simple: 1500,
    46	  moderate: 2500,
    47	  complex: 4000,
    48	};
    49	
    50	/* --- 2. FEATURE FLAG --- */
    51	
    52	/* --- 3. BUDGET RESOLUTION --- */
    53	
    54	/**
    55	 * Get the token budget for a given query complexity tier.
    56	 *
    57	 * When SPECKIT_DYNAMIC_TOKEN_BUDGET is disabled (default), returns the DEFAULT_BUDGET
    58	 * (4000) for all queries regardless of tier, with applied=false.
    59	 *
    60	 * When enabled, maps tier to the configured budget:
    61	 *   simple   → 1500 tokens
    62	 *   moderate → 2500 tokens
    63	 *   complex  → 4000 tokens
    64	 *
    65	 * @param tier   - The complexity tier from the query classifier
    66	 * @param config - Optional custom budget config (overrides DEFAULT_TOKEN_BUDGET_CONFIG)
    67	 * @returns BudgetResult with tier, budget, and applied flag
    68	 */
    69	function getDynamicTokenBudget(
    70	  tier: QueryComplexityTier,
    71	  config?: TokenBudgetConfig,
    72	): BudgetResult {
    73	  // Feature flag gate: return default when disabled
    74	  if (!isDynamicTokenBudgetEnabled()) {
    75	    return {
    76	      tier,
    77	      budget: DEFAULT_BUDGET,
    78	      applied: false,
    79	    };
    80	  }
    81	
    82	  const effectiveConfig = config ?? DEFAULT_TOKEN_BUDGET_CONFIG;
    83	  const budget = effectiveConfig[tier] ?? DEFAULT_BUDGET;
    84	
    85	  return {
    86	    tier,
    87	    budget,
    88	    applied: true,
    89	  };
    90	}
    91	
    92	/* --- 4. EXPORTS --- */
    93	
    94	export {
    95	  // Types
    96	  type TokenBudgetConfig,
    97	  type BudgetResult,
    98	
    99	  // Constants
   100	  DEFAULT_BUDGET,
   101	  DEFAULT_TOKEN_BUDGET_CONFIG,
   102	
   103	  // Functions
   104	  getDynamicTokenBudget,
   105	  isDynamicTokenBudgetEnabled,
   106	};

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts | sed -n '88,320p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
    88	  'memory_quick_search',
    89	  'memory_match_triggers',
    90	  'memory_list',
    91	  'memory_save',
    92	  'memory_index_scan'
    93	]);
    94	
    95	// Token budgets for dual-scope lifecycle hooks (TM-05)
    96	const TOOL_DISPATCH_TOKEN_BUDGET = 4000;
    97	const COMPACTION_TOKEN_BUDGET = 4000;
    98	
    99	// Constitutional memory cache
   100	// Module-level mutable state: safe in a single-process MCP server.
   101	// If the server ever runs multi-process, replace with a shared store.
   102	let constitutionalCache: ConstitutionalMemory[] | null = null;
   103	let constitutionalCacheTime = 0;
   104	const CONSTITUTIONAL_CACHE_TTL = 60000; // 1 minute
   105	// Per-session priming tracker: a Set of session IDs that have been primed.
   106	// Replaces the previous process-global boolean to avoid skipping priming
   107	// for new sessions on long-lived MCP servers.
   108	const primedSessionIds: Set<string> = new Set();
   109	
   110	// T018: Session-level tracking for prime package and session_health
   111	const serverStartedAt = Date.now();
   112	let lastToolCallAt = Date.now();
   113	let lastActiveSessionId: string | null = null;
   114	
   115	/** T018: Update last tool call timestamp (called from context-server dispatch). */
   116	function recordToolCall(sessionId?: string): void {
   117	  lastToolCallAt = Date.now();
   118	  if (typeof sessionId === 'string' && sessionId.trim().length > 0) {
   119	    lastActiveSessionId = sessionId.trim();
   120	  }
   121	}
   122	
   123	/** T018: Get session tracking timestamps */
   124	function getSessionTimestamps(): { serverStartedAt: number; lastToolCallAt: number } {
   125	  return { serverStartedAt, lastToolCallAt };
   126	}
   127	
   128	/**
   129	 * T018: Check if a specific session has been primed.
   130	 * Session identity is required to avoid cross-session bleed-through.
   131	 */
   132	function isSessionPrimed(sessionId: string): boolean {
   133	  return primedSessionIds.has(sessionId);
   134	}
   135	
   136	/** Mark a specific session as primed */
   137	function markSessionPrimed(sessionId: string): void {
   138	  primedSessionIds.add(sessionId);
   139	  lastActiveSessionId = sessionId;
   140	}
   141	
   142	function getLastActiveSessionId(): string | null {
   143	  return lastActiveSessionId;
   144	}
   145	
   146	/* ───────────────────────────────────────────────────────────────
   147	   3. CONTEXT EXTRACTION
   148	──────────────────────────────────────────────────────────────── */
   149	
   150	function extractContextHint(args: Record<string, unknown> | null | undefined): string | null {
   151	  if (!args || typeof args !== 'object') return null;
   152	
   153	  const contextFields = ['input', 'query', 'prompt', 'specFolder', 'filePath'];
   154	  for (const field of contextFields) {
   155	    if (args[field] && typeof args[field] === 'string' && (args[field] as string).length >= 3) {
   156	      return args[field] as string;
   157	    }
   158	  }
   159	
   160	  // Join concepts array if present
   161	  if (args.concepts && Array.isArray(args.concepts) && args.concepts.length > 0) {
   162	    const strings = args.concepts.filter((c): c is string => typeof c === 'string');
   163	    if (strings.length > 0) return strings.join(' ');
   164	  }
   165	
   166	  return null;
   167	}
   168	
   169	/* ───────────────────────────────────────────────────────────────
   170	   4. CONSTITUTIONAL MEMORIES
   171	──────────────────────────────────────────────────────────────── */
   172	
   173	async function getConstitutionalMemories(): Promise<ConstitutionalMemory[]> {
   174	  const now = Date.now();
   175	
   176	  if (constitutionalCache && (now - constitutionalCacheTime) < CONSTITUTIONAL_CACHE_TTL) {
   177	    return constitutionalCache;
   178	  }
   179	
   180	  try {
   181	    const db: Database | null = vectorIndex.getDb();
   182	    if (!db) return [];
   183	
   184	    const rows = db.prepare(`
   185	      SELECT id, spec_folder, file_path, title, trigger_phrases, importance_tier
   186	      FROM memory_index
   187	      WHERE importance_tier = 'constitutional'
   188	      AND embedding_status IN ('success', 'pending', 'partial')
   189	      ORDER BY created_at DESC
   190	      LIMIT 10
   191	    `).all();
   192	
   193	    constitutionalCache = (rows as Record<string, unknown>[]).map((r) => ({
   194	      id: r.id as number,
   195	      specFolder: r.spec_folder as string,
   196	      filePath: r.file_path as string,
   197	      title: r.title as string,
   198	      importanceTier: r.importance_tier as string
   199	    }));
   200	    constitutionalCacheTime = now;
   201	
   202	    return constitutionalCache;
   203	  } catch (err: unknown) {
   204	    const message = err instanceof Error ? err.message : String(err);
   205	    console.warn('[SK-004] Failed to fetch constitutional memories:', message);
   206	    return [];
   207	  }
   208	}
   209	
   210	function clearConstitutionalCache(): void {
   211	  constitutionalCache = null;
   212	  constitutionalCacheTime = 0;
   213	}
   214	
   215	function getCodeGraphStatusSnapshot(): NonNullable<AutoSurfaceResult['codeGraphStatus']> {
   216	  try {
   217	    const stats = graphDb.getStats();
   218	    const staleCount = (graphDb.getDb().prepare(`
   219	      SELECT COUNT(*) as c FROM code_files
   220	      WHERE parse_health = 'error' OR parse_health = 'recovered'
   221	    `).get() as { c: number }).c;
   222	
   223	    return {
   224	      status: 'ok',
   225	      data: {
   226	        totalFiles: stats.totalFiles,
   227	        totalNodes: stats.totalNodes,
   228	        totalEdges: stats.totalEdges,
   229	        staleFiles: staleCount,
   230	        lastScanAt: stats.lastScanTimestamp,
   231	        dbFileSize: stats.dbFileSize,
   232	        schemaVersion: stats.schemaVersion,
   233	        nodesByKind: stats.nodesByKind,
   234	        edgesByType: stats.edgesByType,
   235	        parseHealth: stats.parseHealthSummary,
   236	      },
   237	    };
   238	  } catch (err: unknown) {
   239	    return {
   240	      status: 'error',
   241	      error: `Code graph not initialized: ${err instanceof Error ? err.message : String(err)}`,
   242	    };
   243	  }
   244	}
   245	
   246	/* ───────────────────────────────────────────────────────────────
   247	   5. AUTO-SURFACE MEMORIES
   248	──────────────────────────────────────────────────────────────── */
   249	
   250	function enforceAutoSurfaceTokenBudget(
   251	  result: AutoSurfaceResult | null,
   252	  tokenBudget: number,
   253	  hookName: 'tool-dispatch' | 'compaction' | 'memory-aware'
   254	): AutoSurfaceResult | null {
   255	  if (!result) {
   256	    return null;
   257	  }
   258	
   259	  const measureTokens = (candidate: AutoSurfaceResult): number =>
   260	    estimateTokenCount(JSON.stringify(candidate));
   261	
   262	  const budgetLimit = Number.isFinite(tokenBudget) && tokenBudget > 0
   263	    ? tokenBudget
   264	    : TOOL_DISPATCH_TOKEN_BUDGET;
   265	
   266	  let boundedResult: AutoSurfaceResult = result;
   267	  let tokenCount = measureTokens(boundedResult);
   268	
   269	  if (tokenCount <= budgetLimit) {
   270	    return boundedResult;
   271	  }
   272	
   273	  const triggered = [...boundedResult.triggered];
   274	  while (triggered.length > 0 && tokenCount > budgetLimit) {
   275	    triggered.pop();
   276	    boundedResult = { ...boundedResult, triggered };
   277	    tokenCount = measureTokens(boundedResult);
   278	  }
   279	
   280	  const constitutional = [...boundedResult.constitutional];
   281	  while (constitutional.length > 0 && tokenCount > budgetLimit) {
   282	    constitutional.pop();
   283	    boundedResult = { ...boundedResult, constitutional };
   284	    tokenCount = measureTokens(boundedResult);
   285	  }
   286	
   287	  if (tokenCount > budgetLimit) {
   288	    console.warn(
   289	      `[SK-004] Auto-surface output exceeded ${hookName} token budget ` +
   290	      `(${tokenCount} > ${budgetLimit}); dropping payload`
   291	    );
   292	    return null;
   293	  }
   294	
   295	  console.warn(
   296	    `[SK-004] Auto-surface output truncated to fit ${hookName} token budget ` +
   297	    `(${tokenCount}/${budgetLimit})`
   298	  );
   299	  return boundedResult;
   300	}
   301	
   302	/**
   303	 * Phase C: Get top-N attention-weighted memory IDs from working memory.
   304	 * Used to boost trigger-matched results that also appear in the active
   305	 * working set, improving surface relevance.
   306	 *
   307	 * @param limit - Maximum number of memory IDs to return
   308	 * @returns Set of memory IDs with high attention in working memory
   309	 */
   310	function getAttentionWeightedMemoryIds(limit: number = 5): Set<number> {
   311	  try {
   312	    const db: Database | null = vectorIndex.getDb();
   313	    if (!db) return new Set();
   314	
   315	    // Query top attention-weighted memories, scoped to the current session
   316	    // by filtering to entries focused within the last hour. This prevents
   317	    // stale cross-session entries from influencing auto-surface ordering.
   318	    const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000).toISOString();
   319	    const rows = db.prepare(`
   320	      SELECT DISTINCT wm.memory_id

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts | sed -n '1,120p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Shared Hook Utilities
     3	// ───────────────────────────────────────────────────────────────
     4	// Keep the provenance re-exports in lockstep with hooks/gemini/shared.ts.
     5	// Copilot imports these helpers straight from ../shared-provenance.js, so
     6	// drift in any one runtime silently forks the recovered-payload contract.
     7	
     8	/** Timeout for hook scripts — must stay under 2s hard cap */
     9	export const HOOK_TIMEOUT_MS = 1800;
    10	/** Token budget for compaction context injection */
    11	export const COMPACTION_TOKEN_BUDGET = 4000;
    12	/** Token budget for session priming (startup/resume) */
    13	export const SESSION_PRIME_TOKEN_BUDGET = 2000;
    14	
    15	/** Parsed JSON from Claude Code hook stdin */
    16	export interface HookInput {
    17	  readonly session_id?: string;
    18	  readonly transcript_path?: string;
    19	  readonly trigger?: 'auto' | 'manual';
    20	  readonly source?: 'startup' | 'resume' | 'clear' | 'compact';
    21	  readonly custom_instructions?: string;
    22	  readonly stop_hook_active?: boolean;
    23	  readonly last_assistant_message?: string;
    24	  readonly [key: string]: unknown;
    25	}
    26	
    27	/** A titled section for hook stdout output */
    28	export interface OutputSection {
    29	  readonly title: string;
    30	  readonly content: string;
    31	}
    32	
    33	/** Require a non-empty session_id for any hook that touches shared temp-state. */
    34	export function getRequiredSessionId(sessionId: unknown, surface: string): string {
    35	  const normalized = typeof sessionId === 'string' ? sessionId.trim() : '';
    36	  if (normalized.length === 0) {
    37	    throw new Error(`${surface} hook payload missing required session_id`);
    38	  }
    39	  return normalized;
    40	}
    41	
    42	/** Read and parse JSON from stdin. Returns null on failure. */
    43	export async function parseHookStdin(): Promise<HookInput | null> {
    44	  try {
    45	    const chunks: Buffer[] = [];
    46	    for await (const chunk of process.stdin) {
    47	      chunks.push(chunk as Buffer);
    48	    }
    49	    const raw = Buffer.concat(chunks).toString('utf-8').trim();
    50	    if (!raw) return null;
    51	    return JSON.parse(raw) as HookInput;
    52	  } catch (err: unknown) {
    53	    hookLog('warn', 'stdin', `Failed to parse hook stdin: ${err instanceof Error ? err.message : String(err)}`);
    54	    return null;
    55	  }
    56	}
    57	
    58	/** Format sections into readable text block for stdout injection */
    59	export function formatHookOutput(sections: OutputSection[]): string {
    60	  return sections
    61	    .filter(s => s.content.trim().length > 0)
    62	    .map(s => `## ${s.title}\n${s.content}`)
    63	    .join('\n\n');
    64	}
    65	
    66	/** Wrap a promise with a timeout. Returns fallback value on timeout. */
    67	export async function withTimeout<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T> {
    68	  let timer: ReturnType<typeof setTimeout> | undefined;
    69	  const timeout = new Promise<T>((resolve) => {
    70	    timer = setTimeout(() => {
    71	      hookLog('warn', 'timeout', `Operation timed out after ${ms}ms`);
    72	      resolve(fallback);
    73	    }, ms);
    74	  });
    75	  try {
    76	    return await Promise.race([promise, timeout]);
    77	  } finally {
    78	    if (timer !== undefined) clearTimeout(timer);
    79	  }
    80	}
    81	
    82	/** Log to stderr (stdout is reserved for hook output injection) */
    83	export function hookLog(level: 'info' | 'warn' | 'error', tag: string, msg: string): void {
    84	  const prefix = `[speckit-hook:${tag}]`;
    85	  const line = `${prefix} ${msg}`;
    86	  if (level === 'error') {
    87	    process.stderr.write(`ERROR ${line}\n`);
    88	  } else if (level === 'warn') {
    89	    process.stderr.write(`WARN ${line}\n`);
    90	  } else {
    91	    process.stderr.write(`INFO ${line}\n`);
    92	  }
    93	}
    94	
    95	/** Estimate token count (rough: 1 token ≈ 4 chars) and truncate if over budget */
    96	export function truncateToTokenBudget(text: string, maxTokens: number): string {
    97	  const estimatedTokens = Math.ceil(text.length / 4);
    98	  if (estimatedTokens <= maxTokens) return text;
    99	  const maxChars = maxTokens * 4;
   100	  return text.slice(0, maxChars) + '\n[...truncated to fit token budget]';
   101	}
   102	
   103	// Provenance helpers (escapeProvenanceField, sanitizeRecoveredPayload,
   104	// wrapRecoveredCompactPayload) live in ../shared-provenance.ts so they
   105	// can be consumed by Claude, Gemini, and Copilot runtimes without
   106	// transitive coupling to this Claude-specific module (T-W1-HOK-02).
   107	export {
   108	  escapeProvenanceField,
   109	  sanitizeRecoveredPayload,
   110	  wrapRecoveredCompactPayload,
   111	  type RecoveredCompactMetadata,
   112	} from '../shared-provenance.js';
   113	
   114	/** Calculate pressure-adjusted budget based on context window usage */
   115	export function calculatePressureAdjustedBudget(
   116	  currentTokens: number | undefined,
   117	  maxTokens: number | undefined,
   118	  baseBudget: number,
   119	): number {
   120	  if (!currentTokens || !maxTokens || maxTokens <= 0) return baseBudget;

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts | sed -n '1,180p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Compact Merger
     3	// ───────────────────────────────────────────────────────────────
     4	// Merges context from multiple sources (Memory, Code Graph, CocoIndex, Session)
     5	// into a unified compact brief for compaction injection.
     6	
     7	import { allocateBudget, createDefaultSources, type AllocationResult } from './budget-allocator.js';
     8	import {
     9	  createSharedPayloadEnvelope,
    10	  type PreMergeSelectionMetadata,
    11	  type SharedPayloadEnvelope,
    12	} from '../../lib/context/shared-payload.js';
    13	
    14	/** Input from each context source */
    15	export interface MergeInput {
    16	  constitutional: string;    // Constitutional rules (from Memory)
    17	  codeGraph: string;         // Structural context (from Code Graph)
    18	  cocoIndex: string;         // Semantic neighbors (from CocoIndex)
    19	  triggered: string;         // Triggered memories (from Memory)
    20	  sessionState: string;      // Active task / next steps
    21	}
    22	
    23	/** Per-source freshness metadata */
    24	export interface SourceFreshness {
    25	  source: string;
    26	  lastUpdated: string | null;
    27	  staleness: 'fresh' | 'recent' | 'stale' | 'unknown';
    28	}
    29	
    30	/** Merged compact brief with metadata */
    31	export interface MergedBrief {
    32	  text: string;
    33	  sections: {
    34	    name: string;
    35	    content: string;
    36	    tokenEstimate: number;
    37	    source: string;
    38	  }[];
    39	  allocation: AllocationResult;
    40	  payloadContract: SharedPayloadEnvelope;
    41	  metadata: {
    42	    totalTokenEstimate: number;
    43	    sourceCount: number;
    44	    mergedAt: string;
    45	    mergeDurationMs: number;
    46	    deduplicatedFiles: number;
    47	    freshness: SourceFreshness[];
    48	    selection?: PreMergeSelectionMetadata;
    49	  };
    50	}
    51	
    52	/** Estimate tokens from string (4 chars ≈ 1 token) */
    53	function estimateTokens(text: string): number {
    54	  return Math.ceil(text.length / 4);
    55	}
    56	
    57	/** Truncate text to fit within a token budget */
    58	function truncateToTokens(text: string, maxTokens: number): string {
    59	  if (maxTokens <= 0) return '';
    60	  if (estimateTokens(text) <= maxTokens) return text;
    61	
    62	  const marker = '\n[...truncated]';
    63	  const maxChars = maxTokens * 4;
    64	  if (marker.length >= maxChars) {
    65	    return text.slice(0, maxChars);
    66	  }
    67	
    68	  const contentChars = Math.max(0, maxChars - marker.length);
    69	  return text.slice(0, contentChars) + marker;
    70	}
    71	
    72	/** Extract file paths from a text section for deduplication */
    73	function extractFilePathsFromText(text: string): Set<string> {
    74	  const paths = new Set<string>();
    75	  const pathRegex = /(?:\/[\w.-]+){2,}(?:\.\w+)/g;
    76	  const matches = text.match(pathRegex);
    77	  if (matches) matches.forEach(m => paths.add(m));
    78	  return paths;
    79	}
    80	
    81	/** Deduplicate file references across sections — higher priority sources keep their mentions */
    82	function deduplicateFilePaths(sections: MergedBrief['sections']): number {
    83	  const seenFiles = new Set<string>();
    84	  let removedCount = 0;
    85	
    86	  for (const section of sections) {
    87	    const filePaths = extractFilePathsFromText(section.content);
    88	    const duplicates: string[] = [];
    89	
    90	    for (const fp of filePaths) {
    91	      if (seenFiles.has(fp)) {
    92	        duplicates.push(fp);
    93	        removedCount++;
    94	      } else {
    95	        seenFiles.add(fp);
    96	      }
    97	    }
    98	
    99	    // Remove duplicate file path lines from lower-priority sections
   100	    if (duplicates.length > 0) {
   101	      let content = section.content;
   102	      for (const dup of duplicates) {
   103	        const lineRegex = new RegExp(`^.*${dup.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}.*$\n?`, 'gm');
   104	        content = content.replace(lineRegex, '');
   105	      }
   106	      section.content = content.trim();
   107	      section.tokenEstimate = estimateTokens(section.content);
   108	    }
   109	  }
   110	  return removedCount;
   111	}
   112	
   113	/**
   114	 * Merge context from multiple sources into a compact brief.
   115	 *
   116	 * Strategy:
   117	 * 1. Allocate budget across sources (floor + overflow)
   118	 * 2. Truncate each source to its granted budget
   119	 * 3. Deduplicate at file level (same file from multiple sources → keep highest priority)
   120	 * 4. Render sections in priority order with headers
   121	 */
   122	export function mergeCompactBrief(
   123	  input: MergeInput,
   124	  totalBudget: number = 4000,
   125	  freshness?: SourceFreshness[],
   126	  selection?: PreMergeSelectionMetadata,
   127	): MergedBrief {
   128	  const startTime = performance.now();
   129	
   130	  const constitutionalSize = estimateTokens(input.constitutional);
   131	  const codeGraphSize = estimateTokens(input.codeGraph);
   132	  const cocoIndexSize = estimateTokens(input.cocoIndex);
   133	  const triggeredSize = estimateTokens(input.triggered);
   134	  const sessionStateSize = estimateTokens(input.sessionState);
   135	
   136	  const sources = createDefaultSources(
   137	    constitutionalSize,
   138	    codeGraphSize,
   139	    cocoIndexSize,
   140	    triggeredSize,
   141	    sessionStateSize,
   142	  );
   143	  const allocation = allocateBudget(sources, totalBudget);
   144	
   145	  // Build sections with granted budgets
   146	  const sections: MergedBrief['sections'] = [];
   147	  const allocationMap = new Map(allocation.allocations.map(a => [a.name, a]));
   148	  const pushSection = (
   149	    inputText: string,
   150	    allocationName: string,
   151	    sectionName: string,
   152	    source: string,
   153	  ): void => {
   154	    if (!inputText.trim()) return;
   155	
   156	    const granted = allocationMap.get(allocationName)?.granted ?? 0;
   157	    if (granted <= 0) return;
   158	
   159	    const content = truncateToTokens(inputText, granted);
   160	    if (!content.trim()) return;
   161	
   162	    sections.push({
   163	      name: sectionName,
   164	      content,
   165	      tokenEstimate: estimateTokens(content),
   166	      source,
   167	    });
   168	  };
   169	
   170	  pushSection(input.constitutional, 'constitutional', 'Constitutional Rules', 'memory');
   171	  pushSection(input.codeGraph, 'codeGraph', 'Active Files & Structural Context', 'code-graph');
   172	  pushSection(input.cocoIndex, 'cocoIndex', 'Semantic Neighbors', 'cocoindex');
   173	  pushSection(input.sessionState, 'sessionState', 'Session State / Next Steps', 'session');
   174	  pushSection(input.triggered, 'triggered', 'Triggered Memories', 'memory');
   175	
   176	  // File-level deduplication across sections
   177	  const deduplicatedFiles = deduplicateFilePaths(sections);
   178	
   179	  // Render final text
   180	  const text = sections

exec
/bin/zsh -lc "rg -n \"truncateToTokenBudget\\(|enforceAutoSurfaceTokenBudget\\(|truncateToBudget\\(|getDynamicTokenBudget\\(|truncateByConfidence\\(|getTokenBudget\\(\" .opencode/skills/system-spec-kit/mcp_server --glob '"'!tests/**'"' --glob '"'!**/*.md'"'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1139:          const budget = getTokenBudget(name);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1362:    const truncated = hybridSearch.truncateToBudget([oversized, compact], budget, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1393:    const truncated = hybridSearch.truncateToBudget([oversizedSecond, oversizedTop], 50, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search.vitest.ts:1419:    const truncated = hybridSearch.truncateToBudget([resultWithGetter], 1, {
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:114:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:123:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:147:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:162:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:170:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:178:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:185:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:212:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:225:    const out = truncateByConfidence(results, { minResults: 2 });
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:233:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:260:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:267:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:274:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:291:    const out = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:300:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:308:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:317:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:342:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:358:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:418:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:428:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:437:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/confidence-truncation.vitest.ts:447:    const out = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:250:function enforceAutoSurfaceTokenBudget(
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:401:    return enforceAutoSurfaceTokenBudget({
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:527:      return enforceAutoSurfaceTokenBudget({
.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:539:    return enforceAutoSurfaceTokenBudget({
.opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts:160:    const additionalContext = truncateToTokenBudget(
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts:391:  const output = truncateToTokenBudget(formatHookOutput(sections), adjustedBudget);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96:export function truncateToTokenBudget(text: string, maxTokens: number): string {
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:396:    payload = truncateToTokenBudget(mergedContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts:425:    payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts:230:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:86:    const truncated = truncateToBudget(rows, budgetForTopTwo, {
.opencode/skills/system-spec-kit/mcp_server/tests/hybrid-search-context-headers.vitest.ts:126:    const truncated = truncateToBudget(rows, adjustedBudget, {
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-cache.ts:142:  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:59:      const truncated = truncateToTokenBudget(largePayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-precompact.vitest.ts:66:      const result = truncateToTokenBudget(smallPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts:307:  const rawOutput = truncateToTokenBudget(formatHookOutput(sections), budget);
.opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts:92:  const rawOutput = truncateToTokenBudget(sections.join('\n'), COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:225:    const { results: truncated, truncated: wasTruncated } = truncateToBudget(results, 500);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:247:    const { results: out, truncated } = truncateToBudget(results, 2000);
.opencode/skills/system-spec-kit/mcp_server/tests/graph-scoring-integration.vitest.ts:357:    const { results: output, truncated } = truncateToBudget(results, budget);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:40:        const actual = layerDefs.getTokenBudget(tool);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:46:      const budget = layerDefs.getTokenBudget('nonexistent_tool');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts:289:      expect(serverSrc).toContain('getTokenBudget(name)');
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:94:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:95:    expect(getTokenBudget()).toBe(2000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:100:    expect(getTokenBudget()).toBe(5000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:105:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:108:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:111:    expect(getTokenBudget()).toBe(DEFAULT_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:130:    const { results: output, truncated, overflow } = truncateToBudget(results, 10000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:138:    const { results, truncated, overflow } = truncateToBudget([], 100);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:156:    const { results: output, truncated, overflow } = truncateToBudget(results, budget);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:180:    const { results: output, truncated, overflow } = truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:210:    const { results: output, truncated, overflow } = truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:229:    const { overflow } = truncateToBudget(results, 100, { queryId: 'eval-test' });
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:252:    const { results: output } = truncateToBudget(results, 10000);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:263:    // With undefined budget — should use getTokenBudget()
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:264:    const r1 = truncateToBudget(results);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:268:    const r2 = truncateToBudget(results, 0);
.opencode/skills/system-spec-kit/mcp_server/tests/token-budget.vitest.ts:334:    const { truncated } = truncateToBudget(results, adjusted);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1065:    const budgetResult = getDynamicTokenBudget(routeResult.tier);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1592:      const truncationResult: TruncationResult = truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1678:    const budgeted = truncateToBudget(reranked, adjustedBudget, {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2363:function getTokenBudget(): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2398:function truncateToBudget(
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2403:  const effectiveBudget = (budget && budget > 0) ? budget : getTokenBudget();
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:209:      const truncated = truncateToTokenBudget(output, SESSION_PRIME_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/tests/hook-session-start.vitest.ts:216:      const truncated = truncateToTokenBudget(longPayload, COMPACTION_TOKEN_BUDGET);
.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:102:function truncateByConfidence(
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:258:  // 4.5 getTokenBudget()
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:260:  describe('getTokenBudget()', () => {
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:273:        expect(mod.getTokenBudget(tool)).toBe(expected);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:278:      expect(mod.getTokenBudget('nonexistent_tool')).toBe(1000);
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:282:      expect(typeof mod.getTokenBudget('memory_context')).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/layer-definitions.vitest.ts:283:      expect(typeof mod.getTokenBudget('fake_tool')).toBe('number');
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:102:    expect(truncateToTokenBudget(short, 1000)).toBe(short);
.opencode/skills/system-spec-kit/mcp_server/tests/edge-cases.vitest.ts:108:    const result = truncateToTokenBudget(long, 100);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:225:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:244:    const output = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:260:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:280:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:294:    const output = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:311:    const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:317:    const result = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:323:    const result = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-query-intelligence.vitest.ts:331:    const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:162:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:183:      const truncated = truncateByConfidence(results);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:202:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:226:      const truncResult = truncateByConfidence(scoredResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:281:      const simpleBudget = getDynamicTokenBudget(simpleResult.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:291:      const complexBudget = getDynamicTokenBudget(complexResult.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:360:      const truncResult = truncateByConfidence(results, { minResults: 3 });
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:448:      const emptyTrunc = truncateByConfidence([]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:483:      const singleTrunc = truncateByConfidence([{ id: 1, score: 0.9 }]);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:513:      const truncResult = truncateByConfidence(tiedResults);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:583:      const budget = getDynamicTokenBudget(classification.tier);
.opencode/skills/system-spec-kit/mcp_server/tests/cross-feature-integration-eval.vitest.ts:626:      const truncated = truncateByConfidence(scored);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:105:    const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:112:    const result = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:118:    const result = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:124:    const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:138:    const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:145:    const result = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:152:    const result = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:159:    const simple = getDynamicTokenBudget('simple').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:160:    const moderate = getDynamicTokenBudget('moderate').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:161:    const complex = getDynamicTokenBudget('complex').budget;
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:167:    const result = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:187:    expect(getDynamicTokenBudget('simple', customConfig).budget).toBe(800);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:188:    expect(getDynamicTokenBudget('moderate', customConfig).budget).toBe(1600);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:189:    expect(getDynamicTokenBudget('complex', customConfig).budget).toBe(3200);
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:210:      const result = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/dynamic-token-budget.vitest.ts:217:    const result = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:600:    const simple = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:601:    const moderate = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:602:    const complex = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:613:    const simple = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:614:    const moderate = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:615:    const complex = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:626:    const s = getDynamicTokenBudget('simple');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:627:    const m = getDynamicTokenBudget('moderate');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:628:    const c = getDynamicTokenBudget('complex');
.opencode/skills/system-spec-kit/mcp_server/tests/feature-eval-graph-signals.vitest.ts:638:    const result = getDynamicTokenBudget('simple', customConfig);
.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:69:function getDynamicTokenBudget(
.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:193:export function getTokenBudget(toolName: string): number {

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts | sed -n '500,620p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   500	function resolveSubjectToRef(subject: string): ArtifactRef | null {
   501	  try {
   502	    const d = graphDb.getDb();
   503	    // Try as symbolId, fqName, or name
   504	    const row = d.prepare(`
   505	      SELECT * FROM code_nodes
   506	      WHERE symbol_id = ? OR fq_name = ? OR name = ?
   507	      LIMIT 1
   508	    `).get(subject, subject, subject) as Record<string, unknown> | undefined;
   509	
   510	    if (row) {
   511	      return {
   512	        filePath: row.file_path as string,
   513	        startLine: row.start_line as number,
   514	        endLine: row.end_line as number,
   515	        symbolId: row.symbol_id as string,
   516	        fqName: row.fq_name as string,
   517	        kind: row.kind as string,
   518	        confidence: 0.9,
   519	        resolution: 'exact',
   520	        score: null,
   521	        snippet: null,
   522	        range: null,
   523	        provider: 'code_graph',
   524	      };
   525	    }
   526	  } catch { /* DB not available */ }
   527	  return null;
   528	}
   529	
   530	/**
   531	 * Format sections into compact text brief within token budget.
   532	 * Never-drops guarantee: always includes top seed, root anchor, one boundary edge, one next action.
   533	 */
   534	function formatTextBrief(sections: GraphContextSection[], budgetTokens: number, _anchors?: ArtifactRef[]): FormattedTextBrief {
   535	  const maxChars = budgetTokens * 4;
   536	  const lines: string[] = [];
   537	  let omittedSections = 0;
   538	
   539	  // Priority rendering: first section is always fully rendered (never dropped)
   540	  for (let i = 0; i < sections.length; i++) {
   541	    const section = sections[i];
   542	    const isFirst = i === 0;
   543	    const nodeLimit = isFirst ? 15 : Math.max(5, 15 - i * 3);
   544	    const edgeLimit = isFirst ? 10 : Math.max(3, 10 - i * 2);
   545	
   546	    lines.push(`### ${section.anchor}`);
   547	
   548	    if (section.nodes.length > 0) {
   549	      lines.push('Symbols:');
   550	      for (const n of section.nodes.slice(0, nodeLimit)) {
   551	        lines.push(`  ${n.kind} ${n.name} (${n.file}:${n.line})`);
   552	      }
   553	      if (section.nodes.length > nodeLimit) {
   554	        lines.push(`  ... +${section.nodes.length - nodeLimit} more`);
   555	      }
   556	    }
   557	
   558	    if (section.edges.length > 0) {
   559	      lines.push('Relationships:');
   560	      for (const e of section.edges.slice(0, edgeLimit)) {
   561	        const metadata = [
   562	          e.reason ? `reason=${e.reason}` : null,
   563	          e.step ? `step=${e.step}` : null,
   564	          typeof e.confidence === 'number' ? `confidence=${e.confidence}` : null,
   565	        ].filter(Boolean).join(' ');
   566	        lines.push(`  ${e.from} -[${e.type}${metadata ? ` ${metadata}` : ''}]-> ${e.to}`);
   567	      }
   568	      if (section.edges.length > edgeLimit) {
   569	        lines.push(`  ... +${section.edges.length - edgeLimit} more`);
   570	      }
   571	    }
   572	
   573	    lines.push('');
   574	
   575	    // Budget check: stop adding sections if we're over budget (but first section always included)
   576	    if (!isFirst && lines.join('\n').length > maxChars * 0.9) {
   577	      omittedSections = sections.length - i - 1;
   578	      lines.push(`[${omittedSections} more sections omitted — budget limit]`);
   579	      break;
   580	    }
   581	  }
   582	
   583	  let result = lines.join('\n');
   584	  let truncated = false;
   585	  if (result.length > maxChars) {
   586	    truncated = true;
   587	    result = result.slice(0, maxChars) + '\n[...truncated]';
   588	  }
   589	  return {
   590	    text: result,
   591	    omittedSections,
   592	    truncated,
   593	  };
   594	}

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts | sed -n '40,325p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
    40	──────────────────────────────────────────────────────────────── */
    41	
    42	const MIN_TOTAL_MEMORY_BYTES = 8 * 1024 * 1024 * 1024;
    43	// Lower total-memory threshold when custom model is configured — still
    44	// Prevents OOM on truly constrained systems without blocking intentional
    45	// Overrides. We use totalmem() because freemem() is unreliable on macOS/Linux
    46	// Where disk cache can make "free" memory appear deceptively low.
    47	const MIN_TOTAL_MEMORY_CUSTOM_BYTES = 2 * 1024 * 1024 * 1024;
    48	const DEFAULT_MODEL_RELATIVE_PATH = path.join('models', 'bge-reranker-v2-m3.Q4_K_M.gguf');
    49	const RERANKER_TIMEOUT_MS = Number(process.env.SPECKIT_RERANKER_TIMEOUT_MS) || 30_000;
    50	const MAX_PROMPT_BYTES = 10 * 1024;
    51	const MAX_RERANK_CANDIDATES = 50;
    52	
    53	/* ───────────────────────────────────────────────────────────────
    54	   4. MODEL MANAGEMENT
    55	──────────────────────────────────────────────────────────────── */
    56	
    57	let cachedLlama: unknown | null = null;
    58	let cachedModel: unknown | null = null;
    59	let cachedModelPath: string | null = null;
    60	let modelLoadPromise: Promise<unknown> | null = null;
    61	let modelLoadPromisePath: string | null = null;
    62	
    63	function resolveModelPath(): string {
    64	  const configured = process.env.SPECKIT_RERANKER_MODEL?.trim();
    65	  if (!configured) {
    66	    return path.resolve(process.cwd(), DEFAULT_MODEL_RELATIVE_PATH);
    67	  }
    68	  if (path.isAbsolute(configured)) {
    69	    return configured;
    70	  }
    71	  return path.resolve(process.cwd(), configured);
    72	}
    73	
    74	function resolveRowText(row: LocalRerankRow): string {
    75	  if (typeof row.content === 'string' && row.content.trim().length > 0) {
    76	    return row.content.trim();
    77	  }
    78	  if (typeof row.file_path === 'string' && row.file_path.trim().length > 0) {
    79	    return row.file_path.trim();
    80	  }
    81	  return '';
    82	}
    83	
    84	async function loadNodeLlamaCpp(): Promise<NodeLlamaCppModule> {
    85	  const dynamicImport = new Function('m', 'return import(m)');
    86	  const mod = await dynamicImport('node-llama-cpp') as unknown;
    87	  if (!mod || typeof mod !== 'object' || typeof (mod as NodeLlamaCppModule).getLlama !== 'function') {
    88	    throw new Error('node-llama-cpp loaded without getLlama() export');
    89	  }
    90	  return mod as NodeLlamaCppModule;
    91	}
    92	
    93	async function ensureModelLoaded(modelPath: string): Promise<unknown> {
    94	  // Fast path: model already cached for this path
    95	  if (cachedModel && cachedModelPath === modelPath) {
    96	    return cachedModel;
    97	  }
    98	
    99	  // H4 fix: Explicitly reuse in-flight promise for the same model path
   100	  // To prevent concurrent callers from orphaning promises
   101	  if (modelLoadPromise && modelLoadPromisePath === modelPath) {
   102	    return await modelLoadPromise;
   103	  }
   104	
   105	  // Discard stale promise if the model path changed since the last load
   106	  if (modelLoadPromise && modelLoadPromisePath !== modelPath) {
   107	    modelLoadPromise = null;
   108	    modelLoadPromisePath = null;
   109	  }
   110	
   111	  modelLoadPromisePath = modelPath;
   112	  modelLoadPromise = (async () => {
   113	    const llamaModule = await loadNodeLlamaCpp();
   114	    cachedLlama = await llamaModule.getLlama();
   115	    if (!cachedLlama || typeof cachedLlama !== 'object') {
   116	      throw new Error('getLlama() did not return a usable object');
   117	    }
   118	    const loadModel = (cachedLlama as { loadModel?: (args: { modelPath: string }) => Promise<unknown> }).loadModel;
   119	    if (typeof loadModel !== 'function') {
   120	      throw new Error('node-llama-cpp runtime missing loadModel()');
   121	    }
   122	    const model = await loadModel.call(cachedLlama, { modelPath });
   123	    if (!model || typeof model !== 'object') {
   124	      throw new Error('loadModel() returned invalid model');
   125	    }
   126	    cachedModel = model;
   127	    cachedModelPath = modelPath;
   128	    return model;
   129	  })();
   130	
   131	  try {
   132	    return await modelLoadPromise;
   133	  } catch (error: unknown) {
   134	    modelLoadPromise = null;
   135	    modelLoadPromisePath = null;
   136	    cachedModel = null;
   137	    cachedModelPath = null;
   138	    throw error;
   139	  }
   140	}
   141	
   142	/* ───────────────────────────────────────────────────────────────
   143	   5. SCORING
   144	──────────────────────────────────────────────────────────────── */
   145	
   146	function normalizeScore(value: number): number {
   147	  if (!Number.isFinite(value)) return 0;
   148	  // Keep score bounded and monotonic without assuming provider-native scale.
   149	  return (Math.tanh(value) + 1) / 2;
   150	}
   151	
   152	function extractNumericScore(value: unknown): number | null {
   153	  if (typeof value === 'number' && Number.isFinite(value)) {
   154	    return value;
   155	  }
   156	  if (typeof value === 'string') {
   157	    const parsed = Number.parseFloat(value);
   158	    return Number.isFinite(parsed) ? parsed : null;
   159	  }
   160	  if (value && typeof value === 'object') {
   161	    const record = value as Record<string, unknown>;
   162	    const directKeys = ['score', 'relevance', 'relevanceScore', 'similarity', 'logit'];
   163	    for (const key of directKeys) {
   164	      const extracted = extractNumericScore(record[key]);
   165	      if (extracted !== null) return extracted;
   166	    }
   167	  }
   168	  return null;
   169	}
   170	
   171	async function scorePrompt(context: unknown, prompt: string): Promise<number> {
   172	  if (!context || typeof context !== 'object') {
   173	    throw new Error('Invalid llama context');
   174	  }
   175	
   176	  const directFns = ['score', 'getScore', 'evaluate', 'eval'] as const;
   177	  for (const fnName of directFns) {
   178	    const fn = (context as Record<string, unknown>)[fnName];
   179	    if (typeof fn === 'function') {
   180	      const raw = await (fn as (input: string) => Promise<unknown>).call(context, prompt);
   181	      const score = extractNumericScore(raw);
   182	      if (score !== null) return normalizeScore(score);
   183	    }
   184	  }
   185	
   186	  const getSequence = (context as { getSequence?: () => Promise<unknown> }).getSequence;
   187	  if (typeof getSequence === 'function') {
   188	    const sequence = await getSequence.call(context);
   189	    if (sequence && typeof sequence === 'object') {
   190	      const seqEval = (sequence as { evaluate?: (input: string) => Promise<unknown> }).evaluate;
   191	      if (typeof seqEval === 'function') {
   192	        const raw = await seqEval.call(sequence, prompt);
   193	        const score = extractNumericScore(raw);
   194	        if (score !== null) return normalizeScore(score);
   195	      }
   196	    }
   197	  }
   198	
   199	  throw new Error('Unable to resolve a scoring method from llama context');
   200	}
   201	
   202	/* ───────────────────────────────────────────────────────────────
   203	   6. PUBLIC API
   204	──────────────────────────────────────────────────────────────── */
   205	
   206	/**
   207	 * Feature-flag gate for local reranking.
   208	 * This guard is intentionally strict: local reranking only runs when the
   209	 * operator opts in with `RERANKER_LOCAL=true`, has enough total RAM, and the
   210	 * configured GGUF model file is available.
   211	 */
   212	export async function canUseLocalReranker(): Promise<boolean> {
   213	  if (process.env.RERANKER_LOCAL?.toLowerCase().trim() !== 'true') {
   214	    return false;
   215	  }
   216	
   217	  // Use total system memory instead of free memory. On macOS/Linux,
   218	  // Os.freemem() can look artificially low due to disk cache usage.
   219	  const hasCustomModel = Boolean(process.env.SPECKIT_RERANKER_MODEL?.trim());
   220	  const memThreshold = hasCustomModel ? MIN_TOTAL_MEMORY_CUSTOM_BYTES : MIN_TOTAL_MEMORY_BYTES;
   221	  if (os.totalmem() < memThreshold) {
   222	    return false;
   223	  }
   224	
   225	  const modelPath = resolveModelPath();
   226	  try {
   227	    await access(modelPath);
   228	    return true;
   229	  } catch (_error: unknown) {
   230	    return false;
   231	  }
   232	}
   233	
   234	/**
   235	 * Local GGUF reranking entrypoint for Stage 3.
   236	 * Falls back to original ordering whenever preconditions fail or runtime
   237	 * inference errors occur, preserving deterministic behavior.
   238	 */
   239	export async function rerankLocal<T extends LocalRerankRow>(
   240	  query: string,
   241	  candidates: T[],
   242	  topK: number
   243	): Promise<T[]> {
   244	  if (!Array.isArray(candidates) || candidates.length < 2) {
   245	    return candidates;
   246	  }
   247	
   248	  /**
   249	   * Internal guard for direct callers: rerankLocal re-checks eligibility even
   250	   * when invoked outside the Stage 3 flag path, and fails closed to the
   251	   * original ranking when local execution is unavailable.
   252	   */
   253	  const localEnabled = await canUseLocalReranker();
   254	  if (!localEnabled) {
   255	    return candidates;
   256	  }
   257	
   258	  const modelPath = resolveModelPath();
   259	  const rerankCandidates = candidates.slice(0, MAX_RERANK_CANDIDATES);
   260	  const rerankCount = Math.max(1, Math.min(topK, rerankCandidates.length));
   261	  const startedAt = Date.now();
   262	
   263	  let context: unknown | null = null;
   264	  let timeoutId: ReturnType<typeof setTimeout> | null = null;
   265	  try {
   266	    const model = await ensureModelLoaded(modelPath);
   267	    const createContext = (model as { createContext?: () => Promise<unknown> }).createContext;
   268	    if (typeof createContext !== 'function') {
   269	      throw new Error('Loaded model does not expose createContext()');
   270	    }
   271	    context = await createContext.call(model);
   272	
   273	    /**
   274	     * Feature-flagged local inference branch.
   275	     * This code path exists for opt-in deployments (`RERANKER_LOCAL=true`) so
   276	     * local GGUF reranking can be exercised without changing the default
   277	     * remote/fallback behavior for non-opted-in environments.
   278	     *
   279	     * [CHK-069] Quality comparison against Cohere/Voyage is deferred to
   280	     * `tests/reranker-eval-comparison.vitest.ts`, where benchmark protocol and
   281	     * remote-provider requirements are isolated from runtime code paths.
   282	     */
   283	    const reranked = await Promise.race([
   284	      (async (): Promise<T[]> => {
   285	        // Sequential scoring instead of Promise.all to avoid
   286	        // Allocating multiple sequence states simultaneously in VRAM, which
   287	        // Can trigger OOM or context mixing on local LLM inference.
   288	        // PERF(CHK-113): Sequential per-candidate inference. For 20 candidates, latency depends on
   289	        // Model size and hardware. On Apple Silicon with small GGUF (~100MB), expect 200-400ms.
   290	        // Future optimization: batch inference via node-llama-cpp's evaluateBatch API.
   291	        const scored: Array<{ candidate: T; rerankScore: number }> = [];
   292	        for (const candidate of rerankCandidates.slice(0, rerankCount)) {
   293	          const content = resolveRowText(candidate);
   294	          const prompt = `query: ${query}\ndocument: ${content}`;
   295	          // Truncate by character count after converting from bytes to avoid
   296	          // Splitting multi-byte UTF-8 sequences (which produces replacement chars).
   297	          let boundedPrompt = prompt;
   298	          if (Buffer.byteLength(prompt, 'utf8') > MAX_PROMPT_BYTES) {
   299	            const buf = Buffer.from(prompt, 'utf8');
   300	            let end = MAX_PROMPT_BYTES;
   301	            // Walk back to a valid UTF-8 boundary (continuation bytes start with 10xxxxxx).
   302	            while (end > 0 && (buf[end] & 0xC0) === 0x80) { end -= 1; }
   303	            boundedPrompt = buf.subarray(0, end).toString('utf8');
   304	          }
   305	          const rerankScore = await scorePrompt(context, boundedPrompt);
   306	          scored.push({ candidate, rerankScore });
   307	        }
   308	
   309	        scored.sort((a, b) => b.rerankScore - a.rerankScore);
   310	        const rerankedTop = scored.map((entry) => ({
   311	          ...entry.candidate,
   312	          rerankerScore: entry.rerankScore,
   313	          score: entry.rerankScore,
   314	        }));
   315	        const remainder = candidates.slice(rerankCount);
   316	        const elapsed = Date.now() - startedAt;
   317	        console.error(
   318	          `[local-reranker] reranked=${rerankCount} total=${candidates.length} durationMs=${elapsed} model=${path.basename(modelPath)}`
   319	        );
   320	        return [...rerankedTop, ...remainder];
   321	      })(),
   322	      new Promise<never>((_, reject) => {
   323	        timeoutId = setTimeout(() => {
   324	          reject(new Error(`local reranker timed out after ${RERANKER_TIMEOUT_MS}ms`));
   325	        }, RERANKER_TIMEOUT_MS);

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts | sed -n '1,140p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Budget Allocator
     3	// ───────────────────────────────────────────────────────────────
     4	// Distributes a total token budget across multiple context sources
     5	// using floor allocations + overflow redistribution.
     6	
     7	/** Per-source budget configuration */
     8	export interface SourceBudget {
     9	  name: string;
    10	  floor: number;
    11	  actualSize: number; // 0 if source is empty
    12	}
    13	
    14	/** Allocation result for a single source */
    15	export interface SourceAllocation {
    16	  name: string;
    17	  floor: number;
    18	  requested: number;
    19	  granted: number;
    20	  dropped: number;
    21	}
    22	
    23	/** Combined allocation result */
    24	export interface AllocationResult {
    25	  totalBudget: number;
    26	  totalUsed: number;
    27	  overflow: number;
    28	  allocations: SourceAllocation[];
    29	}
    30	
    31	/** Default floor layout for the 4000-token compact brief budget */
    32	export const DEFAULT_FLOORS = {
    33	  constitutional: 700,
    34	  codeGraph: 1200,
    35	  cocoIndex: 900,
    36	  triggered: 400,
    37	  overflow: 800,
    38	} as const;
    39	
    40	/** Priority order for overflow redistribution (highest first) */
    41	const PRIORITY_ORDER = ['constitutional', 'codeGraph', 'cocoIndex', 'sessionState', 'triggered'] as const;
    42	
    43	/**
    44	 * Allocate token budget across sources.
    45	 *
    46	 * Algorithm:
    47	 * 1. Assign floor to each source (capped at actual size)
    48	 * 2. Calculate overflow from empty/under-floor sources
    49	 * 3. Redistribute overflow by priority order
    50	 * 4. Enforce total budget cap with deterministic trim
    51	 */
    52	export function allocateBudget(
    53	  sources: SourceBudget[],
    54	  totalBudget: number = 4000,
    55	): AllocationResult {
    56	  const allocations: SourceAllocation[] = [];
    57	  const floorTotal = sources.reduce((sum, source) => sum + source.floor, 0);
    58	  let overflowPool = Math.max(totalBudget - floorTotal, 0);
    59	
    60	  // Step 1: Assign floors, collect overflow from empty sources
    61	  for (const source of sources) {
    62	    const floor = source.floor;
    63	    const granted = Math.min(floor, source.actualSize);
    64	    const unused = floor - granted;
    65	    overflowPool += unused;
    66	
    67	    allocations.push({
    68	      name: source.name,
    69	      floor,
    70	      requested: source.actualSize,
    71	      granted,
    72	      dropped: Math.max(0, source.actualSize - granted),
    73	    });
    74	  }
    75	
    76	  // Step 2: Redistribute overflow by priority
    77	  if (overflowPool > 0) {
    78	    for (const priorityName of PRIORITY_ORDER) {
    79	      const alloc = allocations.find(a => a.name === priorityName);
    80	      if (!alloc) continue;
    81	
    82	      const headroom = alloc.requested - alloc.granted;
    83	      if (headroom <= 0) continue;
    84	
    85	      const bonus = Math.min(headroom, overflowPool);
    86	      alloc.granted += bonus;
    87	      alloc.dropped -= bonus;
    88	      overflowPool -= bonus;
    89	
    90	      if (overflowPool <= 0) break;
    91	    }
    92	  }
    93	
    94	  // Step 3: Enforce total budget cap (trim in reverse priority order)
    95	  let totalUsed = allocations.reduce((sum, a) => sum + a.granted, 0);
    96	  if (totalUsed > totalBudget) {
    97	    const reversed = [...PRIORITY_ORDER].reverse();
    98	    for (const name of reversed) {
    99	      if (totalUsed <= totalBudget) break;
   100	      const alloc = allocations.find(a => a.name === name);
   101	      if (!alloc) continue;
   102	
   103	      const excess = totalUsed - totalBudget;
   104	      const trim = Math.min(excess, alloc.granted);
   105	      alloc.granted -= trim;
   106	      alloc.dropped += trim;
   107	      totalUsed -= trim;
   108	    }
   109	  }
   110	
   111	  return {
   112	    totalBudget,
   113	    totalUsed: allocations.reduce((sum, a) => sum + a.granted, 0),
   114	    overflow: overflowPool,
   115	    allocations,
   116	  };
   117	}
   118	
   119	/** Create source budgets with default floors */
   120	export function createDefaultSources(
   121	  constitutionalSize: number,
   122	  codeGraphSize: number,
   123	  cocoIndexSize: number,
   124	  triggeredSize: number,
   125	  sessionStateSize: number = 0,
   126	): SourceBudget[] {
   127	  return [
   128	    { name: 'constitutional', floor: DEFAULT_FLOORS.constitutional, actualSize: constitutionalSize },
   129	    { name: 'codeGraph', floor: DEFAULT_FLOORS.codeGraph, actualSize: codeGraphSize },
   130	    { name: 'cocoIndex', floor: DEFAULT_FLOORS.cocoIndex, actualSize: cocoIndexSize },
   131	    { name: 'sessionState', floor: 0, actualSize: sessionStateSize },
   132	    { name: 'triggered', floor: DEFAULT_FLOORS.triggered, actualSize: triggeredSize },
   133	  ];
   134	}

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/codex/session-start.ts | sed -n '145,175p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   145	export async function handleCodexSessionStart(
   146	  input: CodexSessionStartInput | null,
   147	  dependencies: CodexSessionStartDependencies = {},
   148	): Promise<CodexSessionStartOutput | Record<string, never>> {
   149	  const startedAt = dependencies.now?.() ?? performance.now();
   150	  const elapsed = (): number => Number(((dependencies.now?.() ?? performance.now()) - startedAt).toFixed(3));
   151	  const sessionId = sessionIdFor(input);
   152	
   153	  try {
   154	    const source = sourceFor(input);
   155	    const sections = source === 'resume'
   156	      ? (dependencies.resumeSections ?? defaultResumeSections)(sessionId)
   157	      : source === 'clear'
   158	        ? (dependencies.clearSections ?? defaultClearSections)()
   159	        : (dependencies.startupSections ?? buildStartupSections)(input ?? {});
   160	    const additionalContext = truncateToTokenBudget(
   161	      formatHookOutput(sections),
   162	      adjustedBudgetFor(input),
   163	    );
   164	
   165	    if (additionalContext.trim().length === 0) {
   166	      emitDiagnostic('fail_open', input, elapsed(), dependencies.writeDiagnostic);
   167	      return {};
   168	    }
   169	
   170	    emitDiagnostic('ok', input, elapsed(), dependencies.writeDiagnostic);
   171	    return {
   172	      hookSpecificOutput: {
   173	        hookEventName: 'SessionStart',
   174	        additionalContext,
   175	      },

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/claude/session-prime.ts | sed -n '350,400p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   350	  const sessionId = getRequiredSessionId(input.session_id, 'session-prime');
   351	  const source = input.source ?? 'startup';
   352	  hookLog('info', 'session-prime', `SessionStart triggered (source: ${source}, session: ${sessionId})`);
   353	
   354	  let sections: OutputSection[];
   355	  let budget: number;
   356	  let compactIdentity: { cachedAt: string; opaqueId?: string | null } | null = null;
   357	
   358	  switch (source) {
   359	    case 'compact':
   360	      compactIdentity = readCompactPrimeIdentity(sessionId);
   361	      sections = handleCompact(sessionId);
   362	      budget = COMPACTION_TOKEN_BUDGET;
   363	      break;
   364	    case 'startup':
   365	      sections = handleStartup(input);
   366	      budget = SESSION_PRIME_TOKEN_BUDGET;
   367	      break;
   368	    case 'resume':
   369	      sections = handleResume(sessionId);
   370	      budget = SESSION_PRIME_TOKEN_BUDGET;
   371	      break;
   372	    case 'clear':
   373	      sections = handleClear();
   374	      budget = SESSION_PRIME_TOKEN_BUDGET;
   375	      break;
   376	    default:
   377	      sections = handleStartup(input);
   378	      budget = SESSION_PRIME_TOKEN_BUDGET;
   379	  }
   380	
   381	  // Apply token pressure awareness — reduce budget when context window is filling up
   382	  const adjustedBudget = calculatePressureAdjustedBudget(
   383	    input.context_window_tokens as number | undefined,
   384	    input.context_window_max as number | undefined,
   385	    budget,
   386	  );
   387	  if (adjustedBudget !== budget) {
   388	    hookLog('info', 'session-prime', `Token pressure: budget ${budget} → ${adjustedBudget} (window ${input.context_window_tokens}/${input.context_window_max})`);
   389	  }
   390	
   391	  const output = truncateToTokenBudget(formatHookOutput(sections), adjustedBudget);
   392	
   393	  // Write to stdout for Claude Code to inject into conversation.
   394	  // Clear compact payload only after the write callback confirms the
   395	  // output was handed off, so compact recovery cannot be dropped early.
   396	  await writeHookOutput(output);
   397	  if (source === 'compact') {
   398	    clearCompactPrime(sessionId, compactIdentity ?? undefined);
   399	  }
   400	  hookLog('info', 'session-prime', `Output ${output.length} chars for source=${source}`);

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/claude/compact-inject.ts | sed -n '380,432p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   380	    return;
   381	  }
   382	
   383	  const sessionId = getRequiredSessionId(input.session_id, 'compact-inject');
   384	  hookLog('info', 'compact-inject', `PreCompact triggered for session ${sessionId} (trigger: ${input.trigger ?? 'unknown'})`);
   385	
   386	  let transcriptLines: string[] = [];
   387	  if (input.transcript_path) {
   388	    transcriptLines = tailFile(input.transcript_path, 50);
   389	    hookLog('info', 'compact-inject', `Read ${transcriptLines.length} transcript lines`);
   390	  }
   391	
   392	  // Use the 3-source merge pipeline, falling back to legacy on error
   393	  let payload: string;
   394	  try {
   395	    const mergedContext = await buildMergedContext(transcriptLines);
   396	    payload = truncateToTokenBudget(mergedContext, COMPACTION_TOKEN_BUDGET);
   397	    const payloadContract = await buildMergedPayloadContract(transcriptLines);
   398	    const timestamp = new Date().toISOString();
   399	    const updateResult = updateState(sessionId, {
   400	      pendingCompactPrime: {
   401	        payload,
   402	        cachedAt: timestamp,
   403	        payloadContract: {
   404	          ...payloadContract,
   405	          provenance: {
   406	            ...payloadContract.provenance,
   407	            producer: 'hook_cache',
   408	            sourceSurface: 'compact-cache',
   409	            trustState: 'cached',
   410	            sanitizerVersion: CANONICAL_FOLD_VERSION,
   411	            runtimeFingerprint: getUnicodeRuntimeFingerprint(),
   412	          },
   413	        },
   414	      },
   415	    });
   416	    if (!updateResult.persisted) {
   417	      hookLog('warn', 'compact-inject', `Compact context cache was not persisted for session ${sessionId}`);
   418	      return;
   419	    }
   420	    hookLog('info', 'compact-inject', `Cached compact context (${payload.length} chars) for session ${sessionId}`);
   421	    return;
   422	  } catch (err: unknown) {
   423	    hookLog('warn', 'compact-inject', `Merge pipeline failed, falling back to legacy: ${err instanceof Error ? err.message : String(err)}`);
   424	    const rawContext = buildCompactContext(transcriptLines);
   425	    payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
   426	  }
   427	
   428	  const timestamp = new Date().toISOString();
   429	  const updateResult = updateState(sessionId, {
   430	    pendingCompactPrime: {
   431	      payload,
   432	      cachedAt: timestamp,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/plugin_bridges/spec-kit-skill-advisor-bridge.mjs | sed -n '120,155p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   120	  const skillLabel = sanitizeLabel(top?.skillId);
   121	  if (!skillLabel) {
   122	    return null;
   123	  }
   124	
   125	  const parts = [
   126	    `Advisor: ${data.freshness}; use ${skillLabel} ${formatScore(top.confidence)}/${formatScore(top.uncertainty)} pass.`,
   127	  ];
   128	  const status = sanitizeLabel(top.status);
   129	  if (status && status !== 'active') {
   130	    parts.push(`status ${status}.`);
   131	  }
   132	  const redirectTo = sanitizeLabel(top.redirectTo);
   133	  if (redirectTo) {
   134	    parts.push(`redirect_to ${redirectTo}.`);
   135	  }
   136	  const redirectFrom = Array.isArray(top.redirectFrom)
   137	    ? top.redirectFrom.map(sanitizeLabel).filter(Boolean).join(',')
   138	    : null;
   139	  if (redirectFrom) {
   140	    parts.push(`redirect_from ${redirectFrom}.`);
   141	  }
   142	
   143	  const tokenCap = positiveInt(maxTokens, 80);
   144	  return parts.join(' ').slice(0, tokenCap * 4).trim();
   145	}
   146	
   147	async function loadNativeAdvisorModules() {
   148	  const compatModule = await import('../dist/skill_advisor/compat/index.js');
   149	
   150	  return {
   151	    readAdvisorStatus: compatModule.readAdvisorStatus,
   152	    handleAdvisorRecommend: compatModule.handleAdvisorRecommend,
   153	    probeAdvisorDaemon: compatModule.probeAdvisorDaemon ?? null,
   154	    buildSkillAdvisorBrief: compatModule.buildSkillAdvisorBrief,
   155	    renderAdvisorBrief: compatModule.renderAdvisorBrief,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/gemini/session-prime.ts | sed -n '270,312p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   270	  let sections: OutputSection[];
   271	  let budget: number;
   272	  let compactIdentity: { cachedAt: string; opaqueId?: string | null } | null = null;
   273	
   274	  switch (source) {
   275	    case 'compact':
   276	      // Gemini doesn't have a native compact source, but we handle it
   277	      // in case BeforeAgent injects a one-shot compact recovery
   278	      compactIdentity = readCompactPrimeIdentity(sessionId);
   279	      sections = handleCompact(sessionId);
   280	      budget = COMPACTION_TOKEN_BUDGET;
   281	      break;
   282	    case 'startup':
   283	      sections = handleStartup({
   284	        sessionId,
   285	        cwd: input.cwd,
   286	        specFolder: input.specFolder,
   287	      });
   288	      budget = SESSION_PRIME_TOKEN_BUDGET;
   289	      break;
   290	    case 'resume':
   291	      sections = handleResume(sessionId);
   292	      budget = SESSION_PRIME_TOKEN_BUDGET;
   293	      break;
   294	    case 'clear':
   295	      sections = handleClear();
   296	      budget = SESSION_PRIME_TOKEN_BUDGET;
   297	      break;
   298	    default:
   299	      sections = handleStartup({
   300	        sessionId,
   301	        cwd: input.cwd,
   302	        specFolder: input.specFolder,
   303	      });
   304	      budget = SESSION_PRIME_TOKEN_BUDGET;
   305	  }
   306	
   307	  const rawOutput = truncateToTokenBudget(formatHookOutput(sections), budget);
   308	
   309	  // Output as Gemini-compatible JSON with additionalContext.
   310	  // Clear compact payload only AFTER stdout write succeeds.
   311	  const output = formatGeminiOutput(rawOutput);
   312	  process.stdout.write(output);

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/gemini/compact-inject.ts | sed -n '84,98p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
    84	    '## Recovery Instructions',
    85	    'Context was compressed and auto-recovered. For full session state, call `memory_context({ mode: "resume", profile: "resume" })`.',
    86	  ];
    87	
    88	  if (state?.lastSpecFolder) {
    89	    sections.push('', `## Active Spec Folder`, `Last active: ${state.lastSpecFolder}`);
    90	  }
    91	
    92	  const rawOutput = truncateToTokenBudget(sections.join('\n'), COMPACTION_TOKEN_BUDGET);
    93	  const output = formatGeminiOutput(rawOutput);
    94	  process.stdout.write(output);
    95	
    96	  // Clear compact payload only AFTER stdout write succeeds
    97	  clearCompactPrime(sessionId, {
    98	    cachedAt: pendingCompactPrime.cachedAt,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/hooks/copilot/compact-cache.ts | sed -n '224,234p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   224	  const transcriptLines = transcriptPath ? tailFile(transcriptPath, 50) : [];
   225	  if (transcriptPath) {
   226	    hookLog('info', 'copilot:compact-cache', `Read ${transcriptLines.length} transcript lines`);
   227	  }
   228	
   229	  const rawContext = buildCompactContext(transcriptLines);
   230	  const payload = truncateToTokenBudget(rawContext, COMPACTION_TOKEN_BUDGET);
   231	  const sanitizedLines = stripRecoveredCompactLines(transcriptLines);
   232	  const filePaths = extractFilePaths(sanitizedLines);
   233	  const topics = extractTopics(sanitizedLines);
   234	  const selection = createPreMergeSelectionMetadata({

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/tests/token-budget-enforcement.vitest.ts | sed -n '1,340p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// TEST: TOKEN BUDGET ENFORCEMENT
     2	import { describe, it, expect } from 'vitest';
     3	import * as fs from 'fs';
     4	import * as path from 'path';
     5	
     6	import * as layerDefs from '../lib/architecture/layer-definitions';
     7	import * as memoryContext from '../handlers/memory-context';
     8	import { expectReturnedCountMatchesPayload } from './_support/token-budget-assertions';
     9	
    10	const PROJECT_ROOT = path.resolve(__dirname, '..');
    11	
    12	describe('T205: Token Budget Enforcement [deferred - requires DB test fixtures]', () => {
    13	  // =========================================================
    14	  // T205-A: Layer Definition Token Budgets
    15	  // =========================================================
    16	  describe('T205-A: Layer Token Budgets', () => {
    17	    it('T205-A1: All layer token budgets correct', () => {
    18	      const budgets: Record<string, number> = {
    19	        memory_context: 3500,
    20	        memory_search: 3500,
    21	        memory_save: 3500,
    22	        memory_match_triggers: 3500,
    23	        memory_list: 1000,
    24	        memory_stats: 1000,
    25	        memory_health: 1000,
    26	        memory_update: 1000,
    27	        memory_delete: 1000,
    28	        memory_validate: 1000,
    29	        checkpoint_create: 1000,
    30	        checkpoint_list: 1000,
    31	        checkpoint_restore: 1000,
    32	        checkpoint_delete: 1000,
    33	        memory_drift_why: 1500,
    34	        task_preflight: 1500,
    35	        task_postflight: 1500,
    36	        memory_index_scan: 1000,
    37	      };
    38	
    39	      for (const [tool, expected] of Object.entries(budgets)) {
    40	        const actual = layerDefs.getTokenBudget(tool);
    41	        expect(actual, `${tool} budget`).toBe(expected);
    42	      }
    43	    });
    44	
    45	    it('T205-A2: Unknown tool gets default budget (1000)', () => {
    46	      const budget = layerDefs.getTokenBudget('nonexistent_tool');
    47	      expect(budget).toBe(1000);
    48	    });
    49	
    50	    it('T205-A3: All 7 layers have positive token budgets', () => {
    51	      const layers = layerDefs.LAYER_DEFINITIONS;
    52	      for (const [id, layer] of Object.entries(layers)) {
    53	        expect((layer as { tokenBudget: number }).tokenBudget, `${id} should have positive budget`).toBeGreaterThan(0);
    54	      }
    55	    });
    56	  });
    57	
    58	  // =========================================================
    59	  // T205-B: enforceTokenBudget Function (memory-context.ts)
    60	  // =========================================================
    61	  describe('T205-B: enforceTokenBudget Function', () => {
    62	    it('T205-B1: Small result under budget is not truncated', () => {
    63	      const smallResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
    64	        strategy: 'test',
    65	        mode: 'quick',
    66	        content: [{ type: 'text', text: '{"data":{"results":[{"id":1}]},"meta":{}}' }],
    67	      };
    68	      const { result, enforcement } = memoryContext.enforceTokenBudget(smallResult, 2000);
    69	      expect(enforcement.enforced).toBe(false);
    70	      expect(enforcement.truncated).toBe(false);
    71	      expect(enforcement.preEnforcementTokens).toBe(enforcement.returnedTokens);
    72	      expect(enforcement.returnedTokens).toBe(enforcement.actualTokens);
    73	      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
    74	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, 1);
    75	    });
    76	
    77	    it('T205-B2: Large result over budget IS truncated', () => {
    78	      const results = Array.from({ length: 50 }, (_, i) => ({
    79	        id: i,
    80	        title: `Memory ${i}`,
    81	        content: 'A'.repeat(200),
    82	        score: 1.0 - (i * 0.01),
    83	      }));
    84	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
    85	        strategy: 'test',
    86	        mode: 'quick',
    87	        content: [{
    88	          type: 'text',
    89	          text: JSON.stringify({ data: { results, count: 50 }, meta: {} })
    90	        }]
    91	      };
    92	
    93	      const { result, enforcement } = memoryContext.enforceTokenBudget(mockResult, 500);
    94	      expect(enforcement.enforced).toBe(true);
    95	      expect(enforcement.truncated).toBe(true);
    96	      expect(enforcement.originalResultCount).toBe(50);
    97	      expect(enforcement.returnedResultCount).toBeLessThan(50);
    98	      expect(enforcement.returnedResultCount).toBeGreaterThanOrEqual(1);
    99	      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
   100	      expect(enforcement.returnedTokens).toBe(enforcement.actualTokens);
   101	      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
   102	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
   103	    });
   104	
   105	    it('T205-B3: Truncation preserves highest-scored results', () => {
   106	      const results = Array.from({ length: 20 }, (_, i) => ({
   107	        id: i,
   108	        title: `Memory ${i}`,
   109	        content: 'B'.repeat(300),
   110	        score: 1.0 - (i * 0.01),
   111	      }));
   112	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   113	        strategy: 'test',
   114	        mode: 'quick',
   115	        content: [{
   116	          type: 'text',
   117	          text: JSON.stringify({ data: { results, count: 20 }, meta: {} })
   118	        }]
   119	      };
   120	
   121	      const { result: truncatedResult, enforcement } = memoryContext.enforceTokenBudget(mockResult, 500);
   122	      expect(enforcement.truncated).toBe(true);
   123	      expect(enforcement.returnedTokens).toBe(enforcement.actualTokens);
   124	      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
   125	      expectReturnedCountMatchesPayload(truncatedResult as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
   126	      const content = truncatedResult.content as Array<{ text: string }>;
   127	      const parsed = JSON.parse(content[0].text) as { data: { results: Array<{ id: number }> } };
   128	      const returnedIds = parsed.data.results.map((r) => r.id);
   129	      expect(returnedIds[0]).toBe(0);
   130	    });
   131	
   132	    it('T205-B4: Non-envelope payload over budget reports truncated', () => {
   133	      const nonEnvelopeResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   134	        strategy: 'test',
   135	        mode: 'quick',
   136	        content: [{ type: 'text', text: 'x'.repeat(5000) }],
   137	      };
   138	      const { enforcement } = memoryContext.enforceTokenBudget(nonEnvelopeResult, 500);
   139	      expect(enforcement.enforced).toBe(true);
   140	      expect(enforcement.truncated).toBe(true);
   141	      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
   142	    });
   143	
   144	    it('T205-B5: Single structured result is compacted to fit within budget', () => {
   145	      const results = [{
   146	        id: 1,
   147	        title: 'Oversized memory',
   148	        content: 'C'.repeat(8000),
   149	        score: 0.99,
   150	      }];
   151	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   152	        strategy: 'test',
   153	        mode: 'quick',
   154	        content: [{
   155	          type: 'text',
   156	          text: JSON.stringify({ data: { results, count: 1 }, meta: {} })
   157	        }]
   158	      };
   159	
   160	      const { result, enforcement } = memoryContext.enforceTokenBudget(mockResult, 500);
   161	      expect(enforcement.enforced).toBe(true);
   162	      expect(enforcement.truncated).toBe(true);
   163	      expect(enforcement.originalResultCount).toBe(1);
   164	      expect(enforcement.returnedResultCount).toBe(1);
   165	      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
   166	      expect(enforcement.returnedTokens).toBe(enforcement.actualTokens);
   167	      expect(enforcement.actualTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
   168	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
   169	
   170	      const parsed = JSON.parse((result.content as Array<{ text: string }>)[0].text) as {
   171	        data: { results: Array<{ content: string }>; count: number };
   172	      };
   173	      expect(parsed.data.count).toBe(1);
   174	      expect(parsed.data.results[0].content.length).toBeLessThan(results[0].content.length);
   175	    });
   176	
   177	    it('T205-B6: Under-budget payload exposes equal token telemetry', () => {
   178	      const results = Array.from({ length: 5 }, (_, i) => ({
   179	        id: i,
   180	        title: `M${i}`,
   181	      }));
   182	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   183	        strategy: 'test',
   184	        mode: 'deep',
   185	        content: [{
   186	          type: 'text',
   187	          text: JSON.stringify({ data: { results, count: results.length }, meta: {} }),
   188	        }],
   189	      };
   190	
   191	      const { result, enforcement } = memoryContext.enforceTokenBudget(mockResult, 3500);
   192	
   193	      expect(enforcement.enforced).toBe(false);
   194	      expect(enforcement.truncated).toBe(false);
   195	      expect(enforcement.preEnforcementTokens).toBe(enforcement.returnedTokens);
   196	      expect(enforcement.returnedTokens).toBe(enforcement.actualTokens);
   197	      expect(enforcement.droppedAllResultsReason).toBeUndefined();
   198	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, 5);
   199	    });
   200	
   201	    it('T205-B7: Over-budget resolvable payload separates pre and returned tokens', () => {
   202	      const results = Array.from({ length: 5 }, (_, i) => ({
   203	        id: i,
   204	        title: `Large memory ${i}`,
   205	        content: 'D'.repeat(1200),
   206	        score: 1.0 - (i * 0.01),
   207	      }));
   208	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   209	        strategy: 'test',
   210	        mode: 'quick',
   211	        content: [{
   212	          type: 'text',
   213	          text: JSON.stringify({ data: { results, count: results.length }, meta: {} }),
   214	        }],
   215	      };
   216	
   217	      const { result, enforcement } = memoryContext.enforceTokenBudget(mockResult, 500);
   218	
   219	      expect(enforcement.enforced).toBe(true);
   220	      expect(enforcement.truncated).toBe(true);
   221	      expect(enforcement.preEnforcementTokens).toBeGreaterThan(enforcement.budgetTokens);
   222	      expect(enforcement.returnedTokens).toBeLessThanOrEqual(enforcement.budgetTokens);
   223	      expect(enforcement.actualTokens).toBe(enforcement.returnedTokens);
   224	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, enforcement.returnedResultCount ?? 0);
   225	    });
   226	
   227	    it('T205-B8: Impossible budget reports droppedAllResultsReason', () => {
   228	      const results = [{
   229	        id: 1,
   230	        title: 'Impossible memory',
   231	        content: 'E'.repeat(8000),
   232	        score: 0.99,
   233	      }];
   234	      const mockResult: Parameters<typeof memoryContext.enforceTokenBudget>[0] = {
   235	        strategy: 'test',
   236	        mode: 'quick',
   237	        content: [{
   238	          type: 'text',
   239	          text: JSON.stringify({ data: { results, count: results.length }, meta: {} }),
   240	        }],
   241	      };
   242	
   243	      const { result, enforcement } = memoryContext.enforceTokenBudget(mockResult, 1);
   244	
   245	      expect(enforcement.enforced).toBe(true);
   246	      expect(enforcement.truncated).toBe(true);
   247	      expect(enforcement.returnedResultCount).toBe(0);
   248	      expect(enforcement.droppedAllResultsReason).toBe('impossible_budget');
   249	      expect(enforcement.actualTokens).toBe(enforcement.returnedTokens);
   250	      expectReturnedCountMatchesPayload(result as { content: Array<{ text: string }> }, 0);
   251	    });
   252	  });
   253	
   254	  // =========================================================
   255	  // T205-C: Dispatch-Level Enforcement (context-server.ts)
   256	  // =========================================================
   257	  describe('T205-C: Dispatch-Level Token Budget Enforcement', () => {
   258	    it('T205-C1: Dispatch-level truncation logic present', () => {
   259	      const serverSrc = fs.readFileSync(
   260	        path.join(PROJECT_ROOT, 'context-server.ts'),
   261	        'utf8'
   262	      );
   263	      expect(serverSrc).toContain('innerResults.pop()');
   264	    });
   265	
   266	    it('T205-C2: Dispatch reports truncation metadata', () => {
   267	      const serverSrc = fs.readFileSync(
   268	        path.join(PROJECT_ROOT, 'context-server.ts'),
   269	        'utf8'
   270	      );
   271	      expect(serverSrc).toContain('tokenBudgetTruncated');
   272	      expect(serverSrc).toContain('originalResultCount');
   273	      expect(serverSrc).toContain('returnedResultCount');
   274	    });
   275	
   276	    it('T205-C3: Dispatch preserves at least 1 result', () => {
   277	      const serverSrc = fs.readFileSync(
   278	        path.join(PROJECT_ROOT, 'context-server.ts'),
   279	        'utf8'
   280	      );
   281	      expect(serverSrc).toContain('innerResults.length > 1');
   282	    });
   283	
   284	    it('T205-C4: Uses getTokenBudget for layer-specific budgets', () => {
   285	      const serverSrc = fs.readFileSync(
   286	        path.join(PROJECT_ROOT, 'context-server.ts'),
   287	        'utf8'
   288	      );
   289	      expect(serverSrc).toContain('getTokenBudget(name)');
   290	    });
   291	  });
   292	
   293	  // =========================================================
   294	  // T205-D: Mode-Level Budgets (memory-context CONTEXT_MODES)
   295	  // =========================================================
   296	  describe('T205-D: Context Mode Token Budgets', () => {
   297	    it('T205-D1: Mode budgets correct', () => {
   298	      if (!memoryContext?.CONTEXT_MODES) return;
   299	
   300	      const modes = memoryContext.CONTEXT_MODES;
   301	      expect(modes.quick.tokenBudget).toBe(800);
   302	      expect(modes.deep.tokenBudget).toBe(3500);
   303	      expect(modes.focused.tokenBudget).toBe(3000);
   304	      expect(modes.resume.tokenBudget).toBe(2000);
   305	    });
   306	
   307	    it('T205-D2: Auto mode delegates budget (undefined)', () => {
   308	      if (!memoryContext?.CONTEXT_MODES) return;
   309	
   310	      const modes = memoryContext.CONTEXT_MODES;
   311	      expect(modes.auto.tokenBudget).toBeUndefined();
   312	    });
   313	
   314	    it('T205-D3: Budget ordering is logical (quick < resume < focused < deep)', () => {
   315	      if (!memoryContext?.CONTEXT_MODES) return;
   316	
   317	      const modes = memoryContext.CONTEXT_MODES;
   318	      const quickBudget = modes.quick.tokenBudget;
   319	      const resumeBudget = modes.resume.tokenBudget;
   320	      const focusedBudget = modes.focused.tokenBudget;
   321	      const deepBudget = modes.deep.tokenBudget;
   322	      expect(quickBudget).toBeDefined();
   323	      expect(resumeBudget).toBeDefined();
   324	      expect(focusedBudget).toBeDefined();
   325	      expect(deepBudget).toBeDefined();
   326	      if (quickBudget === undefined || resumeBudget === undefined || focusedBudget === undefined || deepBudget === undefined) {
   327	        throw new Error('Expected all non-auto mode budgets to be defined');
   328	      }
   329	      expect(quickBudget).toBeLessThan(resumeBudget);
   330	      expect(resumeBudget).toBeLessThan(focusedBudget);
   331	      expect(focusedBudget).toBeLessThan(deepBudget);
   332	    });
   333	  });
   334	});

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts | sed -n '1,120p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ───────────────────────────────────────────────────────────────
     2	// MODULE: Envelope
     3	// ───────────────────────────────────────────────────────────────
     4	import { estimateTokens } from '../../formatters/token-metrics.js';
     5	
     6	// Feature catalog: Provenance-rich response envelopes
     7	
     8	
     9	// ───────────────────────────────────────────────────────────────
    10	// 1. TYPES
    11	
    12	// ───────────────────────────────────────────────────────────────
    13	/**
    14	 * Describes the ResponseMeta shape.
    15	 */
    16	export interface ResponseMeta {
    17	  tool: string;
    18	  tokenCount: number;
    19	  tokenBudget?: number;
    20	  latencyMs?: number;
    21	  cacheHit: boolean;
    22	  isError?: boolean;
    23	  severity?: string;
    24	  [key: string]: unknown;
    25	}
    26	
    27	/**
    28	 * Describes the MCPEnvelope shape.
    29	 */
    30	export interface MCPEnvelope<T = unknown> {
    31	  summary: string;
    32	  data: T;
    33	  hints: string[];
    34	  meta: ResponseMeta;
    35	}
    36	
    37	/**
    38	 * Describes the CreateResponseOptions shape.
    39	 */
    40	export interface CreateResponseOptions<T = unknown> {
    41	  tool: string;
    42	  summary: string;
    43	  data: T;
    44	  hints?: string[];
    45	  startTime?: number | null;
    46	  cacheHit?: boolean;
    47	  extraMeta?: Record<string, unknown>;
    48	}
    49	
    50	/**
    51	 * Describes the CreateEmptyResponseOptions shape.
    52	 */
    53	export interface CreateEmptyResponseOptions {
    54	  tool: string;
    55	  summary?: string;
    56	  data?: Record<string, unknown>;
    57	  hints?: string[];
    58	  startTime?: number | null;
    59	}
    60	
    61	/**
    62	 * Describes the RecoveryInfo shape.
    63	 */
    64	export interface RecoveryInfo {
    65	  hint?: string;
    66	  actions?: string[];
    67	  toolTip?: string;
    68	  severity?: string;
    69	}
    70	
    71	/**
    72	 * Describes the CreateErrorResponseOptions shape.
    73	 */
    74	export interface CreateErrorResponseOptions {
    75	  tool: string;
    76	  error: Error | string;
    77	  code?: string;
    78	  details?: Record<string, unknown>;
    79	  recovery?: RecoveryInfo | null;
    80	  startTime?: number | null;
    81	}
    82	
    83	// Re-export canonical MCPResponse from shared (REC-010)
    84	/**
    85	 * Re-exports related public types.
    86	 */
    87	export type { MCPResponse } from '@spec-kit/shared/types';
    88	import type { MCPResponse } from '@spec-kit/shared/types';
    89	
    90	/**
    91	 * Describes the DefaultHints shape.
    92	 */
    93	export interface DefaultHints {
    94	  empty_results: string[];
    95	  success: string[];
    96	  rate_limited: string[];
    97	}
    98	
    99	function serializeEnvelope<T>(envelope: MCPEnvelope<T>): string {
   100	  return JSON.stringify(envelope, null, 2);
   101	}
   102	
   103	type EnvelopeRecord = Record<string, unknown> & { meta?: Record<string, unknown> };
   104	
   105	function ensureEnvelopeMeta(envelope: EnvelopeRecord): Record<string, unknown> {
   106	  const meta = envelope.meta;
   107	  if (typeof meta === 'object' && meta !== null && !Array.isArray(meta)) {
   108	    return meta;
   109	  }
   110	
   111	  const nextMeta: Record<string, unknown> = {};
   112	  envelope.meta = nextMeta;
   113	  return nextMeta;
   114	}
   115	
   116	export function syncEnvelopeTokenCount<T>(envelope: MCPEnvelope<T> | EnvelopeRecord): number {
   117	  const meta = ensureEnvelopeMeta(envelope as EnvelopeRecord);
   118	  const currentTokenCount = meta.tokenCount;
   119	  let previousCount = typeof currentTokenCount === 'number' && Number.isFinite(currentTokenCount)
   120	    ? currentTokenCount

exec
/bin/zsh -lc "rg -n \"syncEnvelopeTokenCount|serializeEnvelopeWithTokenCount|estimateTokenCount\" .opencode/skills/system-spec-kit/mcp_server/context-server.ts .opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts .opencode/skills/system-spec-kit/mcp_server/shared .opencode/skills/system-spec-kit/mcp_server/lib -g '*.ts'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:116:export function syncEnvelopeTokenCount<T>(envelope: MCPEnvelope<T> | EnvelopeRecord): number {
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:136:export function serializeEnvelopeWithTokenCount<T>(envelope: MCPEnvelope<T> | EnvelopeRecord): string {
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:137:  syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:198:  syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:57:  syncEnvelopeTokenCount,
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:58:  serializeEnvelopeWithTokenCount,
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1141:          syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1156:                syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1175:          result.content[0].text = serializeEnvelopeWithTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:116:export function syncEnvelopeTokenCount<T>(envelope: MCPEnvelope<T> | EnvelopeRecord): number {
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:136:export function serializeEnvelopeWithTokenCount<T>(envelope: MCPEnvelope<T> | EnvelopeRecord): string {
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:137:  syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/lib/response/envelope.ts:198:  syncEnvelopeTokenCount(envelope);
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2285:function estimateTokenCount(text: string): number {
.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2535:  estimateTokenCount,
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:15:import { estimateTokenCount } from '@spec-kit/shared/utils/token-estimate';
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:107:    if (estimateTokenCount(hint) > tokenBudget) {
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:110:      return estimateTokenCount(trimmed) <= tokenBudget ? [trimmed] : [];
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:174:        const cost = estimateTokenCount(hint);
.opencode/skills/system-spec-kit/mcp_server/lib/enrichment/passive-enrichment.ts:185:        const cost = estimateTokenCount(hint);
.opencode/skills/system-spec-kit/mcp_server/shared/utils/token-estimate.d.ts:5:export declare function estimateTokenCount(text: string | null | undefined): number;

codex
One important extra path surfaced in the tests: `handlers/memory-context.ts` has its own exported `enforceTokenBudget`, separate from the dispatch wrapper. I’m reading that now because it looks like the more direct truncation function, not just metadata decoration.
exec
/bin/zsh -lc 'rg -n "CONTEXT_MODES|enforceTokenBudget|tokenBudget|budgetTokens|truncate" .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts' in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
76:  readonly tokenBudget?: number;
110:  tokenBudget?: number;
136:  budgetTokens: number;
142:  truncated: boolean;
463:function enforceTokenBudget(result: ContextResult, budgetTokens: number): { result: ContextResult; enforcement: TokenBudgetEnforcement } {
468:  if (preEnforcementTokens <= budgetTokens) {
472:        budgetTokens,
477:        truncated: false,
483:  // we somehow entered enforcement (e.g. estimator ran twice on already-truncated
487:  if (budgetTokens > 0 && preEnforcementTokens / budgetTokens < 0.50) {
491:        budgetTokens,
496:        truncated: false,
501:  // Over budget — attempt to truncate embedded results
503:  // That JSON has a .data.results array we can truncate
504:  const truncatedResult = { ...result };
558:          summary: 'Context truncated to fit token budget',
565:            truncated: true,
570:          summary: 'Context truncated to fit token budget',
577:            truncated: true,
587:        summary: 'Context truncated to fit token budget',
594:          truncated: true,
605:          truncated: true,
639:      if (estimateTokens(JSON.stringify(fallbackResult)) <= budgetTokens) {
663:    const truncateKeys = ['content', 'snippet', 'summary', 'text'] as const;
675:    for (const key of truncateKeys) {
704:          ...truncatedResult,
709:        if (candidateTokens <= budgetTokens) {
729:  // Try to find and truncate the inner results array
730:  const contentArr = (truncatedResult as Record<string, unknown>).content as Array<{ type: string; text: string }> | undefined;
748:        // Phase 1: Adaptive content truncation — truncate content fields before dropping results
762:        while (currentResults.length > 1 && currentTokens > budgetTokens) {
783:          if (currentTokens + metadataTokens <= budgetTokens) {
800:        (truncatedResult as Record<string, unknown>).content = contentArr;
803:        const newSerializedTokens = estimateTokens(JSON.stringify(truncatedResult));
805:        if (newSerializedTokens <= budgetTokens) {
807:            result: truncatedResult,
809:              budgetTokens,
814:              truncated: true,
826:              budgetTokens,
831:              truncated: true,
850:    parseFailed ? result : truncatedResult,
868:      budgetTokens,
873:      truncated: true,
885:const CONTEXT_MODES: Record<string, ContextMode> = {
898:    tokenBudget: 800
906:    tokenBudget: 3500
914:    tokenBudget: 3000
922:    tokenBudget: 2000
1187:  if (!CONTEXT_MODES[effectiveMode]) {
1316:    tokenBudget: effectiveBudget,
1317:    tokenBudgetEnforcement: enforcement,
1521:  const tokenBudget = layerInfo?.tokenBudget ?? 2000;
1524:    tokenBudget,
1692:  const modeTokenBudget = CONTEXT_MODES[effectiveMode]?.tokenBudget;
1693:  const effectiveBudget = modeTokenBudget || tokenBudget;
1719:  const { result: budgetedResult, enforcement } = enforceTokenBudget(tracedResult0, effectiveBudget);
1761:    summary: enforcement.truncated
1762:      ? `Context retrieved via ${effectiveMode} mode (${tracedResult.strategy} strategy) [truncated${enforcement.originalResultCount !== undefined ? `: ${enforcement.originalResultCount} → ${enforcement.returnedResultCount} results` : ''} to fit ${effectiveBudget} token budget]`
1766:      `Mode: ${CONTEXT_MODES[effectiveMode].description}`,
1891:  CONTEXT_MODES,
1893:  enforceTokenBudget,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '1,220p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
     1	// ────────────────────────────────────────────────────────────────
     2	// MODULE: Memory Context
     3	// ────────────────────────────────────────────────────────────────
     4	
     5	import { randomUUID } from 'crypto';
     6	import { readFileSync } from 'node:fs';
     7	
     8	// Layer definitions
     9	import * as layerDefs from '../lib/architecture/layer-definitions.js';
    10	import { checkDatabaseUpdated } from '../core/index.js';
    11	import { toErrorMessage } from '../utils/index.js';
    12	
    13	// Intent classifier
    14	import * as intentClassifier from '../lib/search/intent-classifier.js';
    15	import type { IntentTelemetry } from '../lib/search/intent-classifier.js';
    16	
    17	// Query-intent routing (Phase 020: structural/semantic/hybrid classification)
    18	import { classifyQueryIntent } from '../code_graph/lib/query-intent-classifier.js';
    19	import { buildContext } from '../code_graph/lib/code-graph-context.js';
    20	
    21	// Core handlers for routing
    22	import { handleMemorySearch } from './memory-search.js';
    23	import { handleMemoryMatchTriggers } from './memory-triggers.js';
    24	
    25	// Response envelope
    26	import { createMCPErrorResponse, createMCPResponse } from '../lib/response/envelope.js';
    27	
    28	// Token estimation
    29	import { estimateTokens } from '../formatters/token-metrics.js';
    30	import {
    31	  getPressureLevel,
    32	  type RuntimeContextStats,
    33	} from '../lib/cognitive/pressure-monitor.js';
    34	import * as workingMemory from '../lib/cognitive/working-memory.js';
    35	import * as sessionManager from '../lib/session/session-manager.js';
    36	
    37	// Telemetry
    38	import * as retrievalTelemetry from '../lib/telemetry/retrieval-telemetry.js';
    39	import { initConsumptionLog, logConsumptionEvent } from '../lib/telemetry/consumption-logger.js';
    40	import {
    41	  attachSessionTransitionTrace,
    42	  buildSessionTransitionTrace,
    43	  type SessionTransitionTrace,
    44	} from '../lib/search/session-transition.js';
    45	
    46	// Eval logger — fail-safe, no-op when SPECKIT_EVAL_LOGGING !== "true"
    47	import { logSearchQuery, logChannelResult, logFinalResult } from '../lib/eval/eval-logger.js';
    48	import * as vectorIndex from '../lib/search/vector-index.js';
    49	
    50	// Shared handler types
    51	import type { MCPResponse } from './types.js';
    52	
    53	// PI-B3: Folder discovery integration
    54	import { discoverSpecFolder, getSpecsBasePaths } from '../lib/search/folder-discovery.js';
    55	import {
    56	  isAutoResumeEnabled,
    57	  isFolderDiscoveryEnabled,
    58	  isPressurePolicyEnabled,
    59	  isIntentAutoProfileEnabled,
    60	} from '../lib/search/search-flags.js';
    61	import { buildResumeLadder, type ResumeLadderResult } from '../lib/resume/resume-ladder.js';
    62	
    63	// Feature catalog: Unified context retrieval (memory_context)
    64	// Feature catalog: Dual-scope memory auto-surface
    65	// Feature catalog: Provenance-rich response envelopes
    66	
    67	
    68	/* ───────────────────────────────────────────────────────────────
    69	   1. TYPES
    70	──────────────────────────────────────────────────────────────── */
    71	
    72	interface ContextMode {
    73	  readonly name: string;
    74	  readonly description: string;
    75	  readonly strategy: string;
    76	  readonly tokenBudget?: number;
    77	}
    78	
    79	interface ContextOptions {
    80	  specFolder?: string;
    81	  folderBoost?: { folder: string; factor: number };
    82	  tenantId?: string;
    83	  userId?: string;
    84	  agentId?: string;
    85	  limit?: number;
    86	  sessionId?: string;
    87	  enableDedup?: boolean;
    88	  includeContent?: boolean;
    89	  includeTrace?: boolean; // CHK-040: Forward to internal memory_search calls
    90	  anchors?: string[];
    91	  profile?: string;
    92	  sessionTransition?: SessionTransitionTrace;
    93	}
    94	
    95	interface SessionLifecycleMetadata {
    96	  sessionScope: 'caller' | 'ephemeral';
    97	  requestedSessionId: string | null;
    98	  effectiveSessionId: string;
    99	  resumed: boolean;
   100	  eventCounterStart: number;
   101	  resumedContextCount: number;
   102	}
   103	
   104	interface ContextResult extends Record<string, unknown> {
   105	  strategy: string;
   106	  mode: string;
   107	}
   108	
   109	interface LayerInfo {
   110	  tokenBudget?: number;
   111	}
   112	
   113	interface ContextArgs {
   114	  input: string;
   115	  mode?: string;
   116	  intent?: string;
   117	  specFolder?: string;
   118	  tenantId?: string;
   119	  userId?: string;
   120	  agentId?: string;
   121	  limit?: number;
   122	  sessionId?: string;
   123	  enableDedup?: boolean;
   124	  includeContent?: boolean;
   125	  includeTrace?: boolean; // CHK-040: Forward to internal memory_search calls
   126	  tokenUsage?: number;
   127	  anchors?: string[];
   128	  /** REQ-D5-003: Presentation profile ('quick'|'research'|'resume'|'debug'). Default: full response. */
   129	  profile?: string;
   130	}
   131	
   132	/** T205: Token budget enforcement metadata */
   133	type DroppedAllResultsReason = 'impossible_budget' | 'parse_failed' | 'no_survivor_fits';
   134	
   135	interface TokenBudgetEnforcement {
   136	  budgetTokens: number;
   137	  preEnforcementTokens: number;
   138	  returnedTokens: number;
   139	  /** Backward-compatible alias of returnedTokens. */
   140	  actualTokens: number;
   141	  enforced: boolean;
   142	  truncated: boolean;
   143	  originalResultCount?: number;
   144	  returnedResultCount?: number;
   145	  droppedAllResultsReason?: DroppedAllResultsReason;
   146	}
   147	
   148	type PressureOverrideTargetMode = 'quick' | 'focused' | null;
   149	
   150	interface SessionLifecycleResolution {
   151	  requestedSessionId: string | null;
   152	  effectiveSessionId: string;
   153	  resumed: boolean;
   154	  priorMode: string | null;
   155	  counter: number;
   156	  error?: string;
   157	}
   158	
   159	interface EffectiveModeIntentClassification {
   160	  detectedIntent?: string;
   161	  intentConfidence: number;
   162	  intentEvidence: string[];
   163	  resumeHeuristicApplied: boolean;
   164	  source: 'explicit' | 'auto-detected';
   165	}
   166	
   167	interface EffectiveModeResolution {
   168	  effectiveMode: string;
   169	  pressureOverrideApplied: boolean;
   170	  pressureOverrideTargetMode: PressureOverrideTargetMode;
   171	  pressureWarning: string | null;
   172	  intentClassification: EffectiveModeIntentClassification;
   173	}
   174	
   175	interface BuildResponseMetaParams {
   176	  effectiveMode: string;
   177	  requestedMode: string;
   178	  tracedResult: ContextResult;
   179	  pressurePolicy: {
   180	    level: string;
   181	    ratio: number | null;
   182	    source: string;
   183	    warning: string | null;
   184	  };
   185	  pressureOverrideApplied: boolean;
   186	  pressureOverrideTargetMode: PressureOverrideTargetMode;
   187	  pressureWarning: string | null;
   188	  sessionLifecycle: SessionLifecycleMetadata;
   189	  effectiveBudget: number;
   190	  enforcement: TokenBudgetEnforcement;
   191	  intentClassification: EffectiveModeIntentClassification;
   192	  discoveredFolder?: string;
   193	  includeTrace: boolean;
   194	  sessionTransition: SessionTransitionTrace;
   195	  structuralRoutingNudge: StructuralRoutingNudgeMeta | null;
   196	  intentTelemetry: IntentTelemetry | null;
   197	}
   198	
   199	interface QueryIntentMetadata {
   200	  queryIntent: string;
   201	  routedBackend: string;
   202	  confidence: number;
   203	  matchedKeywords?: string[];
   204	}
   205	
   206	interface StrategyErrorPayload {
   207	  error: string;
   208	  code: string;
   209	  details: Record<string, unknown>;
   210	  hints: string[];
   211	  severity: string | null;
   212	}
   213	
   214	interface StructuralRoutingNudgeMeta {
   215	  advisory: true;
   216	  advisoryPreset: 'ready';
   217	  preferredTool: 'code_graph_query';
   218	  message: string;
   219	  preservesAuthority: 'session_bootstrap';
   220	}

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '220,520p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   220	}
   221	
   222	interface ResumeRow extends Record<string, unknown> {
   223	  id: string;
   224	  title: string;
   225	  filePath: string;
   226	  specFolder: string;
   227	  documentType: 'handover' | 'continuity' | 'spec_doc';
   228	  source: 'handover' | 'continuity' | 'spec_docs';
   229	  score: number;
   230	  similarity: number;
   231	  fingerprint: string;
   232	  fingerprintExpected: string | null;
   233	  fingerprintStatus: 'verified';
   234	  content: string;
   235	}
   236	
   237	const RESUME_LADDER_ORDER = ['handover', 'continuity', 'spec_docs'] as const;
   238	
   239	const STRUCTURAL_ROUTING_PATTERNS = [
   240	  /\b(?:who|what)\s+calls?\b/i,
   241	  /\bcallers?\s+of\b/i,
   242	  /\b(?:who|what)\s+imports?\b/i,
   243	  /\bimports?\s+of\b/i,
   244	  /\b(?:show|list)\s+(?:the\s+)?outline\b/i,
   245	  /\boutline\s+of\b/i,
   246	  /\bdependenc(?:y|ies)\b/i,
   247	  /\bdependents?\b/i,
   248	  /\bwhat\s+extends\b/i,
   249	];
   250	
   251	function extractResultRowsFromContextResponse(responseText: string): Array<Record<string, unknown>> {
   252	  try {
   253	    const parsed = JSON.parse(responseText) as Record<string, unknown>;
   254	    const outerData = parsed?.data as Record<string, unknown> | undefined;
   255	
   256	    const directRows = Array.isArray(outerData?.results)
   257	      ? outerData.results as Array<Record<string, unknown>>
   258	      : null;
   259	    if (directRows) {
   260	      return directRows;
   261	    }
   262	
   263	    const nestedContent = Array.isArray(outerData?.content)
   264	      ? outerData.content as Array<{ type?: string; text?: string }>
   265	      : [];
   266	    const nestedText = nestedContent[0]?.text;
   267	    if (typeof nestedText !== 'string' || nestedText.length === 0) {
   268	      return [];
   269	    }
   270	
   271	    const nestedEnvelope = JSON.parse(nestedText) as Record<string, unknown>;
   272	    const nestedData = nestedEnvelope?.data as Record<string, unknown> | undefined;
   273	    return Array.isArray(nestedData?.results)
   274	      ? nestedData.results as Array<Record<string, unknown>>
   275	      : [];
   276	  } catch {
   277	    return [];
   278	  }
   279	}
   280	
   281	function readResumeDocumentContent(documentPath: string): string {
   282	  try {
   283	    return readFileSync(documentPath, 'utf8');
   284	  } catch {
   285	    return '';
   286	  }
   287	}
   288	
   289	function formatResumeLadderContent(result: ResumeLadderResult, row: ResumeRow): string {
   290	  if (row.documentType !== 'continuity') {
   291	    return readResumeDocumentContent(row.filePath);
   292	  }
   293	
   294	  const lines = [
   295	    `Recent action: ${result.recentAction ?? ''}`,
   296	    `Next safe action: ${result.nextSafeAction ?? ''}`,
   297	  ];
   298	
   299	  if (result.blockers.length > 0) {
   300	    lines.push(`Blockers: ${result.blockers.join('; ')}`);
   301	  }
   302	  if (result.keyFiles.length > 0) {
   303	    lines.push(`Key files: ${result.keyFiles.join(', ')}`);
   304	  }
   305	
   306	  return lines.join('\n');
   307	}
   308	
   309	function normalizeResumeSource(
   310	  source: ResumeLadderResult['source'],
   311	): 'handover' | 'continuity' | 'spec_docs' | 'unresolved' {
   312	  if (source === 'spec-docs') {
   313	    return 'spec_docs';
   314	  }
   315	  if (source === 'none') {
   316	    return 'unresolved';
   317	  }
   318	  return source;
   319	}
   320	
   321	function normalizeResumeDocumentType(
   322	  type: ResumeLadderResult['documents'][number]['type'],
   323	): ResumeRow['documentType'] {
   324	  if (type === 'spec-doc') {
   325	    return 'spec_doc';
   326	  }
   327	  return type;
   328	}
   329	
   330	function convertResumeLadderToRows(result: ResumeLadderResult, limit: number): ResumeRow[] {
   331	  const preferredDocuments = result.documents.filter((document) => {
   332	    if (result.source === 'handover') {
   333	      return document.type === 'handover';
   334	    }
   335	    if (result.source === 'continuity') {
   336	      return document.type === 'continuity';
   337	    }
   338	    if (result.source === 'spec-docs') {
   339	      return document.type === 'spec-doc';
   340	    }
   341	    return false;
   342	  });
   343	
   344	  return preferredDocuments.slice(0, limit).map((document) => {
   345	    const documentType = normalizeResumeDocumentType(document.type);
   346	    const source = normalizeResumeSource(result.source === 'none' ? 'spec-docs' : result.source) as ResumeRow['source'];
   347	    const row: ResumeRow = {
   348	      id: `resume:${source}:${document.relativePath}`,
   349	      title: document.relativePath,
   350	      filePath: document.path,
   351	      specFolder: result.specFolder ?? '',
   352	      documentType,
   353	      source,
   354	      score: 1,
   355	      similarity: 1,
   356	      fingerprint: document.fingerprint,
   357	      fingerprintExpected: null,
   358	      fingerprintStatus: 'verified',
   359	      content: '',
   360	    };
   361	
   362	    row.content = formatResumeLadderContent(result, row);
   363	    return row;
   364	  });
   365	}
   366	
   367	function extractStrategyError(result: ContextResult): StrategyErrorPayload | null {
   368	  if ((result as Record<string, unknown>).isError !== true) {
   369	    return null;
   370	  }
   371	
   372	  const content = Array.isArray((result as Record<string, unknown>).content)
   373	    ? ((result as Record<string, unknown>).content as Array<{ text?: string }>)
   374	    : [];
   375	  const responseText = content[0]?.text;
   376	  if (typeof responseText !== 'string' || responseText.length === 0) {
   377	    return {
   378	      error: 'Context strategy failed',
   379	      code: 'E_STRATEGY',
   380	      details: {},
   381	      hints: [],
   382	      severity: null,
   383	    };
   384	  }
   385	
   386	  try {
   387	    const parsed = JSON.parse(responseText) as {
   388	      data?: {
   389	        error?: string;
   390	        code?: string;
   391	        details?: Record<string, unknown>;
   392	      };
   393	      hints?: string[];
   394	      meta?: {
   395	        severity?: string;
   396	      };
   397	    };
   398	
   399	    return {
   400	      error: parsed.data?.error ?? 'Context strategy failed',
   401	      code: parsed.data?.code ?? 'E_STRATEGY',
   402	      details: parsed.data?.details ?? {},
   403	      hints: Array.isArray(parsed.hints) ? parsed.hints : [],
   404	      severity: parsed.meta?.severity ?? null,
   405	    };
   406	  } catch {
   407	    return {
   408	      error: 'Context strategy failed',
   409	      code: 'E_STRATEGY',
   410	      details: {},
   411	      hints: [],
   412	      severity: null,
   413	    };
   414	  }
   415	}
   416	
   417	function buildStructuralRoutingNudge(
   418	  input: string,
   419	  queryIntentMetadata: {
   420	    queryIntent: string;
   421	    confidence: number;
   422	  } | null,
   423	  graphContextResult: Record<string, unknown> | null,
   424	): StructuralRoutingNudgeMeta | null {
   425	  if (!queryIntentMetadata || queryIntentMetadata.queryIntent !== 'structural' || queryIntentMetadata.confidence <= 0.65) {
   426	    return null;
   427	  }
   428	
   429	  if (!STRUCTURAL_ROUTING_PATTERNS.some((pattern) => pattern.test(input))) {
   430	    return null;
   431	  }
   432	
   433	  const metadata = graphContextResult?.metadata as Record<string, unknown> | undefined;
   434	  const totalNodes = typeof metadata?.totalNodes === 'number' ? metadata.totalNodes : 0;
   435	  if (totalNodes <= 0) {
   436	    return null;
   437	  }
   438	
   439	  return {
   440	    advisory: true,
   441	    advisoryPreset: 'ready',
   442	    preferredTool: 'code_graph_query',
   443	    message: 'Advisory only: this looks like a structural question. Prefer `code_graph_query` before Grep or Glob for callers, imports, outline, and dependency lookups.',
   444	    preservesAuthority: 'session_bootstrap',
   445	  };
   446	}
   447	
   448	/* ───────────────────────────────────────────────────────────────
   449	   2. TOKEN BUDGET ENFORCEMENT (T205)
   450	   
   451	   Enforces per-layer/per-mode token budgets by estimating the
   452	   token count of strategy results and truncating when exceeded.
   453	   Uses character-based estimation: 1 token ≈ 4 chars.
   454	──────────────────────────────────────────────────────────────── */
   455	
   456	/**
   457	 * T205: Enforce token budget on strategy results.
   458	 * 
   459	 * Estimates the token count of the serialized result. If over budget,
   460	 * parses embedded result arrays and removes lowest-priority items
   461	 * until within budget. Higher-scored results are preserved.
   462	 */
   463	function enforceTokenBudget(result: ContextResult, budgetTokens: number): { result: ContextResult; enforcement: TokenBudgetEnforcement } {
   464	  const serialized = JSON.stringify(result);
   465	  const preEnforcementTokens = estimateTokens(serialized);
   466	
   467	  // Under budget — no enforcement needed
   468	  if (preEnforcementTokens <= budgetTokens) {
   469	    return {
   470	      result,
   471	      enforcement: {
   472	        budgetTokens,
   473	        preEnforcementTokens,
   474	        returnedTokens: preEnforcementTokens,
   475	        actualTokens: preEnforcementTokens,
   476	        enforced: false,
   477	        truncated: false,
   478	      }
   479	    };
   480	  }
   481	
   482	  // REQ-002 (Cluster 1) Sanity guard: when reported usage is far below budget but
   483	  // we somehow entered enforcement (e.g. estimator ran twice on already-truncated
   484	  // payload, or budget was passed in as a tiny number), short-circuit and return
   485	  // the unmodified result. This prevents the historical regression where a
   486	  // 71-token payload against a 3000-token budget was nuked to count:0,results:[].
   487	  if (budgetTokens > 0 && preEnforcementTokens / budgetTokens < 0.50) {
   488	    return {
   489	      result,
   490	      enforcement: {
   491	        budgetTokens,
   492	        preEnforcementTokens,
   493	        returnedTokens: preEnforcementTokens,
   494	        actualTokens: preEnforcementTokens,
   495	        enforced: false,
   496	        truncated: false,
   497	      }
   498	    };
   499	  }
   500	
   501	  // Over budget — attempt to truncate embedded results
   502	  // Strategy results contain an embedded MCPResponse with content[0].text as JSON
   503	  // That JSON has a .data.results array we can truncate
   504	  const truncatedResult = { ...result };
   505	  let parseFailed = false;
   506	  let originalResultCount: number | undefined;
   507	  let returnedResultCount: number | undefined;
   508	  let droppedAllResultsReason: DroppedAllResultsReason | undefined;
   509	
   510	  const extractNestedResultCount = (candidate: ContextResult): number | undefined => {
   511	    try {
   512	      const candidateContent = (candidate as Record<string, unknown>).content as Array<{ text?: string }> | undefined;
   513	      if (!candidateContent?.[0]?.text) {
   514	        return undefined;
   515	      }
   516	      const parsed = JSON.parse(candidateContent[0].text) as { data?: { results?: unknown[] } };
   517	      return Array.isArray(parsed?.data?.results) ? parsed.data.results.length : undefined;
   518	    } catch {
   519	      return undefined;
   520	    }

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '520,780p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   520	    }
   521	  };
   522	
   523	  const fallbackToStructuredBudget = (
   524	    baseResult: ContextResult,
   525	    parseFailedInnerText?: string,
   526	    preservedResults?: Array<Record<string, unknown>>,
   527	  ): ContextResult => {
   528	    const fallbackResult = { ...baseResult } as ContextResult;
   529	    const fallbackContent = Array.isArray((fallbackResult as Record<string, unknown>).content)
   530	      ? ((fallbackResult as Record<string, unknown>).content as Array<Record<string, unknown>>)
   531	      : [];
   532	    const contentClone = fallbackContent.map((entry) => ({ ...entry }));
   533	
   534	    // REQ-002 (Cluster 1): When structural truncation already produced a non-empty
   535	    // result set, preserve it rather than silently dropping to count:0,results:[].
   536	    // The previous behaviour caused the wrapper to report `returnedResultCount > 0`
   537	    // in metadata while shipping an empty payload to the caller.
   538	    const preservedSafe: Array<Record<string, unknown>> = Array.isArray(preservedResults)
   539	      ? preservedResults
   540	      : [];
   541	
   542	    const buildPreservedCandidates = (): Array<Record<string, unknown>> => {
   543	      if (preservedSafe.length === 0) {
   544	        return [];
   545	      }
   546	      const minimalResults = preservedSafe.map((r) => ({
   547	        id: r.id,
   548	        title: r.title,
   549	        similarity: r.similarity,
   550	        specFolder: r.specFolder,
   551	        confidence: r.confidence,
   552	        importanceTier: r.importanceTier,
   553	        isConstitutional: r.isConstitutional,
   554	        metadataOnly: true,
   555	      }));
   556	      return [
   557	        {
   558	          summary: 'Context truncated to fit token budget',
   559	          data: {
   560	            count: preservedSafe.length,
   561	            results: preservedSafe,
   562	          },
   563	          meta: {
   564	            tool: 'memory_search',
   565	            truncated: true,
   566	            preserved: true,
   567	          },
   568	        },
   569	        {
   570	          summary: 'Context truncated to fit token budget',
   571	          data: {
   572	            count: minimalResults.length,
   573	            results: minimalResults,
   574	          },
   575	          meta: {
   576	            tool: 'memory_search',
   577	            truncated: true,
   578	            preserved: true,
   579	            metadataOnly: true,
   580	          },
   581	        },
   582	      ];
   583	    };
   584	
   585	    const emptyCandidates: Array<Record<string, unknown>> = [
   586	      {
   587	        summary: 'Context truncated to fit token budget',
   588	        data: {
   589	          count: 0,
   590	          results: [],
   591	        },
   592	        meta: {
   593	          tool: 'memory_search',
   594	          truncated: true,
   595	          parseFailed: Boolean(parseFailedInnerText),
   596	        },
   597	      },
   598	      {
   599	        data: {
   600	          count: 0,
   601	          results: [],
   602	        },
   603	        meta: {
   604	          tool: 'memory_search',
   605	          truncated: true,
   606	        },
   607	      },
   608	      {
   609	        data: {
   610	          count: 0,
   611	          results: [],
   612	        },
   613	      },
   614	    ];
   615	
   616	    const candidateInnerStates: Array<Record<string, unknown>> = [
   617	      ...buildPreservedCandidates(),
   618	      ...emptyCandidates,
   619	    ];
   620	
   621	    if (parseFailedInnerText) {
   622	      const meta = (emptyCandidates[0].meta as Record<string, unknown>);
   623	      meta.parseFailedPreview = parseFailedInnerText.slice(0, 120);
   624	    }
   625	
   626	    for (const innerEnvelope of candidateInnerStates) {
   627	      const candidateResults = (innerEnvelope.data as { results?: unknown[] } | undefined)?.results;
   628	      const candidateResultCount = Array.isArray(candidateResults) ? candidateResults.length : undefined;
   629	
   630	      if (contentClone.length > 0) {
   631	        contentClone[0] = { ...contentClone[0], text: JSON.stringify(innerEnvelope) };
   632	        (fallbackResult as Record<string, unknown>).content = contentClone;
   633	      } else {
   634	        (fallbackResult as Record<string, unknown>).content = [
   635	          { type: 'text', text: JSON.stringify(innerEnvelope) },
   636	        ];
   637	      }
   638	
   639	      if (estimateTokens(JSON.stringify(fallbackResult)) <= budgetTokens) {
   640	        if (candidateResultCount === 0) {
   641	          droppedAllResultsReason = 'impossible_budget';
   642	        }
   643	        return fallbackResult;
   644	      }
   645	    }
   646	
   647	    droppedAllResultsReason = 'impossible_budget';
   648	    return {
   649	      strategy: baseResult.strategy,
   650	      mode: baseResult.mode,
   651	      content: [{
   652	        type: 'text',
   653	        text: JSON.stringify({ data: { count: 0, results: [] } }),
   654	      }],
   655	    };
   656	  };
   657	
   658	  const compactStructuredResult = (
   659	    innerEnvelope: Record<string, unknown>,
   660	    currentResults: Array<Record<string, unknown>>,
   661	    contentEntries: Array<{ type: string; text: string }>,
   662	  ): { result: ContextResult; actualTokens: number } | null => {
   663	    const truncateKeys = ['content', 'snippet', 'summary', 'text'] as const;
   664	    const lastIndex = currentResults.length - 1;
   665	
   666	    if (lastIndex < 0) {
   667	      return null;
   668	    }
   669	
   670	    const lastResult = currentResults[lastIndex];
   671	    if (!lastResult || typeof lastResult !== 'object') {
   672	      return null;
   673	    }
   674	
   675	    for (const key of truncateKeys) {
   676	      const originalValue = lastResult[key];
   677	      if (typeof originalValue !== 'string' || originalValue.length === 0) {
   678	        continue;
   679	      }
   680	
   681	      let bestResult: ContextResult | null = null;
   682	      let bestTokens = Number.POSITIVE_INFINITY;
   683	      let low = 0;
   684	      let high = originalValue.length;
   685	
   686	      while (low <= high) {
   687	        const mid = Math.floor((low + high) / 2);
   688	        const candidateResults = [...currentResults];
   689	        candidateResults[lastIndex] = {
   690	          ...lastResult,
   691	          [key]: originalValue.slice(0, mid),
   692	        };
   693	
   694	        innerEnvelope.data = {
   695	          ...((innerEnvelope.data as Record<string, unknown>) ?? {}),
   696	          results: candidateResults,
   697	          count: candidateResults.length,
   698	        };
   699	
   700	        const candidateContent = contentEntries.map((entry, index) => (
   701	          index === 0 ? { type: entry.type, text: JSON.stringify(innerEnvelope) } : { ...entry }
   702	        ));
   703	        const candidateResult = {
   704	          ...truncatedResult,
   705	          content: candidateContent,
   706	        } as ContextResult;
   707	        const candidateTokens = estimateTokens(JSON.stringify(candidateResult));
   708	
   709	        if (candidateTokens <= budgetTokens) {
   710	          bestResult = candidateResult;
   711	          bestTokens = candidateTokens;
   712	          low = mid + 1;
   713	        } else {
   714	          high = mid - 1;
   715	        }
   716	      }
   717	
   718	      if (bestResult) {
   719	        return {
   720	          result: bestResult,
   721	          actualTokens: bestTokens,
   722	        };
   723	      }
   724	    }
   725	
   726	    return null;
   727	  };
   728	
   729	  // Try to find and truncate the inner results array
   730	  const contentArr = (truncatedResult as Record<string, unknown>).content as Array<{ type: string; text: string }> | undefined;
   731	  let parseFailedInnerText: string | undefined;
   732	  // REQ-002 (Cluster 1): Track survivors so the fallback path can preserve them
   733	  // instead of zero-filling.
   734	  let preservedAfterStructural: Array<Record<string, unknown>> = [];
   735	  if (contentArr && Array.isArray(contentArr) && contentArr.length > 0 && contentArr[0]?.text) {
   736	    try {
   737	      const innerEnvelope = JSON.parse(contentArr[0].text);
   738	      const innerResults = innerEnvelope?.data?.results;
   739	
   740	      if (Array.isArray(innerResults) && innerResults.length > 0) {
   741	        originalResultCount = innerResults.length;
   742	
   743	        // Results should already be sorted by score (highest first)
   744	        // Remove items from the end until we fit within budget
   745	        const currentResults = [...innerResults];
   746	        let currentTokens = preEnforcementTokens;
   747	
   748	        // Phase 1: Adaptive content truncation — truncate content fields before dropping results
   749	        const MAX_CONTENT_CHARS = 500;
   750	        for (const r of currentResults) {
   751	          if (r.content && typeof r.content === 'string' && r.content.length > MAX_CONTENT_CHARS) {
   752	            r.content = r.content.substring(0, MAX_CONTENT_CHARS) + '...';
   753	            r.contentTruncated = true;
   754	          }
   755	        }
   756	        // Re-estimate after content truncation
   757	        innerEnvelope.data.results = currentResults;
   758	        innerEnvelope.data.count = currentResults.length;
   759	        currentTokens = estimateTokens(JSON.stringify(innerEnvelope));
   760	
   761	        // Phase 2: Drop lowest-scored results if still over budget
   762	        while (currentResults.length > 1 && currentTokens > budgetTokens) {
   763	          // Remove the last (lowest-scored) result
   764	          const removed = currentResults.pop();
   765	          const removedTokens = estimateTokens(JSON.stringify(removed));
   766	          currentTokens -= removedTokens;
   767	        }
   768	
   769	        // Phase 3: Two-tier response — append metadata-only entries for dropped results
   770	        const droppedResults = innerResults.slice(currentResults.length);
   771	        if (droppedResults.length > 0) {
   772	          const metadataOnly = droppedResults.map((r: Record<string, unknown>) => ({
   773	            id: r.id,
   774	            title: r.title,
   775	            similarity: r.similarity,
   776	            specFolder: r.specFolder,
   777	            confidence: r.confidence,
   778	            importanceTier: r.importanceTier,
   779	            isConstitutional: r.isConstitutional,
   780	            metadataOnly: true,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '780,890p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   780	            metadataOnly: true,
   781	          }));
   782	          const metadataTokens = estimateTokens(JSON.stringify(metadataOnly));
   783	          if (currentTokens + metadataTokens <= budgetTokens) {
   784	            currentResults.push(...metadataOnly);
   785	            currentTokens += metadataTokens;
   786	          }
   787	        }
   788	
   789	        // Update the inner envelope
   790	        innerEnvelope.data.results = currentResults;
   791	        innerEnvelope.data.count = currentResults.length;
   792	        returnedResultCount = currentResults.length;
   793	
   794	        // REQ-002 (Cluster 1): Snapshot survivors before any further compaction
   795	        // so the fallback path can preserve them instead of zero-filling.
   796	        preservedAfterStructural = currentResults.slice();
   797	
   798	        // Re-serialize
   799	        contentArr[0] = { type: 'text', text: JSON.stringify(innerEnvelope) };
   800	        (truncatedResult as Record<string, unknown>).content = contentArr;
   801	
   802	        // Recalculate actual tokens after truncation
   803	        const newSerializedTokens = estimateTokens(JSON.stringify(truncatedResult));
   804	
   805	        if (newSerializedTokens <= budgetTokens) {
   806	          return {
   807	            result: truncatedResult,
   808	            enforcement: {
   809	              budgetTokens,
   810	              preEnforcementTokens,
   811	              returnedTokens: newSerializedTokens,
   812	              actualTokens: newSerializedTokens,
   813	              enforced: true,
   814	              truncated: true,
   815	              originalResultCount,
   816	              returnedResultCount,
   817	            }
   818	          };
   819	        }
   820	
   821	        const compacted = compactStructuredResult(innerEnvelope, currentResults, contentArr);
   822	        if (compacted) {
   823	          return {
   824	            result: compacted.result,
   825	            enforcement: {
   826	              budgetTokens,
   827	              preEnforcementTokens,
   828	              returnedTokens: compacted.actualTokens,
   829	              actualTokens: compacted.actualTokens,
   830	              enforced: true,
   831	              truncated: true,
   832	              originalResultCount,
   833	              returnedResultCount,
   834	            }
   835	          };
   836	        }
   837	      }
   838	    } catch {
   839	      parseFailed = true;
   840	      parseFailedInnerText = contentArr[0].text;
   841	      // JSON parse failed — fall through to structural truncation
   842	    }
   843	  }
   844	
   845	  // Fallback when parsing fails or a structured response still exceeds budget.
   846	  // Always emit valid nested JSON rather than raw character slices.
   847	  // REQ-002 (Cluster 1): Hand the fallback the survivors from structural
   848	  // truncation so it can keep them instead of silently zero-filling.
   849	  const fallbackResult = fallbackToStructuredBudget(
   850	    parseFailed ? result : truncatedResult,
   851	    parseFailedInnerText,
   852	    preservedAfterStructural,
   853	  );
   854	
   855	  const fallbackTokens = estimateTokens(JSON.stringify(fallbackResult));
   856	
   857	  // Re-extract the actual returned count from the fallback envelope so the
   858	  // metadata never advertises survivors that the payload no longer contains.
   859	  const extractedFallbackCount = extractNestedResultCount(fallbackResult);
   860	  const fallbackReturnedCount = extractedFallbackCount ?? returnedResultCount;
   861	  if (fallbackReturnedCount === 0 && !droppedAllResultsReason) {
   862	    droppedAllResultsReason = 'impossible_budget';
   863	  }
   864	
   865	  return {
   866	    result: fallbackResult,
   867	    enforcement: {
   868	      budgetTokens,
   869	      preEnforcementTokens,
   870	      returnedTokens: fallbackTokens,
   871	      actualTokens: fallbackTokens,
   872	      enforced: true,
   873	      truncated: true,
   874	      originalResultCount,
   875	      returnedResultCount: fallbackReturnedCount,
   876	      ...(droppedAllResultsReason ? { droppedAllResultsReason } : {}),
   877	    }
   878	  };
   879	}
   880	
   881	/* ───────────────────────────────────────────────────────────────
   882	   3. CONTEXT MODE DEFINITIONS
   883	──────────────────────────────────────────────────────────────── */
   884	
   885	const CONTEXT_MODES: Record<string, ContextMode> = {
   886	  // Auto-detect: Let the system determine the best approach
   887	  auto: {
   888	    name: 'Auto',
   889	    description: 'Automatically detect intent and route to optimal strategy',
   890	    strategy: 'adaptive'

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '1288,1325p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
  1288	          retrievalTelemetry.recordTransitionDiagnostics(
  1289	            t,
  1290	            includeTrace === true ? sessionTransition : undefined,
  1291	          );
  1292	          return { _telemetry: retrievalTelemetry.toJSON(t) };
  1293	        } catch (error: unknown) {
  1294	          void error;
  1295	          // Telemetry must never crash the handler
  1296	          return {};
  1297	        }
  1298	      })()
  1299	    : {};
  1300	
  1301	  return {
  1302	    layer: 'L1:Orchestration',
  1303	    mode: effectiveMode,
  1304	    requestedMode,
  1305	    strategy: tracedResult.strategy,
  1306	    tokenUsageSource: pressurePolicy.source,
  1307	    tokenUsagePressure: pressurePolicy.ratio,
  1308	    pressureLevel: pressurePolicy.level,
  1309	    pressure_level: pressurePolicy.level,
  1310	    pressurePolicy: {
  1311	      applied: pressureOverrideApplied,
  1312	      overrideMode: pressureOverrideApplied ? pressureOverrideTargetMode : null,
  1313	      warning: pressureWarning,
  1314	    },
  1315	    sessionLifecycle,
  1316	    tokenBudget: effectiveBudget,
  1317	    tokenBudgetEnforcement: enforcement,
  1318	    // REQ-004 (Cluster 2): `meta.intent` is the AUTHORITATIVE intent for output
  1319	    // rendering, anchor selection, mode routing, and weight adjustment. The
  1320	    // separate `data.queryIntentRouting` field (added by Phase 020) describes
  1321	    // backend channel selection only (structural / hybrid / semantic) and MUST
  1322	    // NOT be conflated with this intent. The classification kind is annotated
  1323	    // explicitly here to remove ambiguity for downstream consumers.
  1324	    intent: intentTelemetry ? {
  1325	      ...intentTelemetry,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '1688,1725p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
  1688	    // Best-effort session state write — do not fail the handler
  1689	  }
  1690	
  1691	  // T205: Determine effective token budget from mode or layer definitions
  1692	  const modeTokenBudget = CONTEXT_MODES[effectiveMode]?.tokenBudget;
  1693	  const effectiveBudget = modeTokenBudget || tokenBudget;
  1694	
  1695	  // M1 FIX: Inject auto-resume context BEFORE budget enforcement
  1696	  // so the final response respects the advertised token budget.
  1697	  const tracedResult0: ContextResult = effectiveMode === 'quick' && options.includeTrace === true
  1698	    ? attachSessionTransitionTrace(
  1699	      result as ContextResult & { content?: Array<{ text?: string; type?: string }> },
  1700	      sessionTransition,
  1701	    ) as ContextResult
  1702	    : result;
  1703	
  1704	  if (autoResumeEnabled && effectiveMode === 'resume' && resumedSession) {
  1705	    const resumeContextItems = workingMemory.getSessionPromptContext(effectiveSessionId, workingMemory.DECAY_FLOOR, 5);
  1706	    if (resumeContextItems.length > 0) {
  1707	      sessionLifecycle.resumedContextCount = resumeContextItems.length;
  1708	      (tracedResult0 as Record<string, unknown>).systemPromptContext = resumeContextItems.map((item) => ({
  1709	        memoryId: item.memoryId,
  1710	        title: item.title,
  1711	        filePath: item.filePath,
  1712	        attentionScore: item.attentionScore,
  1713	      }));
  1714	      (tracedResult0 as Record<string, unknown>).systemPromptContextInjected = true;
  1715	    }
  1716	  }
  1717	
  1718	  // T205: Enforce token budget AFTER all context injection
  1719	  const { result: budgetedResult, enforcement } = enforceTokenBudget(tracedResult0, effectiveBudget);
  1720	  const tracedResult = budgetedResult;
  1721	  const intentTelemetry = detectedIntent ? intentClassifier.emitIntentTelemetry(normalizedInput, {
  1722	    taskIntent: {
  1723	      intent: detectedIntent,
  1724	      confidence: intentConfidence,
  1725	      evidence: intentEvidence,

exec
/bin/zsh -lc "nl -ba .opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts | sed -n '884,925p'" in /Users/michelkerkmeester/MEGA/Development/Code_Environment/Public
 succeeded in 0ms:
   884	
   885	const CONTEXT_MODES: Record<string, ContextMode> = {
   886	  // Auto-detect: Let the system determine the best approach
   887	  auto: {
   888	    name: 'Auto',
   889	    description: 'Automatically detect intent and route to optimal strategy',
   890	    strategy: 'adaptive'
   891	  },
   892	
   893	  // Quick: Fast trigger-based matching for reactive context
   894	  quick: {
   895	    name: 'Quick',
   896	    description: 'Fast trigger matching for real-time context (low latency)',
   897	    strategy: 'triggers',
   898	    tokenBudget: 800
   899	  },
   900	
   901	  // Deep: Comprehensive semantic search with full context
   902	  deep: {
   903	    name: 'Deep',
   904	    description: 'Semantic search with full context retrieval',
   905	    strategy: 'search',
   906	    tokenBudget: 3500
   907	  },
   908	
   909	  // Focused: Intent-specific search with optimized weights
   910	  focused: {
   911	    name: 'Focused',
   912	    description: 'Intent-aware search with task-specific optimization',
   913	    strategy: 'intent-search',
   914	    tokenBudget: 3000
   915	  },
   916	
   917	  // Resume: Session recovery mode
   918	  resume: {
   919	    name: 'Resume',
   920	    description: 'Resume previous work with state and next-steps anchors',
   921	    strategy: 'resume',
   922	    tokenBudget: 2000
   923	  }
   924	};
   925	

codex
Found the token-budget enforcement paths under `.opencode/skills/system-spec-kit/mcp_server/`.

The main function responsible for `memory_context` truncation behavior is [enforceTokenBudget](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:463). It estimates the serialized response, truncates oversized embedded `data.results`, compacts content fields, drops lowest-priority tail results, and falls back to minimal structured payloads if the budget is impossible.

Other enforcement/truncation paths:

- [context-server.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1139): dispatch-level wrapper calls `getTokenBudget(name)`, syncs envelope token count, and pops `data.results` until the per-layer budget is met.
- [layer-definitions.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:193): `getTokenBudget(toolName)` resolves per-tool layer budgets.
- [hybrid-search.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1678): search pipeline applies budget truncation after trace/header enrichment.
- [hybrid-search.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2398): `truncateToBudget()` does greedy highest-score-first result selection under budget.
- [dynamic-token-budget.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:69): `getDynamicTokenBudget()` computes tier-based budgets, but the file explicitly says it is advisory only.
- [confidence-truncation.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:102): `truncateByConfidence()` trims low-confidence tails by score-gap analysis; related, but confidence-based rather than token-budget-based.
- [memory-surface.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:250): `enforceAutoSurfaceTokenBudget()` trims auto-surfaced triggered/constitutional memories or drops the payload.
- [hooks/claude/shared.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96): `truncateToTokenBudget()` is the shared hook text truncator used by Claude/Gemini/Copilot/Codex hook paths.
- [compact-merger.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:58): `truncateToTokens()` truncates each compact-brief source after allocation.
- [budget-allocator.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:52): `allocateBudget()` distributes and caps compact-brief source budgets.
- [code-graph-context.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:534): `formatTextBrief()` stops adding sections near budget and slices final output if needed.
- [local-reranker.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:298): local reranker enforces a `MAX_PROMPT_BYTES` prompt cap before scoring.

Bottom line: for the MCP `memory_context` response truncation path, use [handlers/memory-context.ts:463](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:463). For generic hook text truncation, use [hooks/claude/shared.ts:96](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96).
hook: Stop
hook: Stop Completed
2026-04-27T14:52:54.655473Z ERROR codex_core::session: failed to record rollout items: thread 019dcf6c-82c9-78f0-a7d3-022d17fce65e not found
tokens used
126,408
Found the token-budget enforcement paths under `.opencode/skills/system-spec-kit/mcp_server/`.

The main function responsible for `memory_context` truncation behavior is [enforceTokenBudget](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:463). It estimates the serialized response, truncates oversized embedded `data.results`, compacts content fields, drops lowest-priority tail results, and falls back to minimal structured payloads if the budget is impossible.

Other enforcement/truncation paths:

- [context-server.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/context-server.ts:1139): dispatch-level wrapper calls `getTokenBudget(name)`, syncs envelope token count, and pops `data.results` until the per-layer budget is met.
- [layer-definitions.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/architecture/layer-definitions.ts:193): `getTokenBudget(toolName)` resolves per-tool layer budgets.
- [hybrid-search.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:1678): search pipeline applies budget truncation after trace/header enrichment.
- [hybrid-search.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/hybrid-search.ts:2398): `truncateToBudget()` does greedy highest-score-first result selection under budget.
- [dynamic-token-budget.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/dynamic-token-budget.ts:69): `getDynamicTokenBudget()` computes tier-based budgets, but the file explicitly says it is advisory only.
- [confidence-truncation.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/confidence-truncation.ts:102): `truncateByConfidence()` trims low-confidence tails by score-gap analysis; related, but confidence-based rather than token-budget-based.
- [memory-surface.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/memory-surface.ts:250): `enforceAutoSurfaceTokenBudget()` trims auto-surfaced triggered/constitutional memories or drops the payload.
- [hooks/claude/shared.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96): `truncateToTokenBudget()` is the shared hook text truncator used by Claude/Gemini/Copilot/Codex hook paths.
- [compact-merger.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/compact-merger.ts:58): `truncateToTokens()` truncates each compact-brief source after allocation.
- [budget-allocator.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/budget-allocator.ts:52): `allocateBudget()` distributes and caps compact-brief source budgets.
- [code-graph-context.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/code_graph/lib/code-graph-context.ts:534): `formatTextBrief()` stops adding sections near budget and slices final output if needed.
- [local-reranker.ts](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/lib/search/local-reranker.ts:298): local reranker enforces a `MAX_PROMPT_BYTES` prompt cap before scoring.

Bottom line: for the MCP `memory_context` response truncation path, use [handlers/memory-context.ts:463](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/handlers/memory-context.ts:463). For generic hook text truncation, use [hooks/claude/shared.ts:96](/Users/michelkerkmeester/MEGA/Development/Code_Environment/Public/.opencode/skills/system-spec-kit/mcp_server/hooks/claude/shared.ts:96).
