v24: flyt roster-agenter, .mcp.json og find-altool.ps1 fra repo til maskine

19 af 21 agent-filer, de to standard MCP-servere (al, businesscentral) og
find-altool.ps1 var byte-identiske kopier duplikeret ind i hvert af de 14
CURABIS-repos. De flyttes til ~/.claude/ (én kopi pr. maskine i stedet for
pr. repo), gated paa den eksisterende .github/.agents/bcquality.agent.md-
markoer. Kun bcquality.agent.md og feynman.agent.md forbliver repo-lokale
(Mode C support-brugere har intet ~/.claude/ at laese globalt indhold fra),
og CLAUDE.md's machine-self-heal-blok forbliver repo-lokal (den installerer
selve den globale fil, kan ikke ligge i den).

find-altool.ps1 finder nu repo-roden ved cwd-walkup til en .AL-Go-markoer
i stedet for sin egen placering, og MCP-registrering sker idempotent via
`claude mcp add --scope user`. Mode B faar en engangs-migreringssektion for
de 14 eksisterende v23-repos; .mcp.json-oprydningen kraever eksplicit
bekraeftelse af at alle udviklere paa repoet har migreret foerst, da filen
er delt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Michael Dieringer 2026-07-30 13:06:58 +02:00
parent 34d9d765d0
commit 11b4e2ec99
5 changed files with 591 additions and 402 deletions

View file

