xdrs-core 0.8.0 → 0.10.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.
@@ -23,6 +23,17 @@ Provides clear ownership by scope, predictable navigation, and reusable decision
23
23
 
24
24
  - XDRs MUST contain a clear decision about a certain problem or situation. Avoid being too verbose and focus on explaining clearly the context and the decision. Avoid adding contents that are not original. If you have other references that are important to understand the document, add links and references.
25
25
  - XDRs are the central artifact of the framework and the authoritative policy for their scope, type, and subject. Supporting artifacts may explain, justify, or operationalize the decision, but they do not replace it.
26
+ - XDRs MAY include a `## Metadata` section, but only when at least one supported metadata field is present. When used, `## Metadata` MUST appear immediately before `## Context and Problem Statement`.
27
+ - Supported XDR metadata fields are:
28
+ - `Status:` Optional. Defines the lifecycle state of the decision. Allowed values are `Draft`, `Active`, and `Deprecated`. If omitted, the decision is treated as `Active`. Only `Active` decisions may be treated as current policy.
29
+ - `Valid:` Optional. Defines the time window in which an active decision may be treated as current. Use ISO dates only: `from YYYY-MM-DD`, `until YYYY-MM-DD`, or `from YYYY-MM-DD until YYYY-MM-DD`. If `from` is omitted, the decision takes effect immediately. If `until` is omitted, the decision remains valid indefinitely.
30
+ - `Applied to:` Optional. A short description of the contexts in which the decision is applicable. Keep it under 40 words. If omitted, the decision should be interpreted as applying to all logically applicable elements according to the decision text itself. Examples: `Only frontend code`, `JavaScript projects`, `Performance-sensitive codebases`
31
+ - Before using, enforcing, or citing an XDR as a current rule, humans and AI agents MUST decide whether the decision is in force for the current case.
32
+ - Check `Status:` first to determine whether the XDR is eligible to be used now. If `Status:` is omitted, treat it as `Active`. `Draft` and `Deprecated` decisions are background or history, not current policy.
33
+ - Check `Valid:` next to determine whether the current moment falls inside the decision's active date window. Not-yet-active and expired windows are not current policy.
34
+ - Check `Applied to:` next to determine whether the active, currently valid decision fits the current codebase, system, workflow, or audience.
35
+ - Check the decision context and implementation details last to determine any additional boundaries, exceptions, or qualifiers that metadata alone cannot express.
36
+ - If any check fails, the XDR MAY still be read as background, history, or context, but it MUST NOT be treated as a current requirement for that case.
26
37
  - Research documents MAY be added under the same subject to capture the exploration, findings, and proposals that backed a decision. Research is useful during elaboration, discussion, approval, retirement, and updates, but the XDR remains the source of truth.
27
38
  - Make it clear if an instruction is mandatory or advisory
28
39
  - Mandatory language: "must", "always", "never", "required", "mandatory"
@@ -33,6 +44,12 @@ Provides clear ownership by scope, predictable navigation, and reusable decision
33
44
  - `.xdrs/[scope]/[type]/[subject]/researches/[number]-[short-title].md`
34
45
  - `.xdrs/[scope]/[type]/[subject]/skills/[number]-[skill-name]/SKILL.md`
35
46
  - `.xdrs/[scope]/[type]/[subject]/articles/[number]-[short-title].md`
47
+ - For simple structure, flow, layout, or relationship indications, documents SHOULD prefer plain Markdown, tables, or ASCII art instead of external assets.
48
+ - Images and other supporting files SHOULD be used only when they are materially necessary to preserve clarity, fidelity, or evidence. When used, they SHOULD live in a sibling `assets/` folder next to the document.
49
+ - XDRs in the subject root use `.xdrs/[scope]/[type]/[subject]/assets/`
50
+ - Articles use `.xdrs/[scope]/[type]/[subject]/articles/assets/`
51
+ - Research uses `.xdrs/[scope]/[type]/[subject]/researches/assets/`
52
+ - Skills use `.xdrs/[scope]/[type]/[subject]/skills/[number]-[skill-name]/assets/`
36
53
  - **Scopes:**
37
54
  - examples: `business-x`, `business-y`, `team-43`, `_core`
38
55
  - `_local` is a reserved scope for XDRs created locally to a specific project or repository. XDRs in `_local` must not be shared with or propagated to other contexts. This scope must always be placed in the lowest position in `.xdrs/index.md` so that its decisions override or extend any decisions from all higher-positioned scopes.
@@ -46,7 +63,7 @@ Provides clear ownership by scope, predictable navigation, and reusable decision
46
63
  - Types in IDs: `adr`, `bdr`, `edr`
47
64
  - Define the next number of an XDR by checking what is the highest number present in the type+scope. Don't fill numbering gaps, as they might be old deleted XDRs and we should never reuse numbers of different documents/decisions. Numbering gaps are expected.
48
65
  - Decisions MUST be concise and reference other XDRs to avoid duplication
49
- - The `### Implementation Details` section SHOULD state when the decision applies, relevant boundaries or exceptions, and what a reader should do or avoid in common cases.
66
+ - The `### Implementation Details` section SHOULD state relevant boundaries or exceptions and what a reader should do or avoid in common cases. Use `## Metadata` as the first-pass filter for whether the decision should be used at all, then keep nuanced boundaries in the decision text.
50
67
  - Use concise rules, examples, or `Do` / `Don't` lists only when they help a reader apply the decision correctly. Keep them short and decision-specific.
51
68
  - When research exists for a decision, the XDR SHOULD mention the related research documents after the `## Considered Options` list.
52
69
  - Never use emojis in contents
@@ -73,6 +90,13 @@ All XDRs MUST follow this template
73
90
  ```markdown
74
91
  # [scope]-[type]-[number]: [Short Title]
75
92
 
93
+ ## Metadata
94
+
95
+ [Optional section. Omit the entire section when none of `Status:`, `Valid:`, or `Applied to:` is defined. Readers decide whether to use the XDR by checking `Status:` first, treating omission as `Active`, then `Valid:`, then `Applied to:`, and finally the decision text itself.]
96
+ Status: [Optional. Use `Draft`, `Active`, or `Deprecated`. Defaults to `Active` when omitted]
97
+ Valid: [Optional. Use `from YYYY-MM-DD`, `until YYYY-MM-DD`, or `from YYYY-MM-DD until YYYY-MM-DD`]
98
+ Applied to: [Optional short applicability scope, under 40 words]
99
+
76
100
  ## Context and Problem Statement
77
101
 
78
102
  [Describe the context, background, or need that led to this decision.
@@ -124,6 +148,27 @@ Question: In the end, state explicitly the question that needs to be answered. E
124
148
  - `.xdrs/business-x/edrs/devops/003-required-development-workflow.md`
125
149
  - `.xdrs/business-x/adrs/governance/010-security-and-secrets-management.md`
126
150
  - `.xdrs/_core/adrs/devops/001-multi-repo.md`
151
+ - Metadata examples:
152
+ - `Status: Draft`
153
+ - `Status: Active`
154
+ - `Valid: from 2026-03-01 until 2026-12-31`
155
+ - `Applied to: JavaScript projects`
156
+
157
+ ```text
158
+ subject/
159
+ |-- 001-xdr.md
160
+ |-- assets/
161
+ |-- articles/
162
+ | |-- 001-article.md
163
+ | `-- assets/
164
+ |-- researches/
165
+ | |-- 001-study.md
166
+ | `-- assets/
167
+ `-- skills/
168
+ `-- 001-task/
169
+ |-- SKILL.md
170
+ `-- assets/
171
+ ```
127
172
 
128
173
  **XDR ID Examples:**
129
174
  - `business-x-adr-001` (not `ADR-business-x-001` or `business-x-adr-1`)
@@ -31,6 +31,7 @@ Skills are procedures, XDRs are guardrails and decisions, Research documents cap
31
31
  Always create links back and forth between skills <-> XDRs when the relationship is direct, and link to related Research or Articles when they provide important context.
32
32
  - Skills are task-based artifacts. They should have a clear starting trigger, an expected end result, and enough detail for a human or agent to verify that the task finished correctly.
33
33
  - A skill is not policy by itself. If following a skill is mandatory, that obligation must come from an XDR or another explicit policy that references the skill.
34
+ - When a skill reads, operationalizes, or enforces XDRs, it MUST evaluate the XDR metadata first. `Status:` determines whether the decision is eligible to be used, and an omitted `Status:` must be treated as `Active`. `Valid:` determines whether that active decision is currently in force by date, `Applied to:` determines whether it fits the current task context, and the decision text itself determines any remaining boundaries. Skills must not treat inactive, out-of-window, or out-of-scope XDRs as current requirements.
34
35
  - Skills and XDRs have a many-to-many relationship: one skill may operationalize multiple XDRs, and one XDR may be executed through multiple skills in different contexts.
35
36
 
36
37
  Place a skill under the XDR type that matches the nature of the activity the skill performs:
@@ -50,7 +51,7 @@ Quick test:
50
51
  SKILL.md # required
51
52
  scripts/ # optional: executable scripts the agent may run
52
53
  references/ # optional: detailed reference material
53
- assets/ # optional: templates, images, data files
54
+ assets/ # optional: images, templates, data files, and other local resources
54
55
  ```
55
56
 
56
57
  Examples:
@@ -100,6 +101,8 @@ Rules:
100
101
  - The `name` field must match the parent directory name exactly (e.g., directory `001-code-review` uses `name: 001-code-review`). This preserves agentskills spec compliance while encoding the ordering number.
101
102
  - `## Overview` SHOULD state the task objective, expected outcome, and relevant prerequisites or tools when they matter.
102
103
  - `## 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.
104
+ - For simple structure, flow, layout, or relationship indications, `SKILL.md` SHOULD prefer plain Markdown, tables, or ASCII art instead of external assets.
105
+ - Images and other local resource files referenced from `SKILL.md` SHOULD be used only when they are materially necessary and SHOULD live in `assets/` inside the same skill package.
103
106
  - Keep `SKILL.md` under 500 lines. Move lengthy reference material to `references/`.
104
107
  - Reference other files with relative paths from the skill root.
105
108
  - Always use lowercase file names.
@@ -17,8 +17,11 @@ Articles are Markdown documents placed inside a subject folder alongside decisio
17
17
  - Articles are views, not decisions. They summarize and synthesize content from XDRs, Research, and Skills but are NOT the source of truth. When there is a conflict between an article and a Decision Record, the Decision Record takes precedence.
18
18
  - Articles must reference the XDRs, Research documents, and Skills they synthesize. Never duplicate decision content; link back to the authoritative sources.
19
19
  - Articles may serve as indexes, combining related artifacts on a specific topic into a single navigable document.
20
+ - When an article tells readers which decisions to follow, it SHOULD distinguish currently usable XDRs from background-only ones by checking `Status:` first, treating omission as `Active`, `Valid:` second, `Applied to:` third, and the decision text itself last. Articles must not present Draft, Deprecated, inactive-date, out-of-window, or out-of-scope XDRs as current rules for the discussed context.
20
21
  - Articles must remain consistent with the XDRs, Research documents, and Skills they reference. When a referenced artifact changes, the article must be reviewed and updated.
21
22
  - Place an article in the subject folder that best matches its topic. If an article spans more than one subject, place it in `principles`.
23
+ - For simple structure, flow, layout, or relationship indications, articles SHOULD prefer plain Markdown, tables, or ASCII art instead of external assets.
24
+ - Images and other local resource files referenced by an article SHOULD be used only when they are materially necessary and SHOULD live in `articles/assets/` next to the article files.
22
25
  - Always use lowercase file names.
23
26
  - Never use emojis in article content.
24
27
  - Articles should be kept under 150 lines. Move detailed content to referenced XDRs or Skills.
@@ -29,6 +32,7 @@ Articles are Markdown documents placed inside a subject folder alongside decisio
29
32
  .xdrs/[scope]/[type]/[subject]/
30
33
  articles/
31
34
  [number]-[short-title].md
35
+ assets/
32
36
  ```
33
37
 
34
38
  Examples:
@@ -4,13 +4,13 @@
4
4
 
5
5
  Teams often need more space than an XDR allows to evaluate constraints, explore options, and record findings before or after a decision changes. When that material is scattered across PR comments, docs, and chat, the reasoning behind a decision becomes hard to recover or update.
6
6
 
7
- Question: How should research documents be structured and organized so they support the decision lifecycle without replacing XDRs as the source of truth?
7
+ Question: How should research documents be structured and organized so they communicate an investigated problem, evidence, and conclusions clearly, while remaining traceable from related XDRs?
8
8
 
9
9
  ## Decision Outcome
10
10
 
11
- **subject-level research documents co-located with XDRs**
11
+ **IMRAD-based subject-level research documents co-located with XDRs**
12
12
 
13
- Research documents are Markdown files placed inside a subject folder alongside decision records. They capture the explored option space, relevant constraints, findings, and proposal tradeoffs that back a decision during elaboration, discussion, approval, retirement, and updates.
13
+ Research documents are Markdown files placed inside a subject folder alongside decision records. They use an IMRAD-inspired paper structure adapted to company needs so teams can communicate investigated problems, methods, findings, and conclusions clearly, combine experienced professional judgment with good-enough evidence, preserve reproducibility where it matters, and revisit the work when technology, constraints, or facts change.
14
14
 
15
15
  ### Implementation Details
16
16
 
@@ -18,15 +18,31 @@ Research documents are Markdown files placed inside a subject folder alongside d
18
18
  - `Research` is the artifact name. `researches/` is only the folder name used alongside `skills/` and `articles/`.
19
19
  - Research documents MUST live under `researches/` inside the relevant subject folder:
20
20
  `.xdrs/[scope]/[type]/[subject]/researches/[number]-[short-title].md`
21
- - Research documents SHOULD stay focused on one problem statement or decision thread.
22
- - Research documents MUST state clearly what problem or question is being investigated and who needs the result.
23
- - The `## Overview` section MUST end with a line in the form `Question: [central question]?` that states the central question the research answers.
24
- - Research constraints MAY include hard requirements, stack limitations, regulatory limits, or other conditions that narrow the option space.
25
- - Research documents MUST summarize the problem constraints, important findings, and a small set of proposals with pros and cons for each option.
26
- - Research proposals are the considered options for the decision thread. They are not the final policy.
27
- - Research documents SHOULD link to the XDRs, skills, articles, discussions, and external references they informed.
28
- - One research document MAY inform multiple XDRs, including a mix of ADRs, BDRs, and EDRs, when the same investigation produced several downstream decisions.
29
- - Research documents SHOULD remain concise enough to read end-to-end. Target under 500 lines; hard limit 2000 lines.
21
+ - Research documents SHOULD stay focused on one investigated problem, comparison, or hypothesis.
22
+ - Research documents MUST state clearly what problem or question is being investigated, the relevant system or domain context, and why the subject matters in practice.
23
+ - Research documents MUST follow this section order: `Abstract`, `Introduction`, `Methods`, `Results`, `Discussion`, `Conclusion`, `References`.
24
+ - Research uses a company-adapted IMRAD structure. It MAY include informed professional judgment and experience-based observations, but claims that affect the conclusion MUST have enough evidence to be teachable, reviewable, and useful to other colleagues.
25
+ - Research does not require full academic statistical rigor. Use good-enough evidence that supports the conclusion without demanding exhaustive proof.
26
+ - Research documents MUST read as standalone technical papers for readers who do not know the XDR process.
27
+ - Mentions of future ADRs, decision lifecycle, repository process, or artifact management SHOULD be avoided in the body unless they are materially necessary to understand the research question.
28
+ - Traceability to related XDRs, skills, articles, discussions, and external sources SHOULD live primarily in `## References` and surrounding indexes rather than in the body narrative.
29
+ - 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.
30
+ - The short title portion after the research id MUST stay under 20 words.
31
+ - `## 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.
32
+ - `## Introduction` MUST define the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives. It SHOULD prefer plain Markdown, bullet points, tables, or ASCII art for simple explanations, and SHOULD use external visuals only when they are materially necessary to improve understanding. It MUST stay under 700 words and MUST end with `Question: [central question]?`.
33
+ - `## 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.
34
+ - `## Results` MUST present findings, data, trends, quantitative results, produced code, and option comparisons when relevant. It SHOULD prefer tables, bullet lists, or ASCII art for simple comparisons, and SHOULD use external figures only when they are materially necessary. Keep interpretation to a minimum. It MUST stay under 1800 words.
35
+ - 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.
36
+ - `## Discussion` MUST interpret the results, explain significance, trade-offs, performance considerations, limitations, and implications for technical readers. It MUST stay under 1000 words.
37
+ - `## Conclusion` MUST summarize the main findings, practical takeaway, applicability boundaries, and important open questions. It MUST stay under 400 words.
38
+ - `## References` MUST list all cited literature, websites, tutorials, documentation, discussions, or related artifacts.
39
+ - In general, research SHOULD roughly follow the proportion `Introduction : Methods : Results : Discussion ≈ 3 : 5 : 6 : 4`.
40
+ - Be strict about the goal of each section. Avoid duplicating the same material across sections and prefer clarity over rhetorical flourishes.
41
+ - Research documents SHOULD stay under 5000 words total. They MAY exceed that only when the `## Introduction` explicitly states that the study will be lengthy because a very detailed analysis is required.
42
+ - Research documents SHOULD link in `## References` to the XDRs, skills, articles, discussions, and external references relevant to the subject or that later cite the work.
43
+ - A 1:1 relationship between one research document and one decision will likely be common in practice, but it is not required.
44
+ - One research document MAY also be referenced by multiple XDRs, including a mix of ADRs, BDRs, and EDRs, when the same investigation remains relevant across several decisions.
45
+ - Images and other local resource files referenced by a research document SHOULD be used only when they are materially necessary and SHOULD live in `researches/assets/` next to the research files.
30
46
  - Research file names MUST be lowercase. Never use emojis.
31
47
  - A research document MAY exist before the related XDR is written, or remain after the XDR changes, as long as its status and references stay clear.
32
48
 
@@ -36,6 +52,7 @@ Research documents are Markdown files placed inside a subject folder alongside d
36
52
  .xdrs/[scope]/[type]/[subject]/
37
53
  researches/
38
54
  [number]-[short-title].md
55
+ assets/
39
56
  ```
40
57
 
41
58
  Examples:
@@ -56,46 +73,39 @@ All research documents MUST follow this template:
56
73
  ```markdown
57
74
  # [scope]-research-[number]: [Short Title]
58
75
 
59
- ## Overview
76
+ ## Abstract
60
77
 
61
- [Brief description of the problem or question being explored, who needs the result, and the decision thread(s) it supports. Under 5 lines.]
78
+ [Single paragraph summarizing the goal, methods, results, and conclusion. Goal: let a quick technical reader understand the question, method, main result, and takeaway. Under 200 words.]
62
79
 
63
- Question: [Central question of the research]?
64
-
65
- ## Constraints
66
-
67
- - [Constraint or requirement 1]
68
- - [Constraint or requirement 2]
80
+ ## Introduction
69
81
 
70
- ## Findings
82
+ [Describe the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives.
83
+ Prefer bullets, tables, or ASCII art for simple explanations. Use external visuals only when they are materially necessary. Goal: explain the investigated problem, operating context, constraints, and why the subject matters. Under 700 words.]
71
84
 
72
- - [Important finding 1]
73
- - [Important finding 2]
74
-
75
- ## Proposals
85
+ Question: [Central question of the research]?
76
86
 
77
- ### Option 1: [Name]
87
+ ## Methods
78
88
 
