chore: record journal
This commit is contained in:
parent
887eb14eca
commit
c50465eff4
53
.trellis/tasks/04-17-04-17-fix-sync-panic/task.json
Normal file
53
.trellis/tasks/04-17-04-17-fix-sync-panic/task.json
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"id": "04-17-fix-sync-panic",
|
||||||
|
"name": "04-17-fix-sync-panic",
|
||||||
|
"title": "Fix sync command panic",
|
||||||
|
"description": "",
|
||||||
|
"status": "planning",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "Apale",
|
||||||
|
"assignee": "Apale",
|
||||||
|
"createdAt": "2026-04-17",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "master",
|
||||||
|
"worktree_path": null,
|
||||||
|
"current_phase": 0,
|
||||||
|
"next_action": [
|
||||||
|
{
|
||||||
|
"phase": 1,
|
||||||
|
"action": "brainstorm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 2,
|
||||||
|
"action": "research"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 3,
|
||||||
|
"action": "implement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 4,
|
||||||
|
"action": "check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 5,
|
||||||
|
"action": "update-spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 6,
|
||||||
|
"action": "record-session"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
469
.trellis/tasks/04-17-forwarding-log-viewer-gui/prd.md
Normal file
469
.trellis/tasks/04-17-forwarding-log-viewer-gui/prd.md
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
# OLPX Forwarding Log Viewer Design
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`olpx` currently exposes enough per-request routing information for header-level debugging, but it does not keep a durable request log and it does not provide any local UI.
|
||||||
|
|
||||||
|
This task defines a minimal, implementation-ready design for a local web log viewer that shows each forwarded request with:
|
||||||
|
|
||||||
|
- the selected provider
|
||||||
|
- the selected upstream model
|
||||||
|
- input, output, and total token counts when available
|
||||||
|
- whether failover was triggered
|
||||||
|
- the attempt chain that led to the final result
|
||||||
|
|
||||||
|
The design is intentionally scoped to the current codebase:
|
||||||
|
|
||||||
|
- Go backend only
|
||||||
|
- no existing frontend build pipeline
|
||||||
|
- only OpenAI Responses proxying today
|
||||||
|
- failover is only valid before first downstream byte
|
||||||
|
|
||||||
|
## Current Project State
|
||||||
|
|
||||||
|
### What already exists
|
||||||
|
|
||||||
|
`olpx` already has the core proxy path in `internal/proxy/server.go`:
|
||||||
|
|
||||||
|
- `POST /v1/responses`
|
||||||
|
- deterministic ordered failover
|
||||||
|
- retry on transport errors, `429`, and `5xx`
|
||||||
|
- no mid-stream failover after downstream response starts
|
||||||
|
- debug response headers:
|
||||||
|
- `X-OLPX-Alias`
|
||||||
|
- `X-OLPX-Provider`
|
||||||
|
- `X-OLPX-Remote-Model`
|
||||||
|
- `X-OLPX-Attempt`
|
||||||
|
- `X-OLPX-Failover-Count`
|
||||||
|
|
||||||
|
### What is missing
|
||||||
|
|
||||||
|
- no durable per-request log
|
||||||
|
- no token accounting capture
|
||||||
|
- no HTTP endpoint for log history
|
||||||
|
- no local HTML page
|
||||||
|
- no request attempt history persisted anywhere
|
||||||
|
|
||||||
|
## Product Goal
|
||||||
|
|
||||||
|
Give the user a simple local page that makes forwarding behavior visible without reading raw terminal logs.
|
||||||
|
|
||||||
|
For every completed forwarding operation, the page should make it obvious:
|
||||||
|
|
||||||
|
1. which alias was requested
|
||||||
|
2. which provider and upstream model finally served it
|
||||||
|
3. whether failover happened
|
||||||
|
4. how many attempts were made
|
||||||
|
5. how many input, output, and total tokens were reported
|
||||||
|
|
||||||
|
## Non-Goals
|
||||||
|
|
||||||
|
1. No hosted dashboard.
|
||||||
|
2. No Electron or native desktop GUI.
|
||||||
|
3. No cost accounting or billing estimation.
|
||||||
|
4. No prompt/response body browsing.
|
||||||
|
5. No full-text search over request payloads.
|
||||||
|
6. No live stream reconstruction in the browser.
|
||||||
|
7. No multi-user auth model beyond the current local-only default posture.
|
||||||
|
|
||||||
|
## Recommended MVP Shape
|
||||||
|
|
||||||
|
Choose a local web UI, not a separate GUI app.
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
|
||||||
|
- it fits the current Go-only codebase
|
||||||
|
- it avoids adding a frontend toolchain
|
||||||
|
- it can run off the same `olpx serve` process and listener
|
||||||
|
- it is the smallest path to a usable visual log surface
|
||||||
|
|
||||||
|
## High-Level Design
|
||||||
|
|
||||||
|
When `olpx serve` is running, the same HTTP server should expose three surfaces:
|
||||||
|
|
||||||
|
1. proxy API
|
||||||
|
- `POST /v1/responses`
|
||||||
|
- `GET /v1/models`
|
||||||
|
|
||||||
|
2. log viewer UI
|
||||||
|
- `GET /logs`
|
||||||
|
|
||||||
|
3. log viewer data API
|
||||||
|
- `GET /api/logs`
|
||||||
|
- `GET /api/logs/{id}`
|
||||||
|
|
||||||
|
The UI should be a single embedded HTML page with minimal CSS and vanilla JS.
|
||||||
|
|
||||||
|
No Node, bundler, or SPA framework should be introduced for this feature.
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
incoming /v1/responses request
|
||||||
|
-> create in-memory request log draft
|
||||||
|
-> record each upstream attempt result
|
||||||
|
-> on final completion, attach usage if available
|
||||||
|
-> append one finalized JSON record to local log file
|
||||||
|
-> push finalized record into in-memory recent ring buffer
|
||||||
|
-> /api/logs serves recent records to /logs page
|
||||||
|
```
|
||||||
|
|
||||||
|
The key design choice is: persist one finalized record per request, not one row per streaming chunk and not one row per partial attempt.
|
||||||
|
|
||||||
|
This keeps storage simple and makes the UI directly match the user's mental model: one forwarding operation equals one log entry.
|
||||||
|
|
||||||
|
## Storage Strategy
|
||||||
|
|
||||||
|
### Recommended MVP storage
|
||||||
|
|
||||||
|
Use an append-only JSONL file stored next to the existing `olpx` config:
|
||||||
|
|
||||||
|
- config path today: `~/.config/olpx/config.json` by default
|
||||||
|
- proposed log path: `~/.config/olpx/request-log.jsonl`
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
|
||||||
|
- no database dependency required
|
||||||
|
- minimal code and operational complexity
|
||||||
|
- easy to inspect manually
|
||||||
|
- easy to rotate or delete
|
||||||
|
- aligned with current non-SQLite implementation
|
||||||
|
|
||||||
|
### In-memory cache
|
||||||
|
|
||||||
|
Maintain a small in-memory ring buffer of the most recent finalized records, for example the latest `500` entries.
|
||||||
|
|
||||||
|
On process start:
|
||||||
|
|
||||||
|
- load the latest records from `request-log.jsonl` into memory
|
||||||
|
|
||||||
|
During runtime:
|
||||||
|
|
||||||
|
- append finalized record to disk
|
||||||
|
- append finalized record to ring buffer
|
||||||
|
|
||||||
|
This gives fast UI reads while still preserving history across restarts.
|
||||||
|
|
||||||
|
## Log Record Schema
|
||||||
|
|
||||||
|
Each finalized request log entry should contain at least the following fields:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "req_20260417_000123",
|
||||||
|
"started_at": "2026-04-17T12:34:56.123Z",
|
||||||
|
"completed_at": "2026-04-17T12:34:58.004Z",
|
||||||
|
"duration_ms": 1881,
|
||||||
|
"protocol": "openai-responses",
|
||||||
|
"alias": "gpt-5.4",
|
||||||
|
"raw_model": "olpx/gpt-5.4",
|
||||||
|
"stream": true,
|
||||||
|
"final_status": 200,
|
||||||
|
"final_provider": "p2",
|
||||||
|
"final_remote_model": "GPT-5.4",
|
||||||
|
"attempt_count": 2,
|
||||||
|
"failover_count": 1,
|
||||||
|
"failover_triggered": true,
|
||||||
|
"usage": {
|
||||||
|
"input_tokens": 812,
|
||||||
|
"output_tokens": 143,
|
||||||
|
"total_tokens": 955,
|
||||||
|
"available": true,
|
||||||
|
"source": "response_usage"
|
||||||
|
},
|
||||||
|
"attempts": [
|
||||||
|
{
|
||||||
|
"attempt": 1,
|
||||||
|
"provider": "p1",
|
||||||
|
"remote_model": "up-1",
|
||||||
|
"outcome": "retryable_status",
|
||||||
|
"upstream_status": 429,
|
||||||
|
"error_summary": "upstream 429: rate limit",
|
||||||
|
"duration_ms": 220
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attempt": 2,
|
||||||
|
"provider": "p2",
|
||||||
|
"remote_model": "GPT-5.4",
|
||||||
|
"outcome": "success",
|
||||||
|
"upstream_status": 200,
|
||||||
|
"duration_ms": 1661
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required field semantics
|
||||||
|
|
||||||
|
- `alias`: normalized local alias actually routed by `olpx`
|
||||||
|
- `raw_model`: original request payload `model` value before normalization
|
||||||
|
- `final_provider`: provider that produced the downstream response visible to the client
|
||||||
|
- `final_remote_model`: upstream model name actually sent to that provider
|
||||||
|
- `failover_triggered`: `true` when the request had to move beyond the initial target
|
||||||
|
- `attempts`: ordered attempt chain, including retryable failures before success
|
||||||
|
|
||||||
|
### Fields that must stay nullable
|
||||||
|
|
||||||
|
`usage.input_tokens`, `usage.output_tokens`, and `usage.total_tokens` must be nullable in storage and UI.
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
|
||||||
|
- some failures end before usage exists
|
||||||
|
- some providers may omit usage
|
||||||
|
- some stream terminations may prevent complete usage extraction
|
||||||
|
|
||||||
|
## Token Collection Design
|
||||||
|
|
||||||
|
### Requirement boundary
|
||||||
|
|
||||||
|
The user asked for input/output token counts, so MVP must collect usage from upstream responses when that information is present.
|
||||||
|
|
||||||
|
### Non-streaming path
|
||||||
|
|
||||||
|
For non-streaming OpenAI Responses responses:
|
||||||
|
|
||||||
|
- capture the full JSON body already headed to the client
|
||||||
|
- parse `usage` from the final response object
|
||||||
|
|
||||||
|
### Streaming path
|
||||||
|
|
||||||
|
For streaming responses:
|
||||||
|
|
||||||
|
- do not buffer the whole response before writing downstream
|
||||||
|
- keep current streaming pass-through behavior
|
||||||
|
- tee streamed bytes into a lightweight SSE parser
|
||||||
|
- extract usage from the terminal lifecycle event that contains final response usage when present
|
||||||
|
|
||||||
|
In practice this will usually mean parsing the final response completion event and reading its usage payload.
|
||||||
|
|
||||||
|
### Missing usage behavior
|
||||||
|
|
||||||
|
If usage cannot be determined:
|
||||||
|
|
||||||
|
- keep the request log entry
|
||||||
|
- set usage fields to `null`
|
||||||
|
- set `usage.available = false`
|
||||||
|
- record a short reason such as `missing_from_upstream` or `stream_incomplete`
|
||||||
|
|
||||||
|
The request itself must not fail just because logging could not extract usage.
|
||||||
|
|
||||||
|
## Failover Visibility Design
|
||||||
|
|
||||||
|
The UI must make failover impossible to miss.
|
||||||
|
|
||||||
|
### Request list presentation
|
||||||
|
|
||||||
|
Each row should show a failover badge with one of two states:
|
||||||
|
|
||||||
|
- `Primary` when `failover_triggered = false`
|
||||||
|
- `Failover` when `failover_triggered = true`
|
||||||
|
|
||||||
|
### Request detail presentation
|
||||||
|
|
||||||
|
Expanding a row should show the attempt chain in order, for example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Attempt 1 p1 / up-1 429 retryable
|
||||||
|
Attempt 2 p2 / GPT-5.4 success
|
||||||
|
```
|
||||||
|
|
||||||
|
This detail view is necessary because `failover_count` alone does not explain why failover happened.
|
||||||
|
|
||||||
|
## UI Design
|
||||||
|
|
||||||
|
### Route
|
||||||
|
|
||||||
|
`GET /logs`
|
||||||
|
|
||||||
|
### Layout
|
||||||
|
|
||||||
|
Use one compact page with two sections:
|
||||||
|
|
||||||
|
1. top summary strip
|
||||||
|
2. request table with expandable detail rows
|
||||||
|
|
||||||
|
### Summary strip
|
||||||
|
|
||||||
|
Show a small set of metrics derived from loaded records:
|
||||||
|
|
||||||
|
- recent request count
|
||||||
|
- recent failover count
|
||||||
|
- recent failover rate
|
||||||
|
- last request time
|
||||||
|
|
||||||
|
This should stay informational only. No charts are required for MVP.
|
||||||
|
|
||||||
|
### Request table columns
|
||||||
|
|
||||||
|
The main table should show:
|
||||||
|
|
||||||
|
- Time
|
||||||
|
- Alias
|
||||||
|
- Final Provider
|
||||||
|
- Final Model
|
||||||
|
- Status
|
||||||
|
- Tokens In
|
||||||
|
- Tokens Out
|
||||||
|
- Tokens Total
|
||||||
|
- Failover
|
||||||
|
- Duration
|
||||||
|
|
||||||
|
### Filters
|
||||||
|
|
||||||
|
Keep filters intentionally small:
|
||||||
|
|
||||||
|
- text search for alias/provider/model
|
||||||
|
- failover only toggle
|
||||||
|
- status filter
|
||||||
|
- page size selector
|
||||||
|
|
||||||
|
### Detail row
|
||||||
|
|
||||||
|
Expanding a row should show:
|
||||||
|
|
||||||
|
- request id
|
||||||
|
- raw model
|
||||||
|
- stream true/false
|
||||||
|
- attempt timeline
|
||||||
|
- short error summary for failed attempts
|
||||||
|
|
||||||
|
Do not show prompt text, response text, or authorization headers.
|
||||||
|
|
||||||
|
## HTTP API Design
|
||||||
|
|
||||||
|
### `GET /api/logs`
|
||||||
|
|
||||||
|
Returns recent finalized records in reverse chronological order.
|
||||||
|
|
||||||
|
Suggested query params:
|
||||||
|
|
||||||
|
- `limit`
|
||||||
|
- `cursor`
|
||||||
|
- `failover_only`
|
||||||
|
- `status`
|
||||||
|
- `q`
|
||||||
|
|
||||||
|
### `GET /api/logs/{id}`
|
||||||
|
|
||||||
|
Returns one full finalized record including all attempts.
|
||||||
|
|
||||||
|
### Pagination
|
||||||
|
|
||||||
|
Cursor pagination is preferred over offset pagination.
|
||||||
|
|
||||||
|
Reason:
|
||||||
|
|
||||||
|
- append-only log shape
|
||||||
|
- stable ordering by completion time
|
||||||
|
- easier incremental page refresh
|
||||||
|
|
||||||
|
## Security and Privacy
|
||||||
|
|
||||||
|
### Must not log
|
||||||
|
|
||||||
|
- upstream API keys
|
||||||
|
- incoming Authorization headers
|
||||||
|
- full request body
|
||||||
|
- full model input text
|
||||||
|
- full model output text
|
||||||
|
|
||||||
|
### Why
|
||||||
|
|
||||||
|
The viewer is for routing observability, not transcript storage.
|
||||||
|
|
||||||
|
This keeps the feature useful without turning it into a sensitive local prompt archive.
|
||||||
|
|
||||||
|
### Local exposure model
|
||||||
|
|
||||||
|
For MVP, the log viewer can follow the same trust model as the current local proxy:
|
||||||
|
|
||||||
|
- same local process
|
||||||
|
- same loopback listener by default
|
||||||
|
- intended for single-user localhost usage
|
||||||
|
|
||||||
|
If `olpx` is later allowed to bind non-loopback addresses, the log UI and log API should be explicitly gated before reuse in that mode.
|
||||||
|
|
||||||
|
## Implementation Plan
|
||||||
|
|
||||||
|
### Phase 1: request log model and storage
|
||||||
|
|
||||||
|
- add a request log record type
|
||||||
|
- add append-only JSONL writer
|
||||||
|
- add startup loader for recent records
|
||||||
|
- add in-memory ring buffer
|
||||||
|
|
||||||
|
### Phase 2: proxy instrumentation
|
||||||
|
|
||||||
|
- create one draft log object per incoming request
|
||||||
|
- capture normalized alias and raw model
|
||||||
|
- record every attempt outcome
|
||||||
|
- record final provider, remote model, status, and duration
|
||||||
|
- extract usage from success responses when available
|
||||||
|
|
||||||
|
### Phase 3: local web surface
|
||||||
|
|
||||||
|
- add `GET /logs`
|
||||||
|
- add `GET /api/logs`
|
||||||
|
- add `GET /api/logs/{id}`
|
||||||
|
- embed a single static HTML/CSS/JS page
|
||||||
|
|
||||||
|
### Phase 4: docs and tests
|
||||||
|
|
||||||
|
- document the viewer route in `README.md`
|
||||||
|
- add tests for failover logging
|
||||||
|
- add tests for non-failover logging
|
||||||
|
- add tests for usage extraction fallback behavior
|
||||||
|
|
||||||
|
## Suggested Package Additions
|
||||||
|
|
||||||
|
Keep the changes minimal.
|
||||||
|
|
||||||
|
Suggested new package:
|
||||||
|
|
||||||
|
```text
|
||||||
|
internal/requestlog/
|
||||||
|
model.go
|
||||||
|
store.go
|
||||||
|
api.go
|
||||||
|
```
|
||||||
|
|
||||||
|
Suggested existing files to extend:
|
||||||
|
|
||||||
|
- `internal/proxy/server.go`
|
||||||
|
- `internal/proxy/server_test.go`
|
||||||
|
- `internal/cli/serve.go`
|
||||||
|
- `README.md`
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
This design is considered implemented successfully when:
|
||||||
|
|
||||||
|
1. running `olpx serve` exposes a local page at `/logs`
|
||||||
|
2. the page shows one row per completed forwarding request
|
||||||
|
3. each row clearly shows final provider and final upstream model
|
||||||
|
4. each row clearly shows whether failover happened
|
||||||
|
5. token counts are displayed when upstream usage is available
|
||||||
|
6. expanding a row shows the attempt chain that led to the final result
|
||||||
|
7. no request/response text or secrets are persisted to the log
|
||||||
|
|
||||||
|
## Out of Scope for This Task
|
||||||
|
|
||||||
|
1. historical charts and trends
|
||||||
|
2. exporting CSV
|
||||||
|
3. provider health scoring
|
||||||
|
4. live websocket or SSE push to the browser
|
||||||
|
5. per-provider cost calculation
|
||||||
|
6. editing provider or alias config from the UI
|
||||||
|
|
||||||
|
## Final Recommendation
|
||||||
|
|
||||||
|
Implement this as a same-process local web viewer backed by append-only JSONL request summaries.
|
||||||
|
|
||||||
|
This is the smallest design that satisfies the user's stated need:
|
||||||
|
|
||||||
|
- concise GUI/web page
|
||||||
|
- explicit provider/model visibility
|
||||||
|
- token visibility
|
||||||
|
- unambiguous failover visibility
|
||||||
|
|
||||||
|
It also fits the actual repository state today without introducing a frontend stack, database migration, or broader dashboard scope.
|
||||||
73
.trellis/tasks/04-17-forwarding-log-viewer-gui/task.json
Normal file
73
.trellis/tasks/04-17-forwarding-log-viewer-gui/task.json
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"id": "forwarding-log-viewer-gui",
|
||||||
|
"name": "forwarding-log-viewer-gui",
|
||||||
|
"title": "Design forwarding log viewer GUI for olpx",
|
||||||
|
"description": "Define a minimal local web UI and request logging design for olpx forwarding operations, including provider/model visibility, token usage, and failover display.",
|
||||||
|
"status": "completed",
|
||||||
|
"dev_type": "docs",
|
||||||
|
"scope": "observability",
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "Apale",
|
||||||
|
"assignee": "Apale",
|
||||||
|
"createdAt": "2026-04-17",
|
||||||
|
"completedAt": "2026-04-17",
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "master",
|
||||||
|
"worktree_path": null,
|
||||||
|
"current_phase": 0,
|
||||||
|
"next_action": [
|
||||||
|
{
|
||||||
|
"phase": 1,
|
||||||
|
"action": "brainstorm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 2,
|
||||||
|
"action": "research"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 3,
|
||||||
|
"action": "implement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 4,
|
||||||
|
"action": "check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 5,
|
||||||
|
"action": "update-spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 6,
|
||||||
|
"action": "record-session"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [
|
||||||
|
".trellis/tasks/04-17-forwarding-log-viewer-gui/prd.md",
|
||||||
|
"internal/proxy/server.go",
|
||||||
|
"internal/proxy/server_test.go",
|
||||||
|
"internal/cli/serve.go",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"notes": "Design-only task completed. The PRD recommends a same-process local web viewer with append-only JSONL request logs and no new frontend build system.",
|
||||||
|
"meta": {
|
||||||
|
"recommendedSurface": "local-web-ui",
|
||||||
|
"protocolScope": [
|
||||||
|
"openai-responses"
|
||||||
|
],
|
||||||
|
"storageRecommendation": "jsonl-next-to-config",
|
||||||
|
"mustShow": [
|
||||||
|
"provider",
|
||||||
|
"remote-model",
|
||||||
|
"input-tokens",
|
||||||
|
"output-tokens",
|
||||||
|
"total-tokens",
|
||||||
|
"failover"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"id": "preserve-opencode-model-metadata-sync",
|
||||||
|
"name": "preserve-opencode-model-metadata-sync",
|
||||||
|
"title": "Preserve OpenCode model metadata during olpx sync",
|
||||||
|
"description": "",
|
||||||
|
"status": "completed",
|
||||||
|
"dev_type": null,
|
||||||
|
"scope": null,
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "Apale",
|
||||||
|
"assignee": "Apale",
|
||||||
|
"createdAt": "2026-04-17",
|
||||||
|
"completedAt": "2026-04-17",
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "master",
|
||||||
|
"worktree_path": null,
|
||||||
|
"current_phase": 0,
|
||||||
|
"next_action": [
|
||||||
|
{
|
||||||
|
"phase": 1,
|
||||||
|
"action": "brainstorm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 2,
|
||||||
|
"action": "research"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 3,
|
||||||
|
"action": "implement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 4,
|
||||||
|
"action": "check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 5,
|
||||||
|
"action": "update-spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phase": 6,
|
||||||
|
"action": "record-session"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [],
|
||||||
|
"notes": "",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<!-- @@@auto:current-status -->
|
<!-- @@@auto:current-status -->
|
||||||
- **Active File**: `journal-1.md`
|
- **Active File**: `journal-1.md`
|
||||||
- **Total Sessions**: 4
|
- **Total Sessions**: 5
|
||||||
- **Last Active**: 2026-04-17
|
- **Last Active**: 2026-04-17
|
||||||
<!-- @@@/auto:current-status -->
|
<!-- @@@/auto:current-status -->
|
||||||
|
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<!-- @@@auto:active-documents -->
|
<!-- @@@auto:active-documents -->
|
||||||
| File | Lines | Status |
|
| File | Lines | Status |
|
||||||
|------|-------|--------|
|
|------|-------|--------|
|
||||||
| `journal-1.md` | ~179 | Active |
|
| `journal-1.md` | ~216 | Active |
|
||||||
<!-- @@@/auto:active-documents -->
|
<!-- @@@/auto:active-documents -->
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -29,6 +29,7 @@
|
|||||||
<!-- @@@auto:session-history -->
|
<!-- @@@auto:session-history -->
|
||||||
| # | Date | Title | Commits | Branch |
|
| # | Date | Title | Commits | Branch |
|
||||||
|---|------|-------|---------|--------|
|
|---|------|-------|---------|--------|
|
||||||
|
| 5 | 2026-04-17 | Fix sync command panic | `887eb14` | `master` |
|
||||||
| 4 | 2026-04-17 | Review MVP completion status | - | `master` |
|
| 4 | 2026-04-17 | Review MVP completion status | - | `master` |
|
||||||
| 3 | 2026-04-17 | Support disabling providers in olpx | HEAD | `master` |
|
| 3 | 2026-04-17 | Support disabling providers in olpx | HEAD | `master` |
|
||||||
| 2 | 2026-04-17 | Build OPS MVP failover proxy | `2b04d91` | `master` |
|
| 2 | 2026-04-17 | Build OPS MVP failover proxy | `2b04d91` | `master` |
|
||||||
|
|||||||
@ -177,3 +177,40 @@ Reviewed current implementation against the archived MVP PRD and classified impl
|
|||||||
### Next Steps
|
### Next Steps
|
||||||
|
|
||||||
- None - task complete
|
- None - task complete
|
||||||
|
|
||||||
|
|
||||||
|
## Session 5: Fix sync command panic
|
||||||
|
|
||||||
|
**Date**: 2026-04-17
|
||||||
|
**Task**: Fix sync command panic
|
||||||
|
**Branch**: `master`
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
Fixed a panic in opencode sync when preserved model metadata contains slices, and added package plus CLI regression coverage.
|
||||||
|
|
||||||
|
### Main Changes
|
||||||
|
|
||||||
|
- Root cause: `internal/opencode/opencode.go` compared `interface{}` values directly inside `mapsEqualShallow`, which panicked when preserved `provider.olpx.models.<alias>` metadata included slices.
|
||||||
|
- Fix: replaced the unsafe hand-rolled comparison with `reflect.DeepEqual` so existing model metadata with nested maps/slices can be compared safely during `sync`.
|
||||||
|
- Added regression tests in `internal/opencode/opencode_test.go` and `internal/cli/cli_test.go` covering preserved slice metadata and a real `opencode sync --target` no-op path.
|
||||||
|
- Verification: ran `rtk go test ./internal/opencode`, `rtk go test ./internal/cli ./internal/opencode`, and `rtk go test ./...` successfully.
|
||||||
|
|
||||||
|
|
||||||
|
### Git Commits
|
||||||
|
|
||||||
|
| Hash | Message |
|
||||||
|
|------|---------|
|
||||||
|
| `887eb14` | (see git log) |
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
- [OK] (Add test results)
|
||||||
|
|
||||||
|
### Status
|
||||||
|
|
||||||
|
[OK] **Completed**
|
||||||
|
|
||||||
|
### Next Steps
|
||||||
|
|
||||||
|
- None - task complete
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user