# Continuity ledger (per-branch)

## Human intent (must not be overwritten)

- Implement the missing public API needed for `@giselles-ai/sdk` `runAndWait`, so server-side integrations can run an App and wait for completion via polling.

## Goal (incl. success criteria)

- Add a public status/results endpoint that the SDK can poll after `POST /api/apps/{appId}/run`.
- Implement SDK `runAndWait()` to poll until the task reaches a terminal status, then return final data.

## Constraints/Assumptions

- Keep the public API minimal and scoped to a single App (avoid cross-app task access).
- Do not try to match Studio UI task page data shape; only reuse the polling mechanism.

## Key decisions

- Implement `GET /api/apps/{appId}/tasks/{taskId}` with optional `?includeGenerations=1` for the final fetch.
- SDK polls status-only until terminal, then does one final `includeGenerations=1` fetch.

## State

- `POST /api/apps/{appId}/run` already exists and returns `{ taskId }`.
- Task JSON is stored in Giselle Storage and can be loaded via `giselle.getTask({ taskId })`.

## Done

- Added `steps` + `outputs` to Studio public task result response on the final fetch (`GET /api/apps/{appId}/tasks/{taskId}?includeGenerations=1`), derived the same way as Studio task UI (sequences → step items; `nodeIdsConnectedToEnd` → outputs).
- Kept status-only polling cheap: `GET /api/apps/{appId}/tasks/{taskId}` still returns `{ task }` when `includeGenerations` is off.
- Updated `@giselles-ai/sdk` to parse/return the new `{ steps, outputs }` fields and updated tests/README.
- Fixed SDK task response parsing to require `task.status` for the final `includeGenerations=1` response and updated SDK tests to match the real API shape.
  - Parser now identifies the final result by the presence of `steps` + `outputs` (and validates `status` in both branches).
- Fixed SDK `#getTask()` error messages to correctly reference the Tasks API endpoint (not “Runs API”).
- Fixed SDK `#runApp()` error messages to correctly reference the Runs API endpoint (not “Tasks API”).

## Now

- Adjusting the public task results response shape: omit `generationsById` and return `task` as a plain spread object (`task: { ...task }`).

## Next

- None.

## Open questions (UNCONFIRMED if needed)

- None.

## Working set (files/ids/commands)

- `apps/studio.giselles.ai/app/api/apps/[appId]/tasks/[taskId]/route.ts`
- `packages/sdk/src/sdk.ts`
- `packages/sdk/src/sdk.test.ts`
- `packages/sdk/src/errors.ts`
- `packages/sdk/README.md`
- `pnpm -F @giselles-ai/sdk test`
- `pnpm -F @giselles-ai/sdk format`

