feat: env-based skill selection — run LLM once, cache for session#192
feat: env-based skill selection — run LLM once, cache for session#192
Conversation
2d217e6 to
71b8625
Compare
42ccc76 to
3e0314a
Compare
3e0314a to
7afaff9
Compare
5ee9c30 to
c1ef28c
Compare
c1ef28c to
26caeb1
Compare
| return detect(previousCwd) | ||
| } | ||
|
|
||
| export async function detect(cwd: string, root?: string): Promise<Result> { |
There was a problem hiding this comment.
Bug: The fingerprint cache is not invalidated between sessions for the same directory, leading to stale environment data being used for skill selection.
Severity: MEDIUM
Suggested Fix
The cache should be made session-aware. One approach is to call Fingerprint.refresh() at the start of each new session to force re-detection. Alternatively, the cache could be invalidated between sessions or the cache key could be modified to include a session-specific identifier.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: packages/opencode/src/altimate/fingerprint/index.ts#L28
Potential issue: A module-level cache for environment fingerprints is keyed only by the
current working directory (`cwd`). When a user starts a new session in the same
directory, `Fingerprint.detect()` is called with the same `cwd` and returns the cached
result from the previous session. If the project's dependencies or configuration (e.g.,
adding a `databricks.yml` file) changed between sessions, the stale cache is used. This
leads to incorrect environment detection and subsequent inaccurate skill selection, as
the system will not be aware of the updated project state.
26caeb1 to
eaeac4a
Compare
| log.info("returning cached skill selection", { | ||
| count: cachedResult.length, | ||
| }) | ||
| Tracer.active?.logSpan({ | ||
| name: "skill-selection", | ||
| startTime, | ||
| endTime: Date.now(), | ||
| input: { fingerprint: fingerprint?.tags, source: "cache" }, | ||
| output: { count: cachedResult.length, skills: cachedResult.map((s) => s.name) }, | ||
| }) | ||
| return cachedResult |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
dac4a4c to
b330ecf
Compare
b330ecf to
4661224
Compare
|
🚧 Skipped: PR exceeds review size limit. Please split into smaller PRs and re-run. |
4661224 to
99882ae
Compare
|
🚧 Skipped: PR exceeds review size limit. Please split into smaller PRs and re-run. |
99882ae to
d290e88
Compare
|
🚧 Skipped: PR exceeds review size limit. Please split into smaller PRs and re-run. |
Run LLM skill selector once per session using environment fingerprint, cache by working directory, and apply filtering to both system prompt and tool description. Adds tracing spans for fingerprint, skill selection, and system prompt. - Use LLM.stream for skill selection (proper provider auth) - Plain text response parsing (one skill name per line) - Cache keyed by cwd — invalidates on project change - Filter skills in both SystemPrompt.skills() and SkillTool - Add env_fingerprint_skill_selection config (default: true) - Trim fingerprint to data-engineering detections only - Add tracing for fingerprint, skill-selection, and system-prompt spans Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d290e88 to
1b04d6a
Compare
| try { | ||
| const sqlFiles = await Glob.scan("*.sql", { | ||
| cwd: dir, | ||
| include: "file", | ||
| }) | ||
| if (sqlFiles.length > 0) { |
There was a problem hiding this comment.
Bug: The glob pattern *.sql only scans the root directory for SQL files, failing to detect them in subdirectories, which is standard for dbt projects.
Severity: MEDIUM
Suggested Fix
To correctly identify SQL files in a typical dbt project structure, update the glob pattern in fingerprint/index.ts from *.sql to **/*.sql. This will enable a recursive search through all subdirectories.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: packages/opencode/src/altimate/fingerprint/index.ts#L114-L119
Potential issue: The SQL detection logic uses `Glob.scan("*.sql", ...)` to identify SQL
files for project fingerprinting. This pattern does not recursively search
subdirectories. Since dbt projects typically organize SQL models within subdirectories
like `models/`, the detection will fail for these standard project structures. This
results in an incomplete project fingerprint, as the `sql` tag will be missing.
Consequently, the LLM skill selector receives inaccurate environment information,
leading to suboptimal skill selection. The failure is silent due to an exception
handler.
Summary
env_fingerprint_skill_selectionconfig toggle underexperimental(default:true; setfalseto skip LLM selection entirely)Test plan
bun test test/altimate/skill-filtering.test.ts— 18 tests (selection, caching, fallbacks, prompt content)bun test test/altimate/fingerprint.test.ts— 5 tests (detect, cache, refresh, dedup)dynamic_skills, verify LLM called once on first turn, cached on second turn (check logs)env_fingerprint_skill_selection: false, verify all skills returned without LLM call🤖 Generated with Claude Code