@ddtcorex/dsh-maestro-review 0.1.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.
Files changed (110) hide show
  1. package/README.md +53 -0
  2. package/client/settings-card.tsx +4 -0
  3. package/lib/config-store.d.ts +53 -0
  4. package/lib/config-store.d.ts.map +1 -0
  5. package/lib/config-store.js +60 -0
  6. package/lib/config-store.js.map +1 -0
  7. package/lib/events.d.ts +27 -0
  8. package/lib/events.d.ts.map +1 -0
  9. package/lib/events.js +2 -0
  10. package/lib/events.js.map +1 -0
  11. package/lib/gitlab-client.d.ts +14 -0
  12. package/lib/gitlab-client.d.ts.map +1 -0
  13. package/lib/gitlab-client.js +146 -0
  14. package/lib/gitlab-client.js.map +1 -0
  15. package/lib/gitlab-webhook.d.ts +17 -0
  16. package/lib/gitlab-webhook.d.ts.map +1 -0
  17. package/lib/gitlab-webhook.js +144 -0
  18. package/lib/gitlab-webhook.js.map +1 -0
  19. package/lib/govard-tool.d.ts +11 -0
  20. package/lib/govard-tool.d.ts.map +1 -0
  21. package/lib/govard-tool.js +95 -0
  22. package/lib/govard-tool.js.map +1 -0
  23. package/lib/index.d.ts +4 -0
  24. package/lib/index.d.ts.map +1 -0
  25. package/lib/index.js +15 -0
  26. package/lib/index.js.map +1 -0
  27. package/lib/notify.d.ts +23 -0
  28. package/lib/notify.d.ts.map +1 -0
  29. package/lib/notify.js +10 -0
  30. package/lib/notify.js.map +1 -0
  31. package/lib/orchestrator.d.ts +144 -0
  32. package/lib/orchestrator.d.ts.map +1 -0
  33. package/lib/orchestrator.js +655 -0
  34. package/lib/orchestrator.js.map +1 -0
  35. package/lib/pin-store.d.ts +5 -0
  36. package/lib/pin-store.d.ts.map +1 -0
  37. package/lib/pin-store.js +5 -0
  38. package/lib/pin-store.js.map +1 -0
  39. package/lib/providers/github.stub.d.ts +3 -0
  40. package/lib/providers/github.stub.d.ts.map +1 -0
  41. package/lib/providers/github.stub.js +10 -0
  42. package/lib/providers/github.stub.js.map +1 -0
  43. package/lib/providers/gitlab.d.ts +13 -0
  44. package/lib/providers/gitlab.d.ts.map +1 -0
  45. package/lib/providers/gitlab.js +173 -0
  46. package/lib/providers/gitlab.js.map +1 -0
  47. package/lib/providers/interface.d.ts +12 -0
  48. package/lib/providers/interface.d.ts.map +1 -0
  49. package/lib/providers/interface.js +2 -0
  50. package/lib/providers/interface.js.map +1 -0
  51. package/lib/review-findings-tool.d.ts +15 -0
  52. package/lib/review-findings-tool.d.ts.map +1 -0
  53. package/lib/review-findings-tool.js +37 -0
  54. package/lib/review-findings-tool.js.map +1 -0
  55. package/lib/review-history.d.ts +35 -0
  56. package/lib/review-history.d.ts.map +1 -0
  57. package/lib/review-history.js +87 -0
  58. package/lib/review-history.js.map +1 -0
  59. package/lib/review-intake.d.ts +7 -0
  60. package/lib/review-intake.d.ts.map +1 -0
  61. package/lib/review-intake.js +80 -0
  62. package/lib/review-intake.js.map +1 -0
  63. package/lib/review-signals.d.ts +17 -0
  64. package/lib/review-signals.d.ts.map +1 -0
  65. package/lib/review-signals.js +49 -0
  66. package/lib/review-signals.js.map +1 -0
  67. package/lib/secure-compare.d.ts +7 -0
  68. package/lib/secure-compare.d.ts.map +1 -0
  69. package/lib/secure-compare.js +14 -0
  70. package/lib/secure-compare.js.map +1 -0
  71. package/lib/settings-rpc.d.ts +22 -0
  72. package/lib/settings-rpc.d.ts.map +1 -0
  73. package/lib/settings-rpc.js +252 -0
  74. package/lib/settings-rpc.js.map +1 -0
  75. package/lib/skills-tool.d.ts +29 -0
  76. package/lib/skills-tool.d.ts.map +1 -0
  77. package/lib/skills-tool.js +160 -0
  78. package/lib/skills-tool.js.map +1 -0
  79. package/lib/workspace-tool.d.ts +10 -0
  80. package/lib/workspace-tool.d.ts.map +1 -0
  81. package/lib/workspace-tool.js +86 -0
  82. package/lib/workspace-tool.js.map +1 -0
  83. package/package.json +53 -0
  84. package/presets/maestro-auditor/agent.cordis.yml +10 -0
  85. package/presets/maestro-auditor/preset.yml +2 -0
  86. package/presets/maestro-coder/agent.cordis.yml +223 -0
  87. package/presets/maestro-coder/preset.yml +2 -0
  88. package/presets/maestro-reviewer/agent.cordis.yml +14 -0
  89. package/presets/maestro-reviewer/preset.yml +2 -0
  90. package/src/augment.d.ts +47 -0
  91. package/src/config-store.ts +109 -0
  92. package/src/events.ts +25 -0
  93. package/src/gitlab-client.ts +186 -0
  94. package/src/gitlab-webhook.ts +166 -0
  95. package/src/govard-tool.ts +114 -0
  96. package/src/index.ts +15 -0
  97. package/src/notify.ts +30 -0
  98. package/src/orchestrator.ts +740 -0
  99. package/src/pin-store.ts +4 -0
  100. package/src/providers/github.stub.ts +11 -0
  101. package/src/providers/gitlab.ts +190 -0
  102. package/src/providers/interface.ts +2 -0
  103. package/src/review-findings-tool.ts +51 -0
  104. package/src/review-history.ts +112 -0
  105. package/src/review-intake.ts +86 -0
  106. package/src/review-signals.ts +52 -0
  107. package/src/secure-compare.ts +13 -0
  108. package/src/settings-rpc.ts +249 -0
  109. package/src/skills-tool.ts +193 -0
  110. package/src/workspace-tool.ts +90 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tool.d.ts","sourceRoot":"","sources":["../src/workspace-tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAGxC,eAAO,MAAM,IAAI,2BAA2B,CAAA;AAC5C,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAE3B,CAAA;AAkCF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI,CAwC7D"}
