@benzotti/jedi 0.1.23 → 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.
@@ -96,6 +96,12 @@ jobs:
96
96
  grep -qxF "$pattern" .git/info/exclude 2>/dev/null || echo "$pattern" >> .git/info/exclude
97
97
  done
98
98
 
99
+ # Configure git for Jedi commits (used when implementing changes on PR branches)
100
+ - name: Configure git
101
+ run: |
102
+ git config user.name "jedi[bot]"
103
+ git config user.email "jedi[bot]@users.noreply.github.com"
104
+
99
105
  # Install Claude Code CLI (required by Jedi for AI invocations)
100
106
  - name: Install Claude Code
101
107
  run: bun install -g @anthropic-ai/claude-code
package/dist/index.js CHANGED
@@ -9343,11 +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
+
9352
+ ## Auto-Commit (CI Mode)
9353
+
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/)
9356
+ 2. Commit with a conventional commit message (e.g. "feat: implement X")
9357
+ 3. Push to the current branch with \`git push\`
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.
9360
+
9346
9361
  ## Iterative Refinement
9347
9362
 
9348
9363
  After completing any workflow, present a summary and ask for feedback.
9349
- When the user provides feedback, apply changes incrementally \u2014 do not restart from scratch.
9350
- When the user approves ("approved", "lgtm", "looks good"), finalise the work.
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.
9351
9367
 
9352
9368
  ## ClickUp Integration
9353
9369
 
@@ -11213,7 +11229,8 @@ function parseComment(comment, isFollowUp) {
11213
11229
  description: comment.trim(),
11214
11230
  clickUpUrl: null,
11215
11231
  fullFlow: false,
11216
- isFeedback: true
11232
+ isFeedback: true,
11233
+ isApproval: false
11217
11234
  };
11218
11235
  }
11219
11236
  return null;
@@ -11224,28 +11241,28 @@ function parseComment(comment, isFollowUp) {
11224
11241
  const description = body.replace(/(https?:\/\/[^\s]*clickup\.com\/t\/[a-z0-9]+)/i, "").replace(/\s+/g, " ").trim();
11225
11242
  const lower = body.toLowerCase();
11226
11243
  if (lower.startsWith("ping") || lower.startsWith("status")) {
11227
- return { command: "ping", description: "", clickUpUrl: null, fullFlow: false, isFeedback: false };
11244
+ return { command: "ping", description: "", clickUpUrl: null, fullFlow: false, isFeedback: false, isApproval: false };
11228
11245
  }
11229
11246
  if (lower.startsWith("plan ")) {
11230
- return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false };
11247
+ return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11231
11248
  }
11232
11249
  if (lower.startsWith("implement")) {
11233
- return { command: "implement", description, clickUpUrl, fullFlow: false, isFeedback: false };
11250
+ return { command: "implement", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11234
11251
  }
11235
11252
  if (lower.startsWith("quick ")) {
11236
- return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false };
11253
+ return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11237
11254
  }
11238
11255
  if (lower.startsWith("review")) {
11239
- return { command: "review", description, clickUpUrl, fullFlow: false, isFeedback: false };
11256
+ return { command: "review", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11240
11257
  }
11241
11258
  if (lower.startsWith("feedback")) {
11242
- return { command: "feedback", description, clickUpUrl, fullFlow: false, isFeedback: false };
11259
+ return { command: "feedback", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11243
11260
  }
11244
11261
  if (lower.startsWith("do ")) {
11245
11262
  if (clickUpUrl) {
11246
- return { command: "plan", description, clickUpUrl, fullFlow: true, isFeedback: false };
11263
+ return { command: "plan", description, clickUpUrl, fullFlow: true, isFeedback: false, isApproval: false };
11247
11264
  }
11248
- return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false };
11265
+ return { command: "quick", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11249
11266
  }
11250
11267
  if (/^(approved?|lgtm|looks?\s*good|ship\s*it)/i.test(lower)) {
11251
11268
  return {
@@ -11253,7 +11270,8 @@ function parseComment(comment, isFollowUp) {
11253
11270
  description: body,
11254
11271
  clickUpUrl: null,
11255
11272
  fullFlow: false,
11256
- isFeedback: true
11273
+ isFeedback: true,
11274
+ isApproval: true
11257
11275
  };
11258
11276
  }
11259
11277
  if (isFollowUp) {
@@ -11262,10 +11280,11 @@ function parseComment(comment, isFollowUp) {
11262
11280
  description: body,
11263
11281
  clickUpUrl: null,
11264
11282
  fullFlow: false,
11265
- isFeedback: true
11283
+ isFeedback: true,
11284
+ isApproval: false
11266
11285
  };
11267
11286
  }
11268
- return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false };
11287
+ return { command: "plan", description, clickUpUrl, fullFlow: false, isFeedback: false, isApproval: false };
11269
11288
  }
11270
11289
  var actionCommand = defineCommand({
11271
11290
  meta: {
@@ -11316,11 +11335,11 @@ var actionCommand = defineCommand({
11316
11335
  consola.error("Could not parse 'Hey Jedi' intent from comment");
11317
11336
  process.exit(1);
11318
11337
  }
11319
- 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)" : ""}`);
11320
11339
  if (repo && commentId) {
11321
11340
  await reactToComment(repo, commentId, "eyes").catch(() => {});
11322
11341
  }
