Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 170 additions & 57 deletions BUILD_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,198 @@

## sprint objective

Implement Sprint 6C: stabilize the `apps/web` workspace so lint and build are clean, repeatable, non-interactive verification steps while preserving the shipped Sprint 6A and Sprint 6B shell routes and workflow behavior.
Implement Sprint 6D by exposing deterministic user-scoped read-only trace review APIs for:

- `GET /v0/traces`
- `GET /v0/traces/{trace_id}`
- `GET /v0/traces/{trace_id}/events`

The sprint stayed limited to explain-why trace reads over existing persisted `traces` and `trace_events` data.

## completed work

- committed a stable ESLint setup in `apps/web` and switched the web lint script to `eslint . --max-warnings=0` so `npm run lint` no longer invokes interactive `next lint` setup
- intentionally adopted the Next-generated TypeScript config updates in `apps/web/tsconfig.json`
- added `esModuleInterop: true`
- added the `next` TypeScript plugin
- added `.next/types/**/*.ts` to `include`
- intentionally adopted the framework-managed `apps/web/next-env.d.ts` header text produced by Next.js
- made one behavior-preserving component change in `apps/web/components/approval-actions.tsx` to satisfy the committed hook lint rule without changing approval UI flow
- verified that `npm run build` no longer changes the contents of `apps/web/tsconfig.json` or `apps/web/next-env.d.ts` after those adopted config updates were in place
- introduced stable trace review contracts in `apps/api/src/alicebot_api/contracts.py`
- `TraceReviewSummaryRecord`
- `TraceReviewRecord`
- `TraceReviewListSummary`
- `TraceReviewListResponse`
- `TraceReviewDetailResponse`
- `TraceReviewEventRecord`
- `TraceReviewEventListSummary`
- `TraceReviewEventListResponse`
- `TRACE_REVIEW_LIST_ORDER`
- `TRACE_REVIEW_EVENT_LIST_ORDER`
- added a narrow trace review module in `apps/api/src/alicebot_api/traces.py`
- `list_trace_records()`
- `get_trace_record()`
- `list_trace_event_records()`
- `TraceNotFoundError`
- extended `apps/api/src/alicebot_api/store.py` with read-only trace review queries
- `list_trace_reviews()`
- `get_trace_review_optional()`
- deterministic list SQL with trace-event counts
- deterministic trace-event SQL ordering
- added FastAPI endpoints in `apps/api/src/alicebot_api/main.py`
- `GET /v0/traces`
- `GET /v0/traces/{trace_id}`
- `GET /v0/traces/{trace_id}/events`
- added unit coverage in `tests/unit/test_traces.py` for
- deterministic list ordering
- stable detail shape
- stable event-list shape
- invisible-trace not-found behavior
- endpoint translation and 404 mapping
- added Postgres-backed integration coverage in `tests/integration/test_traces_api.py` for
- deterministic trace list ordering
- trace detail reads
- ordered trace-event reads
- cross-user isolation
- invisible-trace 404 behavior

## incomplete work

- no backend endpoint, schema, or contract changes
- no new routes or workflow features
- no shell redesign or adjacent UI expansion
- no Gmail, Calendar, auth, runner, or connector scope expansion
- no additional frontend tests beyond the existing narrow verification set
- none inside the sprint’s scoped backend deliverables
- no UI migration from fixture-backed `/traces`
- no trace creation or mutation changes
- no filtering, search, or expanded explainability surface beyond the three read endpoints

## files changed

- `apps/api/src/alicebot_api/contracts.py`
- `apps/api/src/alicebot_api/main.py`
- `apps/api/src/alicebot_api/store.py`
- `apps/api/src/alicebot_api/traces.py`
- `tests/unit/test_traces.py`
- `tests/integration/test_traces_api.py`
- `BUILD_REPORT.md`
- `apps/web/package.json`
- `apps/web/eslint.config.mjs`
- `apps/web/tsconfig.json`
- `apps/web/next-env.d.ts`
- `apps/web/components/approval-actions.tsx`

