xdrs-core 0.24.1 → 0.26.0
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/.xdrs/_core/adrs/index.md +19 -19
- package/.xdrs/_core/adrs/principles/001-xdrs-core.md +37 -37
- package/.xdrs/_core/adrs/principles/002-policy-standards.md +153 -0
- package/.xdrs/_core/adrs/principles/003-skill-standards.md +23 -22
- package/.xdrs/_core/adrs/principles/004-article-standards.md +23 -23
- package/.xdrs/_core/adrs/principles/{005-semantic-versioning-for-xdr-packages.md → 005-semantic-versioning-for-xdrs-packages.md} +11 -11
- package/.xdrs/_core/adrs/principles/006-research-standards.md +24 -24
- package/.xdrs/_core/adrs/principles/007-plan-standards.md +14 -14
- package/.xdrs/_core/adrs/principles/008-xdr-standards-structured.md +19 -19
- package/.xdrs/_core/adrs/principles/009-presentation-standards.md +11 -11
- package/.xdrs/_core/adrs/principles/articles/001-xdrs-overview.md +61 -50
- package/.xdrs/_core/adrs/principles/skills/{001-lint/001-lint.test.int.js → 001-review/001-review.test.int.js} +4 -4
- package/.xdrs/_core/adrs/principles/skills/{001-lint/001-lint.test.int.report → 001-review/001-review.test.int.report} +1 -1
- package/.xdrs/_core/adrs/principles/skills/001-review/SKILL.md +94 -0
- package/.xdrs/_core/adrs/principles/skills/002-write-policy/002-write-policy.test.int.js +24 -0
- package/.xdrs/_core/adrs/principles/skills/{002-write-xdr/002-write-xdr.test.int.report → 002-write-policy/002-write-policy.test.int.report} +2 -2
- package/.xdrs/_core/adrs/principles/skills/{002-write-xdr → 002-write-policy}/SKILL.md +40 -40
- package/.xdrs/_core/adrs/principles/skills/003-write-skill/SKILL.md +18 -18
- package/.xdrs/_core/adrs/principles/skills/004-write-article/SKILL.md +32 -32
- package/.xdrs/_core/adrs/principles/skills/005-write-research/SKILL.md +25 -25
- package/.xdrs/_core/adrs/principles/skills/006-write-plan/SKILL.md +17 -17
- package/.xdrs/_core/adrs/principles/skills/007-write-presentation/SKILL.md +14 -14
- package/.xdrs/_core/index.md +21 -26
- package/.xdrs/index.md +4 -4
- package/AGENTS.md +12 -12
- package/README.md +53 -40
- package/lib/lint.js +53 -48
- package/lib/lint.test.js +96 -96
- package/package.json +3 -3
- package/.xdrs/_core/adrs/principles/002-xdr-standards.md +0 -158
- package/.xdrs/_core/adrs/principles/skills/001-lint/SKILL.md +0 -94
- package/.xdrs/_core/adrs/principles/skills/002-write-xdr/002-write-xdr.test.int.js +0 -24
- package/.xdrs/_core/bdrs/index.md +0 -9
- package/.xdrs/_core/bdrs/principles/001-xdr-decisions-and-skills-usage.md +0 -52
package/lib/lint.test.js
CHANGED
|
@@ -16,8 +16,8 @@ afterAll(() => {
|
|
|
16
16
|
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
test('reports broken local document links in
|
|
20
|
-
const workspaceRoot = createWorkspace('broken-
|
|
19
|
+
test('reports broken local document links in XDRS element files', () => {
|
|
20
|
+
const workspaceRoot = createWorkspace('broken-xdrs-element-link', {
|
|
21
21
|
'.xdrs/index.md': rootIndex(),
|
|
22
22
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
23
23
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -80,11 +80,11 @@ test('skips external scopes by default and checks them when ignoreExternal is fa
|
|
|
80
80
|
].join('\n'),
|
|
81
81
|
'.xdrs/extscope/adrs/principles/001-ext.md': [
|
|
82
82
|
'---',
|
|
83
|
-
'name: extscope-adr-001-ext',
|
|
84
|
-
'description: External test
|
|
83
|
+
'name: extscope-adr-policy-001-ext',
|
|
84
|
+
'description: External test XDRS element',
|
|
85
85
|
'---',
|
|
86
86
|
'',
|
|
87
|
-
'# extscope-adr-001: Ext decision',
|
|
87
|
+
'# extscope-adr-policy-001: Ext decision',
|
|
88
88
|
'',
|
|
89
89
|
'## Context and Problem Statement',
|
|
90
90
|
'',
|
|
@@ -136,11 +136,11 @@ test('skips entire external scope when only some of its files are in filedist',
|
|
|
136
136
|
].join('\n'),
|
|
137
137
|
'.xdrs/extscope/adrs/principles/001-ext.md': [
|
|
138
138
|
'---',
|
|
139
|
-
'name: extscope-adr-001-ext',
|
|
140
|
-
'description: External test
|
|
139
|
+
'name: extscope-adr-policy-001-ext',
|
|
140
|
+
'description: External test XDRS element',
|
|
141
141
|
'---',
|
|
142
142
|
'',
|
|
143
|
-
'# extscope-adr-001: Ext decision',
|
|
143
|
+
'# extscope-adr-policy-001: Ext decision',
|
|
144
144
|
'',
|
|
145
145
|
'## Context and Problem Statement',
|
|
146
146
|
'',
|
|
@@ -149,11 +149,11 @@ test('skips entire external scope when only some of its files are in filedist',
|
|
|
149
149
|
].join('\n'),
|
|
150
150
|
'.xdrs/extscope/adrs/principles/002-local.md': [
|
|
151
151
|
'---',
|
|
152
|
-
'name: extscope-adr-002-local',
|
|
153
|
-
'description: Second
|
|
152
|
+
'name: extscope-adr-policy-002-local',
|
|
153
|
+
'description: Second XDRS element in external scope',
|
|
154
154
|
'---',
|
|
155
155
|
'',
|
|
156
|
-
'# extscope-adr-002: Local decision',
|
|
156
|
+
'# extscope-adr-policy-002: Local decision',
|
|
157
157
|
'',
|
|
158
158
|
'## Context and Problem Statement',
|
|
159
159
|
'',
|
|
@@ -168,20 +168,20 @@ test('skips entire external scope when only some of its files are in filedist',
|
|
|
168
168
|
expect(result.errors.join('\n')).not.toContain('Broken local link in');
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
test('reports unknown frontmatter fields in
|
|
172
|
-
const workspaceRoot = createWorkspace('
|
|
171
|
+
test('reports unknown frontmatter fields in XDRS element documents', () => {
|
|
172
|
+
const workspaceRoot = createWorkspace('xdrs-element-unknown-frontmatter', {
|
|
173
173
|
'.xdrs/index.md': rootIndex(),
|
|
174
174
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
175
175
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
176
176
|
]),
|
|
177
177
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
178
178
|
'---',
|
|
179
|
-
'name: _local-adr-001-main',
|
|
180
|
-
'description: Test
|
|
179
|
+
'name: _local-adr-policy-001-main',
|
|
180
|
+
'description: Test XDRS element',
|
|
181
181
|
'unknown-field: some value',
|
|
182
182
|
'---',
|
|
183
183
|
'',
|
|
184
|
-
'# _local-adr-001: Main decision',
|
|
184
|
+
'# _local-adr-policy-001: Main decision',
|
|
185
185
|
'',
|
|
186
186
|
'## Context and Problem Statement',
|
|
187
187
|
'',
|
|
@@ -196,19 +196,19 @@ test('reports unknown frontmatter fields in XDR documents', () => {
|
|
|
196
196
|
|
|
197
197
|
const result = lintWorkspace(workspaceRoot);
|
|
198
198
|
|
|
199
|
-
expect(result.errors.join('\n')).toContain('
|
|
199
|
+
expect(result.errors.join('\n')).toContain('Policy frontmatter has unknown field "unknown-field"');
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
test('accepts all known frontmatter fields in
|
|
203
|
-
const workspaceRoot = createWorkspace('
|
|
202
|
+
test('accepts all known frontmatter fields in XDRS element documents', () => {
|
|
203
|
+
const workspaceRoot = createWorkspace('xdrs-element-known-frontmatter', {
|
|
204
204
|
'.xdrs/index.md': rootIndex(),
|
|
205
205
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
206
206
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
207
207
|
]),
|
|
208
208
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
209
209
|
'---',
|
|
210
|
-
'name: _local-adr-001-main',
|
|
211
|
-
'description: Test
|
|
210
|
+
'name: _local-adr-policy-001-main',
|
|
211
|
+
'description: Test XDRS element',
|
|
212
212
|
'apply-to: All projects',
|
|
213
213
|
'valid-from: 2026-01-01',
|
|
214
214
|
'license: MIT',
|
|
@@ -216,7 +216,7 @@ test('accepts all known frontmatter fields in XDR documents', () => {
|
|
|
216
216
|
' author: test',
|
|
217
217
|
'---',
|
|
218
218
|
'',
|
|
219
|
-
'# _local-adr-001: Main decision',
|
|
219
|
+
'# _local-adr-policy-001: Main decision',
|
|
220
220
|
'',
|
|
221
221
|
'## Context and Problem Statement',
|
|
222
222
|
'',
|
|
@@ -242,7 +242,7 @@ test('reports unknown frontmatter fields in SKILL.md files', () => {
|
|
|
242
242
|
]),
|
|
243
243
|
'.xdrs/_local/adrs/principles/skills/001-check-links/SKILL.md': [
|
|
244
244
|
'---',
|
|
245
|
-
'name: 001-check-links',
|
|
245
|
+
'name: _local-adr-skill-001-check-links',
|
|
246
246
|
'description: Test skill document',
|
|
247
247
|
'unknown-field: some value',
|
|
248
248
|
'---',
|
|
@@ -271,7 +271,7 @@ test('accepts all known frontmatter fields in SKILL.md files', () => {
|
|
|
271
271
|
]),
|
|
272
272
|
'.xdrs/_local/adrs/principles/skills/001-check-links/SKILL.md': [
|
|
273
273
|
'---',
|
|
274
|
-
'name: 001-check-links',
|
|
274
|
+
'name: _local-adr-skill-001-check-links',
|
|
275
275
|
'description: Test skill document',
|
|
276
276
|
'license: MIT',
|
|
277
277
|
'metadata:',
|
|
@@ -300,15 +300,15 @@ test('derives expected frontmatter name from the markdown heading title', () =>
|
|
|
300
300
|
const workspaceRoot = createWorkspace('heading-name-match', {
|
|
301
301
|
'.xdrs/index.md': rootIndex(),
|
|
302
302
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
303
|
-
'- [002-scope-guidelines](principles/002-
|
|
303
|
+
'- [002-scope-guidelines](principles/002-xdrs-scope-guidelines.md) - Scope guidelines'
|
|
304
304
|
]),
|
|
305
|
-
'.xdrs/_local/adrs/principles/002-
|
|
305
|
+
'.xdrs/_local/adrs/principles/002-xdrs-scope-guidelines.md': [
|
|
306
306
|
'---',
|
|
307
|
-
'name: _local-adr-002-
|
|
308
|
-
'description: Test
|
|
307
|
+
'name: _local-adr-policy-002-xdrs-scope-guidelines-for-agentme',
|
|
308
|
+
'description: Test XDRS element',
|
|
309
309
|
'---',
|
|
310
310
|
'',
|
|
311
|
-
'# _local-adr-002:
|
|
311
|
+
'# _local-adr-policy-002: XDRS scope guidelines for agentme',
|
|
312
312
|
'',
|
|
313
313
|
'## Context and Problem Statement',
|
|
314
314
|
'',
|
|
@@ -319,11 +319,11 @@ test('derives expected frontmatter name from the markdown heading title', () =>
|
|
|
319
319
|
|
|
320
320
|
const result = lintWorkspace(workspaceRoot, { ignoreExternal: false });
|
|
321
321
|
|
|
322
|
-
expect(result.errors.join('\n')).not.toContain('
|
|
322
|
+
expect(result.errors.join('\n')).not.toContain('Policy frontmatter name must be');
|
|
323
323
|
});
|
|
324
324
|
|
|
325
|
-
test('reports non-_local
|
|
326
|
-
const workspaceRoot = createWorkspace('non-local-links-to-local-
|
|
325
|
+
test('reports non-_local XDRS element linking to _local scope document', () => {
|
|
326
|
+
const workspaceRoot = createWorkspace('non-local-links-to-local-xdrs-element', {
|
|
327
327
|
'.xdrs/index.md': rootIndex(['[myteam](myteam/index.md)']),
|
|
328
328
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
329
329
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -343,7 +343,7 @@ test('reports non-_local XDR linking to _local scope document', () => {
|
|
|
343
343
|
expect(result.errors.join('\n')).toContain('Non-_local document must not link into _local scope');
|
|
344
344
|
});
|
|
345
345
|
|
|
346
|
-
test('allows _local
|
|
346
|
+
test('allows _local XDRS element linking to another _local scope document', () => {
|
|
347
347
|
const workspaceRoot = createWorkspace('local-links-to-local', {
|
|
348
348
|
'.xdrs/index.md': rootIndex(),
|
|
349
349
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
@@ -352,11 +352,11 @@ test('allows _local XDR linking to another _local scope document', () => {
|
|
|
352
352
|
]),
|
|
353
353
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
354
354
|
'---',
|
|
355
|
-
'name: _local-adr-001-main',
|
|
356
|
-
'description: Test
|
|
355
|
+
'name: _local-adr-policy-001-main',
|
|
356
|
+
'description: Test XDRS element',
|
|
357
357
|
'---',
|
|
358
358
|
'',
|
|
359
|
-
'# _local-adr-001: Main decision',
|
|
359
|
+
'# _local-adr-policy-001: Main decision',
|
|
360
360
|
'',
|
|
361
361
|
'## Context and Problem Statement',
|
|
362
362
|
'',
|
|
@@ -365,11 +365,11 @@ test('allows _local XDR linking to another _local scope document', () => {
|
|
|
365
365
|
].join('\n'),
|
|
366
366
|
'.xdrs/_local/adrs/principles/002-second.md': [
|
|
367
367
|
'---',
|
|
368
|
-
'name: _local-adr-002-second',
|
|
369
|
-
'description: Second test
|
|
368
|
+
'name: _local-adr-policy-002-second',
|
|
369
|
+
'description: Second test XDRS element',
|
|
370
370
|
'---',
|
|
371
371
|
'',
|
|
372
|
-
'# _local-adr-002: Second decision',
|
|
372
|
+
'# _local-adr-policy-002: Second decision',
|
|
373
373
|
'',
|
|
374
374
|
'## Context and Problem Statement',
|
|
375
375
|
'',
|
|
@@ -403,8 +403,8 @@ test('reports non-_local canonical index linking to _local scope document', () =
|
|
|
403
403
|
expect(result.errors.join('\n')).toContain('Non-_local document must not link into _local scope');
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
-
test('allows relative parent directory links but reports broken ones in
|
|
407
|
-
const workspaceRoot = createWorkspace('parent-dir-relative-link-in-
|
|
406
|
+
test('allows relative parent directory links but reports broken ones in XDRS element documents', () => {
|
|
407
|
+
const workspaceRoot = createWorkspace('parent-dir-relative-link-in-xdrs-element', {
|
|
408
408
|
'.xdrs/index.md': rootIndex(),
|
|
409
409
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
410
410
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -419,17 +419,17 @@ test('allows relative parent directory links but reports broken ones in XDR docu
|
|
|
419
419
|
expect(result.errors.join('\n')).toContain('../other.md');
|
|
420
420
|
});
|
|
421
421
|
|
|
422
|
-
test('allows child directory relative non-asset links in
|
|
423
|
-
const workspaceRoot = createWorkspace('child-dir-relative-link-in-
|
|
422
|
+
test('allows child directory relative non-asset links in XDRS element documents', () => {
|
|
423
|
+
const workspaceRoot = createWorkspace('child-dir-relative-link-in-xdrs-element', {
|
|
424
424
|
'.xdrs/index.md': rootIndex(),
|
|
425
425
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
426
426
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
427
427
|
]),
|
|
428
|
-
'.xdrs/_local/adrs/principles/001-main.md': xdrDocument('See [skill](skills/001-
|
|
428
|
+
'.xdrs/_local/adrs/principles/001-main.md': xdrDocument('See [skill](skills/001-review/SKILL.md).'),
|
|
429
429
|
});
|
|
430
|
-
const skillDir = path.join(workspaceRoot, '.xdrs/_local/adrs/principles/skills/001-
|
|
430
|
+
const skillDir = path.join(workspaceRoot, '.xdrs/_local/adrs/principles/skills/001-review');
|
|
431
431
|
fs.mkdirSync(skillDir, { recursive: true });
|
|
432
|
-
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), '---\nname: 001-
|
|
432
|
+
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), '---\nname: _local-adr-skill-001-review\ndescription: test skill\n---\n# Skill');
|
|
433
433
|
|
|
434
434
|
const result = lintWorkspace(workspaceRoot);
|
|
435
435
|
|
|
@@ -437,15 +437,15 @@ test('allows child directory relative non-asset links in XDR documents', () => {
|
|
|
437
437
|
expect(result.errors.join('\n')).not.toContain('Broken local link');
|
|
438
438
|
});
|
|
439
439
|
|
|
440
|
-
test('allows same-directory relative non-asset links in
|
|
441
|
-
const workspaceRoot = createWorkspace('same-dir-relative-link-in-
|
|
440
|
+
test('allows same-directory relative non-asset links in XDRS element documents', () => {
|
|
441
|
+
const workspaceRoot = createWorkspace('same-dir-relative-link-in-xdrs-element', {
|
|
442
442
|
'.xdrs/index.md': rootIndex(),
|
|
443
443
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
444
444
|
'- [001-main](principles/001-main.md) - Main decision',
|
|
445
445
|
'- [002-other](principles/002-other.md) - Other decision'
|
|
446
446
|
]),
|
|
447
447
|
'.xdrs/_local/adrs/principles/001-main.md': xdrDocument('See [other](002-other.md).'),
|
|
448
|
-
'.xdrs/_local/adrs/principles/002-other.md': xdrDocument('Other body.').replace('_local-adr-001-main', '_local-adr-002-other').replace('# _local-adr-001: Main decision', '# _local-adr-002: Other decision'),
|
|
448
|
+
'.xdrs/_local/adrs/principles/002-other.md': xdrDocument('Other body.').replace('_local-adr-policy-001-main', '_local-adr-policy-002-other').replace('# _local-adr-policy-001: Main decision', '# _local-adr-policy-002: Other decision'),
|
|
449
449
|
});
|
|
450
450
|
|
|
451
451
|
const result = lintWorkspace(workspaceRoot);
|
|
@@ -454,7 +454,7 @@ test('allows same-directory relative non-asset links in XDR documents', () => {
|
|
|
454
454
|
expect(result.errors.join('\n')).not.toContain('Broken local link');
|
|
455
455
|
});
|
|
456
456
|
|
|
457
|
-
test('allows relative asset links in
|
|
457
|
+
test('allows relative asset links in XDRS element documents', () => {
|
|
458
458
|
const workspaceRoot = createWorkspace('relative-asset-link', {
|
|
459
459
|
'.xdrs/index.md': rootIndex(),
|
|
460
460
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
@@ -487,7 +487,7 @@ test('reports absolute path link as error', () => {
|
|
|
487
487
|
expect(result.errors.join('\n')).toContain('999-nonexistent.md');
|
|
488
488
|
});
|
|
489
489
|
|
|
490
|
-
test('reports non-_local
|
|
490
|
+
test('reports non-_local XDRS element linking to _local scope via absolute path', () => {
|
|
491
491
|
const workspaceRoot = createWorkspace('abs-non-local-links-to-local', {
|
|
492
492
|
'.xdrs/index.md': rootIndex(['[myteam](myteam/index.md)']),
|
|
493
493
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
@@ -626,7 +626,7 @@ test('reports orphan asset in articles .assets directory', () => {
|
|
|
626
626
|
'- [001-guide](principles/articles/001-guide.md) - Guide article'
|
|
627
627
|
]),
|
|
628
628
|
'.xdrs/_local/adrs/principles/articles/001-guide.md': [
|
|
629
|
-
'# _local-article-001: Guide',
|
|
629
|
+
'# _local-adr-article-001: Guide',
|
|
630
630
|
'',
|
|
631
631
|
'See .',
|
|
632
632
|
''
|
|
@@ -668,11 +668,11 @@ test('reports nested directories in .assets when it has 10 files or fewer', () =
|
|
|
668
668
|
]),
|
|
669
669
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
670
670
|
'---',
|
|
671
|
-
'name: _local-adr-001-main-decision',
|
|
672
|
-
'description: Test
|
|
671
|
+
'name: _local-adr-policy-001-main-decision',
|
|
672
|
+
'description: Test XDRS element',
|
|
673
673
|
'---',
|
|
674
674
|
'',
|
|
675
|
-
'# _local-adr-001: Main decision',
|
|
675
|
+
'# _local-adr-policy-001: Main decision',
|
|
676
676
|
'',
|
|
677
677
|
'## Context and Problem Statement',
|
|
678
678
|
'',
|
|
@@ -702,11 +702,11 @@ test('allows nested directories in .assets when it has more than 10 files', () =
|
|
|
702
702
|
]),
|
|
703
703
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
704
704
|
'---',
|
|
705
|
-
'name: _local-adr-001-main-decision',
|
|
706
|
-
'description: Test
|
|
705
|
+
'name: _local-adr-policy-001-main-decision',
|
|
706
|
+
'description: Test XDRS element',
|
|
707
707
|
'---',
|
|
708
708
|
'',
|
|
709
|
-
'# _local-adr-001: Main decision',
|
|
709
|
+
'# _local-adr-policy-001: Main decision',
|
|
710
710
|
'',
|
|
711
711
|
'## Context and Problem Statement',
|
|
712
712
|
'',
|
|
@@ -752,11 +752,11 @@ function teamAdrIndex(entries) {
|
|
|
752
752
|
function teamXdrDocument(body) {
|
|
753
753
|
return [
|
|
754
754
|
'---',
|
|
755
|
-
'name: myteam-adr-001-team',
|
|
756
|
-
'description: Team test
|
|
755
|
+
'name: myteam-adr-policy-001-team',
|
|
756
|
+
'description: Team test XDRS element',
|
|
757
757
|
'---',
|
|
758
758
|
'',
|
|
759
|
-
'# myteam-adr-001: Team decision',
|
|
759
|
+
'# myteam-adr-policy-001: Team decision',
|
|
760
760
|
'',
|
|
761
761
|
'## Context and Problem Statement',
|
|
762
762
|
'',
|
|
@@ -784,11 +784,11 @@ function createWorkspace(name, files) {
|
|
|
784
784
|
|
|
785
785
|
function rootIndex(extraScopeLinks) {
|
|
786
786
|
const lines = [
|
|
787
|
-
'#
|
|
787
|
+
'# XDRS Index',
|
|
788
788
|
'',
|
|
789
789
|
'## Scope Indexes',
|
|
790
790
|
'',
|
|
791
|
-
'
|
|
791
|
+
'XDRS scopes listed last override the ones listed first',
|
|
792
792
|
'',
|
|
793
793
|
];
|
|
794
794
|
if (extraScopeLinks) {
|
|
@@ -818,11 +818,11 @@ function localAdrIndex(entries) {
|
|
|
818
818
|
function xdrDocument(body) {
|
|
819
819
|
return [
|
|
820
820
|
'---',
|
|
821
|
-
'name: _local-adr-001-main',
|
|
822
|
-
'description: Test
|
|
821
|
+
'name: _local-adr-policy-001-main',
|
|
822
|
+
'description: Test XDRS element',
|
|
823
823
|
'---',
|
|
824
824
|
'',
|
|
825
|
-
'# _local-adr-001: Main decision',
|
|
825
|
+
'# _local-adr-policy-001: Main decision',
|
|
826
826
|
'',
|
|
827
827
|
'## Context and Problem Statement',
|
|
828
828
|
'',
|
|
@@ -838,7 +838,7 @@ function xdrDocument(body) {
|
|
|
838
838
|
function skillDocument(body) {
|
|
839
839
|
return [
|
|
840
840
|
'---',
|
|
841
|
-
'name: 001-check-links',
|
|
841
|
+
'name: _local-adr-skill-001-check-links',
|
|
842
842
|
'description: Test skill document',
|
|
843
843
|
'---',
|
|
844
844
|
'',
|
|
@@ -855,14 +855,14 @@ function skillDocument(body) {
|
|
|
855
855
|
].join('\n');
|
|
856
856
|
}
|
|
857
857
|
|
|
858
|
-
test('accepts a custom root folder name as the
|
|
858
|
+
test('accepts a custom root folder name as the XDRS root when it contains index.md', () => {
|
|
859
859
|
const doc = [
|
|
860
860
|
'---',
|
|
861
|
-
'name: _local-adr-001-main-decision',
|
|
862
|
-
'description: Test
|
|
861
|
+
'name: _local-adr-policy-001-main-decision',
|
|
862
|
+
'description: Test XDRS element',
|
|
863
863
|
'---',
|
|
864
864
|
'',
|
|
865
|
-
'# _local-adr-001: Main decision',
|
|
865
|
+
'# _local-adr-policy-001: Main decision',
|
|
866
866
|
'',
|
|
867
867
|
'## Context and Problem Statement',
|
|
868
868
|
'',
|
|
@@ -891,11 +891,11 @@ test('accepts a custom root folder name as the XDR root when it contains index.m
|
|
|
891
891
|
test('falls back to .xdrs subdirectory when given path has no index.md', () => {
|
|
892
892
|
const doc = [
|
|
893
893
|
'---',
|
|
894
|
-
'name: _local-adr-001-main-decision',
|
|
895
|
-
'description: Test
|
|
894
|
+
'name: _local-adr-policy-001-main-decision',
|
|
895
|
+
'description: Test XDRS element',
|
|
896
896
|
'---',
|
|
897
897
|
'',
|
|
898
|
-
'# _local-adr-001: Main decision',
|
|
898
|
+
'# _local-adr-policy-001: Main decision',
|
|
899
899
|
'',
|
|
900
900
|
'## Context and Problem Statement',
|
|
901
901
|
'',
|
|
@@ -923,8 +923,8 @@ test('falls back to .xdrs subdirectory when given path has no index.md', () => {
|
|
|
923
923
|
|
|
924
924
|
// ─── Emoji checks ─────────────────────────────────────────────────────────────
|
|
925
925
|
|
|
926
|
-
test('reports emoji in
|
|
927
|
-
const workspaceRoot = createWorkspace('
|
|
926
|
+
test('reports emoji in XDRS element body', () => {
|
|
927
|
+
const workspaceRoot = createWorkspace('xdrs-element-emoji-body', {
|
|
928
928
|
'.xdrs/index.md': rootIndex(),
|
|
929
929
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
930
930
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -934,11 +934,11 @@ test('reports emoji in XDR document body', () => {
|
|
|
934
934
|
|
|
935
935
|
const result = lintWorkspace(workspaceRoot);
|
|
936
936
|
|
|
937
|
-
expect(result.errors.join('\n')).toContain('
|
|
937
|
+
expect(result.errors.join('\n')).toContain('Policy must not contain emojis');
|
|
938
938
|
});
|
|
939
939
|
|
|
940
|
-
test('does not report emoji inside a code block in
|
|
941
|
-
const workspaceRoot = createWorkspace('
|
|
940
|
+
test('does not report emoji inside a code block in XDRS element documents', () => {
|
|
941
|
+
const workspaceRoot = createWorkspace('xdrs-element-emoji-in-code-block', {
|
|
942
942
|
'.xdrs/index.md': rootIndex(),
|
|
943
943
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
944
944
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -1009,9 +1009,9 @@ test('reports emoji in plan document', () => {
|
|
|
1009
1009
|
|
|
1010
1010
|
// ─── Name / description length ────────────────────────────────────────────────
|
|
1011
1011
|
|
|
1012
|
-
test('reports
|
|
1013
|
-
const longName = '_local-adr-001-' + 'a'.repeat(50);
|
|
1014
|
-
const workspaceRoot = createWorkspace('
|
|
1012
|
+
test('reports XDRS element frontmatter name exceeding 64 characters', () => {
|
|
1013
|
+
const longName = '_local-adr-policy-001-' + 'a'.repeat(50);
|
|
1014
|
+
const workspaceRoot = createWorkspace('xdrs-element-name-too-long', {
|
|
1015
1015
|
'.xdrs/index.md': rootIndex(),
|
|
1016
1016
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
1017
1017
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -1019,10 +1019,10 @@ test('reports XDR frontmatter name exceeding 64 characters', () => {
|
|
|
1019
1019
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
1020
1020
|
'---',
|
|
1021
1021
|
`name: ${longName}`,
|
|
1022
|
-
'description: Test
|
|
1022
|
+
'description: Test XDRS element',
|
|
1023
1023
|
'---',
|
|
1024
1024
|
'',
|
|
1025
|
-
'# _local-adr-001: Main decision',
|
|
1025
|
+
'# _local-adr-policy-001: Main decision',
|
|
1026
1026
|
'',
|
|
1027
1027
|
'## Context and Problem Statement',
|
|
1028
1028
|
'',
|
|
@@ -1037,22 +1037,22 @@ test('reports XDR frontmatter name exceeding 64 characters', () => {
|
|
|
1037
1037
|
|
|
1038
1038
|
const result = lintWorkspace(workspaceRoot);
|
|
1039
1039
|
|
|
1040
|
-
expect(result.errors.join('\n')).toContain('
|
|
1040
|
+
expect(result.errors.join('\n')).toContain('Policy frontmatter name must be 64 characters or fewer');
|
|
1041
1041
|
});
|
|
1042
1042
|
|
|
1043
|
-
test('reports
|
|
1044
|
-
const workspaceRoot = createWorkspace('
|
|
1043
|
+
test('reports XDRS element frontmatter description exceeding 1024 characters', () => {
|
|
1044
|
+
const workspaceRoot = createWorkspace('xdrs-element-description-too-long', {
|
|
1045
1045
|
'.xdrs/index.md': rootIndex(),
|
|
1046
1046
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
1047
1047
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
1048
1048
|
]),
|
|
1049
1049
|
'.xdrs/_local/adrs/principles/001-main.md': [
|
|
1050
1050
|
'---',
|
|
1051
|
-
'name: _local-adr-001-main',
|
|
1051
|
+
'name: _local-adr-policy-001-main',
|
|
1052
1052
|
`description: ${'x'.repeat(1025)}`,
|
|
1053
1053
|
'---',
|
|
1054
1054
|
'',
|
|
1055
|
-
'# _local-adr-001: Main decision',
|
|
1055
|
+
'# _local-adr-policy-001: Main decision',
|
|
1056
1056
|
'',
|
|
1057
1057
|
'## Context and Problem Statement',
|
|
1058
1058
|
'',
|
|
@@ -1067,7 +1067,7 @@ test('reports XDR frontmatter description exceeding 1024 characters', () => {
|
|
|
1067
1067
|
|
|
1068
1068
|
const result = lintWorkspace(workspaceRoot);
|
|
1069
1069
|
|
|
1070
|
-
expect(result.errors.join('\n')).toContain('
|
|
1070
|
+
expect(result.errors.join('\n')).toContain('Policy frontmatter description must be 1024 characters or fewer');
|
|
1071
1071
|
});
|
|
1072
1072
|
|
|
1073
1073
|
test('reports SKILL.md frontmatter name exceeding 64 characters', () => {
|
|
@@ -1129,9 +1129,9 @@ test('reports SKILL.md frontmatter description exceeding 1024 characters', () =>
|
|
|
1129
1129
|
|
|
1130
1130
|
// ─── Word count ───────────────────────────────────────────────────────────────
|
|
1131
1131
|
|
|
1132
|
-
test('reports
|
|
1132
|
+
test('reports XDRS element document exceeding 2600 word limit', () => {
|
|
1133
1133
|
const longBody = ('word '.repeat(2601)).trimEnd();
|
|
1134
|
-
const workspaceRoot = createWorkspace('
|
|
1134
|
+
const workspaceRoot = createWorkspace('xdrs-element-too-many-words', {
|
|
1135
1135
|
'.xdrs/index.md': rootIndex(),
|
|
1136
1136
|
'.xdrs/_local/adrs/index.md': localAdrIndex([
|
|
1137
1137
|
'- [001-main](principles/001-main.md) - Main decision'
|
|
@@ -1141,7 +1141,7 @@ test('reports XDR document exceeding 2600 word limit', () => {
|
|
|
1141
1141
|
|
|
1142
1142
|
const result = lintWorkspace(workspaceRoot);
|
|
1143
1143
|
|
|
1144
|
-
expect(result.errors.join('\n')).toContain('
|
|
1144
|
+
expect(result.errors.join('\n')).toContain('Policy exceeds maximum word count of 2600');
|
|
1145
1145
|
});
|
|
1146
1146
|
|
|
1147
1147
|
test('reports article exceeding 5000 word limit', () => {
|
|
@@ -1392,7 +1392,7 @@ function slideDocument(body) {
|
|
|
1392
1392
|
|
|
1393
1393
|
function articleDocument(body) {
|
|
1394
1394
|
return [
|
|
1395
|
-
'# _local-article-001: Guide',
|
|
1395
|
+
'# _local-adr-article-001: Guide',
|
|
1396
1396
|
'',
|
|
1397
1397
|
'## Overview',
|
|
1398
1398
|
'',
|
|
@@ -1414,7 +1414,7 @@ function researchDocument(introBody, questionLine) {
|
|
|
1414
1414
|
? `${introBody}\n\n${questionLine}`
|
|
1415
1415
|
: introBody;
|
|
1416
1416
|
return [
|
|
1417
|
-
'# _local-research-001: Study',
|
|
1417
|
+
'# _local-adr-research-001: Study',
|
|
1418
1418
|
'',
|
|
1419
1419
|
'## Abstract',
|
|
1420
1420
|
'',
|
|
@@ -1449,7 +1449,7 @@ function researchDocument(introBody, questionLine) {
|
|
|
1449
1449
|
|
|
1450
1450
|
function planDocument(body) {
|
|
1451
1451
|
return [
|
|
1452
|
-
'# _local-plan-001: My plan',
|
|
1452
|
+
'# _local-adr-plan-001: My plan',
|
|
1453
1453
|
'',
|
|
1454
1454
|
'## Executive Summary',
|
|
1455
1455
|
'',
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xdrs-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "0.26.0",
|
|
4
|
+
"description": "A framework to structure, compile and distribute Architectural (ADR), Business (BDR), and Engineering (EDR) decision records contents so that AI agents and humans can reliably find and use them with hierarchical scopes and controlled rollout in the format of distributable versioned packages.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/flaviostutz/xdrs-core.git"
|
|
8
8
|
},
|
|
9
9
|
"keywords": [
|
|
10
|
-
"
|
|
10
|
+
"xdrs",
|
|
11
11
|
"adr",
|
|
12
12
|
"decision-records",
|
|
13
13
|
"ai-agents"
|