Skip to content

feat(routines): rewrite six new routines, ground-truthed and hardened#20

Open
JacobPEvans-personal wants to merge 14 commits into
mainfrom
feat/six-new-routines
Open

feat(routines): rewrite six new routines, ground-truthed and hardened#20
JacobPEvans-personal wants to merge 14 commits into
mainfrom
feat/six-new-routines

Conversation

@JacobPEvans-personal
Copy link
Copy Markdown
Member

@JacobPEvans-personal JacobPEvans-personal commented May 22, 2026

Update history

  • Commit 1f59d71 (refactor(routines): simplify per /simplify review): batched API calls in Apothecary/Quartermaster/Conductor (~200 calls/run saved); unified terminology ("skip-list" everywhere instead of mixed "blacklist"/"skip-list").
  • Commit 26f45c4 (merge from main): incorporated PR fix(routines): sign Issue Solver commits via createCommitOnBranch GraphQL #19's GraphQL createCommitOnBranch signing fix for Issue Solver; conflict resolution kept both that signing approach AND this branch's "review-ready, not draft" policy (per the unified attribution decision; ai-merge-gate is Issue Solver's human-in-the-loop checkpoint).

Rewrites all six new cloud routines (Distributor, Inspector, Quartermaster, Archivist, Apothecary, Conductor) plus the attribution block in CLAUDE.md. Ground-truthing against the actual JacobPEvans estate revealed broad fabrication in the original PR — invented workflow lists, drift dimensions, docs-site paths, bot allowlists. This rewrite addresses that plus three CRITICAL security flaws and substantial over-engineering surfaced by two rounds of external review (9 reviewers total: Claude Opus 4.7, Codex/gpt-5.2, code-modernization architecture-critic, cloud-architect, security-auditor, performance-engineer, plus a docs.jacobpevans.com fetch and one continuation pass each with Opus and Codex).

Full design plan: see /Users/jevans/.claude/plans/this-whole-pr-needs-peppy-pixel.md (local; planning artifact, not in repo).

What this PR contains

