@samaksh/git-worker 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/cli/index.js +1 -1
- package/dist/config/repo-presets.d.ts +16 -0
- package/dist/config/repo-presets.js +271 -0
- package/dist/core/types.d.ts +6 -0
- package/dist/services/workspace/manager.js +1 -1
- package/dist/stages/apply.js +92 -71
- package/dist/stages/edit-template.js +167 -111
- package/dist/stages/eligibility.js +45 -16
- package/dist/stages/load-template.js +109 -94
- package/dist/stages/plan.js +231 -187
- package/dist/stages/report.js +23 -18
- package/dist/stages/review.js +129 -111
- package/dist/stages/select.js +115 -15
- package/package.json +3 -5
package/dist/stages/review.js
CHANGED
|
@@ -10,19 +10,43 @@ export const reviewChangesStage = async (context, deps) => {
|
|
|
10
10
|
const isCi = context.input.ci ?? false;
|
|
11
11
|
const autoApprove = context.input.autoApprove || deps.config.review.autoApprove;
|
|
12
12
|
sectionHeader("Review Changes");
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
// Group plans by branch
|
|
14
|
+
const branchMap = new Map();
|
|
15
|
+
for (const plan of context.plans) {
|
|
16
|
+
const list = branchMap.get(plan.branch.name) || [];
|
|
17
|
+
list.push(plan);
|
|
18
|
+
branchMap.set(plan.branch.name, list);
|
|
19
|
+
}
|
|
20
|
+
// Show summary table grouped by branch
|
|
21
|
+
const tableRows = Array.from(branchMap.entries()).map(([branchName, plans]) => {
|
|
22
|
+
const hasError = plans.some((p) => p.status === "error");
|
|
23
|
+
const changedPlans = plans.filter((p) => p.status === "changed");
|
|
24
|
+
if (hasError) {
|
|
25
|
+
const errPlan = plans.find((p) => p.status === "error");
|
|
26
|
+
return {
|
|
27
|
+
name: branchName,
|
|
28
|
+
status: "error",
|
|
29
|
+
detail: `${errPlan?.path}: ${errPlan?.reason ?? "error"}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (changedPlans.length > 0) {
|
|
33
|
+
const fileSummary = changedPlans.map((p) => p.path).join(", ");
|
|
34
|
+
return {
|
|
35
|
+
name: branchName,
|
|
36
|
+
status: "changed",
|
|
37
|
+
detail: `${changedPlans.length} file(s) modified (${fileSummary})`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
name: branchName,
|
|
42
|
+
status: "unchanged",
|
|
43
|
+
detail: "no changes across files",
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
renderBranchTable(tableRows);
|
|
47
|
+
const changedBranches = Array.from(branchMap.entries()).filter(([_, plans]) => plans.some((p) => p.status === "changed") && !plans.some((p) => p.status === "error"));
|
|
24
48
|
const approvals = [];
|
|
25
|
-
// Auto-
|
|
49
|
+
// Auto-record non-changed or errored plans as unapproved
|
|
26
50
|
for (const plan of context.plans) {
|
|
27
51
|
if (plan.status !== "changed") {
|
|
28
52
|
approvals.push({
|
|
@@ -32,42 +56,48 @@ export const reviewChangesStage = async (context, deps) => {
|
|
|
32
56
|
});
|
|
33
57
|
}
|
|
34
58
|
}
|
|
35
|
-
if (
|
|
59
|
+
if (changedBranches.length === 0) {
|
|
36
60
|
statusLine("info", "No changed branches to review");
|
|
37
61
|
return ok({ ...context, approvals });
|
|
38
62
|
}
|
|
39
63
|
// Auto-approve all
|
|
40
64
|
if (autoApprove) {
|
|
41
|
-
for (const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
for (const [_, plans] of changedBranches) {
|
|
66
|
+
for (const plan of plans) {
|
|
67
|
+
if (plan.status === "changed") {
|
|
68
|
+
approvals.push({
|
|
69
|
+
branchName: plan.branch.name,
|
|
70
|
+
approved: true,
|
|
71
|
+
planHash: plan.planHash,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
47
75
|
}
|
|
48
|
-
statusLine("ok", `Auto-approved ${
|
|
76
|
+
statusLine("ok", `Auto-approved ${changedBranches.length} branch(es)`);
|
|
49
77
|
return ok({ ...context, approvals });
|
|
50
78
|
}
|
|
51
79
|
if (isCi) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
80
|
+
for (const [_, plans] of changedBranches) {
|
|
81
|
+
for (const plan of plans) {
|
|
82
|
+
if (plan.status === "changed") {
|
|
83
|
+
approvals.push({
|
|
84
|
+
branchName: plan.branch.name,
|
|
85
|
+
approved: false,
|
|
86
|
+
planHash: plan.planHash,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
59
90
|
}
|
|
60
91
|
statusLine("warn", "CI mode — all branches rejected (use --auto-approve to commit in CI)");
|
|
61
92
|
return ok({ ...context, approvals });
|
|
62
93
|
}
|
|
63
94
|
// Interactive review
|
|
64
95
|
console.log("");
|
|
65
|
-
// Ask if user wants batch action or per-branch review
|
|
66
96
|
const batchChoice = await clack.select({
|
|
67
|
-
message: `Review ${
|
|
97
|
+
message: `Review ${changedBranches.length} changed branch(es):`,
|
|
68
98
|
options: [
|
|
69
99
|
{ value: "per-branch", label: "Review each branch individually", hint: "recommended" },
|
|
70
|
-
{ value: "approve-all", label: `Approve all ${
|
|
100
|
+
{ value: "approve-all", label: `Approve all ${changedBranches.length} branches` },
|
|
71
101
|
{ value: "reject-all", label: "Reject all" },
|
|
72
102
|
],
|
|
73
103
|
});
|
|
@@ -75,118 +105,106 @@ export const reviewChangesStage = async (context, deps) => {
|
|
|
75
105
|
return err(inputCancelledError("Review cancelled"));
|
|
76
106
|
}
|
|
77
107
|
if (batchChoice === "approve-all") {
|
|
78
|
-
for (const
|
|
79
|
-
|
|
108
|
+
for (const [_, plans] of changedBranches) {
|
|
109
|
+
for (const plan of plans) {
|
|
110
|
+
if (plan.status === "changed") {
|
|
111
|
+
approvals.push({ branchName: plan.branch.name, approved: true, planHash: plan.planHash });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
80
114
|
}
|
|
81
|
-
statusLine("ok", `Approved all ${
|
|
115
|
+
statusLine("ok", `Approved all ${changedBranches.length} branch(es)`);
|
|
82
116
|
return ok({ ...context, approvals });
|
|
83
117
|
}
|
|
84
118
|
if (batchChoice === "reject-all") {
|
|
85
|
-
for (const
|
|
86
|
-
|
|
119
|
+
for (const [_, plans] of changedBranches) {
|
|
120
|
+
for (const plan of plans) {
|
|
121
|
+
if (plan.status === "changed") {
|
|
122
|
+
approvals.push({ branchName: plan.branch.name, approved: false, planHash: plan.planHash });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
87
125
|
}
|
|
88
126
|
statusLine("warn", "All branches rejected");
|
|
89
127
|
return ok({ ...context, approvals });
|
|
90
128
|
}
|
|
91
129
|
// Per-branch review
|
|
92
|
-
for (const
|
|
130
|
+
for (const [branchName, plans] of changedBranches) {
|
|
131
|
+
const branchPlansToCommit = plans.filter((p) => p.status === "changed");
|
|
132
|
+
const firstPlan = branchPlansToCommit[0];
|
|
93
133
|
console.log("");
|
|
94
134
|
divider();
|
|
95
|
-
console.log(` ${sym.branch} ${chalk.bold.cyan(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// Show inline diff
|
|
99
|
-
if (deps.config.report.warnOnSecrets) {
|
|
100
|
-
console.log(chalk.yellow(" ⚠ Diff may contain secret values — treat with care"));
|
|
135
|
+
console.log(` ${sym.branch} ${chalk.bold.cyan(branchName)} ${chalk.gray(firstPlan.baseCommitSha.slice(0, 8))} (${branchPlansToCommit.length} file(s) changed)`);
|
|
136
|
+
// Show diffs for each file on this branch
|
|
137
|
+
for (const plan of branchPlansToCommit) {
|
|
101
138
|
console.log("");
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const snapResult = await writeSnapshots(context.project.stagingDir, context.runId, plan);
|
|
106
|
-
let openDiff = false;
|
|
107
|
-
if (snapResult.ok) {
|
|
108
|
-
const choice = await clack.select({
|
|
109
|
-
message: "Action:",
|
|
110
|
-
options: [
|
|
111
|
-
{ value: "approve", label: `${chalk.green("✓")} Approve`, hint: "commit this branch" },
|
|
112
|
-
{ value: "reject", label: `${chalk.red("✗")} Reject`, hint: "skip this branch" },
|
|
113
|
-
{ value: "diff", label: `${chalk.cyan("⊞")} Open in diff viewer`, hint: deps.config.editor.name },
|
|
114
|
-
],
|
|
115
|
-
});
|
|
116
|
-
if (clack.isCancel(choice)) {
|
|
117
|
-
return err(inputCancelledError("Review cancelled"));
|
|
139
|
+
console.log(` ${chalk.bold("File:")} ${chalk.yellow(plan.path)}`);
|
|
140
|
+
if (deps.config.report.warnOnSecrets) {
|
|
141
|
+
console.log(chalk.yellow(" ⚠ Diff may contain secret values — treat with care"));
|
|
118
142
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
143
|
+
renderDiff(plan.diff, false);
|
|
144
|
+
}
|
|
145
|
+
const choice = await clack.select({
|
|
146
|
+
message: `Action for branch ${chalk.cyan(branchName)}:`,
|
|
147
|
+
options: [
|
|
148
|
+
{ value: "approve", label: `${chalk.green("✓")} Approve branch bundle`, hint: `commit ${branchPlansToCommit.length} file(s)` },
|
|
149
|
+
{ value: "reject", label: `${chalk.red("✗")} Reject`, hint: "skip this branch" },
|
|
150
|
+
{ value: "diff", label: `${chalk.cyan("⊞")} Open in external diff viewer`, hint: deps.config.editor.name },
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
if (clack.isCancel(choice)) {
|
|
154
|
+
return err(inputCancelledError("Review cancelled"));
|
|
155
|
+
}
|
|
156
|
+
if (choice === "diff") {
|
|
157
|
+
for (const plan of branchPlansToCommit) {
|
|
158
|
+
const snapResult = await writeSnapshots(context.project.stagingDir, context.runId, plan);
|
|
159
|
+
if (snapResult.ok) {
|
|
160
|
+
await deps.services.editor.openForDiff(snapResult.value.beforePath, snapResult.value.afterPath, deps.config);
|
|
135
161
|
}
|
|
136
|
-
approvals.push({
|
|
137
|
-
branchName: plan.branch.name,
|
|
138
|
-
approved: afterDiff === "approve",
|
|
139
|
-
planHash: plan.planHash,
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
approvals.push({
|
|
144
|
-
branchName: plan.branch.name,
|
|
145
|
-
approved: choice === "approve",
|
|
146
|
-
planHash: plan.planHash,
|
|
147
|
-
});
|
|
148
162
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// No snapshots — just approve/reject
|
|
152
|
-
const choice = await clack.select({
|
|
153
|
-
message: "Action:",
|
|
163
|
+
const afterDiff = await clack.select({
|
|
164
|
+
message: `After reviewing diffs for ${branchName}:`,
|
|
154
165
|
options: [
|
|
155
166
|
{ value: "approve", label: `${chalk.green("✓")} Approve` },
|
|
156
167
|
{ value: "reject", label: `${chalk.red("✗")} Reject` },
|
|
157
168
|
],
|
|
158
169
|
});
|
|
159
|
-
if (clack.isCancel(
|
|
170
|
+
if (clack.isCancel(afterDiff)) {
|
|
160
171
|
return err(inputCancelledError("Review cancelled"));
|
|
161
172
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
approved:
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
const isApproved = afterDiff === "approve";
|
|
174
|
+
for (const plan of branchPlansToCommit) {
|
|
175
|
+
approvals.push({ branchName, approved: isApproved, planHash: plan.planHash });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const isApproved = choice === "approve";
|
|
180
|
+
for (const plan of branchPlansToCommit) {
|
|
181
|
+
approvals.push({ branchName, approved: isApproved, planHash: plan.planHash });
|
|
182
|
+
}
|
|
167
183
|
}
|
|
168
184
|
}
|
|
169
185
|
divider();
|
|
170
|
-
const
|
|
171
|
-
const
|
|
172
|
-
|
|
186
|
+
const approvedCount = new Set(approvals.filter((a) => a.approved).map((a) => a.branchName)).size;
|
|
187
|
+
const rejectedCount = new Set(approvals
|
|
188
|
+
.filter((a) => !a.approved && changedBranches.some(([b]) => b === a.branchName))
|
|
189
|
+
.map((a) => a.branchName)).size;
|
|
190
|
+
statusLine("ok", `Review complete — ${approvedCount} branch(es) approved, ${rejectedCount} rejected`);
|
|
173
191
|
// Confirm before destructive apply
|
|
174
|
-
if (
|
|
192
|
+
if (approvedCount > 0) {
|
|
175
193
|
console.log("");
|
|
176
|
-
console.log(chalk.bold(" Summary of approved
|
|
177
|
-
for (const
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
statusLine("ok",
|
|
194
|
+
console.log(chalk.bold(" Summary of approved branch commits:"));
|
|
195
|
+
for (const [branchName, plans] of changedBranches) {
|
|
196
|
+
const isApp = approvals.some((a) => a.branchName === branchName && a.approved);
|
|
197
|
+
if (isApp) {
|
|
198
|
+
const fileNames = plans
|
|
199
|
+
.filter((p) => p.status === "changed")
|
|
200
|
+
.map((p) => p.path)
|
|
201
|
+
.join(", ");
|
|
202
|
+
statusLine("ok", branchName, `files: ${fileNames}`);
|
|
185
203
|
}
|
|
186
204
|
}
|
|
187
205
|
console.log("");
|
|
188
206
|
const confirm = await clack.confirm({
|
|
189
|
-
message: `Proceed to commit ${
|
|
207
|
+
message: `Proceed to commit ${approvedCount} branch(es)?`,
|
|
190
208
|
initialValue: true,
|
|
191
209
|
});
|
|
192
210
|
if (clack.isCancel(confirm) || !confirm) {
|
package/dist/stages/select.js
CHANGED
|
@@ -3,6 +3,7 @@ import { workspaceError, inputCancelledError } from "../core/errors.js";
|
|
|
3
3
|
import { clack, sectionHeader, statusLine } from "../utils/ui.js";
|
|
4
4
|
import inquirer from "inquirer";
|
|
5
5
|
import chalk from "chalk";
|
|
6
|
+
import { detectPreset } from "../config/repo-presets.js";
|
|
6
7
|
/**
|
|
7
8
|
* Matches a branch name against a pattern.
|
|
8
9
|
* Supports:
|
|
@@ -253,7 +254,7 @@ export const selectTargetsStage = async (context, deps) => {
|
|
|
253
254
|
{
|
|
254
255
|
type: "checkbox",
|
|
255
256
|
name: "picked",
|
|
256
|
-
message: "Select branches to process:",
|
|
257
|
+
message: "Select branches to process (Space: toggle • a: select all • i: invert • Enter: confirm):",
|
|
257
258
|
pageSize: 15,
|
|
258
259
|
choices,
|
|
259
260
|
},
|
|
@@ -325,26 +326,125 @@ export const selectTargetsStage = async (context, deps) => {
|
|
|
325
326
|
clack.log.warn("No branches selected.");
|
|
326
327
|
return err(inputCancelledError("No branches selected"));
|
|
327
328
|
}
|
|
328
|
-
// Target file selection
|
|
329
|
-
let
|
|
330
|
-
if (
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
329
|
+
// ── Target file(s) selection ──────────────────────────────────────────
|
|
330
|
+
let targets = [];
|
|
331
|
+
if (context.input.file) {
|
|
332
|
+
const preset = detectPreset(context.project.remoteUrl, context.project.id);
|
|
333
|
+
const rawPaths = context.input.file
|
|
334
|
+
.split(",")
|
|
335
|
+
.map((p) => p.trim())
|
|
336
|
+
.filter(Boolean);
|
|
337
|
+
targets = rawPaths.map((p) => {
|
|
338
|
+
const presetFile = preset?.files.find((pf) => pf.path === p);
|
|
339
|
+
if (presetFile) {
|
|
340
|
+
return {
|
|
341
|
+
path: presetFile.path,
|
|
342
|
+
description: presetFile.description,
|
|
343
|
+
isDynamic: presetFile.isDynamic,
|
|
344
|
+
dynamicVar: presetFile.dynamicVar,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
return { path: p };
|
|
335
348
|
});
|
|
336
|
-
|
|
337
|
-
|
|
349
|
+
}
|
|
350
|
+
else if (!context.input.ci) {
|
|
351
|
+
const preset = detectPreset(context.project.remoteUrl, context.project.id);
|
|
352
|
+
if (preset) {
|
|
353
|
+
statusLine("ok", `Detected repository preset: ${chalk.bold.cyan(preset.name)}`);
|
|
354
|
+
const CUSTOM_PATH_VAL = "__CUSTOM_PATH__";
|
|
355
|
+
try {
|
|
356
|
+
const { selectedPaths } = await inquirer.prompt([
|
|
357
|
+
{
|
|
358
|
+
type: "checkbox",
|
|
359
|
+
name: "selectedPaths",
|
|
360
|
+
message: "Select template file(s) to edit and sync across branches:",
|
|
361
|
+
pageSize: 15,
|
|
362
|
+
choices: [
|
|
363
|
+
...preset.files.map((f) => ({
|
|
364
|
+
name: `${f.path.padEnd(32)} ${chalk.gray(f.description)}${f.isDynamic ? chalk.yellow(" [dynamic]") : ""}`,
|
|
365
|
+
value: f.path,
|
|
366
|
+
checked: f.path === ".env",
|
|
367
|
+
})),
|
|
368
|
+
new inquirer.Separator(),
|
|
369
|
+
{
|
|
370
|
+
name: chalk.cyan("➕ [Add custom file path...]"),
|
|
371
|
+
value: CUSTOM_PATH_VAL,
|
|
372
|
+
checked: false,
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
validate: (ans) => ans.length > 0 || "Please select at least one file",
|
|
376
|
+
},
|
|
377
|
+
]);
|
|
378
|
+
const chosenPaths = selectedPaths.filter((p) => p !== CUSTOM_PATH_VAL);
|
|
379
|
+
if (selectedPaths.includes(CUSTOM_PATH_VAL)) {
|
|
380
|
+
const customInput = await clack.text({
|
|
381
|
+
message: "Enter custom target file path:",
|
|
382
|
+
placeholder: "config/settings.json",
|
|
383
|
+
validate: (v) => {
|
|
384
|
+
if (!v || v.trim().length === 0)
|
|
385
|
+
return "Please enter a valid path";
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
if (!clack.isCancel(customInput)) {
|
|
389
|
+
chosenPaths.push(customInput.trim());
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
targets = chosenPaths.map((p) => {
|
|
393
|
+
const presetFile = preset.files.find((pf) => pf.path === p);
|
|
394
|
+
if (presetFile) {
|
|
395
|
+
return {
|
|
396
|
+
path: presetFile.path,
|
|
397
|
+
description: presetFile.description,
|
|
398
|
+
isDynamic: presetFile.isDynamic,
|
|
399
|
+
dynamicVar: presetFile.dynamicVar,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
return { path: p };
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
catch (e) {
|
|
406
|
+
if (e.isTtyError ||
|
|
407
|
+
e.name === "ExitPromptError" ||
|
|
408
|
+
e.message?.includes("force closed") ||
|
|
409
|
+
e.message?.includes("User force closed")) {
|
|
410
|
+
return err(inputCancelledError("Target file selection cancelled"));
|
|
411
|
+
}
|
|
412
|
+
targets = [{ path: ".env" }];
|
|
413
|
+
}
|
|
338
414
|
}
|
|
339
|
-
|
|
415
|
+
else {
|
|
416
|
+
// Generic repository target selection
|
|
417
|
+
const fileInput = await clack.text({
|
|
418
|
+
message: "Target file path:",
|
|
419
|
+
placeholder: ".env",
|
|
420
|
+
defaultValue: ".env",
|
|
421
|
+
});
|
|
422
|
+
if (clack.isCancel(fileInput)) {
|
|
423
|
+
return err(inputCancelledError("File selection cancelled"));
|
|
424
|
+
}
|
|
425
|
+
const rawPath = fileInput || ".env";
|
|
426
|
+
targets = rawPath
|
|
427
|
+
.split(",")
|
|
428
|
+
.map((p) => p.trim())
|
|
429
|
+
.filter(Boolean)
|
|
430
|
+
.map((p) => ({ path: p }));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
targets = [{ path: ".env" }];
|
|
340
435
|
}
|
|
341
|
-
|
|
342
|
-
|
|
436
|
+
if (targets.length === 0) {
|
|
437
|
+
targets = [{ path: ".env" }];
|
|
343
438
|
}
|
|
344
|
-
|
|
439
|
+
const primaryTarget = targets[0];
|
|
440
|
+
const targetSummary = targets.length === 1
|
|
441
|
+
? targets[0].path
|
|
442
|
+
: `${targets.length} files (${targets.map((t) => t.path).join(", ")})`;
|
|
443
|
+
statusLine("ok", `Selected ${branches.length} branch(es) → ${targetSummary}`);
|
|
345
444
|
return ok({
|
|
346
445
|
...context,
|
|
347
446
|
selectedBranches: branches,
|
|
348
|
-
target:
|
|
447
|
+
target: primaryTarget,
|
|
448
|
+
targets,
|
|
349
449
|
});
|
|
350
450
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@samaksh/git-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Safe, composable TypeScript CLI/TUI for applying reviewed file changes across many Git branches",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,11 +15,9 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"README.md",
|
|
18
|
+
"LICENSE",
|
|
18
19
|
"docs"
|
|
19
20
|
],
|
|
20
|
-
"licenses": [
|
|
21
|
-
"MIT"
|
|
22
|
-
],
|
|
23
21
|
"scripts": {
|
|
24
22
|
"build": "tsc",
|
|
25
23
|
"prepublishOnly": "npm run build",
|
|
@@ -38,7 +36,7 @@
|
|
|
38
36
|
"branches",
|
|
39
37
|
"multi-branch"
|
|
40
38
|
],
|
|
41
|
-
"author": "",
|
|
39
|
+
"author": "Samaksh Grover <samaksh@bsure.live>",
|
|
42
40
|
"license": "MIT",
|
|
43
41
|
"dependencies": {
|
|
44
42
|
"@clack/prompts": "^1.8.1",
|