@ddtcorex/dsh-maestro-review 0.10.0 → 0.11.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.
Files changed (77) hide show
  1. package/README.md +10 -8
  2. package/cordis.patch.yml +4 -4
  3. package/lib/client.js +493 -0
  4. package/lib/config-store.d.ts +1 -1
  5. package/lib/config-store.d.ts.map +1 -1
  6. package/lib/config-store.js +43 -3
  7. package/lib/config-store.js.map +1 -1
  8. package/lib/govard-lint-detection.d.ts +20 -0
  9. package/lib/govard-lint-detection.d.ts.map +1 -0
  10. package/lib/govard-lint-detection.js +48 -0
  11. package/lib/govard-lint-detection.js.map +1 -0
  12. package/lib/orchestrator.d.ts +45 -9
  13. package/lib/orchestrator.d.ts.map +1 -1
  14. package/lib/orchestrator.js +79 -22
  15. package/lib/orchestrator.js.map +1 -1
  16. package/lib/search-tool.d.ts.map +1 -1
  17. package/lib/search-tool.js.map +1 -1
  18. package/lib/settings-rpc.d.ts +13 -11
  19. package/lib/settings-rpc.d.ts.map +1 -1
  20. package/lib/settings-rpc.js +45 -142
  21. package/lib/settings-rpc.js.map +1 -1
  22. package/lib/types/client/BrandMark.d.ts +22 -0
  23. package/lib/types/client/BrandMark.d.ts.map +1 -0
  24. package/lib/types/client/index.d.ts +12 -0
  25. package/lib/types/client/index.d.ts.map +1 -0
  26. package/lib/types/client/maestro-mark.d.ts +20 -0
  27. package/lib/types/client/maestro-mark.d.ts.map +1 -0
  28. package/lib/types/client/review/ReviewSettings.d.ts +15 -0
  29. package/lib/types/client/review/ReviewSettings.d.ts.map +1 -0
  30. package/lib/types/client/review/styles.d.ts +11 -0
  31. package/lib/types/client/review/styles.d.ts.map +1 -0
  32. package/lib/types/client/settings-nav-icon.d.ts +20 -0
  33. package/lib/types/client/settings-nav-icon.d.ts.map +1 -0
  34. package/lib/vendor/store.d.ts +60 -0
  35. package/lib/vendor/store.d.ts.map +1 -0
  36. package/lib/vendor/store.js +500 -0
  37. package/lib/vendor/store.js.map +1 -0
  38. package/lib/webhook-secret.d.ts +31 -0
  39. package/lib/webhook-secret.d.ts.map +1 -0
  40. package/lib/webhook-secret.js +38 -0
  41. package/lib/webhook-secret.js.map +1 -0
  42. package/package.json +24 -6
  43. package/presets/maestro-auditor.patch.yml +7 -4
  44. package/presets/maestro-coder/agent.cordis.yml +3 -11
  45. package/presets/maestro-coder/preset.yml +1 -1
  46. package/profiles/reviewer-ci/cordis.patch.yml +5 -4
  47. package/profiles/reviewer-ci/package.json +3 -3
  48. package/profiles/reviewer-ci/pnpm-lock.yaml +3524 -3239
  49. package/skills/dsh-native-tools/SKILL.md +5 -5
  50. package/src/client/BrandMark.tsx +42 -0
  51. package/src/client/index.tsx +109 -0
  52. package/src/client/maestro-mark.ts +21 -0
  53. package/src/client/review/ReviewSettings.tsx +236 -0
  54. package/src/client/review/styles.ts +117 -0
  55. package/src/client/settings-nav-icon.ts +68 -0
  56. package/src/host/config-store.ts +42 -3
  57. package/src/host/govard-lint-detection.ts +47 -0
  58. package/src/host/orchestrator.ts +95 -23
  59. package/src/host/search-tool.ts +3 -4
  60. package/src/host/settings-rpc.ts +48 -145
  61. package/src/host/vendor/store.ts +531 -0
  62. package/src/host/webhook-secret.ts +43 -0
  63. package/lib/govard-audit-lint-tool.d.ts +0 -95
  64. package/lib/govard-audit-lint-tool.d.ts.map +0 -1
  65. package/lib/govard-audit-lint-tool.js +0 -286
  66. package/lib/govard-audit-lint-tool.js.map +0 -1
  67. package/lib/govard-tool.d.ts +0 -11
  68. package/lib/govard-tool.d.ts.map +0 -1
  69. package/lib/govard-tool.js +0 -95
  70. package/lib/govard-tool.js.map +0 -1
  71. package/lib/workspace-tool.d.ts +0 -10
  72. package/lib/workspace-tool.d.ts.map +0 -1
  73. package/lib/workspace-tool.js +0 -92
  74. package/lib/workspace-tool.js.map +0 -1
  75. package/src/host/govard-audit-lint-tool.ts +0 -286
  76. package/src/host/govard-tool.ts +0 -114
  77. package/src/host/workspace-tool.ts +0 -108