11323
- const commandLabel = intent.isFeedback ? "feedback" : intent.command;
11342
+ const commandLabel = intent.isApproval ? "plan" : intent.isFeedback ? "feedback" : intent.command;
11324
11343
  let placeholderCommentId = null;
11325
11344
  if (repo && issueNumber) {
11326
11345
  const thinkingBody = `<h3>\uD83E\uDDE0 Jedi <sup>thinking</sup></h3>
@@ -11408,7 +11427,7 @@ _Working on it..._`;
11408
11427
  }
11409
11428
  const baseProtocol = resolve9(cwd, ".jdi/framework/components/meta/AgentBase.md");
11410
11429
  let prompt2;
11411
- if (intent.isFeedback) {
11430
+ if (intent.isFeedback && intent.isApproval) {
11412
11431
  prompt2 = [
11413
11432
  `Read ${baseProtocol} for the base agent protocol.`,
11414
11433
  ``,
@@ -11416,29 +11435,44 @@ _Working on it..._`;
11416
11435
  ``,
11417
11436
  conversationHistory,
11418
11437
  ``,
11419
- `## Current Feedback`,
11420
- `The user has provided feedback on previous Jedi work:`,
11421
- ``,
11438
+ `## Plan Approved`,
11422
11439
  `> ${intent.description}`,
11423
11440
  ``,
11424
- `## Instructions`,
11425
- `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`,
11444
+ ``,
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.`,
11454
+ ``,
11455
+ ...contextLines,
11426
11456
  ``,
11427
- `IMPORTANT: Always be conversational. If the user asks a question, ANSWER IT FIRST before taking any action.`,
11428
- `Explain your reasoning, then describe what you'll do (if anything), then do it.`,
11429
- `Never silently make changes without explaining why.`,
11457
+ conversationHistory,
11458
+ ``,
11459
+ `## Refinement Feedback`,
11460
+ `> ${intent.description}`,
11430
11461
  ``,
11431
- `- 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.`,
11432
- `- If the feedback is an **approval** ("approved", "lgtm", "looks good", "ship it"), finalise the current work \u2014 create commits and/or a PR as appropriate.`,
11433
- `- 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:`,
11434
- ` <details>`,
11435
- ` <summary>View full plan</summary>`,
11436
- ` `,
11437
- ` [full updated plan content here as markdown]`,
11438
- ` `,
11439
- ` </details>`,
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`,
11440
11466
  ``,
11441
- `Read state.yaml and any existing plan files to understand what was previously done. Apply changes incrementally \u2014 do not restart from scratch.`
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.`,
11470
+ ``,
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?"`
11442
11476
  ].join(`
11443
11477
  `);
11444
11478
  } else {
@@ -11522,7 +11556,15 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11522
11556
  historyBlock,
11523
11557
  `## Task`,
11524
11558
  `Execute the current implementation plan. Read state.yaml for the active plan path.`,
11525
- `Follow the implement-plan orchestration. Present a summary when complete and ask for feedback.`
11559
+ `Follow the implement-plan orchestration.`,
11560
+ ``,
11561
+ `## Auto-Commit`,
11562
+ `You are running inside a GitHub Action on a PR branch. After implementing all changes:`,
11563
+ `1. Stage all changed files with \`git add\` (only files you changed \u2014 NOT .jdi/ or .claude/)`,
11564
+ `2. Commit with a conventional commit message (e.g. "feat: implement X")`,
11565
+ `3. Push to the current branch with \`git push\``,
11566
+ `Do NOT ask the user \u2014 just commit and push. The user will review the PR diff directly.`,
11567
+ `Present a summary of what was implemented and committed.`
11526
11568
  ].join(`
11527
11569
  `);
11528
11570
  break;
@@ -11534,7 +11576,14 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11534
11576
  historyBlock,
11535
11577
  `## Task`,
11536
11578
  `Make this quick change: ${intent.description}`,
11537
- `Keep changes minimal and focused. Commit when done. Present what you changed.`
11579
+ `Keep changes minimal and focused.`,
11580
+ ``,
11581
+ `## Auto-Commit`,
11582
+ `You are running inside a GitHub Action on a PR branch. After making changes:`,
11583
+ `1. Stage all changed files with \`git add\` (only files you changed \u2014 NOT .jdi/ or .claude/)`,
11584
+ `2. Commit with a conventional commit message`,
11585
+ `3. Push to the current branch with \`git push\``,
11586
+ `Do NOT ask the user \u2014 just commit and push. Present what you changed.`
11538
11587
  ].join(`
11539
11588
  `);
