@benzotti/jedi 0.1.24 → 0.1.25

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 (2) hide show
  1. package/dist/index.js +65 -39
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -9343,19 +9343,27 @@ Based on the user's request, follow the appropriate workflow:
9343
9343
  - **PR feedback** ("feedback"): Address review comments using \`.jdi/framework/agents/jdi-pr-feedback.md\`. Extract learnings from reviewer preferences.
9344
9344
  - **"do" + ClickUp URL**: Full flow \u2014 plan from ticket, then implement.
9345
9345
 
9346
+ ## Approval Gate
9347
+
9348
+ Planning and implementation are separate gates \u2014 NEVER auto-proceed to implementation after planning or plan refinement.
9349
+ When the user provides refinement feedback on a plan, ONLY update the plan files in \`.jdi/plans/\`. Do NOT implement code.
9350
+ Implementation only happens when the user explicitly approves ("approved", "lgtm", "looks good", "ship it") or explicitly requests implementation ("implement", "build", "execute").
9351
+
9346
9352
  ## Auto-Commit (CI Mode)
9347
9353
 
9348
- You are running inside a GitHub Action on a PR branch. After implementing or making changes:
9349
- 1. Stage all changed files with \`git add\` (only files you changed \u2014 NOT .jdi/ or .claude/)
9354
+ You are running inside a GitHub Action on a PR branch. After **implementing** changes (NOT after planning or plan refinement):
9355
+ 1. Stage all changed files with \`git add\` (only source files you changed \u2014 NOT .jdi/ or .claude/)
9350
9356
  2. Commit with a conventional commit message (e.g. "feat: implement X")
9351
9357
  3. Push to the current branch with \`git push\`
9352
9358
  Do NOT ask the user whether to commit \u2014 just do it. The user will review the PR diff directly.
9359
+ Plan files (\`.jdi/plans/\`) are cached separately and should NOT be committed.
9353
9360
 
9354
9361
  ## Iterative Refinement
9355
9362
 
9356
9363
  After completing any workflow, present a summary and ask for feedback.
9357
- When the user provides feedback, apply changes incrementally \u2014 do not restart from scratch.
9358
- When the user approves ("approved", "lgtm", "looks good"), finalise the work \u2014 commit and push all outstanding changes.
9364
+ - **Plan refinement feedback** (e.g. "add error handling", "change task 2", "use a different approach"): Update ONLY the plan files in \`.jdi/plans/\`. Present the updated plan. Ask "Any changes before implementation?" Do NOT implement code.
9365
+ - **Approval** ("approved", "lgtm", "looks good", "ship it"): Mark the plan as approved. Do NOT implement \u2014 wait for an explicit "implement" command.
9366
+ - **Questions** ("why did you...", "what about..."): Answer conversationally first, then take action if needed.
9359
9367
 
9360
9368
  ## ClickUp Integration
9361
9369
 
@@ -11221,7 +11229,8 @@ function parseComment(comment, isFollowUp) {
11221
11229
  description: comment.trim(),
11222
11230
  clickUpUrl: null,
11223
11231
  fullFlow: false,
11224
- isFeedback: true
11232
+ isFeedback: true,
11233
+ isApproval: false
11225
11234
  };
11226
11235
  }
11227
11236
  return null;
@@ -11232,28 +11241,28 @@ function parseComment(comment, isFollowUp) {
11232
11241
  const description = body.replace(/(https?:\/\/[^\s]*clickup\.com\/t\/[a-z0-9]+)/i, "").replace(/\s+/g, " ").trim();
11233
11242
  const lower = body.toLowerCase();
11234
11243
  if (lower.startsWith("ping") || lower.startsWith("status")) {
11235
- return { command: "ping", description: "", clickUpUrl: null, fullFlow: false, isFeedback: false };
11244
+ return { command: "ping", description: "", clickUpUrl: null, fullFlow: false, isFeedback: false, isApproval: false };
11236
11245
  }
11237
11246
  if (lower.startsWith("plan ")) {
11238
- return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false };
11247
+ return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11239
11248
  }
11240
11249
  if (lower.startsWith("implement")) {
11241
- return { command: "implement", description, clickUpUrl, fullFlow: false, isFeedback: false };
11250
+ return { command: "implement", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11242
11251
  }
11243
11252
  if (lower.startsWith("quick ")) {
11244
- return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false };
11253
+ return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11245
11254
  }
11246
11255
  if (lower.startsWith("review")) {
11247
- return { command: "review", description, clickUpUrl, fullFlow: false, isFeedback: false };
11256
+ return { command: "review", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11248
11257
  }
11249
11258
  if (lower.startsWith("feedback")) {
11250
- return { command: "feedback", description, clickUpUrl, fullFlow: false, isFeedback: false };
11259
+ return { command: "feedback", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11251
11260
  }
11252
11261
  if (lower.startsWith("do ")) {
11253
11262
  if (clickUpUrl) {
11254
- return { command: "plan", description, clickUpUrl, fullFlow: true, isFeedback: false };
11263
+ return { command: "plan", description, clickUpUrl, fullFlow: true, isFeedback: false, isApproval: false };
11255
11264
  }
11256
- return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false };
11265
+ return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11257
11266
  }
11258
11267
  if (/^(approved?|lgtm|looks?\s*good|ship\s*it)/i.test(lower)) {
11259
11268
  return {
@@ -11261,7 +11270,8 @@ function parseComment(comment, isFollowUp) {
11261
11270
  description: body,
11262
11271
  clickUpUrl: null,
11263
11272
  fullFlow: false,
11264
- isFeedback: true
11273
+ isFeedback: true,
11274
+ isApproval: true
11265
11275
  };
11266
11276
  }
11267
11277
  if (isFollowUp) {
@@ -11270,10 +11280,11 @@ function parseComment(comment, isFollowUp) {
11270
11280
  description: body,
11271
11281
  clickUpUrl: null,
11272
11282
  fullFlow: false,
11273
- isFeedback: true
11283
+ isFeedback: true,
11284
+ isApproval: false
11274
11285
  };
11275
11286
  }
11276
- return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false };
11287
+ return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11277
11288
  }
11278
11289
  var actionCommand = defineCommand({
11279
11290
  meta: {
@@ -11324,11 +11335,11 @@ var actionCommand = defineCommand({
11324
11335
  consola.error("Could not parse 'Hey Jedi' intent from comment");
11325
11336
  process.exit(1);
11326
11337
  }
11327
- consola.info(`Parsed intent: ${intent.isFeedback ? "feedback on previous" : intent.command}${intent.fullFlow ? " (full flow)" : ""}`);
11338
+ consola.info(`Parsed intent: ${intent.isApproval ? "approval (finalise plan)" : intent.isFeedback ? "refinement feedback" : intent.command}${intent.fullFlow ? " (full flow)" : ""}`);
11328
11339
  if (repo && commentId) {
11329
11340
  await reactToComment(repo, commentId, "eyes").catch(() => {});
11330
11341
  }
11331
- const commandLabel = intent.isFeedback ? "feedback" : intent.command;
11342
+ const commandLabel = intent.isApproval ? "plan" : intent.isFeedback ? "feedback" : intent.command;
11332
11343
  let placeholderCommentId = null;
11333
11344
  if (repo && issueNumber) {
11334
11345
  const thinkingBody = `<h3>\uD83E\uDDE0 Jedi <sup>thinking</sup></h3>
