@yemi33/minions 0.1.2217 → 0.1.2218

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/dashboard.js CHANGED
@@ -13033,6 +13033,36 @@ What would you like to discuss or change? When you're happy, say "approve" and I
13033
13033
  }
13034
13034
  }},
13035
13035
 
13036
+ { method: 'POST', path: '/api/pr-action/offer-create-pr', desc: 'Offer a "Create PR" follow-up chip after Command Center makes a LOCAL code edit itself in a configured project (P-cc-createpr). Validates the project has uncommitted working-tree changes (git status --porcelain in project.localPath) and returns a create-pr follow-up chip — same CC-mediated shape as the pr-action chips, so the existing dashboard chip renderer/click handler light up unchanged. Returns {ok, hasChanges, branch, changedFileCount, followups}; followups is [] when there is nothing to PR. READ-ONLY: never stages/commits/pushes — clicking the chip routes a fresh CC turn that does the commit/push/PR-create/link.', params: 'project (configured project name), branch (optional — defaults to the working-tree current branch), contextOnly (optional bool — link the new PR as context-only instead of auto-managed)', handler: async (req, res) => {
13037
+ const body = await readBody(req);
13038
+ try {
13039
+ reloadConfig();
13040
+ const projectName = typeof body?.project === 'string' ? body.project.trim() : '';
13041
+ if (!projectName) return jsonReply(res, 400, { error: 'project is required' }, req);
13042
+ const project = shared.getProjects(CONFIG).find(p => p && p.name === projectName);
13043
+ if (!project) return jsonReply(res, 404, { error: `unknown project: ${projectName}` }, req);
13044
+ if (!project.localPath) return jsonReply(res, 400, { error: `project ${projectName} has no localPath (no working tree to PR)` }, req);
13045
+ let porcelain = '';
13046
+ let currentBranch = '';
13047
+ try {
13048
+ porcelain = await shared.shellSafeGit(['-C', project.localPath, 'status', '--porcelain']);
13049
+ currentBranch = (await shared.shellSafeGit(['-C', project.localPath, 'rev-parse', '--abbrev-ref', 'HEAD'])).trim();
13050
+ } catch (e) {
13051
+ return jsonReply(res, 400, { error: `git status failed for ${projectName}: ${e.message}` }, req);
13052
+ }
13053
+ const changedFileCount = porcelain.split('\n').map(s => s.trim()).filter(Boolean).length;
13054
+ const hasChanges = changedFileCount > 0;
13055
+ const branch = (typeof body?.branch === 'string' && body.branch.trim()) || currentBranch || '';
13056
+ const followups = hasChanges
13057
+ ? prAction.buildCreatePrFollowups({ project: projectName, branch, contextOnly: !!body?.contextOnly })
13058
+ : [];
13059
+ recordCcTurnIfPresent(req, { kind: 'pr-action', id: '', title: `offer create-pr (${projectName})`, project: projectName, followups });
13060
+ return jsonReply(res, 200, { ok: true, hasChanges, branch, changedFileCount, followups }, req);
13061
+ } catch (e) {
13062
+ return jsonReply(res, e.statusCode || 400, { error: e.message }, req);
13063
+ }
13064
+ }},
13065
+
13036
13066
  { method: 'POST', path: '/api/pull-requests/observe', desc: 'Toggle canonical contextOnly flag on a tracked PR (public `observe` body param is preserved as the inverse for backward compat)', params: 'host (github|ado), slug, number, observe (boolean)', handler: async (req, res) => {
13037
13067
  const body = await readBody(req);
13038
13068
  reloadConfig();
@@ -128,6 +128,50 @@ function buildPrActionFollowups(record, opts = {}) {
128
128
  }));
129
129
  }
130
130
 
