@konductro/claude-plugin 2.0.0 → 2.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.
package/README.md CHANGED
@@ -35,6 +35,7 @@ Skills are guided, multi-step workflows invoked with a slash command:
35
35
  | `/find-prototype` | Find and download the approved UX prototype for the current project |
36
36
  | `/profile-repository` | Scan the current repo and submit its profile to Konductro |
37
37
  | `/start-ticket` | Pick up an assigned ticket — creates branch, pushes ticket spec, sets status |
38
+ | `/bug-enrich` | Enrich a bug ticket with technical analysis — explores codebase and submits structured context |
38
39
 
39
40
  ## Tools
40
41
 
@@ -82,6 +83,8 @@ Tools are called automatically by Claude based on natural language. You don't in
82
83
  | Tool | What it does |
83
84
  |---|---|
84
85
  | `profile_repository` | Submit a repository profile (tech stack, APIs, dependencies) |
86
+ | `get_bug_for_enrichment` | Load a bug ticket and project context for enrichment |
87
+ | `submit_bug_enrichment` | Submit structured technical enrichment for a bug ticket |
85
88
 
86
89
  ### Examples
87
90
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konductro/claude-plugin",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "Claude Code plugin for the Konductro platform — technical analysis and delivery tasks",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -297,7 +297,7 @@ server.tool(
297
297
  title: z.string().describe('Task title'),
298
298
  description: z.string().describe('Technical description of the task'),
299
299
  repositoryId: z.string().describe('Repository ID from the context'),
300
- type: z.enum(['ui_component', 'api_java', 'api_node', 'android', 'ios', 'infra']).default('api_node').describe('Task type'),
300
+ type: z.string().trim().max(24).optional().describe('Short free-text tech tag derived from the repo stack (e.g. C#, PHP, Node, Java, UI, Infra); one token, max 24 chars, no fixed list'),
301
301
  acceptanceCriteria: z.array(z.string()).default([]).describe('Technical acceptance criteria'),
302
302
  architecturalNotes: z.array(z.string()).default([]).describe('Implementation notes for the agent'),
303
303
  componentPath: z.string().optional().nullable().describe('Primary file/directory path for this task'),
@@ -882,6 +882,87 @@ server.tool(
882
882
  }
883
883
  );
884
884
 
