Skip to content

Commit bc44570

Browse files
authored
Merge branch 'main' into feat/verifier-gated-router
2 parents fa7a3f6 + 5c1fedf commit bc44570

8 files changed

Lines changed: 433 additions & 9 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Dispatch Code Review
2+
3+
# Lightweight relay — on PR ready (not every push), dispatches the centralized
4+
# ocr/Gemini review in AltimateAI/altimate-qa (code-review.yml).
5+
#
6+
# Gated loop: review fires only when a PR is opened non-draft or marked Ready for
7+
# review. `synchronize` is intentionally omitted so pushes don't re-trigger.
8+
# altimate-qa flips the PR back to draft on CRITICAL findings, so re-review happens
9+
# on the next ready_for_review after the author addresses them.
10+
#
11+
# Token: reuses the org-level AUTOPILOT_DISPATCH_TOKEN (same one dbt-integration /
12+
# vscode-dbt-power-user use to dispatch to altimate-qa). If that org secret is not
13+
# visible to this repo, the step skips cleanly — ask an admin to extend its repo
14+
# visibility (no new token needs to be created).
15+
16+
on:
17+
pull_request:
18+
types: [opened, ready_for_review]
19+
branches: [main]
20+
21+
concurrency:
22+
group: dispatch-code-review-${{ github.event.pull_request.number }}
23+
cancel-in-progress: true
24+
25+
permissions:
26+
contents: read
27+
28+
jobs:
29+
dispatch:
30+
name: Notify altimate-qa
31+
runs-on: ubuntu-latest
32+
if: github.event.pull_request.draft == false
33+
timeout-minutes: 2
34+
steps:
35+
- name: Dispatch to centralized code review
36+
env:
37+
GH_TOKEN: ${{ secrets.AUTOPILOT_DISPATCH_TOKEN }}
38+
PR_NUMBER: ${{ github.event.pull_request.number }}
39+
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
40+
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
41+
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
42+
PR_TITLE: ${{ github.event.pull_request.title }}
43+
run: |
44+
if [ -z "$GH_TOKEN" ]; then
45+
echo "AUTOPILOT_DISPATCH_TOKEN not available to altimate-code — skipping centralized dispatch."
46+
echo "Ask an org admin to extend that org secret's visibility to AltimateAI/altimate-code."
47+
exit 0
48+
fi
49+
gh api repos/AltimateAI/altimate-qa/dispatches \
50+
--method POST \
51+
-f event_type=code-review \
52+
-f "client_payload[repo]=AltimateAI/altimate-code" \
53+
-f "client_payload[pr_number]=$PR_NUMBER" \
54+
-f "client_payload[head_ref]=$PR_HEAD_REF" \
55+
-f "client_payload[head_sha]=$PR_HEAD_SHA" \
56+
-f "client_payload[author]=$PR_AUTHOR" \
57+
-f "client_payload[title]=$PR_TITLE"
58+
echo "Dispatched code review for PR #$PR_NUMBER"

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.8.6] - 2026-06-08
9+
10+
### Added
11+
12+
- **Session traces now work in headless `serve` mode — your VS Code "Altimate Code" chat sessions show up in `/traces` just like terminal sessions.** Sessions driven over `altimate serve` (the server behind the VS Code chat panel) had no TUI worker observing the event stream, so trace files were never written and `/traces` was always empty after a chat. The per-session tracing logic is now a shared `TraceConsumer` wired into both the TUI worker and `serve`, so IDE chat sessions produce the same incremental `ses_<id>.json` files — full multi-turn waterfall, recorded prompt, tool-call log, cost, and timing. `serve` now registers `SIGINT`/`SIGTERM`/`beforeExit` handlers that drain and finalize in-flight traces on shutdown (so a serve trace ends as `completed`, not `running`, and the process exits with signal-conventional codes), finalizes a session as soon as it is deleted, and finalizes all open sessions concurrently so a busy server isn't cut off mid-write by a container shutdown grace period. (#886)
13+
814
## [0.8.5] - 2026-06-06
915

1016
### Fixed

docs/docs/configure/trace.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ Traces are designed to survive process crashes:
325325

326326
2. **Incremental snapshots.** After every tool call and generation completion, the trace file is updated atomically (write to temp file, then rename). The file on disk always contains a valid, complete JSON document.
327327

328-
3. **Crash handlers.** The `run` command registers `SIGINT`/`SIGTERM`/`beforeExit` handlers that flush the trace synchronously with a `"crashed"` status.
328+
3. **Crash handlers.** The `run` and `serve` commands register `SIGINT`/`SIGTERM`/`beforeExit` handlers that finalize in-flight traces on shutdown. (`run` flushes synchronously with a `"crashed"` status; `serve` drains and finalizes its active sessions.)
329329