11540
11589
  break;
@@ -11595,7 +11644,14 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11595
11644
  ``,
11596
11645
  `## Task`,
11597
11646
  `Execute the most recently created implementation plan in .jdi/plans/.`,
11598
- `Follow the implement-plan orchestration. Present a summary when complete.`
11647
+ `Follow the implement-plan orchestration.`,
11648
+ ``,
11649
+ `## Auto-Commit`,
11650
+ `You are running inside a GitHub Action on a PR branch. After implementing all changes:`,
11651
+ `1. Stage all changed files with \`git add\` (only files you changed \u2014 NOT .jdi/ or .claude/)`,
11652
+ `2. Commit with a conventional commit message (e.g. "feat: implement X")`,
11653
+ `3. Push to the current branch with \`git push\``,
11654
+ `Do NOT ask the user \u2014 just commit and push. Present a summary of what was implemented and committed.`
11599
11655
  ].join(`
11600
11656
  `);
11601
11657
  const implResult = await spawnClaude(implementPrompt, {
@@ -11623,7 +11679,7 @@ Use the ClickUp ticket above as the primary requirements source.` : ``,
11623
11679
  if (saved.codebaseIndexSaved)
11624
11680
  consola.info("Codebase index persisted to storage");
11625
11681
  if (repo && issueNumber) {
11626
- const actionLabel = intent.isFeedback ? "feedback" : intent.command;
11682
+ const actionLabel = intent.isApproval ? "implement" : intent.isFeedback ? "feedback" : intent.command;
11627
11683
  let commentBody;
11628
11684
  if (success && fullResponse) {
11629
11685
  commentBody = formatJediComment(actionLabel, fullResponse);
@@ -11712,7 +11768,7 @@ var setupActionCommand = defineCommand({
11712
11768
  // package.json
11713
11769
  var package_default = {
11714
11770
  name: "@benzotti/jedi",
11715
- version: "0.1.23",
11771
+ version: "0.1.25",
11716
11772
  description: "JDI - Context-efficient AI development framework for Claude Code",
11717
11773
  type: "module",
11718
11774
  bin: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@benzotti/jedi",
3
- "version": "0.1.23",
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
  }