## exact ordering rules

- trace list reads use `created_at DESC, id DESC`
- trace-event reads use `sequence_no ASC, id ASC`

## tests run

- `npm run lint` in `apps/web`
- `./.venv/bin/python -m pytest tests/unit/test_traces.py`
- PASS
- non-interactive after the committed ESLint config and script change
- `npm test` in `apps/web`
- `5` tests passed
- `./.venv/bin/python -m pytest tests/integration/test_traces_api.py`
- initial sandboxed run could not reach local Postgres on `localhost:5432`
- rerun as part of the full integration suite below passed
- `./.venv/bin/python -m pytest tests/unit`
- PASS
- `2` test files, `5` tests passed
- `npm run build` in `apps/web`
- `451` tests passed
- `./.venv/bin/python -m pytest tests/integration`
- PASS
- generated shipped routes remained intact: `/`, `/chat`, `/approvals`, `/tasks`, `/traces`

## exact verification results

- lint command used: `npm run lint`
- test command used: `npm test`
- build command used: `npm run build`
- TypeScript or Next-generated config changes intentionally adopted: yes
- `apps/web/tsconfig.json`
- `apps/web/next-env.d.ts`
- build stability check:
- `shasum apps/web/tsconfig.json apps/web/next-env.d.ts` was unchanged before vs. after `npm run build`
- pre-build checksum:
- `23632802ddf6784e5989d71338904efe50848844 apps/web/tsconfig.json`
- `f75a118439f630e5ca41d376cedef8db9b6d7fc6 apps/web/next-env.d.ts`
- post-build checksum:
- `23632802ddf6784e5989d71338904efe50848844 apps/web/tsconfig.json`
- `f75a118439f630e5ca41d376cedef8db9b6d7fc6 apps/web/next-env.d.ts`

## route and behavior confirmation

- route generation from `next build` still includes `/`, `/chat`, `/approvals`, `/tasks`, and `/traces`
- Sprint 6A and 6B governed request, approval, and task behavior remained intact
- no workflow logic or API contract changes were introduced; the only non-config code change was the `approval-actions` hook dependency cleanup required by lint
- `143` tests passed

## unit and integration test results

- unit result: PASS
- trace review module coverage and endpoint translation coverage passed
- integration result: PASS
- live Postgres-backed trace review list/detail/event and isolation coverage passed

## example trace list response

```json
{
"items": [
{
"id": "00000000-0000-4000-8000-000000000002",
"thread_id": "11111111-1111-4111-8111-111111111111",
"kind": "tool.proxy.execute",
"compiler_version": "response_generation_v0",
"status": "completed",
"created_at": "2026-03-17T09:00:00+00:00",
"trace_event_count": 2
},
{
"id": "00000000-0000-4000-8000-000000000001",
"thread_id": "11111111-1111-4111-8111-111111111111",
"kind": "context.compile",
"compiler_version": "continuity_v0",
"status": "completed",
"created_at": "2026-03-17T09:00:00+00:00",
"trace_event_count": 1
}
],
"summary": {
"total_count": 2,
"order": ["created_at_desc", "id_desc"]
}
}
```

## example trace detail response

```json
{
"trace": {
"id": "00000000-0000-4000-8000-000000000002",
"thread_id": "11111111-1111-4111-8111-111111111111",
"kind": "tool.proxy.execute",
"compiler_version": "response_generation_v0",
"status": "completed",
"limits": {
"max_sessions": 1,
"max_events": 2
},
"created_at": "2026-03-17T09:00:00+00:00",
"trace_event_count": 2
}
}
```

## example trace-event list response

