@goodtek/vibeops 0.7.22 → 1.1.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 (144) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +51 -380
  3. package/dist/bootstrap/installer.js +42 -20
  4. package/dist/bootstrap/manifest.js +23 -3
  5. package/dist/cli.js +69 -154
  6. package/dist/commands/init.js +279 -114
  7. package/dist/commands/llm.js +177 -0
  8. package/dist/commands/status.js +181 -8
  9. package/dist/commands/task-add.js +89 -162
  10. package/dist/commands/task-done.js +112 -73
  11. package/dist/lib/config.js +77 -113
  12. package/dist/lib/env.js +32 -0
  13. package/dist/lib/git-config.js +21 -0
  14. package/dist/lib/git-host.js +12 -0
  15. package/dist/lib/git-policy.js +67 -0
  16. package/dist/lib/git-remote.js +108 -0
  17. package/dist/lib/git.js +44 -1
  18. package/dist/lib/init-clients.js +55 -0
  19. package/dist/lib/llm-complete.js +18 -19
  20. package/dist/lib/llm-connect.js +150 -0
  21. package/dist/lib/llm-preference.js +102 -0
  22. package/dist/lib/llm-status.js +19 -0
  23. package/dist/lib/paths.js +7 -3
  24. package/dist/lib/plan-llm-openai.js +0 -63
  25. package/dist/lib/pr-create.js +66 -0
  26. package/dist/lib/resolve-task.js +34 -0
  27. package/dist/lib/task-add-llm.js +53 -233
  28. package/dist/lib/task-context.js +68 -0
  29. package/dist/lib/task-done-llm.js +155 -0
  30. package/dist/lib/task-pr-llm.js +50 -0
  31. package/dist/lib/task-push-pr.js +131 -0
  32. package/dist/lib/task-scaffold.js +39 -43
  33. package/dist/lib/task-start.js +100 -0
  34. package/dist/lib/task-summary.js +12 -239
  35. package/dist/lib/task.js +30 -24
  36. package/dist/types/config.js +0 -16
  37. package/package.json +14 -14
  38. package/templates/.cursor/rules/02-git-safety.mdc +12 -0
  39. package/templates/AGENTS.md +27 -87
  40. package/templates/clients/claude/CLAUDE.md +28 -0
  41. package/templates/clients/cursor/.cursor/rules/01-task-source-of-truth.mdc +12 -0
  42. package/templates/clients/cursor/.cursor/rules/02-git-safety.mdc +11 -0
  43. package/templates/clients/cursor/.cursor/rules/03-docs-on-done.mdc +13 -0
  44. package/templates/core/AGENTS.md +44 -0
  45. package/templates/core/docs/logs/README.md +7 -0
  46. package/templates/core/docs/project/03-architecture.md +15 -0
  47. package/templates/core/docs/project/05-current-state.md +15 -0
  48. package/templates/core/docs/project/06-decisions.md +9 -0
  49. package/templates/core/docs/tasks/TASK-000-template.md +37 -0
  50. package/templates/skills-shared/implement-task/SKILL.md +22 -0
  51. package/templates/skills-shared/plan-task/SKILL.md +19 -0
  52. package/dist/agent/loader.js +0 -71
  53. package/dist/agent/prompt.js +0 -66
  54. package/dist/commands/agent-list.js +0 -32
  55. package/dist/commands/agent-prompt.js +0 -59
  56. package/dist/commands/agent-show.js +0 -26
  57. package/dist/commands/done.js +0 -160
  58. package/dist/commands/github-init.js +0 -554
  59. package/dist/commands/github-status.js +0 -164
  60. package/dist/commands/next.js +0 -283
  61. package/dist/commands/notion-init.js +0 -764
  62. package/dist/commands/notion-sync.js +0 -405
  63. package/dist/commands/notion-test.js +0 -595
  64. package/dist/commands/plan.js +0 -146
  65. package/dist/commands/rollback.js +0 -126
  66. package/dist/commands/start.js +0 -129
  67. package/dist/commands/task-check.js +0 -155
  68. package/dist/commands/task-generate.js +0 -206
  69. package/dist/commands/task-pull.js +0 -277
  70. package/dist/commands/task-rollback.js +0 -174
  71. package/dist/commands/task-start.js +0 -102
  72. package/dist/commands/task-status.js +0 -122
  73. package/dist/lib/brief.js +0 -356
  74. package/dist/lib/cursor-task-prompt.js +0 -60
  75. package/dist/lib/done-follow-up.js +0 -308
  76. package/dist/lib/github-cli.js +0 -247
  77. package/dist/lib/guide-state.js +0 -69
  78. package/dist/lib/mvp-artifacts.js +0 -204
  79. package/dist/lib/mvp-constants.js +0 -15
  80. package/dist/lib/mvp-diff-summary.js +0 -43
  81. package/dist/lib/mvp-done-summary.js +0 -335
  82. package/dist/lib/notion-client.js +0 -459
  83. package/dist/lib/notion-discovery.js +0 -671
  84. package/dist/lib/notion-env.js +0 -140
  85. package/dist/lib/notion-mappers.js +0 -148
  86. package/dist/lib/notion-schema.js +0 -272
  87. package/dist/lib/notion-sync.js +0 -337
  88. package/dist/lib/notion-target.js +0 -247
  89. package/dist/lib/package-json.js +0 -133
  90. package/dist/lib/plan-apply-planner.js +0 -131
  91. package/dist/lib/plan-codex-pkce.js +0 -234
  92. package/dist/lib/plan-llm-models.js +0 -237
  93. package/dist/lib/plan-llm-normalize.js +0 -146
  94. package/dist/lib/plan-llm-session.js +0 -682
  95. package/dist/lib/plan-post-apply-setup.js +0 -116
  96. package/dist/lib/project-docs.js +0 -95
  97. package/dist/lib/prompt-builder.js +0 -135
  98. package/dist/lib/resolve-command-task.js +0 -40
  99. package/dist/lib/task-add-build-prompt.js +0 -39
  100. package/dist/lib/task-add-cursor.js +0 -81
  101. package/dist/lib/task-generator.js +0 -183
  102. package/dist/lib/task-merge.js +0 -220
  103. package/dist/lib/task-prompt.js +0 -23
  104. package/dist/lib/task-pull.js +0 -354
  105. package/dist/lib/task-status-brief.js +0 -132
  106. package/dist/lib/workflow-guide.js +0 -485
  107. package/dist/status/collector.js +0 -103
  108. package/dist/status/format.js +0 -181
  109. package/dist/types/brief.js +0 -126
  110. package/templates/.cursor/rules/00-project-governance.mdc +0 -28
  111. package/templates/.cursor/rules/01-agent-orchestration.mdc +0 -48
  112. package/templates/.cursor/rules/02-task-workflow.mdc +0 -38
  113. package/templates/.cursor/rules/03-git-safety.mdc +0 -30
  114. package/templates/.cursor/rules/04-docs-update.mdc +0 -22
  115. package/templates/.vibeops/agents/architect.md +0 -47
  116. package/templates/.vibeops/agents/builder.md +0 -38
  117. package/templates/.vibeops/agents/docs.md +0 -54
  118. package/templates/.vibeops/agents/orchestrator.md +0 -40
  119. package/templates/.vibeops/agents/planner.md +0 -60
  120. package/templates/.vibeops/agents/recovery.md +0 -49
  121. package/templates/.vibeops/agents/reviewer.md +0 -47
  122. package/templates/.vibeops/agents/tester.md +0 -43
  123. package/templates/.vibeops/prompts/create-plan.md +0 -33
  124. package/templates/.vibeops/prompts/generate-tasks.md +0 -41
  125. package/templates/.vibeops/prompts/implement-task.md +0 -39
  126. package/templates/.vibeops/prompts/review-task.md +0 -34
  127. package/templates/.vibeops/prompts/rollback.md +0 -32
  128. package/templates/.vibeops/prompts/start-project.md +0 -39
  129. package/templates/.vibeops/workflows/notion-sync.md +0 -53
  130. package/templates/.vibeops/workflows/project-start.md +0 -73
  131. package/templates/.vibeops/workflows/rollback.md +0 -45
  132. package/templates/.vibeops/workflows/task-lifecycle.md +0 -71
  133. package/templates/docs/logs/README.md +0 -38
  134. package/templates/docs/project/00-overview.md +0 -27
  135. package/templates/docs/project/01-requirements.md +0 -30
  136. package/templates/docs/project/02-mvp-scope.md +0 -36
  137. package/templates/docs/project/03-architecture.md +0 -34
  138. package/templates/docs/project/04-tech-stack.md +0 -29
  139. package/templates/docs/project/05-current-state.md +0 -35
  140. package/templates/docs/project/06-decisions.md +0 -20
  141. package/templates/docs/project/07-backlog.md +0 -23
  142. package/templates/docs/project/08-env.md +0 -29
  143. package/templates/docs/project/09-deployment.md +0 -28
  144. package/templates/docs/tasks/TASK-000-template.md +0 -72
