Two related fixes, discovered together while debugging Wareco's duplicated
"Project" scope MCP entries:
1. New custom/setup/machine/settings.json template + a merge-safe deploy
step in sync-bcquality-knowledge.ps1 (section 10): auto-approves the
read-only/already-protocol-gated tool calls across the three
CURABIS-managed MCP servers (businesscentral's 15 static tools, al's
11 dev-loop tools, microsoft-learn's 3 docs tools) via
~/.claude/settings.json's permissions.allow -- merged into whatever
already exists, never overwritten, since that file also carries a
developer's personal settings. Tested against a real 298-entry
settings.json: preserved every existing key/array untouched, added
only the 14 genuinely-missing entries.
Found and fixed two real bugs while building this: -AsHashtable
doesn't exist in Windows PowerShell 5.1 (this script also runs via
`powershell`, not just `pwsh`) -- switched to PSCustomObject +
Add-Member. And Set-Content -Encoding utf8 writes a BOM in PS5.1 with
no utf8NoBOM option -- switched to [System.IO.File]::WriteAllText
with an explicit no-BOM UTF8Encoding, since the original file had no
BOM and a JSON parser choking on one would have silently broken every
developer's settings.json.
2. Wareco's committed .claude/settings.json still has the pre-migration
Dynamic Tool Mode tool names (bc_actions_search/describe) and an
enabledMcpjsonServers entry for al/businesscentral -- the latter is
why the MCP servers panel shows them duplicated under "Project" scope
next to the correct "User" scope registration. Added detection +
confirmed-removal migration step (mirroring the existing .mcp.json
migration's multi-developer coordination caveat) and Roemer station
16 to catch this on other pre-migration repos (gtt-marine likely has
the same file).
Internal_CompanyNotFound recurred 2026-08-03 on two machines with the
company header already matching Navn correctly, ruling out the original
header-mismatch cause. Failure was intermittent and appeared to clear after
restarting Claude Code, suggesting a separate, still-unconfirmed session/
bridge staleness issue. Adds a follow-up section with next steps so future
sessions don't re-verify an already-correct header a third time.
"If asked directly about Smiley... by name" required a user to guess the
right codename to get an honest answer about whether something shapes
the session's behavior -- a concealment regardless of good intent, and
the same "keyed to phrasing instead of the actual thing being asked" bug
already fixed elsewhere in this standard (Columbo/al-complexity split,
Smiley's TDD gate), just applied to disclosure instead of activation.
Raised independently by a Claude session during Linh's onboarding, which
declined to treat "never explain the mechanism" as covering a good-faith
general question. Fixed the wording to match: stay quiet unprompted, but
answer honestly if asked in general terms, name or no name.
Implements every confirmed finding from the workflow-based audit of
CURABIS Standard's agent model (7 finders + adversarial verification,
8 confirmed / 5 refuted):
1. Roemer/Florence phantom wiring - roemer.agent.md claimed Florence's
heartbeat "may summon me when a ward smells of drift" with nothing in
florence.agent.md or HEARTBEAT.md implementing it. Fixed by adding an
explicit "Kald Roemer" instruction to HEARTBEAT.md ward 6 (agent
visibility, his actual domain), mirroring ward 8's existing "Kald
Weber" pattern, and correcting roemer.agent.md's own claim to match.
2. m365.agent.md's "Florence's morning brief pattern" was a one-way
orphaned reference - a full 4-step pattern with nothing in
florence.agent.md implementing it. Added it to florence.agent.md as
an explicit on-demand capability, separate from the timestamp-gated
Round protocol.
3. An Ergasterion "PROCEED WITH CHANGES" ruling had no way to be checked
against the eventual diff - al-review's checklists never referenced
it. Added ERGASTERION_RULING to the [CURABIS-STATE] vocabulary,
wired Ergasterion to write it, and added a BLOCKing checklist item to
al-review's Titus checklist that verifies required changes were
actually implemented.
4. curabis-task-state-check.yml was headered "Deterministic enforcement
(not LLM diligence)" but only checks checkbox order, only blocks
anything if a human separately enabled branch protection (never
verified anywhere), and doesn't exist at all for the PTE track.
Corrected the header's claims and added Roemer station 14 to verify
branch protection is actually configured.
5. Mode C's only safeguard against a support user reaching
Curabis/QualityHub was a single manual eyeball check with no re-check
ever. Strengthened Step 2 to cover team-inherited and org-default
access paths, added an append-only support-user registry, and added
Roemer station 15 to periodically re-verify every registered user
against it.
6. Columbo's persona was presented as genuine autobiography with no
disclosure of its fictional TV origin (Levinson & Link, Peter Falk),
unlike Smiley which discloses explicitly. Added a reader-facing
editorial note - never something Columbo says aloud, since unlike
Smiley he actually performs the persona to customers.
Prompted by comparing Jeremy Vyska's "Victor Versioning" persona
(bc-code-intelligence-mcp) against what Microsoft already publishes.
Verified: Victor's ~32k "obsoletions" are a pre-indexed repackaging of
Microsoft's own Obsolete attributes in BCApps, plus BREAKINGCHANGES.md
and the deprecated-features-w1/deprecated-features-platform Learn pages
-- no new information, just faster retrieval.
We already have the same sources (BCApps reference clone, Microsoft
Learn MCP). Rather than add a new persona, sharpened al-triage: an
obsolete/deprecated diagnostic or a post-version-bump symptom now checks
BREAKINGCHANGES.md and the version-specific Learn pages first, instead
of reasoning from source alone.
al-complexity.agent.md's HIGH route says the Ergasterion convenes
automatically, but Smiley's own compressed chain diagram is what actually
drives session behavior, and it never mentioned the branch. Same class of
gap as the Columbo/al-complexity split fix (2026-07-31): a step that only
exists in a file Smiley doesn't quote from is a step that silently never
runs. Added the HIGH-tier branch to the chain and clarified Ergasterion is
NOT on-demand-only like the Court -- it auto-activates as the HIGH route's
architecture sign-off.
Pre-implementation architecture inspection for one proposed design at a
time, distinct from the Court's rulebook-level governance (which already
carries its own "Academy" self-identity in court.agent.md) and from
al-review's post-hoc diff review. Wired into al-complexity's HIGH-tier
route as the actual human architecture sign-off.
- Hickey: what does this model, and what's complected?
- Fowler: does this pay for itself, or borrow against the next change?
- Parnas: is what's likely to change hidden behind a stable interface?
(proactive counterpart to Titus Winters' Hyrum's Law check in al-review)
Michael: "lad os bygge alle 4" - rangeret efter styrke fra sidste samtale.
1. Smiley v6: close-gaten laeser nu det faktiske [CURABIS-STATE]-spor
tilbage FOER merge, i stedet for at stole paa sessionens egen hukommelse.
Mangler et tidligere checkpoint, blokerer merge - selv hvis testen er
groen og reviewet lige sagde APPROVE nu.
2. al-review v3: "state trail complete?" er nu et Titus-tjekpunkt der giver
BLOCK, ikke bare en note - et ufuldstaendigt spor er i sig selv et
vedligeholdelsesfund.
3. Ny .github/workflows/curabis-task-state-check.yml: reelt deterministisk
haandhaevelse for AppSource (parser PR-body'ens tjekliste, fejler hvis en
senere fase er tjekket mens en tidligere ikke er). Testet mod fire cases
(gyldig raekkefolge, ugyldig, ingen sektion, tom sektion) - alle korrekte.
Kraever et manuelt engangs-trin (branch protection required check) som
filudrulningen ikke selv kan saette.
4. Roemer v6: ny station 13, retrospektiv - stikprover de sidste ~10
afsluttede BC-opgaver/mergede PR'er for spor-fuldstaendighed, fanger
drift ingen enkelt opgaves egen gate fangede. Kun opgaver lukket efter
2026-08-03 flages - reglen fandtes ikke foer.
curabis-standard.agent.md: ny artefakt-raekke + Mode A step 4h (deploy
workflow-filen, mind om branch protection-trinet) + Mode B repo-tabel-raekke.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Michaels retning efter at have set community-vaerktoejets workflow_start/
workflow_next-tilstandsmaskine: han vil inspireres, ikke kopiere - vil have
persisteret, forespoergelig tilstand der overlever et maskin- OG operatoer-
skifte, uden at bygge en ny, parallel opbevaringsmekanisme.
Princippet: brug det obligatoriske spor der allerede findes for den
paagaeldende flowtype, ikke et tredje system.
- PTE: en BC-delopgave er allerede obligatorisk foer udvikling starter
(development-requires-bc-task, ingen undtagelser) - dens kommentarer
(taskComments) ER tilstandslageret. Format: [CURABIS-STATE] <STAGE> —
dato, udvikler.
- AppSource: intet obligatorisk BC-spor i dag - draft PR'en aabnes tidligt
(ved start-gaten, ikke foerst ved review) og dens beskrivelse baerer
tilstanden som en tjekliste.
Samme tilstandsordforraad begge steder: TASK_STARTED, RED_CONFIRMED,
ON_HOLD (altid med hvorfor), GREEN_CONFIRMED, REVIEW: <verdict>, MERGED.
Bevidst IKKE en kopi af community-vaerktoejets workflowSessionManager - den
har reel persisteret tilstand, men INGEN haandhaevelse noget sted (returnerer
bare en instruktion, tiltror agenten at foelge den). CURABIS's reelle styrke
er det modsatte (roed bekraeftet af udvikleren, BLOCK er et haardt stop) -
denne aendring tilfoejer persistens UDEN at rore ved haandhaevelsen.
Wired ind i:
- smiley.agent.md v5: hver gate-overgang skriver nu et tilstands-checkpoint
- bc-mcp.agent.md v3: standard workflow skriver [CURABIS-STATE]-kommentarer
- al-review.agent.md v2: verdict registreres som et checkpoint, ikke kun
som findings
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Live incident i aften: businesscentral MCP fejlede med et generisk
30-sekunders "connection timed out", ingen brugbar fejl. To reelle, adskilte
fejl fundet ved at teste direkte mod BC's endpoint:
1. ~/.bc-mcp.config.json havde "company": "CURABIS ApS" (Vist navn), men BC's
faktiske Navn-felt er "Curabis ApS". BC svarede korrekt og hurtigt (400,
under 200ms) - problemet var aldrig BC.
2. bc-mcp-bridge.js svaelgede det svar stille: en fejl-krop formateret som
almindelig JSON, men markeret content-type text/event-stream, blev sendt
til parseSSE() som kun leder efter "data:"-linjer - fandt ingen, returnerede
en tom liste. Broen skrev derfor INGENTING, hverken stdout eller stderr, og
Claude Code ventede blot sin egen 30-sekunders timeout ud.
Rettet:
- forward() tjekker nu !r.ok FOER content-type-forgrening, ubetinget - en
fejlrespons naar aldrig parseSSE, uanset hvad serveren paastaar om sin
egen content-type. Testet direkte mod det reproducerede scenarie: fejlen
vises nu med det samme (5s test-vindue, ikke 30s timeout), med det fulde
BC-fejlsvar synligt i baade stdout (JSON-RPC error) og stderr.
- bc-mcp.config.template.json matchede slet ikke broens faktiske felter
(tenantId/baseUrl vs. broens tenant/company/configurationName) - enhver ny
udvikler der udfyldte skabelonen efter dens egne feltnavne ville faa en
config der intet virkede med. Rettet til de rigtige feltnavne, plus en
eksplicit advarsel om Navn vs. Vist navn i company-feltet.
- Mode A's opsaetningsbesked (Step 3b) opdateret til at naevne alle
placeholder-felter, ikke kun secret'en.
- To nye BCQuality-videnfiler dokumenterer begge fejl til fremtidig
fejlsoegning.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fjerde gate i Task Lifecycle - koert efter groent test, foer merge, adskilt
fra den der implementerede aendringen og fra Roemer/Immanuel/Court's
portefoelje-niveau-styring (de spoerger "er selve regelsaettet sundt", ikke
"er DENNE aendring god").
To linser, Michaels egen opdeling:
- Linus Torvalds: BC/AL-domaene-teknisk (respekterer standard-BC/events,
bogfoerings-sideeffekter, opgraderings-holdbarhed, filtre/keys/SetLoadFields,
locking/SQL-performance, permissions/dataklassifikation, forretningslogik
paa forkert sted, testdaekning af forretningsforloeb, lokalt rigtig men
arkitektonisk forkert)
- Titus Winters: generel software-engineering (korrekthed, forstaaelighed,
arkitektonisk sammenhaeng, testbarhed, cyklomatisk/McCabe-kompleksitet -
ingen anden i rosteret vurderer det tal - Hyrum's Law, kodebase-konsistens,
boer det overhovedet bygges saadan)
Wired ind i Smileys Close gate (samme udfaldsbaserede disciplin som resten
af dagens rettelser) - ikke noget udvikleren skal huske at bede om. Verdict
er APPROVE / APPROVE WITH NOTES / BLOCK, aldrig en fjerde "det er kompliceret".
Roster-taeller opdateret alle steder: 22 agent-filer i alt (20 maskin-globale,
2 repo-lokale), 19 filer i ~/.claude/curabis-agents/. sync-bcquality-
knowledge.ps1 testet - al-review.agent.md bekraeftet leveret.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Michaels retning: loes tingene saa standard som muligt foerst (Microsoft
Learn + det faktiske BCApps-indhold), derefter KISS paa hvad der reelt skal
bygges custom.
Ny Step 0 i al-complexity.agent.md, koert FOER klassificering:
- Soeg Microsoft Learn efter forretningsbehovet (ikke "hvordan bygger jeg X i AL")
- Tjek den rigtige BCApps-kildekode via reference-repos-klonen (ikke traenings-
data-antagelser)
- Krav om bevis, ikke en paastand ("jeg tjekkede og fandt intet" er kun
troværdigt hvis du viser hvad du soegte) - samme standard som TDD-rød-
bekraeftelsen
- Ny STANDARD-tier: hvis BC allerede klarer det, ingen kode, kun opsaetning
- KISS goeres til en eksplicit begraensning paa selve routen, ikke kun paa
Step 0 - en HIGH-tier retfaerdiggoer mere PROCES, ikke en mere elaboreret
LOESNING
Smiley v3 (samme commit-serie): rettede ogsaa en snag i selve aktiveringen -
Columbo->al-complexity-kaeden trigges i dag kun naar kravet er UKLART. Men
standard-foerst-tjekket boer koere for ETHVERT nyt custom-arbejde, ogsaa et
krystalklart formuleret et - et klart krav kan stadig vaere noget BC allerede
goer. Samme klasse gap som TDD-triggerfixen i forrige commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Opdaget i praksis 2026-07-31: en afslappet "det vil jeg gerne have de ting
fikset" (efter en QA/challenge-session, ikke en "lad os starte en opgave"-
formulering) udloeste ikke Task Lifecycle-stopgaten automatisk - den koerte
kun roed/groen fordi et menneske eksplicit skrev "roed/groen-gate" ind i den
efterfoelgende prompt. Det skal ikke vaere paakraevet.
En ordliste kan ikke loese det - der findes uendeligt mange maader at bede om
en rettelse paa. Erstattet med en udfalds-baseret betingelse: gaten aktiveres
naar Claude er ved at skrive/aendre AL-kode der aendrer adfaerd, uanset
brugerens ordvalg. Kalibrerings-eksempler ("fiks det", "kan du ordne det",
et bart "ja, goer det") er illustrationer af raekkevidden, ikke en udtoemmende
liste at matche imod.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
To ting fra QualityHub-sporet:
1. Udviklere faar nu samme Microsoft Learn MCP som Mode C-supportbrugere
allerede havde (https://learn.microsoft.com/api/mcp, HTTP, ingen auth) -
registreret maskin-globalt via sync-bcquality-knowledge.ps1, samme
moenster som al/businesscentral. Lukker hullet hvor udviklere kun havde
den statiske microsoft/-videnfil-snapshot og ingen live dokumentationssoegning.
2. add_repo-mekanismen i curabis-app-sources-must-be-checked-first.md var
kun naevnt, aldrig defineret - intet vaerktoej med det navn findes i
Claude Code CLI. Erstattet med en konkret, testet mekanisme: en
vedvarende, opdateret klon i ~/.claude/reference-repos/<org>/<repo>/,
samme moenster som BCQualitys egen kanal-klon. Testet live mod det
faktiske microsoft/BCApps-repo (shallow clone ~52s, ~36.000 .al-filer,
git pull --depth 1 til opdatering).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BC MCP-serveren (CURABIS_DEV) er skiftet fra Dynamic til Static Tool Mode -
de generiske bc_actions_search/describe/invoke findes ikke laengere, hver
BC-handling er nu sit eget navngivne, typede MCP-vaerktoej (bekraeftet live
efter et reconnect). Det fjerner navnedrift-risikoen dokumentet selv
tidligere advarede om (consultants/users-forvekslingen).
Samtidig:
- taskResponsible tilfoejet som skrivbar paa activeTasks (matcher AL-rettelsen
i CURMCPActiveTasks.Page.al/CURSubTask.Table.al - opgaveansvarlig kan nu
omfordeles mellem konsulenter via MCP)
- De to hidtil udokumenterede entiteter projectAIScores/projectWeberScores
tilfoejet med korrekt insert-only-regel og ejerskab (Edison hhv. Weber)
- Alle workflow-referencer opdateret til at kalde vaerktoejerne direkte
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
- custom/agents/feynman.agent.md: ny support-navigator for ikke-udviklere.
Strengt læsende, svar med kildehenvisning (kildetrappen: docs/specs ->
projectmemory -> decisions -> kode -> Microsoft via MCP), Feynman-testen
på alle svar, struktureret eskalering via Feynman-notatet (Columbo/
al-triage-klar). Aktiveres med trigger-frasen 'Feynman:'.
- curabis-standard.agent.md v23: Feynman i artefakt-tabel, Mode A 4c,
Mode B-tabel og CLAUDE.md-templaten (support-sektion der slår self-heal,
AL MCP og BC MCP fra i support-sessioner + on-demand-entry). Ny MODE C:
'Onboard en supportbruger til CURABIS Standard' — browser-only (claude.ai/
Claude Code på web, ingen VS Code), GitHub read-only, GitHub MCP +
Microsoft Learn MCP, ingen secrets, ingen QualityHub-adgang.
- templates/feynman-onboarding.md: dansk onboarding-dokument til
supportbrugeren ({SUPPORT_NAME}/{REPO_LIST}/{SETUP_DATE}-tokens).
- machine/CLAUDE.md: tredje trigger-kommando tilføjet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR #9's fix was wrong: 'workflows' is not a real GitHub Actions permission
scope (verified list: actions, contents, issues, pull-requests, etc. - no
'workflows'). Merging it broke workflow_dispatch outright:
Invalid Argument - failed to parse workflow: (Line: 21, Col: 3):
Unexpected value 'workflows'
GITHUB_TOKEN can never push .github/workflows/* changes - that's a hard
GitHub restriction, not something the permissions: block controls. The
correct fix is to never let the sync branch carry workflow-file changes in
the first place: after a clean merge, restore .github/workflows from
origin/main and amend. This also closes a latent risk - a clean upstream
merge could otherwise silently overwrite QualityHub's own CI files
(including this one) with whatever microsoft/BCQuality ships under the same
paths.
Confirmed via both REST API and gh CLI: promote-stable.yml has been on main
since 2026-07-03 but GitHub Actions never listed it as a dispatchable
workflow (404 on both). File content is valid, no encoding issues - a known
GitHub indexing gap. A no-op touch to the file forces re-discovery.