xdrs-core 0.38.3 → 0.38.4

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.
@@ -144,8 +144,8 @@ Policies can be of different kinds, depending on the nature of the decision:
144
144
  - Canonical index requirements:
145
145
  - Organize XDRS documents by subject for easier navigation
146
146
  - Add a short description of what this scope is about (responsibilities, general worries, teams involved, link to discussion process, etc)
147
- - Add a list of other scope indexes that this scope might be related to (only add scopes that might be overridden). E.g: "business-x-mobileapp" scope could refer to "business-x" and "sensitive-data" scopes in its index list. XDRS in scopes listed last override XDRS in scopes listed first when addressing the same topic.
148
- - Each XDRS element entry in the index MUST include a short description of its content. The description SHOULD use an imperative statement or the question it answers when possible (<15 words). Example: "Use this while planning a new feature", "What communication tone we use with our customers?", "PNPM vs Yarn comparison study"
147
+ - Add links to related scope indexes that this scope might override or be overridden by (scopes listed last override earlier ones on the same topic).
148
+ - Each XDRS element entry MUST include a short description. SHOULD use an imperative statement or the question it answers (<15 words). Example: "Use this while planning a new feature", "What communication tone we use with our customers?"
149
149
  - Outside the scopes, keep a root index in `[xdrs-root]/index.md` that links to each scope index (`[xdrs-root]/[scope]/index.md`). Add the text "XDRS scopes listed last override the ones listed first". The root index MUST NOT link directly to type indexes; readers navigate from the scope index to the type indexes. Use the link text pattern `View scope [scope_name]` for each scope link (e.g. `[View scope myteam] linking to (myteam/index.md)`).
150
150
  - MUST verify if indexes are up to date after making changes
151
151
  - **Scope index**
@@ -28,7 +28,7 @@ Policy documents are the authoritative source of truth for their scope, type, an
28
28
  | `name` | Yes | 1-64 characters. Lowercase letters, numbers, hyphens, and leading underscores only. MUST NOT end with a hyphen. MUST NOT contain consecutive hyphens. MUST match the document identifier from the heading: `[scope]-[type]-policy-[number]-[short-title]`. |
29
29
  | `description` | Yes | 1-1024 characters. Describes what this decision is about and when to use it. SHOULD include keywords that help agents identify when to apply it. |
30
30
  | `apply-to` | Yes | Short description of contexts this decision is applicable to. Keep it under 40 words. Use `All scopes` when the decision applies broadly. Examples: `Only frontend code`, `JavaScript projects`, `All scopes`. |
31
- | `valid-from` | Yes | ISO date (`YYYY-MM-DD`) indicating from when this decision MUST be enforced. Before this date it SHOULD be used everywhere possible, but compliance is not enforced during reviews until after this date. Defaults to the date the Policy was created. When updating an existing Policy whose `valid-from` date has already passed, preserve the original date—do not update it to the current date. The historical date shows when the policy was originally enabled and is important for understanding policy evolution. |
31
+ | `valid-from` | Yes | ISO date (`YYYY-MM-DD`) indicating from when this decision MUST be enforced. Before this date it SHOULD be used everywhere possible, but compliance is not enforced during reviews until after this date. Defaults to the date the Policy was created. When updating an existing Policy whose `valid-from` date has already passed, preserve the original date—it MUST NOT be updated to the current date. The historical date shows when the policy was originally enabled and is important for understanding policy evolution. |
32
32
  | `license` | No | SPDX license expression (e.g. `MIT`, `Apache-2.0`, `CC-BY-4.0`). Indicates the license under which the document content is shared. If omitted, the license is governed by the repository or package defaults. |
33
33
  | `metadata` | No | Arbitrary key-value map for additional properties not defined by this spec. |
34
34
 
@@ -62,6 +62,8 @@ Policy documents are the authoritative source of truth for their scope, type, an
62
62
  - Types in IDs: `adr-policy`, `bdr-policy`, `edr-policy`
63
63
  - Define the next number of a Policy by checking what is the highest number present in the type+scope. Don't fill numbering gaps, as they might be old deleted Policies and we MUST NOT reuse numbers of different documents/decisions. Numbering gaps are expected.
64
64
  - Policies MUST be concise and reference other Policies to avoid duplication.
