@karmaniverous/jeeves 0.3.0 → 0.3.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.
@@ -177,11 +177,17 @@ No stranded local branches. Push immediately after commit. A commit that isn't p
177
177
 
178
178
  ### Check PR State Before Pushing
179
179
 
180
- **Before EVERY `git push`**, verify the PR is not already merged. Pushing to a merged branch creates orphaned work that is invisible in the main branch and wastes effort.
180
+ **Before EVERY `git push`**, run `gh pr list --head <branch> --repo <repo> --json number,state` to check whether a PR exists on that branch and whether it's merged.
181
181
 
182
- Sequence: `gh pr view --json state` → confirm state is `OPEN` → push. If no PR exists yet, pushing is safe. If the PR is `MERGED` or `CLOSED`, **STOP** and report to the user.
182
+ - **No PR exists:** Safe to push.
183
+ - **PR is `OPEN`:** Safe to push.
184
+ - **PR is `MERGED` or `CLOSED`:** **STOP** and report to the user. Do not push to a merged PR branch.
183
185
 
184
- This is not optional. It applies to every push, every branch, every time.
186
+ This is not optional. It applies to every push, every branch, every time. No judgment call about whether the branch "is a PR branch" — the check is mechanical.
187
+
188
+ ### New PR Over Merged Branch
189
+
190
+ When a PR has been merged and additional work is needed on the same branch, create a new PR on the **same branch** targeting the same base. Do not create new branches, cherry-pick, or start over. The commits are already there — `gh pr create --head <existing-branch>` is the entire operation.
185
191
 
186
192
  ## Managed Content Self-Maintenance
187
193
 
@@ -21,6 +21,7 @@
21
21
  I am a **senior software engineer** first. The persona is style; the engineering discipline is substance.
22
22
 
23
23
  What this means in practice:
24
+ - **Do not execute untested code.** Every mutation script defaults to dry-run mode. The dry-run output is the test — it shows what would happen. Live execution requires an explicit flag. If dry-run is hard to implement, that's a design flaw.
24
25
  - **No cowboy coding.** I don't iterate in production. I don't ship untested changes. I don't treat live systems as scratch pads.
25
26
  - **I follow proper workflows.** Branch, test, review, merge. CI/CD exists for a reason. If there's a pipeline, I use it.
26
27
  - **I resist n00b temptations.** "Let me just quickly…" in prod is how outages happen. I know better.
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
  import require$$0 from 'commander';
4
3
  import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, cpSync, rmSync } from 'node:fs';
5
4
  import { join, dirname } from 'node:path';
@@ -104,6 +103,12 @@ const AGENTS_MARKERS = {
104
103
  /** H1 title prepended in the managed block. */
105
104
  title: 'Jeeves Platform Agents',
106
105
  };
106
+ /** All known marker sets — single source of truth for cross-contamination detection. */
107
+ const ALL_MARKERS = [
108
+ TOOLS_MARKERS,
109
+ SOUL_MARKERS,
110
+ AGENTS_MARKERS,
111
+ ];
107
112
  /**
108
113
  * Regex pattern to extract version stamp from a BEGIN marker comment.
109
114
  *
@@ -200,14 +205,14 @@ const SECTION_ORDER = [
200
205
  * Core library version, inlined at build time.
201
206
  *
202
207
  * @remarks
203
- * The `0.2.0` placeholder is replaced by
208
+ * The `0.3.0` placeholder is replaced by
204
209
  * `@rollup/plugin-replace` during the build with the actual version
205
210
  * from `package.json`. This ensures the correct version survives
206
211
  * when consumers bundle core into their own dist (where runtime
207
212
  * `import.meta.url`-based resolution would find the wrong package.json).
208
213
  */
209
214
  /** The core library version from package.json (inlined at build time). */
210
- const CORE_VERSION = '0.2.0';
215
+ const CORE_VERSION = '0.3.0';
211
216
 
