xdrs-core 0.38.4 → 0.40.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.
@@ -21,6 +21,8 @@ Foundational standards, principles, and guidelines.
21
21
  - [_core-adr-policy-013](principles/013-platform-scope-type.md) - **platform scope type** — Defines the `platform` scope type: live services or operational areas consumable directly
22
22
  - [_core-adr-policy-014](principles/014-standard-scope-type.md) - **standard scope type** — Defines the `standard` scope type: the default for business areas, products, and teams
23
23
  - [_core-adr-policy-015](principles/015-local-scope-type.md) - **_local scope type** — Defines the `_local` scope type: reserved for workspace-local decisions that must never be distributed
24
+ - [_core-adr-policy-016](principles/016-policy-subjects.md) - **Policy Subjects** — Allowed subjects per type (ADR/BDR/EDR), descriptions, examples, and disambiguation tiebreakers
25
+ - [_core-adr-policy-017](principles/017-policy-numbering-ranges.md) - **Policy numbering ranges** — Subject-based 100-number block ranges for policy numbering and the freeze-reference exemption
24
26
 
25
27
  ## Skills
26
28
 
@@ -28,6 +28,8 @@ Policies can be of different kinds, depending on the nature of the decision:
28
28
  - ADR (Architectural Decision Record): Wider architectural and technical decisions. Examples: how big topics relate to each other, system contexts, overview without realy deciding on details, integration patterns, overarching topics, corporate wide practices, corporate systems, external and internal partners etc
29
29
  - EDR (Engineering Decision Record): captures engineering details about how to implement things. Examples: specific tools and libraries selection, framework usage, best practices on coding, testing, quality, project structure, pipelines etc
30
30
 
31
+ ADR and EDR share the same six technical subject names (see [`_core-adr-policy-016`](016-policy-subjects.md)). The type disambiguates the abstraction level: ADR captures the architectural choice (what to adopt, which strategy, which topology); EDR captures the engineering implementation of that choice (how to configure, which conventions to follow, which tools to use). When the same concern spans both layers, authors MUST create two separate documents in the same-named subject across types. See `_core-adr-policy-016` for full subject descriptions, examples, and cross-type tiebreaker rules.
32
+
31
33
  #### General framework standards
32
34
 
33
35
  - The main document type in the collection of XDRS is the Policy document, which contains the core of a decision, contraints, rules and what SHOULD be followed. Other documents are normally related to this policy and MUST NOT go against its contents.
@@ -90,52 +92,8 @@ Policies can be of different kinds, depending on the nature of the decision:
90
92
  - `metadata` (optional): Arbitrary key-value map for additional scope metadata.
91
93
  - `follows` (optional): Core scope names whose Policies apply as mandatory conventions to this scope, beyond `_core`. Last-listed takes precedence on conflicts (e.g., `follows: myarea-core, shared-standards`).
92
94
  - `related-scopes` (optional): Scope names of parent, sibling, or child scopes. Use when structural links help verify policy correctness across related scopes.
93
- - **Subjects:** MUST be one of the following depending on the type of the Policy. Use the subject to indicate the main concern of the decision.
94
- - **ADR subjects**
95
- - `principles`: Cross-cutting architecture and policy foundations.
96
- - Examples: architecture style, interoperability rules, long-term technology direction.
97
- - `application`: System and service design decisions at application level.
98
- - Examples: modularization strategy, service decomposition, app-level security flows.
99
- - `data`: Data architecture and information modeling choices.
100
- - Examples: canonical schemas, data ownership boundaries, retention strategies.
101
- - `integration`: Decisions about communication between internal/external systems.
102
- - Examples: sync vs async patterns, contract strategy, partner integration approach.
103
- - `platform`: Platform-level runtime and enabling capabilities.
104
- - Examples: cloud/runtime baseline, foundational services, platform tenancy approach.
105
- - `controls`: Architecture controls for risk, security, and compliance at a high level.
106
- - Examples: encryption baseline, auditability requirements, policy enforcement points.
107
- - `operations`: Operational architecture decisions.
108
- - Examples: incident model, resilience objectives, operational ownership boundaries.
109
- - **BDR subjects**
110
- - `principles`: Business principles and decision criteria that guide all business areas.
111
- - Examples: customer fairness rules, policy precedence, strategic guardrails.
112
- - `marketing`: Go-to-market, communication, and campaign policy decisions.
113
- - Examples: campaign approval rules, channel usage standards, positioning constraints.
114
- - `product`: Product behavior, lifecycle, and offering decisions.
115
- - Examples: feature rollout policy, packaging/tiers, product requirement governance.
116
- - `controls`: Business control framework decisions.
117
- - Examples: approval segregation, mandatory checks, exception handling policy.
118
- - `operations`: Day-to-day business process and procedure decisions.
119
- - Examples: support workflows, onboarding/offboarding procedures, SLA operations.
120
- - `organization`: Structure, roles, and responsibility model decisions.
121
- - Examples: decision rights, team topology, accountability boundaries.
122
- - `finance`: Financial and cost-control business decisions.
123
- - Examples: budgeting process, pricing governance, investment approval rules.
124
- - `sustainability`: Environmental and social responsibility policy decisions.
125
- - Examples: sustainability KPIs, reporting cadence, procurement sustainability criteria.
126
- - **EDR subjects**
127
- - `principles`: Engineering principles and non-functional quality defaults.
128
- - Examples: coding standards baseline, testing philosophy, secure-by-default engineering rules.
129
- - `application`: Code-level implementation patterns and application conventions.
130
- - Examples: framework patterns, layer organization, API implementation conventions.
131
- - `infra`: Infrastructure implementation and runtime operations details.
132
- - Examples: IaC patterns, environment provisioning, network/runtime hardening details.
133
- - `observability`: Telemetry, monitoring, alerting, and diagnostics implementation.
134
- - Examples: log/metric/tracing standards, alert routing policy, SLO measurement approach.
135
- - `devops`: Delivery pipeline, release automation, and developer workflow decisions.
136
- - Examples: CI/CD stages, branch strategy, release promotion gates.
137
- - `governance`: Engineering governance, risk controls, and compliance mechanics.
138
- - Examples: dependency governance, approval policies, mandatory quality checks.
95
+ - **Subjects:** The subject folder MUST be chosen per [`_core-adr-policy-016`](016-policy-subjects.md), which defines allowed subjects, full descriptions, examples, and disambiguation tiebreakers.
96
+ - **Policy numbering:** Numbers MUST be assigned within the subject-based block ranges defined in [`_core-adr-policy-017`](017-policy-numbering-ranges.md). Use the lowest available number within the block for the chosen subject. See [`_core-adr-policy-002-policy-standards.01-freeze-reference-exemption`](002-policy-standards.md) for exemptions.
139
97
  - MUST NOT use emojis
140
98
  - **Links:** Use relative paths for all links; MUST NOT use absolute paths starting with `/`.
141
99
  - **Indexes**
@@ -157,9 +115,9 @@ Policies can be of different kinds, depending on the nature of the decision:
157
115
  - Whenever the contents of a scope change (new Policies, skills, articles, research, or plans are added, updated, or removed), evaluate whether the scope index SHOULD be updated to reflect the newer contents.
158
116
 
159
117
  **Folder structure examples** (using the default `.xdrs/` root):
160
- - `.xdrs/business-x/edrs/devops/003-required-development-workflow.md`
161
- - `.xdrs/business-x/adrs/controls/010-security-and-secrets-management.md`
162
- - `.xdrs/_core/edrs/devops/001-multi-repo.md`
118
+ - `.xdrs/business-x/edrs/platform/003-required-development-workflow.md`
119
+ - `.xdrs/business-x/adrs/governance/010-security-and-secrets-management.md`
120
+ - `.xdrs/_core/edrs/platform/001-multi-repo.md`
163
121
 
