Skip to content

feat(gate): docs-system input + docs-gate lane + fragment example cleanup#105

Merged
ArchonVII merged 5 commits into
mainfrom
agent/claude/104-docs-gate
Jul 4, 2026
Merged

feat(gate): docs-system input + docs-gate lane + fragment example cleanup#105
ArchonVII merged 5 commits into
mainfrom
agent/claude/104-docs-gate

Conversation

@ArchonVII

@ArchonVII ArchonVII commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • repo-required-gate.yml gains an opt-in docs-system boolean input (default false, same opt-in pattern as stack). When true, a new docs-gate job runs on pull_request events after detect, in the consumer checkout: npm run docs:render -- --check (fails on stale committed rendered blocks) and node scripts/doc-health/health.mjs --repo . --changed-from origin/<base> --json (fails on blocking doc-health findings). The checkout uses fetch-depth: 0 so health.mjs can resolve the merge base with the PR base branch; the base ref is passed through an env var, not shell interpolation.
  • decision aggregates the docs gate exactly like every other optional lane: RUN_DOCS_GATE: ${{ inputs.docs-system }} guarded by the same EVENT_NAME = pull_request check that pr-contract uses. Skipped is NOT failed for non-opted consumers, and opted-in consumers stay green on push/merge_group runs where the PR-only job skips.
  • The job's if: conditions on the input directly, not on a detect output: a caller whose workflow-library-ref lags this workflow body would import a classifier without run-docs-gate, and the empty-string comparison would silently no-op the gate for an opted-in consumer. scripts/classify-pr.mjs still threads docsSystem through to a run-docs-gate detect output and the jobsRequired/jobsSkipped lane summary, so the Actions UI reports the gate honestly. It rides along every PR lane including docs-only — doc drift is precisely a docs-only concern — and stays decoupled from pr-contract (the archon#200 decoupling shape test now covers docs-gate too).
  • Guidance cleanup: examples/changelog-fragment.yml and examples/repo-update-log-fragment.yml are retired so new-workflow guidance no longer points agents at fragment callers. The reusable workflow bodies stay — existing consumers still call them; the installed-baseline/registry migration belongs to the later S3/C1/T1 cleanup. README inventory cells updated and a shape test locks in stubs-gone / bodies-present.