212
217
  /**
213
218
  * Core configuration schema and resolution.
@@ -541,11 +546,17 @@ No stranded local branches. Push immediately after commit. A commit that isn't p
541
546
 
542
547
  ### Check PR State Before Pushing
543
548
 
544
- **Before EVERY \`git push\`**, verify the PR is not already merged. Pushing to a merged branch creates orphaned work that is invisible in the main branch and wastes effort.
549
+ **Before EVERY \`git push\`**, run \`gh pr list --head <branch> --repo <repo> --json number,state\` to check whether a PR exists on that branch and whether it's merged.
550
+
551
+ - **No PR exists:** Safe to push.
552
+ - **PR is \`OPEN\`:** Safe to push.
553
+ - **PR is \`MERGED\` or \`CLOSED\`:** **STOP** and report to the user. Do not push to a merged PR branch.
545
554
 
546
- Sequence: \`gh pr view --json state\` → confirm state is \`OPEN\` → push. If no PR exists yet, pushing is safe. If the PR is \`MERGED\` or \`CLOSED\`, **STOP** and report to the user.
555
+ This is not optional. It applies to every push, every branch, every time. No judgment call about whether the branch "is a PR branch" — the check is mechanical.
547
556
 
548
- This is not optional. It applies to every push, every branch, every time.
557
+ ### New PR Over Merged Branch
558
+
559
+ When a PR has been merged and additional work is needed on the same branch, create a new PR on the **same branch** targeting the same base. Do not create new branches, cherry-pick, or start over. The commits are already there — \`gh pr create --head <existing-branch>\` is the entire operation.
549
560
 
550
561
  ## Managed Content Self-Maintenance
551
562
 
@@ -581,6 +592,7 @@ var soulSectionContent = `## Core Truths
581
592
  I am a **senior software engineer** first. The persona is style; the engineering discipline is substance.
582
593
 
583
594
  What this means in practice:
595
+ - **Do not execute untested code.** Every mutation script defaults to dry-run mode. The dry-run output is the test — it shows what would happen. Live execution requires an explicit flag. If dry-run is hard to implement, that's a design flaw.
584
596
  - **No cowboy coding.** I don't iterate in production. I don't ship untested changes. I don't treat live systems as scratch pads.
585
597
  - **I follow proper workflows.** Branch, test, review, merge. CI/CD exists for a reason. If there's a pipeline, I use it.
586
598
  - **I resist n00b temptations.** "Let me just quickly…" in prod is how outages happen. I know better.
@@ -1024,6 +1036,48 @@ function parseManaged(fileContent, markers = TOOLS_MARKERS) {
1024
1036
  };
1025
1037
  }
1026
1038
 
1039
+ /**
1040
+ * Strip foreign managed blocks from content.
1041
+ *
1042
+ * @remarks
1043
+ * Prevents cross-contamination by removing managed blocks that belong
1044
+ * to other marker sets. For example, when writing TOOLS.md with TOOLS
1045
+ * markers, any SOUL or AGENTS managed blocks found in the user content
1046
+ * zone are stripped — they don't belong there.
1047
+ *
1048
+ * @packageDocumentation
1049
+ */
1050
+ /**
1051
+ * Build a regex that matches an entire managed block (BEGIN marker through END marker).
1052
+ *
1053
+ * @param markers - The marker set to match.
1054
+ * @returns A regex that matches the full block including markers.
1055
+ */
1056
+ function buildBlockPattern(markers) {
1057
+ const escapedBegin = markers.begin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1058
+ const escapedEnd = markers.end.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1059
+ return new RegExp(`\\s*<!--\\s*${escapedBegin}(?:\\s*\\|[^>]*)?\\s*(?:—[^>]*)?\\s*-->[\\s\\S]*?<!--\\s*${escapedEnd}\\s*-->\\s*`, 'g');
1060
+ }
1061
+ /**
1062
+ * Strip managed blocks belonging to foreign marker sets from content.
1063
+ *
1064
+ * @param content - The content to clean (typically user content zone).
1065
+ * @param currentMarkers - The marker set that owns this file (will NOT be stripped).
1066
+ * @returns Content with foreign managed blocks removed.
1067
+ */
1068
+ function stripForeignMarkers(content, currentMarkers) {
1069
+ let result = content;
1070
+ for (const markers of ALL_MARKERS) {
1071
+ // Skip the current file's own markers
1072
+ if (markers.begin === currentMarkers.begin)
1073
+ continue;
1074
+ const pattern = buildBlockPattern(markers);
1075
+ result = result.replace(pattern, '\n');
1076
+ }
1077
+ // Clean up multiple blank lines left by removals
1078
+ return result.replace(/\n{3,}/g, '\n\n').trim();
1079
+ }
1080
+
1027
1081
  /**
1028
1082
  * Version-stamp parsing and convergence logic.
1029
1083
  *
@@ -1140,8 +1194,8 @@ async function updateManagedSection(filePath, content, options = {}) {
1140
1194
  ? `# ${markers.title}\n\n${sectionText}`
1141
1195
  : sectionText;
1142
1196
  }
1143
- // Cleanup detection
1144
- const userContent = parsed.userContent;
1197
+ // Strip foreign managed blocks from user content (cross-contamination fix)
1198
+ const userContent = stripForeignMarkers(parsed.userContent, markers);
1145
1199
  const cleanupNeeded = needsCleanup(newManagedBody, userContent);
1146
1200
  // Build the full managed block
1147
1201
  const beginLine = formatBeginMarker(markers.begin, coreVersion);
package/dist/index.d.ts CHANGED
@@ -910,7 +910,9 @@ declare function patchConfig(config: Record<string, unknown>, pluginId: string,
910
910
  interface ToolResult {
911
911
  /** Content blocks — typically a single text block. */
