mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 22:56:55 +01:00
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.
103 lines
4.7 KiB
YAML
103 lines
4.7 KiB
YAML
name: CURABIS task-state check
|
|
|
|
# 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:
|
|
pull_request:
|
|
types: [opened, edited, synchronize, reopened]
|
|
|
|
jobs:
|
|
check-task-state-order:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Validate CURABIS Task State checklist order
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const body = context.payload.pull_request.body || "";
|
|
const heading = "## CURABIS Task State";
|
|
const headingIdx = body.indexOf(heading);
|
|
if (headingIdx === -1) {
|
|
console.log("No '## CURABIS Task State' section found - not a state-tracked PR, skipping.");
|
|
return;
|
|
}
|
|
|
|
// Take everything after the heading up to the next "## " heading (or end of body).
|
|
const rest = body.slice(headingIdx + heading.length);
|
|
const nextHeadingIdx = rest.search(/\n##\s/);
|
|
const section = nextHeadingIdx === -1 ? rest : rest.slice(0, nextHeadingIdx);
|
|
|
|
const lineRe = /^-\s*\[( |x|X)\]\s*(.+)$/gm;
|
|
const items = [];
|
|
let m;
|
|
while ((m = lineRe.exec(section)) !== null) {
|
|
items.push({ checked: m[1].toLowerCase() === "x", label: m[2].trim() });
|
|
}
|
|
|
|
if (items.length === 0) {
|
|
core.setFailed(
|
|
"Found a '## CURABIS Task State' heading but no checklist lines under it " +
|
|
"(expected '- [ ] ...' / '- [x] ...'). Either add the checklist or remove the heading."
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Valid order is monotonic: once an item is unchecked, every item after it
|
|
// must also be unchecked. A checked item after an unchecked one means a
|
|
// later stage was marked done while an earlier one wasn't.
|
|
let seenUnchecked = false;
|
|
let brokenAt = -1;
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (!items[i].checked) {
|
|
seenUnchecked = true;
|
|
} else if (seenUnchecked) {
|
|
brokenAt = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (brokenAt !== -1) {
|
|
const lines = items.map((it, i) =>
|
|
` ${i === brokenAt ? ">>" : " "} [${it.checked ? "x" : " "}] ${it.label}`
|
|
).join("\n");
|
|
core.setFailed(
|
|
"CURABIS Task State checklist is out of order - a later stage is checked " +
|
|
"while an earlier one is not. A stage cannot be marked done before the ones " +
|
|
"before it. Offending line marked with '>>':\n\n" + lines
|
|
);
|
|
return;
|
|
}
|
|
|
|
console.log(`CURABIS Task State checklist order OK (${items.filter(i => i.checked).length}/${items.length} checked).`);
|