164
122
  ```text
165
123
  subject/
@@ -185,6 +143,7 @@ subject/
185
143
  - [_core-adr-policy-002 - Policy standards](002-policy-standards.md) - Standards for writing individual Policy documents
186
144
  - [_core-adr-policy-010 - Scope governance](010-scope-governance.md) - Scope-type definition convention, scope-local standards, and governance application model
187
145
  - [_core-adr-policy-011 - core scope type](011-core-scope-type.md) - Defines the `core` scope type and meta-governance scope conventions
146
+ - [_core-adr-policy-016 - Policy Subjects](016-policy-subjects.md) - Allowed subjects per type, descriptions, examples, and disambiguation tiebreakers
188
147
  - [001-review skill](skills/001-review/SKILL.md) - Skill for reviewing code changes against Policies
189
148
  - [002-write-policy skill](skills/002-write-policy/SKILL.md) - Skill for creating a new Policy following this standard
190
149
  - [_core-adr-policy-003 - Skill standards](003-skill-standards.md)
@@ -31,6 +31,7 @@ Policy documents are the authoritative source of truth for their scope, type, an
31
31
  | `valid-from` | Yes | ISO date (`YYYY-MM-DD`) indicating from when this decision MUST be enforced. Before this date it SHOULD be used everywhere possible, but compliance is not enforced during reviews until after this date. Defaults to the date the Policy was created. When updating an existing Policy whose `valid-from` date has already passed, preserve the original date—it MUST NOT be updated to the current date. The historical date shows when the policy was originally enabled and is important for understanding policy evolution. |
32
32
  | `license` | No | SPDX license expression (e.g. `MIT`, `Apache-2.0`, `CC-BY-4.0`). Indicates the license under which the document content is shared. If omitted, the license is governed by the repository or package defaults. |
33
33
  | `metadata` | No | Arbitrary key-value map for additional properties not defined by this spec. |
34
+ | `freeze-reference` | No | Boolean (`true` or `false`, defaults to `false`). When `true`, the policy MUST NOT be renamed, renumbered, or moved because external parties reference it by its current identity (path, number, name, heading). Reference-identity issues are intentionally exempt. See rule [`01-freeze-reference-exemption`](#01-freeze-reference-exemption). |
34
35
 
35
36
  - Minimal example:
36
37
  ```yaml
@@ -60,7 +61,8 @@ Policy documents are the authoritative source of truth for their scope, type, an
60
61
  - 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, and updates of Policies, but the Policy document remains the source of truth.
61
62
  - **Policy Id:** [scope]-[type]-policy-[number] (numbers are scoped per type+scope combination and MUST NOT be reused within that combination; MUST be lowercase)
62
63
  - Types in IDs: `adr-policy`, `bdr-policy`, `edr-policy`
63
- - Define the next number of a Policy by checking what is the highest number present in the type+scope. Don't fill numbering gaps, as they might be old deleted Policies and we MUST NOT reuse numbers of different documents/decisions. Numbering gaps are expected.
64
+ - Policy numbers MUST follow the subject-based block ranges defined in [`_core-adr-policy-017`](017-policy-numbering-ranges.md). Each subject has a reserved 100-number block; use the lowest available number within the block for the chosen subject. Use the overflow range (901–999) only when the subject's block is exhausted.
65
+ - Numbering gaps are expected and MUST NOT be filled, as gaps may represent deleted policies whose numbers MUST NOT be reused.
64
66
  - Policies MUST be concise and reference other Policies to avoid duplication.
65
67
  - Policies MUST NOT contain duplicated content: the same rule or information MUST NOT appear more than once in the document, whether stated identically or rephrased. Consolidate into a single authoritative statement and reference it where needed.
66
68
  - Policies MUST NOT contain conflicting content: all rules and statements within the same document MUST be consistent with each other.
@@ -86,6 +88,17 @@ Policy documents are the authoritative source of truth for their scope, type, an
86
88
  - Exceptions can reach under 2600 words (templates, more elaborate decision implementations etc)
87
89
  - MUST use `_local` scope if the user doesn't explicitly indicate a specific scope while creating a policy or skill.
88
90
 
91
+ #### 01-freeze-reference-exemption
92
+
93
+ When a policy's frontmatter includes `freeze-reference: true`, the policy MUST NOT be renamed, renumbered, or moved because external parties reference it by its current identity. The policy's reference identity is its full addressable path and canonical identifier: scope location, type folder, subject folder, number, filename, frontmatter `name` field, and document heading identifier. All checks and reviews that would require changing the reference identity MUST be ignored unless the owner explicitly requests them to be fixed. Specifically, the following checks are exempt:
94
+
95
+ - Invalid subject folder (scope, subject, or type placement does not match allowed values)
96
+ - Numbering range mismatch (number outside the reserved block for the subject per [`_core-adr-policy-017`](017-policy-numbering-ranges.md))
97
+ - Document heading format mismatch (heading does not start with the expected `# scope-type-policy-number:` prefix)
98
+ - Frontmatter `name` field mismatch (name does not match the expected identifier derived from the file path)
99
+
100
+ Content-level checks that do not affect the policy's reference (required sections, word count, emojis, broken outgoing links, structured rule block format, normative language) remain enforced. The `valid-from` date is not taken into consideration when evaluating whether `freeze-reference` applies.
101
+
89
102
  **Policy template**
90
103
 
