@ondrej-svec/hog 1.4.0 → 1.6.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/dist/cli.js CHANGED
@@ -163,6 +163,7 @@ var init_config = __esm({
163
163
  shortName: z.string().min(1),
164
164
  projectNumber: z.number().int().positive(),
165
165
  statusFieldId: z.string().min(1),
166
+ dueDateFieldId: z.string().optional(),
166
167
  completionAction: COMPLETION_ACTION_SCHEMA,
167
168
  statusGroups: z.array(z.string()).optional()
168
169
  });
@@ -532,7 +533,7 @@ function fetchProjectFields(repo, issueNumber, projectNumber) {
532
533
  const fieldValues = projectItem.fieldValues?.nodes ?? [];
533
534
  for (const fv of fieldValues) {
534
535
  if (!fv) continue;
535
- if ("date" in fv && fv.field?.name === "Target date") {
536
+ if ("date" in fv && DATE_FIELD_NAME_RE2.test(fv.field?.name ?? "")) {
536
537
  fields.targetDate = fv.date;
537
538
  }
538
539
  if ("name" in fv && fv.field?.name === "Status") {
@@ -594,7 +595,7 @@ function fetchProjectEnrichment(repo, projectNumber) {
594
595
  const fieldValues = item.fieldValues?.nodes ?? [];
595
596
  for (const fv of fieldValues) {
596
597
  if (!fv) continue;
597
- if ("date" in fv && fv.field?.name === "Target date" && fv.date) {
598
+ if ("date" in fv && fv.date && DATE_FIELD_NAME_RE2.test(fv.field?.name ?? "")) {
598
599
  enrichment.targetDate = fv.date;
599
600
  }
600
601
  if ("name" in fv && fv.field?.name === "Status" && fv.name) {
@@ -824,11 +825,91 @@ async function updateProjectItemStatusAsync(repo, issueNumber, projectConfig) {
824
825
  `optionId=${optionId}`
825
826
  ]);
826
827
  }
827
- var execFileAsync;
828
+ async function updateProjectItemDateAsync(repo, issueNumber, projectConfig, dueDate) {
829
+ const [owner, repoName] = repo.split("/");
830
+ const findItemQuery = `
831
+ query($owner: String!, $repo: String!, $issueNumber: Int!) {
832
+ repository(owner: $owner, name: $repo) {
833
+ issue(number: $issueNumber) {
834
+ projectItems(first: 10) {
835
+ nodes {
836
+ id
837
+ project { number }
838
+ }
839
+ }
840
+ }
841
+ }
842
+ }
843
+ `;
844
+ const findResult = await runGhJsonAsync([
845
+ "api",
846
+ "graphql",
847
+ "-f",
848
+ `query=${findItemQuery}`,
849
+ "-F",
850
+ `owner=${owner}`,
851
+ "-F",
852
+ `repo=${repoName}`,
853
+ "-F",
854
+ `issueNumber=${String(issueNumber)}`
855
+ ]);
856
+ const items = findResult?.data?.repository?.issue?.projectItems?.nodes ?? [];
857
+ const projectItem = items.find((item) => item?.project?.number === projectConfig.projectNumber);
858
+ if (!projectItem?.id) return;
859
+ const projectQuery = `
860
+ query($owner: String!) {
861
+ organization(login: $owner) {
862
+ projectV2(number: ${projectConfig.projectNumber}) {
863
+ id
864
+ }
865
+ }
866
+ }
867
+ `;
868
+ const projectResult = await runGhJsonAsync([
869
+ "api",
870
+ "graphql",
871
+ "-f",
872
+ `query=${projectQuery}`,
873
+ "-F",
874
+ `owner=${owner}`
875
+ ]);
876
+ const projectId = projectResult?.data?.organization?.projectV2?.id;
877
+ if (!projectId) return;
878
+ const mutation = `
879
+ mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $date: Date!) {
880
+ updateProjectV2ItemFieldValue(
881
+ input: {
882
+ projectId: $projectId
883
+ itemId: $itemId
884
+ fieldId: $fieldId
885
+ value: { date: $date }
886
+ }
887
+ ) {
888
+ projectV2Item { id }
889
+ }
890
+ }
891
+ `;
892
+ await runGhAsync([
893
+ "api",
894
+ "graphql",
895
+ "-f",
896
+ `query=${mutation}`,
897
+ "-F",
898
+ `projectId=${projectId}`,
899
+ "-F",
900
+ `itemId=${projectItem.id}`,
901
+ "-F",
902
+ `fieldId=${projectConfig.dueDateFieldId}`,
903
+ "-F",
904
+ `date=${dueDate}`
905
+ ]);
906
+ }
907
+ var execFileAsync, DATE_FIELD_NAME_RE2;
828
908
  var init_github = __esm({
829
909
  "src/github.ts"() {
830
910
  "use strict";
831
911
  execFileAsync = promisify(execFile);
912
+ DATE_FIELD_NAME_RE2 = /^(target\s*date|due\s*date|due|deadline)$/i;
832
913
  }
833
914
  });
834
915
 
@@ -1222,8 +1303,16 @@ function useActions({
1222
1303
  });
1223
1304
  }, [toast, refresh]);
1224
1305
  const handleCreateIssue = useCallback(
1225
- async (repo, title, labels) => {
1226
- const args = ["issue", "create", "--repo", repo, "--title", title];
1306
+ async (repo, title, body, dueDate, labels) => {
1307
+ const repoConfig = configRef.current.repos.find((r) => r.name === repo);
1308
+ let effectiveBody = body;
1309
+ if (dueDate && !repoConfig?.dueDateFieldId) {
1310
+ const dueLine = `Due: ${dueDate}`;
1311
+ effectiveBody = body ? `${body}
1312
+
1313
+ ${dueLine}` : dueLine;
1314
+ }
1315
+ const args = ["issue", "create", "--repo", repo, "--title", title, "--body", effectiveBody];
1227
1316
  if (labels && labels.length > 0) {
1228
1317
  for (const label of labels) {
1229
1318
  args.push("--label", label);
@@ -1235,7 +1324,15 @@ function useActions({
1235
1324
  const output = stdout.trim();
1236
1325
  const match = output.match(/\/(\d+)$/);
1237
1326
  const issueNumber = match?.[1] ? parseInt(match[1], 10) : 0;
1238
- const shortName = configRef.current.repos.find((r) => r.name === repo)?.shortName ?? repo;
1327
+ const shortName = repoConfig?.shortName ?? repo;
1328
+ if (issueNumber > 0 && dueDate && repoConfig?.dueDateFieldId) {
1329
+ const dueDateConfig = {
1330
+ projectNumber: repoConfig.projectNumber,
1331
+ dueDateFieldId: repoConfig.dueDateFieldId
1332
+ };
1333
+ updateProjectItemDateAsync(repo, issueNumber, dueDateConfig, dueDate).catch(() => {
1334
+ });
1335
+ }
1239
1336
  t.resolve(`Created ${shortName}#${issueNumber}`);
1240
1337
  refresh();
1241
1338
  onOverlayDone();
@@ -2778,13 +2875,19 @@ function CreateIssueForm({
2778
2875
  currentLabels: [],
2779
2876
  labelCache: labelCache ?? {},
2780
2877
  onConfirm: (addLabels) => {
2781
- onSubmit(selectedRepo.name, title, addLabels.length > 0 ? addLabels : void 0);
2878
+ onSubmit(
2879
+ selectedRepo.name,
2880
+ title,
2881
+ "",
2882
+ null,
2883
+ addLabels.length > 0 ? addLabels : void 0
2884
+ );
2782
2885
  },
2783
2886
  onCancel: () => {
2784
- onSubmit(selectedRepo.name, title);
2887
+ onSubmit(selectedRepo.name, title, "", null);
2785
2888
  },
2786
2889
  onError: () => {
2787
- onSubmit(selectedRepo.name, title);
2890
+ onSubmit(selectedRepo.name, title, "", null);
2788
2891
  }
2789
2892
  }
2790
2893
  )
@@ -2820,7 +2923,7 @@ function CreateIssueForm({
2820
2923
  setTitle(trimmed);
2821
2924
  setField("labels");
2822
2925
  } else {
2823
- onSubmit(selectedRepo.name, trimmed);
2926
+ onSubmit(selectedRepo.name, trimmed, "", null);
2824
2927
  }
2825
2928
  }
2826
2929
  }
@@ -3018,8 +3121,12 @@ var init_help_overlay = __esm({
3018
3121
  });
3019
3122
 
3020
3123
  // src/board/components/nl-create-overlay.tsx
3124
+ import { spawnSync as spawnSync2 } from "child_process";
3125
+ import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
3126
+ import { tmpdir as tmpdir2 } from "os";
3127
+ import { join as join4 } from "path";
3021
3128
  import { Spinner as Spinner2, TextInput as TextInput3 } from "@inkjs/ui";
3022
- import { Box as Box9, Text as Text9, useInput as useInput9 } from "ink";
3129
+ import { Box as Box9, Text as Text9, useInput as useInput9, useStdin as useStdin2 } from "ink";
3023
3130
  import { useCallback as useCallback9, useEffect as useEffect5, useRef as useRef9, useState as useState9 } from "react";
3024
3131
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
3025
3132
  function NlCreateOverlay({
@@ -3028,15 +3135,28 @@ function NlCreateOverlay({
3028
3135
  labelCache,
3029
3136
  onSubmit,
3030
3137
  onCancel,
3138
+ onPauseRefresh,
3139
+ onResumeRefresh,
3031
3140
  onLlmFallback
3032
3141
  }) {
3033
3142
  const [, setInput] = useState9("");
3034
3143
  const [isParsing, setIsParsing] = useState9(false);
3035
3144
  const [parsed, setParsed] = useState9(null);
3036
3145
  const [parseError, setParseError] = useState9(null);
3037
- const [createError, setCreateError] = useState9(null);
3146
+ const [step, setStep] = useState9("input");
3147
+ const [body, setBody] = useState9("");
3148
+ const [editingBody, setEditingBody] = useState9(false);
3038
3149
  const submittedRef = useRef9(false);
3039
3150
  const parseParamsRef = useRef9(null);
3151
+ const onSubmitRef = useRef9(onSubmit);
3152
+ const onCancelRef = useRef9(onCancel);
3153
+ const onPauseRef = useRef9(onPauseRefresh);
3154
+ const onResumeRef = useRef9(onResumeRefresh);
3155
+ onSubmitRef.current = onSubmit;
3156
+ onCancelRef.current = onCancel;
3157
+ onPauseRef.current = onPauseRefresh;
3158
+ onResumeRef.current = onResumeRefresh;
3159
+ const { setRawMode } = useStdin2();
3040
3160
  const defaultRepoIdx = defaultRepoName ? Math.max(
3041
3161
  0,
3042
3162
  repos.findIndex((r) => r.name === defaultRepoName)
@@ -3044,19 +3164,19 @@ function NlCreateOverlay({
3044
3164
  const [repoIdx, setRepoIdx] = useState9(defaultRepoIdx);
3045
3165
  const selectedRepo = repos[repoIdx];
3046
3166
  useInput9((inputChar, key) => {
3047
- if (isParsing) return;
3167
+ if (isParsing || editingBody) return;
3048
3168
  if (key.escape) {
3169
+ if (step === "body") {
3170
+ setStep("input");
3171
+ setParsed((p) => p);
3172
+ return;
3173
+ }
3049
3174
  onCancel();
3050
3175
  return;
3051
3176
  }
3052
- if (parsed) {
3177
+ if (parsed && step === "input") {
3053
3178
  if (key.return) {
3054
- if (submittedRef.current) return;
3055
- submittedRef.current = true;
3056
- if (!selectedRepo) return;
3057
- setCreateError(null);
3058
- const labels = buildLabelList(parsed);
3059
- onSubmit(selectedRepo.name, parsed.title, labels.length > 0 ? labels : void 0);
3179
+ setStep("body");
3060
3180
  return;
3061
3181
  }
3062
3182
  if (inputChar === "r") {
@@ -3064,7 +3184,43 @@ function NlCreateOverlay({
3064
3184
  return;
3065
3185
  }
3066
3186
  }
3187
+ if (step === "body" && inputChar === "") {
3188
+ setEditingBody(true);
3189
+ }
3067
3190
  });
3191
+ useEffect5(() => {
3192
+ if (!editingBody) return;
3193
+ const editorEnv = process.env["VISUAL"] ?? process.env["EDITOR"] ?? "vi";
3194
+ const [cmd, ...extraArgs] = editorEnv.split(" ").filter(Boolean);
3195
+ if (!cmd) {
3196
+ setEditingBody(false);
3197
+ return;
3198
+ }
3199
+ let tmpDir = null;
3200
+ let tmpFile = null;
3201
+ try {
3202
+ onPauseRef.current?.();
3203
+ tmpDir = mkdtempSync2(join4(tmpdir2(), "hog-body-"));
3204
+ tmpFile = join4(tmpDir, "body.md");
3205
+ writeFileSync4(tmpFile, body);
3206
+ const inkInstance = getInkInstance();
3207
+ inkInstance?.clear();
3208
+ setRawMode(false);
3209
+ spawnSync2(cmd, [...extraArgs, tmpFile], { stdio: "inherit" });
3210
+ const content = readFileSync4(tmpFile, "utf-8");
3211
+ setRawMode(true);
3212
+ setBody(content.trimEnd());
3213
+ } finally {
3214
+ onResumeRef.current?.();
3215
+ if (tmpFile && tmpDir) {
3216
+ try {
3217
+ rmSync2(tmpDir, { recursive: true, force: true });
3218
+ } catch {
3219
+ }
3220
+ }
3221
+ setEditingBody(false);
3222
+ }
3223
+ }, [editingBody, body, setRawMode]);
3068
3224
  const handleInputSubmit = useCallback9(
3069
3225
  (text) => {
3070
3226
  const trimmed = text.trim();
@@ -3103,8 +3259,48 @@ function NlCreateOverlay({
3103
3259
  /* @__PURE__ */ jsx9(Spinner2, { label: "Parsing..." })
3104
3260
  ] });
3105
3261
  }
3262
+ if (parsed && step === "body") {
3263
+ if (editingBody) {
3264
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
3265
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
3266
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "Opening editor for body\u2026" })
3267
+ ] });
3268
+ }
3269
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
3270
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
3271
+ /* @__PURE__ */ jsxs9(Box9, { children: [
3272
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Title: " }),
3273
+ /* @__PURE__ */ jsx9(Text9, { children: parsed.title })
3274
+ ] }),
3275
+ /* @__PURE__ */ jsxs9(Box9, { children: [
3276
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "body: " }),
3277
+ /* @__PURE__ */ jsx9(
3278
+ TextInput3,
3279
+ {
3280
+ defaultValue: body,
3281
+ placeholder: "optional description (ctrl+e for editor)",
3282
+ onChange: setBody,
3283
+ onSubmit: (text) => {
3284
+ if (submittedRef.current) return;
3285
+ submittedRef.current = true;
3286
+ if (!selectedRepo) return;
3287
+ const labels = buildLabelList(parsed);
3288
+ onSubmitRef.current(
3289
+ selectedRepo.name,
3290
+ parsed.title,
3291
+ text.trim(),
3292
+ parsed.dueDate,
3293
+ labels.length > 0 ? labels : void 0
3294
+ );
3295
+ }
3296
+ }
3297
+ )
3298
+ ] }),
3299
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Enter:create ctrl+e:editor Esc:back" })
3300
+ ] });
3301
+ }
3106
3302
  if (parsed) {
3107
- const labels = buildLabelList(parsed);
3303
+ const labels = [...parsed.labels];
3108
3304
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
3109
3305
  /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "\u2728 Creating Issue" }),
3110
3306
  /* @__PURE__ */ jsxs9(Box9, { children: [
@@ -3131,9 +3327,7 @@ function NlCreateOverlay({
3131
3327
  /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Due: " }),
3132
3328
  /* @__PURE__ */ jsx9(Text9, { children: formatDue(parsed.dueDate) })
3133
3329
  ] }) : null,
3134
- parsed.dueDate && selectedRepo && !hasDueLabelInCache(labelCache, selectedRepo.name) ? /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u26A0 No due:* label in this repo \u2014 will try to create label on submit" }) : null,
3135
- createError ? /* @__PURE__ */ jsx9(Text9, { color: "red", children: createError }) : null,
3136
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Enter:create Esc:cancel" })
3330
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Enter:add body Esc:cancel" })
3137
3331
  ] });
3138
3332
  }
3139
3333
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
@@ -3154,24 +3348,17 @@ function NlCreateOverlay({
3154
3348
  ] });
3155
3349
  }
3156
3350
  function buildLabelList(parsed) {
3157
- const labels = [...parsed.labels];
3158
- if (parsed.dueDate) {
3159
- labels.push(`due:${parsed.dueDate}`);
3160
- }
3161
- return labels;
3162
- }
3163
- function hasDueLabelInCache(labelCache, repoName) {
3164
- return (labelCache[repoName] ?? []).some((l) => l.name.startsWith("due:"));
3351
+ return [...parsed.labels];
3165
3352
  }
3166
3353
  function formatDue(dueDate) {
3167
3354
  const d = /* @__PURE__ */ new Date(`${dueDate}T12:00:00`);
3168
- const human = d.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
3169
- return `${human} (label: due:${dueDate})`;
3355
+ return d.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
3170
3356
  }
3171
3357
  var init_nl_create_overlay = __esm({
3172
3358
  "src/board/components/nl-create-overlay.tsx"() {
3173
3359
  "use strict";
3174
3360
  init_ai();
3361
+ init_ink_instance();
3175
3362
  }
3176
3363
  });
3177
3364
 
@@ -3411,6 +3598,8 @@ function OverlayRenderer({
3411
3598
  labelCache,
3412
3599
  onSubmit: onCreateIssue,
3413
3600
  onCancel: onExitOverlay,
3601
+ onPauseRefresh,
3602
+ onResumeRefresh,
3414
3603
  onLlmFallback
3415
3604
  }
3416
3605
  ) : null
@@ -3711,7 +3900,7 @@ var init_toast_container = __esm({
3711
3900
  });
3712
3901
 
3713
3902
  // src/board/components/dashboard.tsx
3714
- import { execFileSync as execFileSync3, spawnSync as spawnSync2 } from "child_process";
3903
+ import { execFileSync as execFileSync3, spawnSync as spawnSync3 } from "child_process";
3715
3904
  import { Spinner as Spinner4 } from "@inkjs/ui";
3716
3905
  import { Box as Box16, Text as Text16, useApp, useStdout } from "ink";
3717
3906
  import { useCallback as useCallback10, useEffect as useEffect6, useMemo as useMemo2, useRef as useRef11, useState as useState11 } from "react";
@@ -4046,8 +4235,8 @@ function Dashboard({ config: config2, options, activeProfile }) {
4046
4235
  const pendingPickRef = useRef11(null);
4047
4236
  const labelCacheRef = useRef11({});
4048
4237
  const handleCreateIssueWithPrompt = useCallback10(
4049
- (repo, title, labels) => {
4050
- actions.handleCreateIssue(repo, title, labels).then((result) => {
4238
+ (repo, title, body, dueDate, labels) => {
4239
+ actions.handleCreateIssue(repo, title, body, dueDate, labels).then((result) => {
4051
4240
  if (result) {
4052
4241
  pendingPickRef.current = result;
4053
4242
  ui.enterConfirmPick();
@@ -4212,7 +4401,7 @@ function Dashboard({ config: config2, options, activeProfile }) {
4212
4401
  toast.info(`${label} \u2014 ${found.issue.url}`);
4213
4402
  return;
4214
4403
  }
4215
- const result = spawnSync2(cmd, args, {
4404
+ const result = spawnSync3(cmd, args, {
4216
4405
  input: found.issue.url,
4217
4406
  stdio: ["pipe", "pipe", "pipe"]
4218
4407
  });
@@ -4963,6 +5152,34 @@ function detectStatusField(owner, projectNumber) {
4963
5152
  if (!statusField) return null;
4964
5153
  return { fieldId: statusField.id, options: statusField.options ?? [] };
4965
5154
  }
5155
+ var DATE_FIELD_NAME_RE = /^(target\s*date|due\s*date|due|deadline)$/i;
5156
+ function detectDateField(owner, projectNumber) {
5157
+ const fields = listProjectFields(owner, projectNumber);
5158
+ return fields.find((f) => DATE_FIELD_NAME_RE.test(f.name)) ?? null;
5159
+ }
5160
+ function createDateField(owner, projectNumber, fieldName) {
5161
+ try {
5162
+ execFileSync(
5163
+ "gh",
5164
+ [
5165
+ "project",
5166
+ "field-create",
5167
+ String(projectNumber),
5168
+ "--owner",
5169
+ owner,
5170
+ "--name",
5171
+ fieldName,
5172
+ "--data-type",
5173
+ "DATE"
5174
+ ],
5175
+ { encoding: "utf-8", timeout: 3e4 }
5176
+ );
5177
+ const fields = listProjectFields(owner, projectNumber);
5178
+ return fields.find((f) => f.name === fieldName)?.id ?? null;
5179
+ } catch {
5180
+ return null;
5181
+ }
5182
+ }
4966
5183
  async function runInit(opts = {}) {
4967
5184
  try {
4968
5185
  await runWizard(opts);
@@ -5046,6 +5263,37 @@ Configuring ${repoName}...`);
5046
5263
  message: " Enter status field ID manually:"
5047
5264
  });
5048
5265
  }
5266
+ console.log(" Detecting due date field...");
5267
+ let dueDateFieldId;
5268
+ const existingDateField = detectDateField(owner, projectNumber);
5269
+ if (existingDateField) {
5270
+ console.log(` Found date field: "${existingDateField.name}" (${existingDateField.id})`);
5271
+ const useDateField = await confirm({
5272
+ message: ` Use "${existingDateField.name}" for due dates?`,
5273
+ default: true
5274
+ });
5275
+ if (useDateField) {
5276
+ dueDateFieldId = existingDateField.id;
5277
+ }
5278
+ } else {
5279
+ console.log(" No due date field found in this project.");
5280
+ const createField = await confirm({
5281
+ message: ' Create a "Due Date" field for due dates?',
5282
+ default: false
5283
+ });
5284
+ if (createField) {
5285
+ console.log(' Creating "Due Date" field...');
5286
+ const newFieldId = createDateField(owner, projectNumber, "Due Date");
5287
+ if (newFieldId) {
5288
+ dueDateFieldId = newFieldId;
5289
+ console.log(` Created "Due Date" field (${newFieldId})`);
5290
+ } else {
5291
+ console.log(" Could not create field \u2014 due dates will be stored in issue body.");
5292
+ }
5293
+ } else {
5294
+ console.log(" Skipped \u2014 due dates will be stored in issue body.");
5295
+ }
5296
+ }
5049
5297
  const completionType = await select({
5050
5298
  message: ` When a task is completed, what should happen on GitHub?`,
5051
5299
  choices: [
@@ -5090,6 +5338,7 @@ Configuring ${repoName}...`);
5090
5338
  shortName,
5091
5339
  projectNumber,
5092
5340
  statusFieldId,
5341
+ ...dueDateFieldId ? { dueDateFieldId } : {},
5093
5342
  completionAction
5094
5343
  });
5095
5344
  }
@@ -5556,7 +5805,7 @@ function resolveProjectId(projectId) {
5556
5805
  process.exit(1);
5557
5806
  }
5558
5807
  var program = new Command();
5559
- program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.4.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
5808
+ program.name("hog").description("Personal command deck \u2014 unified task dashboard for GitHub Projects + TickTick").version("1.6.0").option("--json", "Force JSON output").option("--human", "Force human-readable output").hook("preAction", (thisCommand) => {
5560
5809
  const opts = thisCommand.opts();
5561
5810
  if (opts.json) setFormat("json");
5562
5811
  if (opts.human) setFormat("human");
@@ -5993,7 +6242,7 @@ issueCommand.command("create <text>").description("Create a GitHub issue from na
5993
6242
  console.error("[dry-run] Skipping issue creation.");
5994
6243
  return;
5995
6244
  }
5996
- const args = ["issue", "create", "--repo", repo, "--title", parsed.title];
6245
+ const args = ["issue", "create", "--repo", repo, "--title", parsed.title, "--body", ""];
5997
6246
  for (const label of labels) {
5998
6247
  args.push("--label", label);
5999
6248
  }