package/README.md CHANGED
@@ -6,8 +6,9 @@ child agents on fresh worktrees, webhook intake for GitLab events, and a setting
6
6
  client UI injected into the DSH Web slots.
7
7
 
8
8
  Part of the Maestro Harness suite (`dsh-maestro-*`). Cordis patch rows:
9
- `maestro-review-webhook` (intake), `maestro-review-orchestrator` (pipeline),
10
- `maestro-review-settings-rpc` (settings UI) — all served by this npm package.
9
+ `maestro-review-host` (package root, bundled skills), `maestro-review-webhook` (intake),
10
+ `maestro-review-orchestrator` (pipeline), `maestro-review-settings-rpc` (settings UI),
11
+ all served by this npm package.
11
12
 
12
13
  ## What it provides
13
14
 
@@ -16,9 +17,9 @@ Part of the Maestro Harness suite (`dsh-maestro-*`). Cordis patch rows:
16
17
  - **Orchestrator** — reviewer + auditor agent runs against a disposable worktree of the MR,
17
18
  model selection overridable globally (`reviewModel`) and per project mapping.
18
19
  - **Webhook intake** — receives GitLab MR events, enqueues reviews (dedup + retention).
19
- - **Review findings/history/signals** — findings written through the `review-findings`
20
+ - **Review findings/history/signals**: findings written through the `report_review_findings`
20
21
  tool by tool-only review subagents (never free text); history + signals tracked per MR.
21
- - **Govard/workspace tooling** available inside review runs.
22
+ - **Review tools** (workspace search, Magento/Hyva scans, query-log stats, GitLab diff tools) mounted into review runs.
22
23
  - **Client half** — settings section rendered into DSH Web slots; notification copy stays
23
24
  here, delivery goes through the optional `maestroNotifier` service.
24
25
 
@@ -38,8 +39,10 @@ Templates live in `templates/`, the image in `docker/`.
38
39
  ## Settings
39
40
 
40
41
  Reads its configuration through the **shared namespaced settings store**
41
- (`~/.dsh/maestro/settings.json`, owned by `@ddtcorex/dsh-maestro-config-lib`) via the flat
42
- adapter in `src/config-store.ts`; machine runtime state stays in a package-local sidecar.
42
+ (`~/.dsh/dsh-maestro-config/settings.json`) via the flat adapter in
43
+ `src/host/config-store.ts`, over the embedded store copy `src/host/vendor/store.ts`
44
+ (generated from `dsh-maestro-core`, no runtime dependency); machine runtime state stays in a
45
+ package-local sidecar.
43
46
 
44
47
  ## Install
45
48
 
@@ -53,8 +56,7 @@ dsh plugin --profile web add @ddtcorex/dsh-maestro-review
53
56
  pnpm install
54
57
  pnpm verify # tsc --noEmit
55
58
  pnpm test # vitest run