91
104
  All Policies MUST follow this template
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: _core-adr-policy-016-policy-subjects
3
+ description: Defines the allowed subjects per XDRS type (ADR, BDR, EDR) with descriptions, examples, and disambiguation tiebreakers. Use when choosing a subject for any new policy or document.
4
+ apply-to: All XDRS scopes and document types
5
+ valid-from: 2026-07-09
6
+ ---
7
+
8
+ # _core-adr-policy-016: Policy Subjects
9
+
10
+ ## Context and Problem Statement
11
+
12
+ Policy documents are placed in a subject folder that reflects their primary concern. Without a well-defined and consistently applied subject taxonomy, documents are hard to find, placement decisions are inconsistent, and AI agents cannot reliably determine relevance.
13
+
14
+ What subjects are allowed per type, and how should ambiguous placements be resolved?
15
+
16
+ ## Decision Outcome
17
+
18
+ **A reduced, unambiguous subject taxonomy per type with explicit tiebreaker rules**
19
+
20
+ Each type uses a small, well-separated set of subjects. ADR and EDR share identical subject names, creating a consistent zoom-in relationship: ADR captures architectural decisions at a higher abstraction level; EDR captures engineering implementation decisions for the same concerns. BDR uses a business-specific set.
21
+
22
+ ### Details
23
+
24
+ #### 01-subject-must-be-from-allowed-list
25
+
26
+ The subject folder MUST be one of the subjects listed below. `freeze-reference: true` exempts this check (see [`_core-adr-policy-002-policy-standards.01-freeze-reference-exemption`](002-policy-standards.md)).
27
+
28
+ | Subject | ADR | BDR | EDR |
29
+ |---|---|---|
30
+ | `principles` | ✓ | ✓ | ✓ |
31
+ | `application` | ✓ | | ✓ |
32
+ | `data` | ✓ | | ✓ |
33
+ | `platform` | ✓ | | ✓ |
34
+ | `operations` | ✓ | ✓ | ✓ |
35
+ | `governance` | ✓ | ✓ | ✓ |
36
+ | `product` | | ✓ | |
37
+ | `finance` | | ✓ | |
38
+
39
+ #### 02-principles-must-be-cross-cutting
40
+
41
+ A document MUST only be placed in `principles` when its content affects potentially all other subjects in its type. A document that only concerns a single subject MUST be placed in that specific subject instead. Do not use `principles` as a catch-all when a more specific subject applies.
42
+
43
+ #### 03-adr-and-edr-share-subject-names-at-different-abstraction-levels
44
+
45
+ ADR and EDR intentionally share the same six subject names. The type disambiguates the abstraction level: ADR captures architectural choices about what to adopt or how systems relate at a high level; EDR captures engineering decisions about how to implement those choices in detail. When both an architectural and an engineering decision exist on the same topic, authors MUST create two separate documents. See tiebreaker 18 for the decision test.
46
+
47
+ #### 04-subject-descriptions-for-adr
48
+
49
+ Authors MUST place ADR documents in the subject that best matches the following definitions and examples.
50
+
51
+ - `principles`: Cross-cutting architectural foundations affecting all other ADR subjects. Examples: architecture style adoption, domain-driven design rules, interoperability rules, long-term technology direction.
52
+ - `application`: System and service design decisions. Covers application structure, integration and API patterns, service decomposition, migration patterns, and frontend architecture. Examples: modularization strategy, strangler fig migration, API versioning strategy, service contract approach, sync vs async communication, monolith decomposition, frontend rendering strategy (SSR vs CSR, SPA vs MPA), design system adoption, UI component library selection, mobile app architecture, AI/ML model selection and inference architecture.
53
+ - `data`: Data architecture and information modeling choices. Examples: canonical data model, data ownership boundaries, data retention strategy (technical architecture only — regulatory retention obligations MUST go in BDR `governance`), data mesh vs centralized approach, event sourcing, polyglot persistence.
54
+ - `platform`: Platform-level runtime and enabling capabilities — includes infrastructure topology, identity and authentication, cloud cost management, and managed external technical services adopted as infrastructure. Examples: cloud provider selection, multi-region topology, Kubernetes adoption, SSO/IAM architecture, mTLS, message broker selection, CDN strategy, FinOps and cloud cost allocation model, workflow orchestration tool selection (Airflow, Temporal), managed SaaS adoption (observability platforms, LLM API providers, data warehouse services), SIEM adoption as security monitoring infrastructure (a mandatory enforcement obligation to have a SIEM belongs in ADR `governance`).
55
+ - `operations`: Operational architecture decisions about how systems behave and are owned in production. Examples: resilience and availability objectives, disaster recovery strategy, incident ownership model, SLA definitions, operational accountability boundaries.
56
+ - `governance`: Architecture controls for security, compliance, and risk enforcement. Examples: encryption baseline, zero-trust architecture, threat modeling requirements, SOC2/ISO27001 compliance adoption, data classification and PII tiers, architecture review process, technology radar governance, architecture-level penetration testing requirements.
57
+
58
+ #### 05-subject-descriptions-for-bdr
59
+
60
+ Authors MUST place BDR documents in the subject that best matches the following definitions and examples.
61
+
62
+ - `principles`: Cross-cutting business principles that affect all other BDR subjects. Examples: customer-first decision framework, policy precedence rules, strategic guardrails, brand values, patent and IP strategic stance (e.g., patent-first vs open-core), technology debt governance principle.
63
+ - `product`: Product offering, go-to-market, marketing, and sales policy decisions. Covers product behavior and lifecycle, brand and communication standards, and sales process and revenue operations. Examples: feature rollout policy, product versioning and end-of-life, pricing tier structure, customer SLA commitments, product accessibility standards, beta program criteria, campaign approval process, social media policy, customer communication tone, brand naming, sales methodology, deal approval and discount authority matrix, CRM standards, sales commission structure, channel and partner sales policy, territory and quota policy.
64
+ - `operations`: Day-to-day business processes, organizational structure, responsibility model, and workforce decisions. Covers business process execution, team and organizational decisions, and the employee and contractor lifecycle. Examples: support workflows, vendor selection process, decision rights and RACI, team topology, hiring and interview process, performance management framework, compensation and benefits policy, learning and development standards, remote and hybrid work policy, onboarding and offboarding procedures, workforce planning, internal communication standards, M&A integration process, outage customer communication process, on-call scheduling and compensation policy (on-call ownership model belongs in ADR `operations`).
65
+ - `governance`: Legal, regulatory, compliance, risk management, and enterprise control decisions. Covers all mandatory policies imposed by law, regulation, or risk authority — including external regulatory obligations, internal control frameworks, enterprise risk governance, and ESG compliance requirements. Examples: GDPR and data privacy policy, risk appetite statement, KYC/AML procedures, business continuity policy, legal contract standards, employee data privacy, open-source licensing policy, vendor risk and due diligence standards, AI ethics and responsible AI policy, model risk management policy, regulatory compliance programs (SOX, HIPAA, Basel, MiFID, ISO 27001), internal audit requirements, fraud prevention policy, information security policy, ESG reporting requirements, carbon footprint targets, DEI compliance obligations, whistleblower policy, IP and patent compliance obligations, penetration testing regulatory obligation.
66
+ - `finance`: Financial and cost-control business decisions. Examples: budgeting process, investment approval thresholds, partner revenue sharing model, procurement policy, pricing approval and margin rules.
67
+
68
+ #### 06-subject-descriptions-for-edr
69
+
70
+ Authors MUST place EDR documents in the subject that best matches the following definitions and examples.
71
+
72
+ - `principles`: Cross-cutting engineering principles that affect all other EDR subjects. Examples: test-driven development philosophy, secure-by-default engineering rule, GitOps as default, immutable infrastructure principle.
73
+ - `application`: Code-level implementation patterns and application conventions. Covers coding patterns, API implementation, testing approaches, in-code practices, and frontend and mobile implementation. Examples: framework selection, REST API conventions, error handling patterns, unit testing approach, caching strategy, feature flag implementation, security headers (CSP/HSTS) in code, structured log format, frontend framework selection, UI component library standards, a11y implementation patterns, i18n/l10n patterns, AI/ML inference integration patterns.
74
+ - `data`: Data layer implementation and data management decisions. Examples: ORM selection and usage patterns, database migration tooling (Flyway, Liquibase), query optimization guidelines, ETL/ELT implementation, connection pooling standards, data masking in non-production environments.
75
+ - `platform`: Infrastructure implementation, delivery pipeline, and developer environment decisions. Covers both production infrastructure and local developer tooling. Examples: IaC tool selection (Terraform, Pulumi), CI/CD pipeline stages, Docker image standards, Kubernetes manifest standards, git branching strategy, secrets management tooling (Vault, AWS Secrets Manager), cloud cost tagging standards, local developer environment and devcontainer setup.
76
+ - `operations`: Production behavior and operational response decisions. Covers observability, monitoring, alerting, and runtime incident handling. Examples: log and metric collection standards, distributed tracing implementation, alert routing and escalation, SLO/SLI measurement, incident post-mortem process, rollback procedures, developer productivity and DORA metrics measurement.
77
+ - `governance`: Engineering controls enforced as mandatory checks, gates, or approval policies. Examples: mandatory test coverage thresholds, dependency vulnerability scanning, security scanning in CI pipelines, license compliance checking, code review approval policies, breaking change approval process, deprecation enforcement.
78
+
79
+ #### 07-tiebreaker-rules
80
+
81
+ When a document could plausibly fit more than one subject, authors MUST apply these rules in order until one subject is clearly indicated.
82
+
83
+ 1. `platform` vs `operations` (ADR and EDR): `platform` covers infrastructure capabilities and the delivery pipeline — decisions made before production. `operations` covers production behavior and response — monitoring, rollback, and incident handling. Multi-region topology MUST go in `platform`; rollback procedures MUST go in `operations`. See tiebreaker 22 for delivery pipeline specifics.
84
+
85
+ 2. `application` vs `governance` (EDR): `application` covers how code is written — patterns, conventions, and in-code practices. `governance` covers mandatory controls enforced externally as a gate or automated scan. Security headers written into HTTP responses MUST go in `application`; a mandatory security scanning gate in CI MUST go in `governance`. Rate limiting middleware in code MUST go in `application`; a gateway-enforced rate limit threshold gate MUST go in `governance`. Container security hardening in Dockerfiles MUST go in `platform`; a mandatory container image vulnerability scan gate in CI MUST go in `governance`.
86
+
87
+ 3. `platform` vs `governance` (ADR): `platform` covers capabilities you adopt as part of the runtime. `governance` covers security or compliance controls you enforce. SSO/IAM infrastructure MUST go in `platform`; encryption baseline policy and data classification tiers MUST go in `governance`. See tiebreaker 19 for extended security infrastructure guidance.
88
+
89
+ 4. `application` vs `data` (EDR): `application` covers the implementation pattern in code. `data` covers storage, schema, and data management. A caching strategy MUST go in `application`; ORM configuration and database migration tooling MUST go in `data`.
90
+
91
+ 5. `product` vs `finance` (BDR): `product` covers what is offered and how it behaves. `finance` covers financial governance and cost control. Pricing tier structure MUST go in `product`; pricing approval rules and margin controls MUST go in `finance`.
92
+
93
+ 6. `product` vs `operations` (BDR): `product` covers the commitment made to customers. `operations` covers the process to deliver on that commitment. A customer SLA commitment MUST go in `product`; the operational workflow and escalation process to meet the SLA MUST go in `operations`.
94
+
95
+ 7. Security decisions across types: Security as a concern distributes across subjects by layer — there is no single `security` subject. Authors MUST place security decisions by domain: architecture security controls in ADR `governance`; identity and auth infrastructure in ADR `platform`; secure coding practices and in-code security in EDR `application`; automated security enforcement gates in EDR `governance`.
96
+
97
+ 8. Performance and capacity decisions: A performance design pattern MUST go in `application`. An enforced performance threshold or budget gate MUST go in `governance`. Performance infrastructure (CDN, autoscaling) MUST go in `platform`. Availability objectives and capacity planning (SLA targets, scaling strategy) MUST go in ADR `operations`.
98
+
99
+ 9. Change management: Process automation and delivery pipeline steps MUST go in `platform`. Human authorization and approval policies for changes MUST go in `governance`.
100
+
101
+ 10. `platform` abstraction level across ADR and EDR: ADR/platform covers the architectural choice — what to adopt, which topology, which strategy. EDR/platform covers the implementation conventions — tool configuration, pipeline stages, naming standards, and developer environment setup. A FinOps cost allocation strategy MUST go in ADR/platform; tagging naming conventions MUST go in EDR/platform. When a concern spans both layers, create two separate documents. See tiebreaker 18 for the general ADR-vs-EDR test.
102
+
103
+ 11. On-call rotation across BDR and ADR: The on-call ownership model and system accountability structure MUST go in ADR `operations`; on-call scheduling, rotation cadence, and compensation policy MUST go in BDR `operations`.
104
+
105
+ 12. AI/ML decisions: Model selection and inference architecture MUST go in ADR `application`; AI/ML inference implementation patterns MUST go in EDR `application`. Training pipeline infrastructure (GPUs, orchestration, experiment tracking) MUST go in `platform`. Dataset management, feature stores, model registries, and data labeling standards MUST go in `data`.
106
+
107
+ 13. AI ethics, responsible AI, and agentic governance: Business-level AI ethics and responsible AI policy MUST go in BDR `governance`. Mandatory architecture-level AI controls (AI risk assessment, model risk governance) MUST go in ADR `governance`. Automated AI compliance gates in CI/CD (bias scanning, model validation) MUST go in EDR `governance`. In-code guardrails, prompt safety patterns, and agentic workflow implementation MUST go in EDR `application`. Human-in-the-loop thresholds as runtime behavior MUST go in ADR `operations`.
108
+
109
+ 14. External technical vendor placement: Adopting a managed external technical service as a runtime capability (LLM API provider, observability SaaS, data warehouse) MUST go in ADR `platform`. Integrating with a third-party API as part of an application flow (payment gateway, identity provider, partner API) MUST go in ADR `application`. Risk assessment and due diligence for any external vendor MUST go in BDR `governance`. The business process for selecting and onboarding vendors MUST go in BDR `operations`.
110
+
111
+ 15. `operations` vs `governance` for workforce and sustainability decisions (BDR): `operations` covers discretionary workforce policies. `governance` covers legally or regulatorily mandated obligations. Remote work policy MUST go in `operations`; labor law compliance and ESG regulatory reporting MUST go in `governance`. Voluntary sustainability targets MUST go in `operations`; mandatory ESG disclosure or regulatory sustainability compliance MUST go in `governance`.
112
+
113
+ 16. `product` vs `operations` for customer-facing process decisions (BDR): `product` covers the policy for what is offered, how it is sold, and how it is communicated. `operations` covers the execution process to deliver on those policies. A sales commission structure MUST go in `product`; the operational workflow for onboarding a new customer MUST go in `operations`.
114
+
115
+ 17. Single policy spanning multiple subjects — mandatory split: When one concern spans two subjects, authors MUST NOT merge them. Create two separate documents — one per subject — linked bidirectionally in each References section. Examples: GDPR erasure → one BDR `governance` (legal obligation) + one BDR `operations` (deletion workflow); DR → one BDR `governance` (DR policy) + one BDR `operations` (drill procedure).
116
+
117
+ 18. ADR vs EDR for the same topic — abstraction-level test: If the decision answers *"what to adopt or how systems relate structurally"* → ADR. If it answers *"how to implement or configure that choice"* → EDR. When a concern spans both levels, create one ADR and one EDR in the same-named subject. Examples: error budget policy MUST go in ADR `operations`; SLO measurement implementation MUST go in EDR `operations`. Chaos engineering tool adoption MUST go in ADR `platform`; the chaos runbook standards MUST go in EDR `operations`.
118
+
119
+ 19. Security infrastructure in ADR — `platform` vs `governance`: If the security technology primarily *provides* a runtime capability other systems depend on (KMS, VPN, network segmentation, certificate authority, PAM tooling) → `platform`. If it primarily *mandates, restricts, or audits* behaviour as a compliance control (encryption baseline, mandatory access review, data classification enforcement) → `governance`. When the same security concern yields both a capability adoption and an enforcement obligation, apply tiebreaker 17.
120
+
121
+ 20. Runtime infrastructure always goes to `platform`: Any technology adopted as a runtime enabling capability — regardless of whether it also stores data (cache, message bus, search runtime, workflow engine, session store) — MUST go in `platform`. Place a technology in `data` only when it is selected for data storage, schema management, query patterns, or data lifecycle with no infrastructure runtime role. When both roles are present, apply tiebreaker 17. Examples: Redis as cache → ADR `platform`; ORM patterns → EDR `data`. Elasticsearch as search runtime → ADR `platform`; index schema standards → EDR `data`.
122
+
123
+ 21. BDR `finance` vs `governance` — obligation vs strategy: If the financial decision is driven by external legal, regulatory, or contractual obligation (IFRS 15, tax law, banking capital rules, mandatory insurance) → `governance`. If it is a discretionary organizational financial decision (budget process, investment thresholds, pricing approval, revenue sharing, ESOP design) → `finance`.
124
+
125
+ 22. Delivery pipeline vs production behavior — `platform` vs `operations`: Any decision governing what happens before or at deployment (build, test, package, deploy, canary rollout, blue-green switch) MUST go in `platform`. Any decision governing runtime behaviour after a successful deployment (monitoring, alerting, rollback trigger, incident response, SLO measurement) MUST go in `operations`. Sharpens tiebreaker 1: blue-green strategy → `platform`; rollback trigger and procedure → `operations`.
126
+
127
+ ## References
128
+
129
+ - [_core-adr-policy-001 - XDRS core](001-xdrs-core.md) — Framework structure, scopes, types, and subject folder placement
130
+ - [_core-adr-policy-002 - Policy standards](002-policy-standards.md) — How to write Policy documents
131
+ - [_core-adr-policy-017 - Policy numbering ranges](017-policy-numbering-ranges.md) — Reserved number block per subject
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: _core-adr-policy-017-policy-numbering-ranges
3
+ description: Defines numeric block ranges per subject for policy numbering. Use when assigning a number to a new policy to ensure the number reflects the policy's subject.
4
+ apply-to: All XDRS scopes and policy numbers
5
+ valid-from: 2026-07-09
6
+ ---
7
+
8
+ # _core-adr-policy-017: Policy numbering ranges
9
+
10
+ ## Context and Problem Statement
11
+
12
+ As a scope grows across multiple subjects, doing only sequential numbering alone gives no indication of the subject, making browsing harder and independent authoring more prone to gaps that could have been intentional range separators.
13
+
14
+ How should policy numbers be allocated so that related policies are naturally grouped and the subject is visible from the number alone?
15
+
16
+ ## Decision Outcome
17
+
18
+ **Reserve fixed 100-number blocks per subject, with an upper overflow range for exhausted blocks**
19
+
20
+ Allocating one 100-number block per subject groups related policies in any sequential listing, makes subject membership visible from the number alone, and provides a clear path when a block runs out.
21
+
22
+ ### Details
23
+
24
+ #### 01-numbering-blocks-per-subject
25
+
26
+ Policies within a scope+type MUST be assigned numbers within the block reserved for their subject according to the table below. Each block covers exactly 100 numbers. Subjects that are not valid for a given type leave their block empty and unused.
27
+
28
+ | Block | Subject | Types |
29
+ |----------|---------------|--------------------|
30
+ | 001–100 | `principles` | ADR, BDR, EDR |
31
+ | 101–200 | `application` | ADR, EDR |
32
+ | 201–300 | `data` | ADR, EDR |
33
+ | 301–400 | `platform` | ADR, EDR |
34
+ | 401–500 | `operations` | ADR, BDR, EDR |
35
+ | 501–600 | `governance` | ADR, BDR, EDR |
36
+ | 601–700 | `product` | BDR |
37
+ | 701–800 | `finance` | BDR |
38
+ | 801–900 | *(reserved)* | future subjects |
39
+ | 901–999 | overflow | see rule 03 |
40
+
41
+ #### 02-next-available-number-within-block
42
+
43
+ The subject block rules in rule 01 apply to all policies, including existing ones. Any policy whose number falls outside its subject's reserved block MUST be renumbered to the lowest available number within the correct block. Authors assigning a number to a new policy MUST use the lowest available number within the subject's reserved block. Numbers from deleted policies MUST NOT be reused. Authors MUST NOT assign a number outside the subject's block unless that block is fully exhausted (see rule 03).
44
+
45
+ #### 03-overflow-range
46
+
47
+ When all 100 slots in a subject's block are exhausted, new policies for that subject MUST be placed in the overflow range (901–999), taking the next available number. The policy's subject folder governs placement; the number alone does not determine the subject for overflow policies.
48
+
49
+ #### 04-policy-numbers-must-comply
50
+
51
+ A policy's number MUST comply with the subject block rules in rule 01. Any policy with a non-compliant number MUST be renumbered to the correct block unless `freeze-reference: true` is set in the policy's frontmatter (see rule 06). Renumbering MUST update the filename, the `name` frontmatter field, the document heading, and all references to the old number in indexes, links, and citations.
52
+
53
+ #### 05-reserved-gap-must-not-be-assigned
54
+
55
+ Numbers in the reserved gap (801–900) MUST NOT be assigned to any policy. They are reserved for future subject additions defined by a future update to this policy.
56
+
57
+ #### 06-freeze-reference-exemption
58
+
59
+ When `freeze-reference: true` is set in a policy's frontmatter, numbering range compliance checks for that policy MUST be treated as exempt. The full exemption semantics are defined in [`_core-adr-policy-002-policy-standards.01-freeze-reference-exemption`](002-policy-standards.md).
60
+
61
+ ## References
62
+
63
+ - [`_core-adr-policy-001`](001-xdrs-core.md) — XDRS core framework: numbering and folder structure
64
+ - [`_core-adr-policy-002`](002-policy-standards.md) — Policy standards: freeze-reference exemption semantics
65
+ - [`_core-adr-policy-016`](016-policy-subjects.md) — Policy subjects: allowed subjects and taxonomy per type
@@ -37,15 +37,14 @@ Consult `001-xdrs-core` while making each choice in this phase. The summaries be
37
37
  **Scope** — use `_local` unless the user explicitly names another scope.
