Skip to content

feat(ci): gate non-main-base PRs in the trailer backstop (§13.40 prereq) - #123

Merged
artyhoo merged 1 commit into
mainfrom
feat/backstop-nonmain-base
May 21, 2026
Merged

feat(ci): gate non-main-base PRs in the trailer backstop (§13.40 prereq)#123
artyhoo merged 1 commit into
mainfrom
feat/backstop-nonmain-base

Conversation

@artyhoo

@artyhoo artyhoo commented May 21, 2026

Copy link
Copy Markdown
Owner

What & why

Follow-up to the merged trailer backstop (#121). #121's pr-commit-trailers job diffs against a hard-coded origin/main, so it only gates PRs targeting main. The §13.40 automerge→staging plan routes sub-PRs at a long-lived staging branch — there origin/main..HEAD is the wrong range. This parameterises the diff base so the backstop follows the actual PR base.

This is the unique delta salvaged from the closed dup #122 (see #122 close comment).

Changes

  • pre-push.tsupstreamRef() reads PREPUSH_UPSTREAM_REF (default origin/main, so the local hook and PRs→main are byte-identical to today).
  • audit-self.yml pr-commit-trailers — fetch + diff against the PR base (github.base_ref); assert the base resolves so upstreamExists() can't silently skip the checks (false-pass); pass PREPUSH_UPSTREAM_REF to both check steps.
  • tests/hooks/prepush-upstream-ref.test.sh — paired-negative: proves the override is read (default vs override differ on identical state) and scopes the range correctly (<base>..HEAD). Wired into principles-meta-tests.

Backward-compatible: PRs→main keep base_ref=mainorigin/main → no behaviour change.

Out of scope (surfaced, not fixed)

pre-push.test.ts:54 ("invokes the remaining audit-self self-tests by literal path") already fails on main — Wave 10.4 (#120) renamed audit-ai-docs.test.sh.test.ts but the structural expectation still asserts .test.sh. It's invisible in CI because the principles job runs vitest principles/ only, not hooks/. Flagging for a separate fix; not touched here.

QA done locally

  • prepush-upstream-ref.test.sh 3/3; pre-push hook green on push (92 principle tests).
  • actionlint + zizmor clean on audit-self.yml.
  • tsc --noEmit clean for changed files (the audit-ai-docs.ts remark errors pre-date this PR and resolve under CI npm install).

§1.7 Forward-check applied

The backstop runs against itself on this PR. The new PREPUSH_UPSTREAM_REF override is covered by a dedicated paired-negative at tests/hooks/prepush-upstream-ref.test.sh:99 (default-includes-bad), :113 (override-excludes-bad), :128 (override-includes-bad against a non-main base) — so the env-scoping is proven both read and correctly scoped, not just present.

§1.7 Backward-check applied

Swept the call sites this touches: both UPSTREAM_REF consts in packages/core/hooks/pre-push.ts (priorArtSection ~L91, s17Section ~L144) now route through upstreamRef(); #121's pr-commit-trailers job is the only consumer that overrides the env, and PRs→main keep the origin/main default. No other workflow or hook reads the diff base, so no further consumers to update.

The #121 pr-commit-trailers job diffs against a hard-coded origin/main,
so it only gates PRs targeting main. The §13.40 automerge→staging plan
has sub-PRs target a long-lived staging branch — there the origin/main
range is wrong (it would re-evaluate every commit on staging not yet in
the PR). Parameterise the diff base so the backstop follows the actual
PR base.

- pre-push.ts: upstreamRef() reads PREPUSH_UPSTREAM_REF (default
  origin/main → local hook + PRs→main behaviour unchanged).
- audit-self.yml pr-commit-trailers: fetch + diff against the PR base
  (github.base_ref); assert the base resolves so the gate can never pass
  by silently skipping; pass PREPUSH_UPSTREAM_REF to both check steps.
- tests/hooks/prepush-upstream-ref.test.sh: paired-negative proving the
  override is read (default vs override differ on identical state) and
  scopes the range correctly; wired into principles-meta-tests.

Backward-compatible: PRs→main keep base_ref=main → origin/main.

Observed (out of scope, NOT fixed here): pre-push.test.ts:54 "invokes the
remaining audit-self self-tests by literal path" already fails on current
main — Wave 10.4 (#120) renamed audit-ai-docs.test.sh → .test.ts but the
structural expectation still says .test.sh. Not caught in CI because the
principles job runs only `vitest principles/`, not `hooks/`.

§1.7: forward-check applied — the backstop runs on its own PR; the new override is covered by tests/hooks/prepush-upstream-ref.test.sh:99. Backward-check sweep — reviewed #121's pr-commit-trailers job + both pre-push.ts UPSTREAM_REF call sites, all now route through upstreamRef(); PRs→main behaviour unchanged.
Prior-art: skipped — env-param of an existing check + CI job edit, no new capability/dependency/subdir.
@artyhoo
artyhoo merged commit 6d41fb5 into main May 21, 2026
21 checks passed
artyhoo added a commit that referenced this pull request May 21, 2026
…pe (#124)

Records the decided shape (long-lived staging branch, GitHub native
auto-merge gated on green CI, human staging→main as decision gate), the
now-satisfied CI-backstop prerequisite (#121 + #123), the phased rollout,
the maintainer GitHub-settings recipe, and 3 open sub-decisions.

Dedicated doc rather than open-questions.md §13.40: open-questions hit
its 500-line pre-commit cap and no §13.x was cleanly terminal to archive
(archiving an open/armed entry would silently drop tracked state). A
multi-phase plan fits a dedicated doc better than the open-question
registry; a 1-line pointer can be added to §13.40 once room is freed.

Prior-art: skipped — planning doc, no new capability/dependency/subdir.
@artyhoo
artyhoo deleted the feat/backstop-nonmain-base branch May 22, 2026 18:10
artyhoo added a commit that referenced this pull request May 25, 2026
… detection) (#220)

Run `bash .claude/skills/meta-orchestrator/helpers/plan-currency-check.sh`
(L2 Stage 3 detection shipped in #217) → 88 UNTRACKED-N entries surfaced
between the 2026-05-22 reconciliation and origin/staging tip (#217). Map
each to an existing §0 / Track row by adding the PR number to its evidence
cell, or to a new §0 row for two umbrellas that landed in full since the
prior snapshot. Re-run helper → 0 UNTRACKED remaining.

Key changes:

- Snapshot date 2026-05-22 → 2026-05-25 (header + §0).
- N8 row: A-phase 🔲 → 🟡 — C1 SSOT-existence (#170), C2 kickoff
  T-enumeration floor (#174), C3 principle 13 §1.7 substance (#178),
  C4 delivery-channel marker (#177), activation #180. C5 + cost-levers
  remain gated on §5.3 utilisation trigger.
- Track M.1 / M.4 → DONE: M.1 codified T20 via #212 (with NB note —
  recommendation-laziness took the T20 slot, mutation-equivalence
  T-bump 20→21 still pending); M.4 6 paired-negative bash-hook tests
  shipped #195/#196/#197/#198/#199/#200.
- Two new §0 rows: Meta-orchestrator skill (Track P) — BUILD #186 +
  audit rounds #192/#193/#194/#201/#202 + UX refactor #203/#204/#205
  + planner-completeness #213/#214/#217 + §1.7 PR-body mandate #216;
  Recommendation-laziness discipline — R-phase #206/#207, benchmark
  #210, I-phase Sub-waves A/C/D #211/#212/#215.
- N7 row: + dogfood research-patch #135 / §4 demotion #166 / live-trial
  verified #171. N4b row: + design #136 / record #118.
- Infra paragraph: PR refs for I.1 follow-ups (#121/#123/#124/#125/
  #128/#130/#131/#143/#145/#146/#147/#148/#149/#172/#187), I.2
  (#139/#142/#154/#175), I.3 DN-4 (#126/#132/#133/#138/#140/#152/
  #159/#161/#162/#167).
- Track 2.3 (channel-earliness audit) → DONE 2026-05-23 (#181); removed
  from "What actually remains".
- Footer subsection: standalone work (#191 satellite-arch / #189
  guard-liveness / #173 storm-readiness / #176 §10 port / #182 cleanup),
  Wave 10 follow-ups (#110/#112/#113), plan-revision history (#108/
  #109/#153/#155/#157/#160/#164/#165/#168/#179/#185).

Verification:
- `bash .claude/skills/meta-orchestrator/helpers/plan-currency-check.sh
  | grep -c '^UNTRACKED'` → 0 (down from 88).
- `npx markdownlint-cli docs/meta-factory/wave-sequencing-plan.md`
  → no violations.
- `npx vitest run packages/core/skills/plan-currency-check.test.ts`
  → 14/14 passed.

Prior-art: skipped — chore, doc reconciliation only, no new capability
or rule introduced.
artyhoo added a commit that referenced this pull request Jun 17, 2026
…123) (#596)

Forward SSOT entry recording the build-vs-reuse decision for the
language-discipline guard (.claude/rules/language-discipline.md +
packages/core/principles/22-internal-english.test.ts). The two original
capability commits carried `Prior-art: skipped` (frozen squash history,
unrewritable) — this entry closes the residual register gap.

Verdict BUILD for the coupled guard, derived from the full 6-item search
(2026-06-17): DeepWiki MCP unavailable in env (per #121 precedent) →
WebSearch x3 + repo-level x3 + WebFetch attempt. Search surfaced adjacent
single-purpose tools (comment-lang-detector GitHub Action, Cyrillic Check,
Pulp Fiction) recorded as REFERENCE-class precedent for the detection
sub-pattern; none couples an internal-English machinery gate that preserves
category-3 bilingual match-data with an AIF_HOOK_LANG-gated output-language
directive (T16 problem-class distinguished in the entry rationale).

Re-numbered 122 → 123 on egress: PR #592 (/story skill) merged in parallel
and took SSOT ID 122 on staging; this row is the next free ID 123.

Prior-art: prior-art-evaluations.md#123 — adds the BUILD-with-REFERENCE decision for the language-discipline guard; backed by the 6-item search run 2026-06-17 (DeepWiki unavailable → WebSearch x3 + repo-level x3), not a training-data escape hatch.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
artyhoo added a commit that referenced this pull request Jun 17, 2026
All 3 independent stages merged to staging via aif-handoff dispatch:
S1 #593 (path-scope), S2 #596 (SSOT #123), S3 #595 (budget-guard research).

Prior-art: skipped — umbrella closure marker (done.md), no capability/dependency.
artyhoo added a commit that referenced this pull request Jun 17, 2026
…md) (#597)

All 3 independent stages merged to staging via aif-handoff dispatch:
S1 #593 (path-scope), S2 #596 (SSOT #123), S3 #595 (budget-guard research).

Prior-art: skipped — umbrella closure marker (done.md), no capability/dependency.
artyhoo added a commit that referenced this pull request Jun 17, 2026
…124/#125 (#551 residual) (#607)

Design-first R-phase for an idempotent consumer refresh path that updates
framework-owned shipped artefacts without clobbering consumer-owned files.

Output (doc only, no implementation code — T2/T5):
- research-patch 2026-06-17-consumer-upgrade-path.md: WebSearch prior-art sweep
  (copier/cruft = Python, no Node-consumable analog), recommended BFR verdict
  ADAPT-no-dependency, framework-owned-vs-consumer-owned boundary derived from
  SHIPPED_DOCS + three-layer model + .override.md, conditioned implementation plan.
- prior-art-evaluations.md: SSOT #124 (cruft, ADAPT) + #125 (Copier update for
  refresh, ADAPT) — both cross-reference #22, append-only.

Two genuine forks PARKED for the maintainer per kickoff §9 + reviewer-discipline §2:
(1) ADOPT-dep vs ADAPT-no-dep vs BUILD; (2) stateless refresh vs shipped-version stamp.
DeepWiki MCP unreachable in env (per #121/#123 precedent) → WebSearch + SSOT substituted;
recorded as a §0 methodology caveat. No code shipped.

Prior-art: skipped — docs only (R-phase research-patch + SSOT register rows), no new capability commit (no dep, no code under packages/).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
artyhoo added a commit that referenced this pull request Jun 17, 2026
…#547 P1) (#610)

* docs(aif-init-passport-gen): R-phase prior-art consult + parked design forks (#547 P1)

Design-first task dispatched under the LIVE park-don't-guess contract. Did the
deterministic work the contract authorizes — prior-art consult (own-stack-first
CC /init + tool-bootstrapping; WebSearch/WebFetch x3 phrasings; DeepWiki MCP
unavailable in container, substituted per #121/#123) — and PARKED the 4 genuine
design forks (delivery channel / run-timing / det-vs-LLM split / review gate)
as DECISION-NEEDED rather than guessing them. No generator code (T5, R-phase).

- SSOT #124 ADAPT (CC /init, own-stack — reuse mechanism, build schema residue)
- SSOT #125 DEFER (ai-doc-gen + human-curation research finding)
- SSOT #126 DEFER (Repomix/gitingest/StackSync — own detector covers detection)
- SSOT #127 DEFER (Cursor generators — parallel-evolution, harness-specific)
- SSOT #128 REJECT (Aider repo-map — T16 name-trap, in-context ranking != gen)
- Plan: design/R-phase output, status blocked_external/manualReviewRequired.

Prior-art: prior-art-evaluations.md#124 (CC /init ADAPT, own-stack-first), #125 (ai-doc-gen DEFER), #126 (Repomix family DEFER), #127 (Cursor generators DEFER), #128 (Aider repo-map REJECT, T16 problem-class mismatch). New SSOT entries landed in this commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(aif-init-passport-gen): implement AI-driven passport generation (I-phase, GH #547 P1)

Deliver the aif-init I-phase: portable agents/aif-init.md agent +
deterministic detector/passport.ts + principle 23 (2-fixture acceptance test).

Design forks resolved with evidence-backed defaults (park-don't-guess R-phase
evidence → sensible-defaults in HANDOFF_MODE=1):
- Delivery channel: agents/aif-init.md (portable markdown, ships to consumer
  .claude/agents/ via install.sh glob — same path as existing review-sidecar.md)
- Run-timing: explicit post-install AI-session step (install has no AI; #548 seam)
- Det-vs-LLM split: thin deterministic detectPassportFields() core (all null-safe,
  tested on 2+ fixtures) + agent instructs LLM to fill prose (SSOT #125 empirical:
  deterministic-inspect-first then ground LLM in that evidence)
- Review gate: explicit DRAFT banner + required human edit before removing

Files:
- agents/aif-init.md: 5-step portable agent (detect → generate DESCRIPTION.md
  → generate ARCHITECTURE.md → write DRAFT → review gate). Ships to consumers.
- packages/core/detector/passport.ts: detectPassportFields() reads root +
  workspace package.jsons, maps deps to passport fields (framework/db/orm/
  observability/testRunner/mobile/uiLayer/dbSchemaPath). All-null on unknown.
- packages/core/detector/fixtures/hono-drizzle-monorepo/: Fixture A
  (apps/api workspace: Hono + Drizzle + pg + Honeycomb + Vitest)
- packages/core/detector/fixtures/nextjs-prisma-flat/: Fixture B
  (Next.js + Prisma + Vitest flat repo)
- packages/core/principles/23-aif-init-passport-gen.test.ts: principle 23,
  13 tests - no-placeholder assertion on both fixtures + T-Passport-A counter
  (different fixtures yield different stacks, proves detection is not hardcoded)
- install.sh: add agents/aif-init.md to SHIPPED_DOCS (count 18 to 19)
- 09-doc-authority-hierarchy.ts/.test.ts: add agents/aif-init.md to
  REQUIRED_HEADER_DOCS; update install count sentinel 18 to 19

Acceptance criteria met:
1. detectPassportFields on each fixture produces zero <...> placeholders, stack-correct
2. 2 differently-shaped fixtures proved (Hono+Drizzle monorepo vs Next.js+Prisma flat)
3. AI-agnostic: agents/aif-init.md runs on operator session only; degrades to
   template copy when no AI present (see Degradation section in agent)

Prior-art: prior-art-evaluations.md#124 (CC /init ADAPT - mechanism reused:
AI session reads repo, drafts, human curates; AIF passport schema is the only
build residue), prior-art-evaluations.md#126 (Repomix/StackSync DEFER - own-stack
detectPassportFields reuses readPkgDeps pattern from read-manifest.ts, no new dep).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(aif-init): remove Bash-tool mkdir from agent — Write creates parent dir automatically (rework)

The agent prompt at agents/aif-init.md:183 previously instructed the AI to
run `Bash: mkdir -p .ai-factory` before writing output files. The Write tool
creates parent directories automatically, so this Bash invocation is incorrect
and inconsistent with the declared tool list (Read, Glob, Write only).

Prior-art: skipped — refactor only, no new capability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
artyhoo added a commit that referenced this pull request Jul 24, 2026
…rktrees (#1123)

Every fresh aif task worktree was born with 60 modified files: `.claude/` is
copied from the base clone's WORKING TREE ~3.5s after `git worktree add`, and
that working tree was parked on a PR-#123 branch. So every aif worker executed
hooks, rules and settings.json ~1000 PRs stale regardless of how fresh the git
base was, and shipped leftover /tmp/hook-logger.sh instrumentation with them.

Decisive evidence: the fresh worktree reproduced the base clone's *uncommitted*
settings.json modification and did NOT match its HEAD object, so the copy source
is the working tree, not any git object.

This invalidates the causal claims (not the observations) of the two 2026-07-24
container probes: the gate they measured as SILENT was the pre-#1116 file.

Repaired host-side (base clone moved onto staging, local edits stashed by name).
Verified end-to-end on a live task: worktree now born with 1 untracked entry
instead of 60 modified, executed hook carries _emit_skip=3, debris gone.

The repair also exposed two bugs in the healer itself: its fast path compared
only the ref (so a parked working tree was certified "already current" every
run), and `git branch -f` is refused once the branch is checked out. Fixed and
live-tested in the operator-local copy; the shipped twin still carries both and
is dispatched as a follow-up kickoff.

Ships three dispatch-ready kickoffs: the tsx three-tier resolution fix (v2 —
v1's PATH-fallback premise was falsified by measurement), the container
gate-reachability audit, and the aif-doctor helper parity port.

Prior-art: skipped — research patch documenting an environment defect plus its
dispatch kickoffs, no new capability introduced.
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