79
- [Short description of the option.]
89
+ [Explain how the study was conducted, including design, tools, data sources, and test conditions.
90
+ Include enough detail for an experienced professional to reproduce the relevant parts. Goal: make the important parts of the study reproducible. Under 1200 words.]
80
91
 
81
- **Pros**
82
- - [Benefit 1]
83
- - [Benefit 2]
92
+ ## Results
84
93
 
85
- **Cons**
86
- - [Drawback 1]
87
- - [Drawback 2]
94
+ [Report findings, data, trends, quantitative results, code artifacts, and option comparisons.
95
+ Prefer tables, bullets, or ASCII art for simple comparisons. Use external figures only when they are materially necessary. 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.]
88
96
 
89
- ### Option 2: [Name]
97
+ ## Discussion
90
98
 
91
- [Same structure as above for each meaningful option.]
99
+ [Interpret the results, explain significance, trade-offs, performance considerations, limitations, and implications. Goal: interpret the findings for technical readers. Keep this section technically engaged and under 1000 words.]
92
100
 
93
- ## Recommendation
101
+ ## Conclusion
94
102
 
95
- [Optional summary of the currently preferred direction, if any.]
103
+ [Summarize the main findings, practical takeaway, applicability boundaries, and important open questions. Goal: summarize the main findings and what they mean in practice. Under 400 words.]
96
104
 
97
105
  ## References
98
106
 
107
+ [A list of all cited literature, websites, tutorials, documentation, discussions, and related artifacts. Goal: make all cited sources and supporting artifacts traceable.]
108
+
99
109
  - [Related XDR or artifact](relative/path.md) - Why it matters
100
110
  - [Another related XDR if this research informed multiple decisions](relative/path.md) - Why it matters
101
111
  ```
@@ -106,10 +116,8 @@ Question: [Central question of the research]?
106
116
 
107
117
  * (REJECTED) **Inline long-form analysis inside the XDR** - Put all research and decision text in one file.
108
118
  * Reason: Makes XDRs too long, mixes evidence with the adopted rule set, and hurts fast retrieval by humans and AI agents.
109
- * (REJECTED) **Separate top-level research area outside the subject tree** - Centralize all research in one independent folder.
110
- * Reason: Breaks proximity with the decisions it supports and makes subject-scoped discovery weaker.
111
- * (CHOSEN) **Subject-level research folder co-located with XDRs** - Keep exploratory material beside the decisions, skills, and articles it informs.
112
- * Reason: Preserves lifecycle context, keeps the XDR concise, and makes the research easy to discover when revisiting or updating a decision.
119
+ * (CHOSEN) **IMRAD-based subject-level research beside XDRs** - Keep exploratory material beside the decisions, skills, and articles it informs, using an IMRAD-inspired structure adapted to company work.
120
+ * Reason: Preserves lifecycle context, keeps the XDR concise, gives readers a predictable structure, and raises evidence quality without demanding full academic rigor.
113
121
 
114
122
  ## References
115
123
 
@@ -47,6 +47,16 @@ The easiest way to distinguish the central elements is by asking what job each o
47
47
  This separation matters because mixing these jobs into one file makes the system harder to search,
48
48
  harder to update, and harder for agents to apply correctly.
49
49
 
50
+ ### How to decide whether an XDR should be used
51
+
52
+ Before treating an XDR as a rule for the current case, check its metadata first.
53
+
54
+ - **Status first**: only `Active` decisions can be current policy, and omitted `Status` should be treated as `Active`. `Draft` and `Deprecated` are background or historical context.
55
+ - **Valid second**: if present, the current moment must fall inside the decision's date window.
56
+ - **Applied to third**: if present, the current codebase, workflow, system, or audience must fit that scope.
57
+ - **Decision text last**: the XDR's own context and implementation details still determine the final boundaries and exceptions.
58
+ - **Then enforce**: only decisions that pass those checks should be used as active requirements. The rest may still be useful background or historical context.
59
+
50
60
  ### How they relate over time
51
61
 
52
62
  The framework is easiest to understand as a lifecycle rather than a static folder tree.
@@ -122,6 +132,7 @@ Follow [_core-adr-001](../001-xdr-standards.md) strictly. Key rules:
122
132
 
123
133
  - Use **mandatory language** (`must`, `never`, `required`) for non-negotiable rules and
124
134
  **advisory language** (`should`, `recommended`) for guidance.
135
+ - Before citing an XDR as a requirement, check `Status` first, treating omission as `Active`, then `Valid`, then `Applied to`, and finally the decision text to confirm the decision is active and in scope for the current case.
125
136
  - Keep XDRs under 100 lines. Move procedural detail to a co-located Skill.
126
137
  - Keep exploratory option analysis in a co-located Research document instead of bloating the XDR.
127
138
  - Always update the scope+type index and the root index after adding or changing an XDR.
@@ -24,12 +24,16 @@ Performs a structured review of code changes or files against the XDRs in the re
24
24
 
25
25
  1. Gather all Decision Records from `.xdrs/index.md` starting from the working directory.
26
26
  - XDR scopes are controlled by nested folders; some are broad, others domain-specific.
27
- - Extract metadata first (status, impact, scope, applicability) to filter relevant XDRs before deep analysis.
27
+ - Extract metadata first to decide whether each XDR should be used for the current review context.
28
+ - Check `Status:` first. Treat an omitted `Status:` as `Active`, and treat `Draft` and `Deprecated` XDRs as background only, not active policy.
29
+ - Check `Valid:` second. Keep only `Active` XDRs whose date window covers the current review moment.
30
+ - Check `Applied to:` third. Keep only active, in-window XDRs whose stated scope fits the files, systems, or workflows under review.
31
+ - Check the decision text itself last for additional boundaries or exceptions that metadata does not encode.
28
32
  2. Filter relevance based on file types, domains, and architectural patterns in scope.
29
33
 
30
34
  ### Phase 3: XDR Review
31
35
 
32
- 1. Cross-reference each file in scope against applicable XDRs.
36
+ 1. Cross-reference each file in scope against active, applicable XDRs.
33
37
  - **Drop any finding that cannot be traced to a specific rule in an Accepted XDR.** General good-practice observations, personal opinions, or inferred issues without an explicit XDR backing must not be reported.
34
38
  - Classify as ERROR (mandatory) or WARNING (advisory).
35
39
  - Include: location, description, XDR reference (file + line), suggestion.
@@ -50,7 +54,7 @@ Performs a structured review of code changes or files against the XDRs in the re
50
54
  ### Phase 5: Reporting
51
55
 
52
56
  **Report template**
53
- --------
57
+ ```text
54
58
  ### Code Review Against XDRs
55
59
  Scope: [scope identifier]
56
60
 
@@ -68,7 +72,7 @@ Scope: [scope identifier]
68
72
  - Errors: [count]
69
73
  - Warnings: [count]
70
74
  - Outcome: [PASS|FAIL]
71
- --------
75
+ ```
72
76
 
73
77
  ### Constraints
74
78
  - MUST NOT include any text or explanations outside the required output format.
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  ## Overview
12
12
 
13
- Guides the creation of a well-structured XDR by following the standards in `_core-adr-001`, researching existing records for conflicts, and iterating until the document is concise and decision-focused.
13
+ Guides the creation of a well-structured XDR by following the standards in `_core-adr-001`, researching existing records for conflicts, checking redundancy across related artifacts, and iterating until the document is concise, decision-focused, and clear about when the decision should be used.
14
14
 
15
15
  ## Instructions
16
16
 
@@ -53,13 +53,28 @@ Choose a title that clearly states the question this XDR answers, not the answer
53
53
  4. Read related `researches/` documents when they exist, especially if they contain constraints, findings, or option tradeoffs that should influence the decision.
54
54
  5. Collect XDR IDs and file paths for cross-references.
55
55
 
56
- ### Phase 5: Write the First Draft
56
+ ### Phase 5: Check Redundancy Across Related Artifacts
57
+
58
+ 1. Review the related XDRs, research documents, skills, articles, and guides connected to the same decision thread.
59
+ 2. Identify content that is repeated across those files, especially decision statements, applicability boundaries, mandatory rules, and rationale.
60
+ 3. Prioritize the final decision, core boundaries, and short key instructions in the XDR itself.
61
+ 4. When another document already explains details well, link to it instead of re-explaining the same content in full.
62
+ 5. Copy only short instructions or key excerpts when they materially help a reader apply the decision without leaving the XDR.
63
+ 6. Avoid repeating the same decision text across multiple related documents whenever a link or short reference is enough.
64
+
65
+ ### Phase 6: Write the First Draft
57
66
 
58
67
  Use the mandatory template from `001-xdr-standards`:
59
68
 
60
69
  ```
61
70
  # [scope]-[type]-[number]: [Short Title]
62
71
 
72
+ ## Metadata
73
+ [Optional. Include only when at least one metadata field is present]
74
+ Status: [Optional. Use Draft, Active, or Deprecated. Defaults to Active when omitted]
75
+ Valid: [Optional. Use from YYYY-MM-DD, until YYYY-MM-DD, or from YYYY-MM-DD until YYYY-MM-DD]
76
+ Applied to: [Optional short applicability scope, under 40 words]
77
+
63
78
  ## Context and Problem Statement
64
79
  [4 lines max: background, who is impacted, and the explicit question being answered]
65
80
 
@@ -79,26 +94,35 @@ Use the mandatory template from `001-xdr-standards`:
79
94
  ```
80
95
 
81
96
  Mandatory rules to apply while drafting:
97
+ - Include `## Metadata` only when `Status:`, `Valid:`, and/or `Applied to:` adds value; omit the whole section when none of those fields is defined.
98
+ - When present, place `## Metadata` immediately before `## Context and Problem Statement`.
99
+ - Keep `Applied to:` under 40 words, use `Status:` only with `Draft`, `Active`, or `Deprecated`, remember that omitted `Status:` means `Active`, and use `Valid:` only with ISO date ranges.
100
+ - When metadata is present, write it so a reader can decide whether the XDR should be used for the current case without guessing. `Status:` controls lifecycle state, omitted `Status:` means `Active`, `Valid:` controls the active time window, `Applied to:` narrows the contexts where that active decision applies, and the decision text defines any remaining boundaries.
82
101
  - Use mandatory language ("must", "always", "never") only for hard requirements; use advisory language ("should", "recommended") for guidance.