38
38
  - If the user names a scope other than `_local`, check the workspace root `.filedist.lock` file. If any file under `.xdrs/[scope]/` appears in `.filedist.lock`, the scope is external and new documents MUST NOT be created there. Inform the user and ask them to choose a non-external scope.
39
39
 
40
- **Subject** — pick one from the allowed list for the chosen type (from `001-xdrs-core`):
41
- - ADR: `principles`, `application`, `data`, `integration`, `platform`, `controls`, `operations`
42
- - BDR: `principles`, `marketing`, `product`, `controls`, `operations`, `organization`, `finance`, `sustainability`
43
- - EDR: `principles`, `application`, `infra`, `observability`, `devops`, `governance`
40
+ **Subject** — MUST read `_core-adr-policy-016` ([016-policy-subjects.md](../../016-policy-subjects.md)) in full before choosing. That document defines all allowed subjects per type with full descriptions, examples, and disambiguation tiebreakers. Do not rely on summaries or prior knowledge of the subject list always read the policy and select the subject that best matches the decision topic according to its definitions.
44
41
 
45
42
  When type, scope, or subject cannot be confidently inferred, ask the user a clarifying question before proceeding. Ask one question at a time and wait for the answer; follow up if the response introduces new ambiguity.
46
43
 
47
44
  **Policy ID** — format: `[scope]-[type]-[next available number]`