@@ -11416,7 +11427,7 @@ _Working on it..._`;
11416
11427
  }
11417
11428
  const baseProtocol = resolve9(cwd, ".jdi/framework/components/meta/AgentBase.md");
11418
11429
  let prompt2;
11419
- if (intent.isFeedback) {
11430
+ if (intent.isFeedback && intent.isApproval) {
11420
11431
  prompt2 = [
11421
11432
  `Read ${baseProtocol} for the base agent protocol.`,
11422
11433
  ``,
@@ -11424,29 +11435,44 @@ _Working on it..._`;
11424
11435
  ``,
11425
11436
  conversationHistory,
11426
11437
  ``,
11427
- `## Current Feedback`,
11428
- `The user has provided feedback on previous Jedi work:`,
11429
- ``,
11438
+ `## Plan Approved`,
11430
11439
  `> ${intent.description}`,
11431
11440
  ``,
11432
- `## Instructions`,
11433
- `Review the previous conversation above. The user is iterating on work Jedi already started.`,
11441
+ `The user has approved the plan. Finalise it:`,
11442
+ `1. Read \`.jdi/config/state.yaml\` and update \`review.status\` to "approved" and \`review.approved_at\` to now`,
11443
+ `2. Do NOT implement any code \u2014 approval and implementation are separate gates`,
11434
11444
  ``,
