140 lines
6.9 KiB
Markdown
140 lines
6.9 KiB
Markdown
# stackchain-dashboard
|
|
|
|
Live AI-driven adaptive UI for the Stackchain AI Lab Gitea experience.
|
|
|
|
## Local quickstart
|
|
|
|
Python 3.11 or newer is recommended. Create an isolated environment and install
|
|
the pinned dependencies:
|
|
|
|
```bash
|
|
python3 -m venv .venv
|
|
source .venv/bin/activate
|
|
python3 -m pip install -r requirements.txt
|
|
```
|
|
|
|
Point the dashboard at the Gitea server root (without `/api/v1`) and provide a
|
|
token that can read dashboard data, update the authenticated user's notification
|
|
threads, create and self-assign issues, discover, claim, and release issue assignments,
|
|
list repository labels and open milestones, set or clear due dates on assigned issues, create issue comments, close assigned issues,
|
|
inspect/comment on assigned pull
|
|
requests, merge assigned pull requests, and submit pull-request reviews.
|
|
Pull-request replies and mobile My Work issue and PR comments use Gitea's
|
|
issue-comment API; mobile issue capture requires issue
|
|
creation and assignment permission. The New issue sheet can optionally select an open
|
|
repository milestone and due date; the dashboard validates both and sends them with
|
|
self-assignment in the single create request, so planned work appears in its release
|
|
lane immediately. Issue capture and authored mobile actions (issue
|
|
comments, pull-request comments, notification replies, and reviews) persist per-draft
|
|
idempotency keys, so retrying after a timeout, reload, process restart, or handoff to
|
|
another worker replays a confirmed result instead of posting duplicate content. Results
|
|
are coordinated through a bounded SQLite ledger. Set `STACKCHAIN_STATE_DIR` to a
|
|
persistent, writable service directory (or set `STACKCHAIN_IDEMPOTENCY_DB` to an explicit
|
|
SQLite path); the local default is `.stackchain-state/idempotency.sqlite3`. Direct API callers should preserve the `Idempotency-Key`
|
|
header with the unchanged route and payload until a `201` response is confirmed. Closing an assigned issue, native Comment,
|
|
Approve, and Request changes reviews, and assigned-PR merge require repository
|
|
write permission. Native Comment, Approve, and Request changes reviews support
|
|
head-scoped draft comments anchored to changed lines; the dashboard validates each
|
|
comment path and submits the summary, decision, and inline comments in one review
|
|
request. The dashboard rechecks the current pull-request head, CI success, draft
|
|
state, and mergeability immediately before every merge.
|
|
Serve the dashboard
|
|
only to trusted users on its own origin; cross-origin API
|
|
access is intentionally disabled. Then start the API and bundled frontend:
|
|
|
|
```bash
|
|
export GITEA_URL='https://forge.example.com'
|
|
export GITEA_TOKEN='<read-notification-and-issue-write-token>'
|
|
uvicorn src.main:app --host 127.0.0.1 --port 8000
|
|
```
|
|
|
|
Open `http://127.0.0.1:8000/` for the dashboard. To verify the backend and its
|
|
Gitea connection directly, request
|
|
`http://127.0.0.1:8000/api/v1/context`; a successful response is JSON containing
|
|
`user`, `repos`, `issues`, and `pull_requests`. Press `Ctrl/Cmd+K` in the dashboard
|
|
to search commands plus issues and pull requests across every repository visible to
|
|
the configured Gitea token. Remote search starts after two characters, is debounced,
|
|
and keeps local commands usable if Gitea search is unavailable. Selecting a remote
|
|
result opens a mobile-safe, read-only preview without discarding the search query;
|
|
open unassigned issues can be claimed in place and handed into My Work after Gitea
|
|
confirms the assignment. Closed work and pull requests remain read-only with a safe
|
|
canonical Gitea link. The bounded APIs are available at
|
|
`GET /api/v1/search?q=<query>&limit=<1-25>` and
|
|
`GET /api/v1/repos/<owner>/<repo>/issues/<number>/preview?kind=issue|pull`. Never commit the token
|
|
or place it in a tracked configuration file.
|
|
|
|
For service monitoring, GET `/healthz` is a liveness check that confirms the
|
|
API process is running and does not contact Gitea. GET `/readyz` is the
|
|
readiness check: it validates the configured Gitea credentials and returns
|
|
HTTP 503 with an error when Gitea is unavailable or authentication fails.
|
|
|
|
## Offline mobile shell
|
|
|
|
After one successful online load, the installed dashboard precaches a versioned,
|
|
subpath-scoped application shell. During a network outage or a dashboard HTTP
|
|
`500`, `502`, `503`, or `504` response, navigation falls back to that shell when
|
|
it is available so local issue and review drafts remain reachable. Authentication
|
|
and other client-error responses are never hidden. A visible, accessible offline
|
|
or server-outage notice distinguishes cached mode from live Gitea data, and the
|
|
dashboard keeps polling until it can restore its live snapshot automatically.
|
|
|
|
Users can explicitly enable **Keep My Work available offline**. Each healthy live
|
|
refresh then stores a seven-day, versioned snapshot containing only the signed-in
|
|
user identity and queue-card metadata for issues, pull requests, unread updates,
|
|
and pagination totals. Bodies, comments, diffs, credentials, repository catalogs,
|
|
events, and complete API responses are excluded. A cold offline launch labels the
|
|
saved time and renders this snapshot read-only; opening live details, pagination,
|
|
and server mutations remain disabled until reconnection. **Clear offline work
|
|
data** deletes the snapshot, and opting out deletes it automatically.
|
|
|
|
API responses and mutations are never cached by the service worker or queued;
|
|
submissions still require connectivity. Service-worker upgrades are atomic and
|
|
remove only older `stackchain-dashboard-*` caches, preserving unrelated caches on
|
|
the same origin.
|
|
|
|
Run the test suite with:
|
|
|
|
```bash
|
|
python3 -m pytest tests/ -q
|
|
```
|
|
|
|
## Autonomous release worker
|
|
|
|
The deterministic issue-to-release engine lives at `src/release_engine.py`.
|
|
It discovers or targets one Gitea issue, verifies its claim, creates an issue
|
|
branch, invokes a configured coding agent, runs tests, pushes, and opens a
|
|
linked pull request. Merge remains gated by CI/review; the existing release
|
|
workflow drafts the release candidate after merge.
|
|
|
|
Plan against live Gitea without mutating anything:
|
|
|
|
```bash
|
|
python3 -m src.release_engine \
|
|
--repo stackchain/stackchain-dashboard \
|
|
--agent timmy \
|
|
--issue 14 \
|
|
--dry-run
|
|
```
|
|
|
|
Execute one ticket after implementing and committing its change directly on
|
|
the deterministic branch printed by `--dry-run`:
|
|
|
|
```bash
|
|
export GITEA_TOKEN='<scoped-token>'
|
|
export RELEASE_AGENT_COMMAND=true
|
|
python3 -m src.release_engine \
|
|
--repo stackchain/stackchain-dashboard \
|
|
--agent timmy \
|
|
--issue 19 \
|
|
--test-command 'python3 -m pytest tests/ -q'
|
|
```
|
|
|
|
`GITEA_TOKEN` needs issue and repository write scopes. The engine verifies the
|
|
claim, reruns the test command, pushes the branch, and opens a PR containing
|
|
`Closes #19` plus test evidence. Replace `19` with the selected issue number;
|
|
do not run without `--issue` when processing a preselected ticket.
|
|
|
|
Durable state defaults to `.release-engine/state.json`. Full behavior and
|
|
safety gates are documented in
|
|
[`docs/release-engine-spec.md`](docs/release-engine-spec.md).
|