330330
4. **Status indicators.** Trace status tells you exactly what happened:
331331

docs/docs/usage/ide.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This opens the Altimate Code chat panel where you can interact with altimate age
3939
- **Tool call results inline** — SQL analysis, lineage, dbt operations, and more displayed in the chat
4040
- **Agent mode switching** — switch between Builder (full read/write), Analyst (read-only), and Plan (minimal access) modes from the command palette
4141
- **100+ data engineering tools** — SQL validation, query optimization, column lineage, dbt model generation, FinOps analysis, schema exploration, and more
42+
- **Session tracing** — every chat session is recorded as a trace file (the IDE panel runs `altimate-code serve` under the hood, which now writes traces just like the terminal). Inspect them with `altimate-code trace list` / `altimate-code trace view <id>`. See [Traces](../configure/trace.md).
4243

4344
## Configuration
4445

packages/opencode/src/altimate/observability/trace-consumer.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,17 @@ export class TraceConsumer {
309309
this.sessionUserMsgIds.clear()
310310
}
311311

312-
/** End all in-flight traces and wait for them. Used on shutdown. */
312+
/**
313+
* End all in-flight traces and wait for them. Used on shutdown.
314+
* Finalizes sessions concurrently rather than sequentially: each
315+
* `endTrace()` can wait on an HttpExporter (5s timeout each), so a sequential
316+
* loop over N sessions could take N×5s and blow past a container's shutdown
317+
* grace period (e.g. k8s `terminationGracePeriodSeconds`) and be SIGKILL'd
318+
* mid-write. Concurrent finalization bounds the wall-clock to the slowest
319+
* single trace.
320+
*/
313321
async flush() {
314-
for (const [, trace] of this.sessionTraces) {
315-
await trace.endTrace().catch(() => {})
316-
}
322+
await Promise.allSettled([...this.sessionTraces.values()].map((trace) => trace.endTrace().catch(() => {})))
317323
this.sessionTraces.clear()
318324
this.sessionUserMsgIds.clear()
319325
}
@@ -410,7 +416,11 @@ export function subscribeTraceConsumer(
410416
}
411417
} catch (err) {
412418
if (!signal.aborted) {
413-
Log.Default.warn("[tracing] trace event stream disconnected, reconnecting", {
419+
// debug, not warn: this is the in-process event stream, reconnect is
420+
// automatic and not user-actionable. Logging at warn on every backoff
421+
// iteration (up to ~7 in the first 8s of an outage) would spike log
422+
// aggregators for something the operator can't act on.
423+
Log.Default.debug("[tracing] trace event stream ended, reconnecting", {
414424
error: err instanceof Error ? err.message : String(err),
415425
})
416426
}

packages/opencode/src/cli/cmd/serve.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export const ServeCommand = cmd({
2929
// serve mode. Subscribe the shared trace consumer to the in-process
3030
// event stream so serve sessions produce the same trace files as the
3131
// terminal entrypoints.
32+
//
33+
// `directory` is the SDK workspace/routing context, NOT the trace output
34+
// location — trace files always go to the configured tracing dir
35+
// (`tracing.dir`, default ~/.local/share/altimate-code/traces/).
3236
const traceSub = subscribeTraceConsumer({ directory: process.cwd() })
3337

3438
// Finalize traces on shutdown. `serve` blocks forever on the promise below

packages/opencode/test/skill/release-v0.8.5-adversarial.test.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,15 @@ describe("v0.8.5 adversarial - composite action", () => {
228228
})
229229

230230
test("docs point at the action patch, not the already-published broken tag", async () => {
231+
// This is the 0.8.5 release gate: it asserts the 0.8.5 docs reference the
232+
// patched action tag (@v0.8.5) and NOT the already-published broken @v0.8.4.
233+
// It must stay pinned to the constant "0.8.5" — earlier this derived `version`
234+
// from the changelog's TOP entry, which later releases (0.8.6+) move, breaking
235+
// the gate on every subsequent release. Assert the 0.8.5 entry EXISTS in the
236+
// changelog rather than that it is the latest.
237+
const version = "0.8.5"
231238
const changelog = await fs.readFile(path.join(repoRoot, "CHANGELOG.md"), "utf8")
232-
// Match whether the entry is still "Unreleased" or has been date-stamped at release.
233-
const version = changelog.match(/^## \[(\d+\.\d+\.\d+)\] - (?:Unreleased|\d{4}-\d{2}-\d{2})$/m)?.[1]
234-
expect(version).toBe("0.8.5")
239+
expect(changelog).toContain(`## [${version}]`)
235240

236241
for (const relative of ["docs/docs/usage/dbt-pr-review.md", "github/review/examples/altimate-ingestion.yml"]) {
237242
const content = await fs.readFile(path.join(repoRoot, relative), "utf8")

0 commit comments

Comments
 (0)