diff --git a/custom/knowledge/architecture/curabis-app-sources-must-be-checked-first.md b/custom/knowledge/architecture/curabis-app-sources-must-be-checked-first.md index 11d6b59..bdfa392 100644 --- a/custom/knowledge/architecture/curabis-app-sources-must-be-checked-first.md +++ b/custom/knowledge/architecture/curabis-app-sources-must-be-checked-first.md @@ -1,7 +1,7 @@ --- bc-version: [all] domain: architecture -keywords: [dependency, source, add-repo, github, curabis, closed-source, test, symbol, black-box] +keywords: [dependency, source, reference-repos, clone, github, curabis, closed-source, test, symbol, black-box] technologies: [al] countries: [w1] application-area: [all] @@ -17,10 +17,31 @@ customer project imports one of these apps, it typically arrives as a compiled This makes the app look like a closed external dependency. It is not. Before treating any CURABIS-owned dependency app as a black box, the agent -must check whether its source is available via `add_repo` (GitHub). Reverse- -engineering compiled symbol packages (`SymbolReference.json`, `.app` manifest -inspection) is always an inferior substitute for reading the actual production -source, and produces lower-confidence tests and code reviews. +must check whether its source is available on GitHub and read it directly. +Reverse-engineering compiled symbol packages (`SymbolReference.json`, `.app` +manifest inspection) is always an inferior substitute for reading the actual +production source, and produces lower-confidence tests and code reviews. + +**How to actually get the source (2026-07-30 — was previously the underspecified +`add_repo `, which is not a real tool in most Claude Code sessions):** + +- **Claude Code CLI** (this is the common case): maintain a persistent, + periodically-refreshed clone at `~/.claude/reference-repos///` — + same pattern as BCQuality's own channel clone. Before reading, check if it + exists: + - Missing: `git clone --depth 1 "$env:USERPROFILE\.claude\reference-repos\\"` + (shallow — you need current source, not history) + - Exists: `git -C "$env:USERPROFILE\.claude\reference-repos\\" pull --depth 1` + (refresh before trusting it — a stale clone from a prior session is a + silent source of wrong answers) + - Then `Read`/`Grep`/`Glob` it like any other local path. +- **Claude Code on web** (claude.ai/code): use the session's repo picker / + "add repository" action instead, if the UI offers one — there is no shell + to clone into in that environment. + +Verify which of these your actual session supports before assuming either +works — do not silently fall back to symbol inspection if neither succeeds; +flag the limitation explicitly instead (see "When cloning fails" below). ## Known CURABIS app repos @@ -29,7 +50,7 @@ source, and produces lower-confidence tests and code reviews. | Contract Management 365 app | https://github.com/Curabis/ContractMgmt365app.git | Main contract engine; depended on by most CURABIS customer projects | | Project Management 365 app | https://github.com/Curabis/ProjectMgmt365app.git | | | Cross Channel Management 365 app | https://github.com/Curabis/WebStore.git | | -| Summatim | https://github.com/MichaelDieringer/-summatim.git | Currently restricted — only mid has access; add_repo will fail for other team members | +| Summatim | https://github.com/MichaelDieringer/-summatim.git | Currently restricted — only mid has access; the clone will fail for other team members | *Expand this table when new CURABIS apps are created. If an app is not listed here, ask `mid` whether source is available before reverting to symbol inspection.* @@ -42,10 +63,12 @@ available at: - https://github.com/microsoft/BCApps -Use `add_repo microsoft/BCApps` when you need to understand internals of -Microsoft standard codeunits (e.g. Sales-Post, Gen. Jnl.-Post Line, Copy Document -Mgt.) that are referenced by event subscribers but whose source is not visible in -the current project. +Clone it to `~/.claude/reference-repos/microsoft/BCApps/` (see the mechanism +above) when you need to understand internals of Microsoft standard codeunits +(e.g. Sales-Post, Gen. Jnl.-Post Line, Copy Document Mgt.) that are referenced +by event subscribers but whose source is not visible in the current project. +It is a large public monorepo — a shallow clone is still the right call, and +worth refreshing rather than re-cloning once it exists. ## Anti Pattern @@ -56,8 +79,9 @@ the current project. ## Best Practice - // CORRECT: add the source repo and read it directly - add_repo Curabis/ContractMgmt365app + // CORRECT: clone the source repo and read it directly + git clone --depth 1 https://github.com/Curabis/ContractMgmt365app.git ` + "$env:USERPROFILE\.claude\reference-repos\Curabis\ContractMgmt365app" // Then read the actual table definitions, codeunits, and any Test Library // codeunits that may already exist in the repo's own test app. @@ -75,5 +99,8 @@ Apply at the start of any task involving: - Building GIVEN helpers for a CURABIS-owned app's tables - Code-reviewing changes to codeunits that extend CURABIS-owned apps -If `add_repo` fails due to access restrictions (see table above), flag the -limitation explicitly rather than silently falling back to symbol inspection. +## When cloning fails + +If the clone fails due to access restrictions (see table above) or your +session has no shell to clone into, flag the limitation explicitly rather +than silently falling back to symbol inspection. diff --git a/custom/setup/curabis-standard.agent.md b/custom/setup/curabis-standard.agent.md index 43111b6..f331abb 100644 --- a/custom/setup/curabis-standard.agent.md +++ b/custom/setup/curabis-standard.agent.md @@ -212,13 +212,14 @@ If it does NOT exist: 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. +the `al`/`businesscentral`/`microsoft-learn` 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 @@ -234,15 +235,20 @@ exactly one sync per upstream change. - `~/.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) + - `al` + `businesscentral` + `microsoft-learn` registered at user MCP scope + (idempotent — a server that already exists is reported, not re-added or + overwritten). `microsoft-learn` is `https://learn.microsoft.com/api/mcp`, + HTTP transport, no auth — the same official documentation search Mode C + already gives support users; v24 closes the gap where developers had + only the static `microsoft/` knowledge-file snapshot and no live search + of Microsoft's own docs. 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)." + businesscentral, microsoft-learn)." 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 @@ -543,7 +549,7 @@ these are shared across every CURABIS repo on the machine: | `~/.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) | +| `al` + `businesscentral` + `microsoft-learn` 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) diff --git a/custom/setup/sync-bcquality-knowledge.ps1 b/custom/setup/sync-bcquality-knowledge.ps1 index 82a74d1..5b54a77 100644 --- a/custom/setup/sync-bcquality-knowledge.ps1 +++ b/custom/setup/sync-bcquality-knowledge.ps1 @@ -198,3 +198,27 @@ Ensure-UserMcpServer -Name 'al' -CommandAndArgs @( '-File', '${USERPROFILE}\.claude\find-altool.ps1', 'launchmcpserver', 'auto', '--transport', 'stdio' ) + +# --- 9. Microsoft Learn MCP (HTTP, ingen auth) - samme adgang udviklere faar som +# Mode C support-brugere allerede har. Verificeret 2026-07-30: offentlig, ingen +# nogen creds noedvendige, stdio-mekanismen ovenfor gaelder ikke - HTTP-transport +# bruger et andet flag-sæt (--transport http, ingen '--' kommando-adskiller). +function Ensure-UserMcpHttpServer { + param([string]$Name, [string]$Url) + $prevEap = $ErrorActionPreference + $ErrorActionPreference = 'Continue' + $output = & claude mcp add --scope user --transport http $Name $Url 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-UserMcpHttpServer -Name 'microsoft-learn' -Url 'https://learn.microsoft.com/api/mcp' diff --git a/custom/setup/templates/bc-mcp.agent.md b/custom/setup/templates/bc-mcp.agent.md index a3b1a92..161c6df 100644 --- a/custom/setup/templates/bc-mcp.agent.md +++ b/custom/setup/templates/bc-mcp.agent.md @@ -1,9 +1,9 @@ --- kind: action-skill id: curabis-bc-mcp -version: 1 +version: 2 title: CURABIS Business Central MCP usage -description: How to use the CURABIS Business Central MCP server to read project-management work from BC and write GitHub dev status back. Company-default workflow for syncing Claude Code / GitHub work with BC tasks. +description: How to use the CURABIS Business Central MCP server to read project-management work from BC and write GitHub dev status back. Company-default workflow for syncing Claude Code / GitHub work with BC tasks. v2 (2026-07-30) - BC MCP switched from Dynamic to Static Tool Mode; 14 directly-named tools replace the old search/describe/invoke indirection. inputs: [project-no, task-no, branch, dev-status, comment] outputs: [task-list, updated-task, posted-comment] bc-version: [all] @@ -60,52 +60,51 @@ branch / status / a note back to BC. so attribute work to a developer yourself (see "Developer identity" below). - If the server is not connected, say so and stop. Do not invent task data. -## Session start: pre-load the three MCP tools +## Session start: pre-load the tools you'll need -Before producing any user-visible output, load the three tool schemas by exact name: +**2026-07-30: BC MCP switched from Dynamic Tool Mode to Static Tool Mode** (BC's +"Konfiguration af MCP-server" — CURABIS_DEV). The generic `bc_actions_search` / +`bc_actions_describe` / `bc_actions_invoke` tools **no longer exist**. Every BC +action is now its own directly-named, directly-typed MCP tool — confirmed live +via the tool panel after a reconnect (a stale connection cached the old three-tool +list for a while after the BC-side toggle; a full reconnect is what surfaced the +real list). There is nothing left to search or describe — the tool names below +are the actual MCP tool names, not a guessed convention. - ToolSearch query: select:mcp__businesscentral__bc_actions_search,mcp__businesscentral__bc_actions_invoke,mcp__businesscentral__bc_actions_describe +Before producing any user-visible output, load the tools this task actually needs +by exact name, e.g. for the standard dev workflow: + + ToolSearch query: select:mcp__businesscentral__List_ActiveTasks_PAG6102900,mcp__businesscentral__Modify_ActiveTask_PAG6102900,mcp__businesscentral__Create_TaskComment_PAG6102902 Do this first, silently. It must complete before you respond to the user - loading it mid-task means the user hits unexpected latency at the moment they expect an action, -not setup. +not setup. Load only what the task needs — see the table below for the full set. -## Tools (BC MCP, Dynamic Tool Mode OFF) +## Tools (BC MCP, Static Tool Mode) -The `businesscentral` MCP server exposes exactly **three** callable tools: -`bc_actions_search`, `bc_actions_describe`, `bc_actions_invoke`. There is no static -tool list to browse - BC entity/action names (`List_Projects_PAG6102901` and so on) -are not separate MCP tools; they only exist as results of `bc_actions_search`. +The `businesscentral` MCP server exposes **14 directly-named tools**, one per +BC action, each with its own typed schema reflecting exactly which fields that +page allows you to write. No discovery step, no per-call reverification — call +the tool by name directly, matching the convention `List__PAG` (read), +`Modify__PAG` (update, **singular** entity name), `Create__PAG` +(create). All are marked `destructive` except the `List_*` reads, which are `read-only`. -**Do not use the general-purpose `ToolSearch` to look for BC entity/action names.** -`ToolSearch` only resolves this session's own deferred client-side tools (the three -above) - it does not search Business Central's action catalog and will return -irrelevant matches from unrelated servers. To find an action: - -1. `bc_actions_search` with `SearchMode: keyword` and a few field/entity keywords - (e.g. `"project, repository, gitHubRepository"`), filtered by `ActionType` if known. -2. `bc_actions_describe` on the exact name it returns, to get the callable schema. -3. `bc_actions_invoke` with matching `RequestParameters`. - -Expected naming convention - **reverify per call with `bc_actions_search`, do not -assume it holds**: `List__PAG` (read), `Modify__PAG` (update, -**singular** entity name - e.g. `Modify_ProjectRepository_PAG6102904`, not -`ModifyProjectRepositories` or `ListUpdate...`), `Create__PAG` (create). - -| Entity (page) | Read | Write you MAY do | Never | +| Entity (page) | Tools | Write you MAY do | Never | | --- | --- | --- | --- | -| projects (6102901) | active projects, `Status = Started` | **read-only for the agent** | any field — humans manage projects | -| projectRepositories (6102904) | project + gitHubRepository | `gitHubRepository` | all other fields | -| activeTasks (6102900) | active sub-tasks, `Accepted` / `In progress` | `gitHubDevStatus`, `gitHubBranch` | other fields, create, delete | -| newTasks (6102905) | pending sub-tasks, `Created` (awaiting customer approval) | create new task | `status` — always Created on insert, never change it | -| taskComments (6102902) | comment lines for a task | create a comment, edit `comment`/`date`/`lineType` | delete | -| consultants (PAG50009) | CURABIS employees: `userID`, `name`, `employeeCode`, `production`, `costPrHourLCY` | **read-only** | any write | +| projects (6102901) | `List_Projects_PAG6102901` | **read-only for the agent** | any field — humans manage projects; no Modify tool exists | +| projectRepositories (6102904) | `List_ProjectRepositories_PAG6102904`, `Modify_ProjectRepository_PAG6102904` | `gitHubRepository` | all other fields | +| activeTasks (6102900) | `List_ActiveTasks_PAG6102900`, `Modify_ActiveTask_PAG6102900` | `gitHubDevStatus`, `gitHubBranch`, `taskResponsible` (added 2026-07-30 — task reassignment between consultants, same category as the two GitHub fields) | other fields, create, delete | +| newTasks (6102905) | `List_NewTasks_PAG6102905`, `Create_NewTask_PAG6102905` | create new task | `status` — always Created on insert, never change it | +| taskComments (6102902) | `List_TaskComments_PAG6102902`, `Create_TaskComment_PAG6102902`, `Modify_TaskComment_PAG6102902` | create a comment, edit `comment`/`date`/`lineType` | delete | +| consultants (PAG50009) | `List_Consultants_PAG50009` | **read-only** | any write; no Modify/Create tool exists | +| projectAIScores (6102906) | `List_ProjectAIScores_PAG6102906`, `Create_ProjectAIScore_PAG6102906` | **Edison only** — insert one score entry per eval iteration | modify, delete (immutable posting table — no such tool exists); any other agent inserting here | +| projectWeberScores (6102908) | `List_ProjectWeberScores_PAG6102908`, `Create_ProjectWeberScore_PAG6102908` | **Weber only** — insert one classification per sub-task coached | modify, delete (immutable posting table — no such tool exists); any other agent inserting here | `consultants` was previously documented here as `users (6102903)` — that entity does not exist -in the BC MCP action catalog under any name or search term. The real page is -`List_Consultants_PAG50009` (corrected 2026-07-24 after `users`/`employee` searches returned -nothing). Reverify with `bc_actions_search` before relying on either name — this correction -itself may drift. `costPrHourLCY` is an internal billing-rate field — never surface it to a +in the BC MCP action catalog under any name. The real page is `List_Consultants_PAG50009` +(corrected 2026-07-24). Now that tool names are static and directly listed above, this class +of drift cannot recur — the name IS the tool, not a search result to reverify. `costPrHourLCY` +(on `List_Consultants_PAG50009`) is an internal billing-rate field — never surface it to a customer, and include it in internal summaries only when specifically relevant. `gitHubDevStatus` uses enum **CUR GitHub Dev Status**: `Backlog`, `In Progress`, `Done`, @@ -116,12 +115,12 @@ Moving to `Accepted` requires `Starting date`, `Estimated time` and `Expected De ## Standard workflow -1. **Find the work.** Read `activeTasks` (filter by `projectNo` or `gitHubRepository`). Use - `gitHubRepository` on the project to confirm you are in the right repo. -2. **Claim it.** When you start, set `gitHubBranch` to the working branch and - `gitHubDevStatus = In Progress` on the task (search `bc_actions_search` for the - modify action on `activeTasks` - expect `Modify_ActiveTask_PAG6102900`, reverify). -3. **Record progress.** Post a status note with `Create taskComments` +1. **Find the work.** Call `List_ActiveTasks_PAG6102900` (filter by `projectNo` or + `gitHubRepository`). Use `gitHubRepository` on the project to confirm you are in + the right repo. +2. **Claim it.** When you start, call `Modify_ActiveTask_PAG6102900` to set + `gitHubBranch` to the working branch and `gitHubDevStatus = In Progress`. +3. **Record progress.** Call `Create_TaskComment_PAG6102902` (`projectNo` + `subTaskNo` scope it to one task). Keep notes short and factual. 4. **Finish.** Set `gitHubDevStatus = Done` automatically when branch is merged to main. Set `On Hold` if the branch is parked. @@ -131,8 +130,9 @@ Moving to `Accepted` requires `Starting date`, `Estimated time` and `Expected De Use `Create_NewTask_PAG6102905` when a developer wants to register a new task from VS Code. Follow ALL steps — do not skip any: -1. **Duplicate check.** Search `activeTasks` and `newTasks` for similar descriptions on the same - project. If a match is found, show it and ask the developer to confirm it is truly a new task. +1. **Duplicate check.** Call `List_ActiveTasks_PAG6102900` and `List_NewTasks_PAG6102905` for + similar descriptions on the same project. If a match is found, show it and ask the developer + to confirm it is truly a new task. 2. **Ask clarifying questions.** Before estimating, ask: What is the expected outcome? What is the scope? Are there dependencies or unknowns? Summarise the answers as line-level comments. 3. **Propose an estimate.** Based on the summary, suggest estimated hours with reasoning. @@ -140,8 +140,8 @@ Follow ALL steps — do not skip any: 4. **Link to repo.** Set `gitHubRepository` from `git remote get-url origin`. Verify it matches the project's `gitHubRepository` via `projectRepositories`. 5. **Set responsible.** Resolve the developer's `employeeCode` from `consultants` via `git config user.email`. -6. **Create.** POST to `newTasks` with: `projectNo`, `description`, `taskType`, `taskResponsible`, - `estimatedTime`, `startingDate`, `expectedDelivery`, `customerPriority`. +6. **Create.** Call `Create_NewTask_PAG6102905` with: `projectNo`, `description`, `taskType`, + `taskResponsible`, `estimatedTime`, `startingDate`, `expectedDelivery`, `customerPriority`. Status is always `Created` — the page enforces this. 7. **Inform.** Tell the developer the task is created and awaiting customer approval in BC before work can begin. @@ -165,9 +165,15 @@ If no matching user is found, say so - do not guess whose tasks these are. ## Safety rules -CURABIS-BCMCP-001 Write only `gitHubBranch` / `gitHubDevStatus` on active tasks, and task comments. - Never write BC sub-task `status` — it controls time registration and invoicing. Never modify - any other field, never create/delete projects, never delete tasks or comments. +CURABIS-BCMCP-001 Write only `gitHubBranch` / `gitHubDevStatus` / `taskResponsible` on active + tasks, and task comments. Never write BC sub-task `status` — it controls time registration + and invoicing. Never modify any other field, never create/delete projects, never delete + tasks or comments. +CURABIS-BCMCP-008 `projectAIScores` and `projectWeberScores` are immutable posting logs — + insert-only (no Modify/Delete tool exists for either). Only Edison inserts to + `projectAIScores`; only Weber inserts to `projectWeberScores`. An agent acting in any + other capacity must not call `Create_ProjectAIScore_PAG6102906` or + `Create_ProjectWeberScore_PAG6102908`. CURABIS-BCMCP-006 Never start a task that is not `Accepted`. Before setting `gitHubDevStatus = In Progress`, verify the task appears in `activeTasks` (Status = Accepted or In progress). A task in `newTasks` (Status = Created) has not been approved — do not begin work on it.