912
912
  content: Array<{
913
+ /** MIME type identifier (e.g. `"text"`). */
913
914
  type: string;
915
+ /** Text content of the block. */
914
916
  text: string;
915
917
  }>;
916
918
  /** Whether this result represents an error. */
@@ -955,6 +957,7 @@ interface PluginApi {
955
957
  plugins?: {
956
958
  /** Plugin entries keyed by plugin ID. */
957
959
  entries?: Record<string, {
960
+ /** Plugin-specific configuration key-value pairs. */
958
961
  config?: Record<string, unknown>;
959
962
  }>;
960
963
  };
package/dist/index.js CHANGED
@@ -80,14 +80,14 @@ const COMPONENT_VERSIONS_FILE = 'component-versions.json';
80
80
  * Core library version, inlined at build time.
81
81
  *
82
82
  * @remarks
83
- * The `0.2.0` placeholder is replaced by
83
+ * The `0.3.0` placeholder is replaced by
84
84
  * `@rollup/plugin-replace` during the build with the actual version
85
85
  * from `package.json`. This ensures the correct version survives
86
86
  * when consumers bundle core into their own dist (where runtime
87
87
  * `import.meta.url`-based resolution would find the wrong package.json).
88
88
  */
89
89
  /** The core library version from package.json (inlined at build time). */
90
- const CORE_VERSION = '0.2.0';
90
+ const CORE_VERSION = '0.3.0';
91
91
 
92
92
  /**
93
93
  * Shared file I/O helpers for managed section operations.
@@ -235,6 +235,12 @@ const AGENTS_MARKERS = {
235
235
  /** H1 title prepended in the managed block. */
236
236
  title: 'Jeeves Platform Agents',
237
237
  };
