@goodtek/vibeops 2.4.3 → 2.5.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.
@@ -49,7 +49,7 @@ export function computeNextHint(input) {
49
49
  if (input.hasMergeRequest && !input.mergeRequestMerged)
50
50
  return "task-merge";
51
51
  if (input.hasLocalChanges)
52
- return "task-reship";
52
+ return "task-ship-followup";
53
53
  return "task-add";
54
54
  }
55
55
  if (!input.resultFilled || !input.testFilled) {
@@ -57,36 +57,48 @@ export function computeNextHint(input) {
57
57
  }
58
58
  return input.hasMergeRequest ? "task-merge" : "task-ship";
59
59
  }
60
- export function hintToText(hint, cwd, task) {
60
+ /** Multi-line NEXT block lines (without the leading arrow prefix). */
61
+ export function hintToLines(hint, cwd, task) {
61
62
  switch (hint) {
62
63
  case "init":
63
- return "Run `vibeops init` in this directory.";
64
+ return ["vibeops init"];
64
65
  case "task-add":
65
- return "Run `vibeops task add` to start the next slice.";
66
+ return ["vibeops task add"];
66
67
  case "task-ship":
67
- return task ? `Run \`vibeops task ship ${task.id}\`.` : "Run `vibeops task ship`.";
68
- case "task-reship":
68
+ return [task ? `vibeops task ship ${task.id}` : "vibeops task ship"];
69
+ case "task-ship-followup":
69
70
  return task
70
- ? `Follow-up on ${task.id}? Edit files (develop is fine), then \`vibeops task reship ${task.id}\`.`
71
- : "Run `vibeops task reship TASK-NNN` for a Shipped follow-up.";
71
+ ? [
72
+ `Follow up on ${task.id} (after merge: confirm or --new-cycle)`,
73
+ `vibeops task ship ${task.id}`,
74
+ ]
75
+ : ["vibeops task ship --new-cycle"];
72
76
  case "task-merge":
73
77
  return task
74
- ? `Merge the MR (UI or \`vibeops task merge ${task.id}\`), then optional task sync.`
75
- : "Merge the MR on the host or with `vibeops task merge`.";
78
+ ? [`vibeops task merge ${task.id}`, "(or merge in the host UI)"]
79
+ : ["vibeops task merge"];
76
80
  case "task-sync":
77
81
  return task
78
- ? `Run \`vibeops task sync ${task.id}\` to delete task branches, then task add.`
79
- : "Run `vibeops task sync` to delete task branches after merge.";
82
+ ? [`vibeops task sync ${task.id}`, "then: vibeops task add"]
83
+ : ["vibeops task sync"];
80
84
  case "cursor-plan":
81
85
  return task
82
- ? `In Cursor Ask: @${relPath(cwd, task.filePath)} — refine Scope / AC.`
83
- : "Open the TASK file in Cursor Ask.";
86
+ ? [
87
+ `Cursor Ask: @${relPath(cwd, task.filePath)} — refine Scope / AC`,
88
+ ]
89
+ : ["Open the TASK file in Cursor Ask"];
84
90
  case "cursor-implement":
85
91
  return task
86
- ? `In Cursor Agent: @${relPath(cwd, task.filePath)} — implement, then task ship.`
87
- : "Implement per the TASK file in Cursor.";
92
+ ? [
93
+ `Cursor Agent: @${relPath(cwd, task.filePath)} — implement`,
94
+ `then: vibeops task ship ${task.id}`,
95
+ ]
96
+ : ["Implement per the TASK file, then vibeops task ship"];
88
97
  }
89
98
  }
99
+ export function hintToText(hint, cwd, task) {
100
+ return hintToLines(hint, cwd, task).join(" · ");
101
+ }
90
102
  export async function listInProgressTasks(paths) {
91
103
  return (await loadActionableTasks(paths.docsTasks)).filter((t) => t.status === "in_progress");
92
104
  }
@@ -1,3 +1,4 @@
1
+ import { formatHostCliHint, formatHostCliMissingMessage } from "./git-host-cli.js";
1
2
  import { readText } from "./filesystem.js";
2
3
  import { readConfig } from "./config.js";
3
4
  import { detectGitHost, mergeRequestLabel } from "./git-host.js";
@@ -94,8 +95,11 @@ export async function finishTaskWithPullRequest(opts) {
94
95
  }
95
96
  const cliOk = await probeMergeRequestCli(gitCfg.host);
96
97
  if (!cliOk) {
97
- const tool = gitCfg.host === "gitlab" ? "glab" : "gh";
98
- log.warn(`${tool} CLI not found — create the ${label} manually: ${gitCtx.taskBranch} → ${gitCtx.baseBranch}`);
98
+ log.warn(formatHostCliMissingMessage(gitCfg.host, `create the ${label}`));
99
+ for (const line of formatHostCliHint(gitCfg.host)) {
100
+ log.info(dim(` ${line}`));
101
+ }
102
+ log.info(dim(`Create the ${label} manually: ${gitCtx.taskBranch} → ${gitCtx.baseBranch}`));
99
103
  return { ok: true, pushed: true };
100
104
  }
101
105
  const config = await readConfig(opts.cwd);
@@ -43,7 +43,7 @@ export function reshipNotFoundMessage(taskRef) {
43
43
  if (taskRef?.trim()) {
44
44
  return `Shipped TASK not found: ${normalizeTaskRef(taskRef)}. Check docs/tasks/.`;
45
45
  }
46
- return "No Shipped TASK found. Pass `vibeops task reship TASK-NNN`.";
46
+ return "No Shipped TASK found. Pass `vibeops task ship TASK-NNN` (use --new-cycle after merge).";
47
47
  }
48
48
  async function switchToTaskBranch(cwd, taskBranch) {
49
49
  try {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@goodtek/vibeops",
3
- "version": "2.4.3",
3
+ "version": "2.5.0",
4
4
  "description": "Minimal CLI rails for Cursor-based TASK-driven vibe coding.",
5
5
  "type": "module",
6
+ "packageManager": "pnpm@9.15.9",
6
7
  "author": "VibeOps contributors",
7
8
  "license": "MIT",
8
9
  "repository": {
@@ -29,6 +30,17 @@
29
30
  "engines": {
30
31
  "node": ">=20"
31
32
  },
33
+ "scripts": {
34
+ "dev": "tsx src/cli.ts",
35
+ "build": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit",
37
+ "start": "node dist/cli.js",
38
+ "test": "pnpm build && node --test \"tests/*.test.mjs\"",
39
+ "smoke": "pnpm typecheck && pnpm build && node --test \"tests/*.test.mjs\" && node scripts/smoke.mjs",
40
+ "clean": "rm -rf dist",
41
+ "prepack": "pnpm clean && pnpm build",
42
+ "publish:dry": "pnpm publish --dry-run --no-git-checks"
43
+ },
32
44
  "keywords": [
33
45
  "cursor",
34
46
  "ai",
@@ -47,15 +59,5 @@
47
59
  "@types/node": "^20.14.0",
48
60
  "tsx": "^4.19.0",
49
61
  "typescript": "^5.5.4"
50
- },
51
- "scripts": {
52
- "dev": "tsx src/cli.ts",
53
- "build": "tsc -p tsconfig.json",
54
- "typecheck": "tsc -p tsconfig.json --noEmit",
55
- "start": "node dist/cli.js",
56
- "test": "pnpm build && node --test \"tests/*.test.mjs\"",
57
- "smoke": "pnpm typecheck && pnpm build && node --test \"tests/*.test.mjs\" && node scripts/smoke.mjs",
58
- "clean": "rm -rf dist",
59
- "publish:dry": "pnpm publish --dry-run --no-git-checks"
60
62
  }
61
- }
63
+ }
@@ -40,5 +40,5 @@ vibeops llm connect # optional — task add / ship
40
40
 
41
41
  - One **In Progress** TASK at a time; **Shipped** does not block `task add`.
42
42
  - Fill **Result** and **Test Result** before `vibeops task ship` (warned, not blocked, when updating an open PR).
43
- - `ship` is state-aware: re-run it to update an open PR; after merge it needs `--new-cycle` (or a confirm) to start a new PR cycle. `task reship` still works as a deprecated alias for `task ship --new-cycle`.
43
+ - `ship` is state-aware: re-run it to update an open PR; after merge it needs `--new-cycle` (or a confirm) to start a new PR cycle.
44
44
  - Agents do not run `task merge` or `task sync` unless the human asks.
@@ -5,5 +5,5 @@
5
5
  ## D-001 · VibeOps workflow
6
6
 
7
7
  - **Date:** {{CREATED_AT}}
8
- - **Decision:** TASK-driven development with `vibeops task add` / `task ship` / `task reship` / `merge` / `sync` and Cursor for plan/build. TASK status: **In Progress** → **Shipped** only.
8
+ - **Decision:** TASK-driven development with `vibeops task add` / `task ship` / `merge` / `sync` and Cursor for plan/build. TASK status: **In Progress** → **Shipped** only.
9
9
  - **Why:** Git `docs/tasks` beats chat as source of truth.
@@ -1,21 +0,0 @@
1
- import { dim, log, yellow } from "../lib/logger.js";
2
- import { taskShipCommand } from "./task-ship.js";
3
- /**
4
- * @deprecated `reship` is now `vibeops task ship --new-cycle`.
5
- * Kept as a thin alias for backward compatibility.
6
- */
7
- export async function taskReshipCommand(taskRef, options = {}) {
8
- log.warn(`${yellow("reship is now `ship` (deprecated alias)")} — delegating to \`vibeops task ship --new-cycle\`.`);
9
- log.info(dim("Run `vibeops task ship` directly; it detects first submit / open-PR update / new PR cycle."));
10
- log.blank();
11
- await taskShipCommand(taskRef, {
12
- dryRun: options.dryRun,
13
- cwd: options.cwd,
14
- noPr: options.noPr,
15
- newCycle: true,
16
- noIntegrate: options.noIntegrate,
17
- recreateBranch: options.recreateBranch,
18
- skipLlm: options.skipLlm,
19
- allowOpenMr: options.allowOpenMr,
20
- });
21
- }