Three-way standards consolidation matrix
Phase 0a deliverable. Reconciles three separate standards libraries into one unified HCS-governed library with a single base per domain plus thin per-scope overlays selected at read time by master-registry.db → standards_scope (hcs = default/base, tierpoint-prodtech, azurelocal).
Sources read in full:
| Scope | Location | Format | Domains |
|---|---|---|---|
hcs (base) | D:/git/platform/docs/standards/ | .md (MkDocs) | governance, scripting, automation, infrastructure, testing, variables, documentation, keyvault, build-environments, work-items, work-item-sync, ado-project-strategy, claude-code |
azurelocal | D:/git/azurelocal/platform/docs/standards/ | .md (MkDocs) | authoring-guide, automation, consuming, contributing, documentation, examples, index, infrastructure, naming, new-repo-setup, propagation, repository-management, scripting, solutions, testing, variables |
tierpoint-prodtech | D:/git/tierpoint/prodtech/docs/docs/docs/standards/ | .mdx (Docusaurus) | automation, documentation (+naming-conventions, drawio, badge-library, templates), docusaurus, infrastructure, provisioning, repository-management, scripting (+bash, powershell-organization, framework), solutions, testing, variable-management (+technical-standards, governance, schema-validation) |
Design rule (from the approved plan): there are NOT three libraries. There is one base + overlays only where a rule genuinely differs (not merely phrased differently). Format differences (.md vs .mdx) are a rendering concern handled by docs_platform, not a reason to fork a standard's rules.
Unified library structure (target)
docs/standards/
├── governance.md (base; overlays: azurelocal, tierpoint-prodtech)
├── scripting.md (base; overlay: tierpoint-prodtech, azurelocal — Bash/standalone)
├── automation.md (base; overlays: azurelocal, tierpoint-prodtech — CI platform)
├── infrastructure.md (base; overlay: tierpoint-prodtech — Terraform-first)
├── testing.md (base; overlay: azurelocal — MAPROOM/TRAILHEAD naming)
├── variables.md (base; overlays: azurelocal, tierpoint-prodtech — master-registry)
├── naming.md (NEW-DOMAIN, split from variables; overlays: azurelocal, tierpoint-prodtech)
├── documentation.md (base — platform-agnostic Markdown/diagrams/commit prose)
├── docs-platforms.md (NEW-DOMAIN — MkDocs/Docusaurus/Hugo/Jekyll matrix + per-repo assignment)
├── keyvault.md (base — MERGE, HCS is authoritative)
├── build-environments.md (base — hcs-only content, applies to all)
├── work-items.md (base; overlays: azurelocal=GitHub, tierpoint-prodtech=GitLab)
├── work-item-sync.md (base — ADO master; azurelocal overlay for GitHub Issues intake)
├── ado-project-strategy.md (base — hcs; informational for other scopes)
├── solutions.md (NEW-DOMAIN — MERGE azurelocal+prodtech; base)
├── provisioning.md (NEW-DOMAIN — tierpoint-prodtech scope only)
├── examples.md (NEW-DOMAIN — fictional-company/IIC policy; base)
├── agents.md (replaces claude-code.md — multi-model; never scope-split)
├── ai-workspace.md (NEW per plan)
├── authoring-standards.md (NEW-DOMAIN — how to author/propose a standard; merges azurelocal authoring-guide + contributing)
└── _scopes/
├── README.md (three-way reconciliation matrix — this file feeds it)
├── azurelocal/<domain>.md (overlays)
└── tierpoint-prodtech/<domain>.md (overlays, staged at MCP build time, NOT public)Per-domain classification
Legend: MERGE = one base serves all; OVERLAY = base + scope delta file; NEW-DOMAIN = does not exist in HCS base yet.
| Domain | hcs | azurelocal | tierpoint-prodtech | Decision | Overlay scope(s) |
|---|---|---|---|---|---|
| governance | ✅ | (repository-management) | (repository-management) | OVERLAY | azurelocal (GitHub/release-please/project-board), tierpoint-prodtech (GitLab/type::* labels) |
| scripting | ✅ PS7-only | ✅ PS + standalone | ✅ PS + Bash + standalone | OVERLAY | tierpoint-prodtech + azurelocal (Bash-in-CI, Standalone pattern, config path) |
| automation | ✅ ADO/GHA | ✅ interop | ✅ GitLab CI 4-stage | OVERLAY | azurelocal (GHA), tierpoint-prodtech (GitLab CI) |
| infrastructure | ✅ Bicep-first | ✅ types+parity | ✅ Terraform-common | OVERLAY | tierpoint-prodtech (Terraform-first, infra types) |
| testing | ✅ 5 classes | ✅ MAPROOM/TRAILHEAD | ✅ post-deploy/GitLab | OVERLAY | azurelocal (MAPROOM/TRAILHEAD framework names) |
| variables | ✅ | ✅ master-registry | ✅ master-registry+schema | OVERLAY | azurelocal + tierpoint-prodtech (master-registry/schema) |
| naming | (inside variables) | ✅ naming.md | ✅ naming-conventions.mdx | NEW-DOMAIN (split) | azurelocal (IIC/CAF), tierpoint-prodtech (multi-platform) |
| documentation | ✅ .md/MkDocs | ✅ .md/MkDocs | ✅ .mdx/Docusaurus | MERGE (base) + move platform bits to docs-platforms | — |
| docs-platforms | ✅ (implicit, MkDocs) | (implicit) | ✅ docusaurus.mdx | NEW-DOMAIN | — (base lists all sanctioned frameworks) |
| keyvault | ✅ (rich) | (in variables) | (in security/scripting) | MERGE (HCS authoritative) | — |
| build-environments | ✅ | — | — | MERGE (base, applies to all) | — |
| work-items | ✅ ADO | (project board) | (GitLab issues) | OVERLAY | azurelocal, tierpoint-prodtech |
| work-item-sync | ✅ | (GH Issues+Projects) | (GitLab) | OVERLAY | azurelocal (GH intake) |
| ado-project-strategy | ✅ | — | — | MERGE (base, hcs-authoritative) | — |
| solutions | — | ✅ | ✅ | NEW-DOMAIN (MERGE the two) | — (near-identical) |
| provisioning | — | — | ✅ | NEW-DOMAIN | tierpoint-prodtech only |
| propagation | — | ✅ | — | DEPRECATE (see below) | — |
| consuming | — | ✅ | — | DEPRECATE / fold | — |
| authoring-guide + contributing | — | ✅ | — | NEW-DOMAIN (merge → authoring-standards) | — |
| examples (IIC / fictional company) | — | ✅ | ✅ (in documentation) | NEW-DOMAIN (MERGE) | — |
| new-repo-setup | ✅ (in governance) | ✅ | ✅ (stub) | MERGE into governance/onboarding | azurelocal, tierpoint-prodtech |
| index | — | ✅ | ✅ | DROP (nav artifact, not a standard) | — |
| claude-code | ✅ | — | — | REPLACE → agents.md (multi-model, never scope-split) | — |
Genuine conflicts and the winning rule
Each item below is an actual different rule, not just different phrasing. Winning rule stated with reasoning.
C1 — Bash allowed? (scripting)
- hcs (
scripting.mdline 3): "All scripts across all HCS projects are PowerShell 7+. No exceptions. No Bash. No PS 5.1." - tierpoint-prodtech (
scripting/bash-scripting-standards.md;scripting-standards.mdxline 205): Bash permitted for Azure CLI scripts (az-verb-resource.sh), must pass ShellCheck;#Requires -Version 7.0for PS but one metadata example shows#Requires -Version 5.1(line 1242 — an internal inconsistency). - azurelocal (
scripting.mdline 16,automation.md): Bash az-CLI scripts allowed (az-verb-resource.sh), referencesbash-scripting-standards. - Winner: Base rule = PowerShell 7+ for all first-party automation and orchestration.
tierpoint-prodtechandazurelocaloverlays permit Bash only for Azure-CLI wrapper scripts in CI, must pass ShellCheck, must read the same config source. Reasoning: HCS "no Bash ever" is too absolute for the two scopes that already ship.shaz-CLI wrappers and GitLab CI; but Bash stays the exception, PS7 the default. The#Requires -Version 5.1example in prodtech is a defect — base mandates 7.0 everywhere.
C2 — Config file path (scripting / variables / infrastructure)
Three different canonical locations for the single-source-of-truth config:
- hcs:
config/variables.yml(+config/variables.example.yml) - azurelocal:
config/variables/variables.yml(+variables.example.yml+schema/variables.schema.json) - tierpoint-prodtech:
configs/infrastructure.yml(+infrastructure.yml.template+configs/variables/assets/) - Winner: No single winner is worth forcing — the filename is load-bearing in each scope's existing scripts (
Get-InfrastructureConfig,CanonicalVariable.psm1, bootstrap copy logic). Keep the contract in the base standard (single YAML source,snake_casekeys,keyvault://URIs, example/template committed, real file gitignored, auto-bootstrap-from-template) and record the path per scope in the overlay. Do not force a rename — it would break live automation across ~30 tp repos and the azurelocal toolkit.
C3 — keyvault:// vault name (variables / keyvault)
- hcs (
variables.mdline 199): vault in the URI "should always bekv-hcs-vault-01";keyvault.mdsupports multi-vault by name. - azurelocal:
keyvault://kv-iic-platform/...(IIC example vault) - tierpoint-prodtech:
keyvault://kv-tplabs-platform/...andsecurity.keyvault.kv_namefrom config - Winner: Base = vault name is read from config (
security.keyvault.kv_name/ URI), never assumed. HCS's "always kv-hcs-vault-01" is too narrow — the HCSkeyvault.mditself already documents cross-vault access via the platform MI and per-org vaults. Base adopts thekeyvault.mdmulti-vault model; the "default to kv-hcs-vault-01" line is demoted to an hcs-scope note.
C4 — Azure resource naming pattern (variables / naming)
- hcs (
variables.md):<type>-<org>-<env>-<region>-<instance>→kv-hcs-prd-eus-01(region + instance always). - azurelocal (
naming.md,examples.md):rg-iic-<purpose>-<##>→rg-iic-platform-01(purpose-based, no region segment). - tierpoint-prodtech (
naming-conventions.mdx): CAFrg-<workload>-<environment>-<region>-<instance>→rg-iic-prodtech-eus-connectivity-hub(workload+env+region+purpose). - Winner: These are genuinely different patterns. Recommend a NEW
naming.mdbase stating the CAF-aligned pattern<type>-<workload/org>-<env>-<region>-<instance>as the default, with scope overlays for the deviations: azurelocal's purpose-based short form (community/IIC examples) and tierpoint-prodtech's full multi-platform matrix (VMware/Hyper-V/AVD/networking/firewall naming, which is genuinely tp-specific and huge). Do not try to force one pattern — the tp multi-platform matrix and the HCS Azure-only pattern serve different estates. Split naming out ofvariables.mdso the overlay boundary is clean.
C5 — Fictional company / example identity (examples, documentation)
- hcs: none defined. HCS
keyvault.mdactively usestplabs,tppoc,tpdemos,hcsprodas real KV env-names. - azurelocal + tierpoint-prodtech: mandate Infinite Improbability Corp (IIC) /
improbability.cloudfor ALL examples; prodtech explicitly forbidstpdemos/tplabs/tpprodin examples (they are real environments). - Winner + flag: Adopt IIC as the base fictional-company standard for all documentation examples (new
examples.md). Reasoning: two of three scopes already mandate it and it is the stronger rule. Important boundary note: IIC governs documentation examples; the HCSkeyvault.mdenv-name registry (tplabs,tpdemos, etc.) governs real secret naming — these do not conflict, but the baseexamples.mdmust state explicitly that real env-names must never appear in prose examples, exactly as prodtech requires. This also reinforces why tierpoint-prodtech scoped content must stay off the public site (it references real environment names in KV standards).
C6 — Docs format and generator (documentation, docs-platforms)
- hcs (
documentation.mdline 62): "Do not use Docusaurus unless there is a compelling reason approved by Kris." Markdown.md+ MkDocs Material only. - azurelocal:
.md+ MkDocs Material for the platform site, butazurelocal.github.io(the community standards portal) is Docusaurus 3.9. - tierpoint-prodtech:
.mdx+ Docusaurus everywhere, required frontmatter block, no-emoji policy, badge library, MDX caveats. - Winner: The HCS "no Docusaurus" rule is already contradicted by reality (azurelocal.github.io and all of prodtech run Docusaurus). Resolve by splitting
documentation.md: basedocumentation.md= platform-agnostic prose/Markdown/diagrams/commit-message/heading-case rules (MERGE — these are ~identical across all three); newdocs-platforms.md= the sanctioned-generator matrix (MkDocs Material / Docusaurus / and the incumbents Hugo + Jekyll found in the estate) with per-repo assignment. Drop the "no Docusaurus" prohibition — replace with "MkDocs Material is the HCS default; Docusaurus is sanctioned for the tierpoint-prodtech and azurelocal-community scopes." No-emoji-in-docs (prodtech) is a good base rule — adopt it.
C7 — Work tracking system (work-items, work-item-sync, repository-management)
- hcs: ADO is the single source of truth; GitHub Issues are a mirror; migrate/close them into ADO.
- azurelocal (
repository-management.md): GitHub Issues + org Project board #3 are primary;type/*+priority/*+solution/*labels; milestones per repo. - tierpoint-prodtech (
repository-management.mdx): GitLab Issues + Milestones;type::*+priority::*+solution::*scoped labels. - Winner: Base = ADO Boards is the authoritative work-item system for HCS-governed delivery (hcs), with the
AB#<id>commit convention as the universal link format (all three already use conventional commits). Overlays describe the per-platform intake surface: azurelocal = GitHub Issues → ADO sync + Project board mirror; tierpoint-prodtech = GitLab Issues + Milestones (TierPoint's ADO is a separate org, so tp work tracking stays in GitLab, not forced into HCS ADO). This is the single biggest three-way divergence and the overlays must be explicit that tp does not sync into HCS ADO.
C8 — Deployment phase count (infrastructure)
- hcs: 4 phases — Plan / Provision / Configure / Validate (mandatory manual gate between Provision and Configure).
- azurelocal + tierpoint-prodtech: 3 phases — Azure Foundation / Compute & Workload / Configuration.
- Winner: Base = HCS 4-phase model (Plan/Provision/Configure/Validate). Reasoning: the explicit Plan (what-if) and Validate (contract test) phases are strictly better governance and already map onto the other two scopes' pipelines (validate/plan/deploy/test in prodtech's GitLab CI is essentially the same 4). The azurelocal/prodtech 3-phase "Foundation/Compute/Config" is a scoping of provision work, not a competing lifecycle — fold it in as sub-stages of Provision+Configure in the overlays.
C9 — IaC tool default (infrastructure)
- hcs: Bicep-first for Azure provisioning.
- tierpoint-prodtech: Terraform common/primary (state in Azure Blob), Bicep "preferred over raw ARM for new IaC" but Terraform is the reference.
- azurelocal: tool-parity — all of Terraform/Bicep/ARM/PS/Ansible must produce identical infra.
- Winner: Base = Bicep-first for HCS-owned Azure resources (hcs); tierpoint-prodtech overlay = Terraform-first (matches
tp-tf-module-*repos and GitLab state backend); azurelocal keeps the multi-tool parity requirement as its overlay (it genuinely ships all five toolchains per solution). No forced convergence — the estates differ.
C10 — Internal HCS conflict: pipeline YAML directory (automation vs ado-project-strategy)
automation.md(line 102): ADO pipeline YAML lives under.ado/.ado-project-strategy.md(line 90): Pipeline YAML files live in.azuredevops/.- Winner: This is a pre-existing intra-hcs contradiction (the plan already flags
.ado/vs.azuredevops/duplication for Phase 5 cleanup). Pick one during recreation — recommend.ado/(shorter, already used by the live.ado/docs-deploy.yml) and fixado-project-strategy.mdto match. Confirm which is wired in ADO before deleting the other.
C11 — Standards distribution model (propagation, consuming)
- azurelocal (
propagation.md,consuming.md, ADR-0002): standards distributed by link-not-copy — consumer repos carry aSTANDARDS.mdbreadcrumb pointing atAzureLocal/platform/docs/standards; no vendoring; a scheduled job syncs toazurelocal.github.io. - hcs / new model: the MCP is the router — clients call
bootstrap/get_standardand receive scope-resolved content; repos carryAGENTS.mdwith a public-site fallback URL. - Winner / recommendation: Deprecate
propagation.mdandconsuming.mdas standalone standards. The link-not-copy principle is correct and survives (no vendoring), but the mechanism is superseded: the MCP + public site (platform.hybridsolutions.cloud) replaces theSTANDARDS.mdbreadcrumb + scheduled.github.iosync. Fold the surviving principle ("never vendor standards; resolve them live") intoauthoring-standards.md/ the_scopes/README.md. Keepauthoring-guide+contributingmerged into a newauthoring-standards.md(how to write/propose a standard) — that content is still valuable and model-agnostic.
New domains to create in the base library
| New base domain | Origin | Rationale |
|---|---|---|
naming.md | split from hcs variables.md; azurelocal naming.md; prodtech naming-conventions.mdx | Azure/multi-platform resource naming is large enough and divergent enough (C4) to own a file with clean overlay boundaries |
docs-platforms.md | prodtech docusaurus/*; estate reality (MkDocs/Docusaurus/Hugo/Jekyll) | The sanctioned-generator matrix + per-repo docs_platform assignment (see docs-platform-inventory.md) |
solutions.md | azurelocal solutions.md + prodtech solution-development-standard.mdx | Multi-tool parity / sync-on-change / single-source-of-truth — the two versions are ~90% identical; MERGE into one base |
provisioning.md | prodtech provisioning-runbook-standard.mdx | Execution-Options tab framework; genuinely tierpoint-prodtech-scoped (Docusaurus <Tabs>), but worth a scoped standard |
examples.md | azurelocal examples.md + prodtech IIC policy | Fictional-company (IIC) policy for all doc examples (C5) |
authoring-standards.md | azurelocal authoring-guide.md + contributing.md | How to author/propose/version a standard; model-agnostic; absorbs the surviving "link-not-copy" principle |
Drop / deprecate
| Item | Action | Reason |
|---|---|---|
claude-code.md | Replace with agents.md | Multi-model; never scope-split (per plan) |
azurelocal propagation.md | Deprecate | MCP + public site supersede the breadcrumb/sync mechanism (C11) |
azurelocal consuming.md | Fold principle into authoring-standards | Vendoring ban survives; STANDARDS.md breadcrumb does not |
azurelocal/prodtech index.* | Drop | Nav artifacts, not standards |
prodtech docusaurus/* | Fold into docs-platforms.md | Generator-specific config, not a governance rule |
Scope-selection mapping (for the MCP / _scopes/README.md)
Every recommendation above resolves cleanly onto three standards_scope values already in master-registry.db:
hcs— the base file, served when no scope override exists (default; omitted for most repos).tierpoint-prodtech— alltp-*repos; overlays: scripting (Bash/standalone/configs/infrastructure.yml), automation (GitLab CI 4-stage), infrastructure (Terraform-first), variables/naming (master-registry+schema, multi-platform naming), work-items (GitLab), provisioning (base for this scope), docs-platforms (Docusaurus). Stays off the public site (references real env-names).azurelocal— AzureLocal-org repos (NEW scope to add tomaster-registry.db; see disposition memo); overlays: governance/repository-management (GitHub/release-please/Project-board), testing (MAPROOM/TRAILHEAD), variables (master-registry/canonical), work-items (GitHub Issues + sync), infrastructure (multi-tool parity), docs-platforms (MkDocs default; Docusaurus for.github.io).
Orchestration/agents and auth are never scope-split — one agents.md, one broker, per the plan.