@@ -1,66 +0,0 @@
1
- import { relative } from "node:path";
2
- import { readText } from "../lib/filesystem.js";
3
- function relOrAbs(root, p) {
4
- const r = relative(root, p);
5
- return r === "" ? "." : r.startsWith("..") ? p : r;
6
- }
7
- function header(inputs) {
8
- const lines = [];
9
- lines.push(`# Cursor prompt — agent: ${inputs.agent.meta.name}`);
10
- lines.push("");
11
- if (inputs.config) {
12
- lines.push(`Project: \`${inputs.config.name}\``);
13
- lines.push(`VibeOps: \`${inputs.config.vibeopsVersion}\``);
14
- }
15
- else {
16
- lines.push("Project: (no .vibeops.json found — running outside a VibeOps project)");
17
- }
18
- if (inputs.task) {
19
- lines.push(`TASK: \`${inputs.task.meta.id}\``);
20
- lines.push(`TASK file: \`${relOrAbs(inputs.projectRoot, inputs.task.meta.filePath)}\``);
21
- }
22
- lines.push("");
23
- return lines.join("\n");
24
- }
25
- function agentSection(agent) {
26
- return `## Agent definition (${agent.meta.name})\n\n${agent.body.trim()}\n`;
27
- }
28
- function taskSection(task) {
29
- return `## TASK file content\n\n${task.body.trim()}\n`;
30
- }
31
- async function contextSection(paths, projectRoot) {
32
- if (paths.length === 0)
33
- return "";
34
- const parts = ["## Extra context\n"];
35
- for (const p of paths) {
36
- try {
37
- const text = await readText(p);
38
- parts.push(`### ${relOrAbs(projectRoot, p)}\n\n\`\`\`\n${text}\n\`\`\`\n`);
39
- }
40
- catch {
41
- parts.push(`### ${relOrAbs(projectRoot, p)}\n\n_(could not read file)_\n`);
42
- }
43
- }
44
- return parts.join("\n");
45
- }
46
- const FOOTER = `---
47
-
48
- Apply the **Role / Inputs / Output Format / Rules / Forbidden** sections of the agent definition above as-is.
49
- Your output must be a single markdown blob that pastes cleanly into the Cursor chat.
50
-
51
- When done, follow the "Completion report" format in \`AGENTS.md\`:
52
- TASK ID · summary · changed files · verification · doc updates (05-current-state / TASK / docs/logs).
53
- `;
54
- export async function buildPrompt(inputs) {
55
- const parts = [
56
- header(inputs),
57
- agentSection(inputs.agent),
58
- ];
59
- if (inputs.task)
60
- parts.push(taskSection(inputs.task));
61
- const extra = await contextSection(inputs.contextPaths ?? [], inputs.projectRoot);
62
- if (extra.length > 0)
63
- parts.push(extra);
64
- parts.push(FOOTER);
65
- return parts.join("\n");
66
- }
@@ -1,32 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { listAgents } from "../agent/loader.js";
3
- import { bold, dim, log } from "../lib/logger.js";
4
- import { projectPaths } from "../lib/paths.js";
5
- export async function agentListCommand(options = {}) {
6
- const cwd = resolve(options.cwd ?? process.cwd());
7
- const paths = projectPaths(cwd);
8
- const agents = await listAgents(paths.vibeopsAgents);
9
- if (options.json) {
10
- const payload = agents.map((a) => ({
11
- name: a.meta.name,
12
- role: a.meta.role,
13
- description: a.meta.description ?? null,
14
- filePath: a.meta.filePath,
15
- }));
16
- log.raw(`${JSON.stringify(payload, null, 2)}\n`);
17
- return;
18
- }
19
- if (agents.length === 0) {
20
- log.warn(`No agents found in ${paths.vibeopsAgents}`);
21
- log.info(dim("Run `vibeops init` first."));
22
- process.exitCode = 1;
23
- return;
24
- }
25
- log.info(bold("Agents"));
26
- const nameWidth = Math.max(...agents.map((a) => a.meta.name.length));
27
- for (const a of agents) {
28
- const padded = a.meta.name.padEnd(nameWidth);
29
- const summary = a.meta.description ?? a.meta.role;
30
- log.info(` ${padded} ${dim(summary)}`);
31
- }
32
- }
@@ -1,59 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { findAgent, listAgents } from "../agent/loader.js";
3
- import { buildPrompt } from "../agent/prompt.js";
4
- import { readConfig } from "../lib/config.js";
5
- import { readText } from "../lib/filesystem.js";
6
- import { log } from "../lib/logger.js";
7
- import { projectPaths } from "../lib/paths.js";
8
- import { readTaskFile, scanTasks } from "../lib/task.js";
9
- async function locateTaskFile(tasksDir, taskId) {
10
- const all = await scanTasks(tasksDir);
11
- const target = taskId.toUpperCase();
12
- for (const t of all) {
13
- if (t.id.toUpperCase() === target)
14
- return t.filePath;
15
- }
16
- return null;
17
- }
18
- export async function agentPromptCommand(name, taskId, options = {}) {
19
- const cwd = resolve(options.cwd ?? process.cwd());
20
- const paths = projectPaths(cwd);
21
- const agent = await findAgent(paths.vibeopsAgents, name);
22
- if (!agent) {
23
- const available = (await listAgents(paths.vibeopsAgents)).map((a) => a.meta.name);
24
- log.error(`Unknown agent: "${name}".`);
25
- if (available.length > 0) {
26
- log.info(`Available: ${available.join(", ")}`);
27
- }
28
- else {
29
- log.info(`No agents installed in ${paths.vibeopsAgents}. Run \`vibeops init\` first.`);
30
- }
31
- process.exitCode = 1;
32
- return;
33
- }
34
- const config = await readConfig(paths.root);
35
- let task;
36
- const looksLikeTaskId = /^TASK-\d+/i.test(taskId);
37
- if (looksLikeTaskId) {
38
- const filePath = await locateTaskFile(paths.docsTasks, taskId);
39
- if (!filePath) {
40
- log.error(`TASK not found: ${taskId} (looked in ${paths.docsTasks})`);
41
- process.exitCode = 1;
42
- return;
43
- }
44
- const meta = await readTaskFile(filePath);
45
- const body = await readText(filePath);
46
- task = { meta, body };
47
- }
48
- else if (taskId !== "(unspecified)" && taskId.length > 0) {
49
- log.warn(`"${taskId}" does not look like a TASK id (expected TASK-NNN). Continuing without TASK context.`);
50
- }
51
- const prompt = await buildPrompt({
52
- agent,
53
- config,
54
- task,
55
- projectRoot: paths.root,
56
- contextPaths: options.context ?? [],
57
- });
58
- log.raw(prompt.endsWith("\n") ? prompt : `${prompt}\n`);
59
- }
@@ -1,26 +0,0 @@
1
- import { resolve } from "node:path";
2
- import { findAgent, listAgents } from "../agent/loader.js";
3
- import { log } from "../lib/logger.js";
4
- import { projectPaths } from "../lib/paths.js";
5
- export async function agentShowCommand(name, options = {}) {
6
- const cwd = resolve(options.cwd ?? process.cwd());
7
- const paths = projectPaths(cwd);
8
- const agent = await findAgent(paths.vibeopsAgents, name);
9
- if (!agent) {
10
- const available = (await listAgents(paths.vibeopsAgents)).map((a) => a.meta.name);
11
- log.error(`Unknown agent: "${name}".`);
12
- if (available.length > 0) {
13
- log.info(`Available: ${available.join(", ")}`);
14
- }
15
- else {
16
- log.info(`No agents installed in ${paths.vibeopsAgents}. Run \`vibeops init\` first.`);
17
- }
18
- process.exitCode = 1;
19
- return;
20
- }
21
- if (options.raw) {
22
- log.raw(agent.raw.endsWith("\n") ? agent.raw : `${agent.raw}\n`);
23
- return;
24
- }
25
- log.raw(agent.body.endsWith("\n") ? agent.body : `${agent.body}\n`);
26
- }
@@ -1,160 +0,0 @@
1
- import { relative, resolve } from "node:path";
2
- import { askYesNo } from "../lib/inquirer-helpers.js";
3
- import { readText } from "../lib/filesystem.js";
4
- import { bold, dim, green, log, yellow } from "../lib/logger.js";
5
- import { writeDoneSummary } from "../lib/mvp-done-summary.js";
6
- import { mergeTaskBranch } from "../lib/task-merge.js";
7
- import { projectPaths } from "../lib/paths.js";
8
- import { commandTaskNotFoundMessage, resolveCommandTask, } from "../lib/resolve-command-task.js";
9
- import { hasNonEmptySection, parseTaskFilename, readGitContext, readTaskFile, updateInlineStatus, } from "../lib/task.js";
10
- import { runDoneFollowUp } from "../lib/done-follow-up.js";
11
- import { gitAddPaths, listWorkingTreeRelPaths, partitionPathsForAutoCommit, readGitInfo, runGit, } from "../lib/git.js";
12
- function relOrAbs(root, p) {
13
- const r = relative(root, p);
14
- return r === "" ? "." : r.startsWith("..") ? p : r;
15
- }
16
- function commitMessageFor(taskId, title) {
17
- const trimmed = (title || taskId).trim();
18
- const slug = trimmed.replace(/^TASK-(?:\d+|mvp)\s*[·:\-]\s*/i, "").trim() || trimmed;
19
- return `feat(${taskId.toLowerCase()}): ${slug}`;
20
- }
21
- async function tryCommitDirty(cwd, message, dryRun) {
22
- const git = await readGitInfo(cwd);
23
- if (!git.isRepo || git.dirty !== true)
24
- return false;
25
- const { committable, excluded } = partitionPathsForAutoCommit(await listWorkingTreeRelPaths(cwd), { unmerged: [] });
26
- if (committable.length === 0) {
27
- if (excluded.length > 0) {
28
- log.warn("Dirty tree is only node_modules/.next-style paths — add them to .gitignore; commit skipped.");
29
- }
30
- return false;
31
- }
32
- if (excluded.length > 0) {
33
- log.warn(`Skipping ${excluded.length} build/install path(s) from auto-commit (e.g. ${excluded[0]}).`);
34
- }
35
- if (dryRun) {
36
- log.info(dim(` would: git add (${committable.length} paths) && git commit -m "${message}"`));
37
- return true;
38
- }
39
- try {
40
- await gitAddPaths(cwd, committable);
41
- await runGit(cwd, ["commit", "-q", "-m", message]);
42
- log.ok(`Committed: ${message}`);
43
- return true;
44
- }
45
- catch (e) {
46
- const msg = e instanceof Error ? e.message : String(e);
47
- log.warn(`Commit skipped (${msg}).`);
48
- return false;
49
- }
50
- }
51
- /** Finalize TASK-mvp: auto-fill Result/Test Result, summary md, merge, Notion. */
52
- export async function doneCommand(taskRef, options = {}) {
53
- const cwd = resolve(options.cwd ?? process.cwd());
54
- const paths = projectPaths(cwd);
55
- const dryRun = options.dryRun === true;
56
- const interactive = !dryRun && process.stdin.isTTY === true;
57
- const resolved = await resolveCommandTask(paths, cwd, taskRef);
58
- if (resolved === null) {
59
- log.error(commandTaskNotFoundMessage(taskRef));
60
- process.exitCode = 1;
61
- return;
62
- }
63
- const { taskFile, source } = resolved;
64
- if (source === "backlog-active") {
65
- log.info(dim(`No TASK-mvp — using ${resolved.taskId}.`));
66
- }
67
- const meta = await readTaskFile(taskFile);
68
- log.info(bold(`vibeops done ${meta.id}`));
69
- log.info(` ${dim("file")} ${relOrAbs(cwd, taskFile)}`);
70
- log.blank();
71
- if (options.skipSummary !== true) {
72
- log.step(bold("Summary + TASK sections"));
73
- await writeDoneSummary({
74
- cwd,
75
- taskId: meta.id,
76
- taskTitle: meta.title,
77
- taskFile,
78
- dryRun,
79
- refreshTaskSections: options.refreshTaskSections === true,
80
- });
81
- log.blank();
82
- }
83
- const body = await readText(taskFile);
84
- const resultOk = hasNonEmptySection(body, "Result");
85
- const testResultOk = hasNonEmptySection(body, "Test Result");
86
- log.info(bold("Required sections"));
87
- let missing = 0;
88
- for (const [label, ok] of [
89
- ["Result", resultOk],
90
- ["Test Result", testResultOk],
91
- ]) {
92
- if (!ok)
93
- missing++;
94
- log.info(` ${ok ? green("✓") : yellow("·")} ${label}`);
95
- }
96
- log.blank();
97
- if (missing > 0) {
98
- log.error(`Could not auto-fill Result / Test Result. Connect Codex OAuth, Cursor Agent CLI, or OPENAI_API_KEY — or fill sections manually.`);
99
- process.exitCode = 1;
100
- return;
101
- }
102
- if (dryRun) {
103
- log.info(bold("dry-run — would:"));
104
- log.info(` · Status → Done`);
105
- log.info(` · commit if dirty, then merge (unless --no-merge)`);
106
- log.info(` · Notion sync (if enabled)`);
107
- await runDoneFollowUp({
108
- cwd,
109
- taskFile,
110
- taskTitle: meta.title,
111
- dryRun: true,
112
- noNotionSync: options.noNotionSync,
113
- interactive,
114
- });
115
- return;
116
- }
117
- await updateInlineStatus(taskFile, "done");
118
- log.ok(`Status → Done`);
119
- const parts = parseTaskFilename(taskFile);
120
- const commitMsg = commitMessageFor(parts.id, meta.title);
121
- await tryCommitDirty(cwd, commitMsg, false);
122
- const gitCtx = await readGitContext(taskFile);
123
- if (options.noMerge !== true && gitCtx !== null) {
124
- let doMerge = !interactive;
125
- if (interactive) {
126
- doMerge = await askYesNo({
127
- message: `Push, merge into ${gitCtx.baseBranch}, and delete ${gitCtx.taskBranch}?`,
128
- nonInteractive: false,
129
- defaultValue: true,
130
- });
131
- }
132
- if (doMerge) {
133
- const mergeResult = await mergeTaskBranch({
134
- cwd,
135
- taskId: meta.id,
136
- taskTitle: meta.title,
137
- gitCtx,
138
- mode: options.mergeViaPr === true ? "pr" : "direct",
139
- allowDirty: options.allowDirty,
140
- });
141
- if (!mergeResult.ok) {
142
- process.exitCode = 1;
143
- }
144
- }
145
- else {
146
- log.info(dim("Merge skipped — run `vibeops next` later."));
147
- }
148
- }
149
- else if (gitCtx === null) {
150
- log.info(dim("No Git Context — merge skipped. Run `vibeops start` before the next MVP."));
151
- }
152
- await runDoneFollowUp({
153
- cwd,
154
- taskFile,
155
- taskTitle: meta.title,
156
- dryRun: false,
157
- noNotionSync: options.noNotionSync,
158
- interactive,
159
- });
160
- }