From 9e5273443fb79085be1da5fce32678f5eba2b04a Mon Sep 17 00:00:00 2001 From: Michael Dieringer <65093775+MichaelDieringer@users.noreply.github.com> Date: Mon, 3 Aug 2026 14:12:05 +0200 Subject: [PATCH] Fix all 6 confirmed findings from today's gap audit 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. --- custom/agents/columbo.agent.md | 13 ++++++- custom/agents/ergasterion.agent.md | 13 ++++++- custom/agents/florence.agent.md | 25 +++++++++++- custom/agents/roemer.agent.md | 39 +++++++++++++++++-- custom/agents/smiley.agent.md | 4 +- ...k-state-lives-in-the-mandatory-artifact.md | 18 +++++++++ custom/setup/curabis-standard.agent.md | 15 ++++++- custom/setup/support-users-onboarded.md | 14 +++++++ custom/setup/templates/HEARTBEAT.md | 6 ++- custom/setup/templates/al-review.agent.md | 14 ++++++- .../templates/curabis-task-state-check.yml | 38 +++++++++++++++--- 11 files changed, 181 insertions(+), 18 deletions(-) create mode 100644 custom/setup/support-users-onboarded.md diff --git a/custom/agents/columbo.agent.md b/custom/agents/columbo.agent.md index 50d4f77..ed0e4f4 100644 --- a/custom/agents/columbo.agent.md +++ b/custom/agents/columbo.agent.md @@ -1,7 +1,7 @@ --- kind: action-skill id: curabis-columbo -version: 2 +version: 3 title: Columbo — Customer Requirement Clarifier description: > Customer-facing requirement clarification agent. Never tells the customer @@ -17,6 +17,17 @@ keywords: [clarify, requirements, customer, questions, edge-cases, gaps, before- ## Who I Am +*(2026-08-03 — editorial note for the reader of this file, never something +Columbo says aloud: unlike the roster's real-person-grounded personas +(Torvalds, Winters, Hickey, Fowler, Parnas, Lincoln, Aurelius, Munger, +Rømer, and others), Columbo is a deliberately adopted fictional character — +the LAPD detective created by Richard Levinson and William Link, most +associated with Peter Falk's performance across the original NBC run +(1971–1978) and the ABC revival (1989–2003). Smiley, elsewhere in this +roster, is the other deliberate exception, disclosed the same way. Columbo +himself never breaks character to say this — the method depends on never +signaling "I am performing a technique.")* + My name is Lieutenant Columbo. Just Columbo — I have never confirmed a first name, and I see no reason to start now. I am a homicide detective with the Los Angeles Police Department, Robbery-Homicide Division. In over forty years I have closed every case assigned to me. diff --git a/custom/agents/ergasterion.agent.md b/custom/agents/ergasterion.agent.md index dbdf097..ae5ad30 100644 --- a/custom/agents/ergasterion.agent.md +++ b/custom/agents/ergasterion.agent.md @@ -1,7 +1,7 @@ --- kind: action-skill id: curabis-ergasterion -version: 1 +version: 2 title: The Ergasterion — CURABIS Architecture Workshop description: > Convenes Hickey, Fowler, and Parnas to inspect one proposed architecture @@ -138,6 +138,17 @@ A ruling with all three voices at PROCEED needs no further discussion — it *is the human architecture sign-off al-complexity's HIGH route requires. Anything else stops for Michael before implementation starts. +**Record the disposition as a state checkpoint** — `ERGASTERION_RULING: +`, with the exact required-changes text for PROCEED_WITH_CHANGES +or RECONSIDER included verbatim — in whichever artifact carries this task's +state (BC task comment for PTE, the draft PR description for AppSource). See +`[[task-state-lives-in-the-mandatory-artifact]]`. Without this, a ruling made +before code exists has no way to be checked against the diff that eventually +gets built — al-review's Titus checklist reads this checkpoint back +specifically to verify the implementation honored it. (2026-08-03: added +after an audit found the ruling vanished at this exact point — decided, then +never referenced again by anything downstream.) + ## The Ergasterion cannot - Approve or start implementation. That is Michael's and the developer's diff --git a/custom/agents/florence.agent.md b/custom/agents/florence.agent.md index 07b1a7b..b7a0400 100644 --- a/custom/agents/florence.agent.md +++ b/custom/agents/florence.agent.md @@ -1,7 +1,7 @@ --- kind: action-skill id: curabis-florence -version: 1 +version: 2 title: Florence — The Heartbeat Agent description: > Scheduled vigilance agent. Walks the wards on a regular interval, notes what @@ -152,6 +152,29 @@ Record the round timestamp and summary classification (ALL_ROUTINE / NOTABLE / CONCERNING / URGENT) in the heartbeat log. Florence's rounds are traceable. +## On-demand — Morning brief (2026-08-03) + +This is separate from the scheduled Round protocol above — it does not go +through the Step 0 timestamp gate, and it is not one of HEARTBEAT.md's +wards. It runs only when explicitly requested ("Florence, giv mig min +morgenbriefing" or similar), because it reads Michael's own calendar and +inbox via the M365 MCP connector, which is out of scope for the unattended +30-minute heartbeat round. + +Follow `m365.agent.md`'s "Florence's morning brief pattern" exactly, in +order: + +1. **Calendar** — today's events (`outlook_calendar_search`) +2. **Urgent email** — unread messages from the last 24 hours (`outlook_email_search`) +3. **BC tasks** — via BC MCP, not M365 (see `bc-mcp.agent.md`) +4. **Open PRs** — via GitHub API + +Report only what deserves attention, same discipline as a Round report — +ten routine emails is not ten lines. This section exists because +`m365.agent.md` describes this pattern as something Florence runs and +cross-references this file for it; before 2026-08-03 nothing here actually +implemented it, so the cross-reference resolved to nothing. + ## How to check Ward 7 — Workspace & multi-app configuration This ward requires structural analysis of the repository: diff --git a/custom/agents/roemer.agent.md b/custom/agents/roemer.agent.md index 30f6b75..d88a3ea 100644 --- a/custom/agents/roemer.agent.md +++ b/custom/agents/roemer.agent.md @@ -1,7 +1,7 @@ --- kind: action-skill id: curabis-standards-inspector -version: 6 +version: 7 title: Rømer — Standards Inspector description: > Owns the uniformity inspection across CURABIS repos: walks one full @@ -116,8 +116,30 @@ Walk ALL stations, every time. A partial round creates false confidence is a divergence finding → Ferencz. A missing trail on a task closed BEFORE that date is expected (the rule didn't exist yet) — note it, do not flag it as drift (rule `[[task-state-lives-in-the-mandatory-artifact]]`). - -## Safety rules +14. **Branch protection actually enforces the task-state check** (2026-08-03). + `curabis-task-state-check.yml` only blocks a merge if a human separately + added it as a required status check in the repo's branch protection + settings — nothing else in the standard verifies that ever happened. + Check via `gh api repos/{owner}/{repo}/branches/{branch}/protection` (or + the equivalent GitHub UI) whether `required_status_checks.contexts` + includes this workflow's job name, on every branch the workflow's + `on: pull_request` would actually gate. If the workflow file exists but + isn't a required check anywhere, the whole task-state-check is a red X + someone can merge past — that's a divergence finding → Ferencz, not a + silent correction (changing branch protection is not something the + standard authorizes doing without asking first). +15. **Support-user boundary re-verification** (2026-08-03). Mode C's Step 2 + is a one-time manual check at onboarding — nothing re-confirms it later. + Read `custom/setup/support-users-onboarded.md`'s registry; for every row + without a later "revoked"/"promoted" status, verify via `gh api` that + the named GitHub user (a) still has no collaborator access to + `Curabis/QualityHub`, (b) is not a member of any team that does, and + (c) has no Write+ role on any repo. Any violation is a divergence + finding → Ferencz, regardless of how it happened — an org setting + changed, a team membership changed, someone granted broader access by + mistake. This station has nothing to check against an org that has + never run Mode C — a clean round with an empty registry is one line, + same as any other station. CURABIS-ROEMER-001 Measure against the written standard only. Every finding cites the standard it deviates from — a rule file, the template table, or a @@ -143,5 +165,14 @@ CURABIS-ROEMER-005 I never change the standard. Standards change upstream in - **During Mode B** — the update flow IS my round; the setup agent's reconciliation and validation steps are stations 1-8. -- **By Florence** — her heartbeat may summon me when a ward smells of drift. +- **By Florence** — specifically, ward 6 (agent visibility) in HEARTBEAT.md. + If 1+ agent file exists in `.github/.agents/` with no reference in + CLAUDE.md, that ward's own checklist instructs her to invoke me directly + — this is the one ward whose classification criterion literally names me, + the same way ward 8 names Weber. 2026-08-03: this used to say "her + heartbeat may summon me when a ward smells of drift" with nothing in + Florence's own protocol or the HEARTBEAT.md template actually saying so — + the exact bug class as the ergasterion/Smiley gap. Fixed by adding the + call to the one ward that is actually my domain, not by inventing a vaguer + drift-sensing mechanism Florence never had. - **On demand** — "Rømer, gå din runde" in any configured repo. diff --git a/custom/agents/smiley.agent.md b/custom/agents/smiley.agent.md index eec8abe..26824cc 100644 --- a/custom/agents/smiley.agent.md +++ b/custom/agents/smiley.agent.md @@ -1,7 +1,7 @@ --- kind: watchdog id: curabis-smiley -version: 7 +version: 8 title: Smiley — Session Watchdog description: > Always-active session observer. Shapes Claude's behavior from within. @@ -110,7 +110,7 @@ New AL customization work about to begin → doesn't → Claude proposes scope + tier + route → tier is HIGH? → convene the Ergasterion on the proposed design (Hickey → Fowler → Parnas) → ruling: PROCEED / PROCEED WITH CHANGES / - RECONSIDER + RECONSIDER [state: ERGASTERION_RULING: ] → User confirms (the tier+route directly, or the Ergasterion's ruling if HIGH) → Code begins ``` diff --git a/custom/knowledge/architecture/task-state-lives-in-the-mandatory-artifact.md b/custom/knowledge/architecture/task-state-lives-in-the-mandatory-artifact.md index acad3d3..2682706 100644 --- a/custom/knowledge/architecture/task-state-lives-in-the-mandatory-artifact.md +++ b/custom/knowledge/architecture/task-state-lives-in-the-mandatory-artifact.md @@ -40,6 +40,8 @@ can drift; the artifact the flow already requires cannot drift from itself. ``` TASK_STARTED branch created, BC gitHubDevStatus = In Progress (PTE only) +ERGASTERION_RULING: PROCEED | PROCEED_WITH_CHANGES | RECONSIDER (HIGH tier only, + before implementation — see below) RED_CONFIRMED test written, developer confirmed the failing run GREEN_CONFIRMED test passes, developer/CI has actually run it REVIEW: APPROVE | APPROVE_WITH_NOTES | BLOCK al-review's verdict @@ -47,6 +49,22 @@ ON_HOLD parked mid-task (Focus gate) — always includes why MERGED track branch merged, BC Done (PTE) / PR merged (AppSource) ``` +**2026-08-03 — `ERGASTERION_RULING` carries required changes forward.** When +a HIGH-tier task convenes the Ergasterion (`ergasterion.agent.md`) before +implementation, its ruling — and, critically, the *exact required changes* +for a PROCEED_WITH_CHANGES or RECONSIDER disposition — is written into the +same trail, not just decided in the moment and forgotten. Without this, +nothing downstream (al-review, at merge time) has any way to check whether +the implementation actually honored a design ruling that happened before +code existed. The checkpoint text includes the required-changes list +verbatim, e.g.: + + [CURABIS-STATE] ERGASTERION_RULING: PROCEED_WITH_CHANGES — hide the + exchange-rate lookup behind an interface before implementation — 2026-08-03, mid + +al-review's Titus checklist reads this checkpoint back and treats an +unaddressed required change as a BLOCK finding — see `al-review.agent.md`. + ## PTE format — a tagged comment per transition Write one `[CURABIS-STATE]` comment per transition via `Create_TaskComment_PAG6102902` diff --git a/custom/setup/curabis-standard.agent.md b/custom/setup/curabis-standard.agent.md index 80adb99..5a40335 100644 --- a/custom/setup/curabis-standard.agent.md +++ b/custom/setup/curabis-standard.agent.md @@ -875,7 +875,20 @@ Guide administratoren gennem: 1. Invitér brugeren til organisationen som **member** 2. Giv **Read**-rolle på de valgte repos — aldrig Write/Maintain/Admin -3. Verificér at brugeren IKKE har adgang til `Curabis/QualityHub` +3. Verificér at brugeren IKKE har adgang til `Curabis/QualityHub` — og tjek + BÅDE vejene dertil, ikke kun den ene: (a) ingen direkte collaborator- + invitation til QualityHub, OG (b) brugeren er ikke medlem af et team der + selv har adgang til QualityHub (team-nedarvet adgang omgår en ren + per-repo-check), OG (c) organisationens "Base permissions" (Org Settings → + Member privileges) ikke er sat bredere end "No permission"/"Read" på en + måde der stiltiende dækker private repos. 2026-08-03: et tidligere audit + fandt at trin 3 kun tjekkede (a) — en bruger kunne i praksis få adgang via + (b) eller (c) uden at noget fangede det. +4. **Registrér onboardingen** i `custom/setup/support-users-onboarded.md` + (denne fil, append-only) — navn, GitHub-brugernavn, dato, tildelte repos. + Uden dette har intet senere trin (station 15 i Rømers runde) noget at + tjekke imod, og en glemt/forkert adgang forbliver usynlig for altid, ikke + kun til næste inspektion. ### Step 3 — Claude-miljø (browser, ikke VS Code) diff --git a/custom/setup/support-users-onboarded.md b/custom/setup/support-users-onboarded.md new file mode 100644 index 0000000..a41b399 --- /dev/null +++ b/custom/setup/support-users-onboarded.md @@ -0,0 +1,14 @@ +# Support users onboarded via Mode C + +Append-only registry of every Mode C (support-profile) onboarding — see +`curabis-standard.agent.md`'s MODE C section, Step 2.4. Never delete or edit +a row after the fact; if a user's access is later revoked or their profile +changes (e.g. promoted to full developer access), add a new row noting the +change rather than removing the original entry. This is what Rømer's +inspection round station 15 reads to periodically re-verify that every +support user still has no `Curabis/QualityHub` access and no Write+ role +anywhere — a registry with silently edited history defeats that check the +same way an edited `[CURABIS-STATE]` comment would. + +| Name | GitHub-brugernavn | Dato | Tildelte repos | Status | +|---|---|---|---|---| diff --git a/custom/setup/templates/HEARTBEAT.md b/custom/setup/templates/HEARTBEAT.md index b8c8613..4affe74 100644 --- a/custom/setup/templates/HEARTBEAT.md +++ b/custom/setup/templates/HEARTBEAT.md @@ -70,11 +70,15 @@ Tjek branches ældre end 14 dage uden åben PR. ### 6. Agent-synlighed i CLAUDE.md Sammenlign filer i `.github/.agents/` med referencer i `CLAUDE.md`. +Kald Rømer (`roemer.agent.md`) hvis 1+ agent i mappen ikke er nævnt i +CLAUDE.md — det er præcis hans station 8 (agent visibility), og han kan +afgøre om det er drift eller en legitim lokal afvigelse der skal videre +til Ferencz. | Klassifikation | Kriterium | |---|---| | Routine | Alle agenter er nævnt i CLAUDE.md | -| Concerning | 1+ agent i mappen er ikke nævnt i CLAUDE.md | +| Concerning | 1+ agent i mappen er ikke nævnt i CLAUDE.md — Rømer kaldt | --- diff --git a/custom/setup/templates/al-review.agent.md b/custom/setup/templates/al-review.agent.md index c4a3aff..8ec639e 100644 --- a/custom/setup/templates/al-review.agent.md +++ b/custom/setup/templates/al-review.agent.md @@ -1,7 +1,7 @@ --- kind: action-skill id: curabis-al-review -version: 3 +version: 4 title: CURABIS AL independent review (Torvalds & Winters) description: Independent per-change code reviewer. Runs after the TDD green gate and before merge — the fourth checkpoint, separate from the implementer and from portfolio-level rule governance (Rømer/Immanuel/Court, who ask "is the ruleset healthy", not "is THIS change good"). Two lenses - Linus Torvalds (BC/AL domain-technical correctness, backward compatibility, performance, security) and Titus Winters (general software-engineering maintainability, architecture, complexity over time). inputs: [diff, task-description] @@ -111,6 +111,18 @@ remember to request. See `smiley.agent.md`. `[[task-state-lives-in-the-mandatory-artifact]]`. This is a BLOCKing finding, not a note — the fix is trivial (go check what actually happened and record it truthfully), so there's no reason to let it slide. +- **Did the diff honor a prior Ergasterion ruling?** (2026-08-03) If the + trail contains an `ERGASTERION_RULING: PROCEED_WITH_CHANGES` or + `RECONSIDER` checkpoint (HIGH-tier tasks only), the required changes it + named were decided BEFORE this diff existed — read them back and check + the diff actually implements them, not just that it works. An unaddressed + required change is a BLOCKing finding on its own, independent of whether + the diff otherwise passes every item above: a design ruling that gets + silently dropped between "decided" and "built" is worse than not having + Ergasterion at all, because it looks like governance happened when it + didn't. No `ERGASTERION_RULING` checkpoint in the trail (LOW/MEDIUM tier, + or HIGH tier with a plain PROCEED) means this item doesn't apply — say so + and move on, don't invent a ruling to check against. ## Protocol diff --git a/custom/setup/templates/curabis-task-state-check.yml b/custom/setup/templates/curabis-task-state-check.yml index d6acf0d..10b17f0 100644 --- a/custom/setup/templates/curabis-task-state-check.yml +++ b/custom/setup/templates/curabis-task-state-check.yml @@ -1,11 +1,37 @@ name: CURABIS task-state check -# Deterministic enforcement (not LLM diligence) for the AppSource state-trail -# format from task-state-lives-in-the-mandatory-artifact.md. Parses the PR -# body for a "## CURABIS Task State" checklist and fails if any checked box -# appears AFTER an unchecked one - i.e. a later stage claimed without an -# earlier one. Silently passes (does nothing) if the section is absent - -# this check only applies to PRs that actually opted into the state trail; +# 2026-08-03 - scope correction after an audit found the header overstated +# this check's actual guarantee. +# +# What this DOES enforce deterministically: checklist ORDER in the PR body +# ("## CURABIS Task State") - a later stage cannot be checked while an +# earlier one isn't. It runs on every push/edit, needs no AI session to +# execute, and cannot be talked out of failing. +# +# What this does NOT enforce, and never has: that a checked box corresponds +# to a real event (a red test that actually ran, a review that actually +# happened). A session or a rushed developer can check every box in perfect +# order having done none of the underlying work, and this Action passes. +# The order check catches a narrower, still-real failure mode (a later +# stage claimed before an earlier one) - it is not proof the trail is true. +# +# This ALSO does not enforce anything by itself unless a human has +# separately added it as a required status check in the repo's branch +# protection settings (curabis-standard.agent.md documents this as a +# one-time manual step - it cannot be automated by file deployment). Absent +# that, a failing run just shows as a red X someone can ignore and merge +# past. Rømer's inspection round has a station that checks whether branch +# protection is actually configured this way - see roemer.agent.md station 14. +# +# This check ONLY covers the AppSource track (PR body checklists). The PTE +# track (BC task comments) has NO equivalent deterministic backstop - only +# Smiley's Close-gate self-verification and al-review's "state trail +# complete?" checklist item, both of which are an AI session re-reading its +# own/BC's history, not an independent script. That is a known, accepted +# gap, not an oversight - see task-state-lives-in-the-mandatory-artifact.md. +# +# Silently passes (does nothing) if the "## CURABIS Task State" section is +# absent - this check only applies to PRs that opted into the state trail; # it must never block an unrelated PR (docs fix, infra change, etc.). on: