xdrs-core 0.14.3 → 0.14.5

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.
@@ -39,6 +39,8 @@ Place a skill under the XDR type that matches the nature of the activity the ski
39
39
  - **ADR skills** - architectural evaluation, pattern compliance checks, technology selection guidance (e.g. how to review an architecture diagram, how to assess API design)
40
40
  - **BDR skills** - business process execution, market analysis, operations procedures, business rules
41
41
 
42
+ The `[subject]` component in the folder path MUST be one of the allowed subjects for the chosen type. The required list of allowed subjects per type is defined in `_core-adr-001`.
43
+
42
44
  Quick test:
43
45
  - "Is the skill about *how to implement or operate* something?" → EDR.
44
46
  - "Is the skill about *how to evaluate or decide on* architecture?" → ADR.
@@ -21,7 +21,7 @@ Articles are Markdown documents placed inside a subject folder alongside decisio
21
21
  - In more complex cases, an article may be an index of links to other articles, grouping related documentation into a single entry point that guides readers across a set of related topics.
22
22
  - When an article tells readers which decisions to follow, it SHOULD check `Valid:` first to determine the convergence date, `Applied to:` second to determine context fit, and the decision text itself last. All documents present in the collection are considered active; articles must not present out-of-window or out-of-scope XDRs as current rules for the discussed context.
23
23
  - 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.
24
- - Place an article in the subject folder that best matches its topic. If an article spans more than one subject, place it in `principles`.
24
+ - Place an article in the subject folder that best matches its topic using the required list of subjects per type defined in `_core-adr-001`. If an article spans more than one subject, place it in `principles`.
25
25
  - For simple structure, flow, layout, or relationship indications, articles SHOULD prefer plain Markdown, tables, or ASCII art instead of external assets.
26
26
  - 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.
27
27
  - Always use lowercase file names.
@@ -18,6 +18,7 @@ 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
+ - 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-001`.
21
22
  - Research documents SHOULD stay focused on one investigated problem, comparison, or hypothesis.
22
23
  - 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
24
  - Research documents MUST follow this section order: `Abstract`, `Introduction`, `Methods`, `Results`, `Discussion`, `Conclusion`, `References`.
@@ -22,7 +22,8 @@ Plans are Markdown documents placed inside a subject folder alongside decision r
22
22
  - 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 normally be tracked in specialized software such as GitHub or Azure DevOps.
23
23
  - 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.
24
24
  - Plans MUST live under `plans/` inside the relevant subject folder: `.xdrs/[scope]/[type]/[subject]/plans/[number]-[short-title].md`
25
- - Plans MUST include an `Expected end date:` field in ISO format (YYYY-MM-DD).
25
+ - 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-001`.
26
+ - Plans MUST include an `Expected end date:` field in ISO format (YYYY-MM-DD) inside the `## Proposed Solution` section.
26
27
  - Always use lowercase file names.
27
28
  - Never use emojis in plan content.
28
29
  - Images and other local resource files referenced by a plan SHOULD live in `plans/assets/` next to the plan files.
@@ -70,12 +71,12 @@ E.g.: Our checkout abandon rate is 50%, and it's increasing over time.]
70
71
  [Required. What we expect to achieve to solve the problem described above. Under 200 words.
71
72
  E.g.: Reduce payment time in our App by 30% and fix the 3 most impactful bugs.]
72
73
 
74
+ Expected end date: YYYY-MM-DD
75
+
73
76
  ## Acceptance Criteria
74
77
 
75
78
  [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.]
76
79
 
77
- Expected end date: YYYY-MM-DD
78
-
79
80
  ## Approach
80
81
 
81
82
  [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.]
@@ -2,15 +2,15 @@
2
2
  "Review xdr 001-xdrs-core-ac1c8339": {
3
3
  "result": "success",
4
4
  "contextFiles": [
5
+ ".github/skills/001-lint/SKILL.md",
5
6
  ".xdrs/_core/adrs/index.md",
6
7
  ".xdrs/_core/adrs/principles/001-xdrs-core.md",
7
8
  ".xdrs/_core/adrs/principles/002-xdr-standards.md",
8
- ".xdrs/_core/adrs/principles/skills/001-lint/SKILL.md",
9
- ".xdrs/_local/bdrs/index.md",
9
+ ".xdrs/_local/adrs/index.md",
10
10
  ".xdrs/index.md",
11
11
  "AGENTS.md"
12
12
  ],
13
- "contextHash": "98562e9ef1410e8976d719391a098ab3"
13
+ "contextHash": "080ea010bbb924d74c9196e7c3e0f6af"
14
14
  },