885
+ // Tool: Get bug context for enrichment
886
+ server.tool(
887
+ 'get_bug_for_enrichment',
888
+ 'Load a bug ticket and its project context for enrichment. Returns the bug description, acceptance criteria, project name, and existing notes.',
889
+ {
890
+ ticketId: z.string().describe('The ticket ID or key (e.g. KON-42) of the bug to enrich'),
891
+ },
892
+ async ({ ticketId }) => {
893
+ try {
894
+ const ctx = await konductroFetch(`/api/cli/bugs/${encodeURIComponent(ticketId)}/context`);
895
+
896
+ let text = `## Bug Context\n\n`;
897
+ text += `**Ticket:** ${ctx.key} — ${ctx.title}\n`;
898
+ text += `**Project:** ${ctx.projectName ?? 'Unknown'}\n`;
899
+ text += `**Phase:** ${ctx.phaseName ?? 'Unknown'}\n`;
900
+ if (ctx.componentPath) text += `**Component:** ${ctx.componentPath}\n`;
901
+ if (ctx.repository) text += `**Repository:** ${ctx.repository.name} (${ctx.repository.repoType}) — ${ctx.repository.repoUrl}\n`;
902
+ text += `\n`;
903
+
904
+ text += `### Description\n\n${ctx.description}\n\n`;
905
+
906
+ if (ctx.acceptanceCriteria?.length > 0) {
907
+ text += `### Acceptance Criteria\n\n`;
908
+ ctx.acceptanceCriteria.forEach((ac, i) => { text += `${i + 1}. ${ac}\n`; });
909
+ text += `\n`;
910
+ }
911
+
912
+ if (ctx.architecturalNotes?.length > 0) {
913
+ text += `### Existing Notes\n\n`;
914
+ ctx.architecturalNotes.forEach(n => { text += `- ${n}\n`; });
915
+ text += `\n`;
916
+ }
917
+
918
+ return { content: [{ type: 'text', text }] };
919
+ } catch (err) {
920
+ const msg = err.message?.includes('BUG_NOT_FOUND') || err.message?.includes('404')
921
+ ? `Ticket ${ticketId} not found or is not a bug.`
922
+ : `Failed to load bug context: ${err.message}`;
923
+ return { content: [{ type: 'text', text: msg }], isError: true };
924
+ }
925
+ }
926
+ );
927
+
928
+ // Tool: Submit bug enrichment
929
+ server.tool(
930
+ 'submit_bug_enrichment',
931
+ 'Submit structured technical enrichment for a bug ticket. At least one field must be provided. The enrichment is append-only — the original description is never modified.',
932
+ {
933
+ ticketId: z.string().describe('The ticket ID or key (e.g. KON-42) of the bug to enrich'),
934
+ suspectedRootCause: z.string().optional().describe('Your assessment of why the bug occurs'),
935
+ affectedComponents: z.array(z.string()).optional().describe('File paths or module names involved'),
936
+ stackTraceHints: z.array(z.string()).optional().describe('Relevant error origins, log lines, or exception paths'),
937
+ investigationSteps: z.array(z.string()).optional().describe('What you checked and what you found'),
938
+ verifyFixCriteria: z.array(z.string()).optional().describe('Conditions that confirm the bug is fixed (appended to acceptance criteria)'),
939
+ },
940
+ async ({ ticketId, suspectedRootCause, affectedComponents, stackTraceHints, investigationSteps, verifyFixCriteria }) => {
941
+ if (!suspectedRootCause && !affectedComponents?.length && !stackTraceHints?.length && !investigationSteps?.length && !verifyFixCriteria?.length) {
942
+ return { content: [{ type: 'text', text: 'At least one enrichment field must be provided.' }], isError: true };
943
+ }
944
+
945
+ try {
946
+ const result = await konductroFetch(`/api/cli/bugs/${encodeURIComponent(ticketId)}/enrich`, {
947
+ method: 'POST',
948
+ body: JSON.stringify({ suspectedRootCause, affectedComponents, stackTraceHints, investigationSteps, verifyFixCriteria }),
949
+ });
950
+
951
+ const applied = result.fieldsApplied?.length > 0
952
+ ? `Enrichment applied: ${result.fieldsApplied.join(', ')}`
953
+ : 'No new enrichment applied (fields may already exist on the ticket).';
954
+ return { content: [{ type: 'text', text: applied }] };
955
+ } catch (err) {
956
+ const msg = err.message?.includes('BUG_NOT_FOUND') || err.message?.includes('404')
957
+ ? `Ticket ${ticketId} not found or is not a bug.`
958
+ : err.message?.includes('INVALID_ENRICHMENT')
959
+ ? 'At least one enrichment field must be provided.'
960
+ : `Failed to submit enrichment: ${err.message}`;
961
+ return { content: [{ type: 'text', text: msg }], isError: true };
962
+ }
963
+ }
964
+ );
965
+
885
966
  // Start the server
