@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.
@@ -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
- # Force the whole @deepseek-ai/dsh-* core dependency graph to one coherent
11
- # 0.1.5-rc.2 line. Bumping only dsh/dsh-base/dsh-agent-presets (the packages
12
- # this profile declares directly) left ~23 of THEIR transitive deps resolved
13
- # at the older 0.1.2-rc.1 they used to be pinned to, because nothing in the
14
- # graph forced them past whatever loose range their other consumers still
15
- # declared. The mismatch is silent at install time (a peer warning only) but
16
- # fatal at boot: a newer consumer ESM-imports a symbol the older peer's build
17
- # never exported (e.g. dsh-session-persistence-jsonl@0.1.5-rc.2 importing
18
- # SessionAlreadyExistsError from dsh-session-persistence@0.1.2-rc.1, which
19
- # doesn't have it), crashing the whole plugin tree with exit 1 — root-caused
20
- # 2026-09-14 by reproducing the crash locally (`docker run --entrypoint
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.3.1'
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` (text-only model: `modlens_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} |
@@ -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
- connection: { rpc: { handle: (channel: string, handler: any, opts?: any) => () => void; call: any } }
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
@@ -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-presets'
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
  }
@@ -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, { authority: 'loopback' })
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.8.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,2 +0,0 @@
1
- name: Maestro Auditor
2
- description: Automated Performance Architect that profiles a GitLab merge request's Magento 2 environment via Govard. Invoked programmatically by dsh-maestro-review's orchestrator — not meant for manual selection.
@@ -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
@@ -1,2 +0,0 @@
1
- name: Maestro Reviewer
2
- description: Automated AI Tech Lead that reviews a GitLab merge request's diff against project coding standards. Invoked programmatically by dsh-maestro-review's orchestrator — not meant for manual selection.