15
15
  "Reply ONLY with \"READY\" after checking i-a61b0904": {
16
16
  "result": "success",
@@ -2,13 +2,13 @@
2
2
  "Create a very small XDR deciding to use -8b1a2ddd": {
3
3
  "result": "success",
4
4
  "contextFiles": [
5
+ ".xdrs/_core/adrs/index.md",
5
6
  ".xdrs/_core/adrs/principles/001-xdrs-core.md",
6
7
  ".xdrs/_core/adrs/principles/002-xdr-standards.md",
7
- ".xdrs/_local/bdrs/index.md",
8
- ".xdrs/_local/bdrs/operations/001-agent-behavior-validation-procedure.md",
8
+ ".xdrs/_core/adrs/principles/skills/002-write-xdr/SKILL.md",
9
9
  ".xdrs/index.md",
10
10
  "AGENTS.md"
11
11
  ],
12
- "contextHash": "5ceaa69409aa5eff1728d3a4212865a0"
12
+ "contextHash": "8d030307248237f1775ab38126d354db"
13
13
  }
14
14
  }
@@ -2,13 +2,13 @@
2
2
  "Create a skill with instructions on how -a7079882": {
3
3
  "result": "success",
4
4
  "contextFiles": [
5
+ ".xdrs/_core/adrs/index.md",
5
6
  ".xdrs/_core/adrs/principles/001-xdrs-core.md",
6
7
  ".xdrs/_core/adrs/principles/003-skill-standards.md",
7
- ".xdrs/_local/bdrs/index.md",
8
- ".xdrs/_local/bdrs/operations/001-agent-behavior-validation-procedure.md",
8
+ ".xdrs/_core/adrs/principles/skills/003-write-skill/SKILL.md",
9
9
  ".xdrs/index.md",
10
10
  "AGENTS.md"
11
11
  ],
12
- "contextHash": "738b99bad5adfe36fa14191c6c31ddab"
12
+ "contextHash": "0bbe5ae297e8b1978c7020a7bb8779c1"
13
13
  }
14
14
  }
@@ -37,7 +37,7 @@ Quick test:
37
37
 
38
38
  **Scope** — use `_local` unless the user explicitly names another scope.
39
39
 
40
- **Subject** — pick the most specific match for the chosen type (see `003-skill-standards`):
40
+ **Subject** — pick the most specific match for the chosen type (required list per type is in `_core-adr-001`):
41
41
  - ADR subjects: `principles`, `application`, `data`, `integration`, `platform`, `controls`, `operations`
42
42
  - BDR subjects: `principles`, `marketing`, `product`, `controls`, `operations`, `organization`, `finance`, `sustainability`
43
43
  - EDR subjects: `principles`, `application`, `infra`, `observability`, `devops`, `governance`
@@ -4,14 +4,17 @@
4
4
  "contextFiles": [
5
5
  ".xdrs/_core/adrs/index.md",
6
6
  ".xdrs/_core/adrs/principles/001-xdrs-core.md",
7
+ ".xdrs/_core/adrs/principles/002-xdr-standards.md",
8
+ ".xdrs/_core/adrs/principles/003-skill-standards.md",
7
9
  ".xdrs/_core/adrs/principles/004-article-standards.md",
10
+ ".xdrs/_core/adrs/principles/006-research-standards.md",
11
+ ".xdrs/_core/adrs/principles/007-plan-standards.md",
8
12
  ".xdrs/_core/adrs/principles/articles/001-xdrs-overview.md",
9
- ".xdrs/_local/bdrs/index.md",
10
- ".xdrs/_local/bdrs/operations/001-agent-behavior-validation-procedure.md",
13
+ ".xdrs/_local/adrs/index.md",
14
+ ".xdrs/_local/adrs/principles/researches/001-research-and-decision-lifecycle.md",
11
15
  ".xdrs/index.md",
12
- "AGENTS.md",
13
- "README.md"
16
+ "AGENTS.md"
14
17
  ],
15
- "contextHash": "75745a424155326ee56008bcf923999e"
18
+ "contextHash": "4935b72a3613a4fad7cc72e477afed7a"
16
19
  }
17
20
  }