```json
{
"items": [
{
"id": "10000000-0000-4000-8000-000000000002",
"trace_id": "00000000-0000-4000-8000-000000000002",
"sequence_no": 1,
"kind": "tool.proxy.execute.request",
"payload": {
"approval_id": "approval-2"
},
"created_at": "2026-03-17T09:00:00+00:00"
},
{
"id": "10000000-0000-4000-8000-000000000001",
"trace_id": "00000000-0000-4000-8000-000000000002",
"sequence_no": 2,
"kind": "tool.proxy.execute.summary",
"payload": {
"approval_id": "approval-2"
},
"created_at": "2026-03-17T09:00:00+00:00"
}
],
"summary": {
"trace_id": "00000000-0000-4000-8000-000000000002",
"total_count": 2,
"order": ["sequence_no_asc", "id_asc"]
}
}
```

## blockers/issues

- no active blockers after the repair
- initial pre-fix issue reproduced exactly as described in the sprint packet:
- `npm run lint` prompted for ESLint initialization because the workspace had no committed lint config
- `next build` rewrote `apps/web/tsconfig.json` and `apps/web/next-env.d.ts` until those framework-required changes were intentionally adopted
- no remaining product-scope blockers
- one execution-time environment issue occurred during verification
- sandboxed integration setup could not connect to local Postgres on `localhost:5432`
- rerunning the required integration suite with local database access resolved verification

## recommended next step

Run review against this repair sprint and, if it passes, treat the committed ESLint config plus adopted Next TypeScript settings as the new stable baseline for future `apps/web` UI work.
Hook the existing `/traces` web surface off these live endpoints in a separate sprint, while preserving the same narrow persisted-data-only contract.

## intentionally deferred after this sprint

- any new product workflow surface beyond the existing `/`, `/chat`, `/approvals`, `/tasks`, and `/traces` routes
- any backend work
- any visual redesign
- any additional test expansion beyond narrow preservation coverage
- any UI changes
- any trace mutation endpoints
- any new trace production behavior
- any connector, Gmail, Calendar, approval-flow, or execution-scope expansion
- any search, filtering, pagination, or explainability enrichment beyond persisted trace and trace-event reads
45 changes: 25 additions & 20 deletions REVIEW_REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,49 @@ PASS

## criteria met

- `apps/web/eslint.config.mjs` is now tracked in git, so the non-interactive lint setup is part of the sprint change set.
- `npm run lint` in `apps/web` runs non-interactively and passes with `eslint . --max-warnings=0`.
- `npm test` in `apps/web` passes: `2` test files, `5` tests passed.
- `npm run build` in `apps/web` passes.
- The build output includes the shipped routes `/`, `/chat`, `/approvals`, `/tasks`, and `/traces`.
- `apps/web/tsconfig.json` and `apps/web/next-env.d.ts` remain byte-stable before and after `npm run build`; the `shasum` values were unchanged.
- The implementation stayed inside the repair sprint scope: no backend endpoint, schema, auth, Gmail, Calendar, runner, or product-scope expansion was introduced.
- The only behavior code change remains the narrow `approval-actions` hook dependency cleanup, and the existing approval flow coverage still passes.
- `BUILD_REPORT.md` now matches the current tracked repair: committed ESLint config, adopted Next TypeScript config normalization, exact verification commands, and explicit deferred scope.
- `GET /v0/traces`, `GET /v0/traces/{trace_id}`, and `GET /v0/traces/{trace_id}/events` are implemented in `apps/api/src/alicebot_api/main.py`.
- The sprint stayed limited to read-only trace review over existing persisted `traces` and `trace_events` data.
- Stable trace review contracts were added in `apps/api/src/alicebot_api/contracts.py`.
- The review seam in `apps/api/src/alicebot_api/traces.py` returns deterministic list, detail, and event payloads.
- Deterministic ordering is explicit and test-backed:
- trace list: `created_at DESC, id DESC`
- trace events: `sequence_no ASC, id ASC`
- User isolation is preserved through user-scoped connections plus existing row-level security behavior, and invisible traces return `404`.
- Unit coverage was added for ordering, response shape, endpoint mapping, and invisible-trace handling.
- Integration coverage was added for list/detail/event reads, cross-user isolation, and invisible-trace `404` behavior.
- Acceptance verification passed:
- `./.venv/bin/python -m pytest tests/unit` -> `451 passed`
- `./.venv/bin/python -m pytest tests/integration` -> `143 passed`

