ci(staleness): tolerate in-window reusable pins + wire deliberate bump path#397
Merged
Conversation
… path Stop the workflow-staleness gate being a treadmill. `standards` hosts reusable workflows that consumers pin by full SHA; the gate failed a consumer's CI whenever its pin != standards HEAD. Because HEAD moves often (observed live in stapeln: 5a93d9d -> d72fe5a -> 4ddc926 in ~30 min), every standards commit turned every consumer red until someone manually re-bumped the pins. Replace exact-HEAD equality in check-workflow-staleness.sh with a recency window, mirroring Hypatia HYP-S006 (registry-staleness, which tolerates drift for stale_after_days before escalating). A pin passes when it is a genuine ancestor of HEAD within the window: <= 50 commits behind OR <= 14 days old (both overridable via STALENESS_WINDOW_COMMITS / STALENESS_WINDOW_DAYS). It still fails when out of window (pins can't rot; known-bad historical pins stay blocked) or when not a real standards commit (forged/fork SHAs rejected — supply-chain integrity). In-window-but-behind pins emit a non-failing nudge. governance-reusable.yml now clones standards with --filter=tree:0 (full commit graph, minimal data) so the gate can do ancestry/age math. Wire the deliberate-bump half (the sha_bump_propagation path) as scripts/propagate-workflow-pins.sh: an audit-first helper that rewrites a consumer's standards pins to a target SHA and stages them on a branch, never committing/pushing (mirrors propagate-gitignore-67-68.sh). This is the concrete standards-side action the Hypatia sha_bump_propagation rule routes to; the gate no longer forces the bump. Verified end-to-end against real standards history with a stapeln-shaped consumer: a pin 3 commits behind HEAD passes the relaxed gate (with a nudge), while an out-of-window pin and a forged SHA both still fail. Hermetic regression suites added for both scripts (12 + 11 cases). Docs: docs/decisions/ADR-003-workflow-pin-staleness-window.adoc records the decision and the rejected alternatives (auto-PR-only; mutable @vn tag). Justfile gains staleness-check / staleness-propagate / staleness-test recipes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP
Replace the `eval "$2"` assertion helper in propagate-workflow-pins-test.sh with an eval-free `try CMD [ARGS...]` runner plus small predicate helpers (contains / file_has / staged_has / ...). Behaviour and coverage unchanged (11/11). Avoids contributing a code-injection-shaped pattern to the estate's Hypatia finding set; eval-on-a-variable is a textbook scanner trigger. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP
…epo half Make the workflow-pin staleness work discoverable from the human and machine front doors, and capture the deferred cross-repo automation in-repo so it is not lost at session close: - README.adoc (human) + 0-AI-MANIFEST.a2ml (machine): extend the drift/staleness row to point at ADR-003, check-workflow-staleness.sh, and propagate-workflow-pins.sh. - docs/FUTURE-WORK.adoc: park item #16 — the cross-repo half (activate hypatia sha_bump_propagation; wire gitbot-fleet to open draft bump PRs; optional standards-side scheduled audit). Out of scope for a standards PR (lives in other repos) and gated on a dispatch PAT + owner sign-off. Registry + topology stay in sync (edited files are root/docs, not spec homes). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP
hyperpolymath
added a commit
that referenced
this pull request
Jun 21, 2026
…s/Maintainers) (#398) ## What Adds `docs/wikis/` — a long-form, **audience-segmented education layer** for `standards`, deeper than the `QUICKSTART-*.adoc` setup guides. Follow-up to the #397 close-out (the staleness work), addressing the gap that `standards` had **no education layer beyond quickstart and no wiki mirror**. Follows the estate pattern already used in `k9-svc/*/docs/wikis/` (audience split + machine manifest). ## Contents - `docs/wikis/README.adoc` — wiki home + audience routing + format/sync rules. - `docs/wikis/{users,developers,maintainers}/index.adoc` — three learning paths. Each is a **complete link spine** into the canonical docs (README, EXPLAINME, CLAUDE.md, the ADRs, the policies, the registry) with explicit `TODO` markers where prose still needs writing — an honest scaffold, not an empty stub. - `docs/wikis/0.2-AI-MANIFEST.a2ml` — machine mirror of the track (so it's in **both** human and machine docs). - `README.adoc` + `0-AI-MANIFEST.a2ml` — each gains an "education layer" front-door row. ## Audience split - **Users** — consuming/adopting the standards (reusable workflows incl. the pin-freshness window from ADR-003, A2ML, readiness grades). - **Developers** — building to the standards (language policy, A2ML/K9 authoring, Hypatia rules, the CI gates). - **Maintainers** — evolving the standards (registry generator, the licence Manual-Only guardrail, drift/staleness automation, the 6a2/contractile stack). ## Notes - Registry + topology stay in sync (`docs/` is not a spec home — verified). - SPDX from birth: `CC-BY-SA-4.0` for the `.adoc` docs (matching the existing docs), `MPL-2.0` for the `.a2ml` manifest. - Full per-track prose is intentionally deferred — tracked as a follow-up issue (the docs/wiki education audit). - The pre-existing estate-wide Hypatia checks (`governance` / `hypatia-scan`) are red on `main` independently of this PR; this change is docs-only. Kept **draft** pending review of structure/scope before the prose is written. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP --- _Generated by [Claude Code](https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP)_ Co-authored-by: Claude <noreply@anthropic.com>
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.
Problem
standardshosts reusable workflows (governance-reusable.yml,hypatia-scan-reusable.yml,scorecard-reusable.yml, …). Consumer repos pin them by full SHA, andscripts/check-workflow-staleness.sh(run in every consumer via the governance reusable) failed the consumer's CI whenever its pin ≠ standards HEAD.Because HEAD moves often, every standards commit turned every consumer PR red until someone manually re-bumped the pins. Observed live in a stapeln session: HEAD moved
5a93d9d→d72fe5a→4ddc926in ~30 min, each move forcing a manual 3-file pin bump. The gate was a treadmill, not a guard. The intent to automate this exists as the Hypatia rulesha_bump_propagation.ex, but it was never wired — so the gate just nagged.Decision — recency window (Option B), + wire the deliberate-bump path
Chosen mechanism: a recency-window tolerant gate, mirroring the estate's own staleness idiom (Hypatia HYP-S006
registry-staleness, which tolerates drift forstale_after_days: 14before escalating rather than failing on first mismatch). Full rationale incl. rejected alternatives inADR-003.A pinned SHA now passes when it is a genuine ancestor of HEAD within the window:
STALENESS_WINDOW_COMMITScommits behind HEAD (default 50), ORSTALENESS_WINDOW_DAYSdays old (default 14).A pin still fails when it is out of window (pins can't rot forever; known-bad historical pins stay blocked) or not a published standards commit (forged/fork/divergent SHAs rejected — supply-chain integrity preserved). A pin ahead of the gate's HEAD view (a race during a HEAD move) is treated as fresh. In-window-but-behind pins emit a non-failing
::noticenudge.This satisfies the core requirement — a consumer PR no longer fails purely because standards moved — which the auto-PR-only option (A) does not (the in-flight PR stays red until the bump merges). The mutable
@vNtag option (C) was rejected as a supply-chain regression vs full-SHA pinning.Wiring
sha_bump_propagation(the deliberate bump)A wanted bump now lands via
scripts/propagate-workflow-pins.sh— an audit-first helper that rewrites a consumer's standards pins to a target SHA and stages them on a branch, never committing/pushing (mirrorspropagate-gitignore-67-68.sh). This is the concrete standards-side action the Hypatiasha_bump_propagationrule routes to (gitbot-fleet runs it and opens a draft PR). The gate no longer forces the bump.Changes
scripts/check-workflow-staleness.sh— exact-HEAD → recency-window ancestry check; non-failing nudge for in-window pins; forged/out-of-window still fail.scripts/propagate-workflow-pins.sh(new) — audit-first deliberate-bump helper (--fixstages a branch; never commits/pushes)..github/workflows/governance-reusable.yml— clone standards with--filter=tree:0(full commit graph, minimal data) so the gate can do ancestry/age math.docs/decisions/ADR-003-…adoc(new) — the decision + rejected alternatives + supply-chain trade-off.check-workflow-staleness-test.sh(12 hermetic cases) +propagate-workflow-pins-test.sh(11 cases).Justfile—staleness-check/staleness-propagate/staleness-testrecipes.Verification (against real
standardshistory + a stapeln-shaped consumer)standardsitselfGuardrails
propagate-gitignore-67-68.sh; CC-BY-SA-4.0 for the ADR, matching ADR-002).🤖 Generated with Claude Code
https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP
Generated by Claude Code