hanoman 0.1.9 → 0.1.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hanoman",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Orchestrator + dashboard workflow docs-driven untuk sesi Claude Code / Codex",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,31 @@
1
+ -- SPEC-471 · ADR-0095 · cermin issue GitHub sebagai record lokal (pola Ticket, ADR-0062).
2
+ --
3
+ -- Tabel baru → `CREATE TABLE` polos; tak ada redefinisi tabel.
4
+ -- `id` deterministik "<projectId>:<owner>/<repo>#<number>" ditulis aplikasi, bukan default DB —
5
+ -- itulah yang mencegah dua mesin melahirkan dua baris untuk issue yang sama.
6
+ -- `specId` sengaja TANPA FOREIGN KEY, cermin Ticket.specId: changefeed bisa memancarkan
7
+ -- GithubIssue sebelum Spec-nya mendarat (kelas SPEC-382), dan FK akan menolaknya.
8
+ CREATE TABLE "GithubIssue" (
9
+ "id" TEXT NOT NULL PRIMARY KEY,
10
+ "projectId" TEXT NOT NULL,
11
+ "repoSlug" TEXT NOT NULL,
12
+ "number" INTEGER NOT NULL,
13
+ "title" TEXT NOT NULL,
14
+ "body" TEXT NOT NULL,
15
+ "authorLogin" TEXT NOT NULL,
16
+ "labels" JSONB NOT NULL,
17
+ "url" TEXT NOT NULL,
18
+ "issueState" TEXT NOT NULL,
19
+ "status" TEXT NOT NULL DEFAULT 'new',
20
+ "specId" TEXT,
21
+ "issueCreatedAt" DATETIME NOT NULL,
22
+ "issueUpdatedAt" DATETIME NOT NULL,
23
+ "pulledAt" DATETIME NOT NULL,
24
+ "version" INTEGER NOT NULL DEFAULT 0,
25
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
26
+ "updatedAt" DATETIME NOT NULL,
27
+ CONSTRAINT "GithubIssue_projectId_fkey" FOREIGN KEY ("projectId")
28
+ REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
29
+ );
30
+
31
+ CREATE INDEX "GithubIssue_projectId_status_idx" ON "GithubIssue" ("projectId", "status");
@@ -0,0 +1,112 @@
1
+ -- SPEC-476 · ADR-0096 · durable, local-only Telegram gateway state.
2
+ -- Deliberately no foreign keys: project/session references may disappear while dedupe/audit remains.
3
+ -- Deliberately no credentials or inbound message body.
4
+ CREATE TABLE "TelegramGatewayState" (
5
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1,
6
+ "offset" INTEGER NOT NULL DEFAULT 0,
7
+ "botUsername" TEXT,
8
+ "lastUpdateAt" DATETIME,
9
+ "lastError" TEXT,
10
+ "updatedAt" DATETIME NOT NULL
11
+ );
12
+
13
+ CREATE TABLE "TelegramChat" (
14
+ "chatId" TEXT NOT NULL PRIMARY KEY,
15
+ "userId" TEXT NOT NULL,
16
+ "sessionId" TEXT,
17
+ "activeProjectId" TEXT,
18
+ "activeSessionId" TEXT,
19
+ "personalityAgentId" TEXT,
20
+ "summary" TEXT,
21
+ "agent" TEXT NOT NULL,
22
+ "model" TEXT NOT NULL,
23
+ "effort" TEXT NOT NULL,
24
+ "lastProgressKey" TEXT,
25
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
26
+ "updatedAt" DATETIME NOT NULL
27
+ );
28
+
29
+ CREATE UNIQUE INDEX "TelegramChat_userId_key" ON "TelegramChat"("userId");
30
+
31
+ CREATE TABLE "TelegramUpdate" (
32
+ "updateId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
33
+ "chatId" TEXT,
34
+ "userId" TEXT,
35
+ "kind" TEXT NOT NULL,
36
+ "digest" TEXT NOT NULL,
37
+ "state" TEXT NOT NULL DEFAULT 'received',
38
+ "rejectReason" TEXT,
39
+ "receivedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
40
+ "claimedAt" DATETIME,
41
+ "dispatchedAt" DATETIME
42
+ );
43
+
44
+ CREATE INDEX "TelegramUpdate_userId_receivedAt_idx" ON "TelegramUpdate"("userId", "receivedAt");
45
+ CREATE INDEX "TelegramUpdate_state_idx" ON "TelegramUpdate"("state");
46
+
47
+ CREATE TABLE "TelegramMemory" (
48
+ "id" TEXT NOT NULL PRIMARY KEY,
49
+ "chatId" TEXT NOT NULL,
50
+ "content" TEXT NOT NULL,
51
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
52
+ "updatedAt" DATETIME NOT NULL
53
+ );
54
+
55
+ CREATE INDEX "TelegramMemory_chatId_createdAt_idx" ON "TelegramMemory"("chatId", "createdAt");
56
+
57
+ CREATE TABLE "TelegramOutbox" (
58
+ "id" TEXT NOT NULL PRIMARY KEY,
59
+ "chatId" TEXT NOT NULL,
60
+ "updateId" INTEGER NOT NULL,
61
+ "kind" TEXT NOT NULL,
62
+ "dedupeKey" TEXT NOT NULL,
63
+ "text" TEXT NOT NULL,
64
+ "state" TEXT NOT NULL DEFAULT 'pending',
65
+ "confirmationId" TEXT,
66
+ "telegramMessageId" INTEGER,
67
+ "error" TEXT,
68
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
69
+ "claimedAt" DATETIME,
70
+ "sentAt" DATETIME
71
+ );
72
+
73
+ CREATE UNIQUE INDEX "TelegramOutbox_dedupeKey_key" ON "TelegramOutbox"("dedupeKey");
74
+ CREATE INDEX "TelegramOutbox_state_createdAt_idx" ON "TelegramOutbox"("state", "createdAt");
75
+ CREATE INDEX "TelegramOutbox_chatId_createdAt_idx" ON "TelegramOutbox"("chatId", "createdAt");
76
+
77
+ CREATE TABLE "TelegramConfirmation" (
78
+ "id" TEXT NOT NULL PRIMARY KEY,
79
+ "callbackToken" TEXT NOT NULL,
80
+ "chatId" TEXT NOT NULL,
81
+ "userId" TEXT NOT NULL,
82
+ "updateId" INTEGER NOT NULL,
83
+ "description" TEXT NOT NULL,
84
+ "method" TEXT NOT NULL,
85
+ "path" TEXT NOT NULL,
86
+ "state" TEXT NOT NULL DEFAULT 'pending',
87
+ "expiresAt" DATETIME NOT NULL,
88
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
89
+ "approvedAt" DATETIME,
90
+ "usedAt" DATETIME
91
+ );
92
+
93
+ CREATE UNIQUE INDEX "TelegramConfirmation_callbackToken_key" ON "TelegramConfirmation"("callbackToken");
94
+ CREATE INDEX "TelegramConfirmation_chatId_state_idx" ON "TelegramConfirmation"("chatId", "state");
95
+ CREATE INDEX "TelegramConfirmation_expiresAt_idx" ON "TelegramConfirmation"("expiresAt");
96
+
97
+ CREATE TABLE "TelegramAudit" (
98
+ "id" TEXT NOT NULL PRIMARY KEY,
99
+ "chatId" TEXT,
100
+ "userId" TEXT,
101
+ "updateId" INTEGER,
102
+ "action" TEXT NOT NULL,
103
+ "outcome" TEXT NOT NULL,
104
+ "correlationId" TEXT,
105
+ "method" TEXT,
106
+ "path" TEXT,
107
+ "statusCode" INTEGER,
108
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
109
+ );
110
+
111
+ CREATE INDEX "TelegramAudit_chatId_createdAt_idx" ON "TelegramAudit"("chatId", "createdAt");
112
+ CREATE INDEX "TelegramAudit_updateId_idx" ON "TelegramAudit"("updateId");
@@ -24,6 +24,7 @@ model Project {
24
24
  specs Spec[]
25
25
  tickets Ticket[]
26
26
  customAgents CustomAgent[] // SPEC-450 · ADR-0094 · custom agent milik project ini
27
+ githubIssues GithubIssue[] // SPEC-471 · ADR-0095 · cermin issue repo GitHub project ini
27
28
  }
