xdrs-core 0.35.1 → 0.36.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.
@@ -64,6 +64,9 @@ Policy documents are the authoritative source of truth for their scope, type, an
64
64
  - Policies MUST be concise and reference other Policies to avoid duplication.
65
65
  - The `### Details` section SHOULD state relevant boundaries or exceptions and what a reader should do or avoid in common cases. Use the frontmatter fields `apply-to` and `valid-from` as the first-pass filter for applicability, then keep nuanced boundaries in the decision text.
66
66
  - Use concise rules, examples, `Allowed` / `Disallowed` lists or checklists with required items to help the reader apply the decision correctly. Keep them short and decision-specific.
67
+ - Policies MUST NOT include historical change notes or descriptions of what changed from a previous version. State only the current rule that must be followed. Historical context is available via git history or versioned packages.
68
+ - When a policy covers elements that could be confused with each other, include explicit disambiguation statements clarifying the distinction before stating the rules for each.
69
+ - Rules MUST focus on what is required or forbidden. Explanations of why a rule exists belong in a Research document, not in the Policy itself. Link to the relevant research when the rationale is important for adoption.
67
70
  - When the decision defines strong policies or rules that should be stated explicitly as stable rule blocks, or when other documents, skills, or agents need to cite those rules individually by identifier, the Policy MUST follow the extension [_core-adr-policy-008 - Policy standards - structured](008-xdr-standards-structured.md) instead of using plain bullet lists for those rules.
68
71
  - Conflict handling applies to Policy documents:
69
72
  - For cross-scope overrides, document the decision conflict in the Policy `## Conflicts` section of the Policy that overrides another scope.
@@ -39,7 +39,7 @@ Do not use `scope-type: reference` for scopes that represent a live service, an
39
39
 
40
40
  #### 03-naming-convention
41
41
 
42
- A scope of type `reference` MUST have the word "reference" somewhere in its name. The position of the word is not enforced. Examples: `domain1-reference-mobile`, `security-reference-baseline`, `aws-reference-landing-zone`, `sales-reference-procedures`, `finance-reference-compliance`, `marketing-reference-standards`.
42
+ A scope of type `reference` MUST follow the naming pattern `{domain}-ref-{name}`, where `{domain}` identifies the owning domain or team and `{name}` identifies the specific reference area. Examples: `domain1-ref-mobile`, `security-ref-baseline`, `aws-ref-landing-zone`, `sales-ref-procedures`, `finance-ref-compliance`, `marketing-ref-standards`.
43
43
 
44
44
  #### 04-content-guidance
45
45
 
@@ -35,7 +35,7 @@ Do not use `scope-type: platform` for blueprints or reference architectures. Use
35
35
 
36
36
  #### 03-naming-convention
37
37
 
38
- A scope of type `platform` MUST have the word "platform" somewhere in its name. The position of the word is not enforced. Examples: `domain2-platform-aws`, `domain2-platform-callcenter`, `cloud-platform`.
38
+ A scope of type `platform` MUST follow the naming pattern `{domain}-plat-{name}`, where `{domain}` identifies the owning domain or team and `{name}` identifies the specific platform area. Examples: `domain2-plat-aws`, `domain2-plat-callcenter`, `cloud-plat-infra`.
39
39
 
40
40
  #### 04-content-guidance
41
41
 