## criteria missed

- None.
- none

## quality issues

- No blocking quality issues found in the current sprint change set.
- Coverage remains intentionally narrow, but it is adequate for this repair sprint because the functional code change is minimal and behavior-preserving.
- none blocking
- No sloppy scope expansion was found. The diff is confined to the intended API/store/contracts/test surface plus `BUILD_REPORT.md`.

## regression risks

- Low.
- Residual risk is mostly future UI drift outside this sprint, not the stabilization change itself. Current automated coverage still does not provide route-level smoke tests across all shipped pages.
- Low risk overall. The new seam is narrow and read-only.
- The main ongoing dependency is correct use of `user_connection()` so row-level security remains active for trace visibility. Current unit and integration coverage exercises that path.

## docs issues

- No blocking docs issues found.
- No `ARCHITECTURE.md` update is needed for this repair sprint.
- none blocking
- `BUILD_REPORT.md` matches the sprint packet requirements, including contracts, ordering rules, commands run, example responses, and deferred scope.

## should anything be added to RULES.md?

- No required change.
- Optional future rule: frontend workspaces should commit a repo-owned non-interactive lint configuration before `lint` is treated as a standard verification gate.
- no

## should anything update ARCHITECTURE.md?

- No. This sprint stayed in tooling/workspace stabilization and did not reveal an architecture contradiction.
- no required update for sprint acceptance
- Optional future update: document the new read-only trace review API surface when the `/traces` UI switches from fixtures to live backend reads.

## recommended next action

- Accept Sprint 6C and treat the tracked ESLint config plus adopted Next TypeScript settings as the new stable baseline for future `apps/web` work.
- Accept the sprint.
- In a follow-up sprint, replace the fixture-backed `/traces` UI with these live endpoints without widening the backend contract.
50 changes: 50 additions & 0 deletions apps/api/src/alicebot_api/contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@
RESPONSE_GENERATION_VERSION_V0 = "response_generation_v0"
TRACE_KIND_CONTEXT_COMPILE = "context.compile"
TRACE_KIND_RESPONSE_GENERATE = "response.generate"
TRACE_REVIEW_LIST_ORDER = ["created_at_desc", "id_desc"]
TRACE_REVIEW_EVENT_LIST_ORDER = ["sequence_no_asc", "id_asc"]
MEMORY_REVIEW_ORDER = ["updated_at_desc", "created_at_desc", "id_desc"]
MEMORY_REVIEW_QUEUE_ORDER = ["updated_at_desc", "created_at_desc", "id_desc"]
MEMORY_REVISION_REVIEW_ORDER = ["sequence_no_asc"]
Expand Down Expand Up @@ -314,6 +316,54 @@ class TraceEventRecord:
payload: JsonObject


class TraceReviewSummaryRecord(TypedDict):
id: str
thread_id: str
kind: str
compiler_version: str
status: str
created_at: str
trace_event_count: int


class TraceReviewRecord(TraceReviewSummaryRecord):
limits: JsonObject


class TraceReviewListSummary(TypedDict):
total_count: int
order: list[str]


class TraceReviewListResponse(TypedDict):
items: list[TraceReviewSummaryRecord]
summary: TraceReviewListSummary


class TraceReviewDetailResponse(TypedDict):
trace: TraceReviewRecord


class TraceReviewEventRecord(TypedDict):
id: str
trace_id: str
sequence_no: int
kind: str
payload: JsonObject
created_at: str


class TraceReviewEventListSummary(TypedDict):
trace_id: str
total_count: int
order: list[str]


class TraceReviewEventListResponse(TypedDict):
items: list[TraceReviewEventRecord]
summary: TraceReviewEventListSummary


@dataclass(frozen=True, slots=True)
class CompilerDecision:
kind: DecisionKind
Expand Down
Loading