Security hardening (critical)

  • S1: All uses: refs in propagated workflow callers are 40-char commit SHAs, never tags. Tag→SHA resolution cached per run; refuses to act unless the resolved commit is web-flow signed. Partial-failure-safe (one workflow's signature failing doesn't abort the whole run).
  • S2: Dropped secrets: inherit from caller templates. Each tier's required secrets are named explicitly; missing-secret in target repo opens an issue, not a broken PR.
  • S3: Conductor file-allowlist for chore(main): release PRs (closes the release-please supply-chain attack where a compromised config could ship arbitrary file mutations under a release title). Plus signed-commit verification on every merge.
  • S4: New .github/CODEOWNERS requires @JacobPEvans review on routines/**, the deploy skill, CLAUDE.md, and CODEOWNERS itself. Pair with branch protection (separate admin action — follow-up fix: switch deploy trigger from push to workflow_dispatch + daily schedule #4).
  • S5: Inspector path-redaction regex set applied before any PR/issue body composition. Skip-list extended to *.local.md, .envrc*. Provenance "Why" lines describe the rule, never quote the offending string.
  • S6: Slack output sanitization (escape </> in any field derived from repo content) — closes the <!channel>/<@USER> smuggling attack via package-description-flavored PR titles.
  • S7: State gist content rules (no secrets, no raw alert payloads, no file diffs, no file contents). Sentinel follow-up adds gist secret-scan rule.

Cross-cutting controls (added to CLAUDE.md hard-rules 5-10)

  • C1: Shared routine-pr-budget gist (soft cap 2 PRs per repo per UTC day across all PR-emitting routines). Best-effort; fails open if gist missing.
  • C2: Per-field state retention (run-log 90 days, closed-pair memory and CodeQL ignore-list indefinite, caches rewritten per run).
  • C3: ROUTINE_PAUSED env var kill switch.
  • C5: Prompt fingerprint logging for drift detection (Sentinel cross-check follow-up fix: correct deployment docs + set Issue Solver trigger_id #3).
  • C6: Staggered post-merge deploy protocol (Inspector → 48h watch → Apothecary + Quartermaster → 48h → Distributor + Archivist + Conductor).

Per-routine rewrites

  • Distributor: Thin caller architecture (no full-file copies). 4 inline tiers (core/tests/nix/terraform), down from a fabricated 15-workflow "minimum suite". One recursive tree call per repo replaces 246 contents probes per run. Migration policy: detect already-pollinated repos by Git blob SHA against ai-workflows HEAD + last 3 tagged releases. suites.yaml cross-repo dependency eliminated.
  • Inspector: 3 rules retained with proper scoping (down from 6 fabricated/dangerous). claude-md-staleness with redaction filter. secrets-policy scoped to src/lib/terraform/ansible/workflows, files ISSUES never PRs. no-scripts with safety gates (draft, yaml.safe_load). Dropped soul (folded into Conductor), tool-use (fuzzy), skill-execution-integrity (self-referential).
  • Quartermaster: Single dimension (pre-commit-hooks pin bumps) with explicit Renovate-overlap guard. 4 dimensions dropped (no estate evidence).
  • Archivist: Purpose pivot — README quality (6-item checklist citing makereadme.com + awesome-readme) + Mintlify coverage (docs.json navigation check, issues only). Drops impossible README↔.mdx sync. Acknowledged two-routines-in-one compromise; revisit at 30 days (follow-up harden(custodian): block Write/Edit + move deploy earlier #5).
  • Apothecary: CodeQL-primary triage using rule.security_severity_level (CVSS unreliable). Subset allowlist + diff-hunk content gate replaces exact-set (which would have broken Renovate's standard pyproject.toml+uv.lock flow). Severity-missing fails closed.
  • Conductor: Reframed as allowlist + batching, not auto-merger. Author allowlist corrected (3 dead entries removed). Title allowlist corrected against 200-PR sample (added chore(main): release, fix(deps):, build(deps):, ci(deps):). File-allowlist for release PRs. Signed-commit verification. 4-hour minimum PR age.

Ground-truth data sources (cited in routine prompts)

  • Workflow adoption matrix: 41 non-archived public repos × 15 candidate workflows. No workflow exceeds 50% adoption. Highest: release-please.yml at 19/41 (46%).
  • Archetype clustering: 11 distinct archetypes.
  • Pre-commit drift: ≥4 distinct major-pin generations of pre-commit-hooks across 15+ repos sampled.
  • 200-PR sample window: merged PRs in the 6 months before 2026-05-25.
  • Docs site fetched 2026-05-25 via WebFetch.

Follow-up issues (filed as part of this PR's merge)

  1. JacobPEvans/.github — Provision auto-merge-deps label estate-wide via label-sync (so Apothecary's gate works everywhere).
  2. claude-code-routines — Add silent-rot section to Weekly Scorecard.
  3. claude-code-routines — Add Sentinel rules for prompt fingerprint drift + state-gist secret scan.
  4. claude-code-routines — Enable branch protection on main requiring CODEOWNERS review (admin tier).
  5. claude-code-routines — Evaluate Archivist Task 2 (Mintlify coverage) hit rate after 30 days; fold into Morning Briefing if low.

Deploy protocol (DO NOT all-at-once)

After merge, deploy via the .claude/skills/deploy-routine-changes/SKILL.md skill in this order with 48-hour watch windows between stages:

  • Day 0: Inspector (smallest blast radius, max 1 PR/run, read-mostly).
  • Day 2: Apothecary + Quartermaster (label-only and config-only mutations).
  • Day 4: Distributor + Archivist + Conductor (mutation-heavy).

If any stage produces unexpected output, halt and set ROUTINE_PAUSED=true on the misbehaving routine via the claude.ai web UI.

Backstory commit (Custodian lottery)

The merge from main into this branch (commit 2de04ab) resolved a conflict in routines/custodian.prompt.md between the branch's task-trim (drop pr-triage + aw-health) and main's task-add (bot-thread-resolve from PR #18). Lottery weights rebalanced to sum to 100 across 7 tasks. Already on the branch — no further action needed.

Assisted-by: Claude noreply@anthropic.com

New routines:
- inspector: daily estate-wide CLAUDE.md/rules/skills violation audit
- quartermaster: cross-repo config drift detection and sync
- archivist: public docs site and private docs README drift sync
- apothecary: dependency/security alert triage and auto-merge pre-labeling
- conductor: bot-PR auto-merge (renovate, dependabot, release-please, gh-aw)
- distributor: ai-workflows minimum-suite propagation to all repos

Custodian trim:
- drop pr-triage (Conductor owns it) and aw-health (event-driven GHA will own it)
- reduce per-run task count from 2 to 1; rebalance lottery weights

Cadence: 14 runs/day (15 on Mondays), one spare slot remaining.

Assisted-by: Claude <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Inspector: trig_01Kaa2rWoVFS4HN4LRR5UMWX
Quartermaster: trig_017wzm9n7a8v2yh3tfAsnmg8
Archivist: trig_01U6EPmvAdUDy2k7LfYWkqts
Apothecary: trig_015zNd6NJRJZCd784qX5FEgm
Conductor: trig_01N7W9LBApg9veyo2NgdprNV
Distributor: trig_01HoVTrJjo41JFEyzmY1tU5b

Assisted-by: Claude <noreply@anthropic.com>
Every PR and issue created by a cloud routine now carries the same
three-layer attribution: title suffix, body Provenance block, and
the cloud-routine label.

Title suffix:
  chore(ci): add gh-aw-pin-refresh.yml [routine:distributor]
  docs(int_homelab): polish README [routine:daily-polish]
  [routine:custodian] Repo health audit - 2026-05-23

No emoji in titles or bodies (soul rule). Conventional-commit prefix
preserved so release-please continues to parse it. Emoji remain in
Slack output only, where the rule allows them.

Body footer (every PR + every issue):
  ## Provenance
  - Generated by: [Routine Name](link) - cron description
  - Triggered: what fired this run (cron + task lottery if any)
  - Why this PR/issue: one-line rationale
  - State: link to state gist
  - Label: cloud-routine

Label: cloud-routine, defined in JacobPEvans/.github/labels.yml in
a companion PR. Propagates to every public repo via the existing
label-sync.yml workflow - routines do not gh-label-create per repo.

PRs are now review-ready, not draft. Draft purgatory blocked the
ai-workflows review path (claude-review, final-pr-review,
ai-merge-gate) from picking up routine PRs; review-ready opens them
to the normal flow. Conductor still does not auto-merge them - its
allowlist is bot-author-specific and excludes routine bot identity.

Files touched:
- routines/daily-polish.prompt.md - drop emoji title, branch
  becomes docs/daily-polish/<repo>-<date> (was chore/daily-polish,
  collided across runs).
- routines/sentinel.prompt.md - drop emoji title, drop draft.
- routines/custodian.prompt.md - repo-audit issue gets
  [routine:custodian] prefix + Provenance + label.
- routines/inspector.prompt.md - drop draft, add suffix/block/label.
- routines/quartermaster.prompt.md - same.
- routines/archivist.prompt.md - same; private-docs issue too.
- routines/distributor.prompt.md - same.
- routines/issue-solver.prompt.md - drop emoji prefix from title
  and from abandon-comment; drop draft. PR title becomes
  fix(<repo>): <issue title> (#<NNN>) [routine:issue-solver].
- .github/workflows/issue-solver.yml - rename job to
  'open a review-ready PR'.
- CLAUDE.md - new Attribution conventions section under Hard
  rules. Future routines inherit the convention.

Apothecary, Conductor, Morning Briefing, Weekly Scorecard not
touched: they do not create PRs or issues directly.

Companion PRs:
- JacobPEvans-personal/.github#340 defines the cloud-routine label.
- JacobPEvans/ai-workflows attribution PR will follow.

Assisted-by: Claude <noreply@anthropic.com>
@JacobPEvans-personal JacobPEvans-personal changed the title feat(routines): add six new cloud routines and trim Custodian feat(routines): six new routines + unified attribution + review-ready PRs May 24, 2026
Per PR #20 §S4: prompts are load-bearing code that the cloud sandbox
executes on cron. A malicious or accidental edit to any of these files
can mass-mutate the JacobPEvans estate via the JacobPEvans-claude App
(contents:write across the owner). Pair with branch protection
requiring CODEOWNERS review (separate admin action).

Assisted-by: Claude <noreply@anthropic.com>
Adds five new sections to operator guide:

1. Staggered deploy after multi-routine merges (3-stage rollout with
   48h watch windows).
2. Hard rules 5-10: paused flag (kill switch via env var), body
   redaction regex set, Slack output sanitization, state gist
   schema + per-field retention, shared routine-pr-budget gist,
   prompt fingerprint logging for drift detection.
3. Review-ready exception for workflow-touching PRs (Inspector
   no-scripts refactors must be draft).

All sections derive from PR #20 reviewer feedback (Claude Opus 4.7,
Codex, architecture-critic, cloud-architect, security-auditor,
performance-engineer). Companion to the six routine rewrites in the
same PR.

Assisted-by: Claude <noreply@anthropic.com>
… migration policy

Complete rewrite addressing 3 critical reviewer findings plus the
correctness gap that prompted PR #20's audit.

Architecture changes:
- Thin caller YAML (10-15 lines) replaces full-file workflow copies.
  The reusable workflows in ai-workflows are on: workflow_call;
  copying them into target repos orphans library code.
- uses: refs are 40-char commit SHAs, never tags. Tag resolution
  cached per run; verification requires web-flow signed commit.
- secrets: inherit removed. Tier table declares required secrets
  per workflow; missing secret in target repo opens an issue, not
  a broken PR.

Tier system:
- 4 tiers inline in the prompt (no external suites.yaml — it would
  have created a cross-repo runtime dependency, day-one no-op risk,
  and a new injection vector):
    core (any .github/workflows/*)
    tests (has tests/ or *_test.* files)
    nix (flake.nix at root)
    terraform (any *.tf at root or terragrunt.hcl)
- One recursive git/trees call per repo; predicates evaluated as
  local jq filters (was 246 contents probes per run, now 41).
- Opt-out via skip-distributor topic, per-tier opt-out via
  skip-distributor-<tier>.

Migration policy:
- Detect already-pollinated repos by Git blob SHA against
  ai-workflows HEAD + last 3 tagged releases (bounded; ~4 API
  calls per consumer workflow).
- Recognized full-file copies open DRAFT PRs replacing the body
  with the thin caller. Diverged copies file an issue instead.
- Migration cap: 1 PR per repo per run.

Excludes:
- Workflows: dogfood-*, suite-*, repo-orchestrator,
  notify-ai-pr (ai-workflows-only), claude-review.yml (deprecated
  2026-04-04), all _-prefixed reusables.
- Repos: agentics, agent-os (mirrors), tf-static-website
  (abandoned), splunk-app legacy, profile/meta repos.

Cross-cutting controls:
- ROUTINE_PAUSED kill switch
- Body redaction via CLAUDE.md regex set
- Slack output sanitization
- Per-repo PR budget consultation (routine-pr-budget gist)
- Prompt fingerprint logging
- State gist schema v2 with per-field retention (closed_pairs
  retained indefinitely — rejection memory must outlive trim
  windows)

Reviewer findings addressed: security-auditor S1/S2/S3 (mutable
refs, secrets: inherit, signature verification), architecture-critic
H1 (over-engineering reduced from 6 tiers to 4), opus-4.7
on suites.yaml wrong layer, codex on migration feasibility
(blob-SHA capped, not historical text scan).

Assisted-by: Claude <noreply@anthropic.com>
…aching

Reduces from 6 rules to 3 retained-with-redesign. Drops the rules
that were broken or noise; salvages the two that were dismissed too
quickly.

Kept (with redesign):
- claude-md-staleness — scope expanded to AGENTS.md + SKILL.md.
  Adds placeholder / glob / URL / absolute-path filters. Output
  passes through redaction regex (S5) so private paths cannot
  leak into public PR bodies. Content-hash + resolved-path caches
  in inspector-state gist (~85-90% read reduction at steady state).
- secrets-policy — scoped to src/lib/terraform/ansible/.github/
  workflows only. Hard-skips SECURITY.md, README.md, *resume*,
  obsidian-* repos (the prior version's 100% false-positive rate
  hit user's own contact emails in personal files). Files an ISSUE
  in the affected repo — never a PR. Credential expunge is
  operator judgment (rotate, then expunge from history).
- no-scripts — relaxed Inspector's blanket "no workflow PRs" hard
  rule for this rule only. Safety gates: PRs are DRAFT, post-edit
  YAML must pass yaml.safe_load, CI must pass before any human
  review. Refactor extracts run-block to scripts/<name>.sh.

Dropped:
- soul — folded into Conductor's PR-title regex (Conductor already
  inspects titles). Scope limited to bot PRs; estate baseline is
  clean (zero violations in 100-commit sample 2026-05-15..2026-05-25).
- tool-use — fuzzy commit-message text matching. Real hits
  dominated by `cat /api/...` doc references. No actionable fix.
- skill-execution-integrity — self-referential. Top hit is the
  rule's own canonical definition file.

Rotation reduced from `% 6` to `% 3`.

Cross-cutting controls added: ROUTINE_PAUSED, body redaction,
Slack escape, state schema v2 with cache fields, prompt fingerprint.

Reviewer findings addressed: security-auditor finding #1 (path
leakage — fixed via S5 redaction + skip-list extensions for
*.local.md), architecture-critic on premature rule-dropping
("Dropping is cheap. Redesigning is what a staff engineer does."),
opus-4.7 on no-scripts salvage path, codex on expanded scope
without justification (now justified explicitly).

Assisted-by: Claude <noreply@anthropic.com>
… Renovate guard

Reduces from 5 drift dimensions to 1, with explicit Renovate-overlap
guard so the routine doesn't duplicate Renovate's work in repos that
opt into the central preset.

Dropped 4 of 5 dimensions (no estate evidence):
- osv-ignore-lists: N=2 repos with intentionally disjoint contents
- gitignore-patterns: prompt's specific pattern list (.direnv/,
  .envrc.local, *.pyc) wasn't what was actually in the files
- dependabot-schedule: N=1 repo with dependabot.yml
- renovate-schedule: schedule lives in JacobPEvans/.github central
  preset — no local schedule: arrays in any renovate.json

Kept:
- pre-commit-hooks: real drift confirmed (≥4 distinct major-pin
  generations of pre-commit-hooks across 15+ repos sampled).

New behavior:
- Drift threshold: ≥2 minor versions behind upstream latest tag
  (was: any difference — too noisy).
- Renovate-overlap guard: skip if an open Renovate PR targets
  .pre-commit-config.yaml in the same repo.
- Content-hash skip via state gist (cache sha256 of last-scanned
  config body; re-parse only if changed).
- 14-day cooldown per (repo, hook) pair.

Cross-cutting controls added: ROUTINE_PAUSED, body redaction,
Slack escape, state schema v2, per-repo PR budget, fingerprint.

Reviewer findings addressed: architecture-critic on "Quartermaster
duplicates Renovate" (now explicitly guarded), opus-4.7 on
over-scoping (4-to-1 reduction).

Assisted-by: Claude <noreply@anthropic.com>
Drops the prior README↔docs sync premise (impossible — docs.jacobpevans.com
is a Mintlify topic-sorted .mdx site with frontmatter and JSX components,
not a flat docs/<repo>.md mirror). Routine basename stays archivist;
purpose pivots to two tasks rotating daily:

Task 1 — readme-quality:
- 6-item checklist scoring (exists, purpose paragraph, quickstart,
  usage/examples, license, length 30-400 lines).
- References cited in PR bodies: makeareadme.com, awesome-readme.
- Picks lowest-scoring repo, opens 1 review-ready PR addressing the
  most impactful gap (gap-specific templates for missing-purpose,
  missing-quickstart, missing-usage, missing-license).
- The 7th check originally proposed (broken relative paths) is
  removed — that's Inspector's claude-md-staleness rule. Avoids
  cross-routine PR contention on the same files.

Task 2 — mintlify-coverage:
- Reads docs.json navigation from JacobPEvans/docs.
- Cross-references against the non-blacklisted public repo list.
- Files ONE issue against JacobPEvans/docs for the most-recently-
  pushed uncovered repo. Issues only — Mintlify page authoring is
  editorial (frontmatter, JSX components, narrative prose).
- Replaced the prior "diagram with ≥3 repo names" sub-rule (which
  was silently always-true for common English nouns) with a clean
  docs.json navigation check.

Rotation: % 2 (was: not rotated, single sync task).
Dropped: PRIVATE_DOCS_REPO env var path (private docs is a separate
concern; out of scope).

Cross-cutting controls added: ROUTINE_PAUSED, body redaction,
Slack escape, state schema v2, per-repo PR budget, fingerprint.

Acknowledged compromise: this is two routines under one name.
Follow-up issue (in PR #20 description) commits to revisiting after
30 days of run data; if Task 2 hit rate is low, fold into Morning
Briefing.

Reviewer findings addressed: architecture-critic H4 (two-routines-
in-trench-coat — acknowledged, scheduled revisit), codex on Task 1/
Inspector overlap (check #7 removed), opus-4.7 on issue-only as
correct artifact (not PR scaffold), architecture-critic B3 on
diagram silently-always-true (replaced with docs.json check).

Assisted-by: Claude <noreply@anthropic.com>
…iff-content check

Refocuses from "Dependabot triage" to "CodeQL + Dependabot triage"
using the correct severity field. Ground-truth data:
- Dependabot alerts: zero across 5-repo active sample
- CodeQL alerts: present in 3 of 5 sampled repos
- Lockfile inventory: only flake.lock and uv.lock exist at root
  in the estate (8 of 10 prior lockfile patterns were aspirational)
- auto-merge-deps label: exists in 2 of 5 sampled repos

Changes:
- Use rule.security_severity_level (not CVSS — often missing).
  Dependabot equivalent: security_advisory.severity.
- Auto-label gate is now a conjunction of 8 conditions including:
  state==open, severity==high (Low/Medium do NOT auto-label —
  that's noise; the prior policy would create label-PR storms on
  long-standing accepted findings), age >7d, NOT in per-repo
  codeql_ignore list, file list ⊆ dependency-manifest allowlist
  (subset, NOT exact-set — Renovate's pyproject.toml + uv.lock
  pattern would have been rejected by exact-set), diff-content
  check (every changed hunk line matches a declaration regex —
  closes the one-byte source-edit bypass), signed commits,
  auto-merge-deps label provisioned in target repo.
- Severity-missing → fail closed (Slack-only, never auto-label).
- High/critical alerts → Slack escalation with cooldown (3 days
  per (repo, alert) pair).
- Label-presence gate: skip auto-label and escalate via Slack if
  auto-merge-deps label missing in target repo. Provisioning is
  out-of-band via JacobPEvans/.github label-sync (follow-up issue).

Cross-cutting controls added: ROUTINE_PAUSED, redaction, Slack
escape, state schema v2 (codeql_ignore retained indefinitely),
fingerprint. C1 budget doesn't apply — Apothecary opens no PRs.

Reviewer findings addressed: security-auditor finding #2
(lockfile bypass — subset + diff-content gate), opus-4.7 on CodeQL
severity field (CVSS wrong), opus-4.7 round 2 on exact-set breaking
Renovate flows (NOW subset allowlist), architecture-critic on label
provisioning (escalate when missing, don't paper-over with inline
create).

Assisted-by: Claude <noreply@anthropic.com>
…ed-commit verification

Reframes Conductor's value from "auto-merger" to "allowlist enforcement
and cross-repo audit trail" — native gh pr merge --auto --squash plus
branch protection covers ~80% of the merge mechanic. Conductor adds the
gates that native auto-merge doesn't.

Allowlists corrected against 200-PR sample (last 6 months before
2026-05-25):

Author allowlist:
- Kept: renovate[bot], dependabot[bot], github-actions[bot],
  jacobpevans-github-actions[bot]
- Dropped (dead entries that never matched): release-please[bot]
  (this estate uses github-actions[bot] for release-please),
  app/renovate, app/dependabot (App slugs; author.login is
  always <name>[bot])

Title-pattern allowlist:
- Added: chore(main): release (44/200 sample — actual release-please
  format), fix(deps): (jacobpevans-github-actions action-pin
  refreshes), build(deps): / ci(deps): / ci(deps)(deps): (Dependabot)
- Dropped (never matched): chore(release):, chore: release,
  chore(gh-aw): refresh action pins
- Added rejection clause: emoji in title (absorbs the prior soul
  rule's PR-title concern for bot PRs; scope-note in prompt
  documents the estate-wide gap)

New gates (security hardening):
- Release file-allowlist: chore(main): release PRs from
  github-actions[bot] must have a changed file set ⊆ {CHANGELOG.md,
  manifest, version files, lockfiles} plus per-repo extensions
  from conductor-state. Closes the release-please supply-chain
  attack where a compromised config could ship arbitrary file
  mutations under a release title.
- Signed-commit verification: every commit in the PR must be
  web-flow signed (verification.verified == true).
- Minimum PR age: 4 hours (gives humans a review window between
  Renovate's instant auto-merge and Conductor's pass).

Workflow-edits exception corrected:
- Was: chore(gh-aw): refresh action pins title (never matched)
- Now: fix(deps): + [aw:gh-aw-pin-refresh] tag + author is
  jacobpevans-github-actions[bot]

Blocking-label guard kept as one-line check (none of the labels
are provisioned today; one-line cost survives future label-sync
additions).

Cross-cutting controls added: ROUTINE_PAUSED, Slack escape (PR
titles are user-controlled via package descriptions), state schema
v2 (release_allowlist_extensions indefinite), fingerprint. C1
budget doesn't apply — Conductor merges, doesn't open PRs.

Reviewer findings addressed: security-auditor finding #3
(release-please supply chain — file allowlist + signed commits),
opus-4.7 on framing (allowlist + batching, not the merge mechanic),
opus-4.7 round 2 confirming 4h gate doesn't break Renovate's
auto-merge UX (different paths — Renovate sets native auto-merge
at PR creation; Conductor is the safety-net pass).

Assisted-by: Claude <noreply@anthropic.com>
…minology)

Applies findings from the /simplify pass on the PR #20 rewrites.

Efficiency fixes:
- apothecary: fetch /pulls/<n>/files once, reuse JSON for Gate 4
  (file-list allowlist) and Gate 5 (diff-content check). Eliminates
  one redundant API call per eligible bot PR.
- quartermaster: fetch .pre-commit-config.yaml content and blob SHA
  in one call instead of two (saves ~one request per repo per run,
  ~100 calls/run at current estate size).
- conductor: replace per-repo gh pr list loop with one org-wide
  gh search prs call. Saves ~one request per repo per run (~100
  calls/run). Per-PR enrichment for mergeability still uses
  gh pr view because gh search prs doesn't return those fields.

Terminology consistency:
- Standardize "skip-list" across routines (was a mix of
  "blacklist", "blacklisted", "skip blacklist"). Inspector already
  used skip-list; Archivist/Conductor/Apothecary now match.

No semantic changes. Lint clean.

Assisted-by: Claude <noreply@anthropic.com>
# Conflicts:
#	routines/issue-solver.prompt.md
@JacobPEvans-personal JacobPEvans-personal changed the title feat(routines): six new routines + unified attribution + review-ready PRs feat(routines): rewrite six new routines, ground-truthed and hardened May 25, 2026
@JacobPEvans-personal JacobPEvans-personal enabled auto-merge (squash) May 29, 2026 02:51
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.

1 participant