@@ -0,0 +1,86 @@
1
+ import { basename, dirname, resolve, sep } from 'node:path';
2
+ import { mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
3
+ import z from '@deepseek-ai/schemastery';
4
+ import { defineTool } from '@deepseek-ai/dsh-tools';
5
+ export const name = 'maestro-workspace-tool';
6
+ export const inject = ['tools'];
7
+ export const Config = z.object({
8
+ rootPath: z.string(),
9
+ });
10
+ async function resolveInRoot(rootPath, requestedPath) {
11
+ const absoluteRoot = resolve(rootPath);
12
+ const target = resolve(absoluteRoot, requestedPath);
13
+ if (target !== absoluteRoot && !target.startsWith(absoluteRoot + sep))
14
+ return undefined;
15
+ let realRoot;
16
+ try {
17
+ realRoot = await realpath(absoluteRoot);
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ let existing = target;
23
+ const pending = [];
24
+ while (true) {
25
+ let real;
26
+ try {
27
+ real = await realpath(existing);
28
+ }
29
+ catch (err) {
30
+ if (err.code !== 'ENOENT')
31
+ return undefined;
32
+ const parent = dirname(existing);
33
+ if (parent === existing)
34
+ return undefined;
35
+ pending.unshift(basename(existing));
36
+ existing = parent;
37
+ continue;
38
+ }
39
+ const realTarget = pending.length > 0 ? resolve(real, ...pending) : real;
40
+ if (realTarget !== realRoot && !realTarget.startsWith(realRoot + sep))
41
+ return undefined;
42
+ return target;
43
+ }
44
+ }
45
+ export function apply(ctx, config = {}) {
46
+ const rootPath = config.rootPath ?? process.cwd();
47
+ ctx.tools.register(defineTool({
48
+ name: 'maestro_read_file',
49
+ description: 'Read a text file relative to the current workspace root.',
50
+ parameters: {
51
+ path: { type: 'string', required: true, description: 'Path relative to the workspace root.' },
52
+ },
53
+ output: {
54
+ schema: { type: 'object', additionalProperties: false, properties: { text: { type: 'string', required: true } } },
55
+ render: (_args, value) => [{ type: 'text', text: value.text }],
56
+ },
57
+ async execute(args) {
58
+ const target = await resolveInRoot(rootPath, args.path);
59
+ if (target === undefined)
60
+ return { isError: true, text: `Path "${args.path}" escapes the workspace root.` };
61
+ const text = await readFile(target, 'utf-8');
62
+ return { text };
63
+ },
64
+ }));
65
+ ctx.tools.register(defineTool({
66
+ name: 'maestro_write_file',
67
+ description: 'Write a text file relative to the current workspace root, creating parent directories as needed.',
68
+ parameters: {
69
+ path: { type: 'string', required: true, description: 'Path relative to the workspace root.' },
70
+ content: { type: 'string', required: true, description: 'File content to write.' },
71
+ },
72
+ output: {
73
+ schema: { type: 'object', additionalProperties: false, properties: { written: { type: 'boolean', required: true } } },
74
+ render: (args) => [{ type: 'text', text: `Wrote ${args.path}` }],
75
+ },
76
+ async execute(args) {
77
+ const target = await resolveInRoot(rootPath, args.path);
78
+ if (target === undefined)
79
+ return { isError: true, text: `Path "${args.path}" escapes the workspace root.` };
80
+ await mkdir(dirname(target), { recursive: true });
81
+ await writeFile(target, args.content, 'utf-8');
82
+ return { written: true };
83
+ },
84
+ }));
85
+ }
86
+ //# sourceMappingURL=workspace-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-tool.js","sourceRoot":"","sources":["../src/workspace-tool.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@ddtcorex/dsh-maestro-review",
3
+ "version": "0.1.0",
4
+ "description": "Maestro Review — pluggable ReviewProvider (GitLab/GitHub) + orchestrator for automated MR review",
5
+ "type": "module",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "exports": {
9
+ ".": "./lib/index.js",
10
+ "./lib/*": "./lib/*",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "files": [
14
+ "README.md",
15
+ "lib",
16
+ "src",
17
+ "presets",
18
+ "client"
19
+ ],
20
+ "peerDependencies": {
21
+ "@deepseek-ai/cordis": "^4.0.1",
22
+ "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2"
23
+ },
24
+ "dependencies": {
25
+ "@deepseek-ai/schemastery": "^3.0.0",
26
+ "@ddtcorex/dsh-maestro-config-lib": "^0.1.0"
27
+ },
28
+ "devDependencies": {
29
+ "@deepseek-ai/cordis": "^4.0.1",
30
+ "typescript": "^5.8.0",
31
+ "vitest": "^2.0.0",
32
+ "@types/node": "^22.0.0",
33
+ "@deepseek-ai/dsh-agent": "0.1.0-rc.8",
34
+ "@deepseek-ai/dsh-agent-default-model": "0.1.0-rc.8",
35
+ "@deepseek-ai/dsh-agent-presets": "0.1.0-rc.8",
36
+ "@deepseek-ai/dsh-host-apiproxy": "0.1.0-rc.8",
37
+ "@deepseek-ai/dsh-llm": "0.1.0-rc.8",
38
+ "@deepseek-ai/dsh-session": "0.1.0-rc.8",
39
+ "@deepseek-ai/dsh-session-title": "0.1.0-rc.8",
40
+ "@deepseek-ai/dsh-subagent": "0.1.0-rc.8",
41
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.8"
42
+ },
43
+ "dsh": {
44
+ "bundle": {
45
+ "patch": "./cordis.patch.yml"
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "tsc",
50
+ "test": "vitest run",
51
+ "verify": "tsc --noEmit"
52
+ }
53
+ }
@@ -0,0 +1,10 @@
1
+ - id: persona
2
+ name: '@deepseek-ai/dsh-persona'
3
+ config:
4
+ text: |
5
+ You are Maestro Auditor, a Performance Architect. Workflow:
6
+ 1. Call govard_env_up to bring up the merge request's Magento 2 environment.
7
+ 2. Call govard_shell to run the test suite (e.g. "vendor/bin/phpunit") and any profiling commands.
8
+ 3. Analyze the output for regressions, N+1 queries, or memory issues.
9
+ 4. Call govard_env_down to tear the environment down.
10
+ 5. Output a Markdown report. Do not call gitlab_post_mr_comment yourself — the orchestrator posts the combined report.
@@ -0,0 +1,2 @@
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.
@@ -0,0 +1,223 @@
1
+ # Non-persona rows below are copied from maestro-skills/.dsh-plugin/agent.cordis.yml
2
+ # (formerly agent-dev-skills), which is itself derived from DeepSeek Harness's
3
+ # `standard` preset (MIT License, Copyright (c) 2026 DeepSeek). Attribution
4
+ # retained per MIT license requirements.
5
+
6
+ - id: agent-instructions
7
+ name: '@deepseek-ai/dsh-agent-instructions'
8
+ config:
9
+ maxBytes: 65536
10
+
11
+ # ── shell ───────────────────────────────────────────────────────────────────
12
+
13
+ # `shell-env` stays in the HOST composition: it publishes host-level env vars
14
+ # before any session exists, so there is no agent to key it by. Both shell
15
+ # tools here consume the host registry; their executors (`bash-sandbox`/
16
+ # `pwsh-sandbox`) are host-plane too.
17
+ - id: tool-bash
18
+ name: '@deepseek-ai/dsh-tool-bash'
19
+ disabled: !!js process.platform === 'win32'
20
+
21
+ - id: tool-pwsh
22
+ name: '@deepseek-ai/dsh-tool-pwsh'
23
+ disabled: !!js process.platform !== 'win32'
24
+
25
+ # ── filesystem ──────────────────────────────────────────────────────────────
26
+
27
+ # Both register into the host `tools` registry and provide nothing, so
28
+ # they need no realm. The `fs` service and its policy stay in the host.
29
+ - id: tool-fs
30
+ name: '@deepseek-ai/dsh-tool-fs'
31
+
32
+ - id: tool-fs-search
33
+ name: '@deepseek-ai/dsh-tool-fs-search'
34
+ config:
35
+ sampleOverCapGlobResults: false
36
+
37
+ # ── background jobs ────────────────────────────────────────────────────────
38
+
39
+ # Only the model-facing controls. The task registry stays on the host plane
40
+ # and is keyed by owning agent, so one host instance serves every session;
41
+ # what this preset chooses is whether its agent can use `run_in_background`.
42
+ - id: tool-jobs
43
+ name: '@deepseek-ai/dsh-tool-jobs'
44
+
45
+ # ── skills ──────────────────────────────────────────────────────────────────
46
+
47
+ # The skill registry lives in the host composition and is layered per scope,
48
+ # so these rows register into this preset's layer without needing a realm.
49
+ # skill-filesystem scans ~/.dsh/skills/ by default. Install maestro-skills
50
+ # (plugin or installer) for DSH; this package's install.sh validates the Magento
51
+ # review set.
52
+ - id: skill-filesystem
53
+ name: '@deepseek-ai/dsh-skill-filesystem'
54
+
55
+ - id: tool-skill
56
+ name: '@deepseek-ai/dsh-tool-skill'
57
+
58
+ # ── goals ───────────────────────────────────────────────────────────────────
59
+
60
+ # Only the model-facing tool. The goal service, its session driver, and the
61
+ # `/goal` command stay on the host plane and are keyed by session, so what
62
+ # this preset chooses is whether its agent can call the goal tool.
63
+ - id: tool-goal
64
+ name: '@deepseek-ai/dsh-tool-goal'
65
+
66
+ # ── plan mode ───────────────────────────────────────────────────────────────
67
+
68
+ - id: planning
69
+ name: cordis:group
70
+ group: true
71
+ isolate:
72
+ planMode: true
73
+ config:
74
+ - id: plan-mode
75
+ name: '@deepseek-ai/dsh-plan-mode'
76
+ config:
77
+ section: |
78
+ You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
79
+
80
+ Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
81
+
82
+ The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
83
+
84
+ Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
85
+
86
+ Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
87
+
88
+ When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
89
+
90
+ # ── compaction ──────────────────────────────────────────────────────────────
91
+
92
+ # `compaction-basic` reads `toolResultPrune` through `ctx.get`, so the pruner
93
+ # must share this realm rather than sit outside it. `tokenMeter` is
94
+ # deliberately NOT in this realm: the meter stays on the HOST plane, keyed by
95
+ # Session, so what this preset chooses is only whether its agent compacts.
96
+ - id: compaction
97
+ name: cordis:group
98
+ group: true
99
+ isolate:
100
+ compaction: true
101
+ toolResultPruner: true
102
+ config:
103
+ - id: compaction-basic
104
+ name: '@deepseek-ai/dsh-compaction-basic'
105
+
106
+ - id: command-compact
107
+ name: '@deepseek-ai/dsh-command-compact'
108
+
109
+ - id: tool-result-pruner
110
+ name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
111
+ config:
112
+ thresholdChars: 8192
113
+ headChars: 4096
114
+ tailChars: 1024
115
+
116
+ # ── delegation and workflows ────────────────────────────────────────────────
117
+
118
+ # The `subagents` registry and its spawn/fork backends live in the HOST
119
+ # composition: it's a process singleton, and this preset contributes only the
120
+ # delegation TOOLS that resolve that registry. `workflows` is different —
121
+ # nothing outside an agent reads it — so every row reaching it shares this
122
+ # one entry-local realm.
123
+ - id: delegation
124
+ name: cordis:group
125
+ group: true
126
+ isolate:
127
+ workflowEngine: true
128
+ config:
129
+ - id: tool-subagent-control
130
+ name: '@deepseek-ai/dsh-tool-subagent-control'
131
+
132
+ - id: tool-subagent-list-agents
133
+ name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
134
+
135
+ - id: tool-subagent
136
+ name: '@deepseek-ai/dsh-tool-subagent'
137
+ config:
138
+ provider: spawn
139
+ toolName: subagent
140
+ backgroundMode: continuable
141
+
142
+ - id: tool-subagent-fork
143
+ name: '@deepseek-ai/dsh-tool-subagent'
144
+ config:
145
+ provider: fork
146
+ toolName: subagent_fork
147
+ backgroundMode: continuable
148
+
149
+ # Production dsh does not install these optional providers. Install the
150
+ # matching Bundle in this Profile and restart the Host, then copy this
151
+ # preset and remove `disabled` from the matching tool row. Host
152
+ # availability alone grants no tool.
153
+ - id: tool-subagent-codex
154
+ name: '@deepseek-ai/dsh-tool-subagent'
155
+ disabled: true
156
+ config:
157
+ provider: codex
158
+ toolName: subagent_codex
159
+ backgroundMode: one-shot
160
+ maxDepth: provider-managed
161
+
162
+ - id: tool-subagent-claude-code
163
+ name: '@deepseek-ai/dsh-tool-subagent'
164
+ disabled: true
165
+ config:
166
+ provider: claude-code
167
+ toolName: subagent_claude_code
168
+ backgroundMode: one-shot
169
+ maxDepth: provider-managed
170
+
171
+ - id: workflow-worker-thread
172
+ name: '@deepseek-ai/dsh-workflow-worker-thread'
173
+ config:
174
+ provider: spawn
175
+
176
+ - id: tool-workflow
177
+ name: '@deepseek-ai/dsh-tool-workflow'
178
+
179
+ - id: tool-ralph
180
+ name: '@deepseek-ai/dsh-tool-ralph'
181
+ config:
182
+ subagentProvider: spawn
183
+ maxRounds: 64
184
+
185
+ # ── remaining model-facing rows ─────────────────────────────────────────────
186
+
187
+ - id: tool-ask-user
188
+ name: '@deepseek-ai/dsh-tool-ask-user'
189
+
190
+ - id: tool-todo
191
+ name: '@deepseek-ai/dsh-tool-todo'
192
+ config:
193
+ allowParallelInProgress: true
194
+
195
+ - id: tool-web
196
+ name: '@deepseek-ai/dsh-tool-web'
197
+ config:
198
+ fetch: false
199
+ searchTimeoutMs: 60000
200
+
201
+ # ── maestro-coder-specific rows ─────────────────────────────────────────────
202
+
203
+ - id: persona
204
+ name: '@deepseek-ai/dsh-persona'
205
+ config:
206
+ text: |
207
+ You are Maestro Coder, a strictly-compliant Pair Programming Assistant.
208
+ MANDATORY WORKFLOW:
209
+ 1. Always call maestro_get_skills BEFORE writing code to understand the conventions.
210
+ 2. Use maestro_read_file to analyze existing project modules.
211
+ 3. Write highly optimized, clean code and save via maestro_write_file.
212
+ 4. If requested, call govard_shell to run unit tests and verify your code. Do not explain unnecessarily.
213
+
214
+ - id: skills-tool
215
+ name: '@ddtcorex/dsh-maestro-review/lib/skills-tool.js'
216
+
217
+ - id: workspace-tool
218
+ name: '@ddtcorex/dsh-maestro-govard/lib/workspace-tool.js'
219
+
220
+ - id: govard-tool
221
+ name: '@ddtcorex/dsh-maestro-govard/lib/govard-tool.js'
222
+ config:
223
+ rootPath: null
@@ -0,0 +1,2 @@
1
+ name: Maestro Coder
2
+ description: Strictly-compliant pair programming assistant. Reads project skills before writing code, edits files in the current workspace, and runs tests via Govard. Select this in the DSH Web GUI agent picker for interactive coding sessions.
@@ -0,0 +1,14 @@
1
+ - id: persona
2
+ name: '@deepseek-ai/dsh-persona'
3
+ config:
4
+ text: |
5
+ You are Maestro Reviewer, an AI Tech Lead. Workflow:
6
+ 1. Call maestro_load_review_profile with the profile named by the review request before inspecting code. It fails closed if the required skill set is incomplete.
7
+ 2. Call gitlab_list_own_review_threads to see which findings you already raised on this merge request.
8
+ 3. Call gitlab_get_mr_diff to read the current diff.
9
+ 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.
10
+ 5. For genuinely new issues with no existing thread, prepare a new inline comment (status: "new").
11
+ 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.
12
+
13
+ - id: skills-tool
14
+ name: '@ddtcorex/dsh-maestro-review/lib/skills-tool.js'
@@ -0,0 +1,2 @@
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.
@@ -0,0 +1,47 @@
1
+ import type { ModelSelection } from '@deepseek-ai/dsh-agent'
2
+
3
+ declare module '@deepseek-ai/dsh-host-webserver' {}
4
+ declare module '@deepseek-ai/dsh-client-connection' {}
5
+ declare module '@deepseek-ai/dsh-client-ui-slots' {}
6
+ declare module '@deepseek-ai/dsh-client-ui-settings' {}
7
+ declare module '@deepseek-ai/dsh-host-apiproxy/api' {
8
+ export type RpcResult<T> = { ok: true; value: T } | { ok: false; error: any }
9
+ export type RpcErrorDetailsMap = { 'bad-request': { issues: any[] } }
10
+ }
11
+ declare module '@deepseek-ai/dsh-tools' {
12
+ export function defineTool(...args: any[]): any
13
+ }
14
+
15
+ import '@deepseek-ai/cordis'
16
+
17
+ declare module '@deepseek-ai/cordis' {
18
+ interface Context {
19
+ webServer: { port: number; register: any }
20
+ connection: { rpc: { handle: (channel: string, handler: any, opts?: any) => () => void; call: any } }
21
+ maestroTunnel: {
22
+ status(): any
23
+ start(): Promise<any>
24
+ stop(): Promise<any>
25
+ proxyStatus(): any
26
+ reloadConfig(): Promise<void>
27
+ initialReady(): Promise<void>
28
+ }
29
+ logger?: {
30
+ info?: (...args: any[]) => void
31
+ warn?: (...args: any[]) => void
32
+ error?: (...args: any[]) => void
33
+ }
34
+ tools: { register: any; preExecute?: any }
35
+ agents: any
36
+ sessions: any
37
+ skills: any
38
+ /** DSH default-model service (injected by the host; structural shape only). */
39
+ agentDefaultModel: {
40
+ currentSelection(): ModelSelection
41
+ }
42
+ agentPresets: { mount(agentCtx: Context, id: string): Promise<unknown> | unknown }
43
+ sessionTitle: { rename(session: unknown, title: string): Promise<unknown> | unknown }
44
+ /** Current agent identity inside an agent-scoped context (WeakMap key). */
45
+ agent?: object
46
+ }
47
+ }
@@ -0,0 +1,109 @@
1
+ import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises'
2
+ import { homedir } from 'node:os'
3
+ import { dirname, join } from 'node:path'
4
+ import type { ReviewSkillProfile } from './skills-tool.js'
5
+ import {
6
+ RUNTIME_KEYS,
7
+ readFlat,
8
+ writeLegacyPatch,
9
+ } from '@ddtcorex/dsh-maestro-config-lib'
10
+
11
+ export interface ReviewModelSelection {
12
+ provider: string
13
+ model: string
14
+ reasoningEffort?: string
15
+ }
16
+
17
+ export interface MaestroUserConfig {
18
+ gitlabBaseUrl?: string
19
+ gitlabToken?: string
20
+ botUsername?: string
21
+ webhookSecret?: string
22
+ webhookPort?: number
23
+ projectMappings?: Array<{ projectPath: string; localRepoPath: string; reviewProfile?: ReviewSkillProfile; reviewModel?: ReviewModelSelection }>
24
+ /** Override the DSH default model for automated reviews. When absent the global DSH default is used. */
25
+ reviewModel?: ReviewModelSelection
26
+ /** Re-run a quick review whenever new commits land on a previously reviewed MR. */
27
+ autoRereviewOnPush?: boolean
28
+ /** Bound one automated review agent's turn. */
29
+ agentTimeoutMs?: number
30
+ /** Prune Maestro's own review records older than this many days (0 = keep forever). */
31
+ reviewSessionRetentionDays?: number
32
+ tunnelMode?: 'quick' | 'named'
33
+ quickTarget?: 'dsh-web' | 'webhook'
34
+ tunnelId?: string
35
+ tunnelCredentialsFile?: string
36
+ tunnelHostname?: string
37
+ proxyPort?: number
38
+ proxyHost?: string
39
+ lastTunnelRunning?: boolean
40
+ /** Gate LAN access behind a second PIN. Default false — LAN stays open. */
41
+ lanPinEnabled?: boolean
42
+ /** Telegram Bot API credentials for one-way notifications. */
43
+ telegramBotToken?: string
44
+ telegramChatId?: string
45
+ /** Also notify this chat when a review finishes. Default false. */
46
+ telegramReviewNotifications?: boolean
47
+ }
48
+
49
+ function resolveDshHome(dshHome?: string): string {
50
+ return dshHome ?? process.env.DSH_HOME ?? join(homedir(), '.dsh')
51
+ }
52
+
53
+ /**
54
+ * Settings live in the SHARED namespaced store (`~/.dsh/maestro/settings.json`,
55
+ * owned by @ddtcorex/dsh-maestro-config-lib); this store is a thin adapter that
56
+ * keeps the package's flat `MaestroUserConfig` API while delegating persistence.
57
+ * Machine runtime state (RUNTIME_KEYS) never enters settings — it stays in this
58
+ * package's own sidecar so a settings edit can never silently flip tunnel state.
59
+ */
60
+ export function configStorePath(dshHome?: string): string {
61
+ return join(resolveDshHome(dshHome), 'maestro', 'settings.json')
62
+ }
63
+
64
+ function runtimeStatePath(dshHome?: string): string {
65
+ return join(resolveDshHome(dshHome), 'dsh-maestro-review', 'runtime.json')
66
+ }
67
+
68
+ async function readRuntimeState(dshHome?: string): Promise<Record<string, unknown>> {
69
+ try {
70
+ return JSON.parse(await readFile(runtimeStatePath(dshHome), 'utf8')) as Record<string, unknown>
71
+ } catch {
72
+ return {}
73
+ }
74
+ }
75
+
76
+ async function mergeRuntimeState(
77
+ patch: Record<string, unknown>,
78
+ dshHome?: string,
79
+ ): Promise<void> {
80
+ const path = runtimeStatePath(dshHome)
81
+ const merged = { ...(await readRuntimeState(dshHome)), ...patch }
82
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 })
83
+ await writeFile(path, JSON.stringify(merged, null, 2), { encoding: 'utf-8', mode: 0o600 })
84
+ await chmod(path, 0o600)
85
+ }
86
+
87
+ export async function loadUserConfig(dshHome?: string): Promise<MaestroUserConfig> {
88
+ const [flat, runtime] = await Promise.all([
89
+ readFlat({ dshHome }),
90
+ readRuntimeState(dshHome),
91
+ ])
92
+ return { ...flat, ...runtime } as MaestroUserConfig
93
+ }
94
+
95
+ export async function saveUserConfig(patch: MaestroUserConfig, dshHome?: string): Promise<MaestroUserConfig> {
96
+ const settingsPatch: Record<string, unknown> = {}
97
+ const runtimePatch: Record<string, unknown> = {}
98
+ for (const [key, value] of Object.entries(patch)) {
99
+ if ((RUNTIME_KEYS as readonly string[]).includes(key)) runtimePatch[key] = value
100
+ else settingsPatch[key] = value
101
+ }
102
+ if (Object.keys(settingsPatch).length > 0) {
103
+ await writeLegacyPatch(settingsPatch, { dshHome })
104
+ }
105
+ if (Object.keys(runtimePatch).length > 0) {
106
+ await mergeRuntimeState(runtimePatch, dshHome)
107
+ }
108
+ return loadUserConfig(dshHome)
109
+ }
package/src/events.ts ADDED
@@ -0,0 +1,25 @@
1
+ export interface MrOpenedPayload {
2
+ projectPath: string
3
+ projectId: number
4
+ mrIid: number
5
+ sourceBranch: string
6
+ }
7
+
8
+ export type ReviewMode = 'quick' | 'deep'
9
+
10
+ export type ReviewScope =
11
+ | { kind: 'mr' }
12
+ | { kind: 'discussion'; discussionId: string; path: string; line: number }
13
+
14
+ export interface ReviewRequest extends MrOpenedPayload {
15
+ /** `push` arrives only when auto re-review on push is enabled and passes the completed-history gate. */
16
+ trigger: 'reviewer-assignment' | 'mention' | 'push'
17
+ mode: ReviewMode
18
+ scope: ReviewScope
19
+ }
20
+
21
+ declare module '@deepseek-ai/cordis' {
22
+ interface Events {
23
+ 'maestro/review-request': (payload: ReviewRequest) => void
24
+ }
25
+ }