56
- pnpm build # tsc -> lib/
57
- pnpm run build:client # browser bundle -> lib/client.js (required after client changes)
59
+ pnpm build # tsc -> lib/, plus the browser bundle lib/client.js
58
60
  ```
59
61
 
60
62
  See AGENTS.md for conventions (host/client split, secrets handling, live-validation rules).
package/cordis.patch.yml CHANGED
@@ -1,6 +1,6 @@
1
- # dsh-maestro-review bundle patch — 4 rows as spec §4
2
- # RPC channel: /dsh-maestro-review (loopback, see src/index.ts + src/settings-rpc.ts)
3
- # channel: /dsh-maestro-review
1
+ # dsh-maestro-review bundle patch: 4 rows, maestro-review-host, maestro-review-webhook,
2
+ # maestro-review-orchestrator, maestro-review-settings-rpc
3
+ # RPC channel: /dsh-maestro-review (see src/host/settings-rpc.ts)
4
4
  - insert:
5
5
  # Mounts the package root (lib/index.js -> apply()). Required: `dsh plugin add`
6
6
  # applies ONLY the rows in this file, so without it the skill-provider
@@ -32,4 +32,4 @@
32
32
  # rpc.handle registers a webServer route inside an effect fiber which carries only the row's inject (not the module's);
33
33
  # without webServer the row fails on harnesses that provide webServer after rows apply
34
34
  # (DSH 0.1.5-rc.1+).
35
- inject: ['connection', 'maestroTunnel', 'webServer']
35
+ inject: ['connection', 'webServer']
package/lib/client.js ADDED
@@ -0,0 +1,493 @@
1
+ window.__ModuleLoader__.load({
2
+ id: '@ddtcorex/dsh-maestro-review',
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ var React = require("react");
7
+ "use strict";
8
+ var __create = Object.create;
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __getProtoOf = Object.getPrototypeOf;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
27
+ // If the importer is in node compatibility mode or this is not an ESM
28
+ // file that has been converted to a CommonJS file using a Babel-
29
+ // compatible transform (i.e. "__esModule" has not been set), then set
30
+ // "default" to the CommonJS "module.exports" for node compatibility.
31
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32
+ mod
33
+ ));
34
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
+
36
+ // src/client/index.tsx
37
+ var index_exports = {};
38
+ __export(index_exports, {
39
+ REVIEW_CHANNEL: () => REVIEW_CHANNEL,
40
+ apply: () => apply,
41
+ default: () => index_default,
42
+ inject: () => inject,
43
+ makeRpcCall: () => makeRpcCall
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+ var React2 = __toESM(require("react"), 1);
47
+
48
+ // src/client/review/ReviewSettings.tsx
49
+ var React = __toESM(require("react"), 1);
50
+
51
+ // src/client/BrandMark.tsx
52
+ var import_react = require("react");
53
+
54
+ // src/client/maestro-mark.ts
55
+ var MAESTRO_MARK_PATH = "M2 11 L5 4 L8 9 L11 4 L14 11";
56
+ var MAESTRO_MARK_VIEWBOX = "0 0 16 16";
57
+ var MAESTRO_MARK_STROKE_WIDTH = 1.6;
58
+ var MAESTRO_BRAND_TILE = "#0A84FF";
59
+
60
+ // src/client/BrandMark.tsx
61
+ function MaestroMark(props) {
62
+ const s = props.size ?? 16;
63
+ return (0, import_react.createElement)(
64
+ "svg",
65
+ { width: s, height: s, viewBox: MAESTRO_MARK_VIEWBOX, fill: "none", "aria-hidden": "true" },
66
+ (0, import_react.createElement)("path", { d: MAESTRO_MARK_PATH, stroke: "currentColor", strokeWidth: MAESTRO_MARK_STROKE_WIDTH, strokeLinecap: "round", strokeLinejoin: "round" })
67
+ );
68
+ }
69
+ function BrandBadge(props) {
70
+ const outer = props.outer ?? 28;
71
+ const size = props.size ?? 16;
72
+ const radius = props.radius ?? 8;
73
+ return (0, import_react.createElement)("span", {
74
+ "data-maestro-logo": "",
75
+ style: {
76
+ width: outer,
77
+ height: outer,
78
+ borderRadius: radius,
79
+ display: "inline-flex",
80
+ alignItems: "center",
81
+ justifyContent: "center",
82
+ background: `var(--dsw-alias-brand-primary, ${MAESTRO_BRAND_TILE})`,
83
+ backgroundColor: MAESTRO_BRAND_TILE,
84
+ color: "#fff",
85
+ flex: "none",
86
+ border: "1px solid rgba(0,0,0,0.08)",
87
+ boxShadow: "0 0 0 1px var(--dsw-alias-border-l1)",
88
+ boxSizing: "border-box",
89
+ ...props.style
90
+ }
91
+ }, (0, import_react.createElement)(MaestroMark, { size }));
92
+ }
93
+
94
+ // src/client/review/ReviewSettings.tsx
95
+ var FIELD_LABELS = {
96
+ gitlabBaseUrl: "GitLab base URL",
97
+ botUsername: "Bot username",
98
+ webhookPort: "Webhook port",
99
+ autoRereviewOnPush: "Re-review on push",
100
+ autoReviewOnAssign: "Review on assign",
101
+ agentTimeoutMs: "Agent timeout (ms)",
102
+ reviewSessionRetentionDays: "Session retention (days)"
103
+ };
104
+ function Field(props) {
105
+ return React.createElement(
106
+ "div",
107
+ { "data-review-row": "" },
108
+ React.createElement(
109
+ "div",
110
+ { "data-review-row-text": "" },
111
+ React.createElement("label", { "data-review-label": "", htmlFor: props.id }, props.label),
112
+ props.hint ? React.createElement("p", { "data-review-hint": "" }, props.hint) : null
113
+ ),
114
+ React.createElement("div", { "data-review-control": "" }, props.children)
115
+ );
116
+ }
117
+ function SecretField(props) {
118
+ return Field({
119
+ id: props.id,
120
+ label: props.label,
121
+ hint: props.present ? "A value is stored. Leave blank to keep it." : "Not set.",
122
+ children: React.createElement(
123
+ "div",
124
+ { "data-review-secret-group": "" },
125
+ React.createElement("input", {
126
+ id: props.id,
127
+ type: "password",
128
+ value: props.value,
129
+ placeholder: props.present ? "stored \u2014 type to replace" : "not set",
130
+ disabled: props.disabled,
131
+ autoComplete: "new-password",
132
+ "data-review-secret": "",
133
+ onChange: (e) => props.onChange(e.target.value)
134
+ }),
135
+ // The save belongs to this field: it stays disabled until the field
136
+ // holds something, and floating it below the row left it orphaned.
137
+ React.createElement("button", {
138
+ type: "button",
139
+ disabled: props.disabled || props.value === "",
140
+ "data-review-save-secret": props.name,
141
+ onClick: props.onSave
142
+ }, "Save")
143
+ )
144
+ });
145
+ }
146
+ function ReviewSettings(props) {
147
+ const { rpcCall } = props;
148
+ const [cfg, setCfg] = React.useState({});
149
+ const [gitlabToken, setGitlabToken] = React.useState("");
150
+ const [webhookSecret, setWebhookSecret] = React.useState("");
151
+ const [busy, setBusy] = React.useState(false);
152
+ const [notice, setNotice] = React.useState(null);
153
+ const fail = React.useCallback((e) => {
154
+ setNotice({ tone: "bad", text: e instanceof Error ? e.message : String(e) });
155
+ }, []);
156
+ const refresh = React.useCallback(async () => {
157
+ setBusy(true);
158
+ try {
159
+ setCfg(await rpcCall("maestro.getConfig") ?? {});
160
+ } catch (e) {
161
+ fail(e);
162
+ } finally {
163
+ setBusy(false);
164
+ }
165
+ }, [rpcCall, fail]);
166
+ React.useEffect(() => {
167
+ void refresh();
168
+ }, [refresh]);
169
+ const save = React.useCallback(
170
+ async (patch) => {
171
+ setBusy(true);
172
+ try {
173
+ await rpcCall("maestro.saveConfig", patch);
174
+ if ("gitlabToken" in patch) setGitlabToken("");
175
+ if ("webhookSecret" in patch) setWebhookSecret("");
176
+ setNotice({ tone: "ok", text: "Saved." });
177
+ await refresh();
178
+ } catch (e) {
179
+ fail(e);
180
+ } finally {
181
+ setBusy(false);
182
+ }
183
+ },
184
+ [rpcCall, refresh, fail]
185
+ );
186
+ const text = (key, placeholder = "") => Field({
187
+ id: `review-${String(key)}`,
188
+ label: FIELD_LABELS[key] ?? String(key),
189
+ children: React.createElement("input", {
190
+ id: `review-${String(key)}`,
191
+ type: "text",
192
+ value: cfg[key] ?? "",
193
+ placeholder,
194
+ disabled: busy,
195
+ "data-review-input": String(key),
196
+ onChange: (e) => setCfg((c) => ({ ...c, [key]: e.target.value })),
197
+ onBlur: (e) => void save({ [key]: e.target.value })
198
+ })
199
+ });
200
+ const toggle = (key) => Field({
201
+ id: `review-${String(key)}`,
202
+ label: FIELD_LABELS[key] ?? String(key),
203
+ children: React.createElement("input", {
204
+ id: `review-${String(key)}`,
205
+ type: "checkbox",
206
+ checked: cfg[key] === true,
207
+ disabled: busy,
208
+ "data-review-toggle": String(key),
209
+ onChange: (e) => void save({ [key]: e.target.checked })
210
+ })
211
+ });
212
+ return React.createElement(
213
+ "div",
214
+ { "data-review-root": "" },
215
+ // House header: badge, title, one-line status. The notice lives here so it
216
+ // reports without pushing the rows down.
217
+ React.createElement(
218
+ "div",
219
+ { "data-review-header": "" },
220
+ React.createElement(BrandBadge, { style: { alignSelf: "flex-start", marginTop: 2 } }),
221
+ React.createElement(
222
+ "div",
223
+ { "data-review-heading": "" },
224
+ React.createElement("h2", { "data-review-title": "" }, "GitLab and Review"),
225
+ React.createElement(
226
+ "div",
227
+ { "data-review-status": "" },
228
+ notice ? React.createElement("p", { "data-review-notice": "", "data-tone": notice.tone, role: "status" }, notice.text) : React.createElement("span", null, "GitLab credentials and review triggers.")
229
+ )
230
+ )
231
+ ),
232
+ React.createElement(
233
+ "div",
234
+ { "data-review-actions": "" },
235
+ React.createElement("button", { type: "button", disabled: busy, onClick: () => void refresh() }, "Refresh")
236
+ ),
237
+ text("gitlabBaseUrl", "https://gitlab.example.com"),
238
+ text("botUsername", "maestro-bot"),
239
+ SecretField({
240
+ id: "review-gitlab-token",
241
+ name: "gitlabToken",
242
+ label: "GitLab token",
243
+ present: cfg.hasGitlabToken === true,
244
+ value: gitlabToken,
245
+ disabled: busy,
246
+ onChange: setGitlabToken,
247
+ onSave: () => void save({ gitlabToken })
248
+ }),
249
+ SecretField({
250
+ id: "review-webhook-secret",
251
+ name: "webhookSecret",
252
+ label: "Webhook secret",
253
+ present: cfg.hasWebhookSecret === true,
254
+ value: webhookSecret,
255
+ disabled: busy,
256
+ onChange: setWebhookSecret,
257
+ onSave: () => void save({ webhookSecret })
258
+ }),
259
+ text("webhookPort", "3081"),
260
+ toggle("autoRereviewOnPush"),
261
+ toggle("autoReviewOnAssign"),
262
+ text("agentTimeoutMs", "600000"),
263
+ text("reviewSessionRetentionDays", "30")
264
+ );
265
+ }
266
+
267
+ // src/client/review/styles.ts
268
+ var REVIEW_CSS = `
269
+ [data-review-root], [data-review-root] * { box-sizing: border-box; }
270
+ [data-review-root] {
271
+ display: flex; flex-direction: column; gap: 12px;
272
+ color: var(--dsw-alias-label-primary);
273
+ font-size: 13px; line-height: 1.5;
274
+ min-width: 0; width: 100%; max-width: 640px;
275
+ }
276
+
277
+ /* House header: badge + title + one-line status. */
278
+ [data-review-header] { display: flex; gap: 10px; align-items: flex-start; padding: 2px 2px 8px; }
279
+ [data-review-heading] { display: flex; flex-direction: column; min-width: 0; }
280
+ [data-review-title] { margin: 0; font-size: 15px; font-weight: 600; line-height: 22px; }
281
+ [data-review-status] { font-size: 12px; line-height: 16px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
282
+ [data-review-status] [data-review-notice] { margin: 0; }
283
+ [data-review-status] [data-review-notice][data-tone="ok"] { color: var(--dsw-alias-state-success-primary); }
284
+ [data-review-status] [data-review-notice][data-tone="bad"] { color: var(--dsw-alias-state-error-primary); }
285
+
286
+ [data-review-actions] { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
287
+ [data-review-actions] button {
288
+ min-height: 32px; padding: 0 12px; border-radius: 8px;
289
+ border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1);
290
+ color: inherit; font: inherit; cursor: pointer;
291
+ }
292
+ [data-review-actions] button:disabled { opacity: 0.55; cursor: default; }
293
+ [data-review-actions] button:focus-visible { outline: 2px solid var(--dsw-alias-border-l2); outline-offset: 2px; }
294
+
295
+ /* House row: label and hint left, control held right, hairline between. */
296
+ [data-review-row] {
297
+ display: flex; align-items: center; gap: 8px;
298
+ padding: 16px 0; border-bottom: 1px solid var(--dsw-alias-border-l2); min-width: 0;
299
+ }
300
+ [data-review-row]:last-of-type { border-bottom: none; }
301
+ [data-review-row-text] { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding-right: 48px; }
302
+ [data-review-control] { flex: none; display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-height: 36px; }
303
+ /* Declared once. These two rules previously existed twice \u2014 the 12px/600 pair
304
+ sat AFTER the house values and won on source order at equal specificity, so
305
+ the whole tab rendered at the old weight and the old hint size. */
306
+ [data-review-label] { font-size: 14px; font-weight: 400; line-height: 22px; color: var(--dsw-alias-label-primary); }
307
+ [data-review-hint] { margin: 0; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-tertiary); }
308
+
309
+ /* A secret whose value is committed by a button: input and save travel
310
+ together on ONE row. The button used to sit on a row of its own below the
311
+ field \u2014 the group was a column and the button was align-self: flex-end \u2014
312
+ which orphaned it from the control it saves. It stays disabled until the
313
+ field holds something, so proximity to that field is the point. */
314
+ [data-review-secret-group] { display: flex; flex-direction: row; align-items: center; gap: 8px; min-width: 220px; }
315
+ [data-review-secret-group] input { flex: 1 1 auto; min-width: 0; }
316
+ [data-review-secret-group] button {
317
+ flex: none; align-self: center; min-height: 44px; padding: 0 12px; border-radius: 8px;
318
+ border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1);
319
+ color: inherit; font: inherit; cursor: pointer;
320
+ }
321
+ [data-review-secret-group] button:disabled { opacity: 0.55; cursor: default; }
322
+ [data-review-secret-group] button:focus-visible { outline: 2px solid var(--dsw-alias-border-l2); outline-offset: 2px; }
323
+
324
+ /* Every row control gets the same box \u2014 the shared settings field box, copied
325
+ from the host's own form primitive (ui-primitives ConfigField) so this tab
326
+ follows the shell instead of carrying a geometry of its own. Only
327
+ min-height: 44px is Maestro's: it is the touch target AGENTS.md requires,
328
+ which the host's line-box sizing does not give.
329
+ The password type belongs in this list: without it the two secret fields
330
+ rendered at the UA default \u2014 21px tall, no radius \u2014 beside their neighbours
331
+ in the same column. */
332
+ [data-review-control] input[type="text"], [data-review-control] input[type="password"], [data-review-control] select {
333
+ min-height: 44px; padding: 6px 12px; border: 0.5px solid var(--dsw-alias-border-l4);
334
+ border-radius: var(--dsw-radius-md); background: var(--dsw-alias-bg-layer-3);
335
+ color: var(--dsw-alias-label-primary); font: inherit;
336
+ }
337
+ [data-review-control] input:focus-visible, [data-review-control] select:focus-visible {
338
+ outline: 2px solid var(--dsw-alias-border-l2); outline-offset: 2px;
339
+ }
340
+ /* The checkbox is the one control the harness draws at its own size; without
341
+ this it rendered at the UA's 13px. Same values as the reference row. */
342
+ [data-review-control] input[type="checkbox"] {
343
+ width: 16px; height: 16px; margin: 0; flex: none;
344
+ accent-color: var(--dsw-alias-brand-primary, #0A84FF);
345
+ }
346
+
347
+ [data-review-pin], [data-review-lan] { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
348
+ [data-review-pin] code, [data-review-lan] code {
349
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
350
+ padding: 2px 6px; border-radius: 6px; background: var(--dsw-alias-bg-layer-2);
351
+ }
352
+ [data-review-pin] button, [data-review-lan] button {
353
+ min-height: 32px; padding: 0 10px; border-radius: 8px;
354
+ border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-1);
355
+ color: inherit; font: inherit; cursor: pointer;
356
+ }
357
+
358
+ @media (max-width: 640px) {
359
+ /* Below the measure the row stacks: a right-held control has no room left,
360
+ and a wrapped one reads as a third column. */
361
+ [data-review-row] { flex-direction: column; align-items: stretch; gap: 8px; }
362
+ [data-review-row-text] { padding-right: 0; }
363
+ [data-review-control] { justify-content: flex-start; }
364
+ }
365
+
366
+ @media (max-width: 480px) {
367
+ [data-review-actions] button { flex: 1 1 auto; min-height: 40px; }
368
+ }
369
+
370
+ /* iOS 16px field floor: the magnifier fires below this on a focused field. */
371
+ @media (max-width: 1023px) and (pointer: coarse) {
372
+ html[data-mobile-nav-ios] [data-review-root] input,
373
+ html[data-mobile-nav-ios] [data-review-root] select { font-size: 16px !important; }
374
+ }
375
+ `;
376
+
377
+ // src/client/settings-nav-icon.ts
378
+ var SETTINGS_NAV_MARKER = "data-maestro-review-settings-nav";
379
+ function registerSettingsNavIcon(label, root) {
380
+ if (typeof document === "undefined" && root === void 0) {
381
+ return () => {
382
+ };
383
+ }
384
+ const scope = root ?? document;
385
+ let disposed = false;
386
+ const sync = () => {
387
+ if (disposed) return;
388
+ const currentLabel = label().trim();
389
+ const buttons = scope.querySelectorAll('[role="dialog"] nav button');
390
+ for (const button of Array.from(buttons)) {
391
+ const el = button;
392
+ const matches = currentLabel.length > 0 && button.textContent != null && button.textContent.trim() === currentLabel;
393
+ if (matches) el.setAttribute(SETTINGS_NAV_MARKER, "");
394
+ else if (el.hasAttribute(SETTINGS_NAV_MARKER)) el.removeAttribute(SETTINGS_NAV_MARKER);
395
+ }
396
+ };
397
+ sync();
398
+ let observer = null;
399
+ if (typeof MutationObserver !== "undefined") {
400
+ observer = new MutationObserver(sync);
401
+ observer.observe(document.body, { childList: true, subtree: true, characterData: true });
402
+ }
403
+ return () => {
404
+ disposed = true;
405
+ if (observer !== null) observer.disconnect();
406
+ for (const element of Array.from(scope.querySelectorAll(`[${SETTINGS_NAV_MARKER}]`))) {
407
+ element.removeAttribute(SETTINGS_NAV_MARKER);
408
+ }
409
+ };
410
+ }
411
+
412
+ // src/client/index.tsx
413
+ var REVIEW_CHANNEL = "/dsh-maestro-review";
414
+ function unwrap(res) {
415
+ return res && typeof res === "object" && "ok" in res ? res.ok ? res.value : null : res;
416
+ }
417
+ function makeRpcCall(ctx) {
418
+ return async (endpoint, payload) => {
419
+ const conn = ctx.get?.("connection");
420
+ if (conn?.rpc?.call === void 0) throw new Error("RPC not available");
421
+ const res = await conn.rpc.call(REVIEW_CHANNEL, endpoint, payload ?? {});
422
+ const value = unwrap(res);
423
+ if (value === null) {
424
+ throw new Error(String(res?.error?.message ?? res?.error ?? endpoint));
425
+ }
426
+ return value;
427
+ };
428
+ }
429
+ var REVIEW_NAV_CSS = `
430
+ [${SETTINGS_NAV_MARKER}] > svg:first-child,
431
+ [${SETTINGS_NAV_MARKER}] > svg.zWKi1a_navIcon {
432
+ display: none !important;
433
+ }
434
+
435
+ [${SETTINGS_NAV_MARKER}]::before {
436
+ content: '';
437
+ flex: none;
438
+ width: 16px;
439
+ height: 16px;
440
+ display: inline-block;
441
+ background: currentColor;
442
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 11 L5 4 L8 9 L11 4 L14 11'/%3E%3C/svg%3E") center / contain no-repeat;
443
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 11 L5 4 L8 9 L11 4 L14 11'/%3E%3C/svg%3E") center / contain no-repeat;
444
+ }
445
+ `;
446
+ function installStyleTag(css, pluginCss) {
447
+ if (typeof document === "undefined") return () => {
448
+ };
449
+ const tag = document.createElement("style");
450
+ tag.dataset.plugin = "@ddtcorex/dsh-maestro-review";
451
+ tag.dataset.pluginCss = pluginCss;
452
+ tag.textContent = css;
453
+ document.head.appendChild(tag);
454
+ return () => {
455
+ document.querySelector(`style[data-plugin-css="${pluginCss}"]`)?.remove();
456
+ };
457
+ }
458
+ var inject = ["slots", "connection"];
459
+ function apply(ctx) {
460
+ const slots = ctx.get?.("slots");
461
+ if (!slots?.inject || !slots?.register) return;
462
+ const rpcCall = makeRpcCall(ctx);
463
+ ctx.effect(() => registerSettingsNavIcon(() => "Maestro Review"), "maestro-review: settings nav icon");
464
+ ctx.effect(() => installStyleTag(REVIEW_NAV_CSS, "maestro-review/settings-nav.css"), "maestro-review: settings nav css");
465
+ ctx.effect(() => installStyleTag(REVIEW_CSS, "maestro-review/settings.css"), "maestro-review: settings css");
466
+ ctx.effect(() => {
467
+ const dispose = slots.inject(
468
+ "settings.section",
469
+ () => slots.register(
470
+ {
471
+ name: "settings.section",
472
+ id: "maestro-review",
473
+ order: 32,
474
+ label: () => "Maestro Review",
475
+ inject: () => ({ rpcCall })
476
+ },
477
+ (props) => React2.createElement(ReviewSettings, props)
478
+ )
479
+ );
480
+ return () => {
481
+ try {
482
+ ;
483
+ dispose?.();
484
+ } catch {
485
+ }
486
+ };
487
+ }, "maestro-review: settings");
488
+ }
489
+ var index_default = { inject, apply };
490
+
491
+ return module.exports;
492
+ }
493
+ });
@@ -55,7 +55,7 @@ export interface MaestroUserConfig {
55
55
  }
56
56
  /**
57
57
  * Settings live in the SHARED namespaced store (`~/.dsh/dsh-maestro-config/settings.json`,
58
- * owned by @ddtcorex/dsh-maestro-config-lib); this store is a thin adapter that
58
+ * owned by dsh-maestro-core and embedded here at `src/host/vendor/store.ts`); this store is a thin adapter that
59
59
  * keeps the package's flat `MaestroUserConfig` API while delegating persistence.
60
60
  * Machine runtime state (RUNTIME_KEYS) never enters settings — it stays in this
61
61
  * package's own sidecar so a settings edit can never silently flip tunnel state.
@@ -1 +1 @@
1
- {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/host/config-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAO1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAClC,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IACvC,wGAAwG;IACxG,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAClC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,gGAAgG;IAChG,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uFAAuF;IACvF,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC9B,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mEAAmE;IACnE,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAyBD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAMjF;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAc3G"}
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/host/config-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAO1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAClC,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAA;IACvC,wGAAwG;IACxG,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAClC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,gGAAgG;IAChG,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uFAAuF;IACvF,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC9B,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mEAAmE;IACnE,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC;AAuBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAyBD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA4BjF;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAc3G"}
@@ -1,13 +1,29 @@
1
1
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import { homedir } from 'node:os';
3
3
  import { dirname, join } from 'node:path';
4
- import { RUNTIME_KEYS, readFlat, writeLegacyPatch, } from '@ddtcorex/dsh-maestro-config-lib';
4
+ import { RUNTIME_KEYS, readFlat, writeLegacyPatch, } from './vendor/store.js';
5
5
  function resolveDshHome(dshHome) {
6
6
  return dshHome ?? process.env.DSH_HOME ?? join(homedir(), '.dsh');
7
7
  }
8
+ /**
9
+ * The keys review reads and may persist: its own gitlab + review settings, plus
10
+ * the one machine-runtime flag that belongs to its own sidecar.
11
+ *
12
+ * Deliberately the READ counterpart of `SAVABLE_KEYS` in `settings-rpc.ts`, plus
13
+ * `lastTunnelRunning` — which review reads from its sidecar and never writes to
14
+ * the shared store. Keep both in step: a key here that is not savable is a read
15
+ * review needs but cannot change, and a savable key missing here is one the UI
16
+ * could write but never read back.
17
+ */
18
+ const REVIEW_OWNED_KEYS = [
19
+ 'gitlabBaseUrl', 'gitlabToken', 'botUsername', 'webhookSecret', 'webhookPort',
20
+ 'projectMappings', 'autoRereviewOnPush', 'autoReviewOnAssign',
21
+ 'reviewModel', 'agentTimeoutMs', 'reviewSessionRetentionDays',
22
+ 'lastTunnelRunning',
23
+ ];
8
24
  /**
9
25
  * Settings live in the SHARED namespaced store (`~/.dsh/dsh-maestro-config/settings.json`,
10
- * owned by @ddtcorex/dsh-maestro-config-lib); this store is a thin adapter that
26
+ * owned by dsh-maestro-core and embedded here at `src/host/vendor/store.ts`); this store is a thin adapter that
11
27
  * keeps the package's flat `MaestroUserConfig` API while delegating persistence.
12
28
  * Machine runtime state (RUNTIME_KEYS) never enters settings — it stays in this
13
29
  * package's own sidecar so a settings edit can never silently flip tunnel state.
@@ -38,7 +54,31 @@ export async function loadUserConfig(dshHome) {
38
54
  readFlat({ dshHome }),
39
55
  readRuntimeState(dshHome),
40
56
  ]);
41
- return { ...flat, ...runtime };
57
+ // Scope the read to the keys review OWNS. `readFlat` returns the WHOLE store
58
+ // view — every `DOMAIN_KEY_MAP` key across every domain — so returning it
59
+ // unfiltered made review's own settings RPC (`/dsh-maestro-review`,
60
+ // `maestro.getConfig`) answer with remote's tunnel identity: `tunnelHostname`,
61
+ // `tunnelId`, `tunnelCredentialsFile` (the local path of the machine's
62
+ // Cloudflare credentials file), `lanPort`, `lanPinEnabled`, `proxyPort`,
63
+ // `pinSessionTtlHours` — plus the notifier's telegram token and chat id.
64
+ //
65
+ // The leak was one-directional and therefore invisible: `SAVABLE_KEYS` already
66
+ // rejected every one of those keys on a WRITE (with `OWNER_OF` naming the
67
+ // owning plugin), and nothing in review reads them — but the read side handed
68
+ // them to the client anyway.
69
+ //
70
+ // An ALLOWLIST, not a denylist, so a key added to the shared store later
71
+ // cannot leak by default. `tests/config-scope.spec.ts` pins the set.
72
+ const scoped = {};
73
+ for (const key of REVIEW_OWNED_KEYS) {
74
+ const value = flat[key];
75
+ if (value !== undefined)
76
+ scoped[key] = value;
77
+ const local = runtime[key];
78
+ if (local !== undefined)
79
+ scoped[key] = local;
80
+ }
81
+ return scoped;
42
82
  }
43
83
  export async function saveUserConfig(patch, dshHome) {
44
84
  const settingsPatch = {};
@@ -1 +1 @@
1
- {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/host/config-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/host/config-store.ts"],"names":[],"mappings":"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"}