hanoman 0.1.46 → 0.1.50
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/README.md +43 -1
- package/dist/build-info.json +3 -3
- package/dist/cli.js +100 -38
- package/dist/server.js +27934 -27449
- package/docs/agent-integration.md +10 -0
- package/package.json +1 -1
- package/prisma/migrations/20260819120000_spec_attachment/migration.sql +19 -0
- package/prisma/migrations/20260819130000_session_history_ended_reason/migration.sql +27 -0
- package/prisma/schema.prisma +31 -0
- package/web/assets/index-Ddz2nble.js +7606 -0
- package/web/index.html +1 -1
- package/web/assets/index-pMhBDQcJ.js +0 -7779
|
@@ -169,6 +169,10 @@ dan tak memakai agent token.
|
|
|
169
169
|
| `POST /api/specs` | `backlog:write` | buat backlog item — bentuk payload di §7. |
|
|
170
170
|
| `PATCH /api/specs/:id` | `backlog:write` | ubah item; konten hanya selagi belum dimulai. |
|
|
171
171
|
| `POST /api/specs/:id/done` | `backlog:write` | tandai item **selesai** tanpa menjalankan sesi — untuk pekerjaan yang beres di luar hanoman. Body `{ reason?: string (≤280), confirm?: boolean }`, keduanya opsional; balasannya `Spec` yang sudah `stage:"done"`. Tak menjalankan maupun menghentikan sesi apa pun. |
|
|
172
|
+
| `GET /api/specs/:id/attachments` | `backlog:read` | lampiran backlog item — gambar & dokumen yang dilampirkan manusia sebagai konteks kerja. |
|
|
173
|
+
| `POST /api/specs/:id/attachments` | `backlog:write` | unggah lampiran (`multipart/form-data`, beberapa berkas per request). Berkas yang ditolak **tak** menggagalkan yang lain — periksa `rejected[]`. |
|
|
174
|
+
| `GET /api/specs/:id/attachments/:attId` | `backlog:read` | byte satu lampiran. |
|
|
175
|
+
| `DELETE /api/specs/:id/attachments/:attId` | `backlog:write` | hapus satu lampiran. |
|
|
172
176
|
| `GET /api/specs/:id/docs` | `backlog:read` | dokumen yang ditulis sesi item itu. |
|
|
173
177
|
| `GET /api/specs/:id/review` | `backlog:read` | diff hasil kerja sesi. |
|
|
174
178
|
| `GET /api/projects/:id/docs` | `docs:read` | index Source of Truth project. |
|
|
@@ -299,6 +303,7 @@ memanggilnya; jangan lakukan tanpa manusia.
|
|
|
299
303
|
| `branchFrom` yang tak ada di repo project → **400**, bukan diterima lalu gagal di tengah sesi | ambil kandidatnya dari `GET /api/projects/:id/branches` |
|
|
300
304
|
| **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 |
|
|
301
305
|
| **403** bukan kegagalan permanen | bacalah field `need`, sampaikan ke manusia, minta capability itu ditambahkan |
|
|
306
|
+
| **Lampiran backlog tak menyeberang sync** (`SpecAttachment` LOCAL-only, ADR-0124) | item yang sama di instance lain tampil **tanpa** lampiran. Kalau lampiran yang disebut manusia tak kamu temukan, kemungkinan besar kamu bicara ke instance yang bukan tempat lampiran itu diunggah — tanyakan, jangan simpulkan lampirannya tak ada |
|
|
302
307
|
|
|
303
308
|
## 10. Contoh alur end-to-end
|
|
304
309
|
|
|
@@ -461,6 +466,11 @@ dan seluruh `/api/vps*` (remote exec) **tidak ikut**, begitu pula merge/rebase (
|
|
|
461
466
|
penghapusan backlog, dan perubahan `stage`. Batasan ini ada di katalog toolnya, bukan di token:
|
|
462
467
|
token yang punya `sessions:write` sekalipun tak akan menemukan tool untuk memakainya. Lihat §8.
|
|
463
468
|
|
|
469
|
+
**Lampiran backlog** (`/api/specs/:id/attachments*`, SPEC-843 · ADR-0124) juga sengaja **tak punya
|
|
470
|
+
tool**: berkasnya lahir dari disk manusia, bukan dari model, dan tool MCP berbentuk JSON sehingga
|
|
471
|
+
byte biner tak punya representasi di sana. REST-nya tetap terjangkau agent token
|
|
472
|
+
ber-`backlog:read`/`backlog:write` — yang tak dipajang adalah **tool**-nya.
|
|
473
|
+
|
|
464
474
|
### Opsi
|
|
465
475
|
|
|
466
476
|
| Variabel / flag | Arti |
|
package/package.json
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- SPEC-843 · ADR-0124 · lampiran per backlog item.
|
|
2
|
+
--
|
|
3
|
+
-- Ditulis tangan (bukan `migrate dev`): worktree tetangga membuat `migrate dev` me-reset DB saat
|
|
4
|
+
-- ada drift. ADITIF murni — satu tabel baru, tak ada tabel yang diredefinisi.
|
|
5
|
+
--
|
|
6
|
+
-- TANPA kolom `version`: entitas ini LOCAL-only dan tak pernah masuk changefeed sync.
|
|
7
|
+
CREATE TABLE "SpecAttachment" (
|
|
8
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
9
|
+
"specId" TEXT NOT NULL,
|
|
10
|
+
"projectId" TEXT NOT NULL,
|
|
11
|
+
"filename" TEXT NOT NULL,
|
|
12
|
+
"mimeType" TEXT NOT NULL,
|
|
13
|
+
"size" INTEGER NOT NULL,
|
|
14
|
+
"storageKey" TEXT NOT NULL,
|
|
15
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
16
|
+
CONSTRAINT "SpecAttachment_specId_fkey" FOREIGN KEY ("specId") REFERENCES "Spec" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE INDEX "SpecAttachment_specId_idx" ON "SpecAttachment"("specId");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- SPEC-844 · ADR-0125 · riwayat sesi mencatat BAGAIMANA sebuah baris ditutup.
|
|
2
|
+
--
|
|
3
|
+
-- Ditulis tangan (bukan `migrate dev`): worktree tetangga membuat `migrate dev` me-reset DB saat
|
|
4
|
+
-- ada drift. ADITIF murni — dua kolom NULLABLE tanpa default, tak ada tabel diredefinisi, jadi
|
|
5
|
+
-- jebakan `ADD COLUMN … DEFAULT CURRENT_TIMESTAMP` (ADR-0090) tak berlaku di sini.
|
|
6
|
+
ALTER TABLE "SessionHistory" ADD COLUMN "endedReason" TEXT;
|
|
7
|
+
ALTER TABLE "SessionHistory" ADD COLUMN "reconciledAt" DATETIME;
|
|
8
|
+
|
|
9
|
+
-- Backfill SEKALI JALAN. Baris lama tak bisa ditanyai, tapi jejaknya masih ada: `reconcileHistory`
|
|
10
|
+
-- membaca `updatedAt` SEBELUM update-nya sendiri (jadi `updatedAt` melompat ke waktu boot dan
|
|
11
|
+
-- meninggalkan `endedAt` di belakang), sementara `finishSession` menulis `endedAt = new Date()` DI
|
|
12
|
+
-- DALAM update yang sama (jadi jaraknya nol). Terukur pada DB hidup 806 baris: tutup normal
|
|
13
|
+
-- 0–39 ms (n=777) vs rekonsiliasi 275 966–82 224 277 ms (n=20) — empat orde besaran tanpa satu pun
|
|
14
|
+
-- baris di antaranya; ambang 60 000 ms duduk di tengah celah itu.
|
|
15
|
+
--
|
|
16
|
+
-- Ini backfill, BUKAN aturan render: menjadikannya kontrak akan mengunci detail penyimpanan Prisma
|
|
17
|
+
-- sebagai semantik produk. Prisma menyimpan DateTime SQLite sebagai INTEGER milidetik, jadi
|
|
18
|
+
-- selisihnya aritmetika biasa; `CAST` dipasang supaya representasi lain (teks ISO) menghasilkan
|
|
19
|
+
-- selisih 0 → nol baris cocok → seluruh tabel jatuh ke 'closed', yaitu perilaku sebelum spec ini.
|
|
20
|
+
UPDATE "SessionHistory"
|
|
21
|
+
SET "endedReason" = 'reconciled', "reconciledAt" = "updatedAt"
|
|
22
|
+
WHERE "endedAt" IS NOT NULL
|
|
23
|
+
AND CAST("updatedAt" AS INTEGER) - CAST("endedAt" AS INTEGER) > 60000;
|
|
24
|
+
|
|
25
|
+
UPDATE "SessionHistory"
|
|
26
|
+
SET "endedReason" = 'closed'
|
|
27
|
+
WHERE "endedAt" IS NOT NULL AND "endedReason" IS NULL;
|
package/prisma/schema.prisma
CHANGED
|
@@ -87,6 +87,30 @@ model Spec {
|
|
|
87
87
|
sourceHistory Json?
|
|
88
88
|
updatedAt DateTime @updatedAt
|
|
89
89
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
90
|
+
attachments SpecAttachment[]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// SPEC-843 · ADR-0124 · lampiran per backlog item — konteks yang dipegang manusia saat memfilekan
|
|
94
|
+
// item, dibaca agen di dalam sesi. Byte hidup di HANOMAN_UPLOAD_DIR (server-local, di luar repoDir);
|
|
95
|
+
// `storageKey` opaque, `filename` nama asli tersanitasi untuk tampilan saja.
|
|
96
|
+
//
|
|
97
|
+
// LOCAL-only: TANPA `version`, jadi ia tak pernah masuk changefeed sync (cermin LeadFlow,
|
|
98
|
+
// WebhookEndpoint, Changelog). Byte memang tak menyeberang (ADR-0062), dan metadata yang menyeberang
|
|
99
|
+
// TANPA byte-nya hanya menghasilkan lampiran yang tak bisa dibuka di mesin lain — keadaan terburuk
|
|
100
|
+
// dari ketiga pilihan. Sengaja BUKAN TicketAttachment: tiket dan backlog dua domain dengan aturan
|
|
101
|
+
// sync dan tingkat kepercayaan yang berbeda (ADR-0124 §1/§4).
|
|
102
|
+
model SpecAttachment {
|
|
103
|
+
id String @id @default(cuid())
|
|
104
|
+
specId String
|
|
105
|
+
projectId String // denormal — kuota & isolasi per project, cermin TicketAttachment
|
|
106
|
+
filename String
|
|
107
|
+
mimeType String
|
|
108
|
+
size Int
|
|
109
|
+
storageKey String
|
|
110
|
+
createdAt DateTime @default(now())
|
|
111
|
+
spec Spec @relation(fields: [specId], references: [id], onDelete: Cascade)
|
|
112
|
+
|
|
113
|
+
@@index([specId])
|
|
90
114
|
}
|
|
91
115
|
|
|
92
116
|
// SPEC-516 · ADR-0105 · changelog naratif per project yang sudah dibangkitkan.
|
|
@@ -368,6 +392,13 @@ model SessionHistory {
|
|
|
368
392
|
startedAt DateTime @default(now())
|
|
369
393
|
endedAt DateTime?
|
|
370
394
|
exitCode Int?
|
|
395
|
+
// SPEC-844 · ADR-0125 · CARA baris ini ditutup: "closed" (killSession) atau "reconciled" (pane
|
|
396
|
+
// sudah lenyap saat boot — hasilnya tak diketahui). null = baris lahir sebelum kolom ini ada.
|
|
397
|
+
// Kelas hasil (selesai/gagal) sengaja TIDAK disimpan: ia turunan exitCode (sessionOutcome).
|
|
398
|
+
endedReason String?
|
|
399
|
+
// Kapan boot menemukan panenya lenyap. `endedAt` baris rekonsiliasi adalah batas BAWAH
|
|
400
|
+
// ("terakhir diketahui hidup"); kolom ini batas atasnya.
|
|
401
|
+
reconciledAt DateTime?
|
|
371
402
|
transcriptKey String?
|
|
372
403
|
transcriptBytes Int?
|
|
373
404
|
createdAt DateTime @default(now())
|