@rayburst/cc 3.1.6 → 3.1.8

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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Always-on product context for Claude Code — features, acceptance criteria, and board cards injected automatically.",
9
- "version": "3.1.6"
9
+ "version": "3.1.8"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "rayburst",
14
14
  "source": "./",
15
15
  "description": "Always-on product context for Claude Code. Automatically injects your Rayburst Product Requirement Registry (features, Gherkin acceptance criteria, board cards) into every coding session.",
16
- "version": "3.1.6",
16
+ "version": "3.1.8",
17
17
  "author": {
18
18
  "name": "Rayburst"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rayburst",
3
- "version": "3.1.6",
3
+ "version": "3.1.8",
4
4
  "description": "Always-on product context for Claude Code. Automatically injects feature atlas and acceptance criteria into every coding session — no slash commands needed.",
5
5
  "author": {
6
6
  "name": "Rayburst",
@@ -46,14 +46,13 @@ if (toolName !== "Write" && toolName !== "Edit") {
46
46
  process.exit(0);
47
47
  }
48
48
  var activeFeature = readCache("active-feature");
49
- if (!activeFeature) {
50
- process.exit(0);
51
- }
52
49
  var filePath = toolInput?.file_path || toolInput?.path || "unknown";
53
50
  function escapeXml(str) {
54
51
  return (str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
55
52
  }
56
- var contextBlock = `<rayburst_post_implementation_reminder>
53
+ var contextBlock;
54
+ if (activeFeature) {
55
+ contextBlock = `<rayburst_post_implementation_reminder>
57
56
  <action_required>You just modified ${escapeXml(filePath)}. Before continuing to the next task or responding to the user, you MUST update the Rayburst feature atlas NOW:
58
57
  1. Call rb_add_criterion for any new behaviors introduced
59
58
  2. Call rb_update_criterion to mark criteria as passing/failing
@@ -61,6 +60,16 @@ var contextBlock = `<rayburst_post_implementation_reminder>
61
60
  Do NOT proceed without completing this step. This is a mandatory workflow requirement.</action_required>
62
61
  <active_feature>${escapeXml(activeFeature.title)} (${activeFeature.id})</active_feature>
63
62
  </rayburst_post_implementation_reminder>`;
63
+ } else {
64
+ contextBlock = `<rayburst_post_implementation_reminder>
65
+ <action_required>You just modified ${escapeXml(filePath)} but NO active feature was matched for this task. This likely means you skipped the mandatory feature lookup step. You MUST now:
66
+ 1. Call rb_list_features with a search term related to the area you just changed
67
+ 2. Call rb_get_feature on the best match to load its criteria
68
+ 3. Call rb_add_criterion or rb_update_criterion to reflect what you built
69
+ 4. Call rb_update_feature if the feature description needs updating
70
+ ALL changes \u2014 including visual, layout, and icon changes \u2014 require feature atlas updates. Do NOT skip this.</action_required>
71
+ </rayburst_post_implementation_reminder>`;
72
+ }
64
73
  console.log(
65
74
  JSON.stringify({
66
75
  hookSpecificOutput: {
@@ -24,12 +24,12 @@ function readCache(type) {
24
24
  }
25
25
 
26
26
  // src/hooks/product-context-block.ts
27
- function buildCodingReminderBlock(activeFeature2, filePath2, relatedFeatures2) {
27
+ function buildCodingReminderBlock(activeFeature2, filePath2, relatedFeatures) {
28
28
  if (!activeFeature2) return "";
29
29
  const criteria = (activeFeature2.criteria || []).map((c) => ` - [ ] ${escapeXml(c.title || c.description || "")}`).join("\n");
30
30
  let relatedNote = "";
31
- if (relatedFeatures2 && relatedFeatures2.length > 0) {
32
- const names = relatedFeatures2.map((f) => `"${escapeXml(f.title)}"`).join(", ");
31
+ if (relatedFeatures && relatedFeatures.length > 0) {
32
+ const names = relatedFeatures.map((f) => `"${escapeXml(f.title)}"`).join(", ");
33
33
  relatedNote = `
34
34
  <related_features>This file may also relate to: ${names}. Check that your changes don't break their criteria.</related_features>`;
35
35
  }
@@ -42,6 +42,16 @@ ${criteria}
42
42
  <post_implementation_required>Before submitting your response, you MUST update the Rayburst feature atlas: add/update criteria for any new behaviors via rb_add_criterion, update the feature description if it changed via rb_update_feature. You will be reminded again after writing. Do NOT skip this step.</post_implementation_required>
43
43
  </rayburst_coding_reminder>`;
44
44
  }
45
+ function buildNoFeatureWarningBlock(filePath2) {
46
+ return `<rayburst_no_feature_warning>
47
+ <warning>You are about to modify ${escapeXml(filePath2 || "a file")} but NO feature from the Rayburst atlas was matched to your current task. This means you skipped the mandatory feature lookup step.</warning>
48
+ <required_action>BEFORE writing this code, you MUST:
49
+ 1. Call rb_list_features with a search term related to the area you are changing
50
+ 2. Call rb_get_feature on the best match to load its acceptance criteria
51
+ 3. Work against those criteria
52
+ ALL changes \u2014 including visual, layout, icon, and styling changes \u2014 require a feature lookup. There are no exceptions.</required_action>
53
+ </rayburst_no_feature_warning>`;
54
+ }
45
55
  function escapeXml(str) {
46
56
  return (str || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
47
57
  }
@@ -69,29 +79,31 @@ if (toolName !== "Write" && toolName !== "Edit") {
69
79
  process.exit(0);
70
80
  }
71
81
  var activeFeature = readCache("active-feature");
72
- if (!activeFeature) {
73
- process.exit(0);
74
- }
75
82
  var filePath = toolInput?.file_path || toolInput?.path || "";
76
- var featureList = readCache("features") || [];
77
- var relatedFeatures = [];
78
- if (filePath) {
79
- const fileBasename = filePath.split("/").pop() || "";
80
- const fileDir = filePath.split("/").slice(-2, -1)[0] || "";
81
- for (const f of featureList) {
82
- if (f.id === activeFeature.id) continue;
83
- const desc = (f.description || "").toLowerCase();
84
- const title = (f.title || "").toLowerCase();
85
- if (desc.includes(fileBasename.toLowerCase()) || desc.includes(fileDir.toLowerCase()) || title.includes(fileBasename.toLowerCase().replace(/\.\w+$/, ""))) {
86
- relatedFeatures.push(f);
83
+ var contextBlock;
84
+ if (activeFeature) {
85
+ const featureList = readCache("features") || [];
86
+ const relatedFeatures = [];
87
+ if (filePath) {
88
+ const fileBasename = filePath.split("/").pop() || "";
89
+ const fileDir = filePath.split("/").slice(-2, -1)[0] || "";
90
+ for (const f of featureList) {
91
+ if (f.id === activeFeature.id) continue;
92
+ const desc = (f.description || "").toLowerCase();
93
+ const title = (f.title || "").toLowerCase();
94
+ if (desc.includes(fileBasename.toLowerCase()) || desc.includes(fileDir.toLowerCase()) || title.includes(fileBasename.toLowerCase().replace(/\.\w+$/, ""))) {
95
+ relatedFeatures.push(f);
96
+ }
87
97
  }
88
98
  }
99
+ contextBlock = buildCodingReminderBlock(
100
+ activeFeature,
101
+ filePath,
102
+ relatedFeatures.slice(0, 3)
103
+ );
104
+ } else {
105
+ contextBlock = buildNoFeatureWarningBlock(filePath);
89
106
  }
90
- var contextBlock = buildCodingReminderBlock(
91
- activeFeature,
92
- filePath,
93
- relatedFeatures.slice(0, 3)
94
- );
95
107
  if (contextBlock) {
96
108
  console.log(
97
109
  JSON.stringify({
@@ -153,11 +153,10 @@ function buildProductContextBlock(features, cards) {
153
153
  return `<rayburst_product_context>
154
154
  <rules>
155
155
  <rule>You have access to a Rayburst feature atlas \u2014 a knowledge graph of product features with Gherkin acceptance criteria. Use it to understand what you're building.</rule>
156
- <rule>Before implementing any task, check if a matching feature exists in the atlas below. If found, read its criteria with rb_get_feature and work against them.</rule>
156
+ <rule>MANDATORY PRE-IMPLEMENTATION STEP: Before writing ANY code \u2014 regardless of task size, type, or complexity (including visual changes, icon swaps, layout tweaks, styling, refactoring) \u2014 you MUST: (1) call rb_list_features to search for a matching feature, (2) call rb_get_feature to load its criteria, (3) work against those criteria. There are NO exceptions. If no feature exists, create one with rb_create_feature before proceeding.</rule>
157
157
  <rule>If your changes may affect behaviors described in OTHER features' criteria, flag this to the user before proceeding.</rule>
158
158
  <rule>NEVER create, update, or delete features or criteria in the atlas without explicitly asking the user for confirmation first. Show them what you want to change and wait for approval.</rule>
159
- <rule>When implementation is complete, summarize which acceptance criteria were addressed and which remain pending.</rule>
160
- <rule>MANDATORY: After every implementation \u2014 in the same response as the code changes \u2014 you MUST update Rayburst without being asked: (1) update affected feature descriptions if behavior changed via rb_update_feature, (2) add new acceptance criteria for every new behavior introduced via rb_add_criterion, (3) update criterion status where applicable via rb_update_criterion. Do NOT wait for the user to ask. Skipping this step is a workflow violation.</rule>
159
+ <rule>MANDATORY POST-IMPLEMENTATION STEP: After every implementation \u2014 in the same response as the code changes \u2014 you MUST update Rayburst without being asked: (1) update affected feature descriptions if behavior changed via rb_update_feature, (2) add new acceptance criteria for every new behavior introduced via rb_add_criterion, (3) update criterion status where applicable via rb_update_criterion. Do NOT wait for the user to ask. A post-write hook will verify compliance.</rule>
161
160
  <rule>Use mcp__plugin_rayburst_rayburst__rb_* MCP tools to interact with the atlas. Use rb_get_feature to load full criteria for a specific feature.</rule>
162
161
  </rules>
163
162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rayburst/cc",
3
- "version": "3.1.6",
3
+ "version": "3.1.8",
4
4
  "type": "module",
5
5
  "description": "Always-on product context for Claude Code. Automatically injects feature atlas and acceptance criteria into every coding session.",
6
6
  "author": {