add-coder 0.3.26 → 0.3.27
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 +36 -10
- package/dist/index.js +481 -209
- package/package.json +14 -4
- package/templates/.add-coder-src-hash.json +129 -106
- package/templates/adapters/claude/hooks/doc-format-guard.sh +112 -31
- package/templates/adapters/claude/hooks/lib/common.sh +46 -87
- package/templates/adapters/claude/hooks/lib/context-inject.sh +2 -2
- package/templates/adapters/claude/hooks/lib/notify.sh +6 -4
- package/templates/adapters/claude/hooks/lib/preload-templates.sh +27 -2
- package/templates/adapters/claude/hooks/lib/state-detect.sh +8 -112
- package/templates/adapters/claude/hooks/lib/vocabulary.sh +13 -7
- package/templates/adapters/claude/hooks/prompt-submit.sh +1 -1
- package/templates/adapters/claude/hooks/stop-check.sh +9 -0
- package/templates/adapters/codex/config.toml.example +12 -0
- package/templates/adapters/codex/hooks/doc-format-guard.sh +121 -39
- package/templates/adapters/codex/hooks/lib/common.sh +47 -99
- package/templates/adapters/codex/hooks/lib/context-inject.sh +4 -4
- package/templates/adapters/codex/hooks/lib/notify.sh +6 -4
- package/templates/adapters/codex/hooks/lib/preload-templates.sh +27 -6
- package/templates/adapters/codex/hooks/lib/state-detect.sh +5 -114
- package/templates/adapters/codex/hooks/lib/vocabulary.sh +3 -8
- package/templates/adapters/codex/hooks/notification.sh +3 -18
- package/templates/adapters/codex/hooks/post-tool-use.sh +24 -119
- package/templates/adapters/codex/hooks/pre-tool-use.sh +97 -184
- package/templates/adapters/codex/hooks/prompt-submit.sh +8 -3
- package/templates/adapters/codex/hooks/session-start.sh +19 -9
- package/templates/adapters/codex/hooks/stop-check.sh +44 -18
- package/templates/adapters/codex/hooks.json +67 -1
- package/templates/adapters/qoder/hooks/doc-format-guard.sh +119 -38
- package/templates/adapters/qoder/hooks/lib/common.sh +49 -87
- package/templates/adapters/qoder/hooks/lib/context-inject.sh +2 -2
- package/templates/adapters/qoder/hooks/lib/notify.sh +6 -4
- package/templates/adapters/qoder/hooks/lib/preload-templates.sh +27 -2
- package/templates/adapters/qoder/hooks/lib/state-detect.sh +8 -112
- package/templates/adapters/qoder/hooks/lib/vocabulary.sh +13 -7
- package/templates/adapters/qoder/hooks/prompt-submit.sh +1 -1
- package/templates/adapters/qoder/hooks/session-start.sh +1 -1
- package/templates/adapters/qoder/hooks/stop-check.sh +11 -0
- package/templates/adapters/trae/hooks/doc-format-guard.sh +120 -38
- package/templates/adapters/trae/hooks/lib/common.sh +46 -87
- package/templates/adapters/trae/hooks/lib/context-inject.sh +2 -2
- package/templates/adapters/trae/hooks/lib/notify.sh +5 -3
- package/templates/adapters/trae/hooks/lib/preload-templates.sh +27 -2
- package/templates/adapters/trae/hooks/lib/state-detect.sh +8 -115
- package/templates/adapters/trae/hooks/lib/vocabulary.sh +13 -7
- package/templates/adapters/trae/hooks/pre-tool-use.sh +14 -8
- package/templates/adapters/trae/hooks/stop-check.sh +9 -0
- package/templates/adapters/vscode/hooks/doc-format-guard.sh +112 -31
- package/templates/adapters/vscode/hooks/lib/common.sh +46 -87
- package/templates/adapters/vscode/hooks/lib/context-inject.sh +2 -2
- package/templates/adapters/vscode/hooks/lib/notify.sh +6 -4
- package/templates/adapters/vscode/hooks/lib/preload-templates.sh +27 -2
- package/templates/adapters/vscode/hooks/lib/state-detect.sh +8 -112
- package/templates/adapters/vscode/hooks/lib/vocabulary.sh +13 -7
- package/templates/adapters/vscode/hooks/notification.sh +3 -5
- package/templates/adapters/vscode/hooks/prompt-submit.sh +1 -1
- package/templates/adapters/vscode/hooks/stop-check.sh +9 -0
- package/templates/core/docs/ADD-governance-claude-code.md +1 -1
- package/templates/core/docs/ADD-governance-codex.md +1 -1
- package/templates/core/docs/ADD-governance-qoder-cn.md +1 -1
- package/templates/core/docs/ADD-governance-trae.md +1 -1
- package/templates/core/docs/ADD-governance-vscode-copilot.md +1 -1
- package/templates/core/hooks/doc-format-guard.sh +120 -38
- package/templates/core/hooks/lib/common.sh +46 -87
- package/templates/core/hooks/lib/context-inject.sh +2 -2
- package/templates/core/hooks/lib/notify.sh +5 -3
- package/templates/core/hooks/lib/preload-templates.sh +27 -2
- package/templates/core/hooks/lib/state-detect.sh +8 -115
- package/templates/core/hooks/lib/vocabulary.sh +13 -7
- package/templates/core/hooks/pre-tool-use.sh +14 -8
- package/templates/core/hooks/stop-check.sh +9 -0
- package/templates/core/prisma/add.prisma +140 -82
- package/templates/core/rules/project_rules.md +27 -24
- package/templates/core/scripts/db-ensure.sh +8 -0
- package/templates/core/scripts/gen-plan-index.sh +4 -15
- package/templates/core/scripts/mcp-server/notifications/hitl.ts +9 -1
- package/templates/core/scripts/mcp-server/notifications/hook.ts +25 -9
- package/templates/core/scripts/mcp-server/resources/hitl-approval-widget.ts +34 -0
- package/templates/core/scripts/mcp-server/resources/hook-events-report.ts +14 -2
- package/templates/core/scripts/mcp-server/resources/index.ts +2 -0
- package/templates/core/scripts/mcp-server/sampling/review.ts +25 -10
- package/templates/core/scripts/mcp-server/shared/db-types.ts +33 -8
- package/templates/core/scripts/mcp-server/shared/dps-scoring.strategy.ts +1 -1
- package/templates/core/scripts/mcp-server/shared/env.ts +28 -8
- package/templates/core/scripts/mcp-server/shared/fs.ts +3 -0
- package/templates/core/scripts/mcp-server/shared/hitl-interaction.strategy.ts +2 -3
- package/templates/core/scripts/mcp-server/shared/hitl-lifecycle-mutation.ts +129 -0
- package/templates/core/scripts/mcp-server/shared/hitl-proposal-mutation.ts +98 -0
- package/templates/core/scripts/mcp-server/shared/hitl-ui.ts +3 -0
- package/templates/core/scripts/mcp-server/shared/plan-lifecycle-events.ts +62 -0
- package/templates/core/scripts/mcp-server/shared/plan-lifecycle-mutation.ts +78 -0
- package/templates/core/scripts/mcp-server/shared/plan-lifecycle-subscriber.ts +145 -0
- package/templates/core/scripts/mcp-server/shared/plan-lifecycle.ts +153 -0
- package/templates/core/scripts/mcp-server/shared/plan-round-events.ts +56 -0
- package/templates/core/scripts/mcp-server/shared/plan-round-mutation.ts +143 -0
- package/templates/core/scripts/mcp-server/shared/plan-round-store.ts +47 -0
- package/templates/core/scripts/mcp-server/shared/plan-round-subscriber.ts +99 -0
- package/templates/core/scripts/mcp-server/shared/plan-status-store.ts +37 -0
- package/templates/core/scripts/mcp-server/shared/plan-tracking-mutation.ts +71 -0
- package/templates/core/scripts/mcp-server/shared/prisma.ts +12 -6
- package/templates/core/scripts/mcp-server/shared/project-root-strategy.ts +1 -2
- package/templates/core/scripts/mcp-server/shared/quant-recheck.strategy.ts +16 -0
- package/templates/core/scripts/mcp-server/shared/redact.ts +28 -0
- package/templates/core/scripts/mcp-server/shared/response.ts +3 -2
- package/templates/core/scripts/mcp-server/shared/runtime-context.ts +77 -0
- package/templates/core/scripts/mcp-server/shared/schema-topology.ts +159 -0
- package/templates/core/scripts/mcp-server/tools/audit.ts +49 -7
- package/templates/core/scripts/mcp-server/tools/context.ts +117 -121
- package/templates/core/scripts/mcp-server/tools/contract.ts +34 -9
- package/templates/core/scripts/mcp-server/tools/gateway/check_add_route_status.ts +50 -3
- package/templates/core/scripts/mcp-server/tools/gateway/check_doc_similarity.ts +218 -0
- package/templates/core/scripts/mcp-server/tools/gateway/check_dps.ts +22 -7
- package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +75 -4
- package/templates/core/scripts/mcp-server/tools/gateway/check_spec_sync.ts +19 -6
- package/templates/core/scripts/mcp-server/tools/gateway/index.ts +2 -0
- package/templates/core/scripts/mcp-server/tools/hitl.ts +160 -75
- package/templates/core/scripts/mcp-server/tools/hook-event-report.ts +9 -2
- package/templates/core/scripts/mcp-server/tools/index.ts +69 -3
- package/templates/core/scripts/mcp-server/tools/plan.ts +140 -15
- package/templates/core/scripts/mcp-server/tools/review.ts +44 -15
- package/templates/core/scripts/mcp-server.ts +60 -1
- package/templates/core/scripts/plan-status-bridge.ts +26 -0
- package/templates/core/skills/add-paradigm/SKILL.md +2 -2
- package/templates/core/templates/add-route-template.schema.json +24 -56
- package/templates/core/templates/collab-contract-template.md +1 -1
- package/templates/core/templates/handoff-multi-round-template.schema.json +48 -0
- package/templates/core/templates/handoff-single-round-template.schema.json +92 -0
- package/templates/core/templates/handoff-single-round.schema.json +1 -1
- package/templates/core/templates/hitl-approval-widget.html +222 -37
- package/templates/core/templates/spec-template.schema.json +9 -46
- package/templates/core/templates/standard-plan-template.schema.json +1 -1
- package/templates/core/templates/tasks-template.schema.json +13 -54
|
@@ -1,43 +1,54 @@
|
|
|
1
1
|
// add.prisma — ADD 治理模型,独立于用户业务表
|
|
2
2
|
|
|
3
3
|
model AddUser {
|
|
4
|
-
id
|
|
5
|
-
username
|
|
6
|
-
email
|
|
7
|
-
devOperations
|
|
8
|
-
auditLogs
|
|
4
|
+
id String @id @default(cuid())
|
|
5
|
+
username String @unique
|
|
6
|
+
email String?
|
|
7
|
+
devOperations DevOperation[]
|
|
8
|
+
auditLogs AuditLog[]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
model DevOperation {
|
|
12
|
-
id
|
|
13
|
-
userId
|
|
14
|
-
user
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
id String @id @default(cuid())
|
|
13
|
+
userId String
|
|
14
|
+
user AddUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
15
|
+
projectKey String @default("legacy-unknown")
|
|
16
|
+
producerAdapterKey String @default("legacy-unknown")
|
|
17
|
+
contextId String @default("legacy-unknown")
|
|
18
|
+
toolName String @default("record_dev_operation")
|
|
19
|
+
operationKey String @default(cuid())
|
|
20
|
+
planKeyword String
|
|
21
|
+
action String
|
|
22
|
+
targetType String
|
|
23
|
+
targetId String
|
|
24
|
+
beforeState Json?
|
|
25
|
+
afterState Json?
|
|
26
|
+
reason String?
|
|
27
|
+
createdAt DateTime @default(now())
|
|
23
28
|
|
|
29
|
+
@@unique([projectKey, producerAdapterKey, toolName, operationKey])
|
|
24
30
|
@@index([planKeyword])
|
|
31
|
+
@@index([projectKey, producerAdapterKey, planKeyword])
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
model AuditLog {
|
|
28
|
-
id
|
|
29
|
-
userId
|
|
30
|
-
user
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
id String @id @default(cuid())
|
|
36
|
+
userId String
|
|
37
|
+
user AddUser @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
38
|
+
projectKey String @default("legacy-unknown")
|
|
39
|
+
producerAdapterKey String @default("legacy-unknown")
|
|
40
|
+
contextId String @default("legacy-unknown")
|
|
41
|
+
action String
|
|
42
|
+
targetType String
|
|
43
|
+
targetId String
|
|
44
|
+
traceId String?
|
|
45
|
+
beforeState Json?
|
|
46
|
+
afterState Json?
|
|
47
|
+
reason String?
|
|
48
|
+
createdAt DateTime @default(now())
|
|
39
49
|
|
|
40
50
|
@@index([traceId])
|
|
51
|
+
@@index([projectKey, producerAdapterKey, contextId])
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
// ===== HITL 人机审核架构 =====
|
|
@@ -61,65 +72,85 @@ enum ReviewType {
|
|
|
61
72
|
RUNTIME
|
|
62
73
|
}
|
|
63
74
|
|
|
75
|
+
enum PlanLifecycleStatus {
|
|
76
|
+
DRAFT
|
|
77
|
+
ACTIVE
|
|
78
|
+
BLOCKED
|
|
79
|
+
REJECTED
|
|
80
|
+
CLOSED
|
|
81
|
+
ABANDONED
|
|
82
|
+
}
|
|
83
|
+
|
|
64
84
|
model HitlRecord {
|
|
65
|
-
id String
|
|
85
|
+
id String @id @default(cuid())
|
|
86
|
+
projectKey String @default("legacy-unknown")
|
|
87
|
+
adapterKey String @default("legacy-unknown")
|
|
66
88
|
planName String
|
|
67
|
-
plan PlanRecord
|
|
68
|
-
round Int
|
|
69
|
-
type HitlType
|
|
70
|
-
status HitlStatus
|
|
89
|
+
plan PlanRecord @relation(fields: [projectKey, adapterKey, planName], references: [projectKey, adapterKey, planName], onDelete: Cascade)
|
|
90
|
+
round Int @default(1)
|
|
91
|
+
type HitlType @default(PLAN)
|
|
92
|
+
status HitlStatus @default(DRAFT)
|
|
71
93
|
proposalPath String?
|
|
72
94
|
approvedAt DateTime?
|
|
73
95
|
rejectedAt DateTime?
|
|
74
96
|
rejectReason String?
|
|
75
|
-
createdBy String
|
|
76
|
-
createdAt DateTime
|
|
77
|
-
updatedAt DateTime
|
|
97
|
+
createdBy String @default("ai-assistant")
|
|
98
|
+
createdAt DateTime @default(now())
|
|
99
|
+
updatedAt DateTime @updatedAt
|
|
78
100
|
|
|
79
|
-
@@unique([planName, round])
|
|
80
|
-
@@index([planName])
|
|
101
|
+
@@unique([projectKey, adapterKey, planName, type, round])
|
|
102
|
+
@@index([projectKey, adapterKey, planName])
|
|
81
103
|
@@index([status])
|
|
82
104
|
}
|
|
83
105
|
|
|
84
106
|
model PlanRecord {
|
|
85
|
-
id
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
id String @id @default(cuid())
|
|
108
|
+
projectKey String @default("legacy-unknown")
|
|
109
|
+
adapterKey String @default("legacy-unknown")
|
|
110
|
+
planName String
|
|
111
|
+
lifecycle PlanLifecycleStatus @default(DRAFT)
|
|
112
|
+
revision Int @default(0)
|
|
113
|
+
planPath String
|
|
114
|
+
specPath String?
|
|
115
|
+
tasksPath String?
|
|
116
|
+
checklistPath String?
|
|
117
|
+
addRoutePath String?
|
|
118
|
+
totalTasks Int @default(0)
|
|
119
|
+
doneTasks Int @default(0)
|
|
120
|
+
checklistT Int @default(0)
|
|
121
|
+
checklistTDone Int @default(0)
|
|
122
|
+
checklistR Int @default(0)
|
|
123
|
+
planKeyword String?
|
|
98
124
|
// 并发协作契约:该 Plan 在契约中的角色(MASTER=总控 / SUB=子 Plan)
|
|
99
|
-
contractRole
|
|
125
|
+
contractRole ContractRole?
|
|
100
126
|
// 所属契约名(与 CollabContract.contractName 对应,反查用)
|
|
101
|
-
contractName
|
|
127
|
+
contractName String?
|
|
102
128
|
// 作为总控 Plan 持有的契约(masterPlanName 外键方向)
|
|
103
|
-
masterContract
|
|
129
|
+
masterContract CollabContract? @relation("MasterPlan")
|
|
130
|
+
contractBindings CollaborationPlanBinding[]
|
|
104
131
|
// DPS 四维评分历史(check_dps 调用后回写,供 FFT 自适应权重消费)
|
|
105
|
-
dpsSemScore
|
|
106
|
-
dpsEntropyScore
|
|
107
|
-
dpsCpmScore
|
|
108
|
-
dpsStructScore
|
|
109
|
-
dpsComposite
|
|
110
|
-
hitls
|
|
111
|
-
reviews
|
|
112
|
-
createdAt
|
|
113
|
-
updatedAt
|
|
114
|
-
|
|
132
|
+
dpsSemScore Int? // 语义相关性 0-100
|
|
133
|
+
dpsEntropyScore Int? // 信息熵匹配 0-100
|
|
134
|
+
dpsCpmScore Int? // CPM 关键路径 0-100
|
|
135
|
+
dpsStructScore Int? // 结构完整度 0-100
|
|
136
|
+
dpsComposite Int? // 加权 DPS 总分 0-100
|
|
137
|
+
hitls HitlRecord[]
|
|
138
|
+
reviews ReviewRecord[]
|
|
139
|
+
createdAt DateTime @default(now())
|
|
140
|
+
updatedAt DateTime @updatedAt
|
|
141
|
+
|
|
142
|
+
@@unique([projectKey, adapterKey, planName])
|
|
115
143
|
@@index([planKeyword])
|
|
116
144
|
@@index([contractName])
|
|
145
|
+
@@index([projectKey, adapterKey, lifecycle])
|
|
117
146
|
}
|
|
118
147
|
|
|
119
148
|
model ReviewRecord {
|
|
120
149
|
id String @id @default(cuid())
|
|
150
|
+
projectKey String @default("legacy-unknown")
|
|
151
|
+
adapterKey String @default("legacy-unknown")
|
|
121
152
|
planName String
|
|
122
|
-
plan PlanRecord @relation(fields: [planName], references: [planName], onDelete: Cascade)
|
|
153
|
+
plan PlanRecord @relation(fields: [projectKey, adapterKey, planName], references: [projectKey, adapterKey, planName], onDelete: Cascade)
|
|
123
154
|
type ReviewType @default(PLAN_REVIEW)
|
|
124
155
|
reviewPath String?
|
|
125
156
|
p0Count Int @default(0)
|
|
@@ -128,33 +159,60 @@ model ReviewRecord {
|
|
|
128
159
|
createdAt DateTime @default(now())
|
|
129
160
|
updatedAt DateTime @updatedAt
|
|
130
161
|
|
|
131
|
-
@@index([planName])
|
|
162
|
+
@@index([projectKey, adapterKey, planName])
|
|
132
163
|
@@index([type])
|
|
133
164
|
}
|
|
134
165
|
|
|
135
166
|
enum ContractRole {
|
|
136
|
-
MASTER
|
|
137
|
-
SUB
|
|
167
|
+
MASTER // 总控 Plan(契约持有者)
|
|
168
|
+
SUB // 子 Plan(契约实施单元)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
enum CollaborationBindingRole {
|
|
172
|
+
MASTER
|
|
173
|
+
MEMBER
|
|
138
174
|
}
|
|
139
175
|
|
|
140
176
|
// 并发协作契约(多智能体并行实施规则集,对应 collab-contract 文档)
|
|
141
177
|
model CollabContract {
|
|
142
|
-
id String
|
|
143
|
-
|
|
178
|
+
id String @id @default(cuid())
|
|
179
|
+
projectKey String @default("legacy-unknown")
|
|
180
|
+
ownerAdapterKey String @default("legacy-unknown")
|
|
181
|
+
contractName String
|
|
144
182
|
contractPath String
|
|
145
183
|
// 外键:总控 Plan(契约持有者,ContractRole=MASTER,一对一)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
184
|
+
masterProjectKey String @default("legacy-unknown")
|
|
185
|
+
masterAdapterKey String @default("legacy-unknown")
|
|
186
|
+
masterPlanName String
|
|
187
|
+
masterPlan PlanRecord @relation("MasterPlan", fields: [masterProjectKey, masterAdapterKey, masterPlanName], references: [projectKey, adapterKey, planName], onDelete: Restrict)
|
|
188
|
+
bindings CollaborationPlanBinding[]
|
|
189
|
+
participants Json // [{role, platformEntity, boundPlan, planKeyword, description}]
|
|
190
|
+
abilityMatrix Json? // {能力: {专家: boolean}}
|
|
191
|
+
stages Json // [{stage, expert, trigger, parallelism}]
|
|
192
|
+
dependencyGraph String? // ASCII 图 + 机器可读声明
|
|
193
|
+
fileBoundaries Json // [{expert, exclusiveDomain, forbidden, isolationMode}] isolationMode: file/worktree
|
|
194
|
+
completionCriteria Json? // {专家: 完成标志}
|
|
195
|
+
status String @default("ACTIVE") // ACTIVE / SUPERSEDED
|
|
196
|
+
version Int @default(1)
|
|
197
|
+
createdAt DateTime @default(now())
|
|
198
|
+
updatedAt DateTime @updatedAt
|
|
199
|
+
|
|
200
|
+
@@unique([projectKey, contractName])
|
|
201
|
+
@@unique([masterProjectKey, masterAdapterKey, masterPlanName])
|
|
202
|
+
@@index([projectKey, ownerAdapterKey])
|
|
203
|
+
}
|
|
158
204
|
|
|
159
|
-
|
|
205
|
+
model CollaborationPlanBinding {
|
|
206
|
+
id String @id @default(cuid())
|
|
207
|
+
contractId String
|
|
208
|
+
contract CollabContract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
209
|
+
projectKey String
|
|
210
|
+
adapterKey String
|
|
211
|
+
planName String
|
|
212
|
+
plan PlanRecord @relation(fields: [projectKey, adapterKey, planName], references: [projectKey, adapterKey, planName], onDelete: Cascade)
|
|
213
|
+
role CollaborationBindingRole @default(MEMBER)
|
|
214
|
+
createdAt DateTime @default(now())
|
|
215
|
+
|
|
216
|
+
@@unique([contractId, projectKey, adapterKey, planName])
|
|
217
|
+
@@index([projectKey, adapterKey, planName])
|
|
160
218
|
}
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
| P2 | ADD-13 DPS 上游文档质量闸门 | Plan 概括度 → Review 注意力稀释 → Specs 遗漏 → 实现偏差。`check_dps`(DPS ≥ {{dpsPass}})在 Step 0 末尾量化阻断 | ✅ 已实现 | 2026-06-11 引入 |
|
|
27
27
|
| P2 | ADD-14 RAHS 下游执行健康度闸门 | 范围保真度 + 类型安全 + 审计完整度 + Spec 合规 + 阶段对称性。`check_rahs`(RAHS ≥ 90)在 Step 4/8 量化阻断 | ✅ 已实现 | 2026-06-11 引入 |
|
|
28
28
|
| P2 | ADD-15 add-route 闭环自检 | Step 3 代码完成后必须调用 `check_add_route_completeness` 扫描 add-route Step 完成度,防止执行遗漏。返回 complete 方可进入 Step 3.5 | ✅ 已实现 | 2026-06-11 引入 |
|
|
29
|
-
| P2 | ADD-17 HITL
|
|
30
|
-
| P2 | ADD-18 HITL 人机审核强制规则 | Plan
|
|
29
|
+
| P2 | ADD-17 HITL 提案载体与状态机 | `create_hitl` 接收 `dimensions`,创建 `HitlRecord(DRAFT)` 与 `*.hitl.md` 提案;人工拍板后由 `update_hitl` 写入终态,正式文档仅在 `status_hitl=TONGYI` 后生成 | ✅ 已实现 | 2026-07-23 引入,2026-08-12 对齐 MCP 实现 |
|
|
30
|
+
| P2 | ADD-18 HITL 人机审核强制规则 | Plan、方案 Review、实现 Review 必须经过 `create_hitl` → 人工 tongyi/bohui → `update_hitl`;`TONGYI` 同步写 DB、提案状态和 `.tongyi-{planName}` 哨兵 | ✅ 已实现 | 2026-07-27 引入 |
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
### P0 规则:不可跳过
|
|
@@ -68,7 +68,7 @@ AI 助手必须先恢复到基线、找到对应的 SKILL 文件并按步骤执
|
|
|
68
68
|
| ADD-14 | `add-paradigm` Step 4 末端 + Step 8 收敛 + MCP `check_rahs` | Step 4 合规检查 / Step 8 收敛判定 |
|
|
69
69
|
| ADD-15 | `add-paradigm` Step 3.6 + MCP `check_add_route_completeness` | Step 3 代码完成后自检 |
|
|
70
70
|
| ADD-16 | `add-paradigm` Step 9 | runtime-fix plan 收敛后,关闭 gateway.md 运行时发现 |
|
|
71
|
-
| ADD-17 | `add-paradigm` 独立能力:生成 Plan / Step 0 | Plan/Review HITL
|
|
71
|
+
| ADD-17 | `add-paradigm` 独立能力:生成 Plan / Step 0 / Step 3.5 | Plan/Review HITL:整理 dimensions → create_hitl 生成提案 → update_hitl 拍板 → status_hitl 校验终态 |
|
|
72
72
|
| ADD-18 | `add-paradigm` 独立能力:生成 Plan + Step 0 + pre-tool-use §C | HITL 审批强制:create_hitl → 人工 tongyi/bohui → update_hitl 确认;hook 哨兵检查 |
|
|
73
73
|
|
|
74
74
|
---
|
|
@@ -783,45 +783,47 @@ ADD-0.1 要求"文档先行"(先改文档再改代码)。ADD-16 是对 ADD-0
|
|
|
783
783
|
|
|
784
784
|
---
|
|
785
785
|
|
|
786
|
-
## ADD-17:HITL
|
|
786
|
+
## ADD-17:HITL 提案载体与状态机
|
|
787
787
|
|
|
788
|
-
**Plan
|
|
788
|
+
**Plan、方案 Review 和实现 Review 在写入正式文件前,必须通过 `create_hitl` 建立结构化审批提案。`*.hitl.md` 与 `HitlRecord` 是同一轮审批的文件/数据库双通道载体;正式文档不得替代审批提案。**
|
|
789
789
|
|
|
790
790
|
### 流程
|
|
791
791
|
|
|
792
792
|
```
|
|
793
|
-
① AI
|
|
794
|
-
②
|
|
795
|
-
③
|
|
796
|
-
④
|
|
793
|
+
① AI 读取对应模板并将待拍板发现整理为 dimensions
|
|
794
|
+
② create_hitl({ planName, type, dimensions }) → HitlRecord(DRAFT) + plans/{YYYY-MM}/{DD}/{planName}.hitl.md
|
|
795
|
+
③ 人类审阅提案并逐项拍板 → update_hitl({ planName, type, status })
|
|
796
|
+
④ status_hitl 确认 TONGYI → 生成完整 Plan/Review 并写入正式路径
|
|
797
|
+
⑤ BOHUI → 修订 dimensions 后调用 create_hitl 创建 round+1
|
|
797
798
|
```
|
|
798
799
|
|
|
799
800
|
### 适用范围
|
|
800
801
|
|
|
801
|
-
| 文档类型 |
|
|
802
|
+
| 文档类型 | HITL type | 正式写入路径 |
|
|
802
803
|
|---------|:---:|------|
|
|
803
|
-
| Plan(标准版/精简版) |
|
|
804
|
-
| Review(方案/实现) |
|
|
805
|
-
|
|
|
806
|
-
|
|
|
804
|
+
| Plan(标准版/精简版) | `PLAN` | `{{magicDir}}/plans/{YYYY-MM}/{DD}/` |
|
|
805
|
+
| Review(方案/实现) | `PLAN_REVIEW` | `{{magicDir}}/reviews/` |
|
|
806
|
+
| Runtime Review | 不需要 | `[T]` 全部通过后直接写入 `{{magicDir}}/reviews/` |
|
|
807
|
+
| Spec / Tasks / Checklist | 不需要 | 直接写入 `{{magicDir}}/specs/` |
|
|
808
|
+
| Handoff | 不需要 | 直接写入 `{{magicDir}}/plans/` |
|
|
807
809
|
|
|
808
810
|
### 与 ADD-0.1 的关系
|
|
809
811
|
|
|
810
|
-
ADD-0.1
|
|
812
|
+
ADD-0.1 要求“文档先行”。`create_hitl` 先持久化决策维度与审批状态,再展开正式文档,使“先拍板、后展开”具备可查询、可追溯的事实源。
|
|
811
813
|
|
|
812
814
|
---
|
|
813
815
|
|
|
814
816
|
## ADD-18:HITL 人机审核强制规则
|
|
815
817
|
|
|
816
|
-
**Plan
|
|
818
|
+
**Plan、方案 Review 和实现 Review 在写入正式文件前,必须经过 HITL 审批。** 审批通过后,`update_hitl` 更新数据库与 `*.hitl.md` 状态,并在 `{{magicDir}}/hitl/` 生成 `.tongyi-{planName}` 哨兵。pre-tool-use hook 对 Plan/方案 Review 执行哨兵门禁;实现 Review 由 `add-paradigm` Step 3.5 与 `status_hitl` 门禁约束。
|
|
817
819
|
|
|
818
820
|
### 强制流程
|
|
819
821
|
|
|
820
822
|
```
|
|
821
|
-
① create_hitl({ planName, type }) → HitlRecord DRAFT,生成 hitl.md 提案文件
|
|
822
|
-
② 人类审阅 hitl.md → 逐行拍板
|
|
823
|
-
③ update_hitl({ planName, status: "TONGYI" }) →
|
|
824
|
-
或 update_hitl({ planName, status: "BOHUI", reason }) →
|
|
823
|
+
① create_hitl({ planName, type, dimensions }) → HitlRecord DRAFT,生成 *.hitl.md 提案文件
|
|
824
|
+
② 人类审阅 *.hitl.md → 逐行拍板
|
|
825
|
+
③ update_hitl({ planName, type, status: "TONGYI" }) → 更新 DB/提案并写 .tongyi-{planName} 哨兵
|
|
826
|
+
或 update_hitl({ planName, type, status: "BOHUI", reason }) → 更新 DB/提案并写 .bohui-{planName} 哨兵
|
|
825
827
|
④ TONGYI 后:正式写入 Plan/Review 文件(hook §C 放行)
|
|
826
828
|
⑤ BOHUI 后:create_hitl 新建 round+1,重新审批
|
|
827
829
|
```
|
|
@@ -830,15 +832,16 @@ ADD-0.1 要求"文档先行"——HITL 磋商本身就是文档先行的一种
|
|
|
830
832
|
|
|
831
833
|
| 文档类型 | HITL 审批 | 依据 |
|
|
832
834
|
|---------|:--------:|------|
|
|
833
|
-
| Plan | ✅ 必须 | pre-tool-use §C
|
|
834
|
-
| Review
|
|
835
|
-
| Review
|
|
835
|
+
| Plan | ✅ 必须 | pre-tool-use §C 哨兵门禁 |
|
|
836
|
+
| 方案 Review | ✅ 必须 | pre-tool-use §C 哨兵门禁 |
|
|
837
|
+
| Implementation Review | ✅ 必须 | `add-paradigm` Step 3.5 + `status_hitl` |
|
|
838
|
+
| Runtime Review | ❌ 不需要 | `[T]` 全部通过后直接生成 |
|
|
836
839
|
| Spec / Tasks / Checklist | ❌ 不需要 | 直接写 |
|
|
837
840
|
| Handoff | ❌ 不需要 | 直接写 |
|
|
838
841
|
|
|
839
842
|
### 与 ADD-17 的关系
|
|
840
843
|
|
|
841
|
-
ADD-17
|
|
844
|
+
ADD-17 定义审批提案的载体、维度和状态流转;ADD-18 定义哪些正式文档必须先取得 `TONGYI`。两者共同以 `create_hitl → update_hitl → status_hitl` 为事实链,文件、数据库和哨兵相互校验。
|
|
842
845
|
|
|
843
846
|
---
|
|
844
847
|
|
|
@@ -156,6 +156,14 @@ apply_atlas_diff() {
|
|
|
156
156
|
# ⑦ Atlas 同步主流程(探测 → dev-url → 目标 → baseline → diff → apply)
|
|
157
157
|
atlas_sync() {
|
|
158
158
|
[ "$ENGINE" = "sqlite" ] && return 0
|
|
159
|
+
# 迁移锁(进程层契约 v2 §6):多 IDE 并发 init 时仅一个进程执行迁移
|
|
160
|
+
# 非阻塞拿锁(pg_try_advisory_lock),会话级锁——脚本退出连接断开自动释放
|
|
161
|
+
LOCK_KEY="0xADD001"
|
|
162
|
+
LOCKED="$(podman exec "${PROJECT_NAME:-add-project}-postgres" psql -U "${DATABASE_USER:-admin}" -d "${PROJECT_NAME:-add-project}" -tAc "SELECT pg_try_advisory_lock(${LOCK_KEY});" 2>/dev/null || true)"
|
|
163
|
+
if [ "$LOCKED" != "t" ]; then
|
|
164
|
+
echo "!!! 另一个进程正在迁移,请稍后重试"
|
|
165
|
+
return 1
|
|
166
|
+
fi
|
|
159
167
|
if ! atlas_cmd version > /dev/null 2>&1; then
|
|
160
168
|
echo "!!! Atlas 不可用。add-coder sync --patch 可自动安装 @ariga/atlas;或手动: pnpm add -D @ariga/atlas"
|
|
161
169
|
echo " 降级路径: prisma-diff(免 shadow)→ db-push + 强制备份;文档: README「Atlas 数据库同步能力」"
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# 生成 {MAGIC_DIR}/plans/index.md 总览清单 — 按日期分层,每日自动更新
|
|
3
|
-
#
|
|
3
|
+
# MAGIC_DIR 由脚本自身的物理目录确定,各 adapter 自治。
|
|
4
4
|
set -e
|
|
5
5
|
|
|
6
|
-
# 探测 MAGIC_DIR:在当前目录向上查找包含 plans/ 的隐藏目录
|
|
7
6
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
-
|
|
9
|
-
MAGIC_DIR=""
|
|
10
|
-
while [ "$CURRENT" != "/" ]; do
|
|
11
|
-
for d in "$CURRENT"/.qoder "$CURRENT"/.claude "$CURRENT"/.vscode "$CURRENT"/.trae "$CURRENT"/.codex "$CURRENT"/.add; do
|
|
12
|
-
if [ -d "$d/plans" ]; then
|
|
13
|
-
MAGIC_DIR="$d"
|
|
14
|
-
break 2
|
|
15
|
-
fi
|
|
16
|
-
done
|
|
17
|
-
CURRENT="$(dirname "$CURRENT")"
|
|
18
|
-
done
|
|
7
|
+
MAGIC_DIR="$(dirname "$SCRIPT_DIR")"
|
|
19
8
|
|
|
20
|
-
if [ -
|
|
21
|
-
echo "❌
|
|
9
|
+
if [ ! -d "$MAGIC_DIR/plans" ]; then
|
|
10
|
+
echo "❌ 当前 adapter 不存在 plans/: $MAGIC_DIR" >&2
|
|
22
11
|
exit 1
|
|
23
12
|
fi
|
|
24
13
|
|
|
@@ -3,8 +3,10 @@ import { join } from "path"
|
|
|
3
3
|
import { existsSync } from "fs"
|
|
4
4
|
import { readFileSafe, readdirRecursive, PROJECT_ROOT, MAGIC_DIR } from "../shared/fs.js"
|
|
5
5
|
import { prisma } from "../shared/prisma.js"
|
|
6
|
+
import { getRuntimeContext } from "../shared/env.js"
|
|
6
7
|
|
|
7
8
|
export function registerHitlNotifications(server: McpServer) {
|
|
9
|
+
const runtimeContext = getRuntimeContext()
|
|
8
10
|
// ── HITL 表扫描 ──
|
|
9
11
|
const scanHitl = async () => {
|
|
10
12
|
const plansDir = join(PROJECT_ROOT, MAGIC_DIR, "plans")
|
|
@@ -29,7 +31,13 @@ export function registerHitlNotifications(server: McpServer) {
|
|
|
29
31
|
const ops = prisma.devOperation as Record<string, (...a: unknown[]) => unknown>
|
|
30
32
|
const since = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
|
31
33
|
const count = await ops.count({
|
|
32
|
-
where: {
|
|
34
|
+
where: {
|
|
35
|
+
action: "HOOK_INTERCEPT",
|
|
36
|
+
planKeyword: "no-active-plan",
|
|
37
|
+
projectKey: runtimeContext.projectKey,
|
|
38
|
+
producerAdapterKey: runtimeContext.adapterKey,
|
|
39
|
+
createdAt: { gte: since },
|
|
40
|
+
},
|
|
33
41
|
}) as number
|
|
34
42
|
if (count >= 10 && count !== lastWarnedCount) {
|
|
35
43
|
lastWarnedCount = count
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/server"
|
|
2
2
|
import { join } from "path"
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
appendFileSync,
|
|
5
|
+
closeSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
openSync,
|
|
9
|
+
readSync,
|
|
10
|
+
statSync,
|
|
11
|
+
watch,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
} from "fs"
|
|
4
14
|
import { readFile } from "fs/promises"
|
|
15
|
+
import { createHash } from "crypto"
|
|
5
16
|
import { PROJECT_ROOT, MAGIC_DIR } from "../shared/fs.js"
|
|
6
17
|
import { prisma } from "../shared/prisma.js"
|
|
18
|
+
import { getRuntimeContext } from "../shared/env.js"
|
|
7
19
|
|
|
8
20
|
// ── 类型定义 ──
|
|
9
21
|
interface HookEvent {
|
|
@@ -29,6 +41,7 @@ interface QueueState {
|
|
|
29
41
|
const REPORT_DIR = join(PROJECT_ROOT, MAGIC_DIR, "reports")
|
|
30
42
|
const JSONL_FILE = join(REPORT_DIR, "hook-events.jsonl")
|
|
31
43
|
const OVERFLOW_FILE = join(REPORT_DIR, "hook-events-overflow.jsonl")
|
|
44
|
+
const runtimeContext = getRuntimeContext()
|
|
32
45
|
|
|
33
46
|
// ── 内存缓冲队列 ──
|
|
34
47
|
const MAX_QUEUE = 50
|
|
@@ -98,6 +111,13 @@ async function flushToDB(events: HookEvent[]): Promise<number> {
|
|
|
98
111
|
const ops = prisma.devOperation as Record<string, (...a: unknown[]) => unknown>
|
|
99
112
|
const data = unique.map(e => ({
|
|
100
113
|
userId,
|
|
114
|
+
projectKey: runtimeContext.projectKey,
|
|
115
|
+
producerAdapterKey: runtimeContext.adapterKey,
|
|
116
|
+
contextId: runtimeContext.contextId,
|
|
117
|
+
toolName: "hook-event-notification",
|
|
118
|
+
operationKey: createHash("sha256")
|
|
119
|
+
.update(`${runtimeContext.contextId}\0${dedupKey(e)}\0${e.decision}\0${e.cmd}`)
|
|
120
|
+
.digest("hex"),
|
|
101
121
|
action: "HOOK_INTERCEPT",
|
|
102
122
|
targetType: e.hook,
|
|
103
123
|
targetId: e.cmd.substring(0, 500),
|
|
@@ -106,7 +126,7 @@ async function flushToDB(events: HookEvent[]): Promise<number> {
|
|
|
106
126
|
afterState: JSON.stringify({ planStatus: e.planStatus }),
|
|
107
127
|
}))
|
|
108
128
|
|
|
109
|
-
await ops.createMany({ data })
|
|
129
|
+
await ops.createMany({ data, skipDuplicates: true })
|
|
110
130
|
return unique.length
|
|
111
131
|
} catch (err) {
|
|
112
132
|
console.error("[hook-notify] flushToDB 失败:", err instanceof Error ? err.message : String(err))
|
|
@@ -125,7 +145,6 @@ async function drainOverflowFile(): Promise<HookEvent[]> {
|
|
|
125
145
|
if (ev) events.push(ev)
|
|
126
146
|
}
|
|
127
147
|
// 清空溢出文件
|
|
128
|
-
const { writeFileSync } = await import("fs")
|
|
129
148
|
writeFileSync(OVERFLOW_FILE, "", "utf-8")
|
|
130
149
|
} catch {
|
|
131
150
|
// 忽略,下次 flush 重试
|
|
@@ -145,7 +164,6 @@ async function doFlush(): Promise<void> {
|
|
|
145
164
|
|
|
146
165
|
const count = await flushToDB(allEvents)
|
|
147
166
|
if (count > 0 && serverRef) {
|
|
148
|
-
const noPlanCount = allEvents.filter(e => e.planKeyword === "no-active-plan").length
|
|
149
167
|
const msg = `[Hook] ${count} 条拦截事件已审计落库(计划: ${[...new Set(allEvents.map(e => e.planKeyword))].join(", ")})`
|
|
150
168
|
serverRef.sendLoggingMessage({ level: "warning" as const, data: msg }).catch(() => {})
|
|
151
169
|
}
|
|
@@ -156,7 +174,6 @@ function enqueue(event: HookEvent): void {
|
|
|
156
174
|
if (q.events.length >= MAX_QUEUE) {
|
|
157
175
|
// 降级写入溢出文件
|
|
158
176
|
try {
|
|
159
|
-
const { appendFileSync } = require("fs") as typeof import("fs")
|
|
160
177
|
appendFileSync(OVERFLOW_FILE, JSON.stringify(event) + "\n", "utf-8")
|
|
161
178
|
} catch { /* 静默 */ }
|
|
162
179
|
return
|
|
@@ -191,10 +208,10 @@ function readNewLines(): void {
|
|
|
191
208
|
if (st.size <= q.bytesRead) return
|
|
192
209
|
|
|
193
210
|
// 只读增量部分
|
|
194
|
-
const fd =
|
|
211
|
+
const fd = openSync(JSONL_FILE, "r")
|
|
195
212
|
const buf = Buffer.alloc(st.size - q.bytesRead)
|
|
196
|
-
|
|
197
|
-
|
|
213
|
+
readSync(fd, buf, 0, buf.length, q.bytesRead)
|
|
214
|
+
closeSync(fd)
|
|
198
215
|
|
|
199
216
|
const text = buf.toString("utf-8")
|
|
200
217
|
for (const line of text.split("\n")) {
|
|
@@ -242,7 +259,6 @@ export function registerHookNotifications(server: McpServer) {
|
|
|
242
259
|
void initialScan().then(() => {
|
|
243
260
|
// 确保 jsonl 文件存在(fs.watch 要求文件已存在)
|
|
244
261
|
try {
|
|
245
|
-
const { mkdirSync, writeFileSync } = require("fs") as typeof import("fs")
|
|
246
262
|
mkdirSync(REPORT_DIR, { recursive: true })
|
|
247
263
|
if (!existsSync(JSONL_FILE)) writeFileSync(JSONL_FILE, "", "utf-8")
|
|
248
264
|
} catch { /* ok */ }
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/server"
|
|
2
|
+
import { existsSync, readFileSync } from "fs"
|
|
3
|
+
import { join } from "path"
|
|
4
|
+
import { PROJECT_ROOT, MAGIC_DIR } from "../shared/fs.js"
|
|
5
|
+
import {
|
|
6
|
+
HITL_APPROVAL_WIDGET_FILE,
|
|
7
|
+
HITL_APPROVAL_WIDGET_MIME,
|
|
8
|
+
HITL_APPROVAL_WIDGET_URI,
|
|
9
|
+
} from "../shared/hitl-ui.js"
|
|
10
|
+
|
|
11
|
+
export function registerHitlApprovalWidgetResource(server: McpServer) {
|
|
12
|
+
server.registerResource(
|
|
13
|
+
"hitl-approval-widget",
|
|
14
|
+
HITL_APPROVAL_WIDGET_URI,
|
|
15
|
+
{
|
|
16
|
+
title: "ADD HITL Approval",
|
|
17
|
+
description: "逐项审核 ADD HITL 提案的 core 标准 widget",
|
|
18
|
+
mimeType: HITL_APPROVAL_WIDGET_MIME,
|
|
19
|
+
},
|
|
20
|
+
(uri) => {
|
|
21
|
+
const widgetPath = join(PROJECT_ROOT, MAGIC_DIR, "templates", HITL_APPROVAL_WIDGET_FILE)
|
|
22
|
+
if (!existsSync(widgetPath)) {
|
|
23
|
+
throw new Error(`HITL widget 缺失: ${widgetPath}。请重新执行 add-coder sync。`)
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
contents: [{
|
|
27
|
+
uri: uri.href,
|
|
28
|
+
mimeType: HITL_APPROVAL_WIDGET_MIME,
|
|
29
|
+
text: readFileSync(widgetPath, "utf-8"),
|
|
30
|
+
}],
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/server"
|
|
2
2
|
import { prisma } from "../shared/prisma.js"
|
|
3
|
+
import { getRuntimeContext } from "../shared/env.js"
|
|
3
4
|
|
|
4
5
|
export function registerHookEventResources(server: McpServer) {
|
|
6
|
+
const runtimeContext = getRuntimeContext()
|
|
5
7
|
|
|
6
8
|
// ── 日报 Resource ──
|
|
7
9
|
server.registerResource("hook-events-daily", "add-coder://report/hook-events/daily",
|
|
@@ -11,7 +13,12 @@ export function registerHookEventResources(server: McpServer) {
|
|
|
11
13
|
const ops = prisma.devOperation as Record<string, (...a: unknown[]) => unknown>
|
|
12
14
|
const since = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
|
13
15
|
const logs = await ops.findMany({
|
|
14
|
-
where: {
|
|
16
|
+
where: {
|
|
17
|
+
action: "HOOK_INTERCEPT",
|
|
18
|
+
projectKey: runtimeContext.projectKey,
|
|
19
|
+
producerAdapterKey: runtimeContext.adapterKey,
|
|
20
|
+
createdAt: { gte: since },
|
|
21
|
+
},
|
|
15
22
|
orderBy: { createdAt: "desc" },
|
|
16
23
|
take: 500,
|
|
17
24
|
}) as Array<Record<string, unknown>>
|
|
@@ -60,7 +67,12 @@ export function registerHookEventResources(server: McpServer) {
|
|
|
60
67
|
const ops = prisma.devOperation as Record<string, (...a: unknown[]) => unknown>
|
|
61
68
|
const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
|
|
62
69
|
const logs = await ops.findMany({
|
|
63
|
-
where: {
|
|
70
|
+
where: {
|
|
71
|
+
action: "HOOK_INTERCEPT",
|
|
72
|
+
projectKey: runtimeContext.projectKey,
|
|
73
|
+
producerAdapterKey: runtimeContext.adapterKey,
|
|
74
|
+
createdAt: { gte: since },
|
|
75
|
+
},
|
|
64
76
|
orderBy: { createdAt: "desc" },
|
|
65
77
|
take: 2000,
|
|
66
78
|
}) as Array<Record<string, unknown>>
|
|
@@ -3,10 +3,12 @@ import { registerAddStateResources } from "./add-state.js"
|
|
|
3
3
|
import { registerRoundTaskResources } from "./round-task.js"
|
|
4
4
|
import { registerVersionResource } from "./add-coder-version.js"
|
|
5
5
|
import { registerHookEventResources } from "./hook-events-report.js"
|
|
6
|
+
import { registerHitlApprovalWidgetResource } from "./hitl-approval-widget.js"
|
|
6
7
|
|
|
7
8
|
export function registerAllResources(server: McpServer) {
|
|
8
9
|
registerAddStateResources(server)
|
|
9
10
|
registerRoundTaskResources(server)
|
|
10
11
|
registerVersionResource(server)
|
|
11
12
|
registerHookEventResources(server) // 2 resources: hook-events/{daily,weekly}
|
|
13
|
+
registerHitlApprovalWidgetResource(server)
|
|
12
14
|
}
|