48
- - Scan `.xdrs/[scope]/[type]/` for the highest existing number in that scope+type and increment by 1.
45
+ - Read `_core-adr-policy-017` ([017-policy-numbering-ranges.md](../../017-policy-numbering-ranges.md)) to identify the 100-number block reserved for the chosen subject (e.g. `principles` 001–100, `application` 101–200).
46
+ - Scan `.xdrs/[scope]/[type]/[subject]/` for all existing numbers within that block and use the lowest number in the block that has not yet been assigned.
47
+ - Use the overflow range (901–999) only when all 100 slots in the subject's block are exhausted, taking the next available number there.
49
48
  - Never reuse numbers from deleted Policies.
50
49
 
51
50
  ### Phase 3: Choose the Title
@@ -38,10 +38,7 @@ Quick test:
38
38
  **Scope** — use `_local` unless the user explicitly names another scope.
39
39
  - If the user names a scope other than `_local`, check the workspace root `.filedist.lock` file. If any file under `.xdrs/[scope]/` appears in `.filedist.lock`, the scope is external and new documents MUST NOT be created there. Inform the user and ask them to choose a non-external scope.
40
40
 
41
- **Subject** — pick the most specific match for the chosen type (required list per type is in `_core-adr-policy-001`):
42
- - ADR subjects: `principles`, `application`, `data`, `integration`, `platform`, `controls`, `operations`
43
- - BDR subjects: `principles`, `marketing`, `product`, `controls`, `operations`, `organization`, `finance`, `sustainability`
44
- - EDR subjects: `principles`, `application`, `infra`, `observability`, `devops`, `governance`
41
+ **Subject** — MUST read `_core-adr-policy-016` ([016-policy-subjects.md](../../016-policy-subjects.md)) in full before choosing. That document defines all allowed subjects per type with full descriptions, examples, and disambiguation tiebreakers. Do not rely on summaries or prior knowledge of the subject list — always read the policy and select the most specific subject that matches the skill's activity domain.
45
42
 