83
102
  - Do not duplicate content already in referenced XDRs — link instead.
103
+ - Keep the decision itself authoritative in the XDR. Supporting artifacts may elaborate, but they should not restate the full decision when a short reference is enough.
84
104
  - Make clear when the decision applies and any important exception boundaries.
85
105
  - Keep exploratory option analysis in a related Research document when it would distract from the final decision text.
106
+ - Prefer plain Markdown, tables, or ASCII art for simple structure, flow, layout, or relationship indications.
107
+ - If the XDR genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/assets/` and link with a relative path.
86
108
  - No emojis. Lowercase filenames.
87
109
  - Target under 100 lines total; 200 lines max for complex decisions.
88
110
 
89
- ### Phase 6: Review the Draft
111
+ ### Phase 7: Review the Draft
90
112
 
91
113
  Check every item before finalizing:
92
114
 
93
115
  1. **Length**: Is it under 100 lines? Trim verbose explanations. Move detailed skills to a separate file and link.
94
- 2. **Originality**: Does every sentence add value that cannot be found in a generic web search? Remove obvious advice. Keep only the project-specific decision.
95
- 3. **Clarity**: Is the chosen option unambiguous? Is the "why" clear in one reading?
96
- 4. **Conflicts section**: Is it present and filled if Phase 3 found any conflicts?
97
- 5. **Index entries**: Will the new XDR be added to `[scope]/[type]/index.md` and `.xdrs/index.md`?
116
+ 2. **Metadata**: If metadata exists, is it directly before Context, limited to `Status:` / `Valid:` / `Applied to:`, omitted entirely when all three are absent, and specific enough for a reader to decide whether the XDR is active, currently valid, and applicable?
117
+ 3. **Originality**: Does every sentence add value that cannot be found in a generic web search? Remove obvious advice. Keep only the project-specific decision.
118
+ 4. **Clarity**: Is the chosen option unambiguous? Is the "why" clear in one reading?
119
+ 5. **Redundancy**: Is the XDR the primary source for the decision itself, with related documents linked instead of duplicated wherever possible?
120
+ 6. **Conflicts section**: Is it present and filled if Phase 3 found any conflicts?
121
+ 7. **Index entries**: Will the new XDR be added to `[scope]/[type]/index.md` and `.xdrs/index.md`?
98
122
 
99
123
  If any check fails, revise and re-run this phase before proceeding.
100
124
 
101
- ### Phase 7: Write Files
125
+ ### Phase 8: Write Files
102
126
 
103
127
  1. Create the XDR file at `.xdrs/[scope]/[type]/[subject]/[number]-[short-title].md`.
104
128
  2. Add an entry to `.xdrs/[scope]/[type]/index.md` (create the file if it does not exist).
@@ -111,4 +135,5 @@ If any check fails, revise and re-run this phase before proceeding.
111
135
  - MUST follow the XDR template from `001-xdr-standards` exactly.
112
136
  - MUST NOT add personal opinions or general best-practice content not tied to a decision.
113
137
  - MUST NOT create an XDR that duplicates a decision already captured in another XDR — extend or reference instead.
138
+ - MUST prefer links and short references over repeating the same decision content across related documents.
114
139
  - MUST keep scope `_local` unless the user explicitly states otherwise.
@@ -47,7 +47,8 @@ Quick test:
47
47
 
48
48
  1. List `.xdrs/[scope]/[type]/[subject]/skills/` for existing skills. If one already covers the goal, extend or reference it instead of creating a duplicate.
49
49
  2. Read all XDRs relevant to the skill's domain to collect rules and cross-references.
50
- 3. Decide whether the skill is merely guidance or is being referenced by an XDR as a mandatory procedure. Do not encode policy in the skill unless it comes from a referenced XDR.
50
+ 3. Evaluate XDR metadata before operationalizing those rules. `Status:` decides whether a decision is eligible to be used, and omitted `Status:` means `Active`; `Valid:` decides whether that active decision is in force at the current moment, `Applied to:` decides whether it fits the intended task context, and the decision text defines any remaining boundaries. Keep inactive, out-of-window, or out-of-scope XDRs as background only.
51
+ 4. Decide whether the skill is merely guidance or is being referenced by an XDR as a mandatory procedure. Do not encode policy in the skill unless it comes from a referenced XDR.
51
52
 
52
53
  ### Phase 4: Write the SKILL.md
53
54
 
@@ -92,6 +93,9 @@ Rules:
92
93
  - Mention tools or prerequisites when they are required to complete the task reliably.
93
94
  - Do not duplicate content from referenced XDRs — link instead.
94
95
  - Do not present the skill itself as policy; mandatory behavior must come from referenced XDRs or other policy artifacts.
96
+ - When the skill depends on XDRs, make the activation logic and instructions consistent with the XDR metadata so the skill does not operationalize inactive or out-of-scope decisions.
97
+ - Prefer plain Markdown, tables, or ASCII art for simple structure, flow, layout, or relationship indications.
98
+ - If `SKILL.md` genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/skills/[number]-[skill-name]/assets/` and link with a relative path.
95
99
  - No emojis. Lowercase filenames. Target under 500 lines.
96
100
 
97
101
  ### Phase 5: Review the Draft
@@ -1,11 +1,7 @@
1
1
  ---
2
2
  name: 004-write-article
3
3
  description: >
4
- Creates a new article document following XDR article standards: selects scope, type, subject, and number;
5
- then writes a focused synthetic text that combines and links multiple XDRs, Research documents,
6
- and Skills around a topic.
7
- Activate this skill when the user asks to create, add, or write a new article, guide, or overview document
8
- within an XDR project.
4
+ Creates a new article document following XDR article standards: selects scope, type, subject, and number; then writes a focused synthetic text that combines and links multiple XDRs, Research documents, and Skills around a topic. Activate this skill when the user asks to create, add, or write a new article, guide, or overview document within an XDR project.
9
5
  metadata:
10
6
  author: flaviostutz
11
7
  version: "1.0"
@@ -47,8 +43,9 @@ If the article spans more than one subject, place it in `principles`.
47
43
  ### Phase 4: Research XDRs and Skills to Synthesize
48
44
 
49
45
  1. Read all XDRs, Research documents, and Skills relevant to the article topic across all scopes listed in `.xdrs/index.md`.
50
- 2. Identify the key points a reader needs to understand the topic end-to-end.
51
- 3. Collect XDR IDs and file paths for cross-references. Never copy decision text verbatim; link to it.
46
+ 2. Evaluate XDR metadata before synthesizing guidance. Use `Status:` to determine whether a decision is eligible to be current guidance, treating omitted `Status:` as `Active`; use `Valid:` to determine whether that active decision is in force for the article's time horizon, `Applied to:` to determine whether it fits the audience or context being discussed, and the decision text itself for any remaining applicability boundaries.
47
+ 3. Identify the key points a reader needs to understand the topic end-to-end.
48
+ 4. Collect XDR IDs and file paths for cross-references. Never copy decision text verbatim; link to it.
52
49
 
53
50
  ### Phase 5: Write the Article
54
51
 
@@ -75,7 +72,10 @@ Rules to apply while drafting:
75
72
 
76
73
  - Write for the stated audience; avoid jargon unexplained elsewhere.
77
74
  - Every factual claim must link back to the authoritative XDR or Skill.
75
+ - If the article advises readers what to do, clearly separate active/applicable XDRs from background, historical, or out-of-scope ones.
78
76
  - Never reproduce decision text verbatim; summarize and link.
