xdrs-core 0.47.0 → 0.48.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/lib/lint.test.js CHANGED
@@ -3340,18 +3340,185 @@ test('reports emoji in research document', () => {
3340
3340
  expect(result.errors.join('\n')).toContain('Research must not contain emojis');
3341
3341
  });
3342
3342
 
3343
- test('reports emoji in plan document', () => {
3344
- const workspaceRoot = createWorkspace('plan-emoji', {
3343
+ test('reports emoji in initiative document', () => {
3344
+ const workspaceRoot = createWorkspace('initiative-emoji', {
3345
3345
  '.xdrs/index.md': rootIndex(),
3346
3346
  '.xdrs/_local/adrs/index.md': localAdrIndex([
3347
- '- [001-myplan](principles/plans/001-myplan.md) - My plan'
3347
+ '- [001-myinitiative](principles/initiatives/001-myinitiative.md) - My initiative'
3348
3348
  ]),
3349
- '.xdrs/_local/adrs/principles/plans/001-myplan.md': planDocument('Great plan \uD83C\uDFAF'),
3349
+ '.xdrs/_local/adrs/principles/initiatives/001-myinitiative.md': initiativeDocument('Great initiative \uD83C\uDFAF'),
3350
3350
  });
3351
3351
 
3352
3352
  const result = lintWorkspace(workspaceRoot);
3353
3353
 
3354
- expect(result.errors.join('\n')).toContain('Plan must not contain emojis');
3354
+ expect(result.errors.join('\n')).toContain('Initiative must not contain emojis');
3355
+ });
3356
+
3357
+ test('reports invalid initiative file name', () => {
3358
+ const workspaceRoot = createWorkspace('initiative-invalid-name', {
3359
+ '.xdrs/index.md': rootIndex(),
3360
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3361
+ '- [myinitiative](principles/initiatives/myinitiative.md) - My initiative'
3362
+ ]),
3363
+ '.xdrs/_local/adrs/principles/initiatives/myinitiative.md': initiativeDocument('Body text.'),
3364
+ });
3365
+
3366
+ const result = lintWorkspace(workspaceRoot);
3367
+
3368
+ expect(result.errors.join('\n')).toContain('Invalid initiative file name');
3369
+ });
3370
+
3371
+ test('reports invalid initiative file name for uppercase characters', () => {
3372
+ const workspaceRoot = createWorkspace('initiative-uppercase-name', {
3373
+ '.xdrs/index.md': rootIndex(),
3374
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3375
+ '- [001-MyInitiative](principles/initiatives/001-MyInitiative.md) - My initiative'
3376
+ ]),
3377
+ '.xdrs/_local/adrs/principles/initiatives/001-MyInitiative.md': initiativeDocument('Body text.'),
3378
+ });
3379
+
3380
+ const result = lintWorkspace(workspaceRoot);
3381
+
3382
+ expect(result.errors.join('\n')).toContain('Invalid initiative file name');
3383
+ });
3384
+
3385
+ test('reports duplicate initiative number', () => {
3386
+ const workspaceRoot = createWorkspace('initiative-duplicate-number', {
3387
+ '.xdrs/index.md': rootIndex(),
3388
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3389
+ '- [001-first](principles/initiatives/001-first.md) - First initiative',
3390
+ '- [001-second](principles/initiatives/001-second.md) - Second initiative'
3391
+ ]),
3392
+ '.xdrs/_local/adrs/principles/initiatives/001-first.md': initiativeDocument('First body.'),
3393
+ '.xdrs/_local/adrs/principles/initiatives/001-second.md': initiativeDocument('Second body.'),
3394
+ });
3395
+
3396
+ const result = lintWorkspace(workspaceRoot);
3397
+
3398
+ expect(result.errors.join('\n')).toContain('Duplicate initiative number 001');
3399
+ });
3400
+
3401
+ test('reports initiative title not matching expected header format', () => {
3402
+ const workspaceRoot = createWorkspace('initiative-bad-header', {
3403
+ '.xdrs/index.md': rootIndex(),
3404
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3405
+ '- [001-myinitiative](principles/initiatives/001-myinitiative.md) - My initiative'
3406
+ ]),
3407
+ '.xdrs/_local/adrs/principles/initiatives/001-myinitiative.md': [
3408
+ '# Wrong header',
3409
+ '',
3410
+ '## Executive Summary',
3411
+ '',
3412
+ 'Summary.',
3413
+ '',
3414
+ '## Context and Problem Statement',
3415
+ '',
3416
+ 'Body.',
3417
+ '',
3418
+ '## Proposed Solution',
3419
+ '',
3420
+ 'We will fix it.',
3421
+ '',
3422
+ 'Expected end date: 2026-12-31',
3423
+ ''
3424
+ ].join('\n'),
3425
+ });
3426
+
3427
+ const result = lintWorkspace(workspaceRoot);
3428
+
3429
+ expect(result.errors.join('\n')).toContain('Initiative title must start with "# _local-adr-initiative-001:"');
3430
+ });
3431
+
3432
+ test('reports missing Expected end date in initiative document', () => {
3433
+ const workspaceRoot = createWorkspace('initiative-missing-end-date', {
3434
+ '.xdrs/index.md': rootIndex(),
3435
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3436
+ '- [001-myinitiative](principles/initiatives/001-myinitiative.md) - My initiative'
3437
+ ]),
3438
+ '.xdrs/_local/adrs/principles/initiatives/001-myinitiative.md': [
3439
+ '# _local-adr-initiative-001: My initiative',
3440
+ '',
3441
+ '## Executive Summary',
3442
+ '',
3443
+ 'Summary.',
3444
+ '',
3445
+ '## Context and Problem Statement',
3446
+ '',
3447
+ 'Body.',
3448
+ '',
3449
+ '## Proposed Solution',
3450
+ '',
3451
+ 'We will fix it.',
3452
+ ''
3453
+ ].join('\n'),
3454
+ });
3455
+
3456
+ const result = lintWorkspace(workspaceRoot);
3457
+
3458
+ expect(result.errors.join('\n')).toContain('Initiative must include an Expected end date: field');
3459
+ });
3460
+
3461
+ test('reports duplicate Expected end date in initiative document', () => {
3462
+ const workspaceRoot = createWorkspace('initiative-duplicate-end-date', {
3463
+ '.xdrs/index.md': rootIndex(),
3464
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3465
+ '- [001-myinitiative](principles/initiatives/001-myinitiative.md) - My initiative'
3466
+ ]),
3467
+ '.xdrs/_local/adrs/principles/initiatives/001-myinitiative.md': [
3468
+ '# _local-adr-initiative-001: My initiative',
3469
+ '',
3470
+ '## Executive Summary',
3471
+ '',
3472
+ 'Summary.',
3473
+ '',
3474
+ '## Context and Problem Statement',
3475
+ '',
3476
+ 'Body.',
3477
+ '',
3478
+ '## Proposed Solution',
3479
+ '',
3480
+ 'We will fix it.',
3481
+ '',
3482
+ 'Expected end date: 2026-12-31',
3483
+ 'Expected end date: 2027-01-15',
3484
+ ''
3485
+ ].join('\n'),
3486
+ });
3487
+
3488
+ const result = lintWorkspace(workspaceRoot);
3489
+
3490
+ expect(result.errors.join('\n')).toContain('Initiative must not repeat Expected end date');
3491
+ });
3492
+
3493
+ test('reports invalid Expected end date format in initiative document', () => {
3494
+ const workspaceRoot = createWorkspace('initiative-invalid-end-date', {
3495
+ '.xdrs/index.md': rootIndex(),
3496
+ '.xdrs/_local/adrs/index.md': localAdrIndex([
3497
+ '- [001-myinitiative](principles/initiatives/001-myinitiative.md) - My initiative'
3498
+ ]),
3499
+ '.xdrs/_local/adrs/principles/initiatives/001-myinitiative.md': [
3500
+ '# _local-adr-initiative-001: My initiative',
3501
+ '',
3502
+ '## Executive Summary',
3503
+ '',
3504
+ 'Summary.',
3505
+ '',
3506
+ '## Context and Problem Statement',
3507
+ '',
3508
+ 'Body.',
3509
+ '',
3510
+ '## Proposed Solution',
3511
+ '',
3512
+ 'We will fix it.',
3513
+ '',
3514
+ 'Expected end date: 12/31/2026',
3515
+ ''
3516
+ ].join('\n'),
3517
+ });
3518
+
3519
+ const result = lintWorkspace(workspaceRoot);
3520
+
3521
+ expect(result.errors.join('\n')).toContain('Initiative Expected end date: must be a valid ISO date');
3355
3522
  });