@@ -48,7 +48,7 @@ If the topic spans multiple types, use `adrs`. Use the same rules as `002-write-
48
48
  - **ADR**: system context, integration pattern, overarching architectural choice
49
49
  - **EDR**: specific tool/library, coding practice, testing strategy, project structure, pipelines
50
50
 
51
- **Subject** — pick the subject that best matches the article's topic (see `004-article-standards`).
51
+ **Subject** — pick the subject that best matches the article's topic (required list per type is in `_core-adr-001`).
52
52
  If the article spans more than one subject, place it in `principles`.
53
53
 
54
54
  ### Phase 3: Assign a Number and Name
@@ -42,7 +42,7 @@ Consult `001-xdrs-core` while making each choice in this phase. The summaries be
42
42
  - **ADR**: system context, integration pattern, overarching architectural choice
43
43
  - **EDR**: specific tool/library, coding practice, testing strategy, project structure, pipelines
44
44
 
45
- **Subject** — pick the most specific subject that matches the problem domain.
45
+ **Subject** — pick the most specific subject that matches the problem domain (required list per type is in `_core-adr-001`).
46
46
 
47
47
  **Research number** — scan `.xdrs/[scope]/[type]/[subject]/researches/` for the highest existing number and increment by 1. Never reuse numbers from deleted research documents.
48
48
 
@@ -39,7 +39,7 @@ Consult `001-xdrs-core` while making each choice in this phase. The summaries be
39
39
  - **ADR**: system context, integration pattern, overarching architectural choice
40
40
  - **EDR**: specific tool/library, coding practice, testing strategy, project structure, pipelines
41
41
 
42
- **Subject** — pick the subject that best matches the plan's topic. If the plan spans more than one subject, place it in `principles`.
42
+ **Subject** — pick the subject that best matches the plan's topic (required list per type is in `_core-adr-001`). If the plan spans more than one subject, place it in `principles`.
43
43
 
44
44
  ### Phase 3: Assign a Number and Name
45
45
 
@@ -75,12 +75,12 @@ Use the mandatory template from `007-plan-standards`:
75
75
 
76
76
  [Required. What we expect to achieve. Under 200 words.]
77
77
 
78
+ Expected end date: YYYY-MM-DD
79
+
78
80
  ## Acceptance Criteria
79
81
 
80
82
  [Optional. Expected result and how to verify the goal is achieved. Under 100 words.]
81
83
 
82
- Expected end date: YYYY-MM-DD
83
-
84
84
  ## Approach
85
85
 
86
86
  [Optional. Strategy and high-level how. Under 300 words.]
@@ -110,7 +110,7 @@ Rules to apply while drafting:
110
110
 
111
111
  - Focus on the problem, solution, and approach. Avoid bloating with generic project management content.
112
112
  - Link to Decisions the plan implements, Research that informs it, and Skills that guide execution.
113
- - The Expected end date must be in ISO format (YYYY-MM-DD) and should not be more than 2 years from the plan creation date.
113
+ - The Expected end date must be in ISO format (YYYY-MM-DD), placed inside the `## Proposed Solution` section, and should not be more than 2 years from the plan creation date.
114
114
  - If the plan scope is too large for 2 years, break it into multiple plans.
115
115
  - Remember that this plan must be deleted after full implementation. Write it with that ephemeral nature in mind.
116
116
  - Prefer plain Markdown, tables, or ASCII art for structure and flow.
package/lib/testPrompt.js CHANGED
@@ -28,7 +28,7 @@ async function runPromptTest(config, inputPrompt, judgePrompt, verbose) {
28
28
  try {
29
29
  if (options.workspaceMode === 'copy') {
30
30
  tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'xdrs-core-test-'));
31
- effectiveWorkspace = copyWorkspace(originalWorkspace, path.join(tempRoot, 'workspace'), options.workspaceFilter, verbose);
31
+ effectiveWorkspace = copyWorkspace(originalWorkspace, path.join(tempRoot, 'workspace'), options.workspaceFilter, options.workspaceExclude, verbose);
32
32
  }
33
33
 
34
34
  if(verbose) {
@@ -113,7 +113,9 @@ function copilotCmd(workspaceRoot = findGitRoot(process.cwd())) {
113
113
  '-p',
114
114
  '{PROMPT}'
115
115
  ],
116
- promptCmdContinueFlag: '--continue'
116
+ promptCmdContinueFlag: '--continue',
117
+ workspaceFilter: ['AGENTS.md', '.xdrs/index.md', '.xdrs/_core/**'],
118
+ workspaceExclude: ['**/*.test.js', '**/*.test.int.js', '**/*.test.int.report']
117
119
  };
118
120
  }
119
121
 
