Skip to content

ci(staleness): tolerate in-window reusable pins + wire deliberate bump path#397

Merged
hyperpolymath merged 3 commits into
mainfrom
claude/peaceful-meitner-31757r
Jun 21, 2026
Merged

ci(staleness): tolerate in-window reusable pins + wire deliberate bump path#397
hyperpolymath merged 3 commits into
mainfrom
claude/peaceful-meitner-31757r

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Problem

standards hosts reusable workflows (governance-reusable.yml, hypatia-scan-reusable.yml, scorecard-reusable.yml, …). Consumer repos pin them by full SHA, and scripts/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 5a93d9dd72fe5a4ddc926 in ~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 rule sha_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 for stale_after_days: 14 before escalating rather than failing on first mismatch). Full rationale incl. rejected alternatives in ADR-003.

A pinned SHA now passes when it is a genuine ancestor of HEAD within the window:

  • STALENESS_WINDOW_COMMITS commits behind HEAD (default 50), OR
  • STALENESS_WINDOW_DAYS days 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 ::notice nudge.

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 @vN tag 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 (mirrors propagate-gitignore-67-68.sh). This is the concrete standards-side action the Hypatia sha_bump_propagation rule 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 (--fix stages 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.
  • Tests (new/rewritten)check-workflow-staleness-test.sh (12 hermetic cases) + propagate-workflow-pins-test.sh (11 cases).
  • Justfilestaleness-check / staleness-propagate / staleness-test recipes.

Verification (against real standards history + a stapeln-shaped consumer)

Scenario Result
stapeln pinned 3 commits behind HEAD (the treadmill) PASS (relaxed gate + nudge)
Out-of-window pin (tight window, real 19d/49-behind ancestor) FAIL (window has teeth)
Forged SHA FAIL (supply-chain integrity)
Gate run against standards itself PASS (no self-red)
12/12 check-workflow-staleness tests passed
11/11 propagate-workflow-pins tests passed

Guardrails

  • No SPDX/licence header was added, removed, or swept in any modified file. New files carry correct SPDX from birth (MPL-2.0 for the sole-owner shell scripts, matching propagate-gitignore-67-68.sh; CC-BY-SA-4.0 for the ADR, matching ADR-002).
  • The propagation helper never commits or pushes (no unattended mutations).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BKyi8Bht8xdXyajpkaTdYP


Generated by Claude Code

claude added 3 commits June 21, 2026 18:56
… 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 hyperpolymath marked this pull request as ready for review June 21, 2026 19:11
@hyperpolymath hyperpolymath merged commit 42455b1 into main Jun 21, 2026
12 of 14 checks passed
@hyperpolymath hyperpolymath deleted the claude/peaceful-meitner-31757r branch June 21, 2026 19:11
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants