v19: git-baseret konsumtion - forberedelse til privat repo

Beslutning: BCQuality skal vaere privat. En fork af et offentligt repo
kan ikke goeres privat, saa flyttet sker via detach/nyoprettelse - men
FOERST omlaegges al konsumtion fra tokenfri raw-URLs til git-baseret
adgang, shippet mens kanalen stadig er offentlig, saa flaaden aldrig
oplever et hul. GCM er token-haandteringen: udviklerne er allerede
autentificeret.

Kernen er KANAL-KLONEN: %USERPROFILE%\.claude\BCQuality, pinned til
stable. Alt kopieres derfra (filsystem-kopi = raa bytes; ingen
CDN-cache, ingen API-limits).

- sync-bcquality-knowledge.ps1 v2: git-baseret (klon/fetch/checkout
  stable, mirror bygges lokalt, skriver selv versionsmarkoeren)
- Install-CurabisMachine.ps1 v2: onboarding = git clone + script fra
  klonen; foerste GCM-login ER autentificeringen
- curabis-standard.agent.md v19: SRC/BASE-tokens peger paa klonen;
  fetch betyder copy; Mode B Step 0 freshener klonen; ny Mode B-
  sektion opdaterer maskin-CLAUDE.md ved konsumtionsmodel-skift
  (gated, Identity bevares); CLAUDE.md-templatens self-heals er
  git-baserede
- machine/CLAUDE.md v2: auto-update gater paa git fetch/rev-parse
  i stedet for GitHub API; setup laeses fra klonen
- Ishikawa + al-triage + Francis: fallbacks peger paa mirror/klon;
  al-triages hardcodede URL-liste fjernet (samme sygdom som Ishikawa
  havde). Aerlig konsekvens: Copilot mister live custom-fallback
- CONSUMPTION.md: Access model-sektion + to-linjers onboarding
- Invoke-CurabisEvidence: RawBase markeret legacy/doed

Nul raw.githubusercontent-referencer tilbage i forbrugerkritiske filer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Michael Dieringer 2026-07-03 17:44:19 +02:00
parent a95cf7f43f
commit 3ce08fe91e
9 changed files with 205 additions and 139 deletions

View file

@ -38,22 +38,31 @@ future CI/PR-review integration:
currently consumed by nothing. Keep it — but do not mistake it for active
configuration of the session model.
## Access model: PRIVATE repo, git-based consumption
BCQuality is a **private** repository. All consumption is git-based through
the **channel clone** at `%USERPROFILE%\.claude\BCQuality`, pinned to the
`stable` branch. Authentication is Git Credential Manager — the developer's
existing GitHub login; the first git contact opens a browser login, and that
is the entire token story. `raw.githubusercontent.com` and unauthenticated
GitHub-API calls are dead and must not appear in any consumer.
## Machine onboarding (new developer)
A fresh developer machine is made CURABIS-ready with ONE command
(idempotent — safe to re-run):
Two lines (idempotent — safe to re-run; the clone prompts the GCM login):
powershell -ExecutionPolicy Bypass -Command "Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup/machine/Install-CurabisMachine.ps1 -OutFile $env:TEMP\icm.ps1; & $env:TEMP\icm.ps1"
git clone --branch stable --single-branch https://github.com/Curabis/BCQuality.git "$env:USERPROFILE\.claude\BCQuality"
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\BCQuality\custom\setup\machine\Install-CurabisMachine.ps1"
It installs the global CLAUDE.md (identity substituted from git config),
bc-mcp-bridge.js, the bc-mcp config template (the developer inserts their
personal client secret), the knowledge sync script, and syncs the machine
mirror. Per repo afterwards: "Opdater CURABIS Standard fra BCQuality" — it
deploys `.vscode/find-altool.ps1` (a CURABIS template; no VS Code command
generates it) and the AL MCP wiring itself. The AL Language extension from
the Marketplace is the only per-machine prerequisite for AL MCP.
mirror from the clone. Per repo afterwards: "Opdater CURABIS Standard fra
BCQuality" — it deploys `.vscode/find-altool.ps1` and the AL MCP wiring
itself. The AL Language extension from the Marketplace is the only
per-machine prerequisite for AL MCP.
**Auto-trigger:** the command above rarely needs to be run by hand. Every
**Auto-trigger:** the lines above rarely need to be run by hand. Every
project CLAUDE.md (setup v15+) carries a machine self-heal: any Claude Code
session in any configured CURABIS repo detects an un-onboarded machine
(missing `~/.claude/CLAUDE.md` or bridge) and runs the onboarding itself —

