xdrs-core 0.9.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.
- package/.xdrs/_core/adrs/principles/001-xdr-standards.md +15 -6
- package/.xdrs/_core/adrs/principles/003-skill-standards.md +1 -0
- package/.xdrs/_core/adrs/principles/004-article-standards.md +1 -0
- package/.xdrs/_core/adrs/principles/articles/001-xdrs-overview.md +11 -0
- package/.xdrs/_core/adrs/principles/skills/001-lint/SKILL.md +10 -6
- package/.xdrs/_core/adrs/principles/skills/002-write-xdr/SKILL.md +7 -5
- package/.xdrs/_core/adrs/principles/skills/003-write-skill/SKILL.md +3 -1
- package/.xdrs/_core/adrs/principles/skills/004-write-article/SKILL.md +7 -5
- package/README.md +3 -2
- package/lib/lint.js +49 -22
- package/package.json +1 -1
|
@@ -25,8 +25,15 @@ Provides clear ownership by scope, predictable navigation, and reusable decision
|
|
|
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
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
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.
|
|
28
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`
|
|
29
|
-
|
|
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.
|
|
30
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.
|
|
31
38
|
- Make it clear if an instruction is mandatory or advisory
|
|
32
39
|
- Mandatory language: "must", "always", "never", "required", "mandatory"
|
|
@@ -56,7 +63,7 @@ Provides clear ownership by scope, predictable navigation, and reusable decision
|
|
|
56
63
|
- Types in IDs: `adr`, `bdr`, `edr`
|
|
57
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.
|
|
58
65
|
- Decisions MUST be concise and reference other XDRs to avoid duplication
|
|
59
|
-
- The `### Implementation Details` section SHOULD state relevant boundaries or exceptions and what a reader should do or avoid in common cases. Use `## Metadata` for
|
|
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.
|
|
60
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.
|
|
61
68
|
- When research exists for a decision, the XDR SHOULD mention the related research documents after the `## Considered Options` list.
|
|
62
69
|
- Never use emojis in contents
|
|
@@ -85,9 +92,10 @@ All XDRs MUST follow this template
|
|
|
85
92
|
|
|
86
93
|
## Metadata
|
|
87
94
|
|
|
88
|
-
[Optional section. Omit the entire section when
|
|
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`]
|
|
89
98
|
Applied to: [Optional short applicability scope, under 40 words]
|
|
90
|
-
Validity: [Optional. Use `Draft`, `Retired`, `from YYYY-MM-DD`, `until YYYY-MM-DD`, or `from YYYY-MM-DD until YYYY-MM-DD`]
|
|
91
99
|
|
|
92
100
|
## Context and Problem Statement
|
|
93
101
|
|
|
@@ -141,9 +149,10 @@ Question: In the end, state explicitly the question that needs to be answered. E
|
|
|
141
149
|
- `.xdrs/business-x/adrs/governance/010-security-and-secrets-management.md`
|
|
142
150
|
- `.xdrs/_core/adrs/devops/001-multi-repo.md`
|
|
143
151
|
- Metadata examples:
|
|
152
|
+
- `Status: Draft`
|
|
153
|
+
- `Status: Active`
|
|
154
|
+
- `Valid: from 2026-03-01 until 2026-12-31`
|
|
144
155
|
- `Applied to: JavaScript projects`
|
|
145
|
-
- `Validity: Draft`
|
|
146
|
-
- `Validity: from 2026-03-01 until 2026-12-31`
|
|
147
156
|
|
|
148
157
|
```text
|
|
149
158
|
subject/
|
|
@@ -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:
|
|
@@ -17,6 +17,7 @@ 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`.
|
|
22
23
|
- For simple structure, flow, layout, or relationship indications, articles SHOULD prefer plain Markdown, tables, or ASCII art instead of external assets.
|
|
@@ -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
|
|
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.
|
|
@@ -84,6 +88,6 @@ Scope: [scope identifier]
|
|
|
84
88
|
|
|
85
89
|
## References
|
|
86
90
|
|
|
87
|
-
- [_core-adr-001 - XDR standards](
|
|
88
|
-
- [_core-adr-003 - Skill standards](
|
|
91
|
+
- [_core-adr-001 - XDR standards](../../001-xdr-standards.md)
|
|
92
|
+
- [_core-adr-003 - Skill standards](../../003-skill-standards.md)
|
|
89
93
|
|
|
@@ -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, checking redundancy across related artifacts, and iterating until the document is concise and decision
|
|
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
|
|
|
@@ -71,8 +71,9 @@ Use the mandatory template from `001-xdr-standards`:
|
|
|
71
71
|
|
|
72
72
|
## Metadata
|
|
73
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]
|
|
74
76
|
Applied to: [Optional short applicability scope, under 40 words]
|
|
75
|
-
Validity: [Optional. Use Draft, Retired, from YYYY-MM-DD, until YYYY-MM-DD, or from YYYY-MM-DD until YYYY-MM-DD]
|
|
76
77
|
|
|
77
78
|
## Context and Problem Statement
|
|
78
79
|
[4 lines max: background, who is impacted, and the explicit question being answered]
|
|
@@ -93,9 +94,10 @@ Validity: [Optional. Use Draft, Retired, from YYYY-MM-DD, until YYYY-MM-DD, or f
|
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
Mandatory rules to apply while drafting:
|
|
96
|
-
- Include `## Metadata` only when `
|
|
97
|
+
- Include `## Metadata` only when `Status:`, `Valid:`, and/or `Applied to:` adds value; omit the whole section when none of those fields is defined.
|
|
97
98
|
- When present, place `## Metadata` immediately before `## Context and Problem Statement`.
|
|
98
|
-
- Keep `Applied to:` under 40 words
|
|
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.
|
|
99
101
|
- Use mandatory language ("must", "always", "never") only for hard requirements; use advisory language ("should", "recommended") for guidance.
|
|
100
102
|
- Do not duplicate content already in referenced XDRs — link instead.
|
|
101
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.
|
|
@@ -111,7 +113,7 @@ Mandatory rules to apply while drafting:
|
|
|
111
113
|
Check every item before finalizing:
|
|
112
114
|
|
|
113
115
|
1. **Length**: Is it under 100 lines? Trim verbose explanations. Move detailed skills to a separate file and link.
|
|
114
|
-
2. **Metadata**: If metadata exists, is it directly before Context, limited to `
|
|
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?
|
|
115
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.
|
|
116
118
|
4. **Clarity**: Is the chosen option unambiguous? Is the "why" clear in one reading?
|
|
117
119
|
5. **Redundancy**: Is the XDR the primary source for the decision itself, with related documents linked instead of duplicated wherever possible?
|
|
@@ -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.
|
|
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,7 @@ 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.
|
|
95
97
|
- Prefer plain Markdown, tables, or ASCII art for simple structure, flow, layout, or relationship indications.
|
|
96
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.
|
|
97
99
|
- No emojis. Lowercase filenames. Target under 500 lines.
|
|
@@ -43,8 +43,9 @@ If the article spans more than one subject, place it in `principles`.
|
|
|
43
43
|
### Phase 4: Research XDRs and Skills to Synthesize
|
|
44
44
|
|
|
45
45
|
1. Read all XDRs, Research documents, and Skills relevant to the article topic across all scopes listed in `.xdrs/index.md`.
|
|
46
|
-
2.
|
|
47
|
-
3.
|
|
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.
|
|
48
49
|
|
|
49
50
|
### Phase 5: Write the Article
|
|
50
51
|
|
|
@@ -71,6 +72,7 @@ Rules to apply while drafting:
|
|
|
71
72
|
|
|
72
73
|
- Write for the stated audience; avoid jargon unexplained elsewhere.
|
|
73
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.
|
|
74
76
|
- Never reproduce decision text verbatim; summarize and link.
|
|
75
77
|
- Prefer plain Markdown, tables, or ASCII art for simple structure, flow, layout, or relationship indications.
|
|
76
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.
|
|
@@ -111,6 +113,6 @@ Rules to apply while drafting:
|
|
|
111
113
|
|
|
112
114
|
## References
|
|
113
115
|
|
|
114
|
-
- [_core-adr-004 - Article standards](
|
|
115
|
-
- [_core-adr-006 - Research standards](
|
|
116
|
-
- [_core-adr-001 - XDR standards](
|
|
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)
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ 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. An XDR may optionally start with a `Metadata` section for short applicability and
|
|
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.
|
|
@@ -57,7 +57,7 @@ The `lint` command reads `./.xdrs/**` from the given workspace path and checks c
|
|
|
57
57
|
- research numbering uniqueness per `scope/type/subject/researches`
|
|
58
58
|
- canonical index presence and link consistency
|
|
59
59
|
- root index coverage for all discovered canonical indexes
|
|
60
|
-
- XDR metadata section placement and `
|
|
60
|
+
- XDR metadata section placement and `Status` / `Valid` / `Applied to` field format
|
|
61
61
|
- local image and `assets/` links resolving inside the sibling `assets/` folder for each document
|
|
62
62
|
|
|
63
63
|
Examples:
|
|
@@ -93,6 +93,7 @@ The folder layout, file naming, and document format are designed so that AI agen
|
|
|
93
93
|
- Each XDR is a small, focused Markdown file (target under 100 lines), covering one decision.
|
|
94
94
|
- The canonical index per scope and type lists all XDRs with short descriptions, enabling agents to identify relevant records without reading every file.
|
|
95
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.
|
|
96
97
|
- Decisions cross-reference each other by XDR ID rather than duplicating content, keeping individual files concise.
|
|
97
98
|
- Subject folders reduce the search space when a query maps to a known domain.
|
|
98
99
|
|
package/lib/lint.js
CHANGED
|
@@ -279,10 +279,11 @@ function lintXdrMetadata(content, filePath, errors) {
|
|
|
279
279
|
start: metadataLine + 1,
|
|
280
280
|
end: (headingLines.find((lineIndex) => lineIndex > metadataLine) ?? lines.length) - 1
|
|
281
281
|
};
|
|
282
|
+
const statusLineNumbers = findFieldLines(lines, ignoredLines, 'Status:');
|
|
282
283
|
const appliedLineNumbers = findFieldLines(lines, ignoredLines, 'Applied to:');
|
|
283
|
-
const
|
|
284
|
+
const validLineNumbers = findFieldLines(lines, ignoredLines, 'Valid:');
|
|
284
285
|
|
|
285
|
-
if (!metadataRange && (appliedLineNumbers.length > 0 ||
|
|
286
|
+
if (!metadataRange && (statusLineNumbers.length > 0 || appliedLineNumbers.length > 0 || validLineNumbers.length > 0)) {
|
|
286
287
|
errors.push(`XDR metadata fields require a ## Metadata section immediately before Context and Problem Statement: ${toDisplayPath(filePath)}`);
|
|
287
288
|
return;
|
|
288
289
|
}
|
|
@@ -291,28 +292,34 @@ function lintXdrMetadata(content, filePath, errors) {
|
|
|
291
292
|
return;
|
|
292
293
|
}
|
|
293
294
|
|
|
295
|
+
const metadataStatus = statusLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
|
|
294
296
|
const metadataApplied = appliedLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
|
|
295
|
-
const
|
|
297
|
+
const metadataValid = validLineNumbers.filter((lineIndex) => isLineInsideRange(lineIndex, metadataRange));
|
|
296
298
|
|
|
297
|
-
if (metadataApplied.length === 0 &&
|
|
299
|
+
if (metadataStatus.length === 0 && metadataApplied.length === 0 && metadataValid.length === 0) {
|
|
298
300
|
errors.push(`XDR metadata section must be omitted when no metadata fields are defined: ${toDisplayPath(filePath)}`);
|
|
299
301
|
}
|
|
300
302
|
|
|
303
|
+
if (metadataStatus.length > 1) {
|
|
304
|
+
errors.push(`XDR metadata must not repeat Status: ${toDisplayPath(filePath)}`);
|
|
305
|
+
}
|
|
306
|
+
|
|
301
307
|
if (metadataApplied.length > 1) {
|
|
302
308
|
errors.push(`XDR metadata must not repeat Applied to: ${toDisplayPath(filePath)}`);
|
|
303
309
|
}
|
|
304
310
|
|
|
305
|
-
if (
|
|
306
|
-
errors.push(`XDR metadata must not repeat
|
|
311
|
+
if (metadataValid.length > 1) {
|
|
312
|
+
errors.push(`XDR metadata must not repeat Valid: ${toDisplayPath(filePath)}`);
|
|
307
313
|
}
|
|
308
314
|
|
|
309
|
-
for (const lineIndex of [...appliedLineNumbers, ...
|
|
315
|
+
for (const lineIndex of [...statusLineNumbers, ...appliedLineNumbers, ...validLineNumbers]) {
|
|
310
316
|
if (!isLineInsideRange(lineIndex, metadataRange)) {
|
|
311
317
|
errors.push(`XDR metadata fields must be declared inside ## Metadata: ${toDisplayPath(filePath)}`);
|
|
312
318
|
break;
|
|
313
319
|
}
|
|
314
320
|
}
|
|
315
321
|
|
|
322
|
+
let previousFieldOrder = -1;
|
|
316
323
|
for (let lineIndex = metadataRange.start; lineIndex <= metadataRange.end; lineIndex += 1) {
|
|
317
324
|
if (ignoredLines[lineIndex]) {
|
|
318
325
|
continue;
|
|
@@ -321,10 +328,26 @@ function lintXdrMetadata(content, filePath, errors) {
|
|
|
321
328
|
if (trimmed === '') {
|
|
322
329
|
continue;
|
|
323
330
|
}
|
|
324
|
-
|
|
325
|
-
|
|
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)}`);
|
|
326
340
|
break;
|
|
327
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);
|
|
328
351
|
}
|
|
329
352
|
|
|
330
353
|
if (metadataApplied.length === 1) {
|
|
@@ -336,33 +359,37 @@ function lintXdrMetadata(content, filePath, errors) {
|
|
|
336
359
|
}
|
|
337
360
|
}
|
|
338
361
|
|
|
339
|
-
if (
|
|
340
|
-
|
|
362
|
+
if (metadataValid.length === 1) {
|
|
363
|
+
lintValidField(lines[metadataValid[0]], filePath, errors);
|
|
341
364
|
}
|
|
342
365
|
}
|
|
343
366
|
|
|
344
|
-
function
|
|
345
|
-
const value = line.slice('
|
|
367
|
+
function lintStatusField(line, filePath, errors) {
|
|
368
|
+
const value = line.slice('Status:'.length).trim().replace(/\.$/, '');
|
|
346
369
|
|
|
347
|
-
if (value
|
|
348
|
-
|
|
370
|
+
if (value !== 'Draft' && value !== 'Active' && value !== 'Deprecated') {
|
|
371
|
+
errors.push(`XDR Status: must be Draft, Active, or Deprecated: ${toDisplayPath(filePath)}`);
|
|
349
372
|
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function lintValidField(line, filePath, errors) {
|
|
376
|
+
const value = line.slice('Valid:'.length).trim().replace(/\.$/, '');
|
|
350
377
|
|
|
351
|
-
const
|
|
352
|
-
if (!
|
|
353
|
-
errors.push(`XDR
|
|
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)}`);
|
|
354
381
|
return;
|
|
355
382
|
}
|
|
356
383
|
|
|
357
|
-
const fromDate =
|
|
358
|
-
const untilDate =
|
|
384
|
+
const fromDate = validMatch[1];
|
|
385
|
+
const untilDate = validMatch[2] ?? validMatch[3];
|
|
359
386
|
if ((fromDate && !isIsoDate(fromDate)) || (untilDate && !isIsoDate(untilDate))) {
|
|
360
|
-
errors.push(`XDR
|
|
387
|
+
errors.push(`XDR Valid: must use ISO dates in YYYY-MM-DD format: ${toDisplayPath(filePath)}`);
|
|
361
388
|
return;
|
|
362
389
|
}
|
|
363
390
|
|
|
364
391
|
if (fromDate && untilDate && fromDate > untilDate) {
|
|
365
|
-
errors.push(`XDR
|
|
392
|
+
errors.push(`XDR Valid: from date must be on or before until date: ${toDisplayPath(filePath)}`);
|
|
366
393
|
}
|
|
367
394
|
}
|
|
368
395
|
|
package/package.json
CHANGED