package/AGENTS.md CHANGED
@@ -25,10 +25,7 @@ This rule has NO exceptions. Simple questions ("which command?", "what pattern?"
25
25
  - Analyse your work against the Policies and ensure implementation decisions follow guidelines and patterns
26
26
  - Fix any issues
27
27
 
28
- 4. **Document decisions as Policies when appropriate**
29
- - Check if what is being performed shouldn't be documented as a Policy in _local scope (because the decision has potential to be reused in the future or the topic is complex and would benefit from a document for clarity). Create or update existing documents accordingly.
30
-
31
- 5. **Do not perform git operations unless explicitelly asked**
28
+ 4. **Do not perform risky git operations unless explicitelly asked**
32
29
  - The developer should be in control of possible destructive operations on the workspace
33
30
 
34
31
  **This AGENTS.md file was created with xdrs-core and shouldn't be changed**
package/lib/lint.js CHANGED
@@ -286,11 +286,11 @@ function lintScopeIndexFrontmatter(scopeIndexPath, scopeName, errors, xdrsRoot,
286
286
  if (scopeType === '_local' && scopeName !== '_local') {
287
287
  errors.push(`Scope type "_local" is reserved for the "_local" scope: ${toDisplayPath(scopeIndexPath)}`);
288
288
  }
289
- if (scopeType === 'reference' && !scopeName.includes('reference')) {
290
- errors.push(`Scope with type "reference" must have "reference" in its name: ${toDisplayPath(scopeIndexPath)}`);
289
+ if (scopeType === 'reference' && !scopeName.includes('-ref-')) {
290
+ errors.push(`Scope with type "reference" must follow the naming pattern {domain}-ref-{name} (e.g. "security-ref-baseline"): ${toDisplayPath(scopeIndexPath)}`);
291
291
  }
292
- if (scopeType === 'platform' && !scopeName.includes('platform')) {
293
- errors.push(`Scope with type "platform" must have "platform" in its name: ${toDisplayPath(scopeIndexPath)}`);
292
+ if (scopeType === 'platform' && !scopeName.includes('-plat-')) {
293
+ errors.push(`Scope with type "platform" must follow the naming pattern {domain}-plat-{name} (e.g. "cloud-plat-aws"): ${toDisplayPath(scopeIndexPath)}`);
294
294
  }
295
295
 
296
296
  if (!fm.name) {
package/lib/lint.test.js CHANGED
@@ -716,18 +716,18 @@ test('accepts all valid scope-type values', () => {
716
716
  expect(result.errors.join('\n')).not.toContain('Scope index must start with');
717
717
  });
718
718
 
719
- test('accepts scope-type reference when scope name contains reference', () => {
719
+ test('accepts scope-type reference when scope name follows {domain}-ref-{name} pattern', () => {
720
720
  const workspaceRoot = createWorkspace('valid-reference-type', {
721
- '.xdrs/index.md': rootIndex(['[security-reference-baseline](security-reference-baseline/index.md)']),
722
- '.xdrs/security-reference-baseline/index.md': '---\nscope-type: reference\nname: security-reference-baseline\ndescription: Security reference architecture baseline for all teams.\napply-to: All teams following security reference patterns\nvalid-from: 2026-01-01\n---\n\n# security-reference-baseline Scope Overview\n\nSecurity reference.\n\n[ADRs](adrs/index.md)\n',
723
- '.xdrs/security-reference-baseline/adrs/index.md': [
724
- '# security-reference-baseline ADR Index', '', 'Security reference ADRs.', '', '## principles', '',
721
+ '.xdrs/index.md': rootIndex(['[security-ref-baseline](security-ref-baseline/index.md)']),
722
+ '.xdrs/security-ref-baseline/index.md': '---\nscope-type: reference\nname: security-ref-baseline\ndescription: Security reference architecture baseline for all teams.\napply-to: All teams following security reference patterns\nvalid-from: 2026-01-01\n---\n\n# security-ref-baseline Scope Overview\n\nSecurity reference.\n\n[ADRs](adrs/index.md)\n',
723
+ '.xdrs/security-ref-baseline/adrs/index.md': [
724
+ '# security-ref-baseline ADR Index', '', 'Security reference ADRs.', '', '## principles', '',
725
725
  '- [001-baseline](principles/001-baseline.md) - Security baseline', ''
726
726
  ].join('\n'),
727
- '.xdrs/security-reference-baseline/adrs/principles/001-baseline.md': [
728
- '---', 'name: security-reference-baseline-adr-policy-001-baseline',
727
+ '.xdrs/security-ref-baseline/adrs/principles/001-baseline.md': [
728
+ '---', 'name: security-ref-baseline-adr-policy-001-baseline',
729
729
  'description: Security baseline policy', 'apply-to: All scopes', 'valid-from: 2026-01-01', '---', '',
730
- '# security-reference-baseline-adr-policy-001: Security baseline', '',
730
+ '# security-ref-baseline-adr-policy-001: Security baseline', '',
731
731
  '## Context and Problem Statement', '', 'Baseline context.', '',
732
732
  '## Decision Outcome', '', 'Baseline outcome.', ''
733
733
  ].join('\n'),
@@ -758,21 +758,21 @@ test('reports scope-type reference when scope name does not contain reference',
758
758
 
759
759
  const result = lintWorkspace(workspaceRoot, { ignoreExternal: false });
760
760
 
761
- expect(result.errors.join('\n')).toContain('Scope with type "reference" must have "reference" in its name');
761
+ expect(result.errors.join('\n')).toContain('Scope with type "reference" must follow the naming pattern {domain}-ref-{name}');
762
762
  });
763
763
 
764
- test('accepts scope-type platform when scope name contains platform', () => {
764
+ test('accepts scope-type platform when scope name follows {domain}-plat-{name} pattern', () => {
765
765
  const workspaceRoot = createWorkspace('valid-platform-type', {
766
- '.xdrs/index.md': rootIndex(['[cloud-platform](cloud-platform/index.md)']),
767
- '.xdrs/cloud-platform/index.md': '---\nscope-type: platform\nname: cloud-platform\ndescription: Cloud platform infrastructure decisions for all teams.\napply-to: All teams using the cloud platform\nvalid-from: 2026-01-01\n---\n\n# cloud-platform Scope Overview\n\nCloud platform.\n\n[ADRs](adrs/index.md)\n',
768
- '.xdrs/cloud-platform/adrs/index.md': [
769
- '# cloud-platform ADR Index', '', 'Cloud platform ADRs.', '', '## principles', '',
766
+ '.xdrs/index.md': rootIndex(['[cloud-plat-infra](cloud-plat-infra/index.md)']),
767
+ '.xdrs/cloud-plat-infra/index.md': '---\nscope-type: platform\nname: cloud-plat-infra\ndescription: Cloud platform infrastructure decisions for all teams.\napply-to: All teams using the cloud platform\nvalid-from: 2026-01-01\n---\n\n# cloud-plat-infra Scope Overview\n\nCloud platform.\n\n[ADRs](adrs/index.md)\n',
768
+ '.xdrs/cloud-plat-infra/adrs/index.md': [
769
+ '# cloud-plat-infra ADR Index', '', 'Cloud platform ADRs.', '', '## principles', '',
770
770
  '- [001-baseline](principles/001-baseline.md) - Cloud baseline', ''
771
771
  ].join('\n'),
772
- '.xdrs/cloud-platform/adrs/principles/001-baseline.md': [
773
- '---', 'name: cloud-platform-adr-policy-001-baseline',
772
+ '.xdrs/cloud-plat-infra/adrs/principles/001-baseline.md': [
773
+ '---', 'name: cloud-plat-infra-adr-policy-001-baseline',
774
774
  'description: Cloud platform baseline', 'apply-to: All scopes', 'valid-from: 2026-01-01', '---', '',
775
- '# cloud-platform-adr-policy-001: Cloud baseline', '',
775
+ '# cloud-plat-infra-adr-policy-001: Cloud baseline', '',
776
776
  '## Context and Problem Statement', '', 'Platform context.', '',
777
777
  '## Decision Outcome', '', 'Platform outcome.', ''
778
778
  ].join('\n'),
@@ -804,7 +804,7 @@ test('reports scope-type platform when scope name does not contain platform', ()
804
804
 
805
805
  const result = lintWorkspace(workspaceRoot, { ignoreExternal: false });
806
806
 
807
- expect(result.errors.join('\n')).toContain('Scope with type "platform" must have "platform" in its name');
807
+ expect(result.errors.join('\n')).toContain('Scope with type "platform" must follow the naming pattern {domain}-plat-{name}');
808
808
  });
809
809
 
810
810
  test('reports scope-type core when scope name does not contain core', () => {
@@ -888,19 +888,19 @@ test('accepts custom scope-type when policy exists in core-type scope', () => {
888
888
  test('accepts custom scope-type when policy exists in a non-core scope', () => {
889
889
  // domain-scope-type.md is in a platform-type scope (not a core scope), but lint should still find it
890
890
  const workspaceRoot = createWorkspace('custom-scope-type-in-non-core-scope', {
891
- '.xdrs/index.md': rootIndex(['[nnb-mt-domain](nnb-mt-domain/index.md)', '[my-platform](my-platform/index.md)']),
891
+ '.xdrs/index.md': rootIndex(['[nnb-mt-domain](nnb-mt-domain/index.md)', '[my-plat-custom](my-plat-custom/index.md)']),
892
892
  '.xdrs/nnb-mt-domain/index.md': '---\nscope-type: domain\nname: nnb-mt-domain\ndescription: Domain scope.\napply-to: All\nvalid-from: 2026-01-01\n---\n\n# nnb-mt-domain Scope Overview\n\nDomain scope.\n\n[ADRs](adrs/index.md)\n',
893
893
  '.xdrs/nnb-mt-domain/adrs/index.md': teamAdrIndex([]),
894
894
  // scope-type 'domain' defined in a non-core platform scope (not _core)
895
- '.xdrs/my-platform/index.md': '---\nscope-type: platform\nname: my-platform\ndescription: Platform scope.\napply-to: All\nvalid-from: 2026-01-01\n---\n\n# my-platform Scope Overview\n\nPlatform scope.\n\n[ADRs](adrs/index.md)\n',
896
- '.xdrs/my-platform/adrs/index.md': [
897
- '# my-platform ADR Index', '', 'Platform ADRs.', '', '## principles', '',
895
+ '.xdrs/my-plat-custom/index.md': '---\nscope-type: platform\nname: my-plat-custom\ndescription: Platform scope.\napply-to: All\nvalid-from: 2026-01-01\n---\n\n# my-plat-custom Scope Overview\n\nPlatform scope.\n\n[ADRs](adrs/index.md)\n',
896
+ '.xdrs/my-plat-custom/adrs/index.md': [
897
+ '# my-plat-custom ADR Index', '', 'Platform ADRs.', '', '## principles', '',
898
898
  '- [001-domain-scope-type](principles/001-domain-scope-type.md) - domain type', ''
899
899
  ].join('\n'),
900
- '.xdrs/my-platform/adrs/principles/001-domain-scope-type.md': [
901
- '---', 'name: my-platform-adr-policy-001-domain-scope-type',
900
+ '.xdrs/my-plat-custom/adrs/principles/001-domain-scope-type.md': [
901
+ '---', 'name: my-plat-custom-adr-policy-001-domain-scope-type',
902
902
  'description: Defines the domain scope type.', 'apply-to: All', 'valid-from: 2026-01-01', '---', '',
903
- '# my-platform-adr-policy-001: domain scope type', '', '## Context and Problem Statement', '',
903
+ '# my-plat-custom-adr-policy-001: domain scope type', '', '## Context and Problem Statement', '',
904
904
  'Defines the domain scope type.', '', '## Decision Outcome', '', 'Use scope-type: domain.', ''
905
905
  ].join('\n'),
906
906
  // _core only defines 'core' and 'platform' — no 'domain' here
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.35.1",
3
+ "version": "0.36.1",
4
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",