View file

@ -76,10 +76,9 @@ reviews what happened. He asks one question about every significant event:
> "Er der en BCQuality-regel der ville have fanget dette? Dækkede den fuldt ud?"
He compares against the full BCQuality knowledge base:
```
BASE = https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge
```
He compares against the full BCQuality knowledge base — the machine-local
mirror at `%USERPROFILE%\.claude\bcquality-knowledge\custom\` (fallback: the
channel clone `%USERPROFILE%\.claude\BCQuality\custom\knowledge\`).
Domains: `architecture/`, `testing/`, `mcp/`
## The Two Proposal Types

View file

@ -28,8 +28,10 @@ param(
# Lokal BCQuality-klon. Default: proev ..\bcquality og .\.bcquality.
[string]$BCQualityHome,
# Bruges naar der ikke er en lokal klon: knowledge-filer HTTP-tjekkes herfra.
[string]$RawBase = 'https://raw.githubusercontent.com/Curabis/BCQuality/stable',
# LEGACY: repoet er privat - raw-URLs virker ikke laengere. Brug altid en
# lokal klon; kanal-klonen findes paa alle onboardede maskiner:
# -BCQualityHome "$env:USERPROFILE\.claude\BCQuality"
[string]$RawBase = '',
[switch]$Quiet
)

View file

@ -1,7 +1,7 @@
---
kind: action-skill
id: curabis-standard-setup
version: 18
version: 19
title: CURABIS Standard — Project Setup
description: >
Configures a new or existing repository to the CURABIS Standard development
@ -34,14 +34,33 @@ This agent runs when the developer says any of:
Detect which mode based on the trigger phrase and proceed accordingly.
## Source URLs (BCQuality — always fetch fresh)
## Source: the channel clone (BCQuality is PRIVATE — no raw URLs)
All artifacts come from the machine's **channel clone** — a git clone of
`Curabis/BCQuality` pinned to the `stable` branch. Authentication is Git
Credential Manager (the developer's existing GitHub login); there are NO
tokenless raw.githubusercontent fetches anywhere — the repo is private.
```
BASE = https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup
AGENTS_BASE = https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/agents
SRC = %USERPROFILE%\.claude\BCQuality (kanal-klonen, stable)
BASE = {SRC}\custom\setup
AGENTS_BASE = {SRC}\custom\agents
```
| Artefakt | URL |
**Before ANY Mode A/B work, ensure the channel clone is fresh:**
git -C "$env:USERPROFILE\.claude\BCQuality" fetch origin stable --quiet
git -C "$env:USERPROFILE\.claude\BCQuality" checkout -B stable origin/stable --quiet
If the clone is missing entirely:
git clone --branch stable --single-branch https://github.com/Curabis/BCQuality.git "$env:USERPROFILE\.claude\BCQuality"
**Vocabulary:** wherever this document says "fetch", it means **copy the file
from SRC** — a filesystem copy, which preserves raw bytes by definition (the
old HTTP-encoding pitfalls do not exist here).
| Artefakt | Placering |
|---|---|
| bc-mcp-bridge.js | `{BASE}/bc-mcp-bridge.js` |
| bc-mcp.config.template.json | `{BASE}/machine/bc-mcp.config.template.json` |
@ -188,10 +207,13 @@ covers every repo, and the repo history stays free of upstream rule churn.
**Machine self-heal (auto-onboarding):** if this machine is not CURABIS-
onboarded — `~/.claude/CLAUDE.md` or `~/.claude/bc-mcp-bridge.js` is missing —
run the full onboarding NOW (idempotent; identity taken from git config):
run the full onboarding NOW (idempotent; identity taken from git config; the
first git contact may open a browser login — that IS the authentication):
powershell -ExecutionPolicy Bypass -Command "Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup/machine/Install-CurabisMachine.ps1 -OutFile $env:TEMP\icm.ps1; & $env:TEMP\icm.ps1"
git clone --branch stable --single-branch https://github.com/Curabis/BCQuality.git "$env:USERPROFILE\.claude\BCQuality"
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\BCQuality\custom\setup\machine\Install-CurabisMachine.ps1"
(Skip the clone line if `%USERPROFILE%\.claude\BCQuality` already exists.)
Then report the manual leftovers it lists (personal client secret; the AL
Language extension if VS Code lacks it) and ask the developer to restart
Claude Code.
@ -201,7 +223,9 @@ self-heal suffices:
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"
(If that sync script itself is missing, the full onboarding above installs it.)
(If that sync script itself is missing, copy it from the channel clone:
`%USERPROFILE%\.claude\BCQuality\custom\setup\sync-bcquality-knowledge.ps1` —
or run the full onboarding above.)
These rules are always active.
@ -520,6 +544,10 @@ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Triggered by: "Opdater CURABIS Standard fra BCQuality"
**Step 0 — freshen the channel clone** (see Source section): fetch + checkout
`origin/stable` in `%USERPROFILE%\.claude\BCQuality`; create the clone if
missing. Every copy below reads from that clone.
Updates only the files that come directly from BCQuality.
Never touches `CLAUDE.md`, `projectmemory/`, `docs/`, or `~/.bc-mcp.config.json`.
@ -600,10 +628,24 @@ Detect and clean up:
- a reference to `.github/.agents/bcquality-knowledge/` (v6 repo-mirror era)
- a literal per-developer path such as `C:\Users\<name>\.claude\...` — must be
`~/.claude/...` / `%USERPROFILE%`, never one developer's username
- ANY remaining `raw.githubusercontent.com`-based self-heal or onboarding
command (v15-v18 era) — the repo is private; raw URLs are dead. The
current form is git-based via the channel clone.
If any match, propose replacing the section with the current template from
Step 4a and ask for confirmation before editing CLAUDE.md (same confirmation
gate as the agent-synligheds-check below).
### Machine CLAUDE.md refresh (Mode B)
The developer's global `~/.claude/CLAUDE.md` carries the CURABIS auto-update
instructions. After a consumption-model change (like v19's git migration),
those instructions go stale on every already-onboarded machine. Compare the
machine file's CURABIS sections against `{BASE}/machine/CLAUDE.md` in the
channel clone. If they diverge structurally (e.g. still reference raw URLs
or GitHub-API SHA checks), propose the update — show the diff, preserve the
Identity section verbatim, and ask for confirmation before editing: it is the
developer's personal file.
### .mcp.json — hardcoded developer-path validation (Mode B)
`.mcp.json` is git-committed and shared — it must not contain a path baked in for
@ -735,6 +777,9 @@ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Invocation note
This agent is fetched on demand from BCQuality. Both commands work in any
project — including one not yet configured — because Claude reads the URL
from `~/.claude/CLAUDE.md` (global instructions, present on all CURABIS machines).
This agent is read on demand from the machine's channel clone
(`%USERPROFILE%\.claude\BCQuality\custom\setup\curabis-standard.agent.md`,
after freshening — see Source section). Both commands work in any project —
including one not yet configured — because the machine's `~/.claude/CLAUDE.md`
(installed by onboarding) knows the clone location. On a machine without the
clone, the two-line onboarding in Step 4a's self-heal is the entry point.

View file

@ -2,30 +2,54 @@
# CURABIS — Global Claude Code Instructions
These instructions apply to every Claude Code session, regardless of project.
BCQuality is a PRIVATE repo: all access is git-based via the channel clone at
`%USERPROFILE%\.claude\BCQuality` (pinned to `stable`; auth = Git Credential
Manager). No raw.githubusercontent URLs — they do not work and must not be used.
## Auto-update BCQuality (runs at every session start)
If the current project has `.github/.agents/bcquality.agent.md`:
1. Fetch the latest commit SHA for `custom/setup/` in BCQuality:
`https://api.github.com/repos/Curabis/BCQuality/commits?path=custom/setup&sha=stable&per_page=1`
1. Freshen the channel clone and read its SHA:
`git -C "$env:USERPROFILE\.claude\BCQuality" fetch origin stable --quiet`
`git -C "$env:USERPROFILE\.claude\BCQuality" rev-parse origin/stable`
(If the clone is missing: run the machine self-heal from the project
CLAUDE.md — two lines: git clone + Install-CurabisMachine.ps1.)
2. Read stored SHA from `~/.claude/.bcquality-version` (may not exist yet)
3. If SHA is different (or file missing):
a. Fetch and execute Mode B from:
`https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup/curabis-standard.agent.md`
b. Write new SHA to `~/.claude/.bcquality-version`
c. Report: "BCQuality opdateret til [short-sha] — [antal] filer tjekket"
4. If SHA is unchanged: continue silently
a. `git -C "$env:USERPROFILE\.claude\BCQuality" checkout -B stable origin/stable --quiet`
b. Execute Mode B from the clone:
`%USERPROFILE%\.claude\BCQuality\custom\setup\curabis-standard.agent.md`
c. Refresh the local knowledge mirror:
`powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"`
(git-based; also writes the new SHA to the version marker)
d. Report: "BCQuality opdateret til [short-sha] — [antal] filer tjekket"
4. If SHA is unchanged: continue silently — do NOT re-run the sync script. One
sync per actual upstream change covers every project worked on until the next one.
Do this silently and quickly — do not ask for permission, do not explain the process
unless something actually changed.
## BCQuality knowledge files — session start
At session start, read BCQuality rules from the local cache (fast — no network):
- **`custom/`** — always read in full: `%USERPROFILE%\.claude\bcquality-knowledge\custom\**\*.md`
- **`community/`** and **`microsoft/`** — do NOT read in full (200+ files is too
much to preload). Instead read `%USERPROFILE%\.claude\bcquality-knowledge\INDEX.md`
first, and open only the files whose domain/keywords match the current task.
If the cache directory is missing or empty: run
`powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"`
once, then proceed as above.
## CURABIS Standard project setup
When the user says either of these commands, fetch and follow the setup agent:
When the user says either of these commands, freshen the channel clone (see
Auto-update step 1) and follow the setup agent read from:
```
https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup/curabis-standard.agent.md
%USERPROFILE%\.claude\BCQuality\custom\setup\curabis-standard.agent.md
```
- **"Konfigurer dette projekt til CURABIS Standard"** → fuld setup af nyt repo