Sequencing (issue #104 item 3 is explicitly OUT of this PR): the repo-template caller flip to docs-system: true and its live-red scratch-branch proof must wait until this PR merges AND the owner advances the v1 tag — repo-template pins @v1, and the retag ships the gate fleet-wide, so it stays owner-deferred. Follow-up tracked in ArchonVII/repo-template#124 (P1 lane).

Verification

  • TDD RED then GREEN on the two touched suites: the 12 new assertions (6 classifier, 6 workflow-shape) failed before implementation and passed after.

    command: npx vitest run scripts/classify-pr.test.mjs scripts/workflow-structure.test.mjs
    location: local
    result: RED pre-implementation 12 failed | 67 passed; GREEN post-implementation 79/79 passed
    timestamp: 2026-07-04T11:00-05:00
    
  • Full suite on the lane worktree, all files: 9 test files, 179/179 passing (origin/main baseline was 168; net +11 covering input default, docs-gate decision aggregation, opt-in condition, detect output, decoupling, classifier threading, and retired-example lock-in).

    command: npm test
    location: local
    result: 9 test files passed, 179/179 tests passed (vitest 4.1.7)
    timestamp: 2026-07-04T11:02-05:00
    
  • actionlint on the touched workflow YAML reported no findings.

    command: actionlint .github/workflows/repo-required-gate.yml examples/repo-required-gate.yml
    location: local
    result: exit 0, no findings (actionlint 1.7.7 binary)
    timestamp: 2026-07-04T11:01-05:00
    
  • Adversarial-review mutation gap closed (commit 3ea0c30): deleting the detect job's docsSystem: process.env.DOCS_SYSTEM === 'true' classifier argument previously left all 179 tests green while run-docs-gate silently became 'false' for opted-in consumers (lane summary would report the gate as skipped; enforcement unaffected since the job if: and decision read inputs.docs-system directly). A substring assertion in the docs-gate detect-output test now pins the env -> classifyPR hand-off.

    command: npm test  (run against baseline, mutated, and restored worktree states)
    location: local
    result: baseline 179/179 green; plumb line deleted + new assertion -> 1 failed | 178 passed; workflow restored -> 179/179 green
    timestamp: 2026-07-04T11:19-05:00
    
  • git diff --check exited 0 before each commit (no whitespace errors introduced).

    command: git diff --check origin/main...HEAD
    location: local
    result: exit 0 across all 4 lane commits (no whitespace errors)
    timestamp: 2026-07-04T11:22-05:00
    

Verification Notes

Consumer-side command contract was verified against repo-template origin/main (57d6381): the docs:render npm script exists (scripts/docs/render.mjs), and scripts/doc-health/health.mjs accepts --repo/--changed-from/--json, setting exit code 1 on blocking findings (the L2 contract) and 0 on clean/warnings-only runs. The skipped-is-not-failed invariant is asserted by the new decision-aggregation shape test (RUN_DOCS_GATE env plus the EVENT_NAME = pull_request bash guard), and the lane-decoupling loop test now includes docs-gate so it can never silently gain a pr-contract dependency. This PR cannot exercise the new gate end-to-end in its own CI — this repo's PR CI is the vitest self-test, and the reusable body only runs in consumer context — so the end-to-end live-red proof is deliberately scheduled for the repo-template caller PR after the owner v1 retag, per the sequencing note in the Summary.

Docs / Changelog

  • .changelog/unreleased/104-docs-gate.md fragment added.
  • docs/repo-update-log.md entry appended (2026-07-04) with propagation recorded as pending: owner @v1 retag, then the repo-template caller flip + live-red proof, then the archon-setup snapshot refresh that picks up the retired example stubs.
  • README workflow-inventory caller cells for the two retired examples reworded (reusable bodies stay listed); examples/repo-required-gate.yml now documents the docs-system opt-in block.

Plan/status artifacts: none were created or used by this lane; the living tracker is ArchonVII/repo-template#124 (P1 row), and issue #104's remaining acceptance boxes (rt live-red proof, @v1 retag) are owner/merge-gated follow-ups by design.

Owner decisions this lane: none

Linked Issue

Closes #104

Refs ArchonVII/repo-template#124

Risks

ArchonVII and others added 4 commits July 4, 2026 11:01
New reusable boolean input docs-system (default false, same opt-in
pattern as stack). When true, a docs-gate job runs on pull_request
events after detect in the consumer checkout: npm run docs:render --
--check (rendered-block drift) and node scripts/doc-health/health.mjs
--repo . --changed-from origin/<base> --json (blocking findings; the
checkout uses fetch-depth: 0 to reach the merge base).

The job conditions on the input directly, not on a detect output, so a
caller whose workflow-library-ref lags this body cannot silently no-op
the gate. decision aggregates it like every other optional lane —
skipped is not failed for non-opted consumers, and the require_success
call carries the same pull_request event guard as pr-contract so
opted-in consumers stay green on push/merge_group runs. classify-pr.mjs
threads docsSystem through to a run-docs-gate output and the lane
summary (docs-gate rides along every PR lane incl. docs-only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b2W87gyzLPaHBbpuU9Zxt
Drop examples/changelog-fragment.yml and
examples/repo-update-log-fragment.yml so new-workflow guidance no
longer points agents at fragment callers. Guidance cleanup only: the
reusable workflow bodies stay because existing consumers still call
them; the installed-baseline/registry migration belongs to the later
S3/C1/T1 cleanup. README inventory rows keep the reusable bodies and
mark the example cells retired; a shape test now locks in stubs-gone /
bodies-present.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b2W87gyzLPaHBbpuU9Zxt
Adversarial review (mutation testing) found the one docs-gate wire with
no failing test: deleting the detect job's
`docsSystem: process.env.DOCS_SYSTEM === 'true'` classifier argument
left all 179 tests green while run-docs-gate silently became 'false'
for opted-in consumers, making the lane summary report docs-gate as
skipped even though decision (which reads inputs.docs-system directly)
still requires it. Pin the env -> classifyPR hand-off with a substring
assertion; verified the mutation now fails 1/179 and the restored
workflow passes 179/179.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019b2W87gyzLPaHBbpuU9Zxt
@ArchonVII
ArchonVII marked this pull request as ready for review July 4, 2026 16:22
@ArchonVII

Copy link
Copy Markdown
Owner Author

Adversarial review dispositions (fixer/promoter pass)

One finding adjudicated for this lane:

1. [P3] test-coverage — detect-job docsSystem plumb line had no mutation-catching test — FIXED in 3ea0c30.

Independently re-verified before fixing: deleting docsSystem: process.env.DOCS_SYSTEM === 'true', from the detect job's classifyPR call left the full suite green at 179/179 — the docs-gate detect-output test asserted the DOCS_SYSTEM env line, the run-docs-gate outputs mapping, and the core.setOutput line, but not the env -> classifier argument hand-off between them. With that wire gone, run-docs-gate is silently 'false' for opted-in consumers and the lane summary reports docs-gate as skipped while decision still requires it (enforcement itself is unaffected by design: the job if: and RUN_DOCS_GATE read inputs.docs-system directly).

Fix (test-first): added the pinning substring assertion to scripts/workflow-structure.test.mjs while the mutation was in place — new assertion failed 1/179 against the mutated workflow, then passed 179/179 once the workflow line was restored byte-identical. CI re-green after push: vitest pass (https://github.com/ArchonVII/github-workflows/actions/runs/28712259435/job/85147606106).

No other findings were raised; the review confirmed all six enforcement-path mutations (default-flip, decision ignoring the lane result, job-if/RUN-flag source flips, example resurrection, classifier lane wiring) are each caught by exactly one failing test, and the consumer commands match the real repo-template producers. Review threads checked via GraphQL before and after the push: none present.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3ea0c30cd8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/repo-required-gate.yml
The docs-gate "Detect package manager" step fell through to `npm ci` whenever
no pnpm/yarn lockfile was present. `npm ci` REQUIRES a package-lock.json and
hard-fails without one, so an opted-in docs-system consumer that ships
package.json + docs scripts but no committed lockfile would go red before
either docs check ran.

Add the same fallback the shared node-ci.yml already uses: `npm ci` only when
package-lock.json exists, else `npm install --no-package-lock`. actionlint
exit 0; vitest 179/179.

Resolves the PR #105 review thread (no-lockfile docs consumers).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Eiuy6Jd6Pf372zhG2od66m
@ArchonVII
ArchonVII merged commit adb9df4 into main Jul 4, 2026
1 check passed
@ArchonVII
ArchonVII deleted the agent/claude/104-docs-gate branch July 4, 2026 18:19
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.

repo-required-gate: docs-gate lane (docs:render --check + doc-health blocking subset) + fragment example cleanup

1 participant