65
+ - Policies MUST NOT contain duplicated content: the same rule or information MUST NOT appear more than once in the document, whether stated identically or rephrased. Consolidate into a single authoritative statement and reference it where needed.
66
+ - Policies MUST NOT contain conflicting content: all rules and statements within the same document MUST be consistent with each other.
65
67
  - 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
68
  - 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
69
  - 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.
@@ -69,6 +71,7 @@ Policy documents are the authoritative source of truth for their scope, type, an
69
71
  - 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.
70
72
  - A "why" explanation for a policy rule MAY only be included if it is brief, non-obvious, relevant to the reader, and not longer than the rule itself.
71
73
  - 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.
74
+ - Each policy rule and rule block MUST be unambiguous: it MUST be possible to clearly follow, check, and discuss it without requiring additional interpretation.
72
75
  - 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 structured standards](008-policy-structured-standards.md) instead of using plain bullet lists for those rules.
73
76
  - Conflict handling applies to Policy documents:
74
77
  - For cross-scope overrides, document the decision conflict in the Policy `## Conflicts` section of the Policy that overrides another scope.
@@ -35,7 +35,7 @@ Use `scope-type: reference` when the scope contains:
35
35
  - Business area procedure standards: how sales processes SHOULD be conducted, how customer data MUST be handled, how marketing communications MUST comply with applicable regulations.
36
36
  - Operational compliance guidelines: finance controls, accounting procedures, public communication standards, customer data management rules.
37
37
 
38
- Do not use `scope-type: reference` for scopes that represent a live service, an active team, or a production system. Use `scope-type: platform` for those.
38
+ `scope-type: reference` MUST NOT be used for scopes that represent a live service, an active team, or a production system. Use `scope-type: platform` for those.
39
39
 
40
40
  #### 03-naming-convention
41
41
 
package/lib/lint.js CHANGED
@@ -1654,7 +1654,7 @@ function lintStructuredRuleBlocks(content, filePath, errors) {
1654
1654
  const ruleBodyNonCodeLines = lines.slice(bodyStart, bodyEnd).filter((_, idx) => !ignoredLines[bodyStart + idx]);
1655
1655
  const ruleBodyTextForEmphasis = ruleBodyNonCodeLines.join('\n');
1656
1656
 
1657
- if (!NORMATIVE_KEYWORDS_RE.test(ruleBodyText)) {
1657
+ if (!NORMATIVE_KEYWORDS_RE.test(ruleBodyTextForEmphasis)) {
1658
1658
  errors.push(`Policy structured rule body must contain normative language (MUST/SHOULD/MAY) in "${number}-${title}": ${toDisplayPath(filePath)} [_core-adr-policy-008.03-rule-body-must-use-normative-language]`);
1659
1659
  }
1660
1660
 
package/lib/lint.test.js CHANGED
@@ -2709,6 +2709,33 @@ test('reports structured rule block body missing normative language', () => {
2709
2709
  expect(result.errors.join('\n')).toContain('[_core-adr-policy-008.03-rule-body-must-use-normative-language]');
2710
2710
  });
2711
2711
 
2712
+ test('reports structured rule block body with normative language only inside a code block', () => {
2713
+ const workspaceRoot = createWorkspace('structured-rule-normative-in-code-block', {
2714
+ '.xdrs/index.md': rootIndex(),
2715
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
2716
+ '- [001-main](principles/001-main.md) - Main decision'
2717
+ ]),
2718
+ '.xdrs/_local/adrs/principles/001-main.md': xdrDocument([
2719
+ '### Details',
2720
+ '',
2721
+ '#### 01-my-rule',
2722
+ '',
2723
+ 'Here is an example:',
2724
+ '',
2725
+ '```',
2726
+ 'You MUST do this.',
2727
+ '```',
2728
+ '',
2729
+ 'No normative language in prose.',
2730
+ ].join('\n')),
2731
+ });
2732
+
2733
+ const result = lintWorkspace(workspaceRoot);
2734
+
2735
+ expect(result.errors.join('\n')).toContain('structured rule body must contain normative language');
2736
+ expect(result.errors.join('\n')).toContain('[_core-adr-policy-008.03-rule-body-must-use-normative-language]');
2737
+ });
2738
+
2712
2739
  test('accepts valid structured rule blocks', () => {
2713
2740
  const workspaceRoot = createWorkspace('structured-rule-valid', {
2714
2741
  '.xdrs/index.md': rootIndex(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.38.3",
3
+ "version": "0.38.4",
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",