131
+ // ── "Create PR" follow-up (P-cc-createpr) ───────────────────────────────────
132
+ // Offered after Command Center makes a LOCAL code edit itself (not via a
133
+ // dispatched agent), so the user can open a PR for it with one click. Mirrors
134
+ // the PR_ACTION_FOLLOWUPS chip shape ({ kind, label, message }) so the existing
135
+ // dashboard renderer (_ccFollowupChips) + click handler (ccPrActionFollowup)
136
+ // light up unchanged. CC-mediated by the same deliberate design as the
137
+ // pr-action chips: clicking sends a fresh CC turn that commits/pushes/opens the
138
+ // PR and links it to the tracker — no new server-side git path, maximal reuse.
139
+ const CREATE_PR_FOLLOWUP = Object.freeze({ kind: 'create-pr', label: 'Create PR' });
140
+
141
+ /**
142
+ * Build the "Create PR" follow-up chip(s) for a working-tree change CC just
143
+ * made in `project`. Returns `[]` when no project is given (nothing to act on).
144
+ *
145
+ * `branch` — the working-tree branch to commit on; falls back to "a new
146
+ * well-named branch" wording when absent.
147
+ * `contextOnly` — when true, the chip links the new PR as context-only instead
148
+ * of auto-managed (the default is auto-managed / contextOnly:false).
149
+ *
150
+ * Each chip: `{ kind:'create-pr', label, project, branch, message }` where
151
+ * `message` is the Command Center turn the chip click should send.
152
+ */
153
+ function buildCreatePrFollowups({ project, branch, contextOnly = false } = {}) {
154
+ const proj = (project && String(project).trim()) || '';
155
+ if (!proj) return [];
156
+ const br = branch && String(branch).trim() ? String(branch).trim() : '';
157
+ const branchClause = br
158
+ ? `on the current branch ${br}`
159
+ : 'on a new well-named branch off the project main branch';
160
+ const linkBody = contextOnly
161
+ ? `{"url":"<new PR url>","project":"${proj}","contextOnly":true}`
162
+ : `{"url":"<new PR url>","project":"${proj}","contextOnly":false}`;
163
+ const trackNote = contextOnly
164
+ ? 'so it is tracked but not auto-reviewed'
165
+ : 'so the engine auto-manages it (review -> fix -> re-review -> auto-merge)';
166
+ const message =
167
+ `Create a PR from the local changes you just made in the ${proj} project. ` +
168
+ `Steps: (1) in that project's working tree, stage and commit the modified files ${branchClause} with a clear conventional-commit message; ` +
169
+ `(2) push the branch; (3) open a PR against the project's main branch using the right CLI for the repo host (gh for GitHub, az repos for ADO); ` +
170
+ `(4) link it to the tracker by calling POST /api/pull-requests/link with ${linkBody} ${trackNote}. ` +
171
+ `Then show me the PR URL.`;
172
+ return [{ kind: CREATE_PR_FOLLOWUP.kind, label: CREATE_PR_FOLLOWUP.label, project: proj, branch: br || null, message }];
173
+ }
174
+
131
175
  // Read-only system prompt for the projectless dispatch. Teaches the untrusted-
132
176
  // input contract and the injection-signalling marker. Kept inline (no playbook
133
177
  // render) because this path has no project/worktree context to inject.
@@ -538,6 +582,7 @@ module.exports = {
538
582
  createPrAction,
539
583
  buildPrActionPrompt,
540
584
  buildPrActionFollowups,
585
+ buildCreatePrFollowups,
541
586
  runPrAction,
542
587
  postPrActionComment,
543
588
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2217",
3
+ "version": "0.1.2218",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "minions": "bin/minions.js"
@@ -89,6 +89,15 @@ If you start a small task and discover it's actually Medium (3+ files, more tool
89
89
 
90
90
  When genuinely in doubt about the size, delegate — agents have isolated worktrees, full tool access, durable work-item tracking, and no turn limits.
91
91
 
92
+ ### After you make a local code edit yourself — offer to open a PR
93
+ When you edit files **yourself** in a configured project's working tree (the Step-3 "do it yourself" path — NOT a change a dispatched agent made in its own worktree), don't leave the diff sitting uncommitted. After you finish editing, call:
94
+ ```
95
+ curl -s -X POST http://localhost:{{dashboard_port}}/api/pr-action/offer-create-pr \
96
+ -H 'Content-Type: application/json' -H 'X-CC-Turn-Id: {{cc_turn_id}}' \
97
+ -d '{"project":"<project name>"}'
98
+ ```
99
+ This checks the project's working tree (`git status --porcelain`) and, when there are uncommitted changes, returns a **`[Create PR]`** follow-up chip to the user (same chip mechanism as the `pr-action` `[Comment]`/`[Fix once]`/`[Track for auto-fix]` chips). When the user clicks it, you'll receive a turn instructing you to commit → push → open the PR → link it to the tracker. Pass `"contextOnly":true` if the PR should be tracked-but-not-auto-reviewed; omit it to have the engine auto-manage the PR (review → fix → re-review → auto-merge). If `hasChanges` is `false`, there's nothing to PR — skip the offer. Don't commit/push on your own initiative; surface the chip and let the user decide.
100
+
92
101
  ## When to dispatch vs answer inline
93
102
 
94
103
  - **Action requests** (fix this, implement that, build X, run a build, investigate Y, review PR #N) → dispatch via `POST /api/work-items` (or one of the other state-changing endpoints below). Don't also try to do the work yourself in the chat unless it's truly Small per Step 1.