hanoman 0.1.16 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +102 -8
- package/dist/server.js +719 -96
- package/docs/agent-integration.md +45 -2
- package/package.json +1 -1
- package/prisma/migrations/20260803000000_spec_done_at/migration.sql +16 -0
- package/prisma/migrations/20260803001000_changelog/migration.sql +21 -0
- package/prisma/schema.prisma +31 -1
- package/web/assets/{index-GQaOZTKC.js → index-BJTj--gG.js} +1546 -1546
- package/web/index.html +1 -1
|
@@ -168,12 +168,53 @@ dan tak memakai agent token.
|
|
|
168
168
|
| `GET /api/specs/:id/review` | `backlog:read` | diff hasil kerja sesi. |
|
|
169
169
|
| `GET /api/projects/:id/docs` | `docs:read` | index Source of Truth project. |
|
|
170
170
|
| `GET /api/projects/:id/docs/<path>` | `docs:read` | isi satu dokumen. |
|
|
171
|
+
| `GET /api/projects/:id/changelog` | `docs:read` | changelog yang sudah dibangkitkan (paginated). |
|
|
172
|
+
| `POST /api/projects/:id/changelog` | `docs:write` | bangkitkan changelog baru — bentuknya di **§6a**. |
|
|
171
173
|
| `GET /api/terminal/sessions` | `sessions:read` | sesi yang sedang hidup. |
|
|
172
|
-
| `GET /api/notifications` | `notifications:read` | notifikasi. |
|
|
174
|
+
| `GET /api/notifications` | `notifications:read` | notifikasi. **Tanpa `limit` → 50 teratas**, bukan seluruhnya (lihat jebakan di §10). |
|
|
173
175
|
| `GET /api/tickets` | `support:read` | tiket Help Center. |
|
|
174
|
-
| `GET /api/lead/decisions` | `lead:read` | jejak keputusan hanoman-lead. |
|
|
176
|
+
| `GET /api/lead/decisions` | `lead:read` | jejak keputusan hanoman-lead. Menerima `page`/`limit`; `take`/`skip` lama tetap jalan. |
|
|
177
|
+
| `GET /api/scheduler/queue` | `settings:read` | antrean scheduler (`?status=queued\|launched\|done\|failed`). `GET /api/scheduler/state` **tak lagi** memuat `queue` — ia memuat `queueCounts`. |
|
|
175
178
|
| `POST /api/lead/decisions` | `lead:write` | minta putusan — baca **§8** dan **§11** dulu. |
|
|
176
179
|
|
|
180
|
+
## 6a. Changelog per project
|
|
181
|
+
|
|
182
|
+
Ringkasan perubahan **berorientasi pemakai** — bukan daftar commit. Tiga mode, satu endpoint;
|
|
183
|
+
`mode` menentukan field lainnya:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# 1) backlog yang selesai di rentang tanggal (dua field opsional → 30 hari terakhir)
|
|
187
|
+
curl -sS -X POST "$HANOMAN_HOST/api/projects/<id>/changelog" \
|
|
188
|
+
-H "Authorization: Bearer $HANOMAN_AGENT_TOKEN" -H 'Content-Type: application/json' \
|
|
189
|
+
-d '{"mode":"backlog","from":"2026-07-01","to":"2026-07-31"}'
|
|
190
|
+
|
|
191
|
+
# 2) rentang commit di repo project
|
|
192
|
+
-d '{"mode":"commit","fromSha":"4f2a1c9","toSha":"HEAD"}'
|
|
193
|
+
|
|
194
|
+
# 3) versi/tag rilis (fromTag opsional → sejak versi sebelumnya)
|
|
195
|
+
-d '{"mode":"version","toTag":"v1.2.0"}'
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Jawaban **201** berisi `body` (markdown siap pakai), `title`, `itemCount`, `generator`, dan
|
|
199
|
+
`warning`. Ambil ulang atau unduh kapan saja:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
curl -sS "$HANOMAN_HOST/api/projects/<id>/changelog/<cid>?download=md" \
|
|
203
|
+
-H "Authorization: Bearer $HANOMAN_AGENT_TOKEN"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Tiga hal yang perlu kamu tahu sebelum memanggilnya:
|
|
207
|
+
|
|
208
|
+
- **Panggil `GET /api/projects/:id/changelog/sources` dulu.** Ia memberi tag yang tersedia, HEAD
|
|
209
|
+
singkat, rentang default, dan — bila repo belum ditautkan di mesin itu atau belum punya tag — satu
|
|
210
|
+
`reason` yang menjelaskan sebabnya. Ia menjawab **200**, bukan galat, jadi jangan perlakukan
|
|
211
|
+
`reason` sebagai kegagalan.
|
|
212
|
+
- **422 berarti permintaanmu sah tapi tak ada isinya** (rentang kosong, repo tanpa tag, revisi tak
|
|
213
|
+
dikenal) — pesannya bisa langsung diteruskan ke manusia. **400** berarti bentuknya salah
|
|
214
|
+
(mis. `from` lebih baru dari `to`).
|
|
215
|
+
- **`generator:"fallback"` bukan kegagalan.** Artinya narasi otomatis tak tersedia dan yang kamu
|
|
216
|
+
terima adalah draf ringkas deterministik; alasannya ada di `warning`.
|
|
217
|
+
|
|
177
218
|
## 7. `POST /api/specs` — bentuk payload per `source`
|
|
178
219
|
|
|
179
220
|
`source` dan bentuk `payload` **saling mengikat**. Salah pasang → **400**
|
|
@@ -243,6 +284,8 @@ memanggilnya; jangan lakukan tanpa manusia.
|
|
|
243
284
|
| **`GET /api/specs/:id` tidak ada** | `GET /api/specs?q=SPEC-489` lalu cocokkan `id` **persis** — `q` itu substring, jadi ia bisa mengembalikan lebih dari satu |
|
|
244
285
|
| daftar mengembalikan amplop `{ items, total, page, pageSize }` | jangan perlakukan responsnya sebagai array |
|
|
245
286
|
| tanpa `limit`, daftar mengembalikan **seluruh** item dalam satu halaman | kirim `limit` untuk backlog besar |
|
|
287
|
+
| **`GET /api/notifications` adalah pengecualiannya**: tanpa `limit` ia mengembalikan **50 teratas**, bukan seluruhnya — angka penuhnya ada di `total` | kirim `page`/`limit` bila kamu butuh riwayat lama; jangan simpulkan `items.length` = seluruh notifikasi |
|
|
288
|
+
| `GET /api/scheduler/state` **tidak lagi** memuat `queue` (SPEC-523/ADR-0107) | baca `queueCounts` untuk hitungan, `GET /api/scheduler/queue?status=…&page&limit` untuk barisnya |
|
|
246
289
|
| `PATCH /api/specs/:id` menolak edit konten begitu item pernah dimulai | ubah `title`/`payload` hanya selagi item belum punya sesi |
|
|
247
290
|
| `branchFrom` yang tak ada di repo project → **400**, bukan diterima lalu gagal di tengah sesi | ambil kandidatnya dari `GET /api/projects/:id/branches` |
|
|
248
291
|
| **401 telanjang** tak memisahkan "host salah" dari "token salah" dari "master switch mati" | probe `GET /api/health` sekali: 200 = host benar → masalahnya token atau master switch |
|
package/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-- SPEC-516 · ADR-0105 · stempel selesai backlog sebagai kolom.
|
|
2
|
+
--
|
|
3
|
+
-- Ditulis tangan (bukan `migrate dev`): worktree tetangga membuat `migrate dev` me-reset DB saat
|
|
4
|
+
-- ada drift. ADITIF murni — satu kolom NULLABLE tanpa default, tak ada tabel diredefinisi.
|
|
5
|
+
-- Larangan SQLite atas `ADD COLUMN … DEFAULT <non-konstan>` (lihat migration SPEC-408) tak
|
|
6
|
+
-- berlaku karena tak ada default sama sekali.
|
|
7
|
+
ALTER TABLE "Spec" ADD COLUMN "doneAt" DATETIME;
|
|
8
|
+
|
|
9
|
+
-- Backfill sekali-jalan dari stempel yang SUDAH ada: `Notification` ber-key `done:<specId>`
|
|
10
|
+
-- ditulis `recordCompletion` tepat pada transisi ke `done` sejak SPEC-180, di ketiga jalur
|
|
11
|
+
-- persist (dasar yang sama dipakai sweep auto-merge ADR-0103). Item yang selesai sebelum
|
|
12
|
+
-- SPEC-180 — atau yang notifikasinya dihapus operator — tetap NULL; itu keadaan sah yang
|
|
13
|
+
-- dilaporkan sebagai catatan di hasil changelog, bukan disamarkan.
|
|
14
|
+
UPDATE "Spec" SET "doneAt" = (
|
|
15
|
+
SELECT n."createdAt" FROM "Notification" n WHERE n."key" = 'done:' || "Spec"."id"
|
|
16
|
+
) WHERE "doneAt" IS NULL;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- SPEC-516 · ADR-0105 · changelog naratif per project.
|
|
2
|
+
--
|
|
3
|
+
-- Ditulis tangan (bukan `migrate dev`). ADITIF murni — satu tabel baru, nol tabel diredefinisi,
|
|
4
|
+
-- nol baris disentuh. TANPA kolom `version`: tabel ini LOCAL-only dan tak pernah masuk
|
|
5
|
+
-- changefeed sync, persis alasan `LeadFlow` & `WebhookEndpoint`.
|
|
6
|
+
CREATE TABLE "Changelog" (
|
|
7
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
8
|
+
"projectId" TEXT NOT NULL,
|
|
9
|
+
"mode" TEXT NOT NULL,
|
|
10
|
+
"title" TEXT NOT NULL,
|
|
11
|
+
"params" JSONB NOT NULL,
|
|
12
|
+
"body" TEXT NOT NULL,
|
|
13
|
+
"generator" TEXT NOT NULL,
|
|
14
|
+
"warning" TEXT,
|
|
15
|
+
"itemCount" INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
17
|
+
"updatedAt" DATETIME NOT NULL,
|
|
18
|
+
CONSTRAINT "Changelog_projectId_fkey" FOREIGN KEY ("projectId")
|
|
19
|
+
REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
20
|
+
);
|
|
21
|
+
CREATE INDEX "Changelog_projectId_createdAt_idx" ON "Changelog"("projectId", "createdAt");
|
package/prisma/schema.prisma
CHANGED
|
@@ -28,6 +28,7 @@ model Project {
|
|
|
28
28
|
tickets Ticket[]
|
|
29
29
|
customAgents CustomAgent[] // SPEC-450 · ADR-0094 · custom agent milik project ini
|
|
30
30
|
githubIssues GithubIssue[] // SPEC-471 · ADR-0095 · cermin issue repo GitHub project ini
|
|
31
|
+
changelogs Changelog[] // SPEC-516 · ADR-0105 · changelog tersimpan project ini
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
model Spec {
|
|
@@ -51,6 +52,12 @@ model Spec {
|
|
|
51
52
|
// sama dengan `baseSha` (services/session-launch.ts); jalur RESUME (ADR-0084) sengaja tidak
|
|
52
53
|
// menimpanya — melanjutkan sesi bukan "mulai lagi". null = belum pernah dikerjakan.
|
|
53
54
|
startedAt DateTime?
|
|
55
|
+
// SPEC-516 · ADR-0105 · kapan item PERTAMA kali masuk stage `done`. Ditulis HANYA di dalam
|
|
56
|
+
// `recordCompletion()` — satu-satunya fungsi yang sudah dipanggil oleh KETIGA jalur persist
|
|
57
|
+
// `done` (advanceStage, scheduler/reconcile, live-specs). Menyalin bookkeeping ini ke call
|
|
58
|
+
// site adalah kelas bug SPEC-431/448/475. Tulis-sekali: reopen lalu selesai lagi tak
|
|
59
|
+
// memindahkannya, cermin `startedAt` = mulai pertama (ADR-0090).
|
|
60
|
+
doneAt DateTime?
|
|
54
61
|
// SPEC-447 · ADR-0093 · id spec lain yang harus SELESAI & commit-nya sudah ada di branch basis
|
|
55
62
|
// sebelum item ini boleh diluncurkan. Array JSON of string; null/[] = tak bergantung apa pun.
|
|
56
63
|
// Sengaja kolom, bukan tabel join: SQLite melarang scalar list, `Json` sudah dipakai `payload`,
|
|
@@ -64,6 +71,29 @@ model Spec {
|
|
|
64
71
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
// SPEC-516 · ADR-0105 · changelog naratif per project yang sudah dibangkitkan.
|
|
75
|
+
//
|
|
76
|
+
// LOCAL-only: TANPA kolom `version`, jadi ia tak pernah masuk changefeed sync (cermin LeadFlow,
|
|
77
|
+
// WebhookEndpoint, dan Project.autoMerge). Dua dari tiga modenya diturunkan dari checkout git di
|
|
78
|
+
// MESIN INI, jadi barisnya fakta lokal; yang portabel adalah keluarannya, dan jalannya sudah ada
|
|
79
|
+
// — unduh .md.
|
|
80
|
+
model Changelog {
|
|
81
|
+
id String @id @default(cuid())
|
|
82
|
+
projectId String
|
|
83
|
+
mode String // "backlog" | "commit" | "version" (zChangelogMode di @hanoman/shared)
|
|
84
|
+
title String // judul di daftar: rentang tanggal / nama tag / rentang tag
|
|
85
|
+
params Json // parameter pembangkitan apa adanya (zChangelogRequest)
|
|
86
|
+
body String // markdown hasil akhir, sudah lewat scrubOutput
|
|
87
|
+
generator String // "agent" | "fallback"
|
|
88
|
+
warning String? // alasan fallback + catatan cakupan; null = mulus
|
|
89
|
+
itemCount Int @default(0)
|
|
90
|
+
createdAt DateTime @default(now())
|
|
91
|
+
updatedAt DateTime @updatedAt
|
|
92
|
+
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
93
|
+
|
|
94
|
+
@@index([projectId, createdAt])
|
|
95
|
+
}
|
|
96
|
+
|
|
67
97
|
// SPEC-450 · ADR-0094 · custom agent: persona yang bisa dipilih ulang & dibagi.
|
|
68
98
|
// `projectId` null = GLOBAL (semua project); terisi = milik satu project, dan agen project
|
|
69
99
|
// MENIMPA agen global bernama sama.
|
|
@@ -369,7 +399,7 @@ model SchedulerQueueItem {
|
|
|
369
399
|
projectId String
|
|
370
400
|
source String // backlog | triase (asal checker) — SPEC-384 · `errors` dicabut (ADR-0092)
|
|
371
401
|
priority String // tinggi | sedang | rendah (urutan drain)
|
|
372
|
-
status String @default("queued") // queued | launched | done | failed
|
|
402
|
+
status String @default("queued") // queued | launched | done | failed | canceled (SPEC-522 · tombstone operator)
|
|
373
403
|
sessionId String?
|
|
374
404
|
note String? // alasan gagal (diisi daun #5)
|
|
375
405
|
enqueuedAt DateTime @default(now())
|