Daily Fro Bot Report — 2026-09-22 (UTC)
Run Summary
| Category |
Status |
Notes |
| Errored PRs |
✅ |
Remediation pass checked all 5 open PRs against both check-runs and legacy statuses. All green. 0 repairs needed. |
| Security |
⚠️ |
Advisory data fully available for this repo. 1 open medium dev-scope advisory (Renovate-owned, below the remediation bar) + 1 open high Scorecard posture finding. 0 remediation PRs, correctly. |
| Control-Plane Integrity |
✅ |
20/20 action pins verified SHA↔tag, not just "pinned". Strip-only TS clean. All 29 workflows declare permissions:. Live branch protection matches .github/settings.yml exactly. |
| Code Quality |
✅ |
bootstrap / check-types / lint / test all pass at 9b9635b. 3687 tests, 79 files. |
| Oversight |
⚠️ |
43 stale Fro-Bot-authored PRs across 8 repos; 5 repos red on default branch; Gateway tracker #3512 carries 4 closed items as open and version claims ~29 minors stale. ❔ sub-source: Dependabot alerts unreadable on 28 of 34 repos (HTTP 403). |
| Cross-Project Intelligence |
⚠️ |
Coverage partial: 29 of 34 tracked entries scanned. 2 last-survey failures, 3 private never-surveyed (by design), 1 lost-access. 3 accessible write-tier repos are absent from the ledger entirely. |
| Progressive Improvement |
⚠️ |
Compounding pipeline stalled: 10 open learning-proposal issues, last authoring commit 2026-09-07 (15 days). No unmanaged tool drift — the two apparent majors are both deliberate holds. |
Errored PRs
None. The remediation pass ran categories 1–4 in branch-pr mode ahead of this job and opened zero PRs, pushed zero branches, and made zero commits. Its findings are recorded on commit comment 201424711.
All five open PRs were verified green against both signal sources:
| PR |
Author |
Check runs |
Legacy statuses |
| #3912 eslint → v10.11.0 |
app/fro-bot |
17 completed, 0 failing |
renovate/stability-days, Security: Private Leak Scan |
| #3911 fro-bot/agent → v0.114.0 |
app/fro-bot |
20 completed, 0 failing |
Security: Private Leak Scan |
| #3904 bfra-me/.github → v4.31.0 |
app/fro-bot |
20 completed, 0 failing |
Security: Private Leak Scan |
| #3901 renovate comment fix |
fro-bot |
17 completed, 0 failing |
Security: Private Leak Scan |
| #3882 pnpm → v11.27.0 |
app/fro-bot |
17 completed, 0 failing |
renovate/stability-days, Security: Private Leak Scan |
Security: Private Leak Scan and renovate/stability-days never appear in /check-runs — they are commit statuses. Anything reading only gh pr checks is blind to both.
Security
Advisory data was available to the token for this repository. No guessing.
- Dependabot: 1 open alert —
GHSA-p498-v437-472g, npm/@humanfs/node, medium, development scope, transitive via pnpm-lock.yaml. Below the critical/high remediation bar and squarely Renovate's lane. It appears on the Dependency Dashboard as part of the eslint chain.
- Code scanning: 4 open alerts, all OpenSSF Scorecard posture findings, none an exploitable code defect:
VulnerabilitiesID (high — re-reporting the advisory above), BranchProtectionID (high — see Needs Human Attention 3), FuzzingID (medium), CIIBestPracticesID (low).
Zero remediation PRs opened, which is the correct outcome for this input.
Control-Plane Integrity
Verified clean on all four sub-checks.
- SHA pinning. 20 distinct third-party refs across
.github/workflows/*.yaml and .github/actions/**/action.yaml. Zero floating tags, zero missing version comments — and the remediation pass went past the usual check, dereferencing repos/{owner}/{repo}/git/ref/tags/{tag} (following annotated tag objects to their target commit) to confirm each pin actually resolves to the tag its comment claims. Current-version truth came from the GitHub git-ref API on each action's own repository. 20/20 agree. No version bumps were included, so no major-drift decision arose — Renovate owns that.
- Strip-only TypeScript. Clean: no
enum, namespace/module, import x = aliases, or constructor parameter properties in scripts/*.ts. The one grep hit is a comment at scripts/repos-metadata.ts:476 explaining the constraint.
- Least privilege. All 29 workflows declare
permissions:. The only broad grant is permissions: read-all in scorecard.yaml — the upstream OpenSSF template shape, read-only. 18 workflows route through ./.github/actions/setup; no workflow installs dependencies outside it.
- Guard integrity. Live protection on
main matches .github/settings.yml exactly: same 14 required contexts, strict: true, enforce_admins: true, linear history. Nothing weakened. One guard is actively holding the line — see Needs Human Attention 1.
Code Quality
pnpm bootstrap, pnpm check-types, pnpm lint, pnpm test all pass at main 9b9635b. 79 test files, 3687 passing, 3 todo, 21.7s. No mechanical autofix available, so nothing to commit.
Workflow health across all 29 workflows: one failure — Merge Data Branch (see below). Everything else green or explicably idle (Unpublish Wiki never run by design; Capture Patterns manual-first; Reset Survey Status manual-only; Copilot Setup Steps path-filtered).
Oversight
Scope. 38 repositories enumerated via paginated user/repos with affiliation=owner,collaborator,organization_member; 34 non-archived, all public, all write-tier. user/orgs returned empty, so bfra-me/* reaches the account through collaborator affiliation rather than org membership — worth knowing, because an org-scoped enumeration would have returned nothing at all. Public repos outside that affiliation set (e.g. marcusrbrown/panthe.ai, marcusrbrown/awesome-unreal) surface in search but are outside managed scope and are excluded from the counts below.
❔ Unavailable source. Dependabot alerts returned 403 Resource not accessible by personal access token on 28 of 34 repositories. The PAT reads alerts only where fro-bot is the resource owner — all 6 fro-bot/* repos succeeded, every marcusrbrown/* and bfra-me/* repo failed. Org-wide security-alert posture is therefore unmeasured, not clean.
The headline: Fro Bot's own output is the largest stale surface in the fleet.
Of 57 PRs with no update in 14+ days, 43 are fro-bot-authored — 75%. Breakdown by repo:
The oldest are bfra-me/github-app#840 and bfra-me/github-action#1463, both fix(security), both 99 days old. Remediation throughput is not the constraint; merge throughput is. A security PR that sits for three months is not remediation — it is a coverage claim nobody cashed.
Next step: triage the two bfra-me/* security queues first (6 PRs, all one-line override changes). #3652 already exists for cross-repo PR-queue triage — reuse it rather than opening anything new.
Other detections.
Top three hotspots (ranked by qualifying findings in this snapshot — stale issues + aging PRs + stale PRs + unassigned bugs + red default branch):
- marcusrbrown/gpt — 49. 19 stale issues, 15 stale PRs, 12 of them Fro-Bot-authored. The HeroUI migration tree (#2162 and 8 children) has been frozen since March. Next step: decide the HeroUI migration's fate — close the tree or schedule it. Everything else in this repo is downstream of that decision.
- marcusrbrown/vbs — 33. 15 stale issues, 8 stale Fro-Bot PRs including 4
fix(security) aged 44–73 days. Next step: merge or close the security four; they are already catalogued in the wiki as a coverage-inflation case.
- marcusrbrown/marcusrbrown.com — 18. 6 stale Fro-Bot PRs, 2 unassigned a11y bugs, and a red
Fro Bot context on main. Next step: fix the red agent job first — it is why nothing here self-heals.
Gateway rollout tracker (category 8 — review awareness only, no tracker writes).
#3512 has drifted materially from both GitHub Project 1 and live state. Both values, in every case:
| Claim in #3512 |
Live value |
| Project item status implied by the body (verification-only tail remaining) |
Project 1 item for #3512 is Todo |
"Agent releases have since advanced to v0.85.0" |
fro-bot/agent latest release is v0.114.0 (2026-09-21) |
"the deployed pin is v0.83.0" |
marcusrbrown/infra apps/gateway/upstream.json → v0.113.2 |
"Operator push … released in v0.85.0 but not yet deployed" |
The pin is 29 minors past v0.85.0; the premise no longer holds |
"Cancel UI (fro-bot/dashboard#179) — Open" |
dashboard#179 is CLOSED (2026-07-11) |
"One low-severity nit filed: /api/status lacks no-store (fro-bot/dashboard#125)" |
dashboard#125 is CLOSED |
"residual node_id-format gap is tracked at fro-bot/.github#3525" |
#3525 is CLOSED |
"there is no dedicated GitHub App key revocation runbook (marcusrbrown/infra#711)" |
infra#711 is CLOSED |
| Acceptance criterion: "The Project matrix is current and reflects all shipped/closed rollout items" |
Unmet. Project 1 holds 21 items; agent#1033, #1109, #1111, the six push PRs, dashboard#108, #122, and #179 — all named in #3512's own dependency matrix — have no Project item. |
One claim holds: dashboard.fro.bot/operator/health still returns {"ok":true,"contractVersion":"1.6.0"}, so the contract-match gate is genuinely satisfied on both sides.
New live evidence the tracker does not reflect: marcusrbrown/infra#1412 (opened today) reports the gateway deploy parked at the gateway environment's required-reviewer gate since 2026-09-21T20:02Z (run 35648619590), so the running gateway predates infra#1405. The tracker's deploy narrative assumes deploys complete or fail; "waiting on a human" is a third state it does not model.
No tracker comment posted and no Project field edited from this path — the Gateway Rollout Tracker workflow owns those writes.
Cross-Project Intelligence
Coverage: partial — 29 of 34 metadata/repos.yaml entries scanned. Read from origin/data, the authoritative copy.
| Bucket |
Count |
Detail |
Scanned (onboarded, survey succeeded) |
29 |
Wiki pages current |
| Last survey failed |
2 |
marcusrbrown/containers, marcusrbrown/dev-like — both last_survey_status: failure dated 2026-09-12 (10 days, neither retried) |
| Never surveyed |
3 |
onboarding_status: pending, private by classification. Counted only; not named, not described — the public-only invariant is the whole point of this pipeline. |
lost-access |
1 |
marcusrbrown/copiloting, archived, last survey 2026-04-23 |
Ledger gap. The token holds write access to bfra-me/github-action, bfra-me/github-app, and bfra-me/renovate-config, none of which appear in metadata/repos.yaml at all. They carry nine open Fro-Bot PRs between them, six of which are the 98–99-day fix(security) set above. Fro Bot writes into repositories it does not track — so they get no survey, contribute nothing to this category, and are invisible to every metadata-driven loop while remaining fully reachable by the write-tier PAT. Reconcile derives the ledger from collaborator invitations; access acquired any other way never enters it. Persisted to the wiki this run.
Adoptable findings (report-only, no changes made).
- Capability-split agent jobs, from
marcusrbrown/infra. That repo's fro-bot.yaml is split into two jobs with disjoint capabilities: fro-bot-content (content-triggered, contents: read + pull-requests: read, no environment) and fro-bot-storage (schedule/main-dispatch only, environment-gated, OIDC, harden-runner egress-policy: block). This repo's fro-bot.yaml has three jobs — fro-bot (content-triggered), fro-bot-remediate, fro-bot-observe — and all three pass secrets.FRO_BOT_PAT to the agent. There are no job-level permissions: blocks; the workflow-level permissions: contents: read is inert, because the agent authenticates with the PAT, not GITHUB_TOKEN. The file's own comment at line 83 states the stakes plainly: "FRO_BOT_PAT carries cross-repo write-tier authority for the agent." So the attacker-reachable job (any OWNER/MEMBER/COLLABORATOR issue or PR event) holds exactly the same cross-repo write authority as the scheduled autoheal. The infra split is the shape that fixes it. Not a one-line change, and not in scope for a report-only category — recorded here for a deliberate decision.
- Pin/comment agreement as a lint, corroborated across two repos today.
marcusrbrown/marcusrbrown.github.io#431 was opened this morning for exactly this class: actions/configure-pages pinned to a full SHA but commented # v5 instead of # vX.Y.Z. This repo passes 20/20 today, but nothing here verifies it — Check Workflows runs actionlint, which validates syntax, not pin/comment agreement. Independent evidence in a sibling repo the same day moves this from "preventive" to "recurring class." Detail in Needs Human Attention 4.
- Out-of-band health monitoring with a synthetic self-test (
marcusrbrown/infra's cliproxy-auth-monitor.yaml) and the workflow_run failure alarm (release-alert.yaml) both remain unadopted here. The latter was already recorded in #3910; this run adds why the former shape matters too — see Needs Human Attention 1, where the problem is a starved publisher rather than a failing job, and a run alarm would not catch it.
Progressive Improvement
Compounding pipeline: stalled. 10 open learning-proposal issues — #3887–#3891 (8 days) and #3905–#3909 (1 day). None exceeds 14 days individually, but the threshold that matters is "two or more open at once," and there are ten.
The decisive number is on the other side: the last commit authoring proposals into docs/solutions/ was #3868 — "compound five queued learning proposals" — on 2026-09-07, 15 days ago. The loop produces five per week and consumes five roughly every two; two full batches are now queued behind a step that has not run. docs/solutions/ holds 59 entries and has not grown since 2026-09-08.
Per the standing instruction: the healthy reading on Improvement Metrics #3674 is not evidence this is fine. Unauthored proposals never become codified classes, so that report stays green precisely while this is stalled. It is measuring the output of a pipeline whose input queue is the thing backing up.
Tool-version drift: none unmanaged. Current-version truth from the npm registry latest dist-tag (registry.npmjs.org), cross-checked against the Dependency Dashboard. Major drift was included in the comparison — and both majors turn out to be deliberate:
| Tool |
Pinned |
Registry latest |
Read |
typescript |
6.0.3 |
7.0.2 |
Not drift. .github/renovate.json5 holds allowedVersions: '<6.1.0' to mirror typescript-eslint's peer ceiling. Verified live today: @typescript-eslint/parser@8.70.1 still peers typescript >=4.8.4 <6.1.0. The hold and its comment are both still accurate. |
vitest / @vitest/coverage-v8 |
4.1.11 / 4.1.4 |
5.0.1 |
Not drift. renovate/major-vitest-monorepo sits under Pending Approval on the dashboard — gated on a human checkbox, not missed. |
pnpm |
11.25.0 |
12.5.0 |
v11.27.0 open as #3882; v12 pending approval. |
eslint |
10.10.0 |
10.11.0 |
Open as #3912. |
prettier |
3.9.1 |
3.9.8 |
7 patches, same minor — inside tolerance. |
@stryker-mutator/core |
10.0.0 |
10.0.0 |
Current. |
One minor internal skew worth a glance: @vitest/coverage-v8 is pinned at 4.1.4 while vitest is at 4.1.11 — same minor, but they should move together.
Stale TODO/FIXME: none. Two grep hits, both false positives — a fixture string in scripts/check-private-leak.test.ts:219 and the literal word inside this prompt's own text at .github/workflows/fro-bot.yaml:382.
Convention drift from copilot-instructions.md: none detected. pnpm-only contract intact, shared setup action used by all 18 dependency-consuming workflows, no any/@ts-ignore introduced, verification commands all green.
Plan consistency: one active plan with open units — docs/plans/2026-08-29-001-feat-editable-wiki-path-plan.md at 5/10. Correctly labelled; no status-truth drift. No active plan has all units checked.
Needs Human Attention
1. Merge Data Branch is blocked, and the blast radius now includes the public wiki site.
Merge Data Branch last succeeded 2026-09-06 and has failed the privacy gate on 2026-09-13 and 2026-09-20 (two consecutive Sundays — correcting the "three consecutive Sundays" figure in commit comment 201424711, which overstated it). Run 35545734311 failed at 🔒 Block private wiki pages: check-wiki-private-presence.ts reported BLOCKED — unattributable wiki repo pages detected, leak count 1, reason unattributable-page. Identifiers are redacted in the public log and stay redacted here.
The gate is correct. It is not a bug and must not be weakened. What is new today is the downstream cost:
origin/main..origin/data is now 72 commits, oldest 2026-09-06, newest 2026-09-21 — against 67 at yesterday's reading and 47 on 09-17. It grows ~5/day.
Publish Wiki triggers on push to main filtered to knowledge/wiki/**. Wiki content only reaches main via promotion. So Publish Wiki has not run since 2026-09-06, and its five most recent runs are all success. The public site at fro-bot.github.io/.github has served 16-day-old content with every health signal green.
That second point is the part no instrument covers. A workflow_run failure alarm catches the gate failing; it does not catch a publisher that correctly never fired.
- Files:
knowledge/wiki/repos/ and metadata/repos.yaml on the data branch (not main); scripts/check-wiki-private-presence.ts for gate logic; .github/workflows/publish-wiki.yaml for the starved trigger.
- Root cause: a
wiki/repos/ page on data whose slug does not resolve to a public repo via metadata/repos.yaml → computeRepoSlug, and which is not grandfathered. Per the 2026-09-21 wiki entry, three subclasses are live at once, including one row carrying onboarding_status: lost-access with no private key whose repo is currently enumerable as public — so a one-field re-resolution to private: false on data is likely the smallest fix, not a page deletion.
- Do not: weaken the gate, add a slug allowlist, wire
--operator-report into a workflow, delete repos.yaml rows for the lost-access subclass (that converts a one-field repair into a fresh orphan), or re-dispatch expecting a different answer.
- Why no CI agent can fix it: remediation requires writing
knowledge/wiki/** or metadata/repos.yaml on data, and the gate's only diagnostic (--operator-report) hard-refuses to run when GITHUB_ACTIONS or CI=true is set — correctly, since its output is the private data.
- Verify:
Merge Data Branch green → git rev-list --count origin/main..origin/data returns 0 → Publish Wiki fires on the resulting push → the deployed site's commit SHA matches the data wiki tip.
2. Two surveys failed ten days ago and nothing retried them.
marcusrbrown/containers and marcusrbrown/dev-like both carry last_survey_status: failure dated 2026-09-12 in metadata/repos.yaml on data. Their next_survey_eligible_at values sit in October, so the normal cadence will not revisit either for weeks — a failed survey is scheduled exactly like a successful one. Both repos' wiki pages are therefore frozen at their last successful ingest, and marcusrbrown/containers is additionally red on main.
- Files:
metadata/repos.yaml on data; scripts/reconcile-repos.ts / .github/workflows/reconcile-repos.yaml for the cadence rule.
- Smallest safe fix: re-dispatch both surveys by hand —
gh workflow run survey-repo.yaml -f node_id=<node_id>, node ids in metadata/repos.yaml on data — and read the run logs for the actual failure before changing any cadence logic.
- Do not shorten
next_survey_eligible_at globally to work around this; the durable question is whether a failure outcome should get a shorter retry interval than a success, and that is a reviewed change to the cadence rule, not a data edit.
- Verify: both entries flip to
last_survey_status: success with a 2026-09-22-or-later last_survey_at.
3. Scorecard's BranchProtectionID high — leave it alone.
"required approving review count is 1 on branch main." Branch protection is off-limits by hard boundary, and it should stay off-limits by judgment: raising the bar to 2 on a single-operator repository would deadlock the data → main promotion path that item 1 is already stuck behind. If the Scorecard number needs to move, the honest lever is a second reviewer, not a config change.
4. Nothing verifies that a pinned action SHA matches its version comment.
All 20 pins in this repo agree today, so this is preventive here — but marcusrbrown/marcusrbrown.github.io#431, filed this morning, is a live instance of the same class in a sibling repo. The failure mode is quiet: an immutable SHA pin never breaks when its comment goes stale, it just lies. Readers and agents reason about the version in the comment and are wrong, and nothing turns red. Check Workflows runs actionlint, which validates syntax and action shape, not pin/comment agreement.
- Files: new
scripts/check-action-pins.ts + colocated scripts/check-action-pins.test.ts; wire into the pnpm lint chain in package.json alongside check-md-links / check-override-floors / check-solutions-examples.
- Smallest safe fix: parse every
uses: <ref>@<sha> # v<x.y.z> in .github/workflows/*.yaml and .github/actions/**/action.yaml, resolve repos/{owner}/{repo}/git/ref/tags/{tag}, dereference annotated tag objects to their target commit, exit non-zero on mismatch naming the offending ref.
- Constraints: strip-only TypeScript (no
enum, no parameter properties); mock @octokit/rest with vi.hoisted() + vi.mock() per this repo's convention; the network call needs a graceful unauthenticated/rate-limited path so it degrades to a skip rather than a false failure.
- Verify:
pnpm lint passes as-is (all 20 refs agree right now), then flip one version comment by a patch and confirm it fails naming that ref.
5. The learning-authoring step has no owner and no alarm.
Ten proposals queued, last authoring commit 15 days ago (item covered under Progressive Improvement). Capture Learnings reliably opens proposals on schedule; nothing closes the loop by writing them into docs/solutions/. The gap is structural, not a backlog: there is no scheduled job, no staleness check, and no report that goes red when the queue grows. Improvement Metrics #3674 reads healthy throughout, because unauthored proposals never become classes it can measure.
- Smallest useful fix is a measurement, not an automation: add an open-
learning-proposal count-and-age assertion to whatever surface an operator actually reads, so the stall is visible without waiting for a human to notice ten open issues.
- Do not auto-author the proposals. The existing design deliberately keeps a human between a proposal and a committed learning; the problem is that the human gets no signal, not that the human is in the loop.
- Verify: the count drops below 2, or the surface reporting it goes red while it does not.
6. Fro Bot writes into three repositories it does not track.
bfra-me/github-action, bfra-me/github-app, and bfra-me/renovate-config are write-accessible and absent from metadata/repos.yaml. Nine open Fro-Bot PRs live there, six of them fix(security) aged 98–99 days — the oldest unmerged output in the fleet, in the repos least visible to the loops that would notice. Detail under Cross-Project Intelligence; persisted to the wiki this run.
- Smallest safe fix: add the three entries to
metadata/repos.yaml on data, through the established metadata scripts — never from a main PR, which Check Wiki Authority rejects. That alone makes them surveyable and visible to cadence.
- Constraint: do not widen reconcile's discovery to "any writable repo." The ledger should stay an explicit list; the defect is that three known repos are missing from it, not that the derivation rule is too narrow.
- Verify: each appears with
onboarding_status: onboarded and a successful survey, and a wiki page exists for each.
Persisted to the wiki this run: two new sections in knowledge/wiki/topics/github-actions-ci.md (starved event-triggered publisher; write reach exceeding tracked scope), with knowledge/index.md and knowledge/log.md updated. No metadata/** file was written.
Daily Fro Bot Report — 2026-09-22 (UTC)
Run Summary
permissions:. Live branch protection matches.github/settings.ymlexactly.bootstrap/check-types/lint/testall pass at9b9635b. 3687 tests, 79 files.lost-access. 3 accessible write-tier repos are absent from the ledger entirely.learning-proposalissues, last authoring commit 2026-09-07 (15 days). No unmanaged tool drift — the two apparent majors are both deliberate holds.Errored PRs
None. The remediation pass ran categories 1–4 in
branch-prmode ahead of this job and opened zero PRs, pushed zero branches, and made zero commits. Its findings are recorded on commit comment 201424711.All five open PRs were verified green against both signal sources:
app/fro-botrenovate/stability-days,Security: Private Leak Scanapp/fro-botSecurity: Private Leak Scanapp/fro-botSecurity: Private Leak Scanfro-botSecurity: Private Leak Scanapp/fro-botrenovate/stability-days,Security: Private Leak ScanSecurity: Private Leak Scanandrenovate/stability-daysnever appear in/check-runs— they are commit statuses. Anything reading onlygh pr checksis blind to both.Security
Advisory data was available to the token for this repository. No guessing.
GHSA-p498-v437-472g,npm/@humanfs/node, medium,developmentscope, transitive viapnpm-lock.yaml. Below the critical/high remediation bar and squarely Renovate's lane. It appears on the Dependency Dashboard as part of the eslint chain.VulnerabilitiesID(high — re-reporting the advisory above),BranchProtectionID(high — see Needs Human Attention 3),FuzzingID(medium),CIIBestPracticesID(low).Zero remediation PRs opened, which is the correct outcome for this input.
Control-Plane Integrity
Verified clean on all four sub-checks.
.github/workflows/*.yamland.github/actions/**/action.yaml. Zero floating tags, zero missing version comments — and the remediation pass went past the usual check, dereferencingrepos/{owner}/{repo}/git/ref/tags/{tag}(following annotated tag objects to their target commit) to confirm each pin actually resolves to the tag its comment claims. Current-version truth came from the GitHub git-ref API on each action's own repository. 20/20 agree. No version bumps were included, so no major-drift decision arose — Renovate owns that.enum,namespace/module,import x =aliases, or constructor parameter properties inscripts/*.ts. The one grep hit is a comment atscripts/repos-metadata.ts:476explaining the constraint.permissions:. The only broad grant ispermissions: read-allinscorecard.yaml— the upstream OpenSSF template shape, read-only. 18 workflows route through./.github/actions/setup; no workflow installs dependencies outside it.mainmatches.github/settings.ymlexactly: same 14 required contexts,strict: true,enforce_admins: true, linear history. Nothing weakened. One guard is actively holding the line — see Needs Human Attention 1.Code Quality
pnpm bootstrap,pnpm check-types,pnpm lint,pnpm testall pass atmain9b9635b. 79 test files, 3687 passing, 3 todo, 21.7s. No mechanical autofix available, so nothing to commit.Workflow health across all 29 workflows: one failure —
Merge Data Branch(see below). Everything else green or explicably idle (Unpublish Wikinever run by design;Capture Patternsmanual-first;Reset Survey Statusmanual-only;Copilot Setup Stepspath-filtered).Oversight
Scope. 38 repositories enumerated via paginated
user/reposwithaffiliation=owner,collaborator,organization_member; 34 non-archived, all public, all write-tier.user/orgsreturned empty, sobfra-me/*reaches the account through collaborator affiliation rather than org membership — worth knowing, because an org-scoped enumeration would have returned nothing at all. Public repos outside that affiliation set (e.g.marcusrbrown/panthe.ai,marcusrbrown/awesome-unreal) surface in search but are outside managed scope and are excluded from the counts below.❔ Unavailable source. Dependabot alerts returned
403 Resource not accessible by personal access tokenon 28 of 34 repositories. The PAT reads alerts only wherefro-botis the resource owner — all 6fro-bot/*repos succeeded, everymarcusrbrown/*andbfra-me/*repo failed. Org-wide security-alert posture is therefore unmeasured, not clean.The headline: Fro Bot's own output is the largest stale surface in the fleet.
Of 57 PRs with no update in 14+ days, 43 are
fro-bot-authored — 75%. Breakdown by repo:The oldest are
bfra-me/github-app#840andbfra-me/github-action#1463, bothfix(security), both 99 days old. Remediation throughput is not the constraint; merge throughput is. A security PR that sits for three months is not remediation — it is a coverage claim nobody cashed.Next step: triage the two
bfra-me/*security queues first (6 PRs, all one-line override changes). #3652 already exists for cross-repo PR-queue triage — reuse it rather than opening anything new.Other detections.
main@47e32358—Renovate / Renovate×2main@6ae965f7—Renovate / Renovatemarcusrbrown/main@99fdbe90—Fro Botmain@9328e620—Pre-Release Validation (vulnerabilities)main@3777c3ea—Fro BotFro Botcontexts are the agent failing on its own repos — check those before anything else, since a broken agent job is a broken detector.fro-bot/agent#1636–#1639,#1642(5 operator/gateway issues frommarcusrbrown) andmarcusrbrown/tokentoilet#1517–#1520(mainnet enablement).marcusrbrown/systematic#1005,bfra-me/ha-addon-repository#569,marcusrbrown/marcusrbrown.com#517,marcusrbrown/systematic#740,marcusrbrown/marcusrbrown.com#465. Next step: assign or close the twomarcusrbrown.coma11y bugs (44 and 76 days old, both small).Top three hotspots (ranked by qualifying findings in this snapshot — stale issues + aging PRs + stale PRs + unassigned bugs + red default branch):
fix(security)aged 44–73 days. Next step: merge or close the security four; they are already catalogued in the wiki as a coverage-inflation case.Fro Botcontext onmain. Next step: fix the red agent job first — it is why nothing here self-heals.Gateway rollout tracker (category 8 — review awareness only, no tracker writes).
#3512 has drifted materially from both GitHub Project 1 and live state. Both values, in every case:
Todov0.85.0"fro-bot/agentlatest release isv0.114.0(2026-09-21)v0.83.0"marcusrbrown/infraapps/gateway/upstream.json→v0.113.2v0.85.0but not yet deployed"v0.85.0; the premise no longer holdsfro-bot/dashboard#179) — Open"dashboard#179is CLOSED (2026-07-11)/api/statuslacksno-store(fro-bot/dashboard#125)"dashboard#125is CLOSEDfro-bot/.github#3525"marcusrbrown/infra#711)"infra#711is CLOSEDagent#1033,#1109,#1111, the six push PRs,dashboard#108,#122, and#179— all named in #3512's own dependency matrix — have no Project item.One claim holds:
dashboard.fro.bot/operator/healthstill returns{"ok":true,"contractVersion":"1.6.0"}, so the contract-match gate is genuinely satisfied on both sides.New live evidence the tracker does not reflect:
marcusrbrown/infra#1412(opened today) reports the gateway deploy parked at thegatewayenvironment's required-reviewer gate since 2026-09-21T20:02Z (run35648619590), so the running gateway predatesinfra#1405. The tracker's deploy narrative assumes deploys complete or fail; "waiting on a human" is a third state it does not model.No tracker comment posted and no Project field edited from this path — the Gateway Rollout Tracker workflow owns those writes.
Cross-Project Intelligence
Coverage: partial — 29 of 34
metadata/repos.yamlentries scanned. Read fromorigin/data, the authoritative copy.onboarded, survey succeeded)marcusrbrown/containers,marcusrbrown/dev-like— bothlast_survey_status: failuredated 2026-09-12 (10 days, neither retried)onboarding_status: pending, private by classification. Counted only; not named, not described — the public-only invariant is the whole point of this pipeline.lost-accessmarcusrbrown/copiloting, archived, last survey 2026-04-23Ledger gap. The token holds write access to
bfra-me/github-action,bfra-me/github-app, andbfra-me/renovate-config, none of which appear inmetadata/repos.yamlat all. They carry nine open Fro-Bot PRs between them, six of which are the 98–99-dayfix(security)set above. Fro Bot writes into repositories it does not track — so they get no survey, contribute nothing to this category, and are invisible to every metadata-driven loop while remaining fully reachable by the write-tier PAT. Reconcile derives the ledger from collaborator invitations; access acquired any other way never enters it. Persisted to the wiki this run.Adoptable findings (report-only, no changes made).
marcusrbrown/infra. That repo'sfro-bot.yamlis split into two jobs with disjoint capabilities:fro-bot-content(content-triggered,contents: read+pull-requests: read, no environment) andfro-bot-storage(schedule/main-dispatch only, environment-gated, OIDC,harden-runner egress-policy: block). This repo'sfro-bot.yamlhas three jobs —fro-bot(content-triggered),fro-bot-remediate,fro-bot-observe— and all three passsecrets.FRO_BOT_PATto the agent. There are no job-levelpermissions:blocks; the workflow-levelpermissions: contents: readis inert, because the agent authenticates with the PAT, notGITHUB_TOKEN. The file's own comment at line 83 states the stakes plainly: "FRO_BOT_PAT carries cross-repo write-tier authority for the agent." So the attacker-reachable job (any OWNER/MEMBER/COLLABORATOR issue or PR event) holds exactly the same cross-repo write authority as the scheduled autoheal. The infra split is the shape that fixes it. Not a one-line change, and not in scope for a report-only category — recorded here for a deliberate decision.marcusrbrown/marcusrbrown.github.io#431was opened this morning for exactly this class:actions/configure-pagespinned to a full SHA but commented# v5instead of# vX.Y.Z. This repo passes 20/20 today, but nothing here verifies it —Check Workflowsruns actionlint, which validates syntax, not pin/comment agreement. Independent evidence in a sibling repo the same day moves this from "preventive" to "recurring class." Detail in Needs Human Attention 4.marcusrbrown/infra'scliproxy-auth-monitor.yaml) and theworkflow_runfailure alarm (release-alert.yaml) both remain unadopted here. The latter was already recorded in #3910; this run adds why the former shape matters too — see Needs Human Attention 1, where the problem is a starved publisher rather than a failing job, and a run alarm would not catch it.Progressive Improvement
Compounding pipeline: stalled. 10 open
learning-proposalissues — #3887–#3891 (8 days) and #3905–#3909 (1 day). None exceeds 14 days individually, but the threshold that matters is "two or more open at once," and there are ten.The decisive number is on the other side: the last commit authoring proposals into
docs/solutions/was #3868 — "compound five queued learning proposals" — on 2026-09-07, 15 days ago. The loop produces five per week and consumes five roughly every two; two full batches are now queued behind a step that has not run.docs/solutions/holds 59 entries and has not grown since 2026-09-08.Per the standing instruction: the
healthyreading on Improvement Metrics #3674 is not evidence this is fine. Unauthored proposals never become codified classes, so that report stays green precisely while this is stalled. It is measuring the output of a pipeline whose input queue is the thing backing up.Tool-version drift: none unmanaged. Current-version truth from the npm registry
latestdist-tag (registry.npmjs.org), cross-checked against the Dependency Dashboard. Major drift was included in the comparison — and both majors turn out to be deliberate:latesttypescript.github/renovate.json5holdsallowedVersions: '<6.1.0'to mirror typescript-eslint's peer ceiling. Verified live today:@typescript-eslint/parser@8.70.1still peerstypescript >=4.8.4 <6.1.0. The hold and its comment are both still accurate.vitest/@vitest/coverage-v8renovate/major-vitest-monoreposits under Pending Approval on the dashboard — gated on a human checkbox, not missed.pnpmeslintprettier@stryker-mutator/coreOne minor internal skew worth a glance:
@vitest/coverage-v8is pinned at4.1.4whilevitestis at4.1.11— same minor, but they should move together.Stale TODO/FIXME: none. Two grep hits, both false positives — a fixture string in
scripts/check-private-leak.test.ts:219and the literal word inside this prompt's own text at.github/workflows/fro-bot.yaml:382.Convention drift from
copilot-instructions.md: none detected. pnpm-only contract intact, shared setup action used by all 18 dependency-consuming workflows, noany/@ts-ignoreintroduced, verification commands all green.Plan consistency: one
activeplan with open units —docs/plans/2026-08-29-001-feat-editable-wiki-path-plan.mdat 5/10. Correctly labelled; no status-truth drift. Noactiveplan has all units checked.Needs Human Attention
1.
Merge Data Branchis blocked, and the blast radius now includes the public wiki site.Merge Data Branchlast succeeded 2026-09-06 and has failed the privacy gate on 2026-09-13 and 2026-09-20 (two consecutive Sundays — correcting the "three consecutive Sundays" figure in commit comment 201424711, which overstated it). Run 35545734311 failed at🔒 Block private wiki pages:check-wiki-private-presence.tsreportedBLOCKED — unattributable wiki repo pages detected, leak count 1, reasonunattributable-page. Identifiers are redacted in the public log and stay redacted here.The gate is correct. It is not a bug and must not be weakened. What is new today is the downstream cost:
origin/main..origin/datais now 72 commits, oldest 2026-09-06, newest 2026-09-21 — against 67 at yesterday's reading and 47 on 09-17. It grows ~5/day.Publish Wikitriggers onpushtomainfiltered toknowledge/wiki/**. Wiki content only reachesmainvia promotion. SoPublish Wikihas not run since 2026-09-06, and its five most recent runs are allsuccess. The public site atfro-bot.github.io/.githubhas served 16-day-old content with every health signal green.That second point is the part no instrument covers. A
workflow_runfailure alarm catches the gate failing; it does not catch a publisher that correctly never fired.knowledge/wiki/repos/andmetadata/repos.yamlon thedatabranch (notmain);scripts/check-wiki-private-presence.tsfor gate logic;.github/workflows/publish-wiki.yamlfor the starved trigger.wiki/repos/page ondatawhose slug does not resolve to a public repo viametadata/repos.yaml→computeRepoSlug, and which is not grandfathered. Per the 2026-09-21 wiki entry, three subclasses are live at once, including one row carryingonboarding_status: lost-accesswith noprivatekey whose repo is currently enumerable as public — so a one-field re-resolution toprivate: falseondatais likely the smallest fix, not a page deletion.--operator-reportinto a workflow, deleterepos.yamlrows for thelost-accesssubclass (that converts a one-field repair into a fresh orphan), or re-dispatch expecting a different answer.knowledge/wiki/**ormetadata/repos.yamlondata, and the gate's only diagnostic (--operator-report) hard-refuses to run whenGITHUB_ACTIONSorCI=trueis set — correctly, since its output is the private data.Merge Data Branchgreen →git rev-list --count origin/main..origin/datareturns 0 →Publish Wikifires on the resulting push → the deployed site's commit SHA matches thedatawiki tip.2. Two surveys failed ten days ago and nothing retried them.
marcusrbrown/containersandmarcusrbrown/dev-likeboth carrylast_survey_status: failuredated 2026-09-12 inmetadata/repos.yamlondata. Theirnext_survey_eligible_atvalues sit in October, so the normal cadence will not revisit either for weeks — a failed survey is scheduled exactly like a successful one. Both repos' wiki pages are therefore frozen at their last successful ingest, andmarcusrbrown/containersis additionally red onmain.metadata/repos.yamlondata;scripts/reconcile-repos.ts/.github/workflows/reconcile-repos.yamlfor the cadence rule.gh workflow run survey-repo.yaml -f node_id=<node_id>, node ids inmetadata/repos.yamlondata— and read the run logs for the actual failure before changing any cadence logic.next_survey_eligible_atglobally to work around this; the durable question is whether afailureoutcome should get a shorter retry interval than asuccess, and that is a reviewed change to the cadence rule, not a data edit.last_survey_status: successwith a 2026-09-22-or-laterlast_survey_at.3. Scorecard's
BranchProtectionIDhigh — leave it alone."required approving review count is 1 on branch
main." Branch protection is off-limits by hard boundary, and it should stay off-limits by judgment: raising the bar to 2 on a single-operator repository would deadlock thedata → mainpromotion path that item 1 is already stuck behind. If the Scorecard number needs to move, the honest lever is a second reviewer, not a config change.4. Nothing verifies that a pinned action SHA matches its version comment.
All 20 pins in this repo agree today, so this is preventive here — but
marcusrbrown/marcusrbrown.github.io#431, filed this morning, is a live instance of the same class in a sibling repo. The failure mode is quiet: an immutable SHA pin never breaks when its comment goes stale, it just lies. Readers and agents reason about the version in the comment and are wrong, and nothing turns red.Check Workflowsruns actionlint, which validates syntax and action shape, not pin/comment agreement.scripts/check-action-pins.ts+ colocatedscripts/check-action-pins.test.ts; wire into thepnpm lintchain inpackage.jsonalongsidecheck-md-links/check-override-floors/check-solutions-examples.uses: <ref>@<sha> # v<x.y.z>in.github/workflows/*.yamland.github/actions/**/action.yaml, resolverepos/{owner}/{repo}/git/ref/tags/{tag}, dereference annotated tag objects to their target commit, exit non-zero on mismatch naming the offending ref.enum, no parameter properties); mock@octokit/restwithvi.hoisted()+vi.mock()per this repo's convention; the network call needs a graceful unauthenticated/rate-limited path so it degrades to a skip rather than a false failure.pnpm lintpasses as-is (all 20 refs agree right now), then flip one version comment by a patch and confirm it fails naming that ref.5. The learning-authoring step has no owner and no alarm.
Ten proposals queued, last authoring commit 15 days ago (item covered under Progressive Improvement).
Capture Learningsreliably opens proposals on schedule; nothing closes the loop by writing them intodocs/solutions/. The gap is structural, not a backlog: there is no scheduled job, no staleness check, and no report that goes red when the queue grows. Improvement Metrics #3674 readshealthythroughout, because unauthored proposals never become classes it can measure.learning-proposalcount-and-age assertion to whatever surface an operator actually reads, so the stall is visible without waiting for a human to notice ten open issues.6. Fro Bot writes into three repositories it does not track.
bfra-me/github-action,bfra-me/github-app, andbfra-me/renovate-configare write-accessible and absent frommetadata/repos.yaml. Nine open Fro-Bot PRs live there, six of themfix(security)aged 98–99 days — the oldest unmerged output in the fleet, in the repos least visible to the loops that would notice. Detail under Cross-Project Intelligence; persisted to the wiki this run.metadata/repos.yamlondata, through the established metadata scripts — never from amainPR, whichCheck Wiki Authorityrejects. That alone makes them surveyable and visible to cadence.onboarding_status: onboardedand a successful survey, and a wiki page exists for each.Persisted to the wiki this run: two new sections in
knowledge/wiki/topics/github-actions-ci.md(starved event-triggered publisher; write reach exceeding tracked scope), withknowledge/index.mdandknowledge/log.mdupdated. Nometadata/**file was written.