# Projects & items

## Projects

A project is the unit of configuration in LoopDesk. Every item belongs to exactly one project, and every project carries its own:

* **Routing thresholds** — `auto_threshold`, `review_threshold`
* **Flag rules** — `hard_block_flags`, `escalate_flags`, `force_review_flags`
* **Reviewer pool** — which users can pick up items from this project
* **Guidelines** — reviewer-facing rules
* **Webhooks** — where decisions are POSTed
* **API keys** — credentials for the public submission API
* **SLA** — `max_queue_age_minutes` before auto-escalation

Two AI use cases should be two projects unless their policy and reviewer pool are literally identical.

### Lifecycle

1. **Create** — from `/projects`, name it, set thresholds (defaults are fine to start)
2. **Generate API key** — copy and store; visible once
3. **Configure webhook** — URL and secret
4. **Write guidelines** — one paragraph per rule, plain English
5. **Add reviewers** — assign users to the pool
6. **Pipe traffic** — your pipeline starts submitting items
7. **Tune** — after a few hundred items, revisit thresholds (see [Tuning thresholds](/hitl-docs/guides/tuning-thresholds.md))

## Items

An item is a single AI decision. Once submitted, an item is routed and either auto-approved, queued, escalated, or hard-rejected.

### Schema (simplified)

| Field         | Type          | Notes                                                                                        |
| ------------- | ------------- | -------------------------------------------------------------------------------------------- |
| `id`          | uuid          | PK                                                                                           |
| `project_id`  | uuid          | FK → projects                                                                                |
| `input`       | jsonb         | Original request payload                                                                     |
| `suggestion`  | text or jsonb | AI's proposed answer                                                                         |
| `confidence`  | float         | 0–1, supplied by caller                                                                      |
| `risk_flags`  | text\[]       | Supplied by caller                                                                           |
| `metadata`    | jsonb         | Caller-supplied, does not affect routing                                                     |
| `status`      | enum          | `auto_approved`, `queued`, `claimed`, `escalated`, `approved`, `rejected`, `escalated_final` |
| `assignee_id` | uuid          | Reviewer (optional)                                                                          |
| `decision`    | jsonb         | Final answer (may differ from suggestion)                                                    |
| `reviewer_id` | uuid          | Who decided                                                                                  |
| `decided_at`  | timestamptz   | When                                                                                         |
| `created_at`  | timestamptz   | Submission time                                                                              |

### Status transitions

```
                  ┌──► auto_approved ──► approved (terminal)
submitted ─► routed ┼──► rejected (policy, terminal)
                  ├──► queued ──► claimed ──► approved / rejected (terminal)
                  └──► escalated ──► claimed (by senior) ──► escalated_final / approved / rejected (terminal)
```

`approved`, `rejected`, and `escalated_final` are terminal states. They trigger the outbound webhook and never change.

### Immutability

Decided items are immutable. If a decision turns out to be wrong, log a new corrective action upstream — do not edit the historical record. The audit trail is more valuable than the convenience.

## Programmatic management

Most project operations are exposed as server functions (`src/lib/*.functions.ts`) and admin-only UI. Items are typically created via the public API, never the dashboard.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hitl-01.gitbook.io/hitl-docs/features/projects.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
