@dalzoubi/dev-agents-sync 1.0.26 → 2.0.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 +14 -0
- package/eslint.config.mjs +9 -0
- package/package.json +1 -1
- package/src/claudeMd.mjs +220 -0
- package/src/commands/check.mjs +66 -1
- package/src/commands/init.mjs +26 -0
- package/src/commands/update.mjs +24 -0
- package/tests/checkClaudeMd.test.mjs +656 -0
- package/tests/claudeMd.test.mjs +910 -0
- package/tests/e2e/claudeMd-injection.test.mjs +846 -0
- package/tests/e2e/readme-coverage.test.mjs +183 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tests/e2e/readme-coverage.test.mjs
|
|
3
|
+
*
|
|
4
|
+
* Asserts that the CLI README documents CLAUDE.md injection in the
|
|
5
|
+
* init → update → check flow.
|
|
6
|
+
*
|
|
7
|
+
* These tests are RED until the README is updated to describe the feature.
|
|
8
|
+
*
|
|
9
|
+
* The README must:
|
|
10
|
+
* 1. Mention "CLAUDE.md" somewhere in the document.
|
|
11
|
+
* 2. Describe "auto-route" or "routing" in the context of init/update/check.
|
|
12
|
+
* 3. Mention the auto-route feature in the init section (so users know it
|
|
13
|
+
* happens on first run).
|
|
14
|
+
* 4. Mention the auto-route feature in the update section (so users know
|
|
15
|
+
* the block is refreshed on update).
|
|
16
|
+
* 5. Mention CLAUDE.md or routing in the check section (so users know
|
|
17
|
+
* check verifies the block).
|
|
18
|
+
*
|
|
19
|
+
* Implement agent must update `packages/dev-agents-sync/README.md` before
|
|
20
|
+
* these tests go green.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { describe, it } from 'node:test';
|
|
24
|
+
import assert from 'node:assert/strict';
|
|
25
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import { fileURLToPath } from 'node:url';
|
|
28
|
+
|
|
29
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const README_PATH = path.join(__dirname, '..', '..', 'README.md');
|
|
31
|
+
|
|
32
|
+
function readReadme() {
|
|
33
|
+
assert.ok(
|
|
34
|
+
existsSync(README_PATH),
|
|
35
|
+
`README.md must exist at ${README_PATH}`,
|
|
36
|
+
);
|
|
37
|
+
return readFileSync(README_PATH, 'utf8');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Criterion 1 — README mentions "CLAUDE.md"
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
describe('README: mentions CLAUDE.md', () => {
|
|
45
|
+
it('README.md contains the string "CLAUDE.md"', () => {
|
|
46
|
+
const content = readReadme();
|
|
47
|
+
assert.ok(
|
|
48
|
+
content.includes('CLAUDE.md'),
|
|
49
|
+
'README.md must mention "CLAUDE.md" to document the injection feature.\n' +
|
|
50
|
+
'The init → update → check flow injects a fenced routing block into the ' +
|
|
51
|
+
"consumer's CLAUDE.md — this must be documented.",
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Criterion 2 — README mentions "auto-route" or "routing"
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
describe('README: mentions routing/auto-route', () => {
|
|
61
|
+
it('README.md contains "auto-route" or "routing"', () => {
|
|
62
|
+
const content = readReadme();
|
|
63
|
+
const mentionsRouting =
|
|
64
|
+
content.includes('auto-route') ||
|
|
65
|
+
content.toLowerCase().includes('routing');
|
|
66
|
+
|
|
67
|
+
assert.ok(
|
|
68
|
+
mentionsRouting,
|
|
69
|
+
'README.md must mention "auto-route" or "routing" to describe what ' +
|
|
70
|
+
'the CLAUDE.md injection feature does (it injects an auto-routing block).',
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Criterion 3 — init section describes CLAUDE.md injection
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
describe('README: init section describes CLAUDE.md injection', () => {
|
|
80
|
+
it('the init section (or surrounding text) mentions CLAUDE.md injection', () => {
|
|
81
|
+
const content = readReadme();
|
|
82
|
+
|
|
83
|
+
// Find the region around `init` documentation.
|
|
84
|
+
// Accept any of: a code block containing `init`, a heading containing init,
|
|
85
|
+
// or a paragraph mentioning init alongside CLAUDE.md.
|
|
86
|
+
//
|
|
87
|
+
// Strategy: check that both "init" and "CLAUDE.md" appear, and that
|
|
88
|
+
// there's a passage where they are in proximity (within 500 chars).
|
|
89
|
+
const initIndex = content.indexOf('init');
|
|
90
|
+
assert.notEqual(
|
|
91
|
+
initIndex,
|
|
92
|
+
-1,
|
|
93
|
+
'README.md must contain the text "init" to document the init subcommand',
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Find the nearest occurrence of CLAUDE.md to any occurrence of init.
|
|
97
|
+
let foundProximity = false;
|
|
98
|
+
let searchFrom = 0;
|
|
99
|
+
while (true) {
|
|
100
|
+
const idx = content.indexOf('init', searchFrom);
|
|
101
|
+
if (idx === -1) break;
|
|
102
|
+
// Look for CLAUDE.md within 600 characters before or after this occurrence.
|
|
103
|
+
const windowStart = Math.max(0, idx - 300);
|
|
104
|
+
const windowEnd = Math.min(content.length, idx + 300);
|
|
105
|
+
const window = content.slice(windowStart, windowEnd);
|
|
106
|
+
if (window.includes('CLAUDE.md')) {
|
|
107
|
+
foundProximity = true;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
searchFrom = idx + 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
assert.ok(
|
|
114
|
+
foundProximity,
|
|
115
|
+
'README.md must describe CLAUDE.md injection in proximity to the "init" section.\n' +
|
|
116
|
+
'Users running `init` need to know that CLAUDE.md will be created/updated with ' +
|
|
117
|
+
'the auto-routing fenced block.',
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Criterion 4 — update section describes CLAUDE.md injection
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
describe('README: update section describes CLAUDE.md injection', () => {
|
|
127
|
+
it('the update section (or surrounding text) mentions CLAUDE.md or routing', () => {
|
|
128
|
+
const content = readReadme();
|
|
129
|
+
|
|
130
|
+
let foundProximity = false;
|
|
131
|
+
let searchFrom = 0;
|
|
132
|
+
while (true) {
|
|
133
|
+
const idx = content.indexOf('update', searchFrom);
|
|
134
|
+
if (idx === -1) break;
|
|
135
|
+
const windowStart = Math.max(0, idx - 300);
|
|
136
|
+
const windowEnd = Math.min(content.length, idx + 300);
|
|
137
|
+
const window = content.slice(windowStart, windowEnd);
|
|
138
|
+
if (window.includes('CLAUDE.md') || window.toLowerCase().includes('routing') || window.includes('auto-route')) {
|
|
139
|
+
foundProximity = true;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
searchFrom = idx + 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
assert.ok(
|
|
146
|
+
foundProximity,
|
|
147
|
+
'README.md must describe CLAUDE.md or routing in proximity to the "update" section.\n' +
|
|
148
|
+
'Users running `update` need to know that the CLAUDE.md routing block will be refreshed.',
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Criterion 5 — check section describes CLAUDE.md or routing verification
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
describe('README: check section describes CLAUDE.md / routing verification', () => {
|
|
158
|
+
it('the check section (or surrounding text) mentions CLAUDE.md or routing', () => {
|
|
159
|
+
const content = readReadme();
|
|
160
|
+
|
|
161
|
+
let foundProximity = false;
|
|
162
|
+
let searchFrom = 0;
|
|
163
|
+
while (true) {
|
|
164
|
+
const idx = content.indexOf('check', searchFrom);
|
|
165
|
+
if (idx === -1) break;
|
|
166
|
+
const windowStart = Math.max(0, idx - 300);
|
|
167
|
+
const windowEnd = Math.min(content.length, idx + 300);
|
|
168
|
+
const window = content.slice(windowStart, windowEnd);
|
|
169
|
+
if (window.includes('CLAUDE.md') || window.toLowerCase().includes('routing') || window.includes('auto-route')) {
|
|
170
|
+
foundProximity = true;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
searchFrom = idx + 1;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
assert.ok(
|
|
177
|
+
foundProximity,
|
|
178
|
+
'README.md must describe CLAUDE.md or routing in proximity to the "check" section.\n' +
|
|
179
|
+
'Users running `check` need to know that drift in the CLAUDE.md routing block ' +
|
|
180
|
+
'is detected (exit 1, CLAUDE.md named in the error).',
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
});
|