46
43
  **Skill number** — scan `.xdrs/[scope]/[type]/[subject]/skills/` for the highest existing number and increment by 1. Never reuse numbers from deleted skills.
47
44
 
@@ -146,16 +143,16 @@ If any check fails, revise before continuing.
146
143
  **Input**: "Create a skill to help debug CI pipelines"
147
144
  - Type: EDR (engineering workflow)
148
145
  - Scope: `_local`
149
- - Subject: `devops`
150
- - Number: scan `.xdrs/_local/edrs/devops/skills/` → next available
151
- - Output: `.xdrs/_local/edrs/devops/skills/001-debug-ci-pipeline/SKILL.md`
146
+ - Subject: `platform`
147
+ - Number: scan `.xdrs/_local/edrs/platform/skills/` → next available
148
+ - Output: `.xdrs/_local/edrs/platform/skills/001-debug-ci-pipeline/SKILL.md`
152
149
 
153
150
  **Input**: "Create a skill to review API designs"
154
151
  - Type: ADR (architectural evaluation)
155
152
  - Scope: `_local`
156
- - Subject: `integration`
157
- - Number: scan `.xdrs/_local/adrs/integration/skills/` → next available
158
- - Output: `.xdrs/_local/adrs/integration/skills/001-review-api-design/SKILL.md`
153
+ - Subject: `application`
154
+ - Number: scan `.xdrs/_local/adrs/application/skills/` → next available
155
+ - Output: `.xdrs/_local/adrs/application/skills/001-review-api-design/SKILL.md`
159
156
 
160
157
  ## Edge Cases
161
158
 
@@ -142,7 +142,7 @@ Rules to apply while drafting:
142
142
  **Expected actions:**
143
143
  1. Read `007-plan-standards.md`.
144
144
  2. Topic: API v2 migration. Scope: `_local`.
145
- 3. Type: `adrs` (architectural). Subject: `integration` or `application`.
145
+ 3. Type: `adrs` (architectural). Subject: `application`.
146
146
  4. Research related Policies about API design and integration patterns.
147
147
  5. Draft the plan with clear problem, solution, milestones, and expected end date.
148
148
  6. Save, register in canonical index, and lint.
@@ -44,3 +44,5 @@ Read the full content of the skill file for the inferred type, then follow all i
44
44
  - MUST read the full target SKILL.md before proceeding — do not rely on summaries or prior knowledge of the target skill.
45
45
  - MUST follow all phases of the target skill from Phase 1 onward; do not skip any phase.
46
46
  - MUST NOT create documents of a type not listed in the routing table above.
47
+ - When routing to the Policy skill, MUST also read `_core-adr-policy-016` (`.xdrs/_core/adrs/principles/016-policy-subjects.md`) before choosing a subject — it contains the allowed subject list, descriptions, and disambiguation tiebreaker rules.
48
+ - When routing to the Policy skill, MUST also read `_core-adr-policy-017` (`.xdrs/_core/adrs/principles/017-policy-numbering-ranges.md`) before choosing a policy number — it defines the subject-based block ranges that determine valid numbers for each subject.
package/README.md CHANGED
@@ -60,6 +60,16 @@ The compilation process of a raw Decision Record is to distribute it into those
60
60
 
61
61
  Different teams at different organizational levels make decisions that apply to different audiences. XDRS are organized by scope (e.g. `_core`, `business-x`, `business-y-mobileapp`) so that each team owns its own decision space. Scopes can extend or override policies from broader scopes, with explicit precedence rules: scopes listed later in an index override those listed earlier.
62
62
 
63
+ ### Scope types and `follows`
64
+
65
+ Every scope declares a `scope-type` in its `index.md` frontmatter. The five built-in types are `core`, `reference`, `platform`, `standard`, and `_local`, each with different governance rules. Custom types (e.g. `business-area`) can be introduced by adding a `{type}-scope-type` policy to any `core`-type scope.
66
+
67
+ `core` scopes play a special role: they carry **meta-policies** — authoring standards, scope-type definitions, and governance conventions that apply to all scopes in the workspace. `_core` is the built-in foundation; teams can add their own `core` scope (e.g. `myorg-core`) to extend it with organization-level standards.
68
+
69
+ The `follows` field in a scope's `index.md` links it to one or more `core` scopes whose policies it must respect (beyond `_core`). This models organizational hierarchies: a team scope can follow a business-area `core` scope, which in turn follows `_core`.
70
+
71
+ See [examples/typed-scope](examples/typed-scope) for a full working example covering all five scope types and a custom `business-area` type.
72
+
63
73
  ### Subject grouping
64
74
 
65
75
  Within each scope and type, decisions are grouped by subject (e.g. `application`, `data`, `platform` for ADRs; `product`, `finance` for BDRs). This keeps related decisions together, improves human navigation, and allows AI agents to narrow their search to the relevant subject folder before reading individual records.
package/lib/lint.js CHANGED
@@ -11,9 +11,9 @@ const TYPE_TO_ID = {
11
11
  };
12
12
 
13
13
  const ALLOWED_SUBJECTS = {
14
- adrs: new Set(['principles', 'application', 'data', 'integration', 'platform', 'controls', 'operations']),
15
- bdrs: new Set(['principles', 'marketing', 'product', 'controls', 'operations', 'organization', 'finance', 'sustainability']),
16
- edrs: new Set(['principles', 'application', 'infra', 'observability', 'devops', 'governance'])
14
+ adrs: new Set(['principles', 'application', 'data', 'platform', 'operations', 'governance']),
15
+ bdrs: new Set(['principles', 'product', 'marketing', 'operations', 'governance', 'finance', 'sustainability']),
16
+ edrs: new Set(['principles', 'application', 'data', 'platform', 'operations', 'governance'])
17
17
  };
18
18
 
19
19
  const TYPE_NAMES = new Set(Object.keys(TYPE_TO_ID));