3356
3523
 
3357
3524
  // ─── Name / description length ────────────────────────────────────────────────
@@ -3819,9 +3986,9 @@ function researchDocument(introBody, questionLine) {
3819
3986
  ].join('\n');
3820
3987
  }
3821
3988
 
3822
- function planDocument(body) {
3989
+ function initiativeDocument(body) {
3823
3990
  return [
3824
- '# _local-adr-plan-001: My plan',
3991
+ '# _local-adr-initiative-001: My initiative',
3825
3992
  '',
3826
3993
  '## Executive Summary',
3827
3994
  '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "A framework to structure, compile and distribute Architectural (ADR), Business (BDR), and Engineering (EDR) decision records contents so that AI agents and humans can reliably find and use them with hierarchical scopes and controlled rollout in the format of distributable versioned packages.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,140 +0,0 @@
1
- ---
2
- name: _core-adr-policy-007-plan-standards
3
- description: Defines plan document standards for describing problems, solutions, and activities. Use when creating or reviewing plans.
4
- apply-to: All plan documents
5
- valid-from: 2025-01-01
6
- ---
7
-
8
- # _core-adr-policy-007: Plan standards
9
-
10
- ## Context and Problem Statement
11
-
12
- Teams need a structured way to describe a problem, propose a solution, and lay out the approach and activities needed to solve it. Without a standard format, planning documents drift in structure and completeness, making it hard to assess scope, track progress, and verify that a plan was fully implemented.
13
-
14
- How should plans be structured and organized so they provide clear guidance for execution while remaining connected to the decisions, research, and skills they relate to?
15
-
16
- ## Decision Outcome
17
-
18
- **Subject-level ephemeral plan documents co-located with Policies**
19
-
20
- Plans are Markdown documents placed inside a subject folder alongside policies. They describe a problem, a proposed solution, and the approach to solve it. Plans have a clear start and end and a well-defined scope.
21
-
22
- ### Details
23
-
24
- - Plans describe a problem (why), what we will do to solve the problem, and the approach and activities needed to solve it (how).
25
- - Plans are NOT the source of truth. When a plan and a Policy disagree, the Policy takes precedence.
26
- - Plans are ephemeral. They MUST be deleted after full implementation. The lasting outputs of a plan are actual actions or Decisions, Skills, Articles, Research documents, and other artifacts that result from execution.
27
- - Plans MAY be used to implement a certain Decision. They MAY also use Research documents to help with the planning process. Articles MAY be written on top of a plan to give more context and connect more details present in other decisions and research to people involved in the plan.
28
- - During the implementation of a plan, new Decisions, Articles, Skills, Research documents, and even other Plans MAY be created. All related elements MUST be linked to each other.
29
- - A plan can be high level, describing only one milestone, or more complex, describing a WBS (work breakdown structure) along with owners, multiple milestones in a tactical sequence, and checklists to verify completeness. Actual tasks performed by actors SHOULD be tracked in specialized software such as GitHub or Azure DevOps.
30
- - The total time to deliver a plan SHOULD NOT be more than 2 years. If more time is needed, create a new plan later with what was learned.
31
- - Plans MUST live under `plans/` inside the relevant subject folder: `.xdrs/[scope]/[type]/[subject]/plans/[number]-[short-title].md`
32
- - The `[subject]` component MUST be one of the allowed subjects for the chosen type. The required list of allowed subjects per type is defined in `_core-adr-policy-001`.
33
- - Plans MUST include an `Expected end date:` field in ISO format (YYYY-MM-DD) inside the `## Proposed Solution` section.
34
- - File names MUST be lowercase.
35
- - MUST NOT use emojis in plan content.
36
- - For diagram format preferences and non-Markdown asset rules, see [`_core-adr-policy-020`](020-media-and-asset-standards.md).
37
-
38
- **Folder layout**
39
-
40
- ```
41
- .xdrs/
42
- [scope]/
43
- [type]/
44
- [subject]/
45
- plans/
46
- [number]-[short-title].md
47
- .assets/
48
- ```
49
-
50
- Examples:
51
- - `.xdrs/_local/adrs/principles/plans/001-checkout-performance.md`
52
- - `.xdrs/business-x/bdrs/product/plans/002-onboarding-redesign.md`
53
-
54
- **Plan numbering**
55
-
56
- - Each plan has a number unique within its `scope/type/subject/plans/` namespace.
57
- - Determine the next number by checking the highest number already present in that namespace.
58
- - MUST NOT reuse numbers of deleted plans. Gaps in the sequence are expected and allowed.
59
-
60
- **Plan template**
61
-
62
- All plans MUST follow this template:
63
-
64
- ```markdown
65
- # [scope]-[type]-plan-[number]: [Short Title]
66
-
67
- ## Executive Summary
68
-
69
- [Required. A summary of all sections below using bullet points, focused on the most important items. Under 500 words.]
70
-
71
- ## Context and Problem Statement
72
-
73
- [Required. Describe clearly why we are executing this plan. What is the impact? Who is impacted? Why is this important? Under 200 words.
74
- E.g.: Our checkout abandon rate is 50%, and it's increasing over time.]
75
-
76
- ## Proposed Solution
77
-
78
- [Required. What we expect to achieve to solve the problem described above. Under 200 words.
79
- E.g.: Reduce payment time in our App by 30% and fix the 3 most impactful bugs.]
80
-
81
- Expected end date: YYYY-MM-DD
82
-
83
- ## Acceptance Criteria
84
-
85
- [Optional. Used to make it clear what the expected result is and to create a way to verify when the goal is achieved. May include a short checklist. Under 100 words.]
86
-
87
- ## Approach
88
-
89
- [Optional. High level description about how to achieve the result and the strategy used, including how to engage people, projects, organize the work, how to learn unknowns, deal with risks, and distribute workload. May include a WBS with the hierarchy of the work. Under 300 words.]
90
-
91
- ## Key Deliverables
92
-
93
- [Optional. List of the main features, goods, artifacts, data, articles, skills, decisions, training, programs, events etc that will be important to achieve the expected result. Under 300 words.]
94
-
95
- ## Key Resources
96
-
97
- [Optional. List of equipment, people, other project results, budget, areas or dependencies that need to be engaged or allocated for this plan to be implemented. Under 100 words.]
98
-
99
- ## Milestones
100
-
101
- [Optional. List of goals to be followed along with an optional acceptance criteria, owner and due date. Each milestone may have a checklist used as acceptance criteria verification. Key tasks and risks can be listed as part of a milestone. Under 1000 words per milestone.]
102
-
103
- ### Milestone 1: [Title]
104
- Owner: [name or team]
105
- Due date: YYYY-MM-DD
106
-
107
- [Description of the milestone goal.]
108
-
109
- **Acceptance checklist:** [optional]
110
- - [ ] [Criterion 1]
111
- - [ ] [Criterion 2]
112
-
113
- **Key tasks:**
114
- - [Task description]
115
-
116
- **Risks:** [optional]
117
- - [Risk description] — Mitigation: [strategy]
118
-
119
- ## Risks Identified
120
-
121
- [Optional. List of risks along with a short description and mitigation strategy. Under 1000 words.]
122
-
123
- ## References
124
-
125
- - [Related Policy or artifact](relative/path.md) - Brief description of relevance
126
- ```
127
-
128
- ## Considered Options
129
-
130
- * (REJECTED) **Inline planning in Policies** — Embed planning details inside policies.
131
- * Reason: Plans are ephemeral execution documents while Policies are lasting decisions. Mixing them bloats Policies and creates confusion about what to delete after execution.
132
- * (CHOSEN) **Subject-level plans folder co-located with Policies** — Keeps plans alongside the decisions they implement, with clear lifecycle expectations.
133
- * Reason: Consistent with how skills, articles, and research are organized. The explicit deletion requirement after implementation keeps the document base clean.
134
-
135
- ## References
136
-
137
- - [_core-adr-policy-001 - XDRS standards](001-xdrs-standards.md) - Framework elements: types, scopes, subjects, folder structure
138
- - [_core-adr-policy-004 - Article standards](004-article-standards.md) - Companion artifact type for synthetic views
139
- - [_core-adr-policy-006 - Research standards](006-research-standards.md) - Companion artifact type for exploratory evidence
140
- - [006-write-plan skill](skills/006-write-plan/SKILL.md) - Step-by-step instructions for creating a new plan