xdrs-core 0.45.0 → 0.46.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 +1 -0
- package/.xdrs/_core/adrs/principles/001-xdrs-standards.md +3 -2
- package/.xdrs/_core/adrs/principles/002-policy-standards.md +1 -1
- package/.xdrs/_core/adrs/principles/003-skill-standards.md +1 -2
- package/.xdrs/_core/adrs/principles/004-article-standards.md +1 -2
- package/.xdrs/_core/adrs/principles/006-research-standards.md +6 -5
- package/.xdrs/_core/adrs/principles/007-plan-standards.md +1 -1
- package/.xdrs/_core/adrs/principles/009-presentation-standards.md +2 -1
- package/.xdrs/_core/adrs/principles/020-media-and-asset-standards.md +48 -0
- package/.xdrs/_core/adrs/principles/articles/.assets/001-xdrs-overview.svg +258 -0
- package/.xdrs/_core/adrs/principles/articles/001-xdrs-overview.md +2 -0
- package/.xdrs/_core/adrs/principles/skills/002-write-policy/SKILL.md +1 -1
- package/.xdrs/_core/adrs/principles/skills/003-write-skill/SKILL.md +1 -1
- package/.xdrs/_core/adrs/principles/skills/004-write-article/SKILL.md +1 -1
- package/.xdrs/_core/adrs/principles/skills/005-write-research/SKILL.md +1 -1
- package/.xdrs/_core/adrs/principles/skills/006-write-plan/SKILL.md +1 -1
- package/.xdrs/_core/adrs/principles/skills/007-write-presentation/SKILL.md +2 -2
- package/lib/lint.js +59 -9
- package/lib/lint.test.js +503 -0
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ Foundational standards, principles, and guidelines.
|
|
|
25
25
|
- [_core-adr-policy-017](principles/017-policy-numbering-ranges.md) - **Policy numbering ranges** — Subject-based 100-number block ranges for policy numbering and the freeze-reference exemption
|
|
26
26
|
- [_core-adr-policy-018](principles/018-external-path-symlinks.md) - **External path symlinks** — How to make XDRS files accessible from paths outside the .xdrs/ root using symlinks
|
|
27
27
|
- [_core-adr-policy-019](principles/019-compiled-scope-type.md) - **compiled scope type** — Defines the `compiled` scope type: scopes whose policies are compiled from external authoritative sources with strict source traceability and no invented content
|
|
28
|
+
- [_core-adr-policy-020](principles/020-media-and-asset-standards.md) - **Media and asset standards** — Canonical diagram format preference order and non-Markdown asset rules for all XDRS document types
|
|
28
29
|
|
|
29
30
|
## Skills
|
|
30
31
|
|
|
@@ -62,11 +62,11 @@ ADR and EDR share the same six technical subject names (see [`_core-adr-policy-0
|
|
|
62
62
|
- `_core-adr-policy-004` defines article standards
|
|
63
63
|
- `_core-adr-policy-006` defines research standards
|
|
64
64
|
- `_core-adr-policy-007` defines plan standards
|
|
65
|
-
- For
|
|
66
|
-
- Any non-Markdown supporting files referenced by a document (schemas, JSON examples, images, diagrams, binaries, or any other data files) SHOULD be used only when they are materially necessary to preserve clarity, fidelity, or evidence. When used, they MUST live in a sibling `.assets/` folder next to the document.
|
|
65
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md). **Per-document-type `.assets/` paths:**
|
|
67
66
|
- Policies in the subject root use `[xdrs-root]/[scope]/[type]/[subject]/.assets/`
|
|
68
67
|
- Articles use `[xdrs-root]/[scope]/[type]/[subject]/articles/.assets/`
|
|
69
68
|
- Research uses `[xdrs-root]/[scope]/[type]/[subject]/researches/.assets/`
|
|
69
|
+
- Plans use `[xdrs-root]/[scope]/[type]/[subject]/plans/.assets/`
|
|
70
70
|
- Skills use `[xdrs-root]/[scope]/[type]/[subject]/skills/[number]-[skill-name]/.assets/`
|
|
71
71
|
- **Scopes:**
|
|
72
72
|
- Short name that defines a group or a package of XDRS
|
|
@@ -152,3 +152,4 @@ subject/
|
|
|
152
152
|
- [_core-adr-policy-004 - Article standards](004-article-standards.md)
|
|
153
153
|
- [_core-adr-policy-006 - Research standards](006-research-standards.md)
|
|
154
154
|
- [_core-adr-policy-007 - Plan standards](007-plan-standards.md)
|
|
155
|
+
- [_core-adr-policy-020 - Media and asset standards](020-media-and-asset-standards.md) - Diagram format preferences and non-Markdown asset rules
|
|
@@ -81,7 +81,7 @@ Policy documents are the authoritative source of truth for their scope, type, an
|
|
|
81
81
|
- When research exists for a decision, the Policy SHOULD mention the related research documents after the `## Considered Options` list.
|
|
82
82
|
- MUST NOT use emojis in contents.
|
|
83
83
|
- File names MUST be lowercase.
|
|
84
|
-
-
|
|
84
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md).
|
|
85
85
|
- Avoid using lengthy instructions on the Policy. If there are long and detailed instructions related to the Policy, or instructions that are outside the decision, create another file with a guide. If the guide is small, keep it in the Policy itself.
|
|
86
86
|
- Policies SHOULD be under 1300 words long as a rule of thumb.
|
|
87
87
|
- This is important to make them focused on a clear decision
|
|
@@ -116,8 +116,7 @@ Rules:
|
|
|
116
116
|
- The directory name MUST follow the format `[number]-[skill-name]` (e.g., `001-code-review`), matching the `name:` field.
|
|
117
117
|
- `## Overview` SHOULD state the task objective, expected outcome, and relevant prerequisites or tools when they matter.
|
|
118
118
|
- `## Instructions` SHOULD include verification steps or acceptance criteria at the end of the task, or at the end of major phases when partial validation matters.
|
|
119
|
-
- For
|
|
120
|
-
- Any non-Markdown files referenced from `SKILL.md` SHOULD be used only when they are materially necessary and MUST live in `.assets/` inside the same skill package. See `_core-adr-policy-001` for the canonical `.assets/` path conventions.
|
|
119
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md).
|
|
121
120
|
- Keep `SKILL.md` under 6500 words. Move lengthy reference material to `references/`.
|
|
122
121
|
- Use relative paths for all links; MUST NOT use absolute paths starting with `/`.
|
|
123
122
|
- File names MUST be lowercase.
|
|
@@ -38,8 +38,7 @@ Articles are Markdown documents placed inside a subject folder alongside policie
|
|
|
38
38
|
- When an article tells readers which decisions to follow, it SHOULD check `valid-from:` first to determine the convergence date, `apply-to:` second to determine context fit, and the decision text itself last. All documents present in the collection are considered active; articles MUST NOT present out-of-window or out-of-scope Policies as current rules for the discussed context.
|
|
39
39
|
- Articles MUST remain consistent with the Policies, Research documents, and Skills they reference. When a referenced artifact changes, the article MUST be reviewed and updated.
|
|
40
40
|
- Place an article in the subject folder that best matches its topic using the required list of subjects per type defined in `_core-adr-policy-001`. If an article spans more than one subject, place it in `principles`.
|
|
41
|
-
- For
|
|
42
|
-
- Any non-Markdown files referenced by an article SHOULD be used only when they are materially necessary and MUST live in `articles/.assets/` next to the article files. See `_core-adr-policy-001` for the canonical `.assets/` path conventions.
|
|
41
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md). Articles SHOULD use diagrams to illustrate concepts, overviews, and relationships; draw.io SHOULD be used for conceptual and relationship diagrams (e.g., component maps, context views, architecture overviews) when Mermaid cannot adequately express them.
|
|
43
42
|
- File names MUST be lowercase.
|
|
44
43
|
- MUST NOT use emojis in article content.
|
|
45
44
|
|
|
@@ -37,9 +37,9 @@ Research documents are Markdown files placed inside a subject folder alongside p
|
|
|
37
37
|
- Research documents MUST describe the methods, tools, sources, and conditions with enough detail that an experienced professional could at least minimally reproduce the important parts of the study, especially the aspects that materially affected the conclusion.
|
|
38
38
|
- The short title portion after the research id MUST stay under 20 words.
|
|
39
39
|
- `## Abstract` MUST be a single paragraph under 200 words summarizing the goal, methods, results, and conclusion. It SHOULD let a quick technical reader understand the question, method, main result, and takeaway.
|
|
40
|
-
- `## Introduction` MUST define the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives. It SHOULD prefer plain Markdown, bullet points, tables
|
|
40
|
+
- `## Introduction` MUST define the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives. It SHOULD prefer plain Markdown, bullet points, and tables for simple explanations, and SHOULD use diagrams to illustrate concepts and relationships when they improve clarity over plain text (see [`_core-adr-policy-020`](020-media-and-asset-standards.md) for format preference; draw.io SHOULD be used for conceptual and relationship diagrams such as context maps, component relationships, and architecture overviews). It MUST stay under 700 words and MUST end with `Question: [central question]?`.
|
|
41
41
|
- `## Methods` MUST explain how the study was conducted, including design, tools, data sources, and test conditions, with a reproducibility goal. It MUST stay under 1200 words.
|
|
42
|
-
- `## Results` MUST present findings, data, trends, quantitative results, produced code, and option comparisons when relevant. It SHOULD prefer tables
|
|
42
|
+
- `## Results` MUST present findings, data, trends, quantitative results, produced code, and option comparisons when relevant. It SHOULD prefer tables and bullet lists for simple comparisons, and SHOULD use diagrams to illustrate concepts and relationships when they improve clarity over plain text (see [`_core-adr-policy-020`](020-media-and-asset-standards.md) for format preference; draw.io SHOULD be used for conceptual and relationship diagrams). Keep interpretation to a minimum. It MUST stay under 1800 words.
|
|
43
43
|
- When different options for the same problem are being analyzed, `## Results` SHOULD include comparison tables and explicit pros and cons for each option so the trade-offs are directly inspectable.
|
|
44
44
|
- `## Discussion` MUST interpret the results, explain significance, trade-offs, performance considerations, limitations, and implications for technical readers. It MUST stay under 1000 words.
|
|
45
45
|
- `## Conclusion` MUST summarize the main findings, practical takeaway, applicability boundaries, and important open questions. It MUST stay under 400 words.
|
|
@@ -50,7 +50,7 @@ Research documents are Markdown files placed inside a subject folder alongside p
|
|
|
50
50
|
- Research documents SHOULD link in `## References` to the Policies, skills, articles, discussions, and external references relevant to the subject or that later cite the work.
|
|
51
51
|
- A 1:1 relationship between one research document and one decision will likely be common in practice, but it is not REQUIRED.
|
|
52
52
|
- One research document MAY also be referenced by multiple Policies, including a mix of ADRs, BDRs, and EDRs, when the same investigation remains relevant across several decisions.
|
|
53
|
-
-
|
|
53
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md). Research documents SHOULD use diagrams to illustrate concepts and relationships; draw.io SHOULD be used for conceptual and relationship diagrams (e.g., context maps, component relationships, architecture overviews) when Mermaid cannot adequately express them.
|
|
54
54
|
- Research file names MUST be lowercase. MUST NOT use emojis.
|
|
55
55
|
- A research document MAY exist before the related Policy is written, or remain after the Policy changes, as long as its status and references stay clear.
|
|
56
56
|
|
|
@@ -91,7 +91,7 @@ All research documents MUST follow this template:
|
|
|
91
91
|
## Introduction
|
|
92
92
|
|
|
93
93
|
[Describe the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives.
|
|
94
|
-
Prefer bullets, tables,
|
|
94
|
+
Prefer markdown structures (bullets, tables, headings) first; for diagrams see _core-adr-policy-020. Goal: explain the investigated problem, operating context, constraints, and why the subject matters. Under 700 words.]
|
|
95
95
|
|
|
96
96
|
Question: [Central question of the research]?
|
|
97
97
|
|
|
@@ -103,7 +103,7 @@ Include enough detail for an experienced professional to reproduce the relevant
|
|
|
103
103
|
## Results
|
|
104
104
|
|
|
105
105
|
[Report findings, data, trends, quantitative results, code artifacts, and option comparisons.
|
|
106
|
-
Prefer tables
|
|
106
|
+
Prefer tables and bullet lists for simple comparisons; for diagrams see _core-adr-policy-020. If multiple options solve the same problem, add comparison tables and explicit pros and cons for each option. Focus on raw findings, not interpretation. Goal: present the raw findings with minimal interpretation. Under 1800 words.]
|
|
107
107
|
|
|
108
108
|
## Discussion
|
|
109
109
|
|
|
@@ -135,4 +135,5 @@ Prefer tables, bullets, or ASCII art for simple comparisons. Use external figure
|
|
|
135
135
|
- [_core-adr-policy-001 - XDRS standards](001-xdrs-standards.md)
|
|
136
136
|
- [_core-adr-policy-003 - Skill standards](003-skill-standards.md)
|
|
137
137
|
- [_core-adr-policy-004 - Article standards](004-article-standards.md)
|
|
138
|
+
- [_core-adr-policy-020 - Media and asset standards](020-media-and-asset-standards.md) - Diagram format preferences and non-Markdown asset rules
|
|
138
139
|
- [005-write-research skill](skills/005-write-research/SKILL.md) - Step-by-step instructions for creating a research document
|
|
@@ -33,7 +33,7 @@ Plans are Markdown documents placed inside a subject folder alongside policies.
|
|
|
33
33
|
- Plans MUST include an `Expected end date:` field in ISO format (YYYY-MM-DD) inside the `## Proposed Solution` section.
|
|
34
34
|
- File names MUST be lowercase.
|
|
35
35
|
- MUST NOT use emojis in plan content.
|
|
36
|
-
-
|
|
36
|
+
- For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md).
|
|
37
37
|
|
|
38
38
|
**Folder layout**
|
|
39
39
|
|
|
@@ -36,7 +36,7 @@ Presentations are Markdown files in Marp format, stored in the `.assets/` folder
|
|
|
36
36
|
- Slide file names MUST NOT exceed 64 characters (including the `.md` extension).
|
|
37
37
|
- Slide file names MUST be lowercase.
|
|
38
38
|
- When slides refer to content from multiple decisions, plans, or research documents, an article explaining the combined view MUST be written first. The slides then support that article, not the individual documents directly.
|
|
39
|
-
- Slides SHOULD contain minimal text.
|
|
39
|
+
- Slides SHOULD contain minimal text. For diagrams, prefer ASCII art for very simple cases, Mermaid for flows and relationships, and draw.io when Mermaid is insufficient (see [`_core-adr-policy-020`](020-media-and-asset-standards.md)); for other slide content, prefer short bullet points, key short statements, and tables. Use longer text only when the exact wording MUST be evaluated by the audience (policies, texts under discussion, controls).
|
|
40
40
|
- Slides SHOULD follow a clean, linear storytelling structure (context, problem, solution, actions). Follow the structure of the underlying document, extracting the most important points and stressing central questions, answers, doubts, decisions, and risks.
|
|
41
41
|
- Define the central message or objective of the presentation before creating the slides. If the objective is unclear or there are multiple possible paths, ask the user before proceeding.
|
|
42
42
|
- The target audience MUST be identified (executives, engineers, specialists, control). If the audience is not clear from the underlying document, ask before creating the slides. Include audience info in the file name when multiple audiences exist (e.g. `005-rail-standards-slides-executive.md`).
|
|
@@ -51,4 +51,5 @@ Presentations are Markdown files in Marp format, stored in the `.assets/` folder
|
|
|
51
51
|
- [_core-adr-policy-002 - Policy standards](002-policy-standards.md) - Policy document writing rules
|
|
52
52
|
- [_core-adr-policy-004 - Article standards](004-article-standards.md) - Article standards for multi-document views
|
|
53
53
|
- [007-write-presentation skill](skills/007-write-presentation/SKILL.md) - Skill for creating slide presentations
|
|
54
|
+
- [_core-adr-policy-020 - Media and asset standards](020-media-and-asset-standards.md) - Diagram format preferences and non-Markdown asset rules
|
|
54
55
|
- [Marp](https://marp.app/) - Markdown Presentation Ecosystem
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: _core-adr-policy-020-media-and-asset-standards
|
|
3
|
+
description: Defines the preferred order for representing visual information and the rules for non-Markdown assets across all XDRS document types. Use when choosing a diagram format or referencing any non-Markdown file in any XDRS document.
|
|
4
|
+
apply-to: All XDRS document types
|
|
5
|
+
valid-from: 2026-08-06
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# _core-adr-policy-020: Media and asset standards
|
|
9
|
+
|
|
10
|
+
## Context and Problem Statement
|
|
11
|
+
|
|
12
|
+
Rules for diagram format preference and non-Markdown asset handling are scattered across multiple policies (001, 002, 003, 004, 006, 007) and all write-\* skills. The same asset placement and diagram preference rules appear independently in each document-type policy, creating duplication that `_core-adr-policy-002` itself prohibits, and inconsistency when the rules diverge.
|
|
13
|
+
|
|
14
|
+
Question: What is the canonical preference order for representing visual information in XDRS documents, and where must non-Markdown files be stored?
|
|
15
|
+
|
|
16
|
+
## Decision Outcome
|
|
17
|
+
|
|
18
|
+
**Markdown-first preference order, with centralized asset placement rules**
|
|
19
|
+
|
|
20
|
+
All diagram format preferences and non-Markdown asset rules are defined here as individually citable rule blocks. Individual document-type policies and skills reference this policy instead of repeating these rules.
|
|
21
|
+
|
|
22
|
+
### Details
|
|
23
|
+
|
|
24
|
+
#### 01-prefer-markdown
|
|
25
|
+
Markdown structures MUST be the first choice for any layout, tabular data, list, heading hierarchy, or simple relationship that can be expressed adequately as plain text. Plain Markdown tables, bullet lists, headings, and code blocks MUST be used before reaching for any external visual format.
|
|
26
|
+
|
|
27
|
+
#### 02-ascii-for-simple
|
|
28
|
+
ASCII art MAY be used for very simple spatial layouts or shapes where plain Markdown structures cannot adequately convey the diagram. ASCII art SHOULD be limited to cases that are trivial to write and maintain as plain text; anything requiring visual complexity SHOULD use Mermaid instead.
|
|
29
|
+
|
|
30
|
+
#### 03-mermaid-for-complex
|
|
31
|
+
Mermaid.js SHOULD be used for diagrams that require explicit visual representation: flows, sequences, state machines, entity relationships, class diagrams, and activity diagrams. Mermaid is preferred over draw.io when it can adequately express the needed diagram.
|
|
32
|
+
|
|
33
|
+
#### 04-drawio-when-mermaid-insufficient
|
|
34
|
+
draw.io SHOULD be used when Mermaid cannot adequately express the needed diagram — for example, custom visual layouts, freehand annotations, or combined view types that Mermaid does not support natively.
|
|
35
|
+
|
|
36
|
+
#### 05-drawio-storage
|
|
37
|
+
draw.io diagrams MUST be saved as editable vector: File → Save As → Editable Vector. The resulting `.svg` file MUST be stored in the sibling `.assets/` folder. This embeds the draw.io source in the SVG so the diagram remains editable without a separate `.drawio` file.
|
|
38
|
+
|
|
39
|
+
#### 06-assets-materially-necessary
|
|
40
|
+
Non-Markdown files (images, diagrams, schemas, JSON examples, binaries, or any other data files) SHOULD be referenced only when they are materially necessary to preserve clarity, fidelity, or evidence. Assets that duplicate information already expressible in Markdown SHOULD NOT be added.
|
|
41
|
+
|
|
42
|
+
#### 07-assets-placement
|
|
43
|
+
Non-Markdown files MUST live in the sibling `.assets/` folder next to the referencing document. The canonical per-document-type `.assets/` paths are defined in `_core-adr-policy-001`.
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
- [_core-adr-policy-001 - XDRS standards](001-xdrs-standards.md) - Per-document-type `.assets/` canonical paths
|
|
48
|
+
- [_core-adr-policy-008 - Policy structured standards](008-policy-structured-standards.md) - Structured rule block format used in this policy
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!-- hand-coded SVG; to make editable in draw.io, import and re-export as Editable Vector -->
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
4
|
+
version="1.1" width="1650" height="980" viewBox="0 0 1650 980"
|
|
5
|
+
style="background-color:#ffffff;">
|
|
6
|
+
<defs>
|
|
7
|
+
<marker id="arr-p" viewBox="0 0 10 10" refX="9" refY="5"
|
|
8
|
+
markerWidth="6" markerHeight="6" orient="auto">
|
|
9
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#7c4dff"/>
|
|
10
|
+
</marker>
|
|
11
|
+
<marker id="arr-o" viewBox="0 0 10 10" refX="9" refY="5"
|
|
12
|
+
markerWidth="6" markerHeight="6" orient="auto">
|
|
13
|
+
<path d="M 0 0 L 10 5 L 0 10 z" fill="#e67e22"/>
|
|
14
|
+
</marker>
|
|
15
|
+
</defs>
|
|
16
|
+
|
|
17
|
+
<!-- ===== TITLE ===== -->
|
|
18
|
+
<text x="825" y="42" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
19
|
+
font-size="24" font-weight="bold" fill="#1a1a2e">XDRS — eXtensible Decision Record System</text>
|
|
20
|
+
<text x="825" y="66" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
21
|
+
font-size="13" fill="#555">A framework to structure, compile and distribute decision records so that AI agents and humans can reliably find and use them</text>
|
|
22
|
+
|
|
23
|
+
<!-- ===== SECTION A: DECISION TYPES ===== -->
|
|
24
|
+
<rect x="20" y="88" width="260" height="422" rx="8" fill="#f0f4ff" stroke="#4a6cf7" stroke-width="2"/>
|
|
25
|
+
<text x="150" y="112" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
26
|
+
font-size="14" font-weight="bold" fill="#4a6cf7">Decision Types</text>
|
|
27
|
+
|
|
28
|
+
<!-- ADR -->
|
|
29
|
+
<rect x="34" y="124" width="232" height="72" rx="6" fill="#dae8fc" stroke="#6c8ebf" stroke-width="1.5"/>
|
|
30
|
+
<text x="150" y="146" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">ADR</text>
|
|
31
|
+
<text x="150" y="163" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#333">Architectural Decision Records</text>
|
|
32
|
+
<text x="150" y="179" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#666">app · data · integration · platform · operations</text>
|
|
33
|
+
|
|
34
|
+
<!-- BDR -->
|
|
35
|
+
<rect x="34" y="208" width="232" height="72" rx="6" fill="#d5e8d4" stroke="#82b366" stroke-width="1.5"/>
|
|
36
|
+
<text x="150" y="230" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">BDR</text>
|
|
37
|
+
<text x="150" y="247" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#333">Business Decision Records</text>
|
|
38
|
+
<text x="150" y="263" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#666">product · marketing · finance · organization</text>
|
|
39
|
+
|
|
40
|
+
<!-- EDR -->
|
|
41
|
+
<rect x="34" y="292" width="232" height="72" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1.5"/>
|
|
42
|
+
<text x="150" y="314" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">EDR</text>
|
|
43
|
+
<text x="150" y="331" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#333">Engineering Decision Records</text>
|
|
44
|
+
<text x="150" y="347" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#666">infra · devops · observability · governance</text>
|
|
45
|
+
|
|
46
|
+
<!-- Policy ID note inside A -->
|
|
47
|
+
<rect x="34" y="382" width="232" height="114" rx="6" fill="#fafafa" stroke="#aaa" stroke-width="1" stroke-dasharray="4,3"/>
|
|
48
|
+
<text x="150" y="401" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="11" font-weight="bold" fill="#555">Policy ID Format</text>
|
|
49
|
+
<text x="44" y="420" font-family="Courier New,monospace" font-size="11" fill="#333">[scope]-[type]-policy-[number]</text>
|
|
50
|
+
<text x="44" y="440" font-family="Courier New,monospace" font-size="10" fill="#666">checkout-adr-policy-001</text>
|
|
51
|
+
<text x="44" y="456" font-family="Courier New,monospace" font-size="10" fill="#666">myorg-edr-policy-042</text>
|
|
52
|
+
<text x="44" y="472" font-family="Courier New,monospace" font-size="10" fill="#666">_core-adr-policy-016</text>
|
|
53
|
+
<text x="44" y="488" font-family="Courier New,monospace" font-size="10" fill="#666"> (sequential, never reused)</text>
|
|
54
|
+
|
|
55
|
+
<!-- Arrow A → B -->
|
|
56
|
+
<line x1="281" y1="299" x2="317" y2="299" stroke="#7c4dff" stroke-width="2" marker-end="url(#arr-p)"/>
|
|
57
|
+
<text x="299" y="291" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#7c4dff">decompose</text>
|
|
58
|
+
<text x="299" y="313" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#7c4dff">into</text>
|
|
59
|
+
|
|
60
|
+
<!-- ===== SECTION B: XDRS ELEMENTS ===== -->
|
|
61
|
+
<rect x="320" y="88" width="440" height="422" rx="8" fill="#f9f0ff" stroke="#7c4dff" stroke-width="2"/>
|
|
62
|
+
<text x="540" y="112" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
63
|
+
font-size="14" font-weight="bold" fill="#7c4dff">XDRS Document Elements</text>
|
|
64
|
+
<text x="540" y="129" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
65
|
+
font-size="11" fill="#888">Each decision record decomposes into specialized document types</text>
|
|
66
|
+
|
|
67
|
+
<!-- Policy element -->
|
|
68
|
+
<rect x="334" y="141" width="412" height="64" rx="6" fill="#e1d5f7" stroke="#7c4dff" stroke-width="1.5"/>
|
|
69
|
+
<text x="354" y="161" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">Policy — What must be followed</text>
|
|
70
|
+
<text x="354" y="178" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Rules, guardrails, core decisions. The source of truth.</text>
|
|
71
|
+
<text x="354" y="195" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Captured as ADR / BDR / EDR policy documents.</text>
|
|
72
|
+
|
|
73
|
+
<!-- Research element -->
|
|
74
|
+
<rect x="334" y="215" width="412" height="64" rx="6" fill="#dae8fc" stroke="#6c8ebf" stroke-width="1.5"/>
|
|
75
|
+
<text x="354" y="235" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">Research — Why the decision was made</text>
|
|
76
|
+
<text x="354" y="252" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Problem context, constraints, findings, option tradeoffs.</text>
|
|
77
|
+
<text x="354" y="269" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">One research may inform multiple downstream policies.</text>
|
|
78
|
+
|
|
79
|
+
<!-- Skills element -->
|
|
80
|
+
<rect x="334" y="289" width="412" height="64" rx="6" fill="#d5e8d4" stroke="#82b366" stroke-width="1.5"/>
|
|
81
|
+
<text x="354" y="309" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">Skills — How to implement</text>
|
|
82
|
+
<text x="354" y="326" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Step-by-step procedural guides for humans or AI agents.</text>
|
|
83
|
+
<text x="354" y="343" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Executable with verifiable outcomes.</text>
|
|
84
|
+
|
|
85
|
+
<!-- Articles element -->
|
|
86
|
+
<rect x="334" y="363" width="412" height="64" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1.5"/>
|
|
87
|
+
<text x="354" y="383" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">Articles — Overview / Views</text>
|
|
88
|
+
<text x="354" y="400" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Synthetic texts combining multiple policies and skills.</text>
|
|
89
|
+
<text x="354" y="417" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Never replace policies as source of truth.</text>
|
|
90
|
+
|
|
91
|
+
<!-- Plans element -->
|
|
92
|
+
<rect x="334" y="437" width="412" height="64" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1.5"/>
|
|
93
|
+
<text x="354" y="457" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">Plans — When / How to roll out</text>
|
|
94
|
+
<text x="354" y="474" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Ephemeral execution docs. Deleted after implementation.</text>
|
|
95
|
+
<text x="354" y="491" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Lasting outputs become Policies, Skills, or Articles.</text>
|
|
96
|
+
|
|
97
|
+
<!-- Arrow B → C -->
|
|
98
|
+
<line x1="761" y1="299" x2="797" y2="299" stroke="#e67e22" stroke-width="2" marker-end="url(#arr-o)"/>
|
|
99
|
+
<text x="779" y="291" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#e67e22">organized</text>
|
|
100
|
+
<text x="779" y="313" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#e67e22">in</text>
|
|
101
|
+
|
|
102
|
+
<!-- ===== SECTION C: SCOPE SYSTEM ===== -->
|
|
103
|
+
<rect x="800" y="88" width="830" height="422" rx="8" fill="#fff8f0" stroke="#e67e22" stroke-width="2"/>
|
|
104
|
+
<text x="1215" y="112" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
105
|
+
font-size="14" font-weight="bold" fill="#e67e22">Scope System — Hierarchical Namespaces</text>
|
|
106
|
+
<text x="1215" y="129" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
107
|
+
font-size="11" fill="#888">Scopes organize decision ownership. Scopes listed later in root index.md override earlier ones.</text>
|
|
108
|
+
|
|
109
|
+
<!-- Precedence arrow (right side) -->
|
|
110
|
+
<line x1="1598" y1="480" x2="1598" y2="148" stroke="#e67e22" stroke-width="2" stroke-dasharray="4,3" marker-end="url(#arr-o)"/>
|
|
111
|
+
<text x="1598" y="314" text-anchor="middle" transform="rotate(-90,1598,314)"
|
|
112
|
+
font-family="Arial,Helvetica,sans-serif" font-size="11" font-weight="bold" fill="#e67e22">Precedence: later overrides earlier</text>
|
|
113
|
+
|
|
114
|
+
<!-- core -->
|
|
115
|
+
<rect x="814" y="141" width="770" height="58" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1.5"/>
|
|
116
|
+
<text x="834" y="162" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">core (e.g. _core, myorg-core)</text>
|
|
117
|
+
<text x="834" y="179" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Meta-governance: authoring standards, scope-type definitions. No consumable policies.</text>
|
|
118
|
+
|
|
119
|
+
<!-- reference -->
|
|
120
|
+
<rect x="814" y="209" width="770" height="58" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1.5"/>
|
|
121
|
+
<text x="834" y="230" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">reference (e.g. security-ref-baseline)</text>
|
|
122
|
+
<text x="834" y="247" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Standards, regulations, reference models. Read-only adoptable material.</text>
|
|
123
|
+
|
|
124
|
+
<!-- platform -->
|
|
125
|
+
<rect x="814" y="277" width="770" height="58" rx="6" fill="#d5e8d4" stroke="#82b366" stroke-width="1.5"/>
|
|
126
|
+
<text x="834" y="298" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">platform (e.g. cloud-plat-infra)</text>
|
|
127
|
+
<text x="834" y="315" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Live services and infrastructure teams can consume. Documents operational capabilities.</text>
|
|
128
|
+
|
|
129
|
+
<!-- standard -->
|
|
130
|
+
<rect x="814" y="345" width="770" height="58" rx="6" fill="#dae8fc" stroke="#6c8ebf" stroke-width="1.5"/>
|
|
131
|
+
<text x="834" y="366" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">standard (e.g. checkout, mobile-app)</text>
|
|
132
|
+
<text x="834" y="383" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Business areas, products, teams. General-purpose scopes. Default type.</text>
|
|
133
|
+
|
|
134
|
+
<!-- _local -->
|
|
135
|
+
<rect x="814" y="413" width="770" height="58" rx="6" fill="#e1d5f7" stroke="#7c4dff" stroke-width="1.5"/>
|
|
136
|
+
<text x="834" y="434" font-family="Arial,Helvetica,sans-serif" font-size="13" font-weight="bold" fill="#1a1a2e">_local (reserved)</text>
|
|
137
|
+
<text x="834" y="451" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Workspace-local overrides. Never distributed. Highest precedence within workspace.</text>
|
|
138
|
+
|
|
139
|
+
<!-- ===== SECTION: FILE STRUCTURE ===== -->
|
|
140
|
+
<rect x="20" y="530" width="390" height="290" rx="8" fill="#f0fff4" stroke="#27ae60" stroke-width="2"/>
|
|
141
|
+
<text x="215" y="554" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
142
|
+
font-size="14" font-weight="bold" fill="#27ae60">Folder Structure</text>
|
|
143
|
+
<text x="38" y="578" font-family="Courier New,monospace" font-size="11" fill="#333">.xdrs/</text>
|
|
144
|
+
<text x="38" y="596" font-family="Courier New,monospace" font-size="11" fill="#333"> index.md ← root index (lists all scopes)</text>
|
|
145
|
+
<text x="38" y="614" font-family="Courier New,monospace" font-size="11" fill="#333"> [scope]/</text>
|
|
146
|
+
<text x="38" y="632" font-family="Courier New,monospace" font-size="11" fill="#333"> index.md ← scope overview + frontmatter</text>
|
|
147
|
+
<text x="38" y="650" font-family="Courier New,monospace" font-size="11" fill="#333"> [adrs|bdrs|edrs]/</text>
|
|
148
|
+
<text x="38" y="668" font-family="Courier New,monospace" font-size="11" fill="#333"> index.md ← type index</text>
|
|
149
|
+
<text x="38" y="686" font-family="Courier New,monospace" font-size="11" fill="#333"> [subject]/</text>
|
|
150
|
+
<text x="38" y="704" font-family="Courier New,monospace" font-size="11" fill="#333"> NNN-title.md ← Policy</text>
|
|
151
|
+
<text x="38" y="722" font-family="Courier New,monospace" font-size="11" fill="#333"> researches/ ← Research docs</text>
|
|
152
|
+
<text x="38" y="740" font-family="Courier New,monospace" font-size="11" fill="#333"> skills/ ← Skill packages</text>
|
|
153
|
+
<text x="38" y="758" font-family="Courier New,monospace" font-size="11" fill="#333"> articles/ ← Article docs</text>
|
|
154
|
+
<text x="38" y="776" font-family="Courier New,monospace" font-size="11" fill="#333"> plans/ ← Plan docs</text>
|
|
155
|
+
<text x="38" y="794" font-family="Courier New,monospace" font-size="11" fill="#333"> .assets/ ← Binary assets</text>
|
|
156
|
+
|
|
157
|
+
<!-- ===== SECTION: GOVERNANCE MECHANISMS ===== -->
|
|
158
|
+
<rect x="430" y="530" width="1200" height="290" rx="8" fill="#fffbf0" stroke="#f39c12" stroke-width="2"/>
|
|
159
|
+
<text x="1030" y="554" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
160
|
+
font-size="14" font-weight="bold" fill="#f39c12">Governance Mechanisms</text>
|
|
161
|
+
|
|
162
|
+
<!-- Gov 1 -->
|
|
163
|
+
<rect x="446" y="568" width="270" height="232" rx="6" fill="#fdebd0" stroke="#f39c12" stroke-width="1.5"/>
|
|
164
|
+
<text x="581" y="589" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">1. Scope-type standards</text>
|
|
165
|
+
<text x="461" y="609" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Policies in core-type scopes that</text>
|
|
166
|
+
<text x="461" y="625" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">define rules for ALL scopes of a</text>
|
|
167
|
+
<text x="461" y="641" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">given type.</text>
|
|
168
|
+
<text x="461" y="669" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">e.g. business-area-scope-type.md</text>
|
|
169
|
+
<text x="461" y="685" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">in ecomm-core applies to all</text>
|
|
170
|
+
<text x="461" y="701" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">business-area scopes</text>
|
|
171
|
+
|
|
172
|
+
<!-- Gov 2 -->
|
|
173
|
+
<rect x="732" y="568" width="270" height="232" rx="6" fill="#fdebd0" stroke="#f39c12" stroke-width="1.5"/>
|
|
174
|
+
<text x="867" y="589" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">2. follows: declaration</text>
|
|
175
|
+
<text x="747" y="609" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Scope explicitly declares which</text>
|
|
176
|
+
<text x="747" y="625" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">core-type scope standards apply.</text>
|
|
177
|
+
<text x="747" y="641" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Creates a mandatory governance</text>
|
|
178
|
+
<text x="747" y="657" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">relationship to that scope.</text>
|
|
179
|
+
<text x="747" y="685" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">e.g. checkout/index.md:</text>
|
|
180
|
+
<text x="747" y="701" font-family="Courier New,monospace" font-size="10" fill="#888">follows: ecomm-core</text>
|
|
181
|
+
|
|
182
|
+
<!-- Gov 3 -->
|
|
183
|
+
<rect x="1018" y="568" width="270" height="232" rx="6" fill="#fdebd0" stroke="#f39c12" stroke-width="1.5"/>
|
|
184
|
+
<text x="1153" y="589" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">3. Local meta-policies</text>
|
|
185
|
+
<text x="1033" y="609" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Files named NNN-core.md inside</text>
|
|
186
|
+
<text x="1033" y="625" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">a scope's principles/ directory.</text>
|
|
187
|
+
<text x="1033" y="641" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">Govern authoring within that</text>
|
|
188
|
+
<text x="1033" y="657" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">scope only.</text>
|
|
189
|
+
<text x="1033" y="685" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">Applied implicitly — no index</text>
|
|
190
|
+
<text x="1033" y="701" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">declaration needed.</text>
|
|
191
|
+
|
|
192
|
+
<!-- Gov 4 -->
|
|
193
|
+
<rect x="1304" y="568" width="310" height="232" rx="6" fill="#fdebd0" stroke="#f39c12" stroke-width="1.5"/>
|
|
194
|
+
<text x="1459" y="589" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">4. -core sibling scope</text>
|
|
195
|
+
<text x="1319" y="609" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">A separate scope directory of</text>
|
|
196
|
+
<text x="1319" y="625" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">scope-type: core for shared</text>
|
|
197
|
+
<text x="1319" y="641" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">meta-governance across a family</text>
|
|
198
|
+
<text x="1319" y="657" font-family="Arial,Helvetica,sans-serif" font-size="11" fill="#444">of governed scopes.</text>
|
|
199
|
+
<text x="1319" y="685" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">e.g. ecomm-core/ governs all</text>
|
|
200
|
+
<text x="1319" y="701" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">ecomm business-area scopes.</text>
|
|
201
|
+
<text x="1319" y="717" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#888">Distinct from local meta-policy.</text>
|
|
202
|
+
|
|
203
|
+
<!-- Precedence chain label -->
|
|
204
|
+
<text x="1030" y="742" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
205
|
+
font-size="11" font-weight="bold" fill="#f39c12">Precedence chain (lowest → highest):</text>
|
|
206
|
+
<text x="1030" y="760" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
207
|
+
font-size="11" fill="#555">1. Scope-type standards → 2. follows: standards → 3. Local meta-policies (all subordinate to _core structural rules)</text>
|
|
208
|
+
<text x="1030" y="778" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
209
|
+
font-size="11" fill="#555">When absent from workspace: companion scope is READ-ONLY. Governed scope declares follows: in its index.md.</text>
|
|
210
|
+
|
|
211
|
+
<!-- ===== DISTRIBUTION SECTION ===== -->
|
|
212
|
+
<rect x="20" y="840" width="1610" height="130" rx="8" fill="#f0f8ff" stroke="#2980b9" stroke-width="2"/>
|
|
213
|
+
<text x="825" y="864" text-anchor="middle" font-family="Arial,Helvetica,sans-serif"
|
|
214
|
+
font-size="14" font-weight="bold" fill="#2980b9">Distribution & Usage — Versioned Packages</text>
|
|
215
|
+
|
|
216
|
+
<!-- Package -->
|
|
217
|
+
<rect x="36" y="876" width="240" height="80" rx="6" fill="#dae8fc" stroke="#6c8ebf" stroke-width="1.5"/>
|
|
218
|
+
<text x="156" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">Package</text>
|
|
219
|
+
<text x="156" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">Scopes are versioned npm</text>
|
|
220
|
+
<text x="156" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">distributions. Consumers install</text>
|
|
221
|
+
<text x="156" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">and extract them into workspace.</text>
|
|
222
|
+
|
|
223
|
+
<!-- Scope Composition -->
|
|
224
|
+
<rect x="296" y="876" width="240" height="80" rx="6" fill="#d5e8d4" stroke="#82b366" stroke-width="1.5"/>
|
|
225
|
+
<text x="416" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">Scope Composition</text>
|
|
226
|
+
<text x="416" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">Multiple scopes compose together.</text>
|
|
227
|
+
<text x="416" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">External scopes tracked in</text>
|
|
228
|
+
<text x="416" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">.filedist.lock as read-only.</text>
|
|
229
|
+
|
|
230
|
+
<!-- Linting -->
|
|
231
|
+
<rect x="556" y="876" width="240" height="80" rx="6" fill="#fff2cc" stroke="#d6b656" stroke-width="1.5"/>
|
|
232
|
+
<text x="676" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">Linting / Validation</text>
|
|
233
|
+
<text x="676" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">xdrs-core CLI validates structure,</text>
|
|
234
|
+
<text x="676" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">frontmatter, naming, index links,</text>
|
|
235
|
+
<text x="676" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">and scope governance compliance.</text>
|
|
236
|
+
|
|
237
|
+
<!-- AI Agents -->
|
|
238
|
+
<rect x="816" y="876" width="240" height="80" rx="6" fill="#e1d5f7" stroke="#7c4dff" stroke-width="1.5"/>
|
|
239
|
+
<text x="936" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">AI Agent Context</text>
|
|
240
|
+
<text x="936" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">AGENTS.md + XDRS structure gives</text>
|
|
241
|
+
<text x="936" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">AI agents reliable, scoped access</text>
|
|
242
|
+
<text x="936" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">to all decisions and skills.</text>
|
|
243
|
+
|
|
244
|
+
<!-- RAG -->
|
|
245
|
+
<rect x="1076" y="876" width="240" height="80" rx="6" fill="#f8cecc" stroke="#b85450" stroke-width="1.5"/>
|
|
246
|
+
<text x="1196" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">RAG / Web Publishing</text>
|
|
247
|
+
<text x="1196" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">Compiled corpus feeds RAG apps,</text>
|
|
248
|
+
<text x="1196" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">documentation sites, or knowledge</text>
|
|
249
|
+
<text x="1196" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">base systems.</text>
|
|
250
|
+
|
|
251
|
+
<!-- Extension Packages -->
|
|
252
|
+
<rect x="1336" y="876" width="280" height="80" rx="6" fill="#fdebd0" stroke="#f39c12" stroke-width="1.5"/>
|
|
253
|
+
<text x="1476" y="896" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="12" font-weight="bold" fill="#1a1a2e">Extension Packages</text>
|
|
254
|
+
<text x="1476" y="912" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">Teams build their own XDRS packages</text>
|
|
255
|
+
<text x="1476" y="926" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">extending xdrs-core with custom</text>
|
|
256
|
+
<text x="1476" y="940" text-anchor="middle" font-family="Arial,Helvetica,sans-serif" font-size="10" fill="#444">scopes and governance rules.</text>
|
|
257
|
+
|
|
258
|
+
</svg>
|
|
@@ -8,6 +8,8 @@ the framework and links out to the authoritative Policy documents for full detai
|
|
|
8
8
|
|
|
9
9
|
## Content
|
|
10
10
|
|
|
11
|
+

|
|
12
|
+
|
|
11
13
|
### What the central elements are
|
|
12
14
|
|
|
13
15
|
The XDRS framework is built around a small set of artifact types that play different roles in the
|
|
@@ -142,7 +142,7 @@ Mandatory rules to apply while drafting:
|
|
|
142
142
|
- Keep the decision itself authoritative in the Policy. Supporting artifacts may elaborate, but they should not restate the full decision when a short reference is enough.
|
|
143
143
|
- Make clear when the decision applies and any important exception boundaries.
|
|
144
144
|
- Keep exploratory option analysis in a related Research document when it would distract from the final decision text.
|
|
145
|
-
-
|
|
145
|
+
- For diagrams and non-Markdown assets, follow `_core-adr-policy-020`: prefer plain Markdown tables/lists first, then ASCII art for very simple cases, then Mermaid.js (sequence, state, activity, entity diagrams) for complex ones, then draw.io when Mermaid is insufficient — save as Editable Vector (File → Save As → Editable Vector) and store as `.svg` in the sibling `.assets/` folder.
|
|
146
146
|
- If the Policy genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/.assets/` and link them using a same-folder relative path (e.g., `.assets/image.png`).
|
|
147
147
|
- Use relative paths for all links; never use absolute paths starting with `/`.
|
|
148
148
|
- No emojis. Lowercase filenames.
|
|
@@ -99,7 +99,7 @@ Rules:
|
|
|
99
99
|
- Do not duplicate content from referenced Policies — link instead.
|
|
100
100
|
- Do not present the skill itself as policy; mandatory behavior must come from referenced Policies or other policy artifacts.
|
|
101
101
|
- When the skill depends on Policies, make the activation logic and instructions consistent with the Policy metadata so the skill does not operationalize inactive or out-of-scope decisions.
|
|
102
|
-
-
|
|
102
|
+
- For diagrams and non-Markdown assets, follow `_core-adr-policy-020`: prefer plain Markdown tables/lists first, then ASCII art for very simple cases, then Mermaid.js (sequence, state, activity, entity diagrams) for complex ones, then draw.io when Mermaid is insufficient — save as Editable Vector (File → Save As → Editable Vector) and store as `.svg` in the sibling `.assets/` folder.
|
|
103
103
|
- If `SKILL.md` genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/skills/[number]-[skill-name]/.assets/` and link them using a same-folder relative path (e.g., `.assets/image.png`).
|
|
104
104
|
- Use relative paths for all links; never use absolute paths starting with `/`.
|
|
105
105
|
- No emojis. Lowercase filenames. Target under 6500 words.
|
|
@@ -98,7 +98,7 @@ Rules to apply while drafting:
|
|
|
98
98
|
- Every factual claim must link back to the authoritative Policy or Skill.
|
|
99
99
|
- If the article advises readers what to do, clearly separate active/applicable Policies from background, historical, or out-of-scope ones.
|
|
100
100
|
- Never reproduce decision text verbatim; summarize and link.
|
|
101
|
-
-
|
|
101
|
+
- For diagrams and non-Markdown assets, follow `_core-adr-policy-020`: prefer plain Markdown tables/lists first, then ASCII art for very simple cases, then Mermaid.js (sequence, state, activity, entity diagrams) for complex ones, then draw.io when Mermaid is insufficient — save as Editable Vector (File → Save As → Editable Vector) and store as `.svg` in the sibling `.assets/` folder.
|
|
102
102
|
- If the article genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/articles/.assets/` and link them using a same-folder relative path (e.g., `.assets/image.png`).
|
|
103
103
|
- Use relative paths for all links; never use absolute paths starting with `/`.
|
|
104
104
|
- Target under 1950 words for best reader engagement (SHOULD). If content grows beyond that, break it into separate chapter articles rather than expanding a single file. The hard limit is 8000 words.
|
|
@@ -139,7 +139,7 @@ Rules:
|
|
|
139
139
|
- Keep traceability to related Policies, skills, articles, discussions, and external sources primarily in `## References`.
|
|
140
140
|
- Use good-enough evidence. Experienced professional judgment is allowed, but the conclusions still need support that other colleagues can inspect and learn from.
|
|
141
141
|
- Ensure the methods and test conditions are reproducible enough for an experienced professional to rerun or evolve the critical parts later.
|
|
142
|
-
-
|
|
142
|
+
- For diagrams and non-Markdown assets, follow `_core-adr-policy-020`: prefer plain Markdown tables/lists and bullet points first, then ASCII art for very simple cases, then Mermaid.js (sequence, state, activity, entity diagrams) for complex ones, then draw.io when Mermaid is insufficient — save as Editable Vector (File → Save As → Editable Vector) and store as `.svg` in the sibling `.assets/` folder.
|
|
143
143
|
- If the research genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/researches/.assets/` and link them using a same-folder relative path (e.g., `.assets/image.png`).
|
|
144
144
|
- Use relative paths for all links; never use absolute paths starting with `/`.
|
|
145
145
|
- Keep section word limits within the standard and keep the document under 5000 words total unless the introduction explicitly states that a very detailed analysis is required.
|
|
@@ -118,7 +118,7 @@ Rules to apply while drafting:
|
|
|
118
118
|
- The Expected end date must be in ISO format (YYYY-MM-DD), placed inside the `## Proposed Solution` section, and should not be more than 2 years from the plan creation date.
|
|
119
119
|
- If the plan scope is too large for 2 years, break it into multiple plans.
|
|
120
120
|
- Remember that this plan must be deleted after full implementation. Write it with that ephemeral nature in mind.
|
|
121
|
-
-
|
|
121
|
+
- For diagrams and non-Markdown assets, follow `_core-adr-policy-020`: prefer plain Markdown tables/lists first, then ASCII art for very simple cases, then Mermaid.js for complex diagrams, then draw.io when Mermaid is insufficient — save as Editable Vector (File → Save As → Editable Vector) and store as `.svg` in the sibling `.assets/` folder.
|
|
122
122
|
- If the plan genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/plans/.assets/` and link them using a same-folder relative path (e.g., `.assets/image.png`).
|
|
123
123
|
- Use relative paths for all links; never use absolute paths starting with `/`.
|
|
124
124
|
- Use lowercase file names. Never use emojis.
|
|
@@ -45,10 +45,10 @@ Identify the target scope from the parent document's path or the user's request;
|
|
|
45
45
|
- **Solution/Decision**: what was decided and why
|
|
46
46
|
- **Actions/Next Steps**: what happens now, who is responsible
|
|
47
47
|
3. For each slide, identify the best format:
|
|
48
|
-
- Mermaid diagrams for flows, relationships, architecture
|
|
48
|
+
- Mermaid diagrams for flows, relationships, architecture; draw.io `.svg` files saved as Editable Vector (File → Save As → Editable Vector, stored in `.assets/`) when Mermaid is not sufficient
|
|
49
|
+
- ASCII art for very simple spatial layouts where Markdown is insufficient (see `_core-adr-policy-020`)
|
|
49
50
|
- Short bullet points for key decisions and trade-offs
|
|
50
51
|
- Tables for comparisons, options, criteria
|
|
51
|
-
- ASCII art for simple layouts or structures
|
|
52
52
|
- Key short statements for emphasis
|
|
53
53
|
- Longer text only when exact wording must be evaluated (policies, controls)
|
|
54
54
|
4. Keep the total under 30 slides. If more content is needed, plan separate slide sets.
|
package/lib/lint.js
CHANGED
|
@@ -670,6 +670,7 @@ function lintScopeDirectory(xdrsRoot, scopeName, errors, warnings, actualTypeInd
|
|
|
670
670
|
// Determine if this scope is a core-type scope (but not _core which is exempt)
|
|
671
671
|
// Used to enforce structured format on all policies in core-type scopes
|
|
672
672
|
let isCoreTypeNonExempt = false;
|
|
673
|
+
let isCompiledScope = false;
|
|
673
674
|
if (scopeName !== '_core') {
|
|
674
675
|
const scopeIndexPath = path.join(scopePath, 'index.md');
|
|
675
676
|
if (existsFile(scopeIndexPath)) {
|
|
@@ -678,10 +679,12 @@ function lintScopeDirectory(xdrsRoot, scopeName, errors, warnings, actualTypeInd
|
|
|
678
679
|
const stMatch = idxContent.match(/^scope-type:\s*(.+)$/m);
|
|
679
680
|
if (stMatch) {
|
|
680
681
|
const stRaw = stMatch[1].trim();
|
|
682
|
+
// Handle both "[type1, type2]" YAML array format and "type1, type2" inline CSV format
|
|
681
683
|
const stList = stRaw.startsWith('[') && stRaw.endsWith(']')
|
|
682
684
|
? stRaw.slice(1, -1).split(',').map((s) => s.trim())
|
|
683
|
-
:
|
|
685
|
+
: stRaw.split(',').map((s) => s.trim());
|
|
684
686
|
isCoreTypeNonExempt = stList.includes('core');
|
|
687
|
+
isCompiledScope = stList.includes('compiled');
|
|
685
688
|
}
|
|
686
689
|
} catch { /* ignore read errors; will be caught later */ }
|
|
687
690
|
}
|
|
@@ -696,7 +699,7 @@ function lintScopeDirectory(xdrsRoot, scopeName, errors, warnings, actualTypeInd
|
|
|
696
699
|
errors.push(`Unexpected directory under scope ${scopeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001]`);
|
|
697
700
|
continue;
|
|
698
701
|
}
|
|
699
|
-
lintTypeDirectory(xdrsRoot, scopeName, entry.name, errors, warnings, actualTypeIndexes, externalScopes, isCoreTypeNonExempt);
|
|
702
|
+
lintTypeDirectory(xdrsRoot, scopeName, entry.name, errors, warnings, actualTypeIndexes, externalScopes, isCoreTypeNonExempt, isCompiledScope);
|
|
700
703
|
const typeIndexPath = path.join(entryPath, 'index.md');
|
|
701
704
|
if (existsFile(typeIndexPath)) {
|
|
702
705
|
typeIndexesInScope.push(typeIndexPath);
|
|
@@ -718,10 +721,10 @@ function lintScopeDirectory(xdrsRoot, scopeName, errors, warnings, actualTypeInd
|
|
|
718
721
|
lintScopeIndex(scopeIndexPath, xdrsRoot, scopeName, typeIndexesInScope, errors, externalScopes);
|
|
719
722
|
lintScopeIndexFrontmatter(scopeIndexPath, scopeName, errors, xdrsRoot, knownScopeTypes, readOnlyScopes, extendsRelationships);
|
|
720
723
|
}
|
|
721
|
-
lintLocalMetaPolicies(xdrsRoot, scopeName, errors);
|
|
724
|
+
lintLocalMetaPolicies(xdrsRoot, scopeName, errors, isCompiledScope);
|
|
722
725
|
}
|
|
723
726
|
|
|
724
|
-
function lintLocalMetaPolicies(xdrsRoot, scopeName, errors) {
|
|
727
|
+
function lintLocalMetaPolicies(xdrsRoot, scopeName, errors, isCompiledScope = false) {
|
|
725
728
|
const scopePath = path.join(xdrsRoot, scopeName);
|
|
726
729
|
// Track qualifiers across all type folders: qualifier ('' for primary) -> filePath
|
|
727
730
|
const seenQualifiers = new Map();
|
|
@@ -757,6 +760,21 @@ function lintLocalMetaPolicies(xdrsRoot, scopeName, errors) {
|
|
|
757
760
|
errors.push(`Local meta-policy companion "${path.basename(companion.filePath)}" requires a primary "NNN-core.md" in the same type folder "${typeName}": ${toDisplayPath(companion.filePath)} [_core-adr-policy-010.10b-local-primary-required]`);
|
|
758
761
|
}
|
|
759
762
|
}
|
|
763
|
+
// For compiled scopes: primary meta-policy must include ## Sources and ## Selectors
|
|
764
|
+
if (isCompiledScope && primaryInFolder) {
|
|
765
|
+
let metaContent;
|
|
766
|
+
try { metaContent = fs.readFileSync(primaryInFolder.filePath, 'utf8'); } catch { /* will be caught elsewhere */ }
|
|
767
|
+
if (metaContent !== undefined) {
|
|
768
|
+
const metaLines = metaContent.split(/\r?\n/);
|
|
769
|
+
const metaIgnored = findIgnoredMarkdownLines(metaLines);
|
|
770
|
+
if (findHeadingLine(metaLines, metaIgnored, '## Sources') === -1) {
|
|
771
|
+
errors.push(`Compiled scope meta-policy must include a "## Sources" section: ${toDisplayPath(primaryInFolder.filePath)} [_core-adr-policy-019.07-compilation-meta-policy]`);
|
|
772
|
+
}
|
|
773
|
+
if (findHeadingLine(metaLines, metaIgnored, '## Selectors') === -1) {
|
|
774
|
+
errors.push(`Compiled scope meta-policy must include a "## Selectors" section: ${toDisplayPath(primaryInFolder.filePath)} [_core-adr-policy-019.07-compilation-meta-policy]`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
760
778
|
// Check qualifier uniqueness across all type folders
|
|
761
779
|
const allInFolder = primaryInFolder ? [primaryInFolder, ...companionsInFolder] : companionsInFolder;
|
|
762
780
|
for (const { filePath, qualifier } of allInFolder) {
|
|
@@ -773,7 +791,7 @@ function lintLocalMetaPolicies(xdrsRoot, scopeName, errors) {
|
|
|
773
791
|
}
|
|
774
792
|
}
|
|
775
793
|
|
|
776
|
-
function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, warnings, actualTypeIndexes, externalScopes = new Set(), enforceStructured = false) {
|
|
794
|
+
function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, warnings, actualTypeIndexes, externalScopes = new Set(), enforceStructured = false, isCompiledScope = false) {
|
|
777
795
|
const typePath = path.join(xdrsRoot, scopeName, typeName);
|
|
778
796
|
const indexPath = path.join(typePath, 'index.md');
|
|
779
797
|
const xdrsNumbers = new Map();
|
|
@@ -804,7 +822,7 @@ function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, warnings, actu
|
|
|
804
822
|
warnings.push(`Invalid subject folder for ${typeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001] [exempt: freeze-reference]`);
|
|
805
823
|
}
|
|
806
824
|
|
|
807
|
-
artifacts.push(...lintSubjectDirectory(xdrsRoot, scopeName, typeName, entry.name, xdrsNumbers, errors, warnings, externalScopes, enforceStructured));
|
|
825
|
+
artifacts.push(...lintSubjectDirectory(xdrsRoot, scopeName, typeName, entry.name, xdrsNumbers, errors, warnings, externalScopes, enforceStructured, isCompiledScope));
|
|
808
826
|
}
|
|
809
827
|
|
|
810
828
|
if (existsFile(indexPath)) {
|
|
@@ -812,7 +830,7 @@ function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, warnings, actu
|
|
|
812
830
|
}
|
|
813
831
|
}
|
|
814
832
|
|
|
815
|
-
function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNumbers, errors, warnings, externalScopes = new Set(), enforceStructured = false) {
|
|
833
|
+
function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNumbers, errors, warnings, externalScopes = new Set(), enforceStructured = false, isCompiledScope = false) {
|
|
816
834
|
const subjectPath = path.join(xdrsRoot, scopeName, typeName, subjectName);
|
|
817
835
|
const artifacts = [];
|
|
818
836
|
const entries = safeReadDir(subjectPath, errors, `read subject directory ${scopeName}/${typeName}/${subjectName}`);
|
|
@@ -851,7 +869,7 @@ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNu
|
|
|
851
869
|
}
|
|
852
870
|
|
|
853
871
|
artifacts.push(entryPath);
|
|
854
|
-
lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, entryPath, xdrsNumbers, errors, warnings, externalScopes, enforceStructured);
|
|
872
|
+
lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, entryPath, xdrsNumbers, errors, warnings, externalScopes, enforceStructured, isCompiledScope);
|
|
855
873
|
}
|
|
856
874
|
|
|
857
875
|
const subjectAssetsDir = path.join(subjectPath, RESOURCE_DIR_NAME);
|
|
@@ -861,7 +879,7 @@ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNu
|
|
|
861
879
|
return artifacts;
|
|
862
880
|
}
|
|
863
881
|
|
|
864
|
-
function lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, filePath, xdrsNumbers, errors, warnings, externalScopes = new Set(), enforceStructured = false) {
|
|
882
|
+
function lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, filePath, xdrsNumbers, errors, warnings, externalScopes = new Set(), enforceStructured = false, isCompiledScope = false) {
|
|
865
883
|
const baseName = path.basename(filePath);
|
|
866
884
|
const match = baseName.match(NUMBERED_FILE_RE);
|
|
867
885
|
if (!match) {
|
|
@@ -903,9 +921,15 @@ function lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, filePat
|
|
|
903
921
|
lintXdrsElementFrontmatter(content, expectedName, filePath, errors, warnings, freezeReference);
|
|
904
922
|
if (enforceStructured) {
|
|
905
923
|
validateStructuredFormatContent(content, filePath, errors, '_core-adr-policy-010.08c-def-core-scope-policies-must-be-structured');
|
|
924
|
+
} else if (isCompiledScope) {
|
|
925
|
+
validateStructuredFormatContent(content, filePath, errors, '_core-adr-policy-019.04-structured-format-required');
|
|
906
926
|
} else {
|
|
907
927
|
lintStructuredRuleBlocks(content, filePath, errors);
|
|
908
928
|
}
|
|
929
|
+
const isLocalMetaPolicy = subjectName === 'principles' && titleParts[0] === 'core';
|
|
930
|
+
if (isCompiledScope && !isLocalMetaPolicy) {
|
|
931
|
+
lintCompiledPolicySourceSection(content, filePath, errors);
|
|
932
|
+
}
|
|
909
933
|
lintRequiredSections(content, filePath, XDRS_REQUIRED_SECTIONS, 'Policy', errors);
|
|
910
934
|
lintNoEmojis(content, filePath, 'Policy', errors);
|
|
911
935
|
lintWordCount(content, filePath, 'Policy', POLICY_MAX_WORDS, errors);
|
|
@@ -1708,6 +1732,32 @@ function validateStructuredFormatContent(content, filePath, errors, errorCode) {
|
|
|
1708
1732
|
lintStructuredRuleBlocks(content, filePath, errors);
|
|
1709
1733
|
}
|
|
1710
1734
|
|
|
1735
|
+
function lintCompiledPolicySourceSection(content, filePath, errors) {
|
|
1736
|
+
const lines = content.split(/\r?\n/);
|
|
1737
|
+
const ignoredLines = findIgnoredMarkdownLines(lines);
|
|
1738
|
+
const sourceStart = findHeadingLine(lines, ignoredLines, '## Source');
|
|
1739
|
+
if (sourceStart === -1) {
|
|
1740
|
+
errors.push(`Compiled policy must include a "## Source" section: ${toDisplayPath(filePath)} [_core-adr-policy-019.10-source-section]`);
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
// Find end of ## Source section (next ## heading or EOF)
|
|
1744
|
+
let sourceEnd = lines.length;
|
|
1745
|
+
for (let i = sourceStart + 1; i < lines.length; i++) {
|
|
1746
|
+
if (!ignoredLines[i] && /^## /.test(lines[i])) {
|
|
1747
|
+
sourceEnd = i;
|
|
1748
|
+
break;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
// Paths in ## Source MUST NOT be written as markdown links
|
|
1752
|
+
const MD_LINK_RE = /\[.+?\]\(.+?\)/;
|
|
1753
|
+
for (let i = sourceStart + 1; i < sourceEnd; i++) {
|
|
1754
|
+
if (!ignoredLines[i] && MD_LINK_RE.test(lines[i])) {
|
|
1755
|
+
errors.push(`Compiled policy "## Source" section must not use markdown links (use plain text paths): ${toDisplayPath(filePath)}:${i + 1} [_core-adr-policy-019.10-source-section]`);
|
|
1756
|
+
break;
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1711
1761
|
function findIgnoredMarkdownLines(lines) {
|
|
1712
1762
|
const ignored = [];
|
|
1713
1763
|
let inCodeFence = false;
|
package/lib/lint.test.js
CHANGED
|
@@ -2456,6 +2456,509 @@ test('does not require structured format for _core scope policies (exempt)', ()
|
|
|
2456
2456
|
expect(result.errors.join('\n')).not.toContain('08c-def-core-scope-policies-must-be-structured');
|
|
2457
2457
|
});
|
|
2458
2458
|
|
|
2459
|
+
// ─── compiled scope-type checks ───────────────────────────────────────────────
|
|
2460
|
+
|
|
2461
|
+
function compiledScopeIndex() {
|
|
2462
|
+
return [
|
|
2463
|
+
'---',
|
|
2464
|
+
'scope-type: compiled',
|
|
2465
|
+
'name: my-compiled',
|
|
2466
|
+
'description: Compiled scope for tests.',
|
|
2467
|
+
'apply-to: All consumers of compiled content',
|
|
2468
|
+
'valid-from: 2026-01-01',
|
|
2469
|
+
'---',
|
|
2470
|
+
'',
|
|
2471
|
+
'# my-compiled Scope Overview',
|
|
2472
|
+
'',
|
|
2473
|
+
'Compiled scope for tests.',
|
|
2474
|
+
'',
|
|
2475
|
+
'[ADRs](adrs/index.md)',
|
|
2476
|
+
''
|
|
2477
|
+
].join('\n');
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
function compiledAdrIndex(entries) {
|
|
2481
|
+
return [
|
|
2482
|
+
'# my-compiled ADR Index',
|
|
2483
|
+
'',
|
|
2484
|
+
'Compiled ADRs for tests.',
|
|
2485
|
+
'',
|
|
2486
|
+
'## principles',
|
|
2487
|
+
'',
|
|
2488
|
+
...entries,
|
|
2489
|
+
''
|
|
2490
|
+
].join('\n');
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
function validCompiledPolicy() {
|
|
2494
|
+
return [
|
|
2495
|
+
'---',
|
|
2496
|
+
'name: my-compiled-adr-policy-001-a01',
|
|
2497
|
+
'description: Compiled test policy.',
|
|
2498
|
+
'apply-to: All teams',
|
|
2499
|
+
'valid-from: 2026-01-01',
|
|
2500
|
+
'---',
|
|
2501
|
+
'',
|
|
2502
|
+
'# my-compiled-adr-policy-001: A01',
|
|
2503
|
+
'',
|
|
2504
|
+
'## Context and Problem Statement',
|
|
2505
|
+
'',
|
|
2506
|
+
'External source defines this requirement.',
|
|
2507
|
+
'',
|
|
2508
|
+
'## Decision Outcome',
|
|
2509
|
+
'',
|
|
2510
|
+
'Follow the rule.',
|
|
2511
|
+
'',
|
|
2512
|
+
'### Details',
|
|
2513
|
+
'',
|
|
2514
|
+
'#### 01-rule',
|
|
2515
|
+
'',
|
|
2516
|
+
'MUST comply.',
|
|
2517
|
+
'',
|
|
2518
|
+
'## Source',
|
|
2519
|
+
'',
|
|
2520
|
+
'- source-1/standards/a01.md',
|
|
2521
|
+
''
|
|
2522
|
+
].join('\n');
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
function validCompiledMetaPolicy() {
|
|
2526
|
+
return [
|
|
2527
|
+
'---',
|
|
2528
|
+
'name: my-compiled-adr-policy-001-core',
|
|
2529
|
+
'description: Compilation meta-policy for adrs.',
|
|
2530
|
+
'apply-to: Compilation process for this scope',
|
|
2531
|
+
'valid-from: 2026-01-01',
|
|
2532
|
+
'---',
|
|
2533
|
+
'',
|
|
2534
|
+
'# my-compiled-adr-policy-001: core',
|
|
2535
|
+
'',
|
|
2536
|
+
'## Context and Problem Statement',
|
|
2537
|
+
'',
|
|
2538
|
+
'Defines compilation configuration.',
|
|
2539
|
+
'',
|
|
2540
|
+
'## Decision Outcome',
|
|
2541
|
+
'',
|
|
2542
|
+
'Use the configured sources.',
|
|
2543
|
+
'',
|
|
2544
|
+
'### Details',
|
|
2545
|
+
'',
|
|
2546
|
+
'#### 01-rule',
|
|
2547
|
+
'',
|
|
2548
|
+
'MUST use configured sources.',
|
|
2549
|
+
'',
|
|
2550
|
+
'## Sources',
|
|
2551
|
+
'',
|
|
2552
|
+
'- [web] https://example.com/standards',
|
|
2553
|
+
'',
|
|
2554
|
+
'## Selectors',
|
|
2555
|
+
'',
|
|
2556
|
+
'- Include all requirement sections.',
|
|
2557
|
+
''
|
|
2558
|
+
].join('\n');
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
test('reports policy in compiled scope missing structured format', () => {
|
|
2562
|
+
const workspaceRoot = createWorkspace('compiled-scope-policy-unstructured', {
|
|
2563
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2564
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2565
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2566
|
+
'- [001-a01](principles/001-a01.md) - A01'
|
|
2567
|
+
]),
|
|
2568
|
+
'.xdrs/my-compiled/adrs/principles/001-a01.md': [
|
|
2569
|
+
'---',
|
|
2570
|
+
'name: my-compiled-adr-policy-001-a01',
|
|
2571
|
+
'description: Compiled test policy.',
|
|
2572
|
+
'apply-to: All teams',
|
|
2573
|
+
'valid-from: 2026-01-01',
|
|
2574
|
+
'---',
|
|
2575
|
+
'',
|
|
2576
|
+
'# my-compiled-adr-policy-001: A01',
|
|
2577
|
+
'',
|
|
2578
|
+
'## Context and Problem Statement',
|
|
2579
|
+
'',
|
|
2580
|
+
'External source.',
|
|
2581
|
+
'',
|
|
2582
|
+
'## Decision Outcome',
|
|
2583
|
+
'',
|
|
2584
|
+
'Follow rule.',
|
|
2585
|
+
'',
|
|
2586
|
+
'## Source',
|
|
2587
|
+
'',
|
|
2588
|
+
'- source-1/a01.md',
|
|
2589
|
+
''
|
|
2590
|
+
].join('\n'),
|
|
2591
|
+
});
|
|
2592
|
+
|
|
2593
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2594
|
+
|
|
2595
|
+
expect(result.errors.join('\n')).toContain('"### Details"');
|
|
2596
|
+
expect(result.errors.join('\n')).toContain('019.04-structured-format-required');
|
|
2597
|
+
});
|
|
2598
|
+
|
|
2599
|
+
test('reports compiled policy missing ## Source section', () => {
|
|
2600
|
+
const workspaceRoot = createWorkspace('compiled-scope-missing-source', {
|
|
2601
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2602
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2603
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2604
|
+
'- [001-a01](principles/001-a01.md) - A01'
|
|
2605
|
+
]),
|
|
2606
|
+
'.xdrs/my-compiled/adrs/principles/001-a01.md': [
|
|
2607
|
+
'---',
|
|
2608
|
+
'name: my-compiled-adr-policy-001-a01',
|
|
2609
|
+
'description: Compiled test policy.',
|
|
2610
|
+
'apply-to: All teams',
|
|
2611
|
+
'valid-from: 2026-01-01',
|
|
2612
|
+
'---',
|
|
2613
|
+
'',
|
|
2614
|
+
'# my-compiled-adr-policy-001: A01',
|
|
2615
|
+
'',
|
|
2616
|
+
'## Context and Problem Statement',
|
|
2617
|
+
'',
|
|
2618
|
+
'External source.',
|
|
2619
|
+
'',
|
|
2620
|
+
'## Decision Outcome',
|
|
2621
|
+
'',
|
|
2622
|
+
'Follow rule.',
|
|
2623
|
+
'',
|
|
2624
|
+
'### Details',
|
|
2625
|
+
'',
|
|
2626
|
+
'#### 01-rule',
|
|
2627
|
+
'',
|
|
2628
|
+
'MUST comply.',
|
|
2629
|
+
''
|
|
2630
|
+
].join('\n'),
|
|
2631
|
+
});
|
|
2632
|
+
|
|
2633
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2634
|
+
|
|
2635
|
+
expect(result.errors.join('\n')).toContain('Compiled policy must include a "## Source" section');
|
|
2636
|
+
expect(result.errors.join('\n')).toContain('019.10-source-section');
|
|
2637
|
+
});
|
|
2638
|
+
|
|
2639
|
+
test('reports compiled policy with markdown links in ## Source section', () => {
|
|
2640
|
+
const workspaceRoot = createWorkspace('compiled-scope-source-md-links', {
|
|
2641
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2642
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2643
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2644
|
+
'- [001-a01](principles/001-a01.md) - A01'
|
|
2645
|
+
]),
|
|
2646
|
+
'.xdrs/my-compiled/adrs/principles/001-a01.md': [
|
|
2647
|
+
'---',
|
|
2648
|
+
'name: my-compiled-adr-policy-001-a01',
|
|
2649
|
+
'description: Compiled test policy.',
|
|
2650
|
+
'apply-to: All teams',
|
|
2651
|
+
'valid-from: 2026-01-01',
|
|
2652
|
+
'---',
|
|
2653
|
+
'',
|
|
2654
|
+
'# my-compiled-adr-policy-001: A01',
|
|
2655
|
+
'',
|
|
2656
|
+
'## Context and Problem Statement',
|
|
2657
|
+
'',
|
|
2658
|
+
'External source.',
|
|
2659
|
+
'',
|
|
2660
|
+
'## Decision Outcome',
|
|
2661
|
+
'',
|
|
2662
|
+
'Follow rule.',
|
|
2663
|
+
'',
|
|
2664
|
+
'### Details',
|
|
2665
|
+
'',
|
|
2666
|
+
'#### 01-rule',
|
|
2667
|
+
'',
|
|
2668
|
+
'MUST comply.',
|
|
2669
|
+
'',
|
|
2670
|
+
'## Source',
|
|
2671
|
+
'',
|
|
2672
|
+
'- [source-1/a01.md](source-1/a01.md)',
|
|
2673
|
+
''
|
|
2674
|
+
].join('\n'),
|
|
2675
|
+
});
|
|
2676
|
+
|
|
2677
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2678
|
+
|
|
2679
|
+
expect(result.errors.join('\n')).toContain('"## Source" section must not use markdown links');
|
|
2680
|
+
expect(result.errors.join('\n')).toContain('019.10-source-section');
|
|
2681
|
+
});
|
|
2682
|
+
|
|
2683
|
+
test('accepts valid compiled policy with ## Source section and no markdown links', () => {
|
|
2684
|
+
const workspaceRoot = createWorkspace('compiled-scope-valid', {
|
|
2685
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2686
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2687
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2688
|
+
'- [001-a01](principles/001-a01.md) - A01'
|
|
2689
|
+
]),
|
|
2690
|
+
'.xdrs/my-compiled/adrs/principles/001-a01.md': validCompiledPolicy(),
|
|
2691
|
+
});
|
|
2692
|
+
|
|
2693
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2694
|
+
|
|
2695
|
+
expect(result.errors.join('\n')).not.toContain('019');
|
|
2696
|
+
});
|
|
2697
|
+
|
|
2698
|
+
test('reports compiled scope meta-policy missing ## Sources section', () => {
|
|
2699
|
+
const workspaceRoot = createWorkspace('compiled-meta-missing-sources', {
|
|
2700
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2701
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2702
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2703
|
+
'- [001-core](principles/001-core.md) - meta-policy',
|
|
2704
|
+
'- [002-a01](principles/002-a01.md) - A01'
|
|
2705
|
+
]),
|
|
2706
|
+
'.xdrs/my-compiled/adrs/principles/001-core.md': [
|
|
2707
|
+
'---',
|
|
2708
|
+
'name: my-compiled-adr-policy-001-core',
|
|
2709
|
+
'description: Compilation meta-policy.',
|
|
2710
|
+
'apply-to: Compilation process',
|
|
2711
|
+
'valid-from: 2026-01-01',
|
|
2712
|
+
'---',
|
|
2713
|
+
'',
|
|
2714
|
+
'# my-compiled-adr-policy-001: core',
|
|
2715
|
+
'',
|
|
2716
|
+
'## Context and Problem Statement',
|
|
2717
|
+
'',
|
|
2718
|
+
'Defines compilation config.',
|
|
2719
|
+
'',
|
|
2720
|
+
'## Decision Outcome',
|
|
2721
|
+
'',
|
|
2722
|
+
'Use configured sources.',
|
|
2723
|
+
'',
|
|
2724
|
+
'### Details',
|
|
2725
|
+
'',
|
|
2726
|
+
'#### 01-rule',
|
|
2727
|
+
'',
|
|
2728
|
+
'MUST use configured sources.',
|
|
2729
|
+
'',
|
|
2730
|
+
'## Selectors',
|
|
2731
|
+
'',
|
|
2732
|
+
'- Include requirement sections.',
|
|
2733
|
+
''
|
|
2734
|
+
].join('\n'),
|
|
2735
|
+
'.xdrs/my-compiled/adrs/principles/002-a01.md': [
|
|
2736
|
+
'---',
|
|
2737
|
+
'name: my-compiled-adr-policy-002-a01',
|
|
2738
|
+
'description: Compiled test policy.',
|
|
2739
|
+
'apply-to: All teams',
|
|
2740
|
+
'valid-from: 2026-01-01',
|
|
2741
|
+
'---',
|
|
2742
|
+
'',
|
|
2743
|
+
'# my-compiled-adr-policy-002: A01',
|
|
2744
|
+
'',
|
|
2745
|
+
'## Context and Problem Statement',
|
|
2746
|
+
'',
|
|
2747
|
+
'External source.',
|
|
2748
|
+
'',
|
|
2749
|
+
'## Decision Outcome',
|
|
2750
|
+
'',
|
|
2751
|
+
'Follow rule.',
|
|
2752
|
+
'',
|
|
2753
|
+
'### Details',
|
|
2754
|
+
'',
|
|
2755
|
+
'#### 01-rule',
|
|
2756
|
+
'',
|
|
2757
|
+
'MUST comply.',
|
|
2758
|
+
'',
|
|
2759
|
+
'## Source',
|
|
2760
|
+
'',
|
|
2761
|
+
'- source-1/a01.md',
|
|
2762
|
+
''
|
|
2763
|
+
].join('\n'),
|
|
2764
|
+
});
|
|
2765
|
+
|
|
2766
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2767
|
+
|
|
2768
|
+
expect(result.errors.join('\n')).toContain('"## Sources" section');
|
|
2769
|
+
expect(result.errors.join('\n')).toContain('019.07-compilation-meta-policy');
|
|
2770
|
+
});
|
|
2771
|
+
|
|
2772
|
+
test('reports compiled scope meta-policy missing ## Selectors section', () => {
|
|
2773
|
+
const workspaceRoot = createWorkspace('compiled-meta-missing-selectors', {
|
|
2774
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2775
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2776
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2777
|
+
'- [001-core](principles/001-core.md) - meta-policy',
|
|
2778
|
+
'- [002-a01](principles/002-a01.md) - A01'
|
|
2779
|
+
]),
|
|
2780
|
+
'.xdrs/my-compiled/adrs/principles/001-core.md': [
|
|
2781
|
+
'---',
|
|
2782
|
+
'name: my-compiled-adr-policy-001-core',
|
|
2783
|
+
'description: Compilation meta-policy.',
|
|
2784
|
+
'apply-to: Compilation process',
|
|
2785
|
+
'valid-from: 2026-01-01',
|
|
2786
|
+
'---',
|
|
2787
|
+
'',
|
|
2788
|
+
'# my-compiled-adr-policy-001: core',
|
|
2789
|
+
'',
|
|
2790
|
+
'## Context and Problem Statement',
|
|
2791
|
+
'',
|
|
2792
|
+
'Defines compilation config.',
|
|
2793
|
+
'',
|
|
2794
|
+
'## Decision Outcome',
|
|
2795
|
+
'',
|
|
2796
|
+
'Use configured sources.',
|
|
2797
|
+
'',
|
|
2798
|
+
'### Details',
|
|
2799
|
+
'',
|
|
2800
|
+
'#### 01-rule',
|
|
2801
|
+
'',
|
|
2802
|
+
'MUST use configured sources.',
|
|
2803
|
+
'',
|
|
2804
|
+
'## Sources',
|
|
2805
|
+
'',
|
|
2806
|
+
'- [web] https://example.com/standards',
|
|
2807
|
+
''
|
|
2808
|
+
].join('\n'),
|
|
2809
|
+
'.xdrs/my-compiled/adrs/principles/002-a01.md': [
|
|
2810
|
+
'---',
|
|
2811
|
+
'name: my-compiled-adr-policy-002-a01',
|
|
2812
|
+
'description: Compiled test policy.',
|
|
2813
|
+
'apply-to: All teams',
|
|
2814
|
+
'valid-from: 2026-01-01',
|
|
2815
|
+
'---',
|
|
2816
|
+
'',
|
|
2817
|
+
'# my-compiled-adr-policy-002: A01',
|
|
2818
|
+
'',
|
|
2819
|
+
'## Context and Problem Statement',
|
|
2820
|
+
'',
|
|
2821
|
+
'External source.',
|
|
2822
|
+
'',
|
|
2823
|
+
'## Decision Outcome',
|
|
2824
|
+
'',
|
|
2825
|
+
'Follow rule.',
|
|
2826
|
+
'',
|
|
2827
|
+
'### Details',
|
|
2828
|
+
'',
|
|
2829
|
+
'#### 01-rule',
|
|
2830
|
+
'',
|
|
2831
|
+
'MUST comply.',
|
|
2832
|
+
'',
|
|
2833
|
+
'## Source',
|
|
2834
|
+
'',
|
|
2835
|
+
'- source-1/a01.md',
|
|
2836
|
+
''
|
|
2837
|
+
].join('\n'),
|
|
2838
|
+
});
|
|
2839
|
+
|
|
2840
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2841
|
+
|
|
2842
|
+
expect(result.errors.join('\n')).toContain('"## Selectors" section');
|
|
2843
|
+
expect(result.errors.join('\n')).toContain('019.07-compilation-meta-policy');
|
|
2844
|
+
});
|
|
2845
|
+
|
|
2846
|
+
test('accepts valid compiled scope meta-policy with required sections', () => {
|
|
2847
|
+
const workspaceRoot = createWorkspace('compiled-meta-valid', {
|
|
2848
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2849
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2850
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2851
|
+
'- [001-core](principles/001-core.md) - meta-policy',
|
|
2852
|
+
'- [002-a01](principles/002-a01.md) - A01'
|
|
2853
|
+
]),
|
|
2854
|
+
'.xdrs/my-compiled/adrs/principles/001-core.md': validCompiledMetaPolicy(),
|
|
2855
|
+
'.xdrs/my-compiled/adrs/principles/002-a01.md': [
|
|
2856
|
+
'---',
|
|
2857
|
+
'name: my-compiled-adr-policy-002-a01',
|
|
2858
|
+
'description: Compiled test policy.',
|
|
2859
|
+
'apply-to: All teams',
|
|
2860
|
+
'valid-from: 2026-01-01',
|
|
2861
|
+
'---',
|
|
2862
|
+
'',
|
|
2863
|
+
'# my-compiled-adr-policy-002: A01',
|
|
2864
|
+
'',
|
|
2865
|
+
'## Context and Problem Statement',
|
|
2866
|
+
'',
|
|
2867
|
+
'External source.',
|
|
2868
|
+
'',
|
|
2869
|
+
'## Decision Outcome',
|
|
2870
|
+
'',
|
|
2871
|
+
'Follow rule.',
|
|
2872
|
+
'',
|
|
2873
|
+
'### Details',
|
|
2874
|
+
'',
|
|
2875
|
+
'#### 01-rule',
|
|
2876
|
+
'',
|
|
2877
|
+
'MUST comply.',
|
|
2878
|
+
'',
|
|
2879
|
+
'## Source',
|
|
2880
|
+
'',
|
|
2881
|
+
'- source-1/a01.md',
|
|
2882
|
+
''
|
|
2883
|
+
].join('\n'),
|
|
2884
|
+
});
|
|
2885
|
+
|
|
2886
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2887
|
+
|
|
2888
|
+
expect(result.errors.join('\n')).not.toContain('019');
|
|
2889
|
+
});
|
|
2890
|
+
|
|
2891
|
+
test('skips ## Source check for local meta-policy files in compiled scope', () => {
|
|
2892
|
+
const workspaceRoot = createWorkspace('compiled-meta-no-source-required', {
|
|
2893
|
+
'.xdrs/index.md': rootIndex(['[my-compiled](my-compiled/index.md)']),
|
|
2894
|
+
'.xdrs/my-compiled/index.md': compiledScopeIndex(),
|
|
2895
|
+
'.xdrs/my-compiled/adrs/index.md': compiledAdrIndex([
|
|
2896
|
+
'- [001-core](principles/001-core.md) - meta-policy'
|
|
2897
|
+
]),
|
|
2898
|
+
'.xdrs/my-compiled/adrs/principles/001-core.md': validCompiledMetaPolicy(),
|
|
2899
|
+
});
|
|
2900
|
+
|
|
2901
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2902
|
+
|
|
2903
|
+
expect(result.errors.join('\n')).not.toContain('Compiled policy must include a "## Source" section');
|
|
2904
|
+
});
|
|
2905
|
+
|
|
2906
|
+
test('enforces compiled scope checks when scope-type is comma-separated with compiled', () => {
|
|
2907
|
+
const workspaceRoot = createWorkspace('compiled-multi-type-checks', {
|
|
2908
|
+
'.xdrs/index.md': rootIndex(['[my-compiled-scope](my-compiled-scope/index.md)']),
|
|
2909
|
+
'.xdrs/my-compiled-scope/index.md': [
|
|
2910
|
+
'---',
|
|
2911
|
+
'scope-type: compiled, standard',
|
|
2912
|
+
'name: my-compiled-scope',
|
|
2913
|
+
'description: Compiled standard scope for tests.',
|
|
2914
|
+
'apply-to: All consumers',
|
|
2915
|
+
'valid-from: 2026-01-01',
|
|
2916
|
+
'---',
|
|
2917
|
+
'',
|
|
2918
|
+
'# my-compiled-scope Scope Overview',
|
|
2919
|
+
'',
|
|
2920
|
+
'Compiled standard.',
|
|
2921
|
+
'',
|
|
2922
|
+
'[ADRs](adrs/index.md)',
|
|
2923
|
+
''
|
|
2924
|
+
].join('\n'),
|
|
2925
|
+
'.xdrs/my-compiled-scope/adrs/index.md': [
|
|
2926
|
+
'# my-compiled-scope ADR Index', '', 'ADRs.', '', '## principles', '',
|
|
2927
|
+
'- [001-a01](principles/001-a01.md) - A01', ''
|
|
2928
|
+
].join('\n'),
|
|
2929
|
+
'.xdrs/my-compiled-scope/adrs/principles/001-a01.md': [
|
|
2930
|
+
'---',
|
|
2931
|
+
'name: my-compiled-scope-adr-policy-001-a01',
|
|
2932
|
+
'description: Compiled test policy.',
|
|
2933
|
+
'apply-to: All teams',
|
|
2934
|
+
'valid-from: 2026-01-01',
|
|
2935
|
+
'---',
|
|
2936
|
+
'',
|
|
2937
|
+
'# my-compiled-scope-adr-policy-001: A01',
|
|
2938
|
+
'',
|
|
2939
|
+
'## Context and Problem Statement',
|
|
2940
|
+
'',
|
|
2941
|
+
'External source.',
|
|
2942
|
+
'',
|
|
2943
|
+
'## Decision Outcome',
|
|
2944
|
+
'',
|
|
2945
|
+
'Follow rule.',
|
|
2946
|
+
'',
|
|
2947
|
+
'## Source',
|
|
2948
|
+
'',
|
|
2949
|
+
'- source-1/a01.md',
|
|
2950
|
+
''
|
|
2951
|
+
].join('\n'),
|
|
2952
|
+
...coreWithStructuredScopeTypes(['standard', 'compiled']),
|
|
2953
|
+
});
|
|
2954
|
+
|
|
2955
|
+
const result = lintWorkspace(workspaceRoot);
|
|
2956
|
+
|
|
2957
|
+
expect(result.errors.join('\n')).toContain('"### Details"');
|
|
2958
|
+
expect(result.errors.join('\n')).toContain('019.04-structured-format-required');
|
|
2959
|
+
});
|
|
2960
|
+
|
|
2961
|
+
|
|
2459
2962
|
function localScopeIndex() {
|
|
2460
2963
|
return [
|
|
2461
2964
|
'---',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xdrs-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
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",
|