@@ -153,6 +155,7 @@ function normalizeConfig(config) {
153
155
  workspaceRoot: config.workspaceRoot ? path.resolve(config.workspaceRoot) : null,
154
156
  workspaceMode,
155
157
  workspaceFilter: normalizeWorkspaceFilter(config.workspaceFilter),
158
+ workspaceExclude: normalizeWorkspaceFilter(config.workspaceExclude),
156
159
  env: normalizeEnv(config.env),
157
160
  taskTimeoutMs: readTimeout(config.taskTimeoutMs, 'taskTimeoutMs'),
158
161
  judgeTimeoutMs: readTimeout(config.judgeTimeoutMs, 'judgeTimeoutMs'),
@@ -667,7 +670,11 @@ async function runPrompt(config, inputPrompt, judgePrompt, id, verbose) {
667
670
  function computeContextHash(model, inputPrompt, judgePrompt, contextFiles, workspaceRoot) {
668
671
  const parts = [model, inputPrompt, judgePrompt];
669
672
  for (const filePath of contextFiles) {
670
- parts.push(fs.readFileSync(path.join(workspaceRoot, filePath), 'utf8'));
673
+ try {
674
+ parts.push(fs.readFileSync(path.join(workspaceRoot, filePath), 'utf8'));
675
+ } catch {
676
+ console.warn(`computeContextHash: file not found, ignoring: ${path.join(workspaceRoot, filePath)}`);
677
+ }
671
678
  }
672
679
  return crypto.createHash('md5').update(parts.join('\n')).digest('hex');
673
680
  }
@@ -725,7 +732,7 @@ function findGitRoot(startPath) {
725
732
  }
726
733
  }
727
734
 
728
- function copyWorkspace(sourcePath, targetPath, workspaceFilter, verbose) {
735
+ function copyWorkspace(sourcePath, targetPath, workspaceFilter, workspaceExclude, verbose) {
729
736
  if(verbose) {
730
737
  console.log(`Copying workspace from ${sourcePath} to ${targetPath}`);
731
738
  }
@@ -736,12 +743,13 @@ function copyWorkspace(sourcePath, targetPath, workspaceFilter, verbose) {
736
743
  rootPath: sourcePath,
737
744
  ignoreContexts: [],
738
745
  activeRealDirectories: new Set(),
739
- workspaceFilter
746
+ workspaceFilter,
747
+ workspaceExclude
740
748
  });
741
749
  return targetPath;
742
750
  }
743
751
 
744
- function copyWorkspaceDirectory({ sourceDir, targetDir, rootPath, ignoreContexts, activeRealDirectories, workspaceFilter }) {
752
+ function copyWorkspaceDirectory({ sourceDir, targetDir, rootPath, ignoreContexts, activeRealDirectories, workspaceFilter, workspaceExclude }) {
745
753
  const realSourceDir = fs.realpathSync(sourceDir);
746
754
  if (activeRealDirectories.has(realSourceDir)) {
747
755
  return;
@@ -782,7 +790,8 @@ function copyWorkspaceDirectory({ sourceDir, targetDir, rootPath, ignoreContexts
782
790
  rootPath,
783
791
  ignoreContexts: nextIgnoreContexts,
784
792
  activeRealDirectories,
785
- workspaceFilter
793
+ workspaceFilter,
794
+ workspaceExclude
786
795
  });
787
796
  continue;
788
797
  }
@@ -791,6 +800,10 @@ function copyWorkspaceDirectory({ sourceDir, targetDir, rootPath, ignoreContexts
791
800
  continue;
792
801
  }
793
802
 
803
+ if (workspaceExclude && workspaceExclude.some((pattern) => minimatch(entryRelativePath, pattern, { dot: true }))) {
804
+ continue;
805
+ }
806
+
794
807
  fs.copyFileSync(sourceEntryPath, targetEntryPath);
795
808
  fs.chmodSync(targetEntryPath, (entryStats || fs.statSync(sourceEntryPath)).mode);
796
809
  }
@@ -89,6 +89,19 @@ test('workspaceFilter copies only files matching the glob pattern to temp worksp
89
89
  expect(err).toBe('');
90
90
  });
91
91
 
92
+ test('workspaceExclude removes files matching glob patterns from copied workspace', async () => {
93
+ const workspaceRoot = createWorkspace('exclude-pass');
94
+ fs.writeFileSync(path.join(workspaceRoot, 'notes.md'), 'notes content\n', 'utf8');
95
+
96
+ const err = await testPrompt(
97
+ createConfig(workspaceRoot, { workspaceExclude: ['*.md'] }),
98
+ 'workspace-exclude-check: list files in the workspace',
99
+ 'workspace-exclude-check: notes.md should not exist in the copied workspace, seed.txt should exist'
100
+ );
101
+
102
+ expect(err).toBe('');
103
+ });
104
+
92
105
  test('copilotCmd defaults to the git repository root', () => {
93
106
  const result = copilotCmd();
94
107
  const command = result.promptCmd;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.14.3",
3
+ "version": "0.14.5",
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",
@@ -44,7 +44,8 @@
44
44
  ],
45
45
  "exclude": [
46
46
  "**/*.test.js",
47
- "**/*.test.int.js"
47
+ "**/*.test.int.js",
48
+ "**/*.test.int.report"
48
49
  ]
49
50
  },
50
51
  "output": {