Skip to content

Commit 135d9b7

Browse files
feat: add validation framework with conversation logger and auto-setup
- Add `/validate` skill with `batch_validate.py` for running trace validation against the Altimate backend (single trace, date range, or session mode) - Add `conversation-logger.ts` that fires on session idle and posts each conversation turn to `/log-conversation` (opt-out via `ALTIMATE_LOGGER_DISABLED=true`) - Add `logger_hook.py` — Claude Code Stop hook that reads the session JSONL transcript and posts conversation turns in the same payload format - Auto-install validate skill and logger hook on every `InstanceBootstrap`: - Copies `SKILL.md` + `batch_validate.py` → `~/.claude/skills/validate/` - Writes `altimate_logger_hook.py` → `~/.claude/hooks/` and merges Stop hook into `~/.claude/settings.json` (skipped if `ALTIMATE_LOGGER_DISABLED=true`) - Add `resolvePrompt` helper in session routes to deterministically route `/validate` commands without LLM classification - Add logging docs at `docs/docs/configure/logging.md` - Remove `validate install` from `bun run build` — setup is fully automatic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f668a67 commit 135d9b7

File tree

21 files changed

+1584
-15
lines changed

21 files changed

+1584
-15
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ concurrency:
1313
jobs:
1414
typescript:
1515
name: TypeScript
16-
runs-on: ubuntu-latest
16+
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'arc-runner-altimate-code' }}
1717
timeout-minutes: 60
1818
steps:
1919
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
@@ -44,7 +44,7 @@ jobs:
4444

4545
lint:
4646
name: Lint
47-
runs-on: ubuntu-latest
47+
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'arc-runner-altimate-code' }}
4848
timeout-minutes: 60
4949
steps:
5050
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
@@ -62,7 +62,7 @@ jobs:
6262

6363
python:
6464
name: Python ${{ matrix.python-version }}
65-
runs-on: ubuntu-latest
65+
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'arc-runner-altimate-code' }}
6666
timeout-minutes: 60
6767
strategy:
6868
matrix:

.github/workflows/release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ env:
1515
jobs:
1616
build:
1717
name: Build (${{ matrix.os }})
18-
runs-on: ubuntu-latest
18+
runs-on: arc-runner-altimate-code
1919
timeout-minutes: 60
2020
permissions:
2121
contents: read
@@ -59,7 +59,7 @@ jobs:
5959
publish-npm:
6060
name: Publish to npm
6161
needs: build
62-
runs-on: ubuntu-latest
62+
runs-on: arc-runner-altimate-code
6363
timeout-minutes: 60
6464
permissions:
6565
contents: read
@@ -125,7 +125,7 @@ jobs:
125125
# doesn't need CLI binary artifacts. This allows it to run in parallel.
126126
publish-engine:
127127
name: Publish engine to PyPI
128-
runs-on: ubuntu-latest
128+
runs-on: arc-runner-altimate-code
129129
timeout-minutes: 60
130130
environment: pypi
131131
permissions:
@@ -156,7 +156,7 @@ jobs:
156156
github-release:
157157
name: Create GitHub Release
158158
needs: [build, publish-npm]
159-
runs-on: ubuntu-latest
159+
runs-on: arc-runner-altimate-code
160160
timeout-minutes: 60
161161
permissions:
162162
contents: write

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
matrix:
1515
settings:
1616
- name: linux
17-
host: ubuntu-latest
17+
host: arc-runner-altimate-code
1818
- name: windows
1919
host: windows-latest
2020
runs-on: ${{ matrix.settings.host }}
@@ -46,7 +46,7 @@ jobs:
4646
matrix:
4747
settings:
4848
- name: linux
49-
host: ubuntu-latest
49+
host: arc-runner-altimate-code
5050
playwright: bunx playwright install --with-deps
5151
- name: windows
5252
host: windows-latest
@@ -89,7 +89,7 @@ jobs:
8989
9090
required:
9191
name: test (linux)
92-
runs-on: ubuntu-latest
92+
runs-on: arc-runner-altimate-code
9393
needs:
9494
- unit
9595
- e2e

.gitignore

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,37 @@ target
2323
.scripts
2424
.direnv/
2525