238
+ /** All known marker sets — single source of truth for cross-contamination detection. */
239
+ const ALL_MARKERS = [
240
+ TOOLS_MARKERS,
241
+ SOUL_MARKERS,
242
+ AGENTS_MARKERS,
243
+ ];
238
244
  /**
239
245
  * Regex pattern to extract version stamp from a BEGIN marker comment.
240
246
  *
@@ -583,6 +589,48 @@ function parseManaged(fileContent, markers = TOOLS_MARKERS) {
583
589
  };
584
590
  }
585
591
 
592
+ /**
593
+ * Strip foreign managed blocks from content.
594
+ *
595
+ * @remarks
596
+ * Prevents cross-contamination by removing managed blocks that belong
597
+ * to other marker sets. For example, when writing TOOLS.md with TOOLS
598
+ * markers, any SOUL or AGENTS managed blocks found in the user content
599
+ * zone are stripped — they don't belong there.
600
+ *
601
+ * @packageDocumentation
602
+ */
603
+ /**
604
+ * Build a regex that matches an entire managed block (BEGIN marker through END marker).
605
+ *
606
+ * @param markers - The marker set to match.
607
+ * @returns A regex that matches the full block including markers.
608
+ */
609
+ function buildBlockPattern(markers) {
610
+ const escapedBegin = markers.begin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
611
+ const escapedEnd = markers.end.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
612
+ return new RegExp(`\\s*<!--\\s*${escapedBegin}(?:\\s*\\|[^>]*)?\\s*(?:—[^>]*)?\\s*-->[\\s\\S]*?<!--\\s*${escapedEnd}\\s*-->\\s*`, 'g');
613
+ }
614
+ /**
615
+ * Strip managed blocks belonging to foreign marker sets from content.
616
+ *
617
+ * @param content - The content to clean (typically user content zone).
618
+ * @param currentMarkers - The marker set that owns this file (will NOT be stripped).
619
+ * @returns Content with foreign managed blocks removed.
620
+ */
621
+ function stripForeignMarkers(content, currentMarkers) {
622
+ let result = content;
623
+ for (const markers of ALL_MARKERS) {
624
+ // Skip the current file's own markers
625
+ if (markers.begin === currentMarkers.begin)
626
+ continue;
627
+ const pattern = buildBlockPattern(markers);
628
+ result = result.replace(pattern, '\n');
629
+ }
630
+ // Clean up multiple blank lines left by removals
631
+ return result.replace(/\n{3,}/g, '\n\n').trim();
632
+ }
633
+
586
634
  /**
587
635
  * Version-stamp parsing and convergence logic.
588
636
  *
@@ -699,8 +747,8 @@ async function updateManagedSection(filePath, content, options = {}) {
699
747
  ? `# ${markers.title}\n\n${sectionText}`
700
748
  : sectionText;
701
749
  }
702
- // Cleanup detection
703
- const userContent = parsed.userContent;
750
+ // Strip foreign managed blocks from user content (cross-contamination fix)
751
+ const userContent = stripForeignMarkers(parsed.userContent, markers);
704
752
  const cleanupNeeded = needsCleanup(newManagedBody, userContent);
705
753
  // Build the full managed block
706
754
  const beginLine = formatBeginMarker(markers.begin, coreVersion);
@@ -914,11 +962,17 @@ No stranded local branches. Push immediately after commit. A commit that isn't p
914
962
 
915
963
  ### Check PR State Before Pushing
916
964
 
917
- **Before EVERY \`git push\`**, verify the PR is not already merged. Pushing to a merged branch creates orphaned work that is invisible in the main branch and wastes effort.
965
+ **Before EVERY \`git push\`**, run \`gh pr list --head <branch> --repo <repo> --json number,state\` to check whether a PR exists on that branch and whether it's merged.
966
+
967
+ - **No PR exists:** Safe to push.
968
+ - **PR is \`OPEN\`:** Safe to push.
969
+ - **PR is \`MERGED\` or \`CLOSED\`:** **STOP** and report to the user. Do not push to a merged PR branch.
970
+
971
+ This is not optional. It applies to every push, every branch, every time. No judgment call about whether the branch "is a PR branch" — the check is mechanical.
918
972
 
919
- Sequence: \`gh pr view --json state\` → confirm state is \`OPEN\` → push. If no PR exists yet, pushing is safe. If the PR is \`MERGED\` or \`CLOSED\`, **STOP** and report to the user.
973
+ ### New PR Over Merged Branch
920
974
 
921
- This is not optional. It applies to every push, every branch, every time.
975
+ When a PR has been merged and additional work is needed on the same branch, create a new PR on the **same branch** targeting the same base. Do not create new branches, cherry-pick, or start over. The commits are already there — \`gh pr create --head <existing-branch>\` is the entire operation.
922
976
 
923
977
  ## Managed Content Self-Maintenance
924
978
 
@@ -954,6 +1008,7 @@ var soulSectionContent = `## Core Truths
954
1008
  I am a **senior software engineer** first. The persona is style; the engineering discipline is substance.
955
1009
 
956
1010
  What this means in practice:
1011
+ - **Do not execute untested code.** Every mutation script defaults to dry-run mode. The dry-run output is the test — it shows what would happen. Live execution requires an explicit flag. If dry-run is hard to implement, that's a design flaw.
957
1012
  - **No cowboy coding.** I don't iterate in production. I don't ship untested changes. I don't treat live systems as scratch pads.
958
1013
  - **I follow proper workflows.** Branch, test, review, merge. CI/CD exists for a reason. If there's a pipeline, I use it.
959
1014
  - **I resist n00b temptations.** "Let me just quickly…" in prod is how outages happen. I know better.
package/package.json CHANGED
@@ -139,5 +139,5 @@
139
139
  },
140
140
  "type": "module",
141
141
  "types": "dist/index.d.ts",
142
- "version": "0.3.0"
142
+ "version": "0.3.1"
143
143
  }