@@ -25,7 +25,7 @@ const SUBJECT_ARTIFACT_DIRS = new Set(['skills', 'articles', 'researches', 'plan
25
25
  const RESOURCE_DIR_NAME = '.assets';
26
26
  const SKILL_PACKAGE_OPTIONAL_DIRS = new Set(['scripts', 'references', RESOURCE_DIR_NAME]);
27
27
 
28
- const POLICY_ALLOWED_FRONTMATTER_KEYS = new Set(['name', 'description', 'apply-to', 'valid-from', 'license', 'metadata']);
28
+ const POLICY_ALLOWED_FRONTMATTER_KEYS = new Set(['name', 'description', 'apply-to', 'valid-from', 'license', 'metadata', 'freeze-reference']);
29
29
  const SKILL_ALLOWED_FRONTMATTER_KEYS = new Set(['name', 'description', 'license', 'metadata', 'compatibility', 'allowed-tools']);
30
30
  const SCOPE_INDEX_ALLOWED_FRONTMATTER_KEYS = new Set(['scope-type', 'name', 'description', 'apply-to', 'valid-from', 'license', 'metadata', 'follows', 'related-scopes']);
31
31
  const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.bmp']);
@@ -37,6 +37,21 @@ const ARTICLE_MAX_WORDS = 8000;
37
37
  const RESEARCH_MAX_WORDS = 5000;
38
38
  const SKILL_MAX_WORDS = 6500;
39
39
 
40
+ // Subject number block ranges per _core-adr-policy-017
41
+ const SUBJECT_NUMBER_RANGES = {
42
+ principles: [1, 100],
43
+ application: [101, 200],
44
+ data: [201, 300],
45
+ platform: [301, 400],
46
+ operations: [401, 500],
47
+ governance: [501, 600],
48
+ product: [601, 700],
49
+ finance: [701, 800],
50
+ };
51
+ const RESERVED_NUMBER_RANGE_MIN = 801;
52
+ const RESERVED_NUMBER_RANGE_MAX = 900;
53
+ const OVERFLOW_RANGE_MIN = 901;
54
+
40
55
  const NORMATIVE_KEYWORDS_RE = /\bMUST NOT\b|\bMUST\b|\bSHOULD NOT\b|\bSHOULD\b|\bMAY\b|\bREQUIRED\b|\bOPTIONAL\b/;
41
56
  const NORMATIVE_EMPHASIS_RE = /(\*{1,2}|_{1,2})(MUST NOT|SHOULD NOT|MUST|SHOULD|MAY|REQUIRED|OPTIONAL|always|never|mandatory|recommended|advised|preferably|possibly|optionally)(\*{1,2}|_{1,2})/i;
42
57
 
@@ -69,6 +84,12 @@ function runLintCli(args) {
69
84
  const targetPath = pathArgs[0] || '.';
70
85
  const result = lintWorkspace(targetPath, { ignoreExternal: !all });
71
86
 
87
+ if (result.warnings.length > 0) {
88
+ for (const warning of result.warnings) {
89
+ console.warn(`- [warning] ${warning}`);
90
+ }
91
+ }
92
+
72
93
  if (result.errors.length === 0) {
73
94
  console.log(`Lint passed for ${toDisplayPath(result.xdrsRoot)}`);
74
95
  if (result.readOnlyScopes.size > 0) {
@@ -110,11 +131,12 @@ function lintWorkspace(targetPath, options = {}) {
110
131
  const resolvedTarget = path.resolve(targetPath);
111
132
  const xdrsRoot = resolveXdrsRoot(resolvedTarget);
112
133
  const errors = [];
134
+ const warnings = [];
113
135
  const readOnlyScopes = new Set();
114
136
 
115
137
  if (!existsDirectory(xdrsRoot)) {
116
138
  errors.push(`Missing XDRS root directory: ${toDisplayPath(xdrsRoot)} [_core-adr-policy-001]`);
117
- return { xdrsRoot, errors, readOnlyScopes };
139
+ return { xdrsRoot, errors, warnings, readOnlyScopes };
118
140
  }
119
141
 
120
142
  const repoRoot = path.dirname(xdrsRoot);
@@ -158,7 +180,7 @@ function lintWorkspace(targetPath, options = {}) {
158
180
  }
159
181
 
160
182
  for (const scopeEntry of scopeEntries) {
161
- lintScopeDirectory(xdrsRoot, scopeEntry.name, errors, actualTypeIndexes, ignoreExternal, effectiveExternalScopes, knownScopeTypes, readOnlyScopes);
183
+ lintScopeDirectory(xdrsRoot, scopeEntry.name, errors, warnings, actualTypeIndexes, ignoreExternal, effectiveExternalScopes, knownScopeTypes, readOnlyScopes);
162
184
  }
163
185
 
164
186
  const rootIndexPath = path.join(xdrsRoot, 'index.md');
@@ -168,7 +190,7 @@ function lintWorkspace(targetPath, options = {}) {
168
190
  lintRootIndex(rootIndexPath, xdrsRoot, actualTypeIndexes, errors, effectiveExternalScopes);
169
191
  }
170
192
 
171
- return { xdrsRoot, errors, readOnlyScopes };
193
+ return { xdrsRoot, errors, warnings, readOnlyScopes };
172
194
  }
173
195
 
174
196
  function lintRootIndex(rootIndexPath, xdrsRoot, actualTypeIndexes, errors, externalScopes = new Set()) {
@@ -495,7 +517,7 @@ function lintScopeIndexFrontmatter(scopeIndexPath, scopeName, errors, xdrsRoot,
495
517
  }
496
518
  }
497
519
 
498
- function lintScopeDirectory(xdrsRoot, scopeName, errors, actualTypeIndexes, ignoreExternal, externalScopes, knownScopeTypes = new Map(), readOnlyScopes = new Set()) {
520
+ function lintScopeDirectory(xdrsRoot, scopeName, errors, warnings, actualTypeIndexes, ignoreExternal, externalScopes, knownScopeTypes = new Map(), readOnlyScopes = new Set()) {
499
521
  const scopePath = path.join(xdrsRoot, scopeName);
500
522
 
501
523
  if (ignoreExternal && externalScopes.has(scopeName)) {
@@ -515,7 +537,7 @@ function lintScopeDirectory(xdrsRoot, scopeName, errors, actualTypeIndexes, igno
515
537
  errors.push(`Unexpected directory under scope ${scopeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001]`);
516
538
  continue;
517
539
  }
518
- lintTypeDirectory(xdrsRoot, scopeName, entry.name, errors, actualTypeIndexes, externalScopes);
540
+ lintTypeDirectory(xdrsRoot, scopeName, entry.name, errors, warnings, actualTypeIndexes, externalScopes);
519
541
  const typeIndexPath = path.join(entryPath, 'index.md');
520
542
  if (existsFile(typeIndexPath)) {
521
543
  typeIndexesInScope.push(typeIndexPath);
@@ -567,7 +589,7 @@ function lintScopeLocalStandards(xdrsRoot, scopeName, errors) {
567
589
  }
568
590
  }
569
591
 
570
- function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, actualTypeIndexes, externalScopes = new Set()) {
592
+ function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, warnings, actualTypeIndexes, externalScopes = new Set()) {
571
593
  const typePath = path.join(xdrsRoot, scopeName, typeName);
572
594
  const indexPath = path.join(typePath, 'index.md');
573
595
  const xdrsNumbers = new Map();
@@ -590,11 +612,15 @@ function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, actualTypeInde
590
612
  }
591
613
 
592
614
  if (!ALLOWED_SUBJECTS[typeName].has(entry.name)) {
593
- errors.push(`Invalid subject folder for ${typeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001]`);
594
- continue;
615
+ if (hasAnyNonFrozenPolicy(entryPath)) {
616
+ errors.push(`Invalid subject folder for ${typeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001]`);
617
+ continue;
618
+ }
619
+ // All policies are frozen: emit a warning and still process for content-level checks.
620
+ warnings.push(`Invalid subject folder for ${typeName}: ${toDisplayPath(entryPath)} [_core-adr-policy-001] [exempt: freeze-reference]`);
595
621
  }
596
622
 
597
- artifacts.push(...lintSubjectDirectory(xdrsRoot, scopeName, typeName, entry.name, xdrsNumbers, errors, externalScopes));
623
+ artifacts.push(...lintSubjectDirectory(xdrsRoot, scopeName, typeName, entry.name, xdrsNumbers, errors, warnings, externalScopes));
598
624
  }
599
625
 
600
626
  if (existsFile(indexPath)) {
@@ -602,7 +628,7 @@ function lintTypeDirectory(xdrsRoot, scopeName, typeName, errors, actualTypeInde
602
628
  }
603
629
  }
604
630
 
605
- function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNumbers, errors, externalScopes = new Set()) {
631
+ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNumbers, errors, warnings, externalScopes = new Set()) {
606
632
  const subjectPath = path.join(xdrsRoot, scopeName, typeName, subjectName);
607
633
  const artifacts = [];
608
634
  const entries = safeReadDir(subjectPath, errors, `read subject directory ${scopeName}/${typeName}/${subjectName}`);
@@ -641,7 +667,7 @@ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNu
641
667
  }
642
668
 
643
669
  artifacts.push(entryPath);
644
- lintXdrsElementFile(xdrsRoot, scopeName, typeName, entryPath, xdrsNumbers, errors, externalScopes);
670
+ lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, entryPath, xdrsNumbers, errors, warnings, externalScopes);
645
671
  }
646
672
 
647
673
  const subjectAssetsDir = path.join(subjectPath, RESOURCE_DIR_NAME);
@@ -651,7 +677,7 @@ function lintSubjectDirectory(xdrsRoot, scopeName, typeName, subjectName, xdrsNu
651
677
  return artifacts;
652
678
  }
653
679
 
654
- function lintXdrsElementFile(xdrsRoot, scopeName, typeName, filePath, xdrsNumbers, errors, externalScopes = new Set()) {
680
+ function lintXdrsElementFile(xdrsRoot, scopeName, typeName, subjectName, filePath, xdrsNumbers, errors, warnings, externalScopes = new Set()) {
655
681
  const baseName = path.basename(filePath);
656
682
  const match = baseName.match(NUMBERED_FILE_RE);
657
683
  if (!match) {
@@ -671,15 +697,19 @@ function lintXdrsElementFile(xdrsRoot, scopeName, typeName, filePath, xdrsNumber
671
697
  }
672
698
 
673
699
  const content = fs.readFileSync(filePath, 'utf8');
700
+ lintPolicyNumberRange(number, subjectName, content, filePath, errors, warnings);
701
+ const { freezeReference } = extractFrontmatter(content);
674
702
  const expectedHeader = `# ${scopeName}-${TYPE_TO_ID[typeName]}-${number}:`;
675
703
  const firstLine = firstNonEmptyLine(stripFrontmatter(content));
676
- if (!firstLine.startsWith(expectedHeader)) {
704
+ if (!freezeReference && !firstLine.startsWith(expectedHeader)) {
677
705
  errors.push(`Policy title must start with "${expectedHeader}": ${toDisplayPath(filePath)} [_core-adr-policy-002]`);
706
+ } else if (freezeReference && !firstLine.startsWith(expectedHeader)) {
707
+ warnings.push(`Policy title must start with "${expectedHeader}": ${toDisplayPath(filePath)} [_core-adr-policy-002] [exempt: freeze-reference]`);
678
708
  }
679
709
 
680
710
  const expectedName = extractExpectedXdrsNameFromHeading(firstLine)
681
711
  || `${scopeName}-${TYPE_TO_ID[typeName]}-${number}-${match[2]}`;
682
- lintXdrsElementFrontmatter(content, expectedName, filePath, errors);
712
+ lintXdrsElementFrontmatter(content, expectedName, filePath, errors, warnings, freezeReference);
683
713
  lintStructuredRuleBlocks(content, filePath, errors);
684
714
  lintRequiredSections(content, filePath, XDRS_REQUIRED_SECTIONS, 'Policy', errors);
685
715
  lintNoEmojis(content, filePath, 'Policy', errors);
@@ -712,7 +742,7 @@ function slugifyTitle(title) {
712
742
  .replace(/--+/g, '-');
713
743
  }
714
744
 
715
- function lintXdrsElementFrontmatter(content, expectedName, filePath, errors) {
745
+ function lintXdrsElementFrontmatter(content, expectedName, filePath, errors, warnings, freezeReference = false) {
716
746
  const fm = extractFrontmatter(content);
717
747
  if (!fm.present) {
718
748
  errors.push(`Policy must start with a YAML frontmatter block: ${toDisplayPath(filePath)} [_core-adr-policy-002]`);
@@ -722,7 +752,8 @@ function lintXdrsElementFrontmatter(content, expectedName, filePath, errors) {
722
752
  errors.push(`Policy frontmatter must include a non-empty name field: ${toDisplayPath(filePath)} [_core-adr-policy-002]`);
723
753
  } else {
724
754
  if (fm.name !== expectedName) {
725
- errors.push(`Policy frontmatter name must be "${expectedName}": ${toDisplayPath(filePath)} [_core-adr-policy-002]`);
755
+ const msg = `Policy frontmatter name must be "${expectedName}": ${toDisplayPath(filePath)} [_core-adr-policy-002]`;
756
+ if (freezeReference) { warnings.push(`${msg} [exempt: freeze-reference]`); } else { errors.push(msg); }
726
757
  }
727
758
  if (fm.name.endsWith('-')) {
728
759
  errors.push(`Policy frontmatter name must not end with a hyphen: ${toDisplayPath(filePath)} [_core-adr-policy-002]`);
@@ -1017,6 +1048,40 @@ function lintPlansDirectory(xdrsRoot, scopeName, typeName, subjectName, plansPat
1017
1048
  return artifacts;
1018
1049
  }
1019
1050
 
1051
+ /**
1052
+ * Returns true when at least one policy file in dirPath does NOT have freeze-reference: true.
1053
+ * Used to decide whether an invalid-subject-folder error should be reported.
1054
+ */
1055
+ function hasAnyNonFrozenPolicy(dirPath) {
1056
+ let entries;
1057
+ try { entries = fs.readdirSync(dirPath, { withFileTypes: true }); } catch { return false; }
1058
+ for (const entry of entries) {
1059
+ if (!entry.isFile() || !NUMBERED_FILE_RE.test(entry.name)) continue;
1060
+ let content;
1061
+ try { content = fs.readFileSync(path.join(dirPath, entry.name), 'utf8'); } catch { return true; }
1062
+ const fm = extractFrontmatter(content);
1063
+ if (!fm.freezeReference) return true;
1064
+ }
1065
+ return false;
1066
+ }
1067
+
1068
+ function lintPolicyNumberRange(number, subjectName, content, filePath, errors, warnings) {
1069
+ const fm = extractFrontmatter(content);
1070
+ const num = parseInt(number, 10);
1071
+ if (num >= RESERVED_NUMBER_RANGE_MIN && num <= RESERVED_NUMBER_RANGE_MAX) {
1072
+ const msg = `Policy number ${number} is in the reserved range (801–900) which MUST NOT be assigned: ${toDisplayPath(filePath)} [_core-adr-policy-017.05-reserved-gap-must-not-be-assigned]`;
1073
+ if (fm.freezeReference) { warnings.push(`${msg} [exempt: freeze-reference]`); } else { errors.push(msg); }
1074
+ return;
1075
+ }
1076
+ if (num < OVERFLOW_RANGE_MIN) {
1077
+ const range = SUBJECT_NUMBER_RANGES[subjectName];
1078
+ if (range && (num < range[0] || num > range[1])) {
1079
+ const msg = `Policy number ${number} is outside the ${range[0]}–${range[1]} block reserved for subject "${subjectName}": ${toDisplayPath(filePath)} [_core-adr-policy-017.01-numbering-blocks-per-subject]`;
1080
+ if (fm.freezeReference) { warnings.push(`${msg} [exempt: freeze-reference]`); } else { errors.push(msg); }
1081
+ }
1082
+ }
1083
+ }
1084
+
1020
1085
  function lintNoEmojis(content, filePath, docType, errors) {
1021
1086
  const lines = content.split(/\r?\n/);
1022
1087
  const ignoredLines = findIgnoredMarkdownLines(lines);
@@ -1401,6 +1466,7 @@ function extractFrontmatter(content) {
1401
1466
  const keyMatch = line.match(/^([a-zA-Z][a-zA-Z0-9_-]*):\s*/);
1402
1467
  if (keyMatch) topLevelKeys.push(keyMatch[1]);
1403
1468
  }
1469
+ const freezeReferenceMatch = block.match(/^freeze-reference:\s*(.+)$/m);
1404
1470
  const descriptionText = extractDescriptionText(block);
1405
1471
  return {
1406
1472
  present: true,
@@ -1409,6 +1475,7 @@ function extractFrontmatter(content) {
1409
1475
  descriptionText,
1410
1476
  validFrom: validFromMatch ? validFromMatch[1].trim() : undefined,
1411
1477
  appliedTo: appliedToMatch ? appliedToMatch[1].trim() : undefined,
1478
+ freezeReference: freezeReferenceMatch ? freezeReferenceMatch[1].trim() === 'true' : false,
1412
1479
  topLevelKeys,
1413
1480
  };
1414
1481
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xdrs-core",
3
- "version": "0.38.4",
3
+ "version": "0.40.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",