clud-bug 0.6.18 → 0.6.19

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/lib/agents-md.js CHANGED
@@ -86,6 +86,35 @@ export function upsertBlock(content, block) {
86
86
  return `${content}${sep}${block}\n`;
87
87
  }
88
88
 
89
+ // 0.0.I.1 (v0.6.X): true if `content` has Claude Code's `@AGENTS.md`
90
+ // @-import — the canonical AGENTS.md content gets eager-loaded.
91
+ //
92
+ // Matches at start-of-line (a literal `@AGENTS.md` mentioned in prose
93
+ // won't fire; only the import directive does). Allows trailing space
94
+ // (some editors trim it; some don't) and optional newline terminator.
95
+ export function hasAgentsMdImport(content) {
96
+ if (typeof content !== 'string') return false;
97
+ return /^@AGENTS\.md\s*$/m.test(content);
98
+ }
99
+
100
+ // 0.0.I.1: strip a clud-bug block (markers + body) AND the blank line
101
+ // that precedes it, if any. Used when an @AGENTS.md import is detected
102
+ // — the AGENTS.md content covers the block, so keeping it in CLAUDE.md
103
+ // (or any tool stub) is duplication.
104
+ //
105
+ // Returns the cleaned content. If no block exists, returns content
106
+ // unchanged. Idempotent.
107
+ export function removeBlock(content) {
108
+ if (typeof content !== 'string') return content;
109
+ // Strip the block. Match \n+ before the marker so we also eat the
110
+ // preceding blank line — otherwise we'd leave a "stub line + blank
111
+ // + block" structure as "stub line + blank line".
112
+ const re = new RegExp(
113
+ `\\n*${escapeRe(START_MARKER)}[\\s\\S]*?${escapeRe(END_MARKER)}\\n?`,
114
+ );
115
+ return content.replace(re, '');
116
+ }
117
+
89
118
  function escapeRe(s) {
90
119
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
91
120
  }
@@ -116,7 +145,7 @@ export async function applyToRepo(cwd, blockOpts = {}) {
116
145
  const full = join(cwd, path);
117
146
  if (!(await fileExists(full))) continue;
118
147
  const prior = await readFile(full, 'utf8');
119
- const next = upsertBlock(prior, block);
148
+ const next = nextContentFor(prior, block);
120
149
  if (next !== prior) {
121
150
  await writeFile(full, next);
122
151
  touched.push(path);
@@ -132,7 +161,7 @@ export async function applyToRepo(cwd, blockOpts = {}) {
132
161
  if (!name.endsWith('.md')) continue;
133
162
  const full = join(cursorRulesDir, name);
134
163
  const prior = await readFile(full, 'utf8');
135
- const next = upsertBlock(prior, block);
164
+ const next = nextContentFor(prior, block);
136
165
  if (next !== prior) {
137
166
  await writeFile(full, next);
138
167
  touched.push(`.cursor/rules/${name}`);
@@ -143,6 +172,18 @@ export async function applyToRepo(cwd, blockOpts = {}) {
143
172
  return { touched, created };
144
173
  }
145
174
 
175
+ // 0.0.I.1: decide what content a TOUCH_IF_PRESENT file should have.
176
+ // If it already imports AGENTS.md via Claude Code's @-syntax, skip the
177
+ // block entirely (and clean up any pre-existing block — the content is
178
+ // duplicated via @-import, so the AGENTS.md block is the only authority).
179
+ // Otherwise, upsert as before.
180
+ //
181
+ // AGENTS.md itself is NOT routed through here — it always gets the
182
+ // block (it's the canonical source).
183
+ function nextContentFor(prior, block) {
184
+ return hasAgentsMdImport(prior) ? removeBlock(prior) : upsertBlock(prior, block);
185
+ }
186
+
146
187
  function seedFile(name) {
147
188
  // When AGENTS.md doesn't exist (no logmind, no prior tooling), seed with a
148
189
  // minimal canonical header so the clud-bug block has context.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clud-bug",
3
- "version": "0.6.18",
3
+ "version": "0.6.19",
4
4
  "description": "Skill-driven Claude PR review. Ship a brand-voice skill, get brand reviews. Each finding cites the skill that motivated it. CLI installs the workflow + a baseline kit; add more from skills.sh.",
5
5
  "homepage": "https://cludbug.dev",
6
6
  "bugs": "https://github.com/thrillmade/clud-bug/issues",
@@ -156,6 +156,6 @@ jobs:
156
156
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
157
157
  - name: Strict mode — fail check on critical findings
158
158
  if: success()
159
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.18
159
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.19
160
160
  with:
161
161
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -156,6 +156,6 @@ jobs:
156
156
  # Strict-mode gate — composite action; see workflow.yml.tmpl for design notes.
157
157
  - name: Strict mode — fail check on critical findings
158
158
  if: success()
159
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.18
159
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.19
160
160
  with:
161
161
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -247,6 +247,6 @@ jobs:
247
247
  # Letting the action's own failure fail the check is louder and right.
248
248
  - name: Strict mode — fail check on critical findings
249
249
  if: success()
250
- uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.18
250
+ uses: thrillmade/clud-bug/.github/actions/strict-mode-gate@v0.6.19
251
251
  with:
252
252
  github-token: ${{ secrets.GITHUB_TOKEN }}