mintree 0.5.2 → 0.5.4
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/dist/commands/dashboard.js +3 -1
- package/dist/commands/orchestrate.d.ts +1 -0
- package/dist/commands/orchestrate.js +20 -3
- package/dist/lib/markers.d.ts +1 -0
- package/dist/lib/markers.js +3 -0
- package/dist/lib/orchestrate.d.ts +13 -0
- package/dist/lib/orchestrate.js +17 -0
- package/dist/lib/providers/linear.js +7 -6
- package/package.json +1 -1
- package/shell/init.bash +3 -0
- package/shell/init.zsh +3 -0
|
@@ -14,6 +14,7 @@ import { runCreate, runCreateDetached, } from "../lib/worktreeCreate.js";
|
|
|
14
14
|
import { runRemove, runRemoveByPath } from "../lib/worktreeRemove.js";
|
|
15
15
|
import { writePromptFile } from "../lib/worktreeCreate.js";
|
|
16
16
|
import { buildCreateMarkers, buildOrchestrateMarkers, emitMarkers } from "../lib/markers.js";
|
|
17
|
+
import { buildOrchestratorRcName } from "../lib/orchestrate.js";
|
|
17
18
|
import { readMetadata } from "../lib/metadata.js";
|
|
18
19
|
import { defaultOrchestratorPrompt, renderOrchestratorTemplate, renderPromptTemplate, } from "../lib/promptTemplate.js";
|
|
19
20
|
import { createProvider } from "../lib/providers/index.js";
|
|
@@ -1101,7 +1102,8 @@ export default function Dashboard() {
|
|
|
1101
1102
|
: defaultOrchestratorPrompt(idList);
|
|
1102
1103
|
const promptFile = writePromptFile(prompt);
|
|
1103
1104
|
const permissionMode = meta.defaultPermissionMode ?? "default";
|
|
1104
|
-
|
|
1105
|
+
const rcName = buildOrchestratorRcName(ids) ?? undefined;
|
|
1106
|
+
emitMarkers(buildOrchestrateMarkers({ repoRoot: root, promptFile, permissionMode, rcName }));
|
|
1105
1107
|
exit();
|
|
1106
1108
|
}
|
|
1107
1109
|
function openCreateOverlay(issue) {
|
|
@@ -10,6 +10,7 @@ import { findMainRepoRoot, getMintreeDir, pathExists } from "../lib/git.js";
|
|
|
10
10
|
import { readMetadata } from "../lib/metadata.js";
|
|
11
11
|
import { launchClaude, PERMISSION_MODES } from "../lib/claude.js";
|
|
12
12
|
import { defaultOrchestratorPrompt, renderOrchestratorTemplate } from "../lib/promptTemplate.js";
|
|
13
|
+
import { buildOrchestratorRcName } from "../lib/orchestrate.js";
|
|
13
14
|
export const description = "Launch a Claude orchestrator in the repo root to resolve a batch of tickets";
|
|
14
15
|
export const args = z
|
|
15
16
|
.array(z.string())
|
|
@@ -38,6 +39,12 @@ export const options = z.object({
|
|
|
38
39
|
description: `Claude --permission-mode (one of: ${PERMISSION_MODES.join(", ")}). Defaults to metadata.defaultPermissionMode, else "default".`,
|
|
39
40
|
alias: "m",
|
|
40
41
|
})),
|
|
42
|
+
rcName: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe(option({
|
|
46
|
+
description: "Remote Control name for the session. Defaults to orchestrator-<ids> derived from the positional ids (used by the dashboard, which has no positional ids), else orchestrator-<session-hash>.",
|
|
47
|
+
})),
|
|
41
48
|
});
|
|
42
49
|
function resolve(cwd, ids, opts) {
|
|
43
50
|
if (opts.prompt && opts.promptFile) {
|
|
@@ -96,9 +103,14 @@ function resolve(cwd, ids, opts) {
|
|
|
96
103
|
};
|
|
97
104
|
}
|
|
98
105
|
const permissionMode = opts.permissionMode ?? readMetadata(repoRoot).defaultPermissionMode ?? "default";
|
|
106
|
+
const sessionId = randomUUID();
|
|
107
|
+
// RC name priority: explicit --rc-name (the dashboard passes the
|
|
108
|
+
// ids-derived name this way) > derive from positional ids > session hash
|
|
109
|
+
// fallback for the prompt-only path with no tickets to name after.
|
|
110
|
+
const remoteControlName = opts.rcName ?? buildOrchestratorRcName(ids) ?? `orchestrator-${sessionId.slice(0, 8)}`;
|
|
99
111
|
return {
|
|
100
112
|
ok: true,
|
|
101
|
-
data: { repoRoot, sessionId
|
|
113
|
+
data: { repoRoot, sessionId, permissionMode, prompt, remoteControlName },
|
|
102
114
|
};
|
|
103
115
|
}
|
|
104
116
|
export default function Orchestrate({ args: ids, options }) {
|
|
@@ -124,7 +136,12 @@ export default function Orchestrate({ args: ids, options }) {
|
|
|
124
136
|
resume: false,
|
|
125
137
|
prompt: resolved.prompt,
|
|
126
138
|
cwd: resolved.repoRoot,
|
|
127
|
-
|
|
139
|
+
// Name the RC session after the tickets it covers
|
|
140
|
+
// (orchestrator-VAL-12_BE-16_FE-3) so it's identifiable in the RC
|
|
141
|
+
// UI. Falls back to a session hash when there are no ids. Note:
|
|
142
|
+
// re-launching the exact same batch reuses the name, which can
|
|
143
|
+
// collide with a still-registered prior session.
|
|
144
|
+
remoteControlName: resolved.remoteControlName,
|
|
128
145
|
});
|
|
129
146
|
child.on("error", (err) => {
|
|
130
147
|
setState({ phase: "error", message: `Failed to launch claude: ${err.message}` });
|
|
@@ -148,7 +165,7 @@ export default function Orchestrate({ args: ids, options }) {
|
|
|
148
165
|
}
|
|
149
166
|
const { resolved } = state;
|
|
150
167
|
const sessionShort = resolved.sessionId.slice(0, 8);
|
|
151
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "mintree orchestrate" }), _jsxs(Text, { dimColor: true, children: [" \u00B7 ", resolved.repoRoot] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "session: " }), _jsxs(Text, { children: [sessionShort, "\u2026"] }), _jsx(Text, { dimColor: true, children: " (starting)" })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "permission-mode: " }), _jsx(Text, { children: resolved.permissionMode })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "prompt: " }), _jsxs(Text, { children: ["\"", truncate(resolved.prompt.replace(/\n/g, " "), 60), "\""] })] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "green", bold: true, children: "\u2713 Launching Claude orchestrator..." }) })] }));
|
|
168
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "mintree orchestrate" }), _jsxs(Text, { dimColor: true, children: [" \u00B7 ", resolved.repoRoot] })] }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "session: " }), _jsxs(Text, { children: [sessionShort, "\u2026"] }), _jsx(Text, { dimColor: true, children: " (starting)" })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "rc: " }), _jsx(Text, { children: resolved.remoteControlName })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "permission-mode: " }), _jsx(Text, { children: resolved.permissionMode })] }), _jsxs(Text, { children: [_jsx(Text, { dimColor: true, children: "prompt: " }), _jsxs(Text, { children: ["\"", truncate(resolved.prompt.replace(/\n/g, " "), 60), "\""] })] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "green", bold: true, children: "\u2713 Launching Claude orchestrator..." }) })] }));
|
|
152
169
|
}
|
|
153
170
|
function truncate(s, max) {
|
|
154
171
|
if (s.length <= max)
|
package/dist/lib/markers.d.ts
CHANGED
package/dist/lib/markers.js
CHANGED
|
@@ -55,5 +55,8 @@ export function buildOrchestrateMarkers(input) {
|
|
|
55
55
|
if (input.permissionMode) {
|
|
56
56
|
lines.push(`MINTREE_PERMISSION_MODE:${input.permissionMode}`);
|
|
57
57
|
}
|
|
58
|
+
if (input.rcName) {
|
|
59
|
+
lines.push(`MINTREE_ORCHESTRATE_RC_NAME:${input.rcName}`);
|
|
60
|
+
}
|
|
58
61
|
return lines;
|
|
59
62
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives the Remote Control name for an orchestrator session from the ticket
|
|
3
|
+
* ids it covers, e.g. ["VAL-12", "BE-16", "FE-3"] -> "orchestrator-VAL-12_BE-16_FE-3".
|
|
4
|
+
*
|
|
5
|
+
* The ids are joined with "_" (not spaces) so the result is a single
|
|
6
|
+
* shell-safe token — it travels through the dashboard markers and the shell
|
|
7
|
+
* wrapper as one `--rc-name` argument without quoting.
|
|
8
|
+
*
|
|
9
|
+
* Returns null when there are no ids, letting the caller fall back to a
|
|
10
|
+
* session-hash name (the `mintree orchestrate --prompt "..."` path, which has
|
|
11
|
+
* no tickets to name the session after).
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildOrchestratorRcName(ids: string[]): string | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives the Remote Control name for an orchestrator session from the ticket
|
|
3
|
+
* ids it covers, e.g. ["VAL-12", "BE-16", "FE-3"] -> "orchestrator-VAL-12_BE-16_FE-3".
|
|
4
|
+
*
|
|
5
|
+
* The ids are joined with "_" (not spaces) so the result is a single
|
|
6
|
+
* shell-safe token — it travels through the dashboard markers and the shell
|
|
7
|
+
* wrapper as one `--rc-name` argument without quoting.
|
|
8
|
+
*
|
|
9
|
+
* Returns null when there are no ids, letting the caller fall back to a
|
|
10
|
+
* session-hash name (the `mintree orchestrate --prompt "..."` path, which has
|
|
11
|
+
* no tickets to name the session after).
|
|
12
|
+
*/
|
|
13
|
+
export function buildOrchestratorRcName(ids) {
|
|
14
|
+
if (ids.length === 0)
|
|
15
|
+
return null;
|
|
16
|
+
return `orchestrator-${ids.join("_")}`;
|
|
17
|
+
}
|
|
@@ -21,9 +21,8 @@ import { readMetadata } from "../metadata.js";
|
|
|
21
21
|
const DEFAULT_API_URL = "https://api.linear.app/graphql";
|
|
22
22
|
// Linear state types we treat as "done" — work in these states is excluded
|
|
23
23
|
// from the assigned list and protected from transitions back to In Progress.
|
|
24
|
-
// "duplicate" is
|
|
25
|
-
//
|
|
26
|
-
// completed/canceled or those tickets keep showing up in the dashboard.
|
|
24
|
+
// "duplicate" is its own terminal state type in Linear (separate from
|
|
25
|
+
// "canceled"), so it has to be listed explicitly or those issues leak in.
|
|
27
26
|
const DEFAULT_PROTECTED_STATE_TYPES = ["completed", "canceled", "duplicate"];
|
|
28
27
|
const STATUS_ORDER_UNSET = 999;
|
|
29
28
|
// One query covers viewer + teams + issues; a single 20s budget comfortably
|
|
@@ -406,9 +405,11 @@ export class LinearProvider {
|
|
|
406
405
|
const protectedTypes = new Set(cfg.protectedStateTypes ?? DEFAULT_PROTECTED_STATE_TYPES);
|
|
407
406
|
const out = [];
|
|
408
407
|
for (const wi of data.issues) {
|
|
409
|
-
// Defensive — the bootstrap query already excludes
|
|
410
|
-
// via state.type.nin, but a workspace
|
|
411
|
-
// the user added to the protected list
|
|
408
|
+
// Defensive — the bootstrap query already excludes
|
|
409
|
+
// completed/canceled/duplicate via state.type.nin, but a workspace
|
|
410
|
+
// could have custom state types the user added to the protected list
|
|
411
|
+
// locally (and a stale snapshot cache predating the query change
|
|
412
|
+
// still gets filtered here).
|
|
412
413
|
const type = wi.state?.type;
|
|
413
414
|
if (type && protectedTypes.has(type))
|
|
414
415
|
continue;
|
package/package.json
CHANGED
package/shell/init.bash
CHANGED
|
@@ -55,6 +55,9 @@ function mintree() {
|
|
|
55
55
|
orch_prompt_file=$(echo "$clean_output" | grep "MINTREE_ORCHESTRATE_PROMPT_FILE:" | sed 's/.*MINTREE_ORCHESTRATE_PROMPT_FILE://')
|
|
56
56
|
[[ -n "$orch_prompt_file" ]] && extra+=(--prompt-file "$orch_prompt_file")
|
|
57
57
|
[[ -n "$perm_mode" ]] && extra+=(--permission-mode "$perm_mode")
|
|
58
|
+
local orch_rc_name
|
|
59
|
+
orch_rc_name=$(echo "$clean_output" | grep "MINTREE_ORCHESTRATE_RC_NAME:" | sed 's/.*MINTREE_ORCHESTRATE_RC_NAME://')
|
|
60
|
+
[[ -n "$orch_rc_name" ]] && extra+=(--rc-name "$orch_rc_name")
|
|
58
61
|
command mintree orchestrate "${extra[@]}"
|
|
59
62
|
return $?
|
|
60
63
|
fi
|
package/shell/init.zsh
CHANGED
|
@@ -65,6 +65,9 @@ function mintree() {
|
|
|
65
65
|
orch_prompt_file=$(echo "$clean_output" | grep "MINTREE_ORCHESTRATE_PROMPT_FILE:" | sed 's/.*MINTREE_ORCHESTRATE_PROMPT_FILE://')
|
|
66
66
|
[[ -n "$orch_prompt_file" ]] && extra+=(--prompt-file "$orch_prompt_file")
|
|
67
67
|
[[ -n "$perm_mode" ]] && extra+=(--permission-mode "$perm_mode")
|
|
68
|
+
local orch_rc_name
|
|
69
|
+
orch_rc_name=$(echo "$clean_output" | grep "MINTREE_ORCHESTRATE_RC_NAME:" | sed 's/.*MINTREE_ORCHESTRATE_RC_NAME://')
|
|
70
|
+
[[ -n "$orch_rc_name" ]] && extra+=(--rc-name "$orch_rc_name")
|
|
68
71
|
command mintree orchestrate "${extra[@]}"
|
|
69
72
|
return $?
|
|
70
73
|
fi
|