26+
# Python
27+
__pycache__/
28+
*.pyc
29+
*.pyo
30+
*.egg-info/
31+
32+
# SQLite databases (feedback store creates these at runtime)
33+
*.db
34+
35+
# Runtime logs
36+
*.log
37+
logs/
38+
39+
# Large intermediate files at repo root (generated during benchmark runs)
40+
/queries.json
41+
/queries_1k.json
42+
/results/
43+
44+
# Local runtime config
45+
.altimate-code/
46+
47+
# Commit message scratch files
48+
.github/meta/
49+
50+
# Experiment / simulation artifacts
51+
/data/
52+
/experiments/
53+
/models/
54+
/simulation/
55+
2656
# Local dev files
2757
opencode-dev
28-
logs/
2958
*.bun-build
3059
tsconfig.tsbuildinfo

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,20 @@ Full docs at **[altimate-code.sh](https://altimate-code.sh)**.
157157
- [Agent Modes](https://altimate-code.sh/data-engineering/agent-modes/)
158158
- [Configuration](https://altimate-code.sh/configure/model-providers/)
159159
160+
## Data Collection
161+
162+
Altimate Code logs conversation turns (prompt, tool calls, and assistant response) to improve validation quality and agent behavior. Logs are sent to Altimate's backend and are not shared with third parties.
163+
164+
**To opt out:**
165+
166+
```bash
167+
export ALTIMATE_LOGGER_DISABLED=true
168+
```
169+
170+
Add it to your shell profile (`~/.zshrc`, `~/.bashrc`) to make it permanent.
171+
172+
See [`docs/docs/configure/logging.md`](docs/docs/configure/logging.md) for details on what is collected.
173+
160174
## Community & Contributing
161175
162176
- **Issues**: [GitHub Issues](https://github.com/AltimateAI/altimate-code/issues)

bun.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/docs/configure/logging.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Conversation Logging
2+
3+
Altimate Code automatically logs each conversation turn to the Altimate backend. This powers validation, audit, and quality analysis features. Logging is **enabled by default** — no configuration is required to activate it.
4+
5+
## What Is Logged
6+
7+
Each turn (one user prompt + all assistant responses) sends the following to the Altimate backend:
8+
9+
| Field | Description |
10+
|-------|-------------|
11+
| `session_id` | The current session identifier |
12+
| `conversation_id` | The assistant message ID for this turn |
13+
| `user_id` | Your email or username (from your Altimate account) |
14+
| `user_prompt` | The text of your message |
15+
| `parts` | All reasoning, text, and tool call/response parts from the assistant |
16+
| `final_response` | The last text response from the assistant |
17+
| `metadata` | Model ID, token counts, and cost for the turn |
18+
19+
Logging fires after the session becomes idle (i.e., after the assistant finishes responding). Up to 500 messages are captured per turn to ensure complete coverage of multi-step agentic sessions.
20+
21+
## Why We Log
22+
23+
Conversation logs are used to:
24+
25+
- **Validate AI responses** — power the `/validate` skill that audits factual claims against source data
26+
- **Quality analysis** — identify recurring failure patterns across sessions
27+
- **Audit trails** — provide a record of what the assistant did and why
28+
29+
## Disabling Logging
30+
31+
Logging is on by default. To disable it, set the following environment variable before starting Altimate Code:
32+
33+
```bash
34+
export ALTIMATE_LOGGER_DISABLED=true
35+
```
36+
37+
To make this permanent, add it to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.):
38+
39+
```bash
40+
echo 'export ALTIMATE_LOGGER_DISABLED=true' >> ~/.zshrc
41+
source ~/.zshrc
42+
```
43+
44+
To re-enable logging, unset the variable:
45+
46+
```bash
47+
unset ALTIMATE_LOGGER_DISABLED
48+
```
49+
50+
Setting `ALTIMATE_LOGGER_DISABLED=false` is equivalent to not setting it — logging will be active.
51+
52+
## Network
53+
54+
Conversation logs are sent to:
55+
56+
| Endpoint | Purpose |
57+
|----------|---------|
58+
| `apimi.tryaltimate.com` | Conversation log ingestion |
59+
60+
Requests are fire-and-forget — a failed log request does not affect your session in any way.

packages/altimate-code/src/provider/models-snapshot.ts

Lines changed: 2 additions & 0 deletions
Large diffs are not rendered by default.

packages/opencode/script/build.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ const migrations = await Promise.all(
7171
)
7272
console.log(`Loaded ${migrations.length} migrations`)
7373

74+
// Load validate skill assets for embedding
75+
const validateSkillMd = await Bun.file(path.join(dir, "src/skill/validate/SKILL.md")).text()
76+
const validateBatchPy = await Bun.file(path.join(dir, "src/skill/validate/batch_validate.py")).text()
77+
console.log("Loaded validate skill assets")
78+
79+
// Load logger hook for embedding
80+
const loggerHookPy = await Bun.file(path.join(dir, "src/skill/validate/logger_hook.py")).text()
81+
console.log("Loaded logger hook")
82+
7483
const singleFlag = process.argv.includes("--single")
7584
const baselineFlag = process.argv.includes("--baseline")
7685
const skipInstall = process.argv.includes("--skip-install")
@@ -220,6 +229,9 @@ for (const item of targets) {
220229
OPENCODE_LIBC: item.os === "linux" ? `'${item.abi ?? "glibc"}'` : "undefined",
221230
OPENCODE_MIGRATIONS: JSON.stringify(migrations),
222231
OPENCODE_CHANGELOG: JSON.stringify(changelog),
232+
ALTIMATE_VALIDATE_SKILL_MD: JSON.stringify(validateSkillMd),
233+
ALTIMATE_VALIDATE_BATCH_PY: JSON.stringify(validateBatchPy),
234+
ALTIMATE_LOGGER_HOOK_PY: JSON.stringify(loggerHookPy),
223235
OTUI_TREE_SITTER_WORKER_PATH: bunfsRoot + workerRelativePath,
224236
},
225237
})

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ import type { EventSource } from "./context/sdk"
106106
export function tui(input: {
107107
url: string
108108
args: Args
109+
config: TuiConfig.Info
109110
directory?: string
110111
fetch?: typeof fetch
111112
headers?: RequestInit["headers"]

0 commit comments

Comments
 (0)