11435
- `IMPORTANT: Always be conversational. If the user asks a question, ANSWER IT FIRST before taking any action.`,
11436
- `Explain your reasoning, then describe what you'll do (if anything), then do it.`,
11437
- `Never silently make changes without explaining why.`,
11445
+ `Respond with a short confirmation that the plan is approved and ready, then ask:`,
11446
+ `"Say **implement** when you're ready to go."`
11447
+ ].join(`
11448
+ `);
11449
+ } else if (intent.isFeedback) {
11450
+ const agentSpec = resolve9(cwd, `.jdi/framework/agents/jdi-planner.md`);
11451
+ prompt2 = [
11452
+ `Read ${baseProtocol} for the base agent protocol.`,
11453
+ `You are jdi-planner. Read ${agentSpec} for your full specification.`,
11438
11454
  ``,
11439
- `- If the feedback is a **question** ("why did you...", "what about...", "can you explain..."), answer it conversationally first. If the answer implies a change is needed, explain that and then apply it.`,
11440
- `- If the feedback is an **approval** ("approved", "lgtm", "looks good", "ship it"), finalise the current work \u2014 commit all outstanding changes and push to the current branch. Do NOT ask \u2014 just do it.`,
11441
- `- If the feedback is a **refinement** ("change task 2", "use a different approach", "add error handling"), explain what you're changing and why, then apply the changes. Present an updated summary with the full updated plan in a collapsible block:`,
11442
- ` <details>`,
11443
- ` <summary>View full plan</summary>`,
11444
- ` `,
11445
- ` [full updated plan content here as markdown]`,
11446
- ` `,
11447
- ` </details>`,
11455
+ ...contextLines,
11456
+ ``,
11457
+ conversationHistory,
11458
+ ``,
11459
+ `## Refinement Feedback`,
11460
+ `> ${intent.description}`,
11461
+ ``,
11462
+ `## HARD CONSTRAINTS \u2014 PLAN REFINEMENT MODE`,
11463
+ `- ONLY modify files under \`.jdi/plans/\` and \`.jdi/config/\` \u2014 NEVER create, edit, or delete source code files`,
11464
+ `- NEVER run \`git commit\`, \`git push\`, or any git write operations`,
11465
+ `- Planning and implementation are SEPARATE gates \u2014 user must explicitly approve before implementation`,
11466
+ ``,
11467
+ `## Instructions`,
11468
+ `Read state.yaml and existing plan files. Apply feedback incrementally \u2014 do not restart from scratch.`,
11469
+ `If the feedback is a question, answer it conversationally. If it implies a plan change, update the plan.`,
11448
11470
  ``,
11449
- `Read state.yaml and any existing plan files to understand what was previously done. Apply changes incrementally \u2014 do not restart from scratch.`
11471
+ `## Response Format (MANDATORY)`,
11472
+ `1-2 sentence summary of what changed. Then the full updated plan in a collapsible block:`,
11473
+ `\`<details><summary>View full plan</summary> ... </details>\``,
11474
+ `Use the same plan structure as the initial plan (tasks table, per-task details, verification).`,
11475
+ `End with: "Any changes before implementation?"`
11450
11476
  ].join(`
11451
11477
  `);
11452
11478
  } else {
@@ -11653,7 +11679,7 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11653
11679
  if (saved.codebaseIndexSaved)
11654
11680
  consola.info("Codebase index persisted to storage");
11655
11681
  if (repo && issueNumber) {
11656
- const actionLabel = intent.isFeedback ? "feedback" : intent.command;
11682
+ const actionLabel = intent.isApproval ? "implement" : intent.isFeedback ? "feedback" : intent.command;
11657
11683
  let commentBody;
11658
11684
  if (success && fullResponse) {
11659
11685
  commentBody = formatJediComment(actionLabel, fullResponse);
@@ -11742,7 +11768,7 @@ var setupActionCommand = defineCommand({
11742
11768
  // package.json
11743
11769
  var package_default = {
11744
11770
  name: "@benzotti/jedi",
11745
- version: "0.1.24",
11771
+ version: "0.1.25",
11746
11772
  description: "JDI - Context-efficient AI development framework for Claude Code",
11747
11773
  type: "module",
11748
11774
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benzotti/jedi",
3
- "version": "0.1.24",
3
+ "version": "0.1.25",
4
4
  "description": "JDI - Context-efficient AI development framework for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,7 +33,7 @@
33
33
  "type": "git",
34
34
  "url": "https://github.com/zottiben/jedi.git"
35
35
  },
36
- "license": "MIT",
36
+ "license": "MIT",
37
37
  "engines": {
38
38
  "node": ">=18"
39
39
  }