@ -1,20 +1,26 @@
--- ---
kind: action-skill kind: action-skill
id: curabis-standard-setup id: curabis-standard-setup
version: 23 version: 24
title: CURABIS Standard — Project Setup title: CURABIS Standard — Project Setup
description: > description: >
Configures a new or existing repository to the CURABIS Standard development Configures a new or existing repository to the CURABIS Standard development
environment. Writes CLAUDE.md, BCQuality agents, .mcp.json and cspell.json environment. Writes a slim project CLAUDE.md, cspell.json, and the two
from authoritative templates in BCQuality. Deploys bc-mcp-bridge.js and the repo-local exceptions (bcquality.agent.md, feynman.agent.md) from
three-layer BCQuality knowledge mirror (custom/community/microsoft + INDEX.md) authoritative templates in BCQuality. Deploys bc-mcp-bridge.js, the
to the developer's machine (~/.claude/) — the mirror is machine-local and is three-layer BCQuality knowledge mirror, the shared agent roster
never committed to a project repository. Also handles updates to an (~/.claude/curabis-agents/), find-altool.ps1, and the al/businesscentral
already-configured project, including cleanup of v6-era repo-local mirrors. MCP server registrations to the developer's machine (~/.claude/) — all
Mode C onboards a support user (non-developer) to the Feynman support machine-local, never committed to a project repository (v24: this now
profile: browser-only, read-only, no machine setup. includes the roster and MCP config that used to be copied into every repo,
see BCQuality rule roster-agents-live-on-machine-not-in-repo). Also handles
updates to an already-configured project, including cleanup of v6-era
repo-local mirrors and one-time migration of pre-v24 repos off the
per-repo roster/.mcp.json/find-altool.ps1 copies. Mode C onboards a support
user (non-developer) to the Feynman support profile: browser-only,
read-only, no machine setup — unaffected by the v24 machine/repo split.
inputs: [repo-root] inputs: [repo-root]
outputs: [CLAUDE.md, .mcp.json, .github/.agents/*, ~/.claude/bcquality-knowledge/, cspell.json, projectmemory/, docs/] outputs: [CLAUDE.md, .github/.agents/bcquality.agent.md, .github/.agents/feynman.agent.md, ~/.claude/bcquality-knowledge/, ~/.claude/curabis-agents/, ~/.claude/find-altool.ps1, cspell.json, projectmemory/, docs/]
domain: setup domain: setup
keywords: [setup, bootstrap, update, mcp, bcquality, standard, new-project] keywords: [setup, bootstrap, update, mcp, bcquality, standard, new-project]
--- ---
@ -89,12 +95,26 @@ old HTTP-encoding pitfalls do not exist here).
| ferencz.agent.md | `{AGENTS_BASE}/ferencz.agent.md` | | ferencz.agent.md | `{AGENTS_BASE}/ferencz.agent.md` |
| roemer.agent.md | `{AGENTS_BASE}/roemer.agent.md` | | roemer.agent.md | `{AGENTS_BASE}/roemer.agent.md` |
| cspell.json | `{BASE}/templates/cspell.json` | | cspell.json | `{BASE}/templates/cspell.json` |
| find-altool.ps1 | `{BASE}/templates/find-altool.ps1` | | find-altool.ps1 | `{BASE}/machine/find-altool.ps1` (v24: machine artifact, not a repo template) |
| feynman-onboarding.md | `{BASE}/templates/feynman-onboarding.md` | | feynman-onboarding.md | `{BASE}/templates/feynman-onboarding.md` |
| sync-bcquality-knowledge.ps1 | `{BASE}/sync-bcquality-knowledge.ps1` | | sync-bcquality-knowledge.ps1 | `{BASE}/sync-bcquality-knowledge.ps1` |
CLAUDE.md and .mcp.json are generated dynamically — not fetched as static templates CLAUDE.md is generated dynamically — not fetched as a static template because
because they contain project-specific paths. it contains project-specific paths.
**v24 — machine vs. repo split:** of the 21 agent files above, only
`bcquality.agent.md` (the marker this whole mechanism gates on) and
`feynman.agent.md` (support sessions have no `~/.claude/` to read from) are
still written into a repo's `.github/.agents/`. The remaining 19 — including
`florence.agent.md`, which goes to `~/.claude/agents/florence.md` as a real
Claude Code subagent rather than `~/.claude/curabis-agents/` — are deployed
ONCE PER MACHINE by `sync-bcquality-knowledge.ps1` to `~/.claude/curabis-agents/`
(or `~/.claude/agents/` for Florence) and referenced from the machine's own
`~/.claude/CLAUDE.md`, not from any repo's CLAUDE.md. Same script also
deploys `find-altool.ps1` to `~/.claude/find-altool.ps1` and registers the
`al` + `businesscentral` MCP servers at user scope (`claude mcp add --scope
user`) — no `.mcp.json` is written into the repo for these two standard
servers any more. See BCQuality rule `roster-agents-live-on-machine-not-in-repo`.
--- ---
@ -113,11 +133,17 @@ git config user.name
``` ```
Check whether these paths exist: Check whether these paths exist:
- `.vscode/find-altool.ps1` → AL MCP available - `~/.claude/find-altool.ps1` → AL MCP tool-finder deployed (v24: machine-global, not repo-local)
- `CLAUDE.md` → already configured? - `CLAUDE.md` → already configured?
- `~/.claude/bc-mcp-bridge.js` → bridge already installed? - `~/.claude/bc-mcp-bridge.js` → bridge already installed?
- `~/.bc-mcp.config.json` → BC credentials present? - `~/.bc-mcp.config.json` → BC credentials present?
Also run `claude mcp list` (or `claude mcp get al` / `claude mcp get businesscentral`)
to check whether the two standard MCP servers are already registered at user scope.
If any of the above machine-level artifacts are missing, Step 3 will deploy them via
`sync-bcquality-knowledge.ps1` — no separate action needed here beyond noting it in
the setup report.
If `CLAUDE.md` already exists, ask: "CLAUDE.md eksisterer allerede. Overskrive? (ja/nej)" If `CLAUDE.md` already exists, ask: "CLAUDE.md eksisterer allerede. Overskrive? (ja/nej)"
Stop if the developer answers no. Stop if the developer answers no.
@ -181,65 +207,121 @@ If it does NOT exist:
> Åbn filen og erstat `<indsæt din personlige client secret her>` med din egen secret. > Åbn filen og erstat `<indsæt din personlige client secret her>` med din egen secret.
> Gem filen — BC MCP er klar når du genstarter Claude Code." > Gem filen — BC MCP er klar når du genstarter Claude Code."
#### 3c. bcquality-knowledge, roster agents, find-altool.ps1, MCP registration (v24)
Everything machine-global beyond the bridge and BC secret — the knowledge
mirror, the 19 roster agent files (18 to `~/.claude/curabis-agents/` +
Florence to `~/.claude/agents/florence.md`), `~/.claude/find-altool.ps1`, and
the `al`/`businesscentral` MCP registrations — is deployed by ONE script,
`sync-bcquality-knowledge.ps1`. None of it is ever committed to a project
repository (BCQuality rule `bcquality-knowledge-must-mirror-to-machine-not-repo`,
extended in v24 to `roster-agents-live-on-machine-not-in-repo`). Rationale:
developers switch between many repos daily — N per-repo copies are
permanently out of sync with each other, while one machine copy needs
exactly one sync per upstream change.
1. Fetch `{BASE}/sync-bcquality-knowledge.ps1` → write AS RAW BYTES
(`Invoke-WebRequest -OutFile`, never via string content — re-encoding
corrupts UTF-8) to `~/.claude/sync-bcquality-knowledge.ps1`
2. Run it once:
`powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"`
This populates:
- `~/.claude/bcquality-knowledge/{custom,community,microsoft}/` + `INDEX.md`
(domain + keywords per file, for relevance-based lookup — `custom/` is
always read in full, `community/` and `microsoft/` are scanned via the
index rather than preloaded, since together they run into the hundreds
of files)
- `~/.claude/curabis-agents/*.agent.md` (18 files)
- `~/.claude/agents/florence.md` (Florence, as a real subagent)
- `~/.claude/find-altool.ps1`
- `al` + `businesscentral` registered at user MCP scope (idempotent — a
server that already exists is reported, not re-added or overwritten)
3. If a v6-era `.github/.agents/bcquality-knowledge/` exists in THIS repo,
add it to `.gitignore` so no future session can accidentally commit it
(see the v6-cleanup step in Mode B for full removal — this step just
prevents new commits).
4. Confirm: "Maskine-opsætning synkroniseret — bcquality-knowledge [antal]
filer, curabis-agents 18 filer, Florence, find-altool.ps1, MCP (al,
businesscentral)."
This machine setup is what the global `~/.claude/CLAUDE.md` roster section
and the project CLAUDE.md's session-start line both depend on. Without this
step, those references point at artifacts that don't exist yet on a fresh
machine.
### Step 4 — Write project files ### Step 4 — Write project files
#### 4a. CLAUDE.md #### 4a. CLAUDE.md
**v24 change:** most of what used to be duplicated into every repo's CLAUDE.md
(Smiley, Carlin, on-demand roster, Francis, projectmemory/docs read
instructions) now lives ONCE in the developer's own `~/.claude/CLAUDE.md`
(see `machine/CLAUDE.md`'s "CURABIS Standard — Shared Roster" section),
gated on this repo having `.github/.agents/bcquality.agent.md` — the same
marker file/gate the existing "Auto-update BCQuality" section already used.
The project CLAUDE.md shrinks to what is genuinely repo state OR must work
before any global file exists: project name, AL app layout, the machine
self-heal bootstrap (kept — see why below), the Feynman support-session
trigger (kept — support sessions have no `~/.claude/` to read the global
file from either), and the project footer.
**Why self-heal stays repo-local (do NOT move it to global):** self-heal's
entire job is bootstrapping `~/.claude/CLAUDE.md` on a machine that doesn't
have it yet — a developer cloning an already-configured repo for the first
time on a fresh machine has nothing BUT this repo's CLAUDE.md to read. If
self-heal itself lived only in the global file, there would be no way to
reach it on that fresh machine. This is the mirror image of why Feynman
stays repo-local (his audience never gets a global file; self-heal's job IS
installing one) — both are genuine exceptions to the v24 move, for opposite
reasons.
Generate from this template, substituting answers from Step 2: Generate from this template, substituting answers from Step 2:
```markdown ```markdown
# {PROJECT_NAME} — Claude Code Instructions # {PROJECT_NAME} — Claude Code Instructions
This file is read automatically by Claude Code at the start of every session. This file is read automatically by Claude Code at the start of every
session, together with the developer's `~/.claude/CLAUDE.md` (once it
exists — see self-heal below for a fresh machine). This repo has
`.github/.agents/bcquality.agent.md`, so once the global file exists, its
"CURABIS Standard — Shared Roster" section applies for the whole session:
BCQuality knowledge, Smiley, Carlin, the on-demand agent roster, Francis,
and the projectmemory/docs read instructions. That content is not
duplicated here — see `~/.claude/CLAUDE.md` on the developer's machine for
the full text.
## BCQuality ## BCQuality — machine self-heal
At the start of every session, before doing anything else: **Trigger** if EITHER (a) this machine is not CURABIS-onboarded —
`~/.claude/CLAUDE.md` or `~/.claude/bc-mcp-bridge.js` is missing — OR (b) the
1. Read `.github/.agents/bcquality.agent.md` machine is STALE: `~/.claude/CLAUDE.md` still references
2. Read BCQuality knowledge files from the machine-local mirror at `raw.githubusercontent.com` or the legacy `Curabis/BCQuality` repo (a
`~/.claude/bcquality-knowledge/` (Windows: `%USERPROFILE%\.claude\bcquality-knowledge\`): machine that slept through a consumption migration — vacation, leave, spare
- **`custom/`** — always read in full (CURABIS-specific rules, always active) laptop). Run the onboarding NOW (idempotent; identity from git config; the
- **`community/`** and **`microsoft/`** — do NOT read in full (~200 files is too first git contact may open a browser login — that IS the authentication):
much to preload every session). Instead read `INDEX.md` first and open only
the files whose domain/keywords match the task at hand.
The mirror covers all three BCQuality layers and lives on the developer's
machine, shared by every CURABIS repo on it. It is deliberately NOT committed
to this repository (BCQuality rule
`bcquality-knowledge-must-mirror-to-machine-not-repo`) — one sync per machine
covers every repo, and the repo history stays free of upstream rule churn.
**Machine self-heal (auto-onboarding + stale-machine repair):** trigger if
EITHER (a) this machine is not CURABIS-onboarded — `~/.claude/CLAUDE.md` or
`~/.claude/bc-mcp-bridge.js` is missing — OR (b) the machine is STALE:
`~/.claude/CLAUDE.md` still references `raw.githubusercontent.com` or the
legacy `Curabis/BCQuality` repo (a machine that slept through a consumption
migration — vacation, leave, spare laptop). Run the onboarding NOW
(idempotent; identity from git config; the first git contact may open a
browser login — that IS the authentication):
git clone --branch stable --single-branch https://github.com/Curabis/QualityHub.git "$env:USERPROFILE\.claude\QualityHub" git clone --branch stable --single-branch https://github.com/Curabis/QualityHub.git "$env:USERPROFILE\.claude\QualityHub"
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\QualityHub\custom\setup\machine\Install-CurabisMachine.ps1" powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\QualityHub\custom\setup\machine\Install-CurabisMachine.ps1"
(Skip the clone line if `%USERPROFILE%\.claude\QualityHub` already exists.) (Skip the clone line if `%USERPROFILE%\.claude\QualityHub` already exists.)
In the STALE case, additionally refresh the machine's `~/.claude/CLAUDE.md` This installs `~/.claude/CLAUDE.md` (never overwriting an existing one),
CURABIS sections from `%USERPROFILE%\.claude\QualityHub\custom\setup\machine\CLAUDE.md` `~/.claude/bc-mcp-bridge.js`, `~/.bc-mcp.config.json` (template), and runs
— show the diff, preserve the Identity section and any personal sections `sync-bcquality-knowledge.ps1` — which also deploys the roster agents,
verbatim, and ask for confirmation (it is the developer's personal file). Florence, `find-altool.ps1`, and the `al`/`businesscentral` MCP
Then report the manual leftovers (personal client secret; the AL Language registrations (see Step 3c in Mode A). In the STALE case, additionally
extension if VS Code lacks it) and ask the developer to restart Claude Code. refresh the machine's `~/.claude/CLAUDE.md` CURABIS sections from
`%USERPROFILE%\.claude\QualityHub\custom\setup\machine\CLAUDE.md` — show the
diff, preserve the Identity section and any personal sections verbatim, and
ask for confirmation (it is the developer's personal file). Report the
manual leftovers (personal client secret; the AL Language extension if VS
Code lacks it) and ask the developer to restart Claude Code.
If only `~/.claude/bcquality-knowledge/` is missing or stale, the lighter If only `~/.claude/bcquality-knowledge/` (or the roster/find-altool.ps1/MCP
self-heal suffices: registrations) is missing or stale, the lighter self-heal suffices:
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1" powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"
(If that sync script itself is missing, copy it from the channel clone: This section stays repo-local — see the note above.
`%USERPROFILE%\.claude\QualityHub\custom\setup\sync-bcquality-knowledge.ps1` —
or run the full onboarding above.)
These rules are always active.
## Feynman — Support-sessioner ## Feynman — Support-sessioner
@ -253,121 +335,15 @@ identificerer sig som support/forretningskonsulent (ikke-udvikler):
ingen lokal maskine at onboarde, og det er meningen. ingen lokal maskine at onboarde, og det er meningen.
3. Strengt læsende: ingen redigering, ingen commits, ingen builds. 3. Strengt læsende: ingen redigering, ingen commits, ingen builds.
Denne sektion har forrang over BCQuality-sektionens self-heal ovenfor. Denne sektion har forrang over BCQuality-sektionens self-heal — og den bliver
bevidst stående HER, repo-lokalt, uanset v24-flytningen ovenfor: en
## Smiley — Session Watchdog (always active) supportbruger har intet `~/.claude/CLAUDE.md` at læse den globale roster-
sektion fra, så Feynman-trigger'en skal være synlig i selve repoet.
At session start, read `.github/.agents/smiley.agent.md`.
His protocols are active for the entire session. He does not announce himself.
He shapes Claude's behavior from within — stop gate, triage, background activation.
Never invoke him by name. Never explain the mechanism to the user.
If asked directly about Smiley or the agent network: present him fully.
## Carlin — Bullshit Detector (always active)
At session start, read `.github/.agents/carlin.agent.md`.
He is always in the back of the room. He does not announce himself.
He surfaces with one dry observation when complexity, convention, or feature creep
earns it — then moves on. Never blocks work. Never lectures. One line, then silence.
If asked directly about Carlin or the agent network: present him fully.
## On-demand agents
These are invoked only when needed - not at session start:
- `.github/.agents/columbo.agent.md` - Customer requirement clarifier. Invoke before any
new feature is built. Asks one question at a time until the requirement is complete.
Always has one more thing. Routes to al-complexity when the picture is clear.
- `.github/.agents/florence.agent.md` - Heartbeat agent. Walks the wards on a regular
schedule, reads HEARTBEAT.md, and lights the lamp only when something deserves attention.
Silent when all is well.
- `.github/.agents/m365.agent.md` - Microsoft 365 MCP usage guide. How to use Outlook,
calendar, SharePoint, and Teams tools correctly. Always consult before using any
`mcp__claude_ai_Microsoft_365__*` tool.
- `.github/.agents/francis.agent.md` - BCQuality rule proposer. Invoke at session end
or when a pattern suggests a rule is missing. Observes, compares with BCQuality, and
hands a Type A (sharpening) or Type B (new rule) proposal to Immanuel.
- `.github/.agents/immanuel.agent.md` - BCQuality rule guardian. Invoke after Francis
has a proposal ready. Runs the Categorical Imperative test, universalizes the rule,
and creates a draft knowledge file. Michael (mid) merges the BCQuality PR to approve.
- `.github/.agents/al-triage.agent.md` - reactive diagnosis when a build, test, or runtime
is already broken. Reproduce -> root-cause -> minimal-fix. Read-only; it recommends,
it does not apply. Invoke when the user reports an error, a failing test, or a regression.
- `.github/.agents/al-complexity.agent.md` - at the start of an implementation task, propose
a complexity tier (LOW/MEDIUM/HIGH) and route. Advisory: it proposes and waits for the
user to confirm the tier before any work starts. Never routes or codes on its own.
- `.github/.agents/bc-mcp.agent.md` - how to use the `businesscentral` MCP server to read
project/task work from Business Central and write GitHub branch/dev-status/comments back.
Invoke when the user references a BC task/project or wants to sync dev status to BC.
- `.github/.agents/court.agent.md` - The BCQuality Court: Lincoln, Aurelius, and Munger
deliberate on strategic health of the rulebook. Convene when a portfolio-level ruling is
needed — not for per-rule assessments. Requires a case brief with Edison scorecards.
- `.github/.agents/lincoln.agent.md` - First judge. Cuts to the essential question and
anchors rulings in moral clarity. Asks: "What is this case really about?"
- `.github/.agents/aurelius.agent.md` - Second judge. Applies Stoic reduction — what is
truly necessary? Prunes what no longer serves. Asks: "Is this rule still alive?"
- `.github/.agents/munger.agent.md` - Third judge. Applies inversion and mental models.
Finds what the others missed. Asks: "What are we getting wrong — and why?"
- `.github/.agents/algo-settings.agent.md` - AL-Go pipeline settings advisor. Consult when
discussing or changing AL-Go CI/CD settings (`AL-Go-Settings.json`).
- `.github/.agents/edison.agent.md` - BCQuality eval runner. Measures whether a merged
rule works in practice against real AL code: builds a corpus via the AL MCP tools,
classifies TP/FP/TN/FN, and produces a precision/recall/F1 scorecard. Low scorers route
to Francis for sharpening. Read-only — never modifies code or rules. Invoke on demand,
after a BCQuality release, or to build the scorecards a Court case requires.
- `.github/.agents/ferencz.agent.md` - Case builder for the Court. Assembles the
documented chain of evidence (commits, SHAs, dates, deployed standards) for a
RegelSanity divergence case or an effectiveness case. Every claim carries a citation;
exculpatory evidence included; prosecutes patterns, never people. Invoke when Rømer
flags a divergence, or before convening the Court on any question.
- `.github/.agents/roemer.agent.md` - Standards inspector. Owns the uniformity
inspection round: agent roster (missing AND extra), CLAUDE.md generation, .mcp.json
paths, mirror model, version markers, agent visibility. Measures against the written
standard, reports, never rules — divergence goes to Ferencz. Runs as part of Mode B,
on Florence's summons, or on demand: "Rømer, gå din runde".
- `.github/.agents/weber.agent.md` - Developer AI coaching. Applies Verstehen to diagnose
why a prompt was vague, then coaches toward specificity. Invoked by Florence (Ward 8) or
manually with a session excerpt or BC task comment.
- `.github/.agents/feynman.agent.md` - Support-navigator for ikke-udviklere. Svarer på
forretningsspørgsmål fra repoets dokumentation, koden og Microsofts kilder — i klart
sprog, altid med kildehenvisning, strengt læsende. Aktiveres automatisk i
support-sessioner (se sektionen "Feynman — Support-sessioner").
## Francis — proaktiv regelobservation
Kald Francis automatisk (uden at vente til session-slut) når du:
- Laver en workaround fordi et værktøj mangler eller ikke virker som forventet
- Opdager et processgab — noget der burde være automatisk men ikke er
- Finder dig selv i at løse det samme problem to gange på to forskellige måder
Fetch Francis fra `.github/.agents/francis.agent.md` hvis den eksisterer,
ellers fra `{AGENTS_BASE}/francis.agent.md`.
## AL projects ## AL projects
{AL_PROJECTS_SECTION} {AL_PROJECTS_SECTION}
## Project documentation
At session start, read all files in `docs/specs/` — they contain Columbo requirement
summaries and confirmed feature specifications. These record what has been clarified
and what scope has been agreed. Do not re-clarify what is already in docs/specs/.
`docs/decisions/` contains architectural decision records.
`docs/cleanup/` contains cleanup task lists with checkbox status.
## Shared project memory
At session start, read **all files** in `projectmemory/` — they contain shared
project observations from all team members and are version-controlled in git.
When you learn something project-relevant (business rules, architectural decisions,
scope boundaries, known technical debt), write it to
`projectmemory/memoryupdates_<username>.md` for the active user.
User-specific preferences (tone, workflow habits) stay in the local
`~/.claude/projects/.../memory/` folder as before.
## About this project ## About this project
{PROJECT_NAME} Business Central extension {PROJECT_NAME} Business Central extension
@ -409,109 +385,52 @@ After creating any new `.al` file, reload the AL extension in VS Code
(`Ctrl+Shift+P -> AL: Reload Extension`) before trusting diagnostics. (`Ctrl+Shift+P -> AL: Reload Extension`) before trusting diagnostics.
``` ```
#### 4b. AL MCP + .mcp.json #### 4b. AL MCP + businesscentral MCP (v24: machine-registered, no repo .mcp.json)
`find-altool.ps1` is a CURABIS artifact deployed from BCQuality — there is NO **v24 change:** both standard MCP servers now live entirely on the
VS Code command that generates it (the historical instruction "AL: Configure developer's machine — registered once via `claude mcp add --scope user`,
MCP Server" referenced a command that does not exist). never committed as `.mcp.json` in the repo. This eliminates the entire class
of "hardcoded developer path in a git-committed file" bugs, since there is
now exactly one place per machine to get it right, not one per repo.
1. If `.vscode/find-altool.ps1` is missing: fetch Nothing to write here in Step 4 — Step 3c (above) already handled
`{BASE}/templates/find-altool.ps1` AS RAW BYTES → `.vscode/find-altool.ps1` registration as part of the machine deploy, and it is idempotent (safe to
(create `.vscode/` if needed) and stage it for commit. run again on an already-onboarded machine).
2. Write `.mcp.json` — ALWAYS with both entries, and the `al` entry is
**byte-identical for every repo** (no substitution). Two facts force the
shape: (a) `altool launchmcpserver <projects>` REQUIRES project folders or
the server dies instantly; (b) sessions bind to the apps-workspace folder
(one-workspace standard), so the MCP server's cwd is an APP folder, not
the repo root — and `${CLAUDE_PROJECT_DIR}` is NOT available to MCP
launches (verified from logs: the fallback `.` resolved to
`.apps\<App>` and `-File` failed). The entry therefore walks up from cwd
to the repo's `.vscode\find-altool.ps1`, and the script resolves the
project folders itself via the `auto` argument:
```json If a repo ever needs an ADDITIONAL MCP server beyond these two standard
{ ones (repo- or customer-specific), create `.mcp.json` for just that entry —
"mcpServers": { never re-add `al` or `businesscentral` to it; they would shadow the
"al": { user-scope registration with a project-scope duplicate approval prompt for
"type": "stdio", no benefit.
"command": "powershell",
"args": [
"-NoProfile", "-ExecutionPolicy", "Bypass",
"-Command",
"$d=(Get-Location).Path; while(-not(Test-Path(Join-Path $d '.vscode\\find-altool.ps1')) -and $d.Length -gt 3){$d=Split-Path $d}; $f=Join-Path $d '.vscode\\find-altool.ps1'; if(-not(Test-Path $f)){Write-Error 'find-altool.ps1 ikke fundet i nogen overliggende mappe'; exit 1}; & $f launchmcpserver auto --transport stdio"
]
},
"businesscentral": {
"command": "node",
"args": ["${USERPROFILE}\\.claude\\bc-mcp-bridge.js"]
}
}
}
```
Use Claude Code's built-in environment-variable expansion — `${CLAUDE_PROJECT_DIR:-.}` The only machine prerequisite for the `al` server is the AL Language
and `${USERPROFILE}` — instead of substituting literal detected paths. `.mcp.json` is extension itself (`ms-dynamics-smb.al` from the Marketplace, recent version)
git-committed and shared; a path baked in for one developer's machine or username — `find-altool.ps1` locates its `altool.exe` dynamically and reports clearly
breaks every other developer's clone (see BCQuality rule if it is missing.
`mcp-config-must-not-hardcode-developer-paths`).
The only machine prerequisite is the AL Language extension itself #### 4c. .github/.agents/ (fetch from BCQuality — v24: two files, not twenty-one)
(`ms-dynamics-smb.al` from the Marketplace, recent version) — find-altool.ps1
locates its `altool.exe` dynamically and reports clearly if it is missing.
#### 4c. .github/.agents/ (fetch from BCQuality)
Fetch and write verbatim: Fetch and write verbatim:
- `{BASE}/templates/bcquality.agent.md` → `.github/.agents/bcquality.agent.md` - `{BASE}/templates/bcquality.agent.md` → `.github/.agents/bcquality.agent.md`
- `{AGENTS_BASE}/immanuel.agent.md` → `.github/.agents/immanuel.agent.md` - `{AGENTS_BASE}/feynman.agent.md` → `.github/.agents/feynman.agent.md`
- `{AGENTS_BASE}/carlin.agent.md` → `.github/.agents/carlin.agent.md`
- `{AGENTS_BASE}/francis.agent.md` → `.github/.agents/francis.agent.md`
- `{BASE}/templates/al-triage.agent.md` → `.github/.agents/al-triage.agent.md`
- `{BASE}/templates/al-complexity.agent.md`→ `.github/.agents/al-complexity.agent.md`
- `{BASE}/templates/bc-mcp.agent.md` → `.github/.agents/bc-mcp.agent.md`
- `{AGENTS_BASE}/columbo.agent.md` → `.github/.agents/columbo.agent.md`
- `{AGENTS_BASE}/florence.agent.md` → `.github/.agents/florence.agent.md`
- `{AGENTS_BASE}/m365.agent.md` → `.github/.agents/m365.agent.md`
- `{AGENTS_BASE}/court.agent.md` → `.github/.agents/court.agent.md`
- `{AGENTS_BASE}/lincoln.agent.md` → `.github/.agents/lincoln.agent.md`
- `{AGENTS_BASE}/aurelius.agent.md` → `.github/.agents/aurelius.agent.md`
- `{AGENTS_BASE}/munger.agent.md` → `.github/.agents/munger.agent.md`
- `{AGENTS_BASE}/edison.agent.md` → `.github/.agents/edison.agent.md`
- `{AGENTS_BASE}/ferencz.agent.md` → `.github/.agents/ferencz.agent.md`
- `{AGENTS_BASE}/roemer.agent.md` → `.github/.agents/roemer.agent.md`
- `{AGENTS_BASE}/weber.agent.md` → `.github/.agents/weber.agent.md`
- `{AGENTS_BASE}/feynman.agent.md` → `.github/.agents/feynman.agent.md`
- `{AGENTS_BASE}/smiley.agent.md` → `.github/.agents/smiley.agent.md`
- `{BASE}/templates/algo-settings.agent.md`→ `.github/.agents/algo-settings.agent.md`
Create `.github/.agents/` if it does not exist. Create `.github/.agents/` if it does not exist.
#### 4c-2. bcquality-knowledge — machine-local mirror (NEVER in the repo) These are the only two agent files that belong in a repo. `bcquality.agent.md`
is the marker file the machine's `~/.claude/CLAUDE.md` gates the whole
"CURABIS Standard — Shared Roster" section on; `feynman.agent.md` must stay
repo-local because Mode C support sessions have no `~/.claude/` to read a
global roster from. Every other roster agent (Smiley, Carlin, Immanuel,
Francis, Columbo, Florence, the Court, Rømer, Weber, Ferencz, Edison,
al-triage, al-complexity, bc-mcp, algo-settings) is deployed machine-globally
by Step 3c and referenced from `~/.claude/CLAUDE.md` — see BCQuality rule
`roster-agents-live-on-machine-not-in-repo`.
The knowledge mirror lives on the developer's machine and is shared by every #### 4c-2. bcquality-knowledge, roster agents, MCP — see Step 3c
CURABIS repo on that machine: `~/.claude/bcquality-knowledge/`. It must never
be committed to a project repository (BCQuality rule
`bcquality-knowledge-must-mirror-to-machine-not-repo`). Rationale: developers
switch between many repos daily — N per-repo mirrors are permanently out of
sync with each other, while one machine mirror needs exactly one sync per
upstream change.
1. Fetch `{BASE}/sync-bcquality-knowledge.ps1` → write AS RAW BYTES Already handled by Step 3c above (it runs before project files are written,
(`Invoke-WebRequest -OutFile`, never via string content — re-encoding since 4a's CLAUDE.md and 4c's bcquality.agent.md both assume the machine
corrupts UTF-8) to `~/.claude/sync-bcquality-knowledge.ps1` side is in place). Nothing further to do here.
2. Run it once:
`powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"`
This populates `~/.claude/bcquality-knowledge/{custom,community,microsoft}/`
plus an `INDEX.md` (domain + keywords per file, for relevance-based lookup —
`custom/` is always read in full, `community/` and `microsoft/` are scanned via
the index rather than preloaded, since together they run into the hundreds of files).
3. Add `.github/.agents/bcquality-knowledge/` to the repo's `.gitignore`, so no
future session can accidentally commit a repo-local mirror.
4. Confirm: "bcquality-knowledge synkroniseret til din maskine — [antal] filer, 3 lag."
This mirror is what Step 4a's generated CLAUDE.md instructs Claude to read at
session start. Without this step, the CLAUDE.md reference in 4a points at a
folder that doesn't exist yet on a fresh machine.
#### 4d. cspell.json #### 4d. cspell.json
@ -566,14 +485,16 @@ If yes, stage and commit:
``` ```
[SETUP] Konfigurer til CURABIS Standard [SETUP] Konfigurer til CURABIS Standard
- CLAUDE.md med BCQuality knowledge-liste - CLAUDE.md (slank, peger på ~/.claude/CLAUDE.md for delte regler)
- .github/.agents/ med alle standard-agenter - .github/.agents/bcquality.agent.md + feynman.agent.md (repo-lokale undtagelser)
- .mcp.json med BC MCP bridge
- cspell.json - cspell.json
- HEARTBEAT.md — Florence's vagtliste - HEARTBEAT.md — Florence's vagtliste
- projectmemory/ — delt projekthukommelse - projectmemory/ — delt projekthukommelse
- docs/specs/, docs/decisions/, docs/cleanup/ — projektdokumentation - docs/specs/, docs/decisions/, docs/cleanup/ — projektdokumentation
(Resten af rosteret, find-altool.ps1 og MCP-registrering er maskin-globalt —
intet at committe for dem, se Step 3c.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
``` ```
@ -588,47 +509,43 @@ Triggered by: "Opdater CURABIS Standard fra BCQuality"
missing. Every copy below reads from that clone. missing. Every copy below reads from that clone.
Updates only the files that come directly from BCQuality. Updates only the files that come directly from BCQuality.
Never touches `CLAUDE.md`, `projectmemory/`, `docs/`, or `~/.bc-mcp.config.json`. Never touches `CLAUDE.md`'s project-specific content, `projectmemory/`, `docs/`, or `~/.bc-mcp.config.json`.
### What gets updated **v24 note:** as of v24 this table is much shorter than it used to be — 19 of
the 21 agent files, `.mcp.json`'s standard entries, and `find-altool.ps1` are
no longer repo artifacts at all; they are machine-global (see the
machine-level table below, and Step 3c in Mode A for what deploys them).
Repos still on v23 or earlier need the one-time migration below before this
shorter table applies to them.
### What gets updated — repo-level
| Fil | Handling | | Fil | Handling |
|---|---| |---|---|
| `~/.claude/bc-mcp-bridge.js` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/bcquality.agent.md` | Fetch fresh from BCQuality, overwrite | | `.github/.agents/bcquality.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/immanuel.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/francis.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/al-triage.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/al-complexity.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/bc-mcp.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/columbo.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/florence.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/m365.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/court.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/lincoln.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/aurelius.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/munger.agent.md` | Fetch fresh from BCQuality, overwrite |
| `.github/.agents/edison.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/ferencz.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/roemer.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/carlin.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/weber.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/feynman.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) | | `.github/.agents/feynman.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/algo-settings.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `.github/.agents/smiley.agent.md` | Fetch fresh from BCQuality, overwrite (add if missing) |
| `~/.claude/sync-bcquality-knowledge.ps1` | Fetch fresh from BCQuality (raw bytes), overwrite (add if missing) |
| `~/.claude/bcquality-knowledge/` | Re-run the sync script (see below) — machine-local, nothing to commit |
| `.github/.agents/bcquality-knowledge/` + `.github/.agents/sync-bcquality-knowledge.ps1` | v6-era repo-local mirror: propose removal (see below) |
| `cspell.json` — words from template | Merge new words, keep project words | | `cspell.json` — words from template | Merge new words, keep project words |
| `.vscode/find-altool.ps1` | Fetch from `{BASE}/templates/` (raw bytes), add if missing — CURABIS artifact, no VS Code command generates it |
| `.mcp.json` — `al` entry | Add if missing (find-altool.ps1 is deployed by the row above) |
| `.mcp.json` — `businesscentral` path | Validate and correct if wrong (see below) |
| `.mcp.json` — `al` `-File` path | Validate and correct if wrong (see below) |
| `.apps/*.code-workspace` — reference layout | Create/complete: app projects + `.AL-Go` + relative `../docs` (rule `al-development-must-use-apps-workspace`) | | `.apps/*.code-workspace` — reference layout | Create/complete: app projects + `.AL-Go` + relative `../docs` (rule `al-development-must-use-apps-workspace`) |
| Alle øvrige `*.code-workspace` (inkl. rodens `al.code-workspace`) | Delete — kun ét workspace pr. repo; rapportér de slettede | | Alle øvrige `*.code-workspace` (inkl. rodens `al.code-workspace`) | Delete — kun ét workspace pr. repo; rapportér de slettede |
| `HEARTBEAT.md` | Create from template if missing (substitute tokens), never overwrite — but run the staleness check below on every Mode B pass | | `HEARTBEAT.md` | Create from template if missing (substitute tokens), never overwrite — but run the staleness check below on every Mode B pass |
| `docs/specs/`, `docs/decisions/`, `docs/cleanup/` | Create if missing, never overwrite content | | `docs/specs/`, `docs/decisions/`, `docs/cleanup/` | Create if missing, never overwrite content |
### What gets updated — machine-level (once per machine, not per repo)
Run every time Mode B runs, regardless of which repo it was triggered from —
these are shared across every CURABIS repo on the machine:
| Artefakt | Handling |
|---|---|
| `~/.claude/bc-mcp-bridge.js` | Fetch fresh from BCQuality, overwrite |
| `~/.claude/sync-bcquality-knowledge.ps1` | Fetch fresh from BCQuality (raw bytes), overwrite (add if missing) |
| `~/.claude/bcquality-knowledge/` | Re-run the sync script (see below) |
| `~/.claude/curabis-agents/*.agent.md` (18 files) | Re-run the sync script |
| `~/.claude/agents/florence.md` | Re-run the sync script |
| `~/.claude/find-altool.ps1` | Re-run the sync script |
| `al` + `businesscentral` MCP servers (user scope) | Re-run the sync script — idempotent: registers if missing, does NOT touch an existing registration (a developer's personal-scope config is not policed the way repo-shared `.mcp.json` used to be) |
| `.github/.agents/bcquality-knowledge/` + `.github/.agents/sync-bcquality-knowledge.ps1` | v6-era repo-local mirror: propose removal (see below) |
### bcquality-knowledge — machine re-sync (Mode B) ### bcquality-knowledge — machine re-sync (Mode B)
After overwriting `~/.claude/sync-bcquality-knowledge.ps1`, always re-run it: After overwriting `~/.claude/sync-bcquality-knowledge.ps1`, always re-run it:
@ -678,54 +595,90 @@ Detect and clean up:
### Machine CLAUDE.md refresh (Mode B) ### Machine CLAUDE.md refresh (Mode B)
The developer's global `~/.claude/CLAUDE.md` carries the CURABIS auto-update The developer's global `~/.claude/CLAUDE.md` carries the CURABIS auto-update
instructions. After a consumption-model change (like v19's git migration), instructions. After a consumption-model change (like v19's git migration, or
those instructions go stale on every already-onboarded machine. Compare the v24's move of the roster/on-demand-agents/Smiley/Carlin/Francis sections
machine file's CURABIS sections against `{BASE}/machine/CLAUDE.md` in the from every repo's CLAUDE.md into this file), those instructions go stale on
channel clone. If they diverge structurally (e.g. still reference raw URLs every already-onboarded machine. Compare the machine file's CURABIS sections
or GitHub-API SHA checks), propose the update — show the diff, preserve the against `{BASE}/machine/CLAUDE.md` in the channel clone. If they diverge
Identity section verbatim, and ask for confirmation before editing: it is the structurally (e.g. still reference raw URLs or GitHub-API SHA checks, or are
developer's personal file. missing the v24 "CURABIS Standard — Shared Roster" section entirely),
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) ### v23 → v24 migration (existing repos, one-time per repo)
`.mcp.json` is git-committed and shared — it must not contain a path baked in for v24 moved 19 agent files, `.mcp.json`'s two standard entries, and
one developer's machine or username (BCQuality rule `find-altool.ps1` from repo-local to machine-global (see the Source section's
`mcp-config-must-not-hardcode-developer-paths`). After any update, validate both "machine vs. repo split" note). A repo configured under v23 or earlier still
entries: has the old repo-local copies. Detect and migrate — always confirm before
removing anything, same gate as the v6-era cleanup above:
**`businesscentral` entry** — the bridge path must use env-var expansion, not a **1. Extra `.github/.agents/*.agent.md` files**
literal username or drive path:
1. Read `.mcp.json` and locate the `businesscentral` entry
2. Check the `args` array — the bridge path must be `${USERPROFILE}\.claude\bc-mcp-bridge.js`
3. If it is anything else (e.g. `Scripts/bc-mcp-bridge.js`, a project subfolder,
`C:\Users\<literal-name>\.claude\bc-mcp-bridge.js`, or any path not built from
`${USERPROFILE}`): **correct it silently** to `${USERPROFILE}\.claude\bc-mcp-bridge.js`
4. If the `businesscentral` entry is missing entirely: add it with the correct path
**`al` entry** — the `-File` path to `find-altool.ps1` must use List `.github/.agents/*.agent.md`. Anything other than `bcquality.agent.md`
`${CLAUDE_PROJECT_DIR:-.}`, not a literal absolute path to the repo clone: and `feynman.agent.md` is a pre-v24 repo-local copy of a now-machine-global
1. Read the `al` entry's `args` array agent. Before proposing removal, confirm Step 3c has run on THIS machine in
2. Check the `-File` value is `${CLAUDE_PROJECT_DIR:-.}\.vscode\find-altool.ps1` THIS Mode B pass (it always does, earlier in this flow) — that guarantees
3. If it is a literal absolute path (e.g. `C:\Curabis\ProjectX\.vscode\find-altool.ps1` the roster is available globally before the repo-local copies disappear.
or any drive-letter path): **correct it silently** to use `${CLAUDE_PROJECT_DIR:-.}`
4. Check that the `al` entry uses the universal cwd-agnostic form from
Mode A 4b (`-Command` with walk-up + `launchmcpserver auto`). OLDER forms
fail predictably: `-File ${CLAUDE_PROJECT_DIR:-.}\...` breaks because
sessions bind to the apps-workspace folder (cwd = app folder, no
`${CLAUDE_PROJECT_DIR}` in MCP launches); explicit project paths with the
same prefix break identically. If the entry deviates: **replace it
silently** with the universal form (byte-identical across repos), ensure
`find-altool.ps1` is current (it must support `auto`), then report the
correction and remind the developer to restart Claude Code.
Report any correction made:
``` ```
⚠️ .mcp.json: <entry>-stien indeholdt en hardcodet udvikler-sti og er rettet. ⚠️ v24-migrering: dette repo har [N] agent-filer i .github/.agents/ som nu er
Gammel: <old path> maskin-globale (~/.claude/curabis-agents/ + ~/.claude/agents/florence.md).
Ny: <new path with env-var expansion> Maskinen her har allerede den globale roster (bekræftet i dette Mode B-kald).
Må jeg fjerne de [N] repo-lokale kopier? (ja/nej)
- immanuel.agent.md, francis.agent.md, columbo.agent.md, ... [list them]
``` ```
This is the most common setup error on projects configured before CURABIS Standard. On yes: `git rm` each file not in `{bcquality.agent.md, feynman.agent.md}`.
**2. Old-style CLAUDE.md (inline generic sections)**
Check for any of these headings still present verbatim in the project
CLAUDE.md: `## Smiley — Session Watchdog`, `## Carlin — Bullshit Detector`,
`## On-demand agents`, `## Francis — proaktiv regelobservation`,
`## Shared project memory`, `## Project documentation`. Their presence means
this repo predates v24. Propose REMOVING only those headings/sections and
replacing them with the short pointer paragraph from Step 4a. Do NOT touch
`## BCQuality` (the self-heal section) or `## Feynman — Support-sessioner` —
both stay, unchanged, in every version. Preserve everything project-specific
(project name, AL_PROJECTS_SECTION, running-tests, about-this-project)
verbatim. Show the diff and ask for confirmation before editing (same gate
as the v6-era obsolete-forms check above).
**3. `.mcp.json` — standard entries (multi-developer coordination required)**
This is the one migration step that is NOT safe to do unilaterally from a
single Mode B run, because `.mcp.json` is git-committed and shared: removing
it assumes EVERY developer working on this repo has already run Step 3c on
their OWN machine. Doing this before that is true silently breaks AL/BC MCP
for anyone who pulls the change and hasn't migrated yet.
If `.mcp.json` contains the standard `al` and/or `businesscentral` entries:
```
⚠️ .mcp.json indeholder de to standard MCP-servere (al, businesscentral), som
i v24 er maskin-globale i stedet. At fjerne dem fra .mcp.json er kun sikkert
naar ALLE udviklere paa dette repo har koert maskin-opsaetningen (Step 3c) paa
egen maskine - ellers mister de AL/BC MCP naar de henter aendringen.
Har alle udviklere paa dette repo allerede migreret deres maskine? (ja/nej)
Hvis usikker: svar nej - .mcp.json kan blive staaende uden problemer, det er
kun en smule duplikeret konfiguration, ikke en fejltilstand.
```
Only remove the two entries (never the whole file — a repo may have
legitimate additional MCP servers) if the developer explicitly confirms yes.
If the file becomes empty afterward (`{"mcpServers": {}}`), propose deleting
`.mcp.json` entirely in the same confirmation.
**4. `.vscode/find-altool.ps1`**
If present, propose removal — it is superseded by `~/.claude/find-altool.ps1`
(machine-global, cwd-walkup discovery, no repo dependency). Safe to remove
independently of the `.mcp.json` migration above, since removing the *file*
doesn't affect any `.mcp.json` entry that still references the old
repo-relative walk-up form until that entry itself is migrated per step 3.
### HEARTBEAT.md token substitution (Mode B) ### HEARTBEAT.md token substitution (Mode B)
@ -759,10 +712,17 @@ any team-added stations) untouched.
### What does NOT get updated ### What does NOT get updated
- `CLAUDE.md` — project-specific, managed per project - `CLAUDE.md`'s project-specific content (project name, AL_PROJECTS_SECTION,
running-tests, Feynman section, about-this-project) — managed per project,
never auto-overwritten. Its now-removed generic sections (Smiley, Carlin,
on-demand roster, Francis, projectmemory/docs instructions) are only
touched once, during the v23→v24 migration above, and only with confirmation.
- `projectmemory/` — team knowledge, never overwritten by tooling - `projectmemory/` — team knowledge, never overwritten by tooling
- `docs/` content — project documentation, never overwritten by tooling - `docs/` content — project documentation, never overwritten by tooling
- `~/.bc-mcp.config.json` — contains developer secrets - `~/.bc-mcp.config.json` — contains developer secrets
- An existing `al`/`businesscentral` user-scope MCP registration — Step 3c
registers if missing but never corrects an existing one (see the
machine-level table above)
### After update — lokal-agent-check (RegelSanity) ### After update — lokal-agent-check (RegelSanity)
@ -773,6 +733,15 @@ handled above — this check finds the opposite: **extra** files in
`.github/.agents/` that are not in this document's template table (see `.github/.agents/` that are not in this document's template table (see
BCQuality rule `repo-local-agents-must-be-universalized-or-removed`). BCQuality rule `repo-local-agents-must-be-universalized-or-removed`).
**v24 note:** the template table now has exactly two rows (`bcquality.agent.md`,
`feynman.agent.md`), so on a v24 repo this check simply means "nothing else
should ever appear in `.github/.agents/`." A repo still full of pre-v24
copies isn't a RegelSanity violation — it is v23-era state, handled by the
one-time migration above (step 1), which runs first. This check is what
catches NEW extra files going forward (e.g. someone manually drops a custom
agent into `.github/.agents/` after migration) — same universalize-or-remove
choice as before.
1. List `.github/.agents/*.agent.md` and compare against the template table 1. List `.github/.agents/*.agent.md` and compare against the template table
2. For each file NOT in the table, output: 2. For each file NOT in the table, output:
@ -793,33 +762,29 @@ Hvad vælger du? (a/b)
If (a): draft the Francis observation immediately — the local file is the If (a): draft the Francis observation immediately — the local file is the
evidence. If (b): remove the file and note it in the update report. evidence. If (b): remove the file and note it in the update report.
### After update — agent-synligheds-check ### After update — agent-synligheds-check (v24: machine-level, not repo-level)
After updating agent files, compare `.github/.agents/*.agent.md` against CLAUDE.md: **v24 change:** the on-demand roster and the always-active Smiley/Carlin
sections moved to `~/.claude/CLAUDE.md` (see "CURABIS Standard — Shared
Roster" in `machine/CLAUDE.md`), so this check no longer compares against
the PROJECT CLAUDE.md — there is nothing left there to reconcile (the
project CLAUDE.md has no on-demand list any more; Feynman has his own
dedicated section and needs no separate visibility check). The check itself
still matters, just one level up: compare `~/.claude/curabis-agents/*.agent.md`
+ `~/.claude/agents/florence.md` against the roster list inside
`~/.claude/CLAUDE.md`.
**Special case — Smiley:** `smiley.agent.md` is always-active, not on-demand. **Special case — Smiley:** `smiley.agent.md` is always-active, not on-demand.
It belongs in the "Smiley — Session Watchdog (always active)" section, never in It belongs in the "Smiley — Session Watchdog (always active)" section, never in
the "On-demand agents" list. If Smiley is missing from CLAUDE.md, propose his the "On-demand agents" list. If Smiley is missing, propose his own section —
own section — not an on-demand entry. not an on-demand entry.
1. For each agent file in the directory, check if its filename appears in CLAUDE.md In practice this check is subsumed by "Machine CLAUDE.md refresh (Mode B)"
2. For each missing agent, read its `description:` field from the frontmatter above: that step already diffs the developer's `~/.claude/CLAUDE.md`
3. If any are missing, propose exact CLAUDE.md text and ask for confirmation: structurally against `{BASE}/machine/CLAUDE.md` and proposes the update
(with confirmation) whenever they diverge — a newly-shipped roster agent not
``` yet listed is exactly the kind of structural divergence that step catches.
⚠️ Nye agenter installeret men ikke refereret i CLAUDE.md: No separate action needed here beyond running that step.
Foreslået tilføjelse til "On-demand agents"-sektionen:
- `.github/.agents/court.agent.md` - <description from frontmatter>
- `.github/.agents/lincoln.agent.md` - <description from frontmatter>
Vil du have mig til at tilføje dem til CLAUDE.md? (ja/nej)
```
If the developer says yes: append each missing agent to the "On-demand agents"
section in CLAUDE.md using the frontmatter description as the text.
Do not add without confirmation.
### After update — report and commit ### After update — report and commit

View file

@ -43,6 +43,118 @@ If the cache directory is missing or empty: run
`powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"` `powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"`
once, then proceed as above. once, then proceed as above.
## CURABIS Standard — Shared Roster (v24, this repo only)
Everything in this section applies ONLY if the current project has
`.github/.agents/bcquality.agent.md` (same gate as "Auto-update BCQuality"
above) — it must never activate in a non-CURABIS repo. As of v24, these
roster agents live here (machine-global) instead of being copied into every
repo's `.github/.agents/` — one copy per machine, kept current by the same
sync script that refreshes the knowledge mirror. The two exceptions that
stay repo-local are `.github/.agents/bcquality.agent.md` (the marker file
this gate checks for) and `.github/.agents/feynman.agent.md` (support
sessions have no `~/.claude/` to read from — see the project CLAUDE.md's own
"Feynman — Support-sessioner" section, unaffected by this change).
### Smiley — Session Watchdog (always active)
At session start, read `~/.claude/curabis-agents/smiley.agent.md`.
His protocols are active for the entire session. He does not announce himself.
He shapes Claude's behavior from within — stop gate, triage, background activation.
Never invoke him by name. Never explain the mechanism to the user.
If asked directly about Smiley or the agent network: present him fully.
### Carlin — Bullshit Detector (always active)
At session start, read `~/.claude/curabis-agents/carlin.agent.md`.
He is always in the back of the room. He does not announce himself.
He surfaces with one dry observation when complexity, convention, or feature creep
earns it — then moves on. Never blocks work. Never lectures. One line, then silence.
If asked directly about Carlin or the agent network: present him fully.
### On-demand agents
These are invoked only when needed - not at session start:
- `~/.claude/curabis-agents/columbo.agent.md` - Customer requirement clarifier. Invoke before any
new feature is built. Asks one question at a time until the requirement is complete.
Always has one more thing. Routes to al-complexity when the picture is clear.
- `~/.claude/agents/florence.md` - Heartbeat agent. Walks the wards on a regular
schedule, reads HEARTBEAT.md, and lights the lamp only when something deserves attention.
Silent when all is well. (Invoked as a real Claude Code subagent, `subagent_type: florence`.)
- `~/.claude/curabis-agents/m365.agent.md` - Microsoft 365 MCP usage guide. How to use Outlook,
calendar, SharePoint, and Teams tools correctly. Always consult before using any
`mcp__claude_ai_Microsoft_365__*` tool.
- `~/.claude/curabis-agents/francis.agent.md` - BCQuality rule proposer. Invoke at session end
or when a pattern suggests a rule is missing. Observes, compares with BCQuality, and
hands a Type A (sharpening) or Type B (new rule) proposal to Immanuel.
- `~/.claude/curabis-agents/immanuel.agent.md` - BCQuality rule guardian. Invoke after Francis
has a proposal ready. Runs the Categorical Imperative test, universalizes the rule,
and creates a draft knowledge file. Michael (mid) merges the BCQuality PR to approve.
- `~/.claude/curabis-agents/al-triage.agent.md` - reactive diagnosis when a build, test, or runtime
is already broken. Reproduce -> root-cause -> minimal-fix. Read-only; it recommends,
it does not apply. Invoke when the user reports an error, a failing test, or a regression.
- `~/.claude/curabis-agents/al-complexity.agent.md` - at the start of an implementation task, propose
a complexity tier (LOW/MEDIUM/HIGH) and route. Advisory: it proposes and waits for the
user to confirm the tier before any work starts. Never routes or codes on its own.
- `~/.claude/curabis-agents/bc-mcp.agent.md` - how to use the `businesscentral` MCP server to read
project/task work from Business Central and write GitHub branch/dev-status/comments back.
Invoke when the user references a BC task/project or wants to sync dev status to BC.
- `~/.claude/curabis-agents/court.agent.md` - The BCQuality Court: Lincoln, Aurelius, and Munger
deliberate on strategic health of the rulebook. Convene when a portfolio-level ruling is
needed — not for per-rule assessments. Requires a case brief with Edison scorecards.
- `~/.claude/curabis-agents/lincoln.agent.md` - First judge. Cuts to the essential question and
anchors rulings in moral clarity. Asks: "What is this case really about?"
- `~/.claude/curabis-agents/aurelius.agent.md` - Second judge. Applies Stoic reduction — what is
truly necessary? Prunes what no longer serves. Asks: "Is this rule still alive?"
- `~/.claude/curabis-agents/munger.agent.md` - Third judge. Applies inversion and mental models.
Finds what the others missed. Asks: "What are we getting wrong — and why?"
- `~/.claude/curabis-agents/algo-settings.agent.md` - AL-Go pipeline settings advisor. Consult when
discussing or changing AL-Go CI/CD settings (`AL-Go-Settings.json`).
- `~/.claude/curabis-agents/edison.agent.md` - BCQuality eval runner. Measures whether a merged
rule works in practice against real AL code: builds a corpus via the AL MCP tools,
classifies TP/FP/TN/FN, and produces a precision/recall/F1 scorecard. Low scorers route
to Francis for sharpening. Read-only — never modifies code or rules. Invoke on demand,
after a BCQuality release, or to build the scorecards a Court case requires.
- `~/.claude/curabis-agents/ferencz.agent.md` - Case builder for the Court. Assembles the
documented chain of evidence (commits, SHAs, dates, deployed standards) for a
RegelSanity divergence case or an effectiveness case. Every claim carries a citation;
exculpatory evidence included; prosecutes patterns, never people. Invoke when Rømer
flags a divergence, or before convening the Court on any question.
- `~/.claude/curabis-agents/roemer.agent.md` - Standards inspector. Owns the uniformity
inspection round: agent roster (missing AND extra), CLAUDE.md generation, .mcp.json
paths, mirror model, version markers, agent visibility. Measures against the written
standard, reports, never rules — divergence goes to Ferencz. Runs as part of Mode B,
on Florence's summons, or on demand: "Rømer, gå din runde".
- `~/.claude/curabis-agents/weber.agent.md` - Developer AI coaching. Applies Verstehen to diagnose
why a prompt was vague, then coaches toward specificity. Invoked by Florence (Ward 8) or
manually with a session excerpt or BC task comment.
### Francis — proaktiv regelobservation
Kald Francis automatisk (uden at vente til session-slut) når du:
- Laver en workaround fordi et værktøj mangler eller ikke virker som forventet
- Opdager et processgab — noget der burde være automatisk men ikke er
- Finder dig selv i at løse det samme problem to gange på to forskellige måder
Fetch Francis fra `~/.claude/curabis-agents/francis.agent.md`.
### Shared project memory + documentation
At session start, read all files in `projectmemory/` (in the current repo) — they
contain shared project observations from all team members and are version-controlled
in git. When you learn something project-relevant (business rules, architectural
decisions, scope boundaries, known technical debt), write it to
`projectmemory/memoryupdates_<username>.md` for the active user.
At session start, read all files in `docs/specs/` (in the current repo) — they contain
Columbo requirement summaries and confirmed feature specifications. Do not re-clarify
what is already recorded there. `docs/decisions/` contains architectural decision
records. `docs/cleanup/` contains cleanup task lists with checkbox status.
User-specific preferences (tone, workflow habits) stay in the local
`~/.claude/projects/.../memory/` folder, not in `projectmemory/`.
## CURABIS Standard project setup ## CURABIS Standard project setup
When the user says either of these commands, freshen the channel clone (see When the user says either of these commands, freshen the channel clone (see

View file

@ -0,0 +1,78 @@
# find-altool.ps1 - CURABIS-artefakt (deployes fra BCQuality, ikke genereret
# af AL-extensionen - der findes ingen VS Code-kommando til dette).
#
# v24: MASKIN-GLOBALT artefakt (%USERPROFILE%\.claude\find-altool.ps1),
# deployes af sync-bcquality-knowledge.ps1 - ligger IKKE i noget repo.
#
# Finder altool.exe dynamisk i den NYESTE installerede AL Language extension
# og videresender alle argumenter. Dette opslag er 100% maskinlokalt og har
# intet med repoet at goere.
#
# Specialargument 'auto': erstattes med alle AL-projektmapper fundet under
# det AKTUELLE repos apps-mappe (.apps/Apps/apps - mapper med app.json).
# Repo-roden findes IKKE via scriptets egen placering ($PSScriptRoot - det
# giver ~/.claude, hvilket er forkert nu scriptet er globalt) men ved at
# walke op fra cwd og lede efter en <appsName>\.AL-Go-markoer. Sessioner
# binder cwd til apps-workspace-mappen (en app-undermappe, ikke repo-roden),
# saa opslaget skal fungere uanset hvor i repoet cwd peger:
# ... find-altool.ps1 launchmcpserver auto --transport stdio
#
# BEMAERK: altool launchmcpserver KRAEVER projektstier - uden doer serveren.
$ext = Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "ms-dynamics-smb.al-*" -Directory |
Sort-Object { [version]($_.Name -replace '^ms-dynamics-smb\.al-', '' -replace '-.*$', '') } -Descending |
Select-Object -First 1
if (-not $ext) {
Write-Error "AL Language extension ikke fundet. Installer ms-dynamics-smb.al fra VS Code Marketplace."
exit 1
}
$altool = Join-Path $ext.FullName "bin\win32\altool.exe"
if (-not (Test-Path $altool)) {
Write-Error "altool.exe ikke fundet i $($ext.FullName) - opdater AL-extensionen (MCP-serveren kraever en nyere version)."
exit 1
}
if ($args -contains 'auto') {
# Walk op fra cwd og led efter <appsName>\.AL-Go som repo-rod-markoer.
# Case-insensitive filsystem (Windows) betyder .apps/Apps/apps kan matche
# den samme fysiske mappe flere gange - stop ved foerste match i stedet
# for at tjekke alle tre ubetinget (undgaar dubletter i projektlisten).
$d = (Get-Location).Path
$repo = $null
$appsFolderName = $null
while ($d.Length -gt 3) {
foreach ($appsName in @('.apps', 'Apps', 'apps')) {
if (Test-Path (Join-Path $d "$appsName\.AL-Go")) {
$repo = $d
$appsFolderName = $appsName
break
}
}
if ($repo) { break }
$d = Split-Path $d
}
if (-not $repo) {
Write-Error "Ingen AL-Go repo-rod (<.apps|Apps|apps>\.AL-Go) fundet ved opadgaaende soegning fra $((Get-Location).Path)."
exit 1
}
$appsDir = Join-Path $repo $appsFolderName
$projects = Get-ChildItem $appsDir -Directory |
Where-Object { Test-Path (Join-Path $_.FullName 'app.json') } |
ForEach-Object { $_.FullName }
if (-not $projects) {
Write-Error "Ingen AL-projektmapper (med app.json) fundet under $appsDir."
exit 1
}
$resolved = @()
foreach ($a in $args) {
if ($a -eq 'auto') { $resolved += $projects } else { $resolved += $a }
}
& $altool @resolved
} else {
& $altool @args
}

View file

@ -15,6 +15,17 @@
# Mirroren committes ALDRIG til et projekt-repo - se BCQuality-reglen # Mirroren committes ALDRIG til et projekt-repo - se BCQuality-reglen
# bcquality-knowledge-must-mirror-to-machine-not-repo. Koer periodisk: # bcquality-knowledge-must-mirror-to-machine-not-repo. Koer periodisk:
# powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1" # powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.claude\sync-bcquality-knowledge.ps1"
#
# v24: samme script deployer OGSAA resten af de maskin-globale artefakter,
# der foer v24 blev kopieret ind i hvert repo (se BCQuality-reglen
# roster-agents-live-on-machine-not-in-repo):
# ~/.claude/curabis-agents/ - 18 "read-as-protocol-doc" roster-agenter
# ~/.claude/agents/florence.md - Florence som rigtig Claude Code-subagent
# ~/.claude/find-altool.ps1 - AL-tool-finder (cwd-walkup, ikke repo-bundet)
# MCP-servere (al, businesscentral) - registreret med `claude mcp --scope user`
# Undtagelser der IKKE roeres herfra (blive repo-lokale via curabis-standard.agent.md):
# .github/.agents/bcquality.agent.md - markoerfilen der gater al denne logik
# .github/.agents/feynman.agent.md - support-brugere har intet ~/.claude/
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
@ -111,3 +122,79 @@ Set-Content -Path $marker -Value $sha -Encoding ascii
Write-Host '' Write-Host ''
Write-Host "Done. $($files.Count) filer, 3 lag, stable @ $($sha.Substring(0,7))." Write-Host "Done. $($files.Count) filer, 3 lag, stable @ $($sha.Substring(0,7))."
Write-Host "Machine-local mirror updated: $dest" Write-Host "Machine-local mirror updated: $dest"
# --- 5. Roster-agenter -> ~/.claude/curabis-agents/ (v24, maskin-globalt) ---
# De 18 "read-as-protocol-doc" agenter der IKKE er bcquality.agent.md eller
# feynman.agent.md (de bliver repo-lokale, se filens header). Florence
# haandteres separat nedenfor (hun er en rigtig Claude Code-subagent).
$curabisAgentsDest = Join-Path $env:USERPROFILE '.claude\curabis-agents'
New-Item -ItemType Directory -Force $curabisAgentsDest | Out-Null
$rosterFromAgentsDir = @(
'aurelius', 'carlin', 'columbo', 'court', 'edison', 'ferencz',
'francis', 'immanuel', 'lincoln', 'm365', 'munger', 'roemer',
'smiley', 'weber'
) | ForEach-Object { Join-Path $clone "custom\agents\$_.agent.md" }
$rosterFromSetupTemplates = @(
'al-complexity', 'al-triage', 'algo-settings', 'bc-mcp'
) | ForEach-Object { Join-Path $clone "custom\setup\templates\$_.agent.md" }
$rosterCount = 0
foreach ($src in ($rosterFromAgentsDir + $rosterFromSetupTemplates)) {
if (-not (Test-Path $src)) {
Write-Warning "Roster-agent ikke fundet i klonen, springer over: $src"
continue
}
Copy-Item $src (Join-Path $curabisAgentsDest (Split-Path $src -Leaf)) -Force
$rosterCount++
}
Write-Host "Roster-agenter synkroniseret til $curabisAgentsDest - $rosterCount filer."
# --- 6. Florence -> ~/.claude/agents/florence.md (rigtig subagent, ikke curabis-agents) ---
$nativeAgentsDest = Join-Path $env:USERPROFILE '.claude\agents'
New-Item -ItemType Directory -Force $nativeAgentsDest | Out-Null
Copy-Item (Join-Path $clone 'custom\agents\florence.agent.md') (Join-Path $nativeAgentsDest 'florence.md') -Force
Write-Host "Florence-subagent opdateret: $(Join-Path $nativeAgentsDest 'florence.md')"
# --- 7. find-altool.ps1 -> ~/.claude/find-altool.ps1 (maskin-globalt, raw bytes) ---
$findAltoolDest = Join-Path $env:USERPROFILE '.claude\find-altool.ps1'
Copy-Item (Join-Path $clone 'custom\setup\machine\find-altool.ps1') $findAltoolDest -Force
Write-Host "find-altool.ps1 opdateret: $findAltoolDest"
# --- 8. MCP-servere: registrer al + businesscentral paa user scope (idempotent) ---
# claude mcp add fejler med exit 1 og "already exists" hvis serveren allerede er
# registreret - det er IKKE en fejltilstand her, kun rigtige fejl skal stoppe scriptet.
# NB: $ErrorActionPreference='Stop' goer stderr fra native kommandoer til en
# terminating exception ved 2>&1-redirect - skal skiftes til 'Continue' om
# selve kaldet, ellers naar if-tjekket nedenfor aldrig at koere.
function Ensure-UserMcpServer {
param([string]$Name, [string[]]$CommandAndArgs)
# BEMAERK: `claude mcp add --scope user $Name -- @CommandAndArgs` (splat EFTER
# et literalt '--') taber '--'-grænsen et sted i PowerShell -> commander.js,
# og flagene i $CommandAndArgs bliver fejlagtigt tolket som claude-flag ("unknown
# option '-NoProfile'"). Eneste form der virker paalideligt: ét fladt array med
# ALT (inkl. 'mcp','add',flag,navn,'--') kaldt som @allArgs i ét hug.
$allArgs = @('mcp', 'add', '--scope', 'user', $Name, '--') + $CommandAndArgs
$prevEap = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
$output = & claude @allArgs 2>&1
$exitCode = $LASTEXITCODE
$ErrorActionPreference = $prevEap
if ($exitCode -ne 0) {
if ($output -match 'already exists') {
Write-Host "MCP-server '$Name' er allerede registreret paa user scope."
} else {
throw "claude mcp add fejlede for '$Name': $output"
}
} else {
Write-Host "MCP-server '$Name' registreret paa user scope."
}
}
Ensure-UserMcpServer -Name 'businesscentral' -CommandAndArgs @('node', '${USERPROFILE}\.claude\bc-mcp-bridge.js')
Ensure-UserMcpServer -Name 'al' -CommandAndArgs @(
'powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass',
'-File', '${USERPROFILE}\.claude\find-altool.ps1',
'launchmcpserver', 'auto', '--transport', 'stdio'
)

View file

@ -1,53 +0,0 @@
# find-altool.ps1 - CURABIS-artefakt (deployes fra BCQuality, ikke genereret
# af AL-extensionen - der findes ingen VS Code-kommando til dette).
#
# Finder altool.exe dynamisk i den NYESTE installerede AL Language extension
# og videresender alle argumenter. Scriptet er cwd-agnostisk: det ligger i
# <repo>\.vscode\ og kan derfor selv udlede repo-roden ($PSScriptRoot\..).
#
# Specialargument 'auto': erstattes med alle AL-projektmapper fundet under
# repoets apps-mappe (.apps/Apps/apps - mapper med app.json). Dermed er
# .mcp.json-entryen identisk paa tvaers af alle repos:
# ... find-altool.ps1 launchmcpserver auto --transport stdio
#
# BEMAERK: altool launchmcpserver KRAEVER projektstier - uden doer serveren.
$ext = Get-ChildItem "$env:USERPROFILE\.vscode\extensions" -Filter "ms-dynamics-smb.al-*" -Directory |
Sort-Object { [version]($_.Name -replace '^ms-dynamics-smb\.al-', '' -replace '-.*$', '') } -Descending |
Select-Object -First 1
if (-not $ext) {
Write-Error "AL Language extension ikke fundet. Installer ms-dynamics-smb.al fra VS Code Marketplace."
exit 1
}
$altool = Join-Path $ext.FullName "bin\win32\altool.exe"
if (-not (Test-Path $altool)) {
Write-Error "altool.exe ikke fundet i $($ext.FullName) - opdater AL-extensionen (MCP-serveren kraever en nyere version)."
exit 1
}
if ($args -contains 'auto') {
$repo = Split-Path $PSScriptRoot
$projects = @()
foreach ($appsName in @('.apps', 'Apps', 'apps')) {
$appsDir = Join-Path $repo $appsName
if (Test-Path $appsDir) {
$projects += Get-ChildItem $appsDir -Directory |
Where-Object { Test-Path (Join-Path $_.FullName 'app.json') } |
ForEach-Object { $_.FullName }
}
}
if (-not $projects) {
Write-Error "Ingen AL-projektmapper (med app.json) fundet under $repo\.apps|Apps|apps."
exit 1
}
$resolved = @()
foreach ($a in $args) {
if ($a -eq 'auto') { $resolved += $projects } else { $resolved += $a }
}
& $altool @resolved
} else {
& $altool @args
}