feat(directie): a signals script that says what is red, without a model - #330
Merged
Conversation
scripts/directie/signalen.py asks a fixed list of questions to GitHub via gh and to production via curl, and turns each answer into a severity, a measurement and a one-sentence proposal. JSON on stdout, readable text with --tekst, exit 1 when anything is red, so cron or a later round can steer on the exit code. It measures: every open pull request with its check status and age in hours; open dependabot pull requests as one signal with the age of the oldest; failed workflow runs of the last 24 hours, red only when main is hit; the last outcome of the three canaries with a timestamp, found by name in .github/workflows rather than hardcoded, so a canary that moves to its own workflow keeps being measured and one that disappears turns orange instead of quietly green; the status code of /health and the response time of the homepage; and the six ParaID deny entries, where POST with an empty body to /v1/paraid/issue-document must answer 404 on every host. A signal that could not be measured is orange, never green. Thresholds sit as named constants at the top of the file so the argument about when something is red happens in one place. Python 3 standard library plus gh and curl, no other dependencies. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…runs Three points from review on the signals script. The canary window was too narrow. gh run list --workflow product-heartbeat.yml --limit 20 put the last schedule run at position 15 of 20 on a busy day, because the list is full of pull_request runs in which the canary steps are skipped. One more busy hour and a living canary would have been reported orange. It now asks for the schedule and workflow_dispatch runs first, which is where the live job runs at all, and only falls back to a wide net over all events when that yields nothing. Side effect: fewer job API calls, so a full run got faster rather than slower. docs/directie.md names the wortel field in the JSON section, and the run duration is now the measured 12 to 17 seconds over four runs instead of a round number, with what makes it grow. signaal_homepage had a dead branch: status >= 400 or status is None can never see None, because a failed measurement returns earlier on the fout field. The None check now comes first, where it can do its work. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Mick's two content requirements for /parasign, plus the rebase onto main. The free plan is called Community, because that is what it is: a give-back, not a trial and not a funnel. The card says so in the founder's own terms (Mick Beer, privacy and security researcher at Paramantis Solutions B.V., the wording about.html already carries) and bridges to /pricing, where the same plan is listed as the tier named Free. PR #328 introduces the same Community wording on the homepage; whichever lands first, the bridge keeps both pages honest. The paid tiers are presented as what they are: business plans that pay for the free one. Names and amounts are lifted from /pricing (Pro 49, Business 299, Enterprise on request, with the incl-btw checkout amounts), and relay/test/pricing-page.test.js already ties every one of them to relay/lib/billing-catalog.js. The technique moved to section 04, under the heading that says it is evidence and not a pitch. ML-DSA-65, FIPS 204 and SHA3-256 no longer appear in the title, the description, the H1 area or the opening paragraph; first occurrence in the rendered page is now at character 4633 of 1280px body text, well past the plans. The hero says what the reader gets, the proof section says how to check it. Three new gates in relay/test/pricing-page.test.js, deliberately in that file rather than in ui-truthfulness.test.mjs, which #328 is rewriting: - saying Community obliges the page to name the /pricing tier it maps to, and obliges /pricing to still carry a tier named Free - every tier name printed on /parasign must be a tier /pricing sells - the founder line may claim only what /about claims, and naming him obliges the page to name the company registration Rebased onto main (#324 navigation, #326 billing stance, #330 signals), no conflicts. frontend/apply-nav.py stamped the seven-item nav shell, the Company/Legal footer and the design-system versions onto the page; a second run produces no diff. bron-seo/apply_seo_head.py re-stamped the JSON-LD for the new title and description. bron-seo/build_sitemap.py said the sitemap was out of date and regenerated it: one line, the lastmod of /vault, which #324 touched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Apolloccrypt
added a commit
that referenced
this pull request
Sep 2, 2026
Mick's two content requirements for /parasign, plus the rebase onto main. The free plan is called Community, because that is what it is: a give-back, not a trial and not a funnel. The card says so in the founder's own terms (Mick Beer, privacy and security researcher at Paramantis Solutions B.V., the wording about.html already carries) and bridges to /pricing, where the same plan is listed as the tier named Free. PR #328 introduces the same Community wording on the homepage; whichever lands first, the bridge keeps both pages honest. The paid tiers are presented as what they are: business plans that pay for the free one. Names and amounts are lifted from /pricing (Pro 49, Business 299, Enterprise on request, with the incl-btw checkout amounts), and relay/test/pricing-page.test.js already ties every one of them to relay/lib/billing-catalog.js. The technique moved to section 04, under the heading that says it is evidence and not a pitch. ML-DSA-65, FIPS 204 and SHA3-256 no longer appear in the title, the description, the H1 area or the opening paragraph; first occurrence in the rendered page is now at character 4633 of 1280px body text, well past the plans. The hero says what the reader gets, the proof section says how to check it. Three new gates in relay/test/pricing-page.test.js, deliberately in that file rather than in ui-truthfulness.test.mjs, which #328 is rewriting: - saying Community obliges the page to name the /pricing tier it maps to, and obliges /pricing to still carry a tier named Free - every tier name printed on /parasign must be a tier /pricing sells - the founder line may claim only what /about claims, and naming him obliges the page to name the company registration Rebased onto main (#324 navigation, #326 billing stance, #330 signals), no conflicts. frontend/apply-nav.py stamped the seven-item nav shell, the Company/Legal footer and the design-system versions onto the page; a second run produces no diff. bron-seo/apply_seo_head.py re-stamped the JSON-LD for the new title and description. bron-seo/build_sitemap.py said the sitemap was out of date and regenerated it: one line, the lastmod of /vault, which #324 touched.
This was referenced Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Een meetscript zonder model dat in een oogopslag laat zien wat rood is.
scripts/directie/signalen.pystelt een vaste lijst vragen aan GitHub (viagh) en aan productie (viacurl), en geeft per vraag een ernst, een metingen een voorstel van een zin. JSON naar stdout, leesbare tekst met
--tekst,exitcode 1 als er iets rood is.
Wat het meet
workflows maar stappen in de live-job van
product-heartbeat.yml, dus hetscript zoekt ze op naam in
.github/workflows. Het kijkt daarbij eerst naarde
schedule- enworkflow_dispatch-runs, want alleen daar draait delive-job; een kale lijst van de laatste twintig runs bestaat op een drukke dag
bijna helemaal uit pull-request-runs waarin de kanariestappen zijn
overgeslagen. Levert dat niets op, dan volgt een breed net over alle events.
Verhuist een kanarie naar een eigen workflow, dan blijft dat werken.
Verdwijnt hij, dan wordt het signaal oranje in plaats van stil groen.
https://paramant.app/healthen de responstijd van de homepage.POSTmet lege JSON-body naar/v1/paraid/issue-documentmoet op alle zes de hosts 404 geven.Een signaal dat niet gemeten kon worden is oranje, nooit groen. De drempels
staan als constanten bovenaan het bestand.
Geen extra afhankelijkheden: Python 3 standaardbibliotheek plus
ghencurl.Een volledige run duurde hier 12 tot 17 seconden over vier runs, vrijwel
helemaal wachten op GitHub.
docs/directie.mdlegt uit wat elk signaal meet enwanneer het rood wordt.
Getest
python3 -m py_compile scripts/directie/signalen.py--reponaar een niet bestaande repo worden de GitHub-signalenoranje met "niet gemeten" in plaats van dat het script sterft.
/healthnaar een 404-pad gaat het signaal rood en eindigt hetscript met exitcode 1. In een eerdere run hier ving het script ook een echt
rood signaal:
sign-e2efaalde toen op PR Homepage speaks to a buyer: what it does, what it costs, why you can check it #328.Uitvoer van
python3 scripts/directie/signalen.py --tekst