Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions GOLD-STANDARD.html
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ <h2>6. The harness standard</h2>
│ ├── deploy-dev.yml # merge to main -&gt; client dev environment (automatic, unattended)
│ ├── deploy-promote.yml # dev -&gt; test -&gt; prod; manual only, named approver every time
│ ├── dependency-scan.yml # weekly advisory scan; raises an issue, never blocks
│ ├── rails-telemetry.yml # weekly gate-outcome report, committed for the fleet view
│ └── eval-*.yml # eval-regression + eval-suite (§11 agentic work)
├── scripts/rails/ # diff-anchors.sh, apply-branch-protection.sh
├── eval-datasets/ + prompts/ # golden-set template + versioned judge prompts (§11 work only)
Expand Down Expand Up @@ -1527,6 +1528,8 @@ <h2>10. The kit (what's in this repo)</h2>
│ │ # manual only, human go/no-go every time — §7)
│ │ # + dependency-scan.yml (weekly standing-stock advisory scan;
│ │ # the blocking half is ci.yml's dependency-gate job — §7)
│ │ # + rails-telemetry.yml (weekly gate-outcome report, committed;
│ │ # read across repos by scripts/collect_rails_telemetry.py — §9)
│ │ # (+ eval-regression.yml, eval-suite.yml for agentic specs — §11)
│ ├── packs/ # composable additions: stacks/dotnet, cicd/github, cicd/azure-devops,
│ │ # frontend/generic, frontend/react, tools/gitnexus
Expand Down
31 changes: 31 additions & 0 deletions GOLD-STANDARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,34 @@ flat.
Client-facing scorecard: their success metric, the DORA stability pair, accepted-as-is trend,
and the demo. That's it.

### Watching the gates across engagements

Every gate outcome and every override is recorded in the repo it happened in — the accepted-risk
labels, the two ledgers, the PR timeline. That is enough to answer a question about one repo and
useless for answering one about a portfolio. So each installed repo writes a weekly
`rails-telemetry.json` and commits it: which gates ran and what they concluded, every override by
name with the change it was applied to, and — the part that needs a machine — **which checks
branch protection actually requires, against which gate jobs actually exist**.

That last comparison is the reason the file exists. A gate has two halves: the check, and the rule
requiring it to pass. Remove the rule and the check still runs, still reports, and looks entirely
normal on the pull request; a red run simply merges anyway. From outside that repo, a gate someone
disarmed and a gate that never caught anything produce identical evidence. No amount of counting
separates them.

Two constraints on this, both non-negotiable. **It stays inside the client's tenancy** — the
workflow reads the repo's own history through the platform's own API and writes into the same
repo; nothing is transmitted anywhere, which is what makes it something a client security team can
approve. And **it counts gates, never people**: an override count is reported against merged
changes so it reads as a rate rather than a bare number, and there is no per-author breakdown
anywhere in the file. The rule from earlier in this section holds here too — we measure the rails,
not the humans.

`scripts/collect_rails_telemetry.py` (operator tooling, not part of the kit and never installed)
reads those files across every reachable repo and reports worst-first. A repo that is not
reporting is listed as **unknown, not clean** — a fleet view that quietly counts silence as health
is the same failure it was built to catch.

---

## 10. The kit (what's in this repo)
Expand Down Expand Up @@ -597,13 +625,16 @@ intent-driven-development/ # cloned locally as delivery-standard/ on some ma
│ │ # manual only, human go/no-go every time — §7)
│ │ # + dependency-scan.yml (weekly standing-stock advisory scan;
│ │ # the blocking half is ci.yml's dependency-gate job — §7)
│ │ # + rails-telemetry.yml (weekly gate-outcome report, committed;
│ │ # read across repos by scripts/collect_rails_telemetry.py — §9)
│ │ # (+ eval-regression.yml, eval-suite.yml for agentic specs — §11)
│ ├── packs/ # composable additions: stacks/dotnet, cicd/github, cicd/azure-devops,
│ │ # frontend/generic, frontend/react, tools/gitnexus
│ ├── eval-datasets/ # golden-set template (§11)
│ ├── prompts/ # versioned judge prompts (§11)
│ ├── infra/ # Bicep starters
│ └── profile/ # CODEOWNERS, rubrics, branch-protection ruleset, rails scripts
│ # + rails-telemetry.schema.json (the report's shape, fixed at v1)
│ # + eval-bypasses.md and dependency-exceptions.md (the two
│ # accepted-risk ledgers — each entry named, dated, and expiring)
│ # (customer profiles — starter, microsoft-enterprise, … — live in
Expand Down
23 changes: 23 additions & 0 deletions docs/the-rails.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,24 @@ inflate every one of those, and the published research is blunt about it — mea
doubled PR volume while actual delivery stayed flat. The rails are healthy when changes flow and
fail rarely, not when the agents are busy.

**Watch that the gates are still armed, not just that they are green.** Proving a rail once, at
Foundation, proves it was wired that week. Branch protection is edited later — during an
incident, in a repo reorganisation, by someone with admin who meant to change one thing. The
moment a check stops being *required*, it keeps running and keeps reporting, and a red run
merges anyway. Nothing on the pull request looks different. From outside the repo, a disarmed
gate and a gate that never caught anything are the same picture.

So each repo writes a weekly `rails-telemetry.json` — what ran, every override by name, and the
comparison of what branch protection *requires* against what the workflows *declare*. It reads
the repo's own history through the platform's own API and commits into the same repo; nothing
leaves the client's tenancy. `scripts/collect_rails_telemetry.py` reads those files across the
fleet and puts disarmed gates at the top, with repos that are not reporting listed as **unknown
rather than clean** — counting silence as health is the failure this exists to catch.

Where the file cannot read live branch protection it falls back to the committed ruleset and
says so, because that reading describes *intent* rather than what the platform is enforcing.
Presenting the two as equivalent would be the same silent-green problem one layer up.

**Log everything with provenance.** Every recommendation an agent made, every artifact that got
applied, every policy-gate outcome — logged centrally, with co-authorship on the commits, so any
change is traceable to the identity that produced it. After a poisoned tool-return steers an agent
Expand Down Expand Up @@ -557,6 +575,11 @@ the provenance trail is what makes the rails auditable rather than merely automa
- **The skipped environment.** A green build promoted from dev directly to prod because the
operator picked the wrong target and nothing checked. "The same build that passed test" is only
true if something enforces that it actually passed test.
- **The gate that was quietly unrequired.** Someone removes a check from branch protection to
unblock an urgent fix and never puts it back. The workflow still runs, still posts its
verdict, still looks exactly as it did — and stops mattering. This is not caught by watching
pull requests, because nothing about them changes; only comparing what is required against
what exists finds it.
- **The dependency scan that reports nothing.** A misconfigured scan, a private feed with no
vulnerability data, or a broken output parser all produce the same clean green as a genuinely
clean repo. "No findings" and "not looking" are indistinguishable from the outside, which is
Expand Down
2 changes: 2 additions & 0 deletions kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ so install here unless you also repoint the references.
| `workflows/RAILS.md` | `./.github/RAILS.md` | Operator's guide + shakedown drills. |
| `profile/rubrics/*` | `./.github/profile/rubrics/` | Workflows read these by this path. |
| `workflows/dependency-scan.yml` | `./.github/workflows/` | Weekly scan of the **standing stock** of third-party advisories. Raises (and self-closes) one issue; never blocks — the blocking, diff-scoped half is `ci.yml`'s `dependency-gate` job. On by default: a security scan you have to remember to switch on is not running. |
| `workflows/rails-telemetry.yml` | `./.github/workflows/` | Weekly gate-outcome report, committed as `.github/rails-telemetry.json`. Records what ran, every override by name, and **which checks branch protection actually requires vs which gate jobs exist** — the comparison that catches a gate someone disarmed. No external calls: it reads this repo's own history and writes into this repo. |
| `profile/rails-telemetry.schema.json` | `./.github/rails-telemetry.schema.json` | The report's shape, fixed at version 1 before the install wave so it is not retrofitted across live repos. The fleet collector refuses a version it does not know rather than misreading it. |
| `profile/eval-bypasses.md` | `./.github/eval-bypasses.md` | Override/bypass ledger. |
| `profile/dependency-exceptions.md` | `./.github/dependency-exceptions.md` | Accepted-risk ledger for `dependency-gate`. The `accepted-risk:dependency` label clears one PR; this records why, who decided, whether the vulnerable path is reachable, and when the acceptance expires. Swept at Setup review. |
| `profile/CODEOWNERS` | `./.github/CODEOWNERS` | |
Expand Down
Loading