77
+ - Prefer plain Markdown, tables, or ASCII art for simple structure, flow, layout, or relationship indications.
78
+ - If the article genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/articles/assets/` and link with a relative path.
79
79
  - Keep the article under 150 lines; move detailed content to XDRs or Skills.
80
80
  - Use lowercase file names. Never use emojis.
81
81
  - If a conflict exists between the article and a Decision Record, note it and defer to the XDR.
@@ -113,6 +113,6 @@ Rules to apply while drafting:
113
113
 
114
114
  ## References
115
115
 
116
- - [_core-adr-004 - Article standards](../../004-article-standards.md)
117
- - [_core-adr-006 - Research standards](../../006-research-standards.md)
118
- - [_core-adr-001 - XDR standards](../../001-xdr-standards.md)
116
+ - [_core-adr-004 - Article standards](../../../.xdrs/_core/adrs/principles/004-article-standards.md)
117
+ - [_core-adr-006 - Research standards](../../../.xdrs/_core/adrs/principles/006-research-standards.md)
118
+ - [_core-adr-001 - XDR standards](../../../.xdrs/_core/adrs/principles/001-xdr-standards.md)
@@ -2,24 +2,29 @@
2
2
  name: 005-write-research
3
3
  description: >
4
4
  Creates a new research document following XDR research standards: selects scope, type, subject, and number;
5
- then writes a focused study of constraints, findings, and option proposals with pros and cons.
5
+ then writes an IMRAD-based study with enough evidence and method detail to stand on its own as a technical paper.
6
6
  Activate this skill when the user asks to create, add, or write a research document that backs a decision.
7
7
  metadata:
8
8
  author: flaviostutz
9
- version: "1.0"
9
+ version: "1.3"
10
10
  ---
11
11
 
12
12
  ## Overview
13
13
 
14
- Guides the creation of a well-structured research document by following `_core-adr-006`, checking related XDRs and existing research to avoid duplication, and producing a concise study that supports a decision lifecycle without replacing the XDR.
14
+ Guides the creation of a well-structured research document by following `_core-adr-006`, checking related XDRs and existing research to avoid duplication, and producing an IMRAD-based study that reads as a standalone technical paper. Treat each section goal in the research template as an acceptance criterion, not as optional wording. Do not assume missing direction, evidence, or intended follow-up; ask the user explicitly before proceeding when those points are not already concrete.
15
15
 
16
16
  ## Instructions
17
17
 
18
18
  ### Phase 1: Understand the Research Goal
19
19
 
20
20
  1. Read `.xdrs/_core/adrs/principles/006-research-standards.md` in full to internalize the folder layout, numbering rules, and mandatory template.
21
- 2. Identify the problem or question being explored, the main constraints or requirements, and which decision or decision threads this research supports.
22
- 3. Do NOT proceed without a clear problem statement and at least one concrete constraint or requirement.
21
+ 2. Ask the user to confirm the intended direction of the research before planning the document: what decision, question, or option space the study should support, what boundaries or exclusions apply, and what kind of outcome they expect.
22
+ 3. Ask the user what evidence already exists and what evidence-gathering methods are acceptable if the current evidence is incomplete. Do not invent facts, sources, or confidence that the user did not provide.
23
+ 4. Ask the user what the proposed next step is after the research, such as writing a new XDR, updating an existing XDR, informing a discussion, or documenting trade-offs for later. Use that answer to shape the framing without turning the research into the final decision.
24
+ 5. Identify the problem or question being explored, the relevant system or domain context, the likely technical audience, and why the subject matters in practice.
25
+ 6. Internalize the goal of each required section before drafting: `Abstract` gives a quick technical reader the question, method, main result, and takeaway, `Introduction` frames the investigated problem and context, `Methods` makes the important parts reproducible, `Results` records raw findings with minimal interpretation, `Discussion` interprets the findings, `Conclusion` summarizes the practical takeaway and boundaries, and `References` makes sources traceable.
26
+ 7. Collect the main constraints, known facts, important experiences, gaps, and assumptions that belong in the introduction.
27
+ 8. Do NOT proceed without a clear problem statement, a central question, explicit user direction, an understood next step, and at least one credible source of evidence or a method for generating it. If any of these are ambiguous, stop and ask instead of assuming.
23
28
 
24
29
  ### Phase 2: Select Scope, Type, Subject, and Number
25
30
 
@@ -38,69 +43,187 @@ Guides the creation of a well-structured research document by following `_core-a
38
43
  3. Read related skills or articles if they contain context, implementation limits, or terminology that must be reflected.
39
44
  4. Collect links that should appear in the final `## References` section.
40
45
 
41
- ### Phase 4: Write the Research Document
46
+ ### Phase 4: Create the Skeleton and Frame the Study
47
+
48
+ 1. Create the final section skeleton in the research file before running the study: `Abstract`, `Introduction`, `Methods`, `Results`, `Discussion`, `Conclusion`, `References`.
49
+ 2. Write a one-line note under each section heading capturing that section's goal before filling in the content so the draft stays disciplined.
50
+ 3. Draft `## Introduction` early so the problem, scope, constraints, assumptions, and central question are fixed before evidence collection expands.
51
+ 4. Draft `## Methods` before or while executing the study so tools, data sources, and conditions are captured while they are still precise.
52
+ 5. Treat `## Abstract` as a late-stage summary. Do not try to finalize it yet.
53
+ 6. Keep process framing out of the body. If related ADRs or repository context matter, push that traceability to `## References` unless it is essential to the technical question itself.
54
+
55
+ ### Phase 5: Capture Evidence as the Study Runs
56
+
57
+ 1. As experiments, comparisons, code spikes, interviews, benchmarks, or document reviews happen, append the concrete findings to `## Results` continuously.
58
+ 2. Prefer capturing tables, bullet points, numbers, code outputs, and option comparisons while the evidence is fresh.
59
+ 3. If multiple options solve the same problem, add a comparison table and explicit pros and cons for each option in `## Results` so the trade-offs are directly inspectable.
60
+ 4. Update `## Methods` whenever the actual study design changes so the final document remains reproducible.
61
+ 5. Keep interpretation out of `## Results`; record observations first and save meaning-making for `## Discussion`.
62
+
63
+ ### Phase 6: Synthesize After Results Stabilize
64
+
65
+ 1. Write `## Discussion` only after the important findings are visible in `## Results`.
66
+ 2. Use `## Discussion` to interpret significance, trade-offs, limitations, implications, and performance considerations for technical readers.
67
+ 3. Write `## Conclusion` after the discussion so it reflects the actual findings, practical takeaway, applicability boundaries, and open questions.
68
+ 4. Write `## Abstract` last so it accurately summarizes the final goal, methods, results, and conclusion for quick technical readers.
69
+
70
+ ### Phase 7: Write the Research Document
42
71
 
43
72
  Use the mandatory template from `006-research-standards`:
44
73
 
45
74
  ```markdown
46
75
  # [scope]-research-[number]: [Short Title]
47
76
 
48
- ## Overview
77
+ ## Abstract
49
78
 
50
- [Brief description of the problem or question, audience, and decision thread(s) it supports.]
79
+ [Single paragraph summarizing the goal, methods, results, and conclusion. Goal: let a quick technical reader understand the question, method, main result, and takeaway. Under 200 words.]
51
80
 
52
- Question: [Central question of the research]?
53
-
54
- ## Constraints
81
+ ## Introduction
55
82
 
56
- - [Constraint 1]
83
+ [Describe the problem, context, constraints, known facts, experiences, gaps, assumptions, and objectives.
84
+ Use visuals, bullets, graphs, or diagrams when helpful. Goal: explain the investigated problem, operating context, constraints, and why the subject matters. Under 700 words.]
57
85
 
58
- ## Findings
86
+ Question: [Central question of the research]?
59
87
 
60
- - [Finding 1]
88
+ ## Methods
61
89
 
62
- ## Proposals
90
+ [Explain how the study was conducted, including design, tools, data sources, and test conditions.
91
+ Include enough detail for an experienced professional to reproduce the relevant parts. Goal: make the important parts of the study reproducible. Under 1200 words.]
63
92
 
64
- ### Option 1: [Name]
93
+ ## Results
65
94
 
66
- [Short description]
95
+ [Report findings, data, trends, quantitative results, code artifacts, and option comparisons.
96
+ Use figures, tables, or bullets when useful. 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.]
67
97
 
68
- **Pros**
69
- - [Benefit]
98
+ ## Discussion
70
99
 
71
- **Cons**
72
- - [Drawback]
100
+ [Interpret the results, explain significance, trade-offs, performance considerations, limitations, and implications. Goal: interpret the findings for technical readers. Keep this section technically engaged and under 1000 words.]
73
101
 
74
- ## Recommendation
102
+ ## Conclusion
75
103
 
76
- [Optional preferred direction]
104
+ [Summarize the main findings, practical takeaway, applicability boundaries, and important open questions. Goal: summarize the main findings and what they mean in practice. Under 400 words.]
77
105
 
78
106
  ## References
107
+
108
+ [A list of all cited literature, websites, tutorials, documentation, discussions, and related artifacts. Goal: make all cited sources and supporting artifacts traceable.]
109
+
110
+ - [Related XDR or artifact](relative/path.md) - Why it matters
111
+ - [Another related XDR if this research informed multiple decisions](relative/path.md) - Why it matters
79
112
  ```
80
113
 
81
114
  Rules:
