@ddtcorex/dsh-maestro-review 0.1.1 → 0.2.1
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/lib/config-store.d.ts.map +1 -1
- package/lib/config-store.js.map +1 -1
- package/lib/events.d.ts.map +1 -1
- package/lib/events.js.map +1 -1
- package/lib/git-worktree-tool.d.ts.map +1 -1
- package/lib/git-worktree-tool.js.map +1 -1
- package/lib/gitlab-client.d.ts.map +1 -1
- package/lib/gitlab-client.js.map +1 -1
- package/lib/govard-audit-lint-tool.d.ts.map +1 -1
- package/lib/govard-audit-lint-tool.js +42 -12
- package/lib/govard-audit-lint-tool.js.map +1 -1
- package/lib/govard-tool.d.ts.map +1 -1
- package/lib/govard-tool.js.map +1 -1
- package/lib/hyva-csp-scan-tool.d.ts.map +1 -1
- package/lib/hyva-csp-scan-tool.js.map +1 -1
- package/lib/hyva-theme-inspect-tool.d.ts.map +1 -1
- package/lib/hyva-theme-inspect-tool.js.map +1 -1
- package/lib/incremental.d.ts.map +1 -1
- package/lib/incremental.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/layout-xml-tool.d.ts.map +1 -1
- package/lib/layout-xml-tool.js.map +1 -1
- package/lib/module-check-tool.d.ts.map +1 -1
- package/lib/module-check-tool.js.map +1 -1
- package/lib/notify.d.ts.map +1 -1
- package/lib/notify.js.map +1 -1
- package/lib/orchestrator.d.ts +1 -0
- package/lib/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator.js +81 -22
- package/lib/orchestrator.js.map +1 -1
- package/lib/perf-log-stats-tool.d.ts.map +1 -1
- package/lib/perf-log-stats-tool.js.map +1 -1
- package/lib/phtml-escape-scan-tool.d.ts.map +1 -1
- package/lib/phtml-escape-scan-tool.js.map +1 -1
- package/lib/plan-track-tool.d.ts.map +1 -1
- package/lib/plan-track-tool.js.map +1 -1
- package/lib/providers/github.stub.d.ts.map +1 -1
- package/lib/providers/github.stub.js.map +1 -1
- package/lib/providers/gitlab.d.ts +1 -1
- package/lib/providers/gitlab.d.ts.map +1 -1
- package/lib/providers/gitlab.js +24 -28
- package/lib/providers/gitlab.js.map +1 -1
- package/lib/providers/interface.d.ts.map +1 -1
- package/lib/providers/interface.js.map +1 -1
- package/lib/review-findings-tool.d.ts.map +1 -1
- package/lib/review-findings-tool.js.map +1 -1
- package/lib/review-history.d.ts.map +1 -1
- package/lib/review-history.js +19 -1
- package/lib/review-history.js.map +1 -1
- package/lib/review-intake.d.ts.map +1 -1
- package/lib/review-intake.js.map +1 -1
- package/lib/review-signals.d.ts.map +1 -1
- package/lib/review-signals.js.map +1 -1
- package/lib/scope-split-tool.d.ts.map +1 -1
- package/lib/scope-split-tool.js.map +1 -1
- package/lib/search-tool.d.ts.map +1 -1
- package/lib/search-tool.js.map +1 -1
- package/lib/secure-compare.d.ts.map +1 -1
- package/lib/secure-compare.js.map +1 -1
- package/lib/settings-rpc.d.ts.map +1 -1
- package/lib/settings-rpc.js.map +1 -1
- package/lib/skills-tool.d.ts +2 -2
- package/lib/skills-tool.d.ts.map +1 -1
- package/lib/skills-tool.js +17 -2
- package/lib/skills-tool.js.map +1 -1
- package/lib/tdd-evidence-tool.d.ts.map +1 -1
- package/lib/tdd-evidence-tool.js.map +1 -1
- package/lib/tool-policy.d.ts.map +1 -1
- package/lib/tool-policy.js.map +1 -1
- package/lib/workspace-tool.d.ts.map +1 -1
- package/lib/workspace-tool.js.map +1 -1
- package/package.json +3 -4
- package/src/{augment.d.ts → host/augment.d.ts} +1 -2
- package/src/{govard-audit-lint-tool.ts → host/govard-audit-lint-tool.ts} +38 -12
- package/src/{orchestrator.ts → host/orchestrator.ts} +73 -21
- package/src/{providers → host/providers}/gitlab.ts +26 -74
- package/src/{review-history.ts → host/review-history.ts} +19 -1
- package/src/{settings-rpc.ts → host/settings-rpc.ts} +1 -1
- package/src/{skills-tool.ts → host/skills-tool.ts} +18 -3
- package/lib/gitlab-webhook.d.ts +0 -17
- package/lib/gitlab-webhook.d.ts.map +0 -1
- package/lib/gitlab-webhook.js +0 -144
- package/lib/gitlab-webhook.js.map +0 -1
- package/src/gitlab-webhook.ts +0 -166
- /package/src/{config-store.ts → host/config-store.ts} +0 -0
- /package/src/{events.ts → host/events.ts} +0 -0
- /package/src/{git-worktree-tool.ts → host/git-worktree-tool.ts} +0 -0
- /package/src/{gitlab-client.ts → host/gitlab-client.ts} +0 -0
- /package/src/{govard-tool.ts → host/govard-tool.ts} +0 -0
- /package/src/{hyva-csp-scan-tool.ts → host/hyva-csp-scan-tool.ts} +0 -0
- /package/src/{hyva-theme-inspect-tool.ts → host/hyva-theme-inspect-tool.ts} +0 -0
- /package/src/{incremental.ts → host/incremental.ts} +0 -0
- /package/src/{index.ts → host/index.ts} +0 -0
- /package/src/{layout-xml-tool.ts → host/layout-xml-tool.ts} +0 -0
- /package/src/{module-check-tool.ts → host/module-check-tool.ts} +0 -0
- /package/src/{notify.ts → host/notify.ts} +0 -0
- /package/src/{perf-log-stats-tool.ts → host/perf-log-stats-tool.ts} +0 -0
- /package/src/{phtml-escape-scan-tool.ts → host/phtml-escape-scan-tool.ts} +0 -0
- /package/src/{plan-track-tool.ts → host/plan-track-tool.ts} +0 -0
- /package/src/{providers → host/providers}/github.stub.ts +0 -0
- /package/src/{providers → host/providers}/interface.ts +0 -0
- /package/src/{review-findings-tool.ts → host/review-findings-tool.ts} +0 -0
- /package/src/{review-intake.ts → host/review-intake.ts} +0 -0
- /package/src/{review-signals.ts → host/review-signals.ts} +0 -0
- /package/src/{scope-split-tool.ts → host/scope-split-tool.ts} +0 -0
- /package/src/{search-tool.ts → host/search-tool.ts} +0 -0
- /package/src/{secure-compare.ts → host/secure-compare.ts} +0 -0
- /package/src/{tdd-evidence-tool.ts → host/tdd-evidence-tool.ts} +0 -0
- /package/src/{tool-policy.ts → host/tool-policy.ts} +0 -0
- /package/src/{workspace-tool.ts → host/workspace-tool.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-tool.js","sourceRoot":"","sources":["../src/workspace-tool.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workspace-tool.js","sourceRoot":"","sources":["../src/host/workspace-tool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ddtcorex/dsh-maestro-review",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "Maestro Review — pluggable ReviewProvider (GitLab/GitHub) + orchestrator for automated MR review",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./lib/index.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
],
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
23
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2"
|
|
23
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6 || >=0.1.1-rc.0 <0.2.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@deepseek-ai/schemastery": "^3.0.0",
|
|
27
|
-
"@ddtcorex/dsh-maestro-config-lib": "^0.1.
|
|
27
|
+
"@ddtcorex/dsh-maestro-config-lib": "^0.1.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"@deepseek-ai/dsh-agent": "0.1.0-rc.8",
|
|
35
35
|
"@deepseek-ai/dsh-agent-default-model": "0.1.0-rc.8",
|
|
36
36
|
"@deepseek-ai/dsh-agent-presets": "0.1.0-rc.8",
|
|
37
|
-
"@deepseek-ai/dsh-host-apiproxy": "0.1.0-rc.8",
|
|
38
37
|
"@deepseek-ai/dsh-llm": "0.1.0-rc.8",
|
|
39
38
|
"@deepseek-ai/dsh-session": "0.1.0-rc.8",
|
|
40
39
|
"@deepseek-ai/dsh-session-title": "0.1.0-rc.8",
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { ModelSelection } from '@deepseek-ai/dsh-agent'
|
|
2
2
|
|
|
3
3
|
declare module '@deepseek-ai/dsh-host-webserver' {}
|
|
4
|
-
declare module '@deepseek-ai/dsh-client-connection' {}
|
|
5
4
|
declare module '@deepseek-ai/dsh-client-ui-slots' {}
|
|
6
5
|
declare module '@deepseek-ai/dsh-client-ui-settings' {}
|
|
7
|
-
declare module '@deepseek-ai/dsh-
|
|
6
|
+
declare module '@deepseek-ai/dsh-client-connection' {
|
|
8
7
|
export type RpcResult<T> = { ok: true; value: T } | { ok: false; error: any }
|
|
9
8
|
export type RpcErrorDetailsMap = { 'bad-request': { issues: any[] } }
|
|
10
9
|
}
|
|
@@ -40,7 +40,9 @@ async function isInsideRoot(r:string,t:string):Promise<boolean>{
|
|
|
40
40
|
export function cleanJson(raw:string):string{
|
|
41
41
|
return raw.replace(/\n\s*ERROR audit run.*$/s, '').replace(/\s{2,}ERROR audit run.*$/s, '').trimEnd()
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
// Govard 1.67 auto timeout: 90s-30m framework-aware (15m floor for wordpress/magento2 → 22.5m auto)
|
|
44
|
+
// Keep kill timeout above the largest auto value so the outer watchdog doesn't cancel a valid auto run.
|
|
45
|
+
const DEFAULT_TIMEOUT=900_000
|
|
44
46
|
|
|
45
47
|
function run(cmd:string, args:string[], cwd:string, timeoutMs:number):Promise<{code:number|null, stdout:string, stderr:string, timedOut:boolean}>{
|
|
46
48
|
return new Promise((resolvePromise)=>{
|
|
@@ -60,7 +62,7 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
60
62
|
const defaultTimeout=config.timeoutMs ?? DEFAULT_TIMEOUT
|
|
61
63
|
ctx.effect(()=>ctx.tools.register(defineTool({
|
|
62
64
|
name:'govard_audit_lint',
|
|
63
|
-
description:'Run govard audit --checks lint --format json and return structured phpcs/phpstan results. Use before hand-parsing text.',
|
|
65
|
+
description:'Run govard audit --checks lint --format json and return structured phpcs/phpstan results. Use before hand-parsing text. Govard 1.67+ uses --timeout auto (framework-aware 90s-30m, 22.5m for wordpress/magento2) by default.',
|
|
64
66
|
parameters:{
|
|
65
67
|
worktreePath:{type:'string'},
|
|
66
68
|
checks:{type:'array', items:{type:'string'}},
|
|
@@ -68,6 +70,11 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
68
70
|
phpVersions:{type:'array', items:{type:'string'}},
|
|
69
71
|
noLintResultCache:{type:'boolean'},
|
|
70
72
|
timeoutMs:{type:'number'},
|
|
73
|
+
// New in 1.67/2.7: framework-aware timeout and native lint provider
|
|
74
|
+
timeout:{type:'string', description:'Govard --timeout (e.g. auto, 300s, 15m, 0 for no timeout). Default auto.'},
|
|
75
|
+
lintProvider:{type:'string', description:'--lint-provider (govard or external). Default govard.'},
|
|
76
|
+
scope:{type:'string', enum:['project','diff']},
|
|
77
|
+
base:{type:'string', description:'--base ref for diff scope'},
|
|
71
78
|
},
|
|
72
79
|
output:{
|
|
73
80
|
schema:{
|
|
@@ -80,6 +87,10 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
80
87
|
lint:{type:'object', required:true, additionalProperties:true},
|
|
81
88
|
summary:{type:'object', required:true, additionalProperties:true},
|
|
82
89
|
rawJson:{type:'object', required:true, additionalProperties:true},
|
|
90
|
+
errors:{type:'array', items:{type:'object', additionalProperties:true}},
|
|
91
|
+
diagnostics:{type:'string'},
|
|
92
|
+
sessionId:{type:'string'},
|
|
93
|
+
runId:{type:'string'},
|
|
83
94
|
}
|
|
84
95
|
},
|
|
85
96
|
render:(_a,v:{ok:boolean})=>[{type:'text', text: v.ok? 'audit lint passed':'audit lint failed'}],
|
|
@@ -91,15 +102,28 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
91
102
|
const checkPath= rawPath ?? ''
|
|
92
103
|
if(checkPath!=='' && !(await isInsideRoot(root, checkPath))) return {text:`Path "${checkPath}" escapes the workspace root.`, truncated:false} as never
|
|
93
104
|
const timeoutMs=(args as {timeoutMs?:number}).timeoutMs ?? defaultTimeout
|
|
94
|
-
if(timeoutMs<5000 || timeoutMs>
|
|
105
|
+
if(timeoutMs<5000 || timeoutMs>1_800_000) return {text:'timeoutMs out of range 5000-1800000 (5s-30m). Use --timeout auto for framework-aware estimation.', truncated:false} as never
|
|
95
106
|
|
|
96
|
-
const
|
|
107
|
+
const a = args as {checks?:string[]; mode?:string; scope?:string; base?:string; phpVersions?:string[]; noLintResultCache?:boolean; timeout?:string; lintProvider?:string}
|
|
108
|
+
const checks = a.checks && a.checks.length ? a.checks.join(',') : 'lint'
|
|
109
|
+
const mode = a.mode ?? 'auto'
|
|
110
|
+
const scope = a.scope
|
|
111
|
+
const base = a.base
|
|
112
|
+
const phpVersionsArg = a.phpVersions
|
|
113
|
+
const noLintResultCache = a.noLintResultCache
|
|
114
|
+
const timeout = a.timeout ?? 'auto'
|
|
115
|
+
const lintProvider = a.lintProvider ?? 'govard'
|
|
116
|
+
const cliArgs=['audit','run','--checks',checks,'--format','json','--mode',mode,'--timeout',timeout,'--lint-provider',lintProvider]
|
|
117
|
+
if(scope) cliArgs.push('--scope', scope)
|
|
118
|
+
if(base) cliArgs.push('--base', base)
|
|
119
|
+
if(phpVersionsArg && phpVersionsArg.length) cliArgs.push('--php', phpVersionsArg.join(','))
|
|
120
|
+
if(noLintResultCache) cliArgs.push('--no-lint-result-cache')
|
|
97
121
|
const result=await run('govard', cliArgs, worktreePath, timeoutMs)
|
|
98
122
|
if(result.timedOut){
|
|
99
|
-
return {ok:false, exitCode:result.code, timedOut:true, worktreePath, lint:{phpcs:{violations:[]}, phpstan:{errors:[]}, pubMediaGuard:{violations:[]}}, summary:{status:null, phpVersions:[], matrixComplete:false, findingCount:0, truncated:false}, rawJson:
|
|
123
|
+
return {ok:false, exitCode: result.code ?? 124, timedOut:true, worktreePath, lint:{phpcs:{violations:[]}, phpstan:{errors:[]}, pubMediaGuard:{violations:[]}}, summary:{status:null, phpVersions:[], matrixComplete:false, findingCount:0, truncated:false}, rawJson:{}, errors:[{code:'timeout', message:`timed out after ${timeoutMs}ms` }], diagnostics:result.stderr.slice(0,4000)} as never
|
|
100
124
|
}
|
|
101
125
|
if(result.code===null && result.stderr.includes('ENOENT')){
|
|
102
|
-
return {ok:false, exitCode:
|
|
126
|
+
return {ok:false, exitCode:127, timedOut:false, worktreePath, lint:{phpcs:{violations:[]}, phpstan:{errors:[]}, pubMediaGuard:{violations:[]}}, summary:{status:null, phpVersions:[], matrixComplete:false, findingCount:0, truncated:false}, rawJson:{}, errors:[{code:'govard_not_found', message:'govard binary not found'}], diagnostics:result.stderr.slice(0,4000)} as never
|
|
103
127
|
}
|
|
104
128
|
const cleaned=cleanJson(result.stdout)
|
|
105
129
|
let parsed:any=null
|
|
@@ -113,7 +137,7 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
113
137
|
}
|
|
114
138
|
}
|
|
115
139
|
if(!parsed){
|
|
116
|
-
return {ok:false, exitCode:result.code, timedOut:false, worktreePath, lint:{phpcs:{violations:[]}, phpstan:{errors:[]}, pubMediaGuard:{violations:[]}}, summary:{status:null, phpVersions:[], matrixComplete:false, findingCount:0, truncated:false}, rawJson:
|
|
140
|
+
return {ok:false, exitCode: result.code ?? 1, timedOut:false, worktreePath, lint:{phpcs:{violations:[]}, phpstan:{errors:[]}, pubMediaGuard:{violations:[]}}, summary:{status:null, phpVersions:[], matrixComplete:false, findingCount:0, truncated:false}, rawJson:{}, errors:[{code:'parse_error', message:'stdout not JSON'}], diagnostics:(cleaned+result.stderr).slice(0,4000)} as never
|
|
117
141
|
}
|
|
118
142
|
const findings:Array<any>=parsed.findings ?? parsed.evidence?.php_results?.flatMap((r:any)=>r.findings) ?? []
|
|
119
143
|
const phpcsViolations:any[]=[]
|
|
@@ -129,18 +153,20 @@ export function apply(ctx:Context, config:{rootPath?:string, timeoutMs?:number}=
|
|
|
129
153
|
const status=parsed.status ?? (result.code===0?'passed':'failed')
|
|
130
154
|
const phpVersions=parsed.php_versions ?? parsed.phpVersions ?? []
|
|
131
155
|
const findingCount=findings.length
|
|
156
|
+
const sessionId = parsed.session_id ?? parsed.sessionId ?? undefined
|
|
157
|
+
const runId = parsed.run_id ?? parsed.runId ?? undefined
|
|
132
158
|
return {
|
|
133
159
|
ok: result.code===0,
|
|
134
|
-
exitCode: result.code,
|
|
160
|
+
exitCode: result.code ?? 0,
|
|
135
161
|
timedOut:false,
|
|
136
162
|
worktreePath,
|
|
137
|
-
sessionId
|
|
138
|
-
runId
|
|
139
|
-
rawJson: parsed,
|
|
163
|
+
...(sessionId ? { sessionId: String(sessionId) } : {}),
|
|
164
|
+
...(runId ? { runId: String(runId) } : {}),
|
|
165
|
+
rawJson: parsed as Record<string, unknown>,
|
|
140
166
|
summary:{status, phpVersions, matrixComplete:true, findingCount, truncated: findingCount>100},
|
|
141
167
|
lint:{phpcs:{violations:phpcsViolations}, phpstan:{errors:phpstanErrors}, pubMediaGuard:{violations:pubMediaViolations}},
|
|
142
168
|
errors:[],
|
|
143
|
-
diagnostics: result.stderr.slice(0,4000)
|
|
169
|
+
diagnostics: result.stderr.slice(0,4000),
|
|
144
170
|
} as never
|
|
145
171
|
}
|
|
146
172
|
})))
|
|
@@ -146,7 +146,7 @@ export const Config: z<Config> = z.object({
|
|
|
146
146
|
projectMappings: z.array(z.object({
|
|
147
147
|
projectPath: z.string().required(),
|
|
148
148
|
localRepoPath: z.string().required(),
|
|
149
|
-
reviewProfile: z.union([z.const('magento2'), z.const('generic')]).default('magento2'),
|
|
149
|
+
reviewProfile: z.union([z.const('magento2'), z.const('laravel'), z.const('symfony'), z.const('wordpress'), z.const('generic')]).default('magento2'),
|
|
150
150
|
})).required(),
|
|
151
151
|
gitlabBaseUrl: z.string().required(),
|
|
152
152
|
gitlabToken: z.string().role('secret'),
|
|
@@ -325,15 +325,22 @@ export async function postReviewFindings(findings: ReviewFinding[], config: Gitl
|
|
|
325
325
|
throw new Error(`cannot post inline finding at ${finding.path}:${finding.line}: GitLab did not return this file's complete diff`)
|
|
326
326
|
}
|
|
327
327
|
const linePosition = diffPositionForNewLine(change.diff, finding.line)
|
|
328
|
-
if (linePosition === undefined)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
328
|
+
if (linePosition === undefined) {
|
|
329
|
+
// Line not in diff — fallback to MR note so finding is not silently lost.
|
|
330
|
+
response = await fetcher(`${apiBase}/notes`, {
|
|
331
|
+
method: 'POST', headers,
|
|
332
|
+
body: JSON.stringify({ body: `**Inline fallback — \`${finding.path}:${finding.line}\` line is not in current MR diff**\n\n${finding.body}` }),
|
|
333
|
+
})
|
|
334
|
+
} else {
|
|
335
|
+
response = await fetcher(`${apiBase}/discussions`, {
|
|
336
|
+
method: 'POST', headers,
|
|
337
|
+
body: JSON.stringify({ body: finding.body, position: {
|
|
338
|
+
position_type: 'text', ...snapshot.diffRefs, old_path: change.old_path, new_path: change.new_path,
|
|
339
|
+
...linePosition.oldLine === undefined ? {} : { old_line: linePosition.oldLine },
|
|
340
|
+
...linePosition.newLine === undefined ? {} : { new_line: linePosition.newLine },
|
|
341
|
+
} }),
|
|
342
|
+
})
|
|
343
|
+
}
|
|
337
344
|
}
|
|
338
345
|
if (!response.ok) throw new Error(`GitLab API error ${response.status}: ${await response.text()}`)
|
|
339
346
|
}
|
|
@@ -490,6 +497,21 @@ function assertSafeBranchName(sourceBranch: string): void {
|
|
|
490
497
|
}
|
|
491
498
|
}
|
|
492
499
|
|
|
500
|
+
export function isBranchNotFoundError(err: unknown): boolean {
|
|
501
|
+
const rawStderr = (err as { stderr?: unknown })?.stderr
|
|
502
|
+
const rawMsg = (err as { message?: unknown })?.message
|
|
503
|
+
const toText = (v: unknown): string => {
|
|
504
|
+
if (typeof v === 'string') return v
|
|
505
|
+
if (v instanceof Uint8Array || (typeof Buffer !== 'undefined' && Buffer.isBuffer(v as unknown))) return Buffer.from(v as Uint8Array).toString('utf8')
|
|
506
|
+
if (typeof v === 'object' && v !== null && 'toString' in v) try { return String(v) } catch {}
|
|
507
|
+
return ''
|
|
508
|
+
}
|
|
509
|
+
const stderrText = toText(rawStderr)
|
|
510
|
+
const msgText = toText(rawMsg)
|
|
511
|
+
const text = stderrText !== '' ? stderrText : msgText !== '' ? msgText : String(err ?? '')
|
|
512
|
+
return text.includes("couldn't find remote ref") || text.includes('could not find remote branch') || text.includes('unknown revision or path')
|
|
513
|
+
}
|
|
514
|
+
|
|
493
515
|
/**
|
|
494
516
|
* Keep a Govard audit worktree isolated from the developer's primary checkout.
|
|
495
517
|
* Without this local override, both checkouts inherit the same `project_name`
|
|
@@ -503,7 +525,17 @@ export function govardWorktreeOverride(projectId: number, mrIid: number, keySuff
|
|
|
503
525
|
export async function ensureWorktree(localRepoPath: string, sourceBranch: string, projectId: number, mrIid: number, keySuffix?: string): Promise<string> {
|
|
504
526
|
assertSafeBranchName(sourceBranch)
|
|
505
527
|
const worktreePath = join('/tmp', `maestro-mr-${projectId}-${mrIid}${keySuffix === undefined ? '' : `-${keySuffix}`}`)
|
|
506
|
-
|
|
528
|
+
try {
|
|
529
|
+
await execFileAsync('git', ['fetch', '--', 'origin', sourceBranch], { cwd: localRepoPath, timeout: GIT_TIMEOUT_MS })
|
|
530
|
+
} catch (err) {
|
|
531
|
+
if (isBranchNotFoundError(err)) {
|
|
532
|
+
const e = new Error(`branch not found on origin: ${sourceBranch}`)
|
|
533
|
+
;(e as unknown as { code: string }).code = 'BRANCH_NOT_FOUND'
|
|
534
|
+
;(e as unknown as { cause: unknown }).cause = err
|
|
535
|
+
throw e
|
|
536
|
+
}
|
|
537
|
+
throw err
|
|
538
|
+
}
|
|
507
539
|
// A host restart can interrupt an active review before its `finally` cleanup.
|
|
508
540
|
// Recover only this deterministic Maestro-owned path so the next delivery can
|
|
509
541
|
// retry; an unrelated worktree is never targeted.
|
|
@@ -824,16 +856,36 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
824
856
|
await signals?.finish('completed')
|
|
825
857
|
return
|
|
826
858
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
859
|
+
let fullBody: string
|
|
860
|
+
try {
|
|
861
|
+
fullBody = await runReviewAndAudit(payload, {
|
|
862
|
+
localRepoPath: mapping.localRepoPath,
|
|
863
|
+
ensureWorktree,
|
|
864
|
+
removeWorktree,
|
|
865
|
+
runReviewer: (worktreePath, p) => runReviewer(worktreePath, p, resolved, mapping.reviewProfile ?? 'magento2', reviewModelSelection, incrementalBlock),
|
|
866
|
+
runAuditor: (worktreePath, p) => runAuditor(worktreePath, p, resolved, reviewModelSelection),
|
|
867
|
+
postComment,
|
|
868
|
+
replyToDiscussion,
|
|
869
|
+
writeFailedReport,
|
|
870
|
+
})
|
|
871
|
+
} catch (err) {
|
|
872
|
+
const isBranchNotFound = (err as { code?: string })?.code === 'BRANCH_NOT_FOUND' || isBranchNotFoundError(err)
|
|
873
|
+
if (isBranchNotFound) {
|
|
874
|
+
const diffBody = await runDiffOnlyReview(payload, {
|
|
875
|
+
runReviewer: (p) => runReviewer(undefined, p, resolved, undefined, reviewModelSelection, incrementalBlock),
|
|
876
|
+
postComment,
|
|
877
|
+
replyToDiscussion,
|
|
878
|
+
writeFailedReport,
|
|
879
|
+
})
|
|
880
|
+
const summary = summarize(diffBody)
|
|
881
|
+
const branchNote = `fallback diff-only: branch ${payload.sourceBranch} not found on origin — ${summary ?? ''}`.trim()
|
|
882
|
+
await recordReviewFinish(historyId, { status: 'completed', summary: branchNote })
|
|
883
|
+
notifyTelegram('completed', branchNote)
|
|
884
|
+
await signals?.finish('completed')
|
|
885
|
+
return
|
|
886
|
+
}
|
|
887
|
+
throw err
|
|
888
|
+
}
|
|
837
889
|
await recordReviewFinish(historyId, { status: 'completed', summary: summarize(fullBody) })
|
|
838
890
|
notifyTelegram('completed', summarize(fullBody))
|
|
839
891
|
await signals?.finish('completed')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis'
|
|
3
3
|
import z from '@deepseek-ai/schemastery'
|
|
4
4
|
import { loadUserConfig } from '../config-store.js'
|
|
@@ -8,15 +8,13 @@ import { routeGitlabReviewRequest } from '../review-intake.js'
|
|
|
8
8
|
import type { ReviewProvider, ReviewRequest } from './interface.js'
|
|
9
9
|
|
|
10
10
|
export const name = 'maestro-review-webhook'
|
|
11
|
+
export const inject = ['webServer'] as const
|
|
11
12
|
|
|
12
13
|
export interface Config {
|
|
13
|
-
port: number
|
|
14
14
|
botUsername?: string
|
|
15
15
|
secret?: string
|
|
16
16
|
}
|
|
17
|
-
|
|
18
17
|
export const Config: z<Config> = z.object({
|
|
19
|
-
port: z.natural().max(65535).required(),
|
|
20
18
|
botUsername: z.string(),
|
|
21
19
|
secret: z.string().role('secret'),
|
|
22
20
|
})
|
|
@@ -108,83 +106,37 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
108
106
|
const userConfig = await loadUserConfig()
|
|
109
107
|
const expected = userConfig.webhookSecret ?? config.secret
|
|
110
108
|
if (expected === undefined) {
|
|
111
|
-
if (!warnedUnconfigured) {
|
|
112
|
-
warnedUnconfigured = true
|
|
113
|
-
console.error('maestro-review-webhook: no webhook secret configured — set one in Maestro Settings or MAESTRO_GITLAB_WEBHOOK_SECRET; rejecting all requests until then')
|
|
114
|
-
}
|
|
109
|
+
if (!warnedUnconfigured) { warnedUnconfigured = true; console.error('maestro-review-webhook: no webhook secret configured — set one in Maestro Settings or MAESTRO_GITLAB_WEBHOOK_SECRET; rejecting all requests until then') }
|
|
115
110
|
return false
|
|
116
111
|
}
|
|
117
112
|
return secretsMatch(headerValue, expected)
|
|
118
113
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
res.writeHead(404).end()
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
res.writeHead(413).end()
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
if (req.url === '/hooks/gitlab-mr/trigger') {
|
|
136
|
-
let parsed: unknown
|
|
137
|
-
try {
|
|
138
|
-
parsed = JSON.parse(raw)
|
|
139
|
-
} catch {
|
|
140
|
-
res.writeHead(400).end()
|
|
141
|
-
return
|
|
142
|
-
}
|
|
143
|
-
if (!isValidMrOpenedPayload(parsed)) {
|
|
144
|
-
res.writeHead(400).end()
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
const request: OrchestratorReviewRequest = {
|
|
148
|
-
...parsed,
|
|
149
|
-
trigger: 'mention',
|
|
150
|
-
mode: 'quick',
|
|
151
|
-
scope: { kind: 'mr' },
|
|
152
|
-
}
|
|
153
|
-
ctx.emit('maestro/review-request', request)
|
|
154
|
-
res.writeHead(200).end()
|
|
155
|
-
return
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (req.url !== '/hooks/gitlab-mr') {
|
|
159
|
-
res.writeHead(404).end()
|
|
160
|
-
return
|
|
161
|
-
}
|
|
162
|
-
let body: GitlabMrWebhookBody
|
|
163
|
-
try {
|
|
164
|
-
body = JSON.parse(raw)
|
|
165
|
-
} catch {
|
|
166
|
-
res.writeHead(400).end()
|
|
167
|
-
return
|
|
114
|
+
function makeHandler(expectedPath: string) {
|
|
115
|
+
return (req: IncomingMessage, res: ServerResponse) => {
|
|
116
|
+
if (req.method !== 'POST') { res.writeHead(404).end(); return }
|
|
117
|
+
if (req.url !== expectedPath) { res.writeHead(404).end(); return }
|
|
118
|
+
void requestAuthorized(req.headers['x-gitlab-token']).then(async (authorized) => {
|
|
119
|
+
if (!authorized) { res.writeHead(401).end(); return }
|
|
120
|
+
const raw = await readBody(req)
|
|
121
|
+
if (raw === undefined) { res.writeHead(413).end(); return }
|
|
122
|
+
if (expectedPath === '/hooks/gitlab-mr/trigger') {
|
|
123
|
+
let parsed: unknown; try { parsed = JSON.parse(raw) } catch { res.writeHead(400).end(); return }
|
|
124
|
+
if (!isValidMrOpenedPayload(parsed)) { res.writeHead(400).end(); return }
|
|
125
|
+
const request: OrchestratorReviewRequest = { ...(parsed as any), trigger: 'mention', mode: 'quick', scope: { kind: 'mr' } }
|
|
126
|
+
ctx.emit('maestro/review-request', request); res.writeHead(200).end(); return
|
|
168
127
|
}
|
|
128
|
+
let body: GitlabMrWebhookBody; try { body = JSON.parse(raw) } catch { res.writeHead(400).end(); return }
|
|
169
129
|
const userConfig = await loadUserConfig()
|
|
170
|
-
if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) {
|
|
171
|
-
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
const request = routeGitlabReviewRequest(
|
|
175
|
-
body,
|
|
176
|
-
userConfig.botUsername ?? config.botUsername ?? 'maestro',
|
|
177
|
-
{ pushEnabled: userConfig.autoRereviewOnPush === true },
|
|
178
|
-
)
|
|
130
|
+
if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) { res.writeHead(400).end(); return }
|
|
131
|
+
const request = routeGitlabReviewRequest(body, userConfig.botUsername ?? config.botUsername ?? 'maestro', { pushEnabled: userConfig.autoRereviewOnPush === true })
|
|
179
132
|
if (request !== undefined) ctx.emit('maestro/review-request', request)
|
|
180
133
|
res.writeHead(200).end()
|
|
181
134
|
})
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
ctx.
|
|
188
|
-
|
|
189
|
-
}, 'gitlab-webhook teardown')
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const h1 = makeHandler('/hooks/gitlab-mr')
|
|
138
|
+
const h2 = makeHandler('/hooks/gitlab-mr/trigger')
|
|
139
|
+
const dispose1 = (ctx as any).webServer.register({ kind: 'exact', path: '/hooks/gitlab-mr', handler: h1 })
|
|
140
|
+
const dispose2 = (ctx as any).webServer.register({ kind: 'exact', path: '/hooks/gitlab-mr/trigger', handler: h2 })
|
|
141
|
+
ctx.effect(() => () => { dispose1(); dispose2() }, 'gitlab-webhook teardown')
|
|
190
142
|
}
|
|
@@ -21,6 +21,7 @@ export interface ReviewHistoryEntry {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const HISTORY_CAP = 100
|
|
24
|
+
const STALE_RUNNING_MS = 2 * 60 * 60_000 // 2h — host restart can leave running without finish
|
|
24
25
|
|
|
25
26
|
export function historyPath(dshHome?: string): string {
|
|
26
27
|
const home = dshHome ?? process.env.DSH_HOME ?? join(homedir(), '.dsh')
|
|
@@ -47,9 +48,24 @@ async function writeAll(entries: ReviewHistoryEntry[], dshHome?: string): Promis
|
|
|
47
48
|
await chmod(path, 0o600)
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
function failStaleRunning(entries: ReviewHistoryEntry[]): boolean {
|
|
52
|
+
let mutated = false
|
|
53
|
+
const now = Date.now()
|
|
54
|
+
for (const e of entries) {
|
|
55
|
+
if (e.status === 'running' && now - e.startedAt > STALE_RUNNING_MS) {
|
|
56
|
+
e.status = 'failed'
|
|
57
|
+
e.error = e.error ?? 'auto-failed: stale running review (host restart or crash)'
|
|
58
|
+
e.finishedAt = e.finishedAt ?? now
|
|
59
|
+
mutated = true
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return mutated
|
|
63
|
+
}
|
|
64
|
+
|
|
50
65
|
/** Prepend a running entry; the oldest entries fall off past `HISTORY_CAP`. */
|
|
51
66
|
export async function recordReviewStart(entry: Omit<ReviewHistoryEntry, 'status'>, dshHome?: string): Promise<void> {
|
|
52
67
|
const all = await readAll(dshHome)
|
|
68
|
+
if (failStaleRunning(all)) await writeAll(all, dshHome)
|
|
53
69
|
all.unshift({ ...entry, status: 'running' })
|
|
54
70
|
await writeAll(all.slice(0, HISTORY_CAP), dshHome)
|
|
55
71
|
}
|
|
@@ -91,9 +107,11 @@ export async function lastCompletedReview(projectId: number, mrIid: number, dshH
|
|
|
91
107
|
*/
|
|
92
108
|
export async function pruneHistory(retentionDays: number, dshHome?: string): Promise<void> {
|
|
93
109
|
if (!Number.isFinite(retentionDays) || retentionDays <= 0) return
|
|
110
|
+
const all = await readAll(dshHome)
|
|
111
|
+
failStaleRunning(all)
|
|
94
112
|
const cutoff = Date.now() - retentionDays * DAY_MS
|
|
95
113
|
const kept: ReviewHistoryEntry[] = []
|
|
96
|
-
for (const entry of
|
|
114
|
+
for (const entry of all) {
|
|
97
115
|
if ((entry.finishedAt ?? entry.startedAt) < cutoff) continue
|
|
98
116
|
kept.push(entry)
|
|
99
117
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis'
|
|
2
2
|
import type {} from '@deepseek-ai/dsh-client-connection'
|
|
3
|
-
import type { RpcErrorDetailsMap, RpcResult } from '@deepseek-ai/dsh-
|
|
3
|
+
import type { RpcErrorDetailsMap, RpcResult } from '@deepseek-ai/dsh-client-connection'
|
|
4
4
|
import { existsSync, statSync } from 'node:fs'
|
|
5
5
|
import { loadUserConfig, saveUserConfig, type MaestroUserConfig } from './config-store.js'
|
|
6
6
|
import { listReviews } from './review-history.js'
|
|
@@ -5,7 +5,7 @@ import type {} from '@deepseek-ai/dsh-agent'
|
|
|
5
5
|
export const name = 'maestro-skills-tool'
|
|
6
6
|
export const inject = ['skills', 'tools']
|
|
7
7
|
|
|
8
|
-
export type ReviewSkillProfile = 'magento2' | 'generic'
|
|
8
|
+
export type ReviewSkillProfile = 'magento2' | 'laravel' | 'symfony' | 'wordpress' | 'generic'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Exact skill names rather than a fuzzy search: a review must not silently
|
|
@@ -25,11 +25,26 @@ export const REVIEW_PROFILE_SKILLS: Record<ReviewSkillProfile, readonly string[]
|
|
|
25
25
|
'magento2-security-scan',
|
|
26
26
|
'magento2-performance-audit',
|
|
27
27
|
],
|
|
28
|
+
laravel: [
|
|
29
|
+
'govard-toolbox',
|
|
30
|
+
'govard-laravel',
|
|
31
|
+
'php-dev-core',
|
|
32
|
+
],
|
|
33
|
+
symfony: [
|
|
34
|
+
'govard-toolbox',
|
|
35
|
+
'govard-symfony',
|
|
36
|
+
'php-dev-core',
|
|
37
|
+
],
|
|
38
|
+
wordpress: [
|
|
39
|
+
'govard-toolbox',
|
|
40
|
+
'govard-wordpress',
|
|
41
|
+
'php-dev-core',
|
|
42
|
+
],
|
|
28
43
|
/** Diff review against general best practices; no project skill set required. */
|
|
29
44
|
generic: [],
|
|
30
45
|
}
|
|
31
46
|
|
|
32
|
-
export const MAESTRO_SKILLS_INSTALL_COMMAND = 'curl -fsSL https://raw.githubusercontent.com/ddtcorex/maestro-skills/master/install.sh | bash -s -- --scope personal --target dsh --skills govard-toolbox,govard-magento,magento2-dev-core,magento2-frontend-dev,magento2-hyva-dev,magento2-code-review,magento2-linter,magento2-security-scan,magento2-performance-audit -y'
|
|
47
|
+
export const MAESTRO_SKILLS_INSTALL_COMMAND = 'curl -fsSL https://raw.githubusercontent.com/ddtcorex/maestro-skills/master/install.sh | bash -s -- --scope personal --target dsh --skills govard-toolbox,govard-magento,govard-laravel,govard-symfony,govard-wordpress,php-dev-core,magento2-dev-core,magento2-frontend-dev,magento2-hyva-dev,magento2-code-review,magento2-linter,magento2-security-scan,magento2-performance-audit -y'
|
|
33
48
|
|
|
34
49
|
// This is deliberately process-local and keyed by the reviewer Agent object,
|
|
35
50
|
// which every Cordis child context inherits. Preset mounting inserts child
|
|
@@ -139,7 +154,7 @@ export function apply(ctx: Context): void {
|
|
|
139
154
|
name: 'maestro_load_review_profile',
|
|
140
155
|
description: 'Load the complete, exact skill set required for a configured review profile. Fails if any required skill is unavailable.',
|
|
141
156
|
parameters: {
|
|
142
|
-
profile: { type: 'string', required: true, description: 'Review profile configured for the project. Supported: "magento2" (full Magento skill set), "generic" (no skills required).' },
|
|
157
|
+
profile: { type: 'string', required: true, description: 'Review profile configured for the project. Supported: "magento2" (full Magento skill set), "laravel" (Govard Laravel + PHP), "symfony" (Govard Symfony + PHP), "wordpress" (Govard WordPress + PHP), "generic" (no skills required).' },
|
|
143
158
|
},
|
|
144
159
|
output: {
|
|
145
160
|
schema: {
|
package/lib/gitlab-webhook.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import z from '@deepseek-ai/schemastery';
|
|
3
|
-
export declare const name = "maestro-gitlab-webhook";
|
|
4
|
-
export interface Config {
|
|
5
|
-
port: number;
|
|
6
|
-
/** Username of the GitLab service account used for reviewer assignments. */
|
|
7
|
-
botUsername?: string;
|
|
8
|
-
/**
|
|
9
|
-
* Fallback when Maestro Settings has no webhook secret; optional so a
|
|
10
|
-
* deployment that configures everything through Settings boots without env
|
|
11
|
-
* vars. With neither source set, every request is rejected (fail closed).
|
|
12
|
-
*/
|
|
13
|
-
secret?: string;
|
|
14
|
-
}
|
|
15
|
-
export declare const Config: z<Config>;
|
|
16
|
-
export declare function apply(ctx: Context, config: Config): void;
|
|
17
|
-
//# sourceMappingURL=gitlab-webhook.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitlab-webhook.d.ts","sourceRoot":"","sources":["../src/gitlab-webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAMxC,eAAO,MAAM,IAAI,2BAA2B,CAAA;AAE5C,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAI3B,CAAA;AAkDF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAyFxD"}
|