886
967
  async function main() {
887
968
  const transport = new StdioServerTransport();
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: bug-enrich
3
+ description: Enrich an existing bug ticket with technical analysis. Use when assigned to triage a bug — fetches the ticket, explores the codebase locally, and submits structured technical context back to Konductro.
4
+ allowed-tools: Read, Grep, Glob, Bash, mcp__konductro__get_bug_for_enrichment, mcp__konductro__submit_bug_enrichment
5
+ ---
6
+
7
+ # Konductro Bug Enrichment
8
+
9
+ You are enriching an existing bug ticket with technical context for the Konductro delivery platform. Your role is to add structured technical detail — never to rewrite or modify the user's original bug description.
10
+
11
+ ## Critical Constraint
12
+
13
+ **DO NOT modify the original `description` of the ticket.** The enrichment is append-only. Your job is to add technical context (root cause, affected components, investigation steps) — the user's original report is preserved byte-for-byte by the server.
14
+
15
+ ## Workflow
16
+
17
+ ### Step 1: Accept Ticket ID
18
+
19
+ The user provides a ticket ID (e.g. `KON-42` or a UUID) as a positional argument from `/bug-enrich <ticket-id>`.
20
+
21
+ ### Step 2: Load Bug Context
22
+
23
+ Call `get_bug_for_enrichment` with the ticket ID. This returns:
24
+ - The bug title, description, and existing acceptance criteria
25
+ - Project and phase context
26
+ - Any existing architectural notes or component path
27
+
28
+ Review the bug report and share a summary with the user. Confirm you understand the issue.
29
+
30
+ ### Step 3: Explore the Codebase
31
+
32
+ The user has the target repository cloned locally. Use Glob, Grep, and Read to investigate:
33
+
34
+ - **Affected code paths** — trace the flow described in the bug report
35
+ - **Potential root cause** — look for the code that could produce the described behaviour
36
+ - **Related components** — what files/modules are involved
37
+ - **Stack trace clues** — if error messages are mentioned, find where they originate
38
+ - **Fix verification** — what would need to be true for the bug to be resolved
39
+
40
+ Focus your exploration on what's relevant to the bug. Don't scan the entire codebase.
41
+
42
+ ### Step 4: Plan the Enrichment
43
+
44
+ Based on your investigation, prepare structured enrichment fields:
45
+
46
+ - **suspectedRootCause** — your best assessment of why the bug occurs (reference specific code)
47
+ - **affectedComponents** — file paths or module names involved
48
+ - **stackTraceHints** — relevant error origins, log lines, or exception paths
49
+ - **investigationSteps** — what you checked and what you found
50
+ - **verifyFixCriteria** — specific conditions that confirm the bug is fixed (these get appended to acceptance criteria)
51
+
52
+ Present your findings to the user before submitting.
53
+
54
+ ### Step 5: Submit Enrichment
55
+
56
+ After the user approves, call `submit_bug_enrichment` with the ticket ID and your structured findings. The server applies them using append-only rules:
57
+ - `architecturalNotes` receives prefixed entries
58
+ - `componentPath` is set only if currently empty
59
+ - `acceptanceCriteria` receives verify-fix criteria (de-duplicated)
60
+
61
+ Report success and summarise what was applied.
62
+
63
+ ## Important Rules
64
+
65
+ - Always load the bug context first — don't assume or hallucinate ticket contents
66
+ - Explore the ACTUAL local codebase — don't invent file paths or code snippets
67
+ - Reference specific files, line numbers, and function names in your findings
68
+ - Present findings for user review before submitting
69
+ - Never modify the original description — enrichment is additive only
70
+ - If you can't find relevant code, say so honestly rather than guessing
@@ -45,7 +45,7 @@ Based on the story requirements and your codebase understanding, plan the tasks.
45
45
  - **Execution order** — what needs to be built first (e.g., schema before API before UI)
46
46
  - **Task boundaries** — each task should be a single PR, touching one concern
47
47
  - **Repository assignment** — which repo does each task belong to
48
- - **Task type** — `api_node`, `api_java`, `ui_component`, `android`, `ios`, `infra`
48
+ - **Task type** — a short free-text tech tag derived from the target repo's stack (e.g. `C#`, `PHP`, `Node`, `Java`, `Angular`, `UI`, `Infra`). One canonical token, max 24 chars — there is no fixed list; match the repo's actual language/domain.
49
49
  - **Dependencies between tasks** — task 2 may depend on task 1's API
50
50
 
51
51
  Present your proposed decomposition to the user before submitting.
@@ -57,7 +57,7 @@ For each task, produce the full developer brief — this is the complete impleme
57
57
  1. **title** — short, action-oriented (e.g., "Add sprint.projectId column and migration")
58
58
  2. **description** — technical description of what to build and how, referencing specific files, patterns, and APIs
59
59
  3. **repositoryId** — from the context (the repo this task targets)
60
- 4. **type** — `api_node`, `api_java`, `ui_component`, `android`, `ios`, `infra`
60
+ 4. **type** — short free-text tech tag from the repo's stack (e.g. `C#`, `PHP`, `Node`, `Java`, `Angular`, `UI`, `Infra`); one canonical token, max 24 chars, no fixed list
61
61
  5. **acceptanceCriteria** — specific, testable criteria for this task
62
62
  6. **architecturalNotes** — implementation hints, patterns to follow, gotchas
63
63
  7. **componentPath** — primary file or directory being changed