82
- - Focus on exploring options under stated constraints; do not turn the document into the final decision.
83
- - End the `## Overview` section with `Question: [central question]?` so the main research question is explicit.
84
- - Make it explicit when the same research may feed multiple downstream XDRs.
85
- - Include a few meaningful proposals and summarize pros and cons for each.
86
- - Keep findings concrete and useful for later discussion or revision.
87
- - Keep the document under 2000 lines. Prefer much shorter when possible.
88
- - Treat `Research` as the artifact name; `researches/` is only the folder name.
89
- - Use lowercase file names. Never use emojis.
115
+ - Treat the goal sentence of each section as a hard check on what belongs in that section.
116
+ - Focus on exploring and evidencing the problem space; do not turn the document into the final decision.
117
+ - Write as a standalone technical paper for readers who do not know the XDR process.
118
+ - Keep mentions of future ADRs, decision lifecycle, repository process, or artifact management out of the body unless they are materially necessary to understand the research question.
119
+ - Keep traceability to related XDRs, skills, articles, discussions, and external sources primarily in `## References`.
120
+ - Use good-enough evidence. Experienced professional judgment is allowed, but the conclusions still need support that other colleagues can inspect and learn from.
121
+ - Ensure the methods and test conditions are reproducible enough for an experienced professional to rerun or evolve the critical parts later.
122
+ - Prefer plain Markdown, bullet points, tables, or ASCII art for simple explanations and comparisons, especially in the introduction and results.
123
+ - If the research genuinely needs local images or supporting files, store them in `.xdrs/[scope]/[type]/[subject]/researches/assets/` and link with a relative path.
124
+ - 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.
125
+
126
+ ### Phase 8: Check Section Goals
127
+
128
+ Before the final review, verify each section against its specific goal:
129
+
130
+ 1. **Abstract goal**: Does it let a quick technical reader understand the question, method, main result, and takeaway, in one paragraph and under 200 words?
131
+ 2. **Introduction goal**: Does it explain the investigated problem and context, stay within scope, and end with `Question: ...?`?
132
+ 3. **Methods goal**: Could an experienced professional reproduce the important parts that materially affect the conclusion?
133
+ 4. **Results goal**: Are the findings concrete and minimally interpreted, with comparisons and pros/cons when multiple options exist?
134
+ 5. **Discussion goal**: Does it interpret the findings rather than repeat the results?
135
+ 6. **Conclusion goal**: Does it summarize the main findings, practical takeaway, applicability boundaries, and open questions without introducing new evidence?
136
+ 7. **References goal**: Are cited sources and related artifacts traceable, including related XDRs, skills, articles, and research where relevant?
137
+
138
+ If any section fails its goal, revise that section before continuing.
139
+
140
+ ### Phase 9: Check Word Counts and Ratios
141
+
142
+ Before the final review, run a word-count pass over the draft and verify that the main body roughly follows the standard proportion `Introduction : Methods : Results : Discussion ≈ 3 : 5 : 6 : 4`.
143
+
144
+ 1. Count words by top-level `##` section after stripping Markdown syntax so lists, tables, and links count as prose rather than punctuation.
145
+ 2. Compare only `Introduction`, `Methods`, `Results`, and `Discussion` for the ratio check.
146
+ 3. Use these target shares of the main body: `Introduction = 16.7%`, `Methods = 27.8%`, `Results = 33.3%`, `Discussion = 22.2%`.
147
+ 4. Treat any section as out of ratio when its share differs by more than 25% from its target share, unless the `## Introduction` explicitly justifies a very detailed or intentionally unbalanced analysis.
148
+ 5. If the ratio check fails, rebalance the draft before final review instead of accepting the imbalance silently.
149
+ 6. Use this Python script when you need a fast deterministic check:
150
+
151
+ ```python
152
+ from pathlib import Path
153
+ import re
154
+
155
+ path = Path(".xdrs/[scope]/[type]/[subject]/researches/[number]-[short-title].md")
156
+ text = path.read_text(encoding="utf-8")
157
+
158
+ sections = {}
159
+ current = None
160
+ for line in text.splitlines():
161
+ if line.startswith("## "):
162
+ current = line[3:].strip()
163
+ sections[current] = []
164
+ continue
165
+ if line.startswith("# "):
166
+ continue
167
+ if current is not None:
168
+ sections[current].append(line)
169
+
170
+
171
+ def count_words(markdown: str) -> int:
172
+ cleaned = markdown
173
+ cleaned = re.sub(r"^\|(?:\s*[-:]+\s*\|)+\s*$", " ", cleaned, flags=re.M)
174
+ cleaned = re.sub(r"```[\s\S]*?```", " ", cleaned)
175
+ cleaned = re.sub(r"`([^`]*)`", r"\1", cleaned)
176
+ cleaned = re.sub(r"!\[([^\]]*)\]\([^)]*\)", r"\1", cleaned)
177
+ cleaned = re.sub(r"\[([^\]]+)\]\([^)]*\)", r"\1", cleaned)
178
+ cleaned = re.sub(r"^#+\s+", "", cleaned, flags=re.M)
179
+ cleaned = re.sub(r"[|*_>#-]", " ", cleaned)
180
+ cleaned = re.sub(r"[^\w'’]+", " ", cleaned, flags=re.UNICODE)
181
+ words = cleaned.strip().split()
182
+ return len(words)
183
+
184
+
185
+ targets = {
186
+ "Introduction": 3,
187
+ "Methods": 5,
188
+ "Results": 6,
189
+ "Discussion": 4,
190
+ }
191
+
192
+ counts = {name: count_words("\n".join(lines)) for name, lines in sections.items()}
193
+ total_words = sum(counts.values())
194
+ body_total = sum(counts.get(name, 0) for name in targets)
195
+ target_weight_total = sum(targets.values())
196
+
197
+ print(f"TOTAL\t{total_words}")
198
+ for name, count in counts.items():
199
+ print(f"{name}\t{count}")
200
+
201
+ print("\nRATIO CHECK")
202
+ for name, weight in targets.items():
203
+ actual_share = counts.get(name, 0) / body_total if body_total else 0
204
+ target_share = weight / target_weight_total
205
+ delta = ((actual_share - target_share) / target_share) if target_share else 0
206
+ status = "OK" if abs(delta) <= 0.25 else "REVISE"
207
+ print(
208
+ f"{name}: actual={actual_share:.1%} target={target_share:.1%} delta={delta:+.1%} {status}"
209
+ )
210
+ ```
90
211
 
91
- ### Phase 5: Review the Draft
212
+ ### Phase 10: Review the Draft
92
213
 
93
214
  Before writing files, verify:
94
215
 
95
216
  1. **Problem clarity**: Is the research question explicit?
96
- 2. **Constraints**: Are the most important constraints stated clearly?
97
- 3. **Option quality**: Do the proposals represent real alternatives with non-trivial pros and cons?
98
- 4. **Decision boundary**: Does the text support a decision without pretending to be the XDR itself?
99
- 5. **References**: Are all related XDRs, research docs, skills, or articles linked, including multiple decisions when applicable?
217
+ 2. **Section discipline**: Does each section contain the right kind of content with minimal duplication?
218
+ 3. **Method quality**: Could an experienced professional reproduce or extend the important parts of the study from the methods section?
219
+ 4. **Evidence quality**: Are the results concrete enough to support the discussion and conclusion?
220
+ 5. **Standalone focus**: Does the text read as a technical paper rather than commentary about future ADRs, repository process, or artifact management?
221
+ 6. **Ratio fit**: Does the document stay within section word limits and pass the Python ratio check, or does the introduction explicitly justify the deviation?
222
+ 7. **References**: Are all related XDRs, research docs, skills, articles, and external sources linked when relevant?
100
223
 
101
224
  If any check fails, revise before continuing.
102
225
 
103
- ### Phase 6: Write Files
226
+ ### Phase 11: Write Files
104
227
 
105
228
  1. Create the research file at `.xdrs/[scope]/[type]/[subject]/researches/[number]-[short-title].md`.
106
229
  2. Add an entry to `.xdrs/[scope]/[type]/index.md`.
@@ -115,15 +238,16 @@ If any check fails, revise before continuing.
115
238
  2. Choose type `adrs` and subject `principles`.
116
239
  3. Scan `.xdrs/_local/adrs/principles/researches/` for the next number.
117
240
  4. Read related XDRs about packaging and versioning.
118
- 5. Write a research document with constraints, findings, and options such as npm package, git submodule, and copy-paste distribution.
241
+ 5. Write an IMRAD-based research document comparing options such as npm package, git submodule, and copy-paste distribution, with the comparison grounded in methods and results.
119
242
  6. Add references to the resulting XDR if a decision is later created.
120
243
 
121
244
  ## Edge Cases
122
245
 
123
246
  - If the user is really asking for a final decision, write an XDR instead of research.
124
- - If only one viable option exists, still record why alternatives were excluded or unavailable.
125
- - If the document grows too large, split independent problem threads into separate research files.
126
- - If the supported decision does not exist yet, reference the decision topic or planned XDR title in the overview.
247
+ - If only one viable option exists, still explain what was evaluated, what was ruled out, or what constraints removed the alternatives.
248
+ - If the document grows too large, split independent problem threads into separate research files unless the introduction explicitly justifies a longer study.
249
+ - If the supported decision does not exist yet, reference the decision topic or planned XDR title in the introduction and conclusion.
250
+ - If the user's direction, evidence base, or intended next step is vague, ask follow-up questions and wait for clarification instead of choosing a path yourself.
127
251
 
128
252
  ## References
129
253
 
package/README.md CHANGED
@@ -14,11 +14,13 @@ This project defines a standard for organizing XDRs that satisfies the following
14
14
 
15
15
  Every XDR package contains four types of documents:
16
16
 
17
- - **Decision Records (XDRs)** — Architectural (ADR), Business (BDR), or Engineering (EDR) records that capture a single decision, its rationale, and the rules that follow from it. They are the source of truth.
17
+ - **Decision Records (XDRs)** — Architectural (ADR), Business (BDR), or Engineering (EDR) records that capture a single decision, its rationale, and the rules that follow from it. They are the source of truth. An XDR may optionally start with a `Metadata` section for short status, validity-window, and applicability markers, and readers should use that metadata to decide whether the decision is currently in force for their case. If `Status:` is omitted, treat the decision as `Active` by default.
18
18
  - **Research** — Exploratory documents that capture the problem being investigated, constraints or requirements, findings, and option tradeoffs that back a decision during its lifecycle. One research document may inform multiple downstream decisions, but it is not a replacement for the Decision Record.
19
19
  - **Skills** — Step-by-step procedural guides that can be followed by humans, AI agents, or both. Skills are task-based artifacts with a concrete outcome and should include enough detail to verify the task was completed correctly. A skill may start as a fully manual procedure and evolve toward partial or full AI automation over time. Co-located with the XDRs they implement.
20
20
  - **Articles** — Synthetic explanatory texts that combine information from multiple XDRs, Research documents, and Skills around a specific topic or audience. They never replace XDRs as source of truth.
21
21
 
22
+ For simple indications, prefer plain Markdown, tables, or ASCII art. Use local images and other supporting files only when they are materially necessary, and keep them in a sibling `assets/` folder next to the document file.
23
+
22
24
  ## Getting started
23
25
 
24
26
  1. Create a new project workspace
@@ -55,6 +57,8 @@ The `lint` command reads `./.xdrs/**` from the given workspace path and checks c
55
57
  - research numbering uniqueness per `scope/type/subject/researches`
56
58
  - canonical index presence and link consistency
57
59
  - root index coverage for all discovered canonical indexes
60
+ - XDR metadata section placement and `Status` / `Valid` / `Applied to` field format
61
+ - local image and `assets/` links resolving inside the sibling `assets/` folder for each document
58
62
 
59
63
  Examples:
60
64
 
@@ -89,6 +93,7 @@ The folder layout, file naming, and document format are designed so that AI agen
89
93
  - Each XDR is a small, focused Markdown file (target under 100 lines), covering one decision.
90
94
  - The canonical index per scope and type lists all XDRs with short descriptions, enabling agents to identify relevant records without reading every file.
91
95
  - The root index at `.xdrs/index.md` provides a single entry point for discovery.
96
+ - XDR metadata gives agents a first-pass filter: check `Status` first, treating an omitted `Status` as `Active`; then check `Valid`, then `Applied to`, and finally the decision text itself to confirm the decision should be used in the current context.
92
97
  - Decisions cross-reference each other by XDR ID rather than duplicating content, keeping individual files concise.
93
98
  - Subject folders reduce the search space when a query maps to a known domain.
94
99
 
@@ -108,13 +113,17 @@ This is especially important for BDRs: because business rules govern decisions t
108
113
  index.md # canonical index for this scope+type
109
114
  [subject]/
110
115
  [number]-[short-title].md # individual decision record
116
+ assets/ # optional local resources for subject-level XDR files
111
117
  researches/ # optional decision-backing research documents
112
118
  [number]-[short-title].md
119
+ assets/
113
120
  skills/ # optional skill packages for humans and AI agents
114
121
  [number]-[skill-name]/
115
122
  SKILL.md
123
+ assets/
116
124
  articles/ # optional synthetic views over XDRs, Research, and Skills
117
125
  [number]-[short-title].md
126
+ assets/
118
127
  ```
119
128
 
120
129
  Document types:
@@ -143,7 +152,7 @@ Each scope manages its own set of XDR artifacts independently. Scope owners disc
143
152
 
144
153
  Once a set of decisions is ready to share, scope owners pack the relevant `.xdrs/[scope]/` folder into a versioned npm package using a tool such as [filedist](https://github.com/flaviostutz/filedist) and publish it to an npm registry, either public or a company-internal one. Versioning gives consumers explicit control over which revision of a scope's decisions they adopt, avoiding situations where a single breaking policy change is forced on all consumers at once.
145
154
 
146
- The same applies to Research documents and skills: because they live alongside XDRs inside the scope folder, they are included in the same package and published together.
155
+ The same applies to Research documents, skills, articles, and any sibling `assets/` folders: because they live alongside XDRs inside the scope folder, they are included in the same package and published together.
147
156
 
148
157
  ### Usage
149
158
 
package/lib/lint.js CHANGED
@@ -22,6 +22,8 @@ const NUMBERED_FILE_RE = /^(\d{3,})-([a-z0-9-]+)\.md$/;
22
22
  const NUMBERED_DIR_RE = /^(\d{3,})-([a-z0-9-]+)$/;
23
23
  const REQUIRED_ROOT_INDEX_TEXT = 'XDRs in scopes listed last override the ones listed first';
24
24
  const SUBJECT_ARTIFACT_DIRS = new Set(['skills', 'articles', 'researches']);
25
+ const RESOURCE_DIR_NAME = 'assets';
26
+ const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.bmp']);
25
27
 
26
28
  function runLintCli(args) {
27
29
  if (args.includes('--help') || args.includes('-h')) {
@@ -191,6 +193,9 @@ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrNum
191
193
  const entryPath = path.join(subjectPath, entry.name);
192
194
 
193
195
  if (entry.isDirectory()) {
196
+ if (entry.name === RESOURCE_DIR_NAME) {
197
+ continue;
198
+ }
194
199
  if (entry.name === 'skills') {
195
200
  artifacts.push(...lintSkillsDirectory(xdrsRoot, scopeName, typeName, subjectName, entryPath, errors));
196
201
  continue;
@@ -245,6 +250,147 @@ function lintXdrFile(xdrsRoot, scopeName, typeName, filePath, xdrNumbers, errors
245
250
  if (!firstLine.startsWith(expectedHeader)) {
246
251
  errors.push(`XDR title must start with "${expectedHeader}": ${toDisplayPath(filePath)}`);
247
252
  }
253
+
254
+ lintXdrMetadata(content, filePath, errors);
255
+ lintDocumentResourceLinks(filePath, errors);
256
+ }
257
+
258
+ function lintXdrMetadata(content, filePath, errors) {
259
+ const lines = content.split(/\r?\n/);
260
+ const ignoredLines = findIgnoredMarkdownLines(lines);
261
+ const metadataLine = findHeadingLine(lines, ignoredLines, '## Metadata');
262
+ const contextLine = findHeadingLine(lines, ignoredLines, '## Context and Problem Statement');
263
+ const headingLines = findHeadingLines(lines, ignoredLines);
264
+
265
+ if (metadataLine !== -1) {
266
+ const nextHeadingLine = headingLines.find((lineIndex) => lineIndex > metadataLine);
267
+ if (nextHeadingLine !== contextLine) {
268
+ errors.push(`XDR metadata section must appear immediately before Context and Problem Statement: ${toDisplayPath(filePath)}`);
269
+ }
270
+ }
271
+
272
+ if (metadataLine !== -1 && contextLine !== -1 && metadataLine > contextLine) {
273
+ errors.push(`XDR metadata section must appear before Context and Problem Statement: ${toDisplayPath(filePath)}`);
274
+ }
275
+
276
+ const metadataRange = metadataLine === -1
277
+ ? null
278
+ : {
279
+ start: metadataLine + 1,
280
+ end: (headingLines.find((lineIndex) => lineIndex > metadataLine) ?? lines.length) - 1
281
+ };
282
+ const statusLineNumbers = findFieldLines(lines, ignoredLines, 'Status:');
283
+ const appliedLineNumbers = findFieldLines(lines, ignoredLines, 'Applied to:');
284
+ const validLineNumbers = findFieldLines(lines, ignoredLines, 'Valid:');
285
+
286
+ if (!metadataRange && (statusLineNumbers.length > 0 || appliedLineNumbers.length > 0 || validLineNumbers.length > 0)) {
287
+ errors.push(`XDR metadata fields require a ## Metadata section immediately before Context and Problem Statement: ${toDisplayPath(filePath)}`);
288
+ return;
289
+ }
290
+
291
+ if (!metadataRange) {
292
+ return;
293
+ }
294
+
295
+ const metadataStatus = statusLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
296
+ const metadataApplied = appliedLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
297
+ const metadataValid = validLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
298
+
299
+ if (metadataStatus.length === 0 && metadataApplied.length === 0 && metadataValid.length === 0) {
300
+ errors.push(`XDR metadata section must be omitted when no metadata fields are defined: ${toDisplayPath(filePath)}`);
301
+ }
302
+
303
+ if (metadataStatus.length > 1) {
304
+ errors.push(`XDR metadata must not repeat Status: ${toDisplayPath(filePath)}`);
305
+ }
306
+
307
+ if (metadataApplied.length > 1) {
308
+ errors.push(`XDR metadata must not repeat Applied to: ${toDisplayPath(filePath)}`);
309
+ }
310
+
311
+ if (metadataValid.length > 1) {
312
+ errors.push(`XDR metadata must not repeat Valid: ${toDisplayPath(filePath)}`);
313
+ }
314
+
315
+ for (const lineIndex of [...statusLineNumbers, ...appliedLineNumbers, ...validLineNumbers]) {
316
+ if (!isLineInsideRange(lineIndex, metadataRange)) {
317
+ errors.push(`XDR metadata fields must be declared inside ## Metadata: ${toDisplayPath(filePath)}`);
318
+ break;
319
+ }
320
+ }
321
+
322
+ let previousFieldOrder = -1;
323
+ for (let lineIndex = metadataRange.start; lineIndex <= metadataRange.end; lineIndex += 1) {
324
+ if (ignoredLines[lineIndex]) {
325
+ continue;
326
+ }
327
+ const trimmed = lines[lineIndex].trim();
328
+ if (trimmed === '') {
329
+ continue;
330
+ }
331
+ const currentFieldOrder = trimmed.startsWith('Status:')
332
+ ? 0
333
+ : trimmed.startsWith('Valid:')
334
+ ? 1
335
+ : trimmed.startsWith('Applied to:')
336
+ ? 2
337
+ : -1;
338
+ if (currentFieldOrder === -1) {
339
+ errors.push(`XDR metadata section only supports Status:, Valid:, and Applied to: fields: ${toDisplayPath(filePath)}`);
340
+ break;
341
+ }
342
+ if (currentFieldOrder < previousFieldOrder) {
343
+ errors.push(`XDR metadata fields must be ordered as Status:, Valid:, Applied to: ${toDisplayPath(filePath)}`);
344
+ break;
345
+ }
346
+ previousFieldOrder = currentFieldOrder;
347
+ }
348
+
349
+ if (metadataStatus.length === 1) {
350
+ lintStatusField(lines[metadataStatus[0]], filePath, errors);
351
+ }
352
+
353
+ if (metadataApplied.length === 1) {
354
+ const value = lines[metadataApplied[0]].slice('Applied to:'.length).trim();
355
+ if (value === '') {
356
+ errors.push(`XDR Applied to: must not be empty: ${toDisplayPath(filePath)}`);
357
+ } else if (countWords(value) >= 40) {
358
+ errors.push(`XDR Applied to: must be under 40 words: ${toDisplayPath(filePath)}`);
359
+ }
360
+ }
361
+
362
+ if (metadataValid.length === 1) {
363
+ lintValidField(lines[metadataValid[0]], filePath, errors);
364
+ }
365
+ }
366
+
367
+ function lintStatusField(line, filePath, errors) {
368
+ const value = line.slice('Status:'.length).trim().replace(/\.$/, '');
369
+
370
+ if (value !== 'Draft' && value !== 'Active' && value !== 'Deprecated') {
371
+ errors.push(`XDR Status: must be Draft, Active, or Deprecated: ${toDisplayPath(filePath)}`);
372
+ }
373
+ }
374
+
375
+ function lintValidField(line, filePath, errors) {
376
+ const value = line.slice('Valid:'.length).trim().replace(/\.$/, '');
377
+
378
+ const validMatch = value.match(/^(?:from\s+(\d{4}-\d{2}-\d{2})(?:\s+until\s+(\d{4}-\d{2}-\d{2}))?|until\s+(\d{4}-\d{2}-\d{2}))$/);
379
+ if (!validMatch) {
380
+ errors.push(`XDR Valid: must be from YYYY-MM-DD, until YYYY-MM-DD, or from YYYY-MM-DD until YYYY-MM-DD: ${toDisplayPath(filePath)}`);
381
+ return;
382
+ }
383
+
384
+ const fromDate = validMatch[1];
385
+ const untilDate = validMatch[2] ?? validMatch[3];
386
+ if ((fromDate && !isIsoDate(fromDate)) || (untilDate && !isIsoDate(untilDate))) {
387
+ errors.push(`XDR Valid: must use ISO dates in YYYY-MM-DD format: ${toDisplayPath(filePath)}`);
388
+ return;
389
+ }
390
+
391
+ if (fromDate && untilDate && fromDate > untilDate) {
392
+ errors.push(`XDR Valid: from date must be on or before until date: ${toDisplayPath(filePath)}`);
393
+ }
248
394
  }
249
395
 
250
396
  function lintSkillsDirectory(xdrsRoot, scopeName, typeName, subjectName, skillsPath, errors) {
@@ -292,6 +438,8 @@ function lintSkillsDirectory(xdrsRoot, scopeName, typeName, subjectName, skillsP
292
438
  } else if (frontmatterName !== entry.name) {
293
439
  errors.push(`Skill frontmatter name must match package directory "${entry.name}": ${toDisplayPath(skillFilePath)}`);
294
440
  }
441
+
442
+ lintDocumentResourceLinks(skillFilePath, errors);
295
443
  }
296
444
 
297
445
  return artifacts;
@@ -304,6 +452,10 @@ function lintArticlesDirectory(xdrsRoot, scopeName, typeName, subjectName, artic
304
452
 
305
453
  for (const entry of entries) {
306
454
  const entryPath = path.join(articlesPath, entry.name);
455
+ if (entry.isDirectory() && entry.name === RESOURCE_DIR_NAME) {
456
+ continue;
457
+ }
458
+
307
459
  if (!entry.isFile()) {
308
460
  errors.push(`Unexpected directory in articles folder: ${toDisplayPath(entryPath)}`);
309
461
  continue;
@@ -335,6 +487,8 @@ function lintArticlesDirectory(xdrsRoot, scopeName, typeName, subjectName, artic
335
487
  if (!firstLine.startsWith(expectedHeader)) {
336
488
  errors.push(`Article title must start with "${expectedHeader}": ${toDisplayPath(entryPath)}`);
337
489
  }
490
+
491
+ lintDocumentResourceLinks(entryPath, errors);
338
492
  }
339
493
 
340
494
  return artifacts;
@@ -347,6 +501,10 @@ function lintResearchDirectory(xdrsRoot, scopeName, typeName, subjectName, resea
347
501
 
348
502
  for (const entry of entries) {
349
503
  const entryPath = path.join(researchPath, entry.name);
504
+ if (entry.isDirectory() && entry.name === RESOURCE_DIR_NAME) {
505
+ continue;
506
+ }
507
+
350
508
  if (!entry.isFile()) {
351
509
  errors.push(`Unexpected directory in researches folder: ${toDisplayPath(entryPath)}`);
352
510
  continue;
@@ -378,6 +536,8 @@ function lintResearchDirectory(xdrsRoot, scopeName, typeName, subjectName, resea
378
536
  if (!firstLine.startsWith(expectedHeader)) {
379
537
  errors.push(`Research title must start with "${expectedHeader}": ${toDisplayPath(entryPath)}`);
380
538
  }
539
+
540
+ lintDocumentResourceLinks(entryPath, errors);
381
541
  }
382
542
 
383
543
  return artifacts;
@@ -404,15 +564,43 @@ function lintTypeIndex(indexPath, xdrsRoot, artifacts, errors) {
404
564
  }
405
565
  }
406
566
 
567
+ function lintDocumentResourceLinks(documentPath, errors) {
568
+ const content = fs.readFileSync(documentPath, 'utf8');
569
+ const documentDir = path.dirname(documentPath);
570
+ const resourceDir = path.join(documentDir, RESOURCE_DIR_NAME);
571
+
572
+ for (const link of parseLocalLinkTargets(content, documentDir)) {
573
+ if (!shouldValidateResourceLink(link.rawTarget)) {
574
+ continue;
575
+ }
576
+
577
+ if (!fs.existsSync(link.resolvedPath)) {
578
+ errors.push(`Broken asset link in ${toDisplayPath(documentPath)}: ${link.rawTarget}`);
579
+ continue;
580
+ }
581
+
582
+ if (!isPathInside(resourceDir, link.resolvedPath)) {
583
+ errors.push(`Asset links in ${toDisplayPath(documentPath)} must point to ${toDisplayPath(resourceDir)}: ${link.rawTarget}`);
584
+ }
585
+ }
586
+ }
587
+
407
588
  function parseLocalLinks(markdown, baseDir) {
589
+ return parseLocalLinkTargets(markdown, baseDir).map((link) => link.resolvedPath);
590
+ }
591
+
592
+ function parseLocalLinkTargets(markdown, baseDir) {
408
593
  const links = [];
409
- const linkRe = /\[[^\]]+\]\(([^)]+)\)/g;
594
+ const linkRe = /!?\[[^\]]+\]\(([^)]+)\)/g;
410
595
  let match = linkRe.exec(markdown);
411
596
  while (match) {
412
597
  const rawTarget = match[1].trim();
413
598
  if (isLocalLink(rawTarget)) {
414
599
  const targetWithoutAnchor = rawTarget.split('#')[0];
415
- links.push(path.resolve(baseDir, targetWithoutAnchor));
600
+ links.push({
601
+ rawTarget,
602
+ resolvedPath: path.resolve(baseDir, targetWithoutAnchor)
603
+ });
416
604
  }
417
605
  match = linkRe.exec(markdown);
418
606
  }
@@ -432,6 +620,17 @@ function isCanonicalTypeIndex(filePath, xdrsRoot) {
432
620
  return relative.length === 3 && TYPE_NAMES.has(relative[1]) && relative[2] === 'index.md';
433
621
  }
434
622
 
623
+ function shouldValidateResourceLink(rawTarget) {
624
+ const targetWithoutAnchor = rawTarget.split('#')[0];
625
+ const normalizedTarget = targetWithoutAnchor.replace(/\\/g, '/');
626
+ const extension = path.extname(targetWithoutAnchor).toLowerCase();
627
+
628
+ return normalizedTarget === RESOURCE_DIR_NAME
629
+ || normalizedTarget.startsWith(`${RESOURCE_DIR_NAME}/`)
630
+ || normalizedTarget.includes(`/${RESOURCE_DIR_NAME}/`)
631
+ || IMAGE_EXTENSIONS.has(extension);
632
+ }
633
+
435
634
  function extractFrontmatterName(content) {
436
635
  const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
437
636
  if (!frontmatterMatch) {
@@ -442,6 +641,82 @@ function extractFrontmatterName(content) {
442
641
  return nameMatch ? nameMatch[1].trim() : null;
443
642
  }
444
643
 
644
+ function findIgnoredMarkdownLines(lines) {
645
+ const ignored = [];
646
+ let inCodeFence = false;
647
+
648
+ for (let index = 0; index < lines.length; index += 1) {
649
+ const trimmed = lines[index].trim();
650
+ if (/^```/.test(trimmed)) {
651
+ ignored[index] = true;
652
+ inCodeFence = !inCodeFence;
653
+ continue;
654
+ }
655
+
656
+ ignored[index] = inCodeFence;
657
+ }
658
+
659
+ return ignored;
660
+ }
661
+
662
+ function findHeadingLine(lines, ignoredLines, headingText) {
663
+ for (let index = 0; index < lines.length; index += 1) {
664
+ if (ignoredLines[index]) {
665
+ continue;
666
+ }
667
+ if (lines[index].trim() === headingText) {
668
+ return index;
669
+ }
670
+ }
671
+ return -1;
672
+ }
673
+
674
+ function findHeadingLines(lines, ignoredLines) {
675
+ const result = [];
676
+ for (let index = 0; index < lines.length; index += 1) {
677
+ if (ignoredLines[index]) {
678
+ continue;
679
+ }
680
+ if (/^##\s+/.test(lines[index].trim())) {
681
+ result.push(index);
682
+ }
683
+ }
684
+ return result;
685
+ }
686
+
687
+ function findFieldLines(lines, ignoredLines, prefix) {
688
+ const result = [];
689
+ for (let index = 0; index < lines.length; index += 1) {
690
+ if (ignoredLines[index]) {
691
+ continue;
692
+ }
693
+ if (lines[index].trim().startsWith(prefix)) {
694
+ result.push(index);
695
+ }
696
+ }
697
+ return result;
698
+ }
699
+
700
+ function isLineInsideRange(lineIndex, range) {
701
+ return lineIndex >= range.start && lineIndex <= range.end;
702
+ }
703
+
704
+ function countWords(value) {
705
+ return value.split(/\s+/).filter(Boolean).length;
706
+ }
707
+
708
+ function isIsoDate(value) {
709
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
710
+ return false;
711
+ }
712
+
713
+ const [year, month, day] = value.split('-').map(Number);
714
+ const date = new Date(Date.UTC(year, month - 1, day));
715
+ return date.getUTCFullYear() === year
716
+ && date.getUTCMonth() === month - 1
717
+ && date.getUTCDate() === day;
718
+ }
719
+
445
720
  function firstNonEmptyLine(content) {
446
721
  const lines = content.split(/\r?\n/);
447
722
  for (const line of lines) {
@@ -500,6 +775,11 @@ function normalizePath(filePath) {
500
775
  return path.normalize(filePath);
501
776
  }
502
777
 
778
+ function isPathInside(parentPath, childPath) {
779
+ const relative = path.relative(parentPath, childPath);
780
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
781
+ }
782
+
503
783
  module.exports = {
504
784
  runLintCli,
505
785
  lintWorkspace
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "A standard way to organize Decision Records (XDRs) across scopes, subjects, and teams so that AI agents can reliably query and follow them.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,8 @@
14
14
  ],
15
15
  "license": "MIT",
16
16
  "files": [
17
- ".xdrs/**",
17
+ ".xdrs/_core/**",
18
+ ".xdrs/index.md",
18
19
  "package.json",
19
20
  "AGENTS.md",
20
21
  "bin/filedist.js",