28
29
 
29
30
  model Spec {
@@ -91,6 +92,38 @@ model CustomAgent {
91
92
  @@index([projectId])
92
93
  }
93
94
 
95
+ // SPEC-471 · ADR-0095 · cermin issue GitHub sebagai record lokal, pola Ticket (ADR-0062).
96
+ // `id` DETERMINISTIK "<projectId>:<owner>/<repo>#<number>" ditulis aplikasi, bukan default DB —
97
+ // alasan yang sama dengan CustomAgent (ADR-0094): dua mesin yang menarik repo yang sama harus
98
+ // bertemu sebagai SATU baris di changefeed, bukan dua yang saling menelan. `projectId` ikut di
99
+ // dalam id karena dua project hanoman boleh menunjuk repo yang sama.
100
+ //
101
+ // `specId` sengaja TANPA FK (cermin Ticket.specId): changefeed bisa memancarkan GithubIssue
102
+ // sebelum Spec-nya mendarat (kelas SPEC-382) dan FK akan menolaknya.
103
+ model GithubIssue {
104
+ id String @id
105
+ projectId String
106
+ repoSlug String // "owner/repo"
107
+ number Int
108
+ title String
109
+ body String
110
+ authorLogin String
111
+ labels Json // string[]
112
+ url String
113
+ issueState String // open | closed — keadaan DI GITHUB saat ditarik
114
+ status String @default("new") // new | accepted | rejected (zGithubIssueStatus)
115
+ specId String? // soft-link Spec hasil promosi
116
+ issueCreatedAt DateTime
117
+ issueUpdatedAt DateTime
118
+ pulledAt DateTime
119
+ version Int @default(0) // SPEC-471 · version-stamp sync (ADR-0045)
120
+ createdAt DateTime @default(now())
121
+ updatedAt DateTime @updatedAt
122
+ project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
123
+
124
+ @@index([projectId, status])
125
+ }
126
+
94
127
  model Setting {
95
128
  id Int @id @default(1)
96
129
  data Json
@@ -378,6 +411,116 @@ model RuntimeConfig {
378
411
  updatedAt DateTime @updatedAt
379
412
  }
380
413
 
414
+ // SPEC-476 · ADR-0096 · seluruh state gateway Telegram bersifat LOCAL-only. Telegram adalah kanal
415
+ // menuju tmux di mesin ini, jadi offset/binding/memory/outbox tidak punya arti untuk sync antar-node.
416
+ // Tujuh model ini sengaja tanpa FK: referensi project/spec/session dapat hilang sementara audit dan
417
+ // dedupe harus tetap bertahan. Tidak ada token, credential, atau body inbound di schema ini.
418
+ model TelegramGatewayState {
419
+ id Int @id @default(1)
420
+ offset Int @default(0)
421
+ botUsername String?
422
+ lastUpdateAt DateTime?
423
+ lastError String?
424
+ updatedAt DateTime @updatedAt
425
+ }
426
+
427
+ model TelegramChat {
428
+ chatId String @id
429
+ userId String @unique
430
+ sessionId String?
431
+ activeProjectId String?
432
+ activeSessionId String?
433
+ personalityAgentId String?
434
+ summary String?
435
+ agent String
436
+ model String
437
+ effort String
438
+ lastProgressKey String?
439
+ createdAt DateTime @default(now())
440
+ updatedAt DateTime @updatedAt
441
+ }
442
+
443
+ model TelegramUpdate {
444
+ updateId Int @id
445
+ chatId String?
446
+ userId String?
447
+ kind String
448
+ digest String
449
+ state String @default("received") // received | rejected | dispatching | dispatched | uncertain
450
+ rejectReason String?
451
+ receivedAt DateTime @default(now())
452
+ claimedAt DateTime?
453
+ dispatchedAt DateTime?
454
+
455
+ @@index([userId, receivedAt])
456
+ @@index([state])
457
+ }
458
+
459
+ model TelegramMemory {
460
+ id String @id @default(cuid())
461
+ chatId String
462
+ content String
463
+ createdAt DateTime @default(now())
464
+ updatedAt DateTime @updatedAt
465
+
466
+ @@index([chatId, createdAt])
467
+ }
468
+
469
+ model TelegramOutbox {
470
+ id String @id @default(cuid())
471
+ chatId String
472
+ updateId Int
473
+ kind String
474
+ dedupeKey String @unique
475
+ text String
476
+ state String @default("pending") // pending | sending | sent | failed | uncertain
477
+ confirmationId String?
478
+ telegramMessageId Int?
479
+ error String?
480
+ createdAt DateTime @default(now())
481
+ claimedAt DateTime?
482
+ sentAt DateTime?
483
+
484
+ @@index([state, createdAt])
485
+ @@index([chatId, createdAt])
486
+ }
487
+
488
+ model TelegramConfirmation {
489
+ id String @id @default(cuid())
490
+ callbackToken String @unique
491
+ chatId String
492
+ userId String
493
+ updateId Int
494
+ description String
495
+ method String
496
+ path String
497
+ state String @default("pending") // pending | approved | denied | used | expired
498
+ expiresAt DateTime
499
+ createdAt DateTime @default(now())
500
+ approvedAt DateTime?
501
+ usedAt DateTime?
502
+
503
+ @@index([chatId, state])
504
+ @@index([expiresAt])
505
+ }
506
+
507
+ model TelegramAudit {
508
+ id String @id @default(cuid())
509
+ chatId String?
510
+ userId String?
511
+ updateId Int?
512
+ action String
513
+ outcome String
514
+ correlationId String?
515
+ method String?
516
+ path String?
517
+ statusCode Int?
518
+ createdAt DateTime @default(now())
519
+
520
+ @@index([chatId, createdAt])
521
+ @@index([updateId])
522
+ }
523
+
381
524
 
382
525
 
383
526