View file

@ -1,16 +1,16 @@
# CURABIS maskin-onboarding - goer en frisk udviklermaskine klar til
# CURABIS Standard. Koeres EEN gang pr. maskine; er idempotent (sikker at
# koere igen). Alt hentes som raa bytes fra stable-kanalen.
# CURABIS maskin-onboarding v2 (GIT-BASERET, privat repo) - goer en frisk
# udviklermaskine CURABIS-klar. Idempotent; sikker at koere igen.
#
# Torsten (eller enhver ny udvikler) koerer:
# powershell -ExecutionPolicy Bypass -File Install-CurabisMachine.ps1
# Onboarding paa en ny maskine er TO linjer (GCM-login i browseren ved
# foerste git-kontakt ER autentificeringen):
#
# Eller direkte fra BCQuality:
# powershell -ExecutionPolicy Bypass -Command "Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup/machine/Install-CurabisMachine.ps1 -OutFile $env:TEMP\icm.ps1; & $env:TEMP\icm.ps1"
# git clone --branch stable --single-branch https://github.com/Curabis/BCQuality.git "$env:USERPROFILE\.claude\BCQuality"
# powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\BCQuality\custom\setup\machine\Install-CurabisMachine.ps1"
#
# Hvad der IKKE haandteres her (personligt/manuel):
# - din client secret i ~/.bc-mcp.config.json (scriptet lægger templaten
# og siger til)
# Alt kopieres fra kanal-klonen (filsystem-kopi = raa bytes; ingen raw-URLs).
#
# Haandteres IKKE her (personligt/manuelt):
# - din client secret i ~/.bc-mcp.config.json (templaten laegges, du udfylder)
# - VS Code + AL Language-extensionen (ms-dynamics-smb.al fra Marketplace)
param(
[string]$FullName,
@ -18,11 +18,21 @@ param(
)
$ErrorActionPreference = 'Stop'
$raw = 'https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/setup'
$claude = Join-Path $env:USERPROFILE '.claude'
$clone = Join-Path $env:USERPROFILE '.claude\BCQuality'
New-Item -ItemType Directory -Force $claude | Out-Null
# Identitet: default fra git config, ellers spoerg
# Kilde: scriptet ligger i <klon>\custom\setup\machine → klonrod tre niveauer op
$src = (Resolve-Path (Join-Path $PSScriptRoot '..\..\..')).Path
# Sikr kanal-klonen paa den kanoniske placering (scriptet KAN vaere koert fra en anden klon)
if (-not (Test-Path (Join-Path $clone '.git'))) {
if ($src -ne $clone) {
git clone --branch stable --single-branch 'https://github.com/Curabis/BCQuality.git' $clone
if ($LASTEXITCODE -ne 0) { throw 'git clone af kanal-klonen fejlede - tjek adgang/GCM.' }
}
}
if (-not $FullName) { $FullName = (git config user.name 2>$null) }
if (-not $UserName) { $UserName = $env:USERNAME }
if (-not $FullName) { $FullName = Read-Host 'Dit fulde navn' }
@ -30,12 +40,12 @@ if (-not $FullName) { $FullName = Read-Host 'Dit fulde navn' }
$done = @()
$todo = @()
# 1. Global CLAUDE.md (fra template; overskriver ALDRIG en eksisterende)
# 1. Global CLAUDE.md (fra template i klonen; overskriver ALDRIG en eksisterende)
$gcm = Join-Path $claude 'CLAUDE.md'
if (Test-Path $gcm) {
$done += "CLAUDE.md fandtes allerede - ikke roert"
$done += 'CLAUDE.md fandtes allerede - ikke roert'
} else {
Invoke-WebRequest -UseBasicParsing "$raw/machine/CLAUDE.md" -OutFile $gcm
Copy-Item (Join-Path $src 'custom\setup\machine\CLAUDE.md') $gcm
$t = [System.IO.File]::ReadAllText($gcm)
$t = $t.Replace('[Your Name]', $FullName).Replace('[your-username]', $UserName)
$t = $t -replace '<!-- Replace the two lines below with your own details -->\r?\n', ''
@ -44,29 +54,22 @@ if (Test-Path $gcm) {
}
# 2. BC MCP bridge (stable er autoritativ - overskriv)
Invoke-WebRequest -UseBasicParsing "$raw/bc-mcp-bridge.js" -OutFile (Join-Path $claude 'bc-mcp-bridge.js')
$done += "bc-mcp-bridge.js installeret"
Copy-Item (Join-Path $src 'custom\setup\bc-mcp-bridge.js') (Join-Path $claude 'bc-mcp-bridge.js') -Force
$done += 'bc-mcp-bridge.js installeret'
# 3. BC MCP config-template (personlig secret - aldrig overskrive)
$cfg = Join-Path $env:USERPROFILE '.bc-mcp.config.json'
if (Test-Path $cfg) {
$done += "bc-mcp.config.json fandtes allerede - ikke roert"
$done += 'bc-mcp.config.json fandtes allerede - ikke roert'
} else {
Invoke-WebRequest -UseBasicParsing "$raw/machine/bc-mcp.config.template.json" -OutFile $cfg
Copy-Item (Join-Path $src 'custom\setup\machine\bc-mcp.config.template.json') $cfg
$todo += "Aabn $cfg og indsaet din personlige client secret"
}
# 4. Knowledge-sync-script + mirror
Invoke-WebRequest -UseBasicParsing "$raw/sync-bcquality-knowledge.ps1" -OutFile (Join-Path $claude 'sync-bcquality-knowledge.ps1')
# 4. Sync-script til maskinen + koer det (bygger mirror + saetter versionsmarkoer)
Copy-Item (Join-Path $src 'custom\setup\sync-bcquality-knowledge.ps1') (Join-Path $claude 'sync-bcquality-knowledge.ps1') -Force
& powershell -ExecutionPolicy Bypass -File (Join-Path $claude 'sync-bcquality-knowledge.ps1')
$done += "bcquality-knowledge mirror synkroniseret"
# 5. Versionsmarkoer (stable-SHA)
try {
$sha = (Invoke-RestMethod 'https://api.github.com/repos/Curabis/BCQuality/commits?sha=stable&per_page=1')[0].sha
Set-Content -Path (Join-Path $claude '.bcquality-version') -Value $sha -Encoding ascii
$done += "versionsmarkoer sat ($($sha.Substring(0,7)))"
} catch { $todo += "Kunne ikke saette versionsmarkoer (GitHub API) - foerste session goer det selv" }
$done += 'bcquality-knowledge mirror synkroniseret (git-baseret)'
Write-Host ''
Write-Host '=== CURABIS maskin-onboarding faerdig ===' -ForegroundColor Green
@ -78,5 +81,4 @@ if ($todo) {
}
Write-Host ''
Write-Host 'Pr. repo herefter: sig "Opdater CURABIS Standard fra BCQuality" i Claude'
Write-Host 'Code - den deployer selv .vscode/find-altool.ps1 og AL MCP-opsaetningen.'
Write-Host 'Genstart Claude Code efter foerste onboarding.'
Write-Host 'Code - den henter alt fra kanal-klonen. Genstart Claude Code foerst.'

View file

@ -1,36 +1,47 @@
# Refresh the MACHINE-LOCAL mirror of the Curabis BCQuality knowledge base.
#
# Mirrors three layers from https://github.com/Curabis/BCQuality:
# v2 - GIT-BASED (privat repo): al konsumtion sker via en kanal-klon i
# %USERPROFILE%\.claude\BCQuality (pinned til stable-branchen)
# Autentificering haandteres af Git Credential Manager - ingen raw-URLs,
# ingen GitHub API, ingen CDN-cache. Foerste koersel udloeser evt. et
# GCM-login i browseren; det ER onboarding-autentificeringen.
#
# Mirrors three layers into %USERPROFILE%\.claude\bcquality-knowledge:
# custom/ - Curabis org-specific rules (ALWAYS read in full each session)
# community/ - BC community patterns (loaded on relevance via INDEX.md)
# microsoft/ - platform guardrails (loaded on relevance via INDEX.md)
# ...plus INDEX.md (domain + keywords per fil) og opdaterer versionsmarkoeren.
#
# The upstream file list is discovered dynamically from the GitHub tree API, so
# new/removed upstream files propagate automatically - nothing is hardcoded.
# After downloading, an INDEX.md is generated (one line per file, with domain +
# keywords from each file's frontmatter) so an agent can scan and pull only the
# files relevant to a task instead of loading all ~100 every session.
#
# The mirror is per developer machine (~/.claude/bcquality-knowledge/), shared
# by every CURABIS repo on it. It is NEVER committed to a project repository -
# see BCQuality rule bcquality-knowledge-must-mirror-to-machine-not-repo.
# One sync per machine covers every repo. Run periodically:
# Mirroren committes ALDRIG til et projekt-repo - se BCQuality-reglen
# bcquality-knowledge-must-mirror-to-machine-not-repo. Koer periodisk:
# powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"
$ErrorActionPreference = 'Stop'
$repo = 'Curabis/BCQuality'
$branch = 'stable'
$repoUrl = 'https://github.com/Curabis/BCQuality.git'
$clone = Join-Path $env:USERPROFILE '.claude\BCQuality'
$dest = Join-Path $env:USERPROFILE '.claude\bcquality-knowledge'
$marker = Join-Path $env:USERPROFILE '.claude\.bcquality-version'
$staging = "$dest.tmp"
$rawBase = "https://raw.githubusercontent.com/$repo/$branch"
$treeUrl = "https://api.github.com/repos/$repo/git/trees/$branch" + '?recursive=1'
# Upstream path prefix -> local layer folder
# --- 1. Kanal-klon: opret eller opdater (pinned til stable) ---
if (-not (Test-Path (Join-Path $clone '.git'))) {
Write-Host "Kanal-klon mangler - kloner stable fra $repoUrl ..."
git clone --branch stable --single-branch $repoUrl $clone
if ($LASTEXITCODE -ne 0) { throw "git clone fejlede - er du autentificeret (GCM), og har du adgang til repoet?" }
} else {
git -C $clone fetch origin stable --quiet
if ($LASTEXITCODE -ne 0) { throw "git fetch fejlede - tjek netvaerk/adgang." }
git -C $clone checkout -B stable origin/stable --quiet
}
$sha = (git -C $clone rev-parse HEAD).Trim()
Write-Host "Kanal-klon paa stable @ $($sha.Substring(0,7))"
# --- 2. Byg mirror fra klonens filer (ingen netvaerk herfra) ---
$layerMap = [ordered]@{
'custom/knowledge/' = 'custom'
'community/knowledge/' = 'community'
'microsoft/knowledge/' = 'microsoft'
'custom\knowledge' = 'custom'
'community\knowledge' = 'community'
'microsoft\knowledge' = 'microsoft'
}
function Get-Frontmatter {
@ -47,50 +58,25 @@ function Get-Frontmatter {
return $fm
}
Write-Host "Fetching file tree from $repo@$branch ..."
$headers = @{ 'User-Agent' = 'wareco-bcquality-sync'; 'Accept' = 'application/vnd.github+json' }
$tree = (Invoke-RestMethod -Uri $treeUrl -Headers $headers).tree
# Build the download worklist from the tree
$files = @()
foreach ($node in $tree) {
if ($node.type -ne 'blob') { continue }
if ($node.path -notlike '*.md') { continue }
foreach ($prefix in $layerMap.Keys) {
if ($node.path.StartsWith($prefix)) {
$relative = $node.path.Substring($prefix.Length) # e.g. performance/avoid-commit-inside-loops.md
$files += [pscustomobject]@{
Url = "$rawBase/$($node.path)"
Layer = $layerMap[$prefix]
Relative = $relative
LocalPath = Join-Path $staging (Join-Path $layerMap[$prefix] $relative)
}
break
}
}
}
if ($files.Count -eq 0) { throw 'No knowledge files found in upstream tree - aborting.' }
# Download into a staging folder so a mid-run failure never wipes the live copy
if (Test-Path $staging) { Remove-Item -Recurse -Force $staging }
New-Item -ItemType Directory -Force $staging | Out-Null
Write-Host "Downloading $($files.Count) knowledge files ..."
$rc = 0
foreach ($f in $files) {
New-Item -ItemType Directory -Force (Split-Path $f.LocalPath) | Out-Null
try {
Invoke-WebRequest -Uri $f.Url -OutFile $f.LocalPath -UseBasicParsing -ErrorAction Stop
Write-Host "OK $($f.Layer)/$($f.Relative)"
} catch {
Write-Error "FAIL $($f.Layer)/$($f.Relative)"
$rc = 1
$files = @()
foreach ($prefix in $layerMap.Keys) {
$srcDir = Join-Path $clone $prefix
if (-not (Test-Path $srcDir)) { continue }
$layer = $layerMap[$prefix]
Get-ChildItem $srcDir -Recurse -Filter *.md | ForEach-Object {
$relative = $_.FullName.Substring($srcDir.Length + 1)
$localPath = Join-Path $staging (Join-Path $layer $relative)
New-Item -ItemType Directory -Force (Split-Path $localPath) | Out-Null
Copy-Item $_.FullName $localPath
$files += [pscustomobject]@{ Layer = $layer; Relative = $relative; LocalPath = $localPath }
}
}
if ($files.Count -eq 0) { throw 'Ingen knowledge-filer fundet i kanal-klonen - afbryder.' }
# Generate INDEX.md (relevance index for all layers)
Write-Host "Generating INDEX.md ..."
# --- 3. INDEX.md (relevans-indeks for alle lag) ---
$idx = [System.Collections.Generic.List[string]]::new()
$idx.Add('# BCQuality Knowledge Index')
$idx.Add('')
@ -100,7 +86,6 @@ $idx.Add('Layers: `custom` is ALWAYS read in full each session. For `community`
$idx.Add('`microsoft`, scan this index and read only the files whose domain/keywords')
$idx.Add('match the task at hand.')
$idx.Add('')
foreach ($layer in @('custom', 'community', 'microsoft')) {
$layerFiles = $files | Where-Object { $_.Layer -eq $layer } | Sort-Object Relative
if (-not $layerFiles) { continue }
@ -111,18 +96,18 @@ foreach ($layer in @('custom', 'community', 'microsoft')) {
$fm = Get-Frontmatter $f.LocalPath
$domain = if ($fm.ContainsKey('domain')) { $fm['domain'] } else { '' }
$keywords = if ($fm.ContainsKey('keywords')) { $fm['keywords'].Trim('[', ']') } else { '' }
$rel = $f.Relative -replace '\.md$', ''
$rel = ($f.Relative -replace '\.md$', '') -replace '\\', '/'
$idx.Add("- ``$layer/$rel`` - domain: $domain; keywords: $keywords")
}
$idx.Add('')
}
Set-Content -Path (Join-Path $staging 'INDEX.md') -Value $idx -Encoding utf8
# Swap staging into place
# --- 4. Swap + markoer ---
if (Test-Path $dest) { Remove-Item -Recurse -Force $dest }
Rename-Item -Path $staging -NewName (Split-Path $dest -Leaf)
Set-Content -Path $marker -Value $sha -Encoding ascii
Write-Host ''
Write-Host "Done. $($files.Count) files across $($layerMap.Count) layers."
Write-Host "Done. $($files.Count) filer, 3 lag, stable @ $($sha.Substring(0,7))."
Write-Host "Machine-local mirror updated: $dest"
exit $rc

View file

@ -56,14 +56,11 @@ Loop: **reproduce -> root-cause -> minimal-fix recommendation.**
Layer 1 - Microsoft BCQuality: https://github.com/microsoft/BCQuality
Layer 2 - CURABIS custom knowledge (fetch before citing a finding):
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/architecture/pages-must-not-contain-business-logic.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/architecture/namespace-must-be-verified-from-source.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/architecture/al-identifiers-must-be-english.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/architecture/clarify-before-building.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/testing/test-setup-must-use-library-codeunit.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/testing/test-data-must-be-random-and-complete.md
- https://raw.githubusercontent.com/Curabis/BCQuality/stable/custom/knowledge/testing/tests-must-adapt-to-existing-code.md
Layer 2 - CURABIS custom knowledge: read from the machine-local mirror —
`%USERPROFILE%\.claude\bcquality-knowledge\custom\` (always complete; never a
hardcoded file list — the rulebook grows). Fallback without a mirror: the
channel clone at `%USERPROFILE%\.claude\BCQuality\custom\knowledge\`. The
repo is PRIVATE — raw URLs do not exist.
If a source is unreachable, **degrade gracefully**: fall back to the triage protocol
below plus the CURABIS-ARCH rules in `bcquality.agent.md`, note that BCQuality was

View file

@ -54,10 +54,13 @@ Resolve the current rule set at review time, in this order:
`~/.claude/bcquality-knowledge/custom/` (Windows:
`%USERPROFILE%\.claude\bcquality-knowledge\custom\`). The mirror is synced
from the `stable` release channel and is always the complete custom layer.
2. **Fallback (no mirror — Copilot, fresh machine, CI):** list the tree via
`https://api.github.com/repos/Curabis/BCQuality/git/trees/stable?recursive=1`
filtered to `custom/knowledge/**/*.md`, and fetch each file from
`https://raw.githubusercontent.com/Curabis/BCQuality/stable/<path>`.
2. **Fallback (no mirror):** read directly from the machine's channel clone —
`%USERPROFILE%\.claude\BCQuality\custom\knowledge\**\*.md` (freshen with
`git -C "$env:USERPROFILE\.claude\BCQuality" pull` if stale). The repo is
PRIVATE: tree-API/raw-URL fallbacks no longer exist. Consumers without
filesystem access outside the workspace (e.g. Copilot) rely on the
repo-committed agent files alone — deep custom-layer lookups happen in
Claude Code sessions.
Relevance filtering: `custom/` rules are always active in CURABIS repos — read
them all; use each file's frontmatter `domain`/`keywords` only to prioritize,