@ddtcorex/dsh-maestro-review 0.8.0 → 0.9.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/cordis.patch.yml +8 -2
- package/lib/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator.js +4 -0
- package/lib/orchestrator.js.map +1 -1
- package/lib/providers/gitlab.d.ts.map +1 -1
- package/lib/providers/gitlab.js +9 -0
- package/lib/providers/gitlab.js.map +1 -1
- package/lib/settings-rpc.js +1 -1
- package/lib/settings-rpc.js.map +1 -1
- package/package.json +21 -16
- package/presets/maestro-auditor.patch.yml +51 -0
- package/presets/maestro-reviewer.patch.yml +55 -0
- package/profiles/reviewer-ci/cordis.patch.yml +11 -6
- package/profiles/reviewer-ci/package.json +3 -3
- package/profiles/reviewer-ci/pnpm-lock.yaml +4932 -4405
- package/profiles/reviewer-ci/pnpm-workspace.yaml +17 -44
- package/skills/dsh-native-tools/SKILL.md +1 -1
- package/src/host/augment.d.ts +4 -2
- package/src/host/orchestrator.ts +8 -1
- package/src/host/providers/gitlab.ts +6 -0
- package/src/host/settings-rpc.ts +1 -1
- package/templates/reviewer-project.gitlab-ci.yml +1 -1
- package/presets/maestro-auditor/agent.cordis.yml +0 -35
- package/presets/maestro-auditor/preset.yml +0 -2
- package/presets/maestro-reviewer/agent.cordis.yml +0 -39
- package/presets/maestro-reviewer/preset.yml +0 -2
|
@@ -7,46 +7,17 @@
|
|
|
7
7
|
# printed "Scope: all 2 workspace projects" and resolved relative to `../..`
|
|
8
8
|
# without this file present).
|
|
9
9
|
packages: []
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# /entrypoint.sh` with real credentials; GITLAB_HOST must be the bare
|
|
22
|
-
# hostname, no `https://` prefix — ci-trigger.ts prepends the scheme itself).
|
|
23
|
-
# pnpm reads `overrides:` here, NOT from package.json, on pnpm 11 (see the
|
|
24
|
-
# dsh-invariants override above/below for the same gotcha in the sibling
|
|
25
|
-
# workspace). Every package below is confirmed to publish a 0.1.5-rc.2.
|
|
26
|
-
overrides:
|
|
27
|
-
'@deepseek-ai/dsh-attachment': 0.1.5-rc.2
|
|
28
|
-
'@deepseek-ai/dsh-session-persistence': 0.1.5-rc.2
|
|
29
|
-
'@deepseek-ai/dsh-fs': 0.1.5-rc.2
|
|
30
|
-
'@deepseek-ai/dsh-code-runtime': 0.1.5-rc.2
|
|
31
|
-
'@deepseek-ai/dsh-compaction': 0.1.5-rc.2
|
|
32
|
-
'@deepseek-ai/dsh-settings': 0.1.5-rc.2
|
|
33
|
-
'@deepseek-ai/dsh-hook-protocol': 0.1.5-rc.2
|
|
34
|
-
'@deepseek-ai/dsh-jobs': 0.1.5-rc.2
|
|
35
|
-
'@deepseek-ai/dsh-sandbox': 0.1.5-rc.2
|
|
36
|
-
'@deepseek-ai/dsh-session-query': 0.1.5-rc.2
|
|
37
|
-
'@deepseek-ai/dsh-util-time': 0.1.5-rc.2
|
|
38
|
-
'@deepseek-ai/dsh-shell': 0.1.5-rc.2
|
|
39
|
-
'@deepseek-ai/dsh-sdk-protocol': 0.1.5-rc.2
|
|
40
|
-
'@deepseek-ai/dsh-anonymous-user-id': 0.1.5-rc.2
|
|
41
|
-
'@deepseek-ai/dsh-output-retention': 0.1.5-rc.2
|
|
42
|
-
'@deepseek-ai/dsh-spill': 0.1.5-rc.2
|
|
43
|
-
'@deepseek-ai/dsh-workflow': 0.1.5-rc.2
|
|
44
|
-
'@deepseek-ai/dsh-util-workspace-path': 0.1.5-rc.2
|
|
45
|
-
'@deepseek-ai/dsh-bash-local': 0.1.5-rc.2
|
|
46
|
-
'@deepseek-ai/dsh-authorization': 0.1.5-rc.2
|
|
47
|
-
'@deepseek-ai/dsh-session-telemetry': 0.1.5-rc.2
|
|
48
|
-
'@deepseek-ai/dsh-session-title-llm': 0.1.5-rc.2
|
|
49
|
-
'@deepseek-ai/dsh-subagent-in-process-driver': 0.1.5-rc.2
|
|
10
|
+
# No `overrides:` block on the 0.1.7-rc.1 line, deliberately. The 0.1.5-rc.2
|
|
11
|
+
# profile needed one because those packages declared loose ranges, so ~23 of
|
|
12
|
+
# their transitive deps resolved back to the older 0.1.2-rc.1 — silent at
|
|
13
|
+
# install time (a peer warning only), fatal at boot: a newer consumer
|
|
14
|
+
# ESM-imported a symbol the older peer's build never exported (e.g.
|
|
15
|
+
# dsh-session-persistence-jsonl@0.1.5-rc.2 importing SessionAlreadyExistsError
|
|
16
|
+
# from dsh-session-persistence@0.1.2-rc.1), crashing the whole plugin tree with
|
|
17
|
+
# exit 1. Every `@deepseek-ai/dsh-*` package on the alpha.2 line pins its own
|
|
18
|
+
# graph exactly, so the same install needs no forcing (verified 2026-09-23:
|
|
19
|
+
# 281 @deepseek-ai packages installed, zero duplicate package names, one
|
|
20
|
+
# cordis@4.0.4 that satisfies the plugin's `~4.0.4` peer).
|
|
50
21
|
# Postinstall scripts required at runtime (node-pty/subprocess-local spawn
|
|
51
22
|
# agents, koffi/protobufjs/genai serve model IO). Exact versions pinned in
|
|
52
23
|
# pnpm-lock.yaml; review on every profile dep bump.
|
|
@@ -56,8 +27,10 @@ allowBuilds:
|
|
|
56
27
|
koffi: true
|
|
57
28
|
node-pty: true
|
|
58
29
|
protobufjs: true
|
|
30
|
+
# pnpm keeps only the FIRST entry per package name, so bumping our own
|
|
31
|
+
# release means REPLACING its entry — appending the newer version leaves it
|
|
32
|
+
# shadowed by the stale one and the 24h age gate keeps rejecting it (observed
|
|
33
|
+
# 2026-09-18). The Docker build additionally passes
|
|
34
|
+
# --config.minimumReleaseAge=0.
|
|
59
35
|
minimumReleaseAgeExclude:
|
|
60
|
-
- '@ddtcorex/dsh-maestro-review@0.
|
|
61
|
-
- '@ddtcorex/maestro-skills@2.11.0'
|
|
62
|
-
- '@ddtcorex/dsh-maestro-review@0.5.1'
|
|
63
|
-
- '@ddtcorex/maestro-skills@2.11.1'
|
|
36
|
+
- '@ddtcorex/dsh-maestro-review@0.8.1'
|
|
@@ -35,7 +35,7 @@ harness-neutral words — announce, dispatch a subagent, ask your partner. On DS
|
|
|
35
35
|
| Write / edit files | `write`, `edit` (read before edit) |
|
|
36
36
|
| Run shell commands, tests, git | `bash`; background via `run_in_background: true`, collect with `job_output`, stop with `job_kill` |
|
|
37
37
|
| Search the web | `web_search` |
|
|
38
|
-
| Look at an image file | `read_image`
|
|
38
|
+
| Look at an image file | `read_image` |
|
|
39
39
|
| Ensure an isolated workspace | `git_worktree {op:'inspect', worktreePath}` → {exists,branch,headSha,isClean,isWorktree} (`worktreePath` is required on every op) |
|
|
40
40
|
| Create a worktree | `git_worktree {op:'create', worktreePath, branch, base?}` → {created,headSha} |
|
|
41
41
|
| Clean up a worktree | `git_worktree {op:'remove', worktreePath}` → {removed,dirtyFiles} |
|
package/src/host/augment.d.ts
CHANGED
|
@@ -16,7 +16,10 @@ import '@deepseek-ai/cordis'
|
|
|
16
16
|
declare module '@deepseek-ai/cordis' {
|
|
17
17
|
interface Context {
|
|
18
18
|
webServer: { port: number; register: any }
|
|
19
|
-
|
|
19
|
+
// `handle` takes exactly (channel, handler): the Host never read an
|
|
20
|
+
// `{ authority: 'loopback' }` third argument, so this shape must not
|
|
21
|
+
// advertise one (dropped at the call site in #129).
|
|
22
|
+
connection: { rpc: { handle: (channel: string, handler: any) => () => void; call: any } }
|
|
20
23
|
maestroTunnel: {
|
|
21
24
|
status(): any
|
|
22
25
|
start(): Promise<any>
|
|
@@ -42,7 +45,6 @@ declare module '@deepseek-ai/cordis' {
|
|
|
42
45
|
agentDefaultModel: {
|
|
43
46
|
currentSelection(): ModelSelection
|
|
44
47
|
}
|
|
45
|
-
agentPresets: { mount(agentCtx: Context, id: string): Promise<unknown> | unknown }
|
|
46
48
|
sessionTitle: { rename(session: unknown, title: string): Promise<unknown> | unknown }
|
|
47
49
|
/** Current agent identity inside an agent-scoped context (WeakMap key). */
|
|
48
50
|
agent?: object
|
package/src/host/orchestrator.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { finalAssistantOutput } from '@deepseek-ai/dsh-subagent'
|
|
|
13
13
|
import type { AgentHandle } from '@deepseek-ai/dsh-agent'
|
|
14
14
|
import { installModelSelection } from '@deepseek-ai/dsh-agent'
|
|
15
15
|
import type { ModelSelection } from '@deepseek-ai/dsh-agent'
|
|
16
|
-
import type {} from '@deepseek-ai/dsh-agent-
|
|
16
|
+
import type {} from '@deepseek-ai/dsh-agent-preset-registry'
|
|
17
17
|
import type {} from '@deepseek-ai/dsh-agent-default-model'
|
|
18
18
|
import type {} from '@deepseek-ai/dsh-session-title'
|
|
19
19
|
import * as GovardTool from './govard-tool.js'
|
|
@@ -1394,6 +1394,13 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1394
1394
|
if (!result.sent && result.reason === 'request-failed') {
|
|
1395
1395
|
console.error(`maestro-orchestrator: Telegram review notification for MR !${String(payload.mrIid)} failed to deliver`)
|
|
1396
1396
|
}
|
|
1397
|
+
}).catch((err) => {
|
|
1398
|
+
// Delivery is fire-and-forget: a rejection must not escape into the
|
|
1399
|
+
// host's unhandled-rejection path, which exits the whole process.
|
|
1400
|
+
console.error(
|
|
1401
|
+
`maestro-orchestrator: Telegram review notification for MR !${String(payload.mrIid)} threw:`,
|
|
1402
|
+
err instanceof Error ? err.message : err,
|
|
1403
|
+
)
|
|
1397
1404
|
})
|
|
1398
1405
|
}
|
|
1399
1406
|
/** First line + bounded excerpt of a posted report, for the history log.
|
|
@@ -146,6 +146,12 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
146
146
|
ctx.emit('maestro/review-request', request)
|
|
147
147
|
}
|
|
148
148
|
res.writeHead(200).end()
|
|
149
|
+
}).catch((err) => {
|
|
150
|
+
// The handler runs detached from the server's request callback: an
|
|
151
|
+
// escaping rejection reaches the host's unhandled-rejection path and
|
|
152
|
+
// exits the process, so answer 500 and keep the webhook alive.
|
|
153
|
+
console.error('maestro-review-webhook: handler failed:', err instanceof Error ? err.message : err)
|
|
154
|
+
try { res.writeHead(500).end() } catch { /* the response was already sent */ }
|
|
149
155
|
})
|
|
150
156
|
}
|
|
151
157
|
}
|
package/src/host/settings-rpc.ts
CHANGED
|
@@ -288,7 +288,7 @@ export function apply(ctx: Context): void {
|
|
|
288
288
|
}
|
|
289
289
|
return fail(`Unknown endpoint: ${endpoint}`)
|
|
290
290
|
}
|
|
291
|
-
const disposeRpc = ctx.connection.rpc.handle(MAESTRO_RPC_CHANNEL, handler
|
|
291
|
+
const disposeRpc = ctx.connection.rpc.handle(MAESTRO_RPC_CHANNEL, handler)
|
|
292
292
|
|
|
293
293
|
ctx.effect(() => () => { disposeRpc(); }, 'maestro-settings-rpc teardown')
|
|
294
294
|
}
|
|
@@ -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:0.
|
|
6
|
+
REVIEWER_IMAGE: "ddtcorex/maestro-reviewer:0.9.0"
|
|
7
7
|
# Or use $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA when building the image in the same project
|
|
8
8
|
|
|
9
9
|
review:
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
- id: persona
|
|
2
|
-
name: '@deepseek-ai/dsh-persona'
|
|
3
|
-
config:
|
|
4
|
-
# The working directory varies per session, so it belongs in the suffix: the
|
|
5
|
-
# prefix is the model-stable part of the prompt that stays cacheable. The row
|
|
6
|
-
# must restate the suffix because an empty one shadows the deployment's away.
|
|
7
|
-
suffix: Your working directory is {{cwd}}.
|
|
8
|
-
prefix: |
|
|
9
|
-
You are Maestro Auditor, a Performance Architect. Workflow:
|
|
10
|
-
1. Call govard_env_up to bring up the merge request's Magento 2 environment.
|
|
11
|
-
2. Call govard_shell to run the test suite (e.g. "vendor/bin/phpunit") and any profiling commands.
|
|
12
|
-
3. Analyze the output for regressions, N+1 queries, or memory issues.
|
|
13
|
-
4. Call govard_env_down to tear the environment down.
|
|
14
|
-
5. Output a Markdown report. Do not call gitlab_post_mr_comment yourself — the orchestrator posts the combined report.
|
|
15
|
-
|
|
16
|
-
# Delegation tools: the providers live in the Profile
|
|
17
|
-
# (`subagent-codex` + `subagent-claude-code` rows), so a deployment without
|
|
18
|
-
# those bundles gets inert rows — `tool-subagent` registers no tool until its
|
|
19
|
-
# provider appears — rather than a failed mount. One-shot rows: a review
|
|
20
|
-
# delegates a bounded task and collects the result.
|
|
21
|
-
- id: tool-subagent-codex
|
|
22
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
23
|
-
config:
|
|
24
|
-
provider: codex
|
|
25
|
-
toolName: subagent_codex
|
|
26
|
-
backgroundMode: one-shot
|
|
27
|
-
maxDepth: provider-managed
|
|
28
|
-
|
|
29
|
-
- id: tool-subagent-claude-code
|
|
30
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
31
|
-
config:
|
|
32
|
-
provider: claude-code
|
|
33
|
-
toolName: subagent_claude_code
|
|
34
|
-
backgroundMode: one-shot
|
|
35
|
-
maxDepth: provider-managed
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
- id: persona
|
|
2
|
-
name: '@deepseek-ai/dsh-persona'
|
|
3
|
-
config:
|
|
4
|
-
# The working directory varies per session, so it belongs in the suffix: the
|
|
5
|
-
# prefix is the model-stable part of the prompt that stays cacheable. The row
|
|
6
|
-
# must restate the suffix because an empty one shadows the deployment's away.
|
|
7
|
-
suffix: Your working directory is {{cwd}}.
|
|
8
|
-
prefix: |
|
|
9
|
-
You are Maestro Reviewer, an AI Tech Lead. Workflow:
|
|
10
|
-
1. If the review request names a profile, call maestro_load_review_profile with that profile before inspecting code — it fails closed if the required skill set is incomplete. For a diff-only review with no local checkout or Magento environment, skip this step: there is no profile to load, and the diff is all the context you need.
|
|
11
|
-
2. Call gitlab_list_own_review_threads to see which findings you already raised on this merge request.
|
|
12
|
-
3. Call gitlab_get_mr_diff to read the current diff.
|
|
13
|
-
4. For each existing thread whose file/line was touched by the new commits, decide whether it still applies, looks fixed, or needs a different comment — reply to it (status: "reply"). Never resolve a thread yourself.
|
|
14
|
-
5. For genuinely new issues with no existing thread, prepare a new inline comment (status: "new").
|
|
15
|
-
6. Call report_review_findings exactly once with your complete list of findings, then stop. Do not call gitlab_post_mr_comment, gitlab_post_inline_comment, or gitlab_reply_to_thread yourself — the orchestrator posts them from your report_review_findings call.
|
|
16
|
-
|
|
17
|
-
- id: skills-tool
|
|
18
|
-
name: '@ddtcorex/dsh-maestro-review/lib/skills-tool.js'
|
|
19
|
-
|
|
20
|
-
# Delegation tools: the providers live in the Profile
|
|
21
|
-
# (`subagent-codex` + `subagent-claude-code` rows), so a deployment without
|
|
22
|
-
# those bundles gets inert rows — `tool-subagent` registers no tool until its
|
|
23
|
-
# provider appears — rather than a failed mount. One-shot rows: a review
|
|
24
|
-
# delegates a bounded task and collects the result.
|
|
25
|
-
- id: tool-subagent-codex
|
|
26
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
27
|
-
config:
|
|
28
|
-
provider: codex
|
|
29
|
-
toolName: subagent_codex
|
|
30
|
-
backgroundMode: one-shot
|
|
31
|
-
maxDepth: provider-managed
|
|
32
|
-
|
|
33
|
-
- id: tool-subagent-claude-code
|
|
34
|
-
name: '@deepseek-ai/dsh-tool-subagent'
|
|
35
|
-
config:
|
|
36
|
-
provider: claude-code
|
|
37
|
-
toolName: subagent_claude_code
|
|
38
|
-
backgroundMode: one-shot
|
|
39
|
-
maxDepth: provider-managed
|