@ddtcorex/dsh-maestro-review 0.5.1 → 0.6.0
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/orchestrator.d.ts +10 -0
- package/lib/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator.js +17 -0
- package/lib/orchestrator.js.map +1 -1
- package/package.json +10 -9
- package/profiles/reviewer-ci/package.json +4 -4
- package/profiles/reviewer-ci/pnpm-lock.yaml +4934 -22
- package/profiles/reviewer-ci/pnpm-workspace.yaml +11 -0
- package/src/host/orchestrator.ts +18 -0
- package/templates/reviewer-project.gitlab-ci.yml +15 -12
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
# printed "Scope: all 2 workspace projects" and resolved relative to `../..`
|
|
8
8
|
# without this file present).
|
|
9
9
|
packages: []
|
|
10
|
+
# Postinstall scripts required at runtime (node-pty/subprocess-local spawn
|
|
11
|
+
# agents, koffi/protobufjs/genai serve model IO). Exact versions pinned in
|
|
12
|
+
# pnpm-lock.yaml; review on every profile dep bump.
|
|
13
|
+
allowBuilds:
|
|
14
|
+
'@deepseek-ai/dsh-subprocess-local': true
|
|
15
|
+
'@google/genai': true
|
|
16
|
+
koffi: true
|
|
17
|
+
node-pty: true
|
|
18
|
+
protobufjs: true
|
|
10
19
|
minimumReleaseAgeExclude:
|
|
11
20
|
- '@ddtcorex/dsh-maestro-review@0.3.1'
|
|
12
21
|
- '@ddtcorex/maestro-skills@2.11.0'
|
|
22
|
+
- '@ddtcorex/dsh-maestro-review@0.5.1'
|
|
23
|
+
- '@ddtcorex/maestro-skills@2.11.1'
|
package/src/host/orchestrator.ts
CHANGED
|
@@ -234,6 +234,22 @@ export function getTurnErrorMessage(handle: unknown): string | undefined {
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
/**
|
|
238
|
+
* A turn can go idle without ever calling a tool when the model provider
|
|
239
|
+
* itself rejects the request (auth/billing/rate-limit) — `whenIdleWithTimeout`
|
|
240
|
+
* only guards against a hang, not this. Left unchecked, the reviewer's
|
|
241
|
+
* missing-skill-profile check and the auditor's empty-output path both treat
|
|
242
|
+
* this the same as "the agent just didn't call anything", misreporting a
|
|
243
|
+
* provider outage as a maestro-skills installation problem (or, for the
|
|
244
|
+
* auditor, as a silent clean pass). Surface the real turn error immediately.
|
|
245
|
+
*/
|
|
246
|
+
export function assertTurnSucceeded(handle: unknown): void {
|
|
247
|
+
const turnMsg = getTurnErrorMessage(handle)
|
|
248
|
+
if (turnMsg !== undefined) {
|
|
249
|
+
throw new Error(`Review turn failed before completing: ${turnMsg}`)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
237
253
|
/**
|
|
238
254
|
* Resolve the model to use for an automated review. Priority: per-project
|
|
239
255
|
* override > global reviewModel (Maestro Settings) > row-config reviewModel
|
|
@@ -1081,6 +1097,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1081
1097
|
source: { kind: 'user' },
|
|
1082
1098
|
}))
|
|
1083
1099
|
await whenIdleWithTimeout(handle, effectiveAgentTimeoutMs)
|
|
1100
|
+
assertTurnSucceeded(handle)
|
|
1084
1101
|
if (reviewProfile !== undefined && (reviewerContext === undefined || loadedReviewProfile(reviewerContext) !== reviewProfile)) {
|
|
1085
1102
|
throw new Error(`reviewer did not successfully load the required ${reviewProfile} review skill profile; no findings were posted`)
|
|
1086
1103
|
}
|
|
@@ -1178,6 +1195,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1178
1195
|
const prompt = buildAuditorPrompt({ staticOnly: opts?.staticOnly === true })
|
|
1179
1196
|
handle.agent.followup(createUserMessage({ content: [{ type: 'text', text: prompt }], source: { kind: 'user' } }))
|
|
1180
1197
|
await whenIdleWithTimeout(handle, effectiveAgentTimeoutMs)
|
|
1198
|
+
assertTurnSucceeded(handle)
|
|
1181
1199
|
const output = auditorOutputFromSession(handle.agent.session)
|
|
1182
1200
|
const text = output.map(block => ('text' in block ? block.text : '')).join('')
|
|
1183
1201
|
return `## Maestro Performance Audit\n\n${text}`
|
|
@@ -3,7 +3,7 @@ stages: [review]
|
|
|
3
3
|
|
|
4
4
|
variables:
|
|
5
5
|
# Image registry — pin the SHA for reproducibility
|
|
6
|
-
REVIEWER_IMAGE: "ddtcorex/maestro-reviewer:
|
|
6
|
+
REVIEWER_IMAGE: "ddtcorex/maestro-reviewer:0.1.0"
|
|
7
7
|
# Or use $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA when building the image in the same project
|
|
8
8
|
|
|
9
9
|
review:
|
|
@@ -42,18 +42,21 @@ review:
|
|
|
42
42
|
# the run would "complete" without ever posting. A human-tied PAT needs yearly
|
|
43
43
|
# rotation; prefer a bot/group token where the instance allows creating one.
|
|
44
44
|
# MAESTRO_GITLAB_TOKEN (api scope) — required
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
45
|
+
# Model route selection — deepseek is the sole baked default; set
|
|
46
|
+
# REVIEW_LLM_API_KEY to overlay any OpenAI-compatible endpoint instead:
|
|
47
|
+
# DEEPSEEK_API_KEY (required unless using the route below) — deepseek-official
|
|
48
|
+
# straight from api.deepseek.com.
|
|
49
|
+
# REVIEW_LLM_API_KEY / REVIEW_LLM_BASE_URL / REVIEW_LLM_MODEL — bring-your-own
|
|
50
|
+
# OpenAI-compatible endpoint (self-hosted, Azure OpenAI, OpenRouter, a
|
|
51
|
+
# private gateway, ...). All three required together; the job fails closed
|
|
52
|
+
# if REVIEW_LLM_API_KEY is set without the other two. Optional
|
|
53
|
+
# REVIEW_LLM_API selects the wire protocol (openai-completions [default]
|
|
54
|
+
# or openai-responses).
|
|
50
55
|
# TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID (optional)
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
# REVIEW_MODEL_PROVIDER: "opencode-go" # or "deepseek-official"
|
|
56
|
-
# REVIEW_MODEL: "muse-spark-1.3-contributor" # e.g. deepseek-v4-flash (deepseek-official via zen)
|
|
56
|
+
# Model pin (optional, as a pair — unset both for the active route's default
|
|
57
|
+
# model, baked in docker/ci-settings.*.yaml):
|
|
58
|
+
# REVIEW_MODEL_PROVIDER: "deepseek-official" # or "custom-openai"
|
|
59
|
+
# REVIEW_MODEL: "deepseek-v4-flash" # the active route's model id
|
|
57
60
|
# Only the provider's key is needed — no settings mount required. ID without
|
|
58
61
|
# provider fails the review with a provider error (not silently the wrong
|
|
59
62
|
# model); provider without ID is ignored.
|