Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions .claude/skills/git-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,23 @@ Resolve LifeSim User's Guide v1.0 Level 3 QC findings

## Branch Naming

Whether a PR gets a review lane is decided by **content**, not by branch name: a PR
that changes any file under `docs/` is a documentation PR; one that changes nothing
under `docs/` has no lane and no review stages.
An administrator assigns every PR a review lane using `/review classify`.
Changed content determines the appropriate classification; branch names are descriptive.

### Documentation branches (changes under `docs/`)

The prefix routes the PR to a review lane. Use the full two-segment prefix — a bare
`docs/{name}` does **not** match a lane and strands the PR in `stage:needs-lane`.
These prefixes describe intent and do not assign or advance a review lane.

- `docs/new/{slug}` — new document (Peer → Lead Civil → Technical edit → Director)
- `docs/new/{slug}` — new document (Peer → Lead Civil → Technical edit in the Content PR; separate Director review after draft merge)
- `docs/major/{slug}-v{X.0}` — major revision (Peer → Lead Civil → Technical edit)
- `docs/minor/{slug}-v{X.Y}` — minor revision (Peer → Technical edit)
- `docs/fix/{slug}` — editorial fix (no review; admin self-merge)
- `docs/dev/{slug}` — dev docs under `docs/dev/` (no review; admin self-merge)

### Non-documentation branches (components, plumbing, styling, scripts, CI)

No review lane, no review stages — `CI Build` is the only gate.
Administrators assign the `code` lane to changes without document edits. It has no
formal review stages, but both `CI Build` and `review-workflow` must pass before administrator merge.

- `feature/{descriptive-name}` — new components, new site capabilities, enhancements
- `fix/{descriptive-name}` — bug fixes in components, styles, scripts, build tooling
Expand All @@ -47,8 +46,8 @@ No review lane, no review stages — `CI Build` is the only gate.

Use `feature/` rather than `enhancement/`; older branches used the latter.

A PR that touches both site code and content under `docs/` is a documentation PR —
put it on the matching `docs/…` prefix.
A PR mixing document content and site code is a specialized administrator-classified
case. Authors should change only one document per PR; a branch prefix grants no exception.

## Pull Requests

Expand Down
14 changes: 11 additions & 3 deletions .claude/skills/new-doc/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ If the category IS `dev/`:

### 1f — Active / Draft Status

Ask: "Should this document be active (visible and clickable) or inactive (shows 'Coming Soon' badge)? (default: active)"

Record both `active` (true/false) and `draft` (inverse of active) values.
Ask whether the draft should be active after its Content PR merges. Record `active` independently and always start a new document with `draft: true`. The later Publication PR removes draft status after Director approval or waiver.

### 1g — File Structure (dev only)

Expand Down Expand Up @@ -393,3 +391,13 @@ Next steps:
- Add chapter files (02-*.mdx, 03-*.mdx, etc.)
- Run `npm start` to preview locally
```

## Step 9: Prepare review

Use a descriptive `docs/new/<slug>` branch. The prefix suggests intent; it does not assign review state. Keep the author PR to one document and directly related source, assets, registrations, and site changes. After the Content PR opens, an administrator records:

```text
/review classify new <doc_location>
```

The Content PR requires peer, Lead Civil, and manually initiated technical editing. It merges and deploys from `main` as an active draft before an administrator starts the separate Director Review PR. Do not remove `draft: true` in the Content PR and do not deploy the author branch.
14 changes: 11 additions & 3 deletions .claude/skills/new-revision/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ The corresponding value in the JSON is the `currentVersion` (e.g., `v1.0`).

Ask: "Is this a major revision or a minor revision?"

- **Major revision** — substantial changes warranting a new major version. Branch prefix: `docs/major/`. Goes through Lane 2 (Peer → Lead Civil → Technical edit). No Director review.
- **Minor revision** — smaller updates warranting a minor version bump. Branch prefix: `docs/minor/`. Goes through Lane 3 (Peer → Technical edit). No Director review.
- **Major revision** — substantial changes warranting a new major version. Descriptive branch prefix: `docs/major/`. Requires Peer → Lead Civil → Technical edit. No Director review.
- **Minor revision** — smaller updates warranting a minor version bump. Descriptive branch prefix: `docs/minor/`. Requires Peer → Technical edit. No Director review.

### 1c — New version number

Expand Down Expand Up @@ -161,5 +161,13 @@ Next steps:
1. Edit the new version's MDX files to make your changes
2. Update 00-version-history.mdx with a real description and your name
3. Run `npm start` to preview locally
4. When ready, commit and open a PR (the workflow will detect the branch prefix and start {Lane 2: Peer → Lead Civil | Lane 3: Peer review} automatically)
4. When ready, commit and open one PR for this document
```

After the PR opens, an administrator records the authoritative classification:

```text
/review classify <major|minor> <doc_location>
```

The branch prefix is descriptive and does not assign review state. The administrator assigns one named reviewer per human stage. Technical editing is manually initiated and reviews the changed content with enough surrounding context to assess it. Production builds only from administrator-merged `main`; do not deploy the revision branch.
14 changes: 7 additions & 7 deletions .claude/skills/pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ Read `.claude/skills/git-conventions.md` for PR conventions.
- Derived from the **overall purpose** of all commits on the branch, not just the latest commit
- Example: "Redesign homepage with product tile grid layout"

### Body — choose the format based on the branch prefix
### Body — choose the format based on the change

**If the current branch starts with `docs/`** → use the **Template Style** (Step 5a). The repo's PR template at `.github/pull_request_template.md` contains a checklist for document authors, including the Lane 1 "Technical edit comments addressed" checkbox that the stage-progression workflow watches for. Passing `--body` to `gh pr create` overrides the template entirely, so the skill must reproduce the template structure with the auto-generated content filled in.
**If the change affects a document** → use the **Template Style** (Step 5a). Reproduce the repository template when passing `--body`, including the one-document scope, `doc_location`, related issues, validation, and review notes. Branch prefixes describe intent; an administrator's controller classification is authoritative.

**Otherwise (infrastructure, tooling, dependency, or any non-doc branch)** → use the **Summary Style** (Step 5b). These PRs are silently ignored by the review workflow and don't need the doc-author checklist.
**Otherwise (infrastructure, tooling, dependency, or any non-doc branch)** → use the **Summary Style** (Step 5b). These PRs still require administrator classification as `code`, the review-workflow gate, and CI; they do not require formal document-review stages.

In both styles, the summary content should be based on **ALL** commits on the branch, not just the most recent one. Read through all the commit messages and the diff to understand the full scope. If `$ARGUMENTS` was provided, use it to focus the title and description.

Expand All @@ -87,12 +87,12 @@ In both styles, the summary content should be based on **ALL** commits on the br
3. Compute the list of affected MDX documents: from `git diff --name-only main...HEAD`, keep entries matching `docs/**/*.mdx`. If the base is not `main`, use that instead.
4. Build the PR body by transforming the template:
- Under `## Description`, replace the `<!-- Briefly describe what this PR does and why. -->` comment with the summary bullets.
- Under `## Affected documents`, replace the bare `- ` line with the list of affected MDX files. Format each as a markdown link relative to the repo root: `- [filename.mdx](docs/full/path/filename.mdx)`. If there are no changed MDX files, write `- _No MDX files changed in this PR._`
- Under `## Document scope`, identify the single document and its `doc_location`. List affected MDX files when useful. For an administrator infrastructure overhaul spanning guides, explicitly describe that scope instead of presenting it as a routine one-document author PR.
- Leave the `## Related issue(s)` section's comment placeholder unchanged so the author can fill it in.
- Leave **all checklist items unchecked**, including the Lane 1 Technical edit checkbox. The author checks them as they complete each item; the workflow specifically depends on the Technical edit checkbox being present and unchecked at PR open time.
- Leave the `## Notes for reviewers` comment placeholder unchanged.
- Mark validation items only when evidence supports them. Do not add a technical-edit advancement checkbox or manually request stage reviewers.
- Under `## Review notes`, include any relevant activation requirements or reviewer context.

The result should be a complete copy of the template with the Description and Affected documents sections populated.
The result should follow the current template with its Description and Document scope sections populated.

### Step 5b: Summary Style (for non-`docs/` branches)

Expand Down
6 changes: 4 additions & 2 deletions .claude/skills/technical-edit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ Tell the user:
- How many files were reviewed
- Which review prompt version was used
- Remind the author to check the "Technical edit comments addressed" checkbox in the PR description when they're done addressing comments
- Remind the author to reply to threads from the **Files changed** tab using **Start a review**, then submit once. Replying from the Conversation tab files each reply as its own standalone review and emails every PR subscriber separately.
- Suggest batching related replies from **Files changed** with **Start a review** to reduce separate submissions and notification noise. Do not promise an exact email count.

Note that step 4 posts a single bundled review on purpose: one `POST /pulls/:pr/reviews` call with every comment in the `comments` array produces one notification. Never loop over `POST /pulls/:pr/comments` — that creates one standalone review per comment and floods every subscriber.
Step 4 posts one bundled review so findings arrive coherently and avoid unnecessary separate notifications. Native GitHub delivery still depends on each user's settings.

For a new document, review the full document. For a major or minor revision, review changed content with enough surrounding context to assess it. Completion is explicit: after the edit finishes, an administrator records `/review complete editor`. Author replies and thread resolution are not stage gates.
35 changes: 12 additions & 23 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
## Description

<!-- Briefly describe what this PR does and why. -->
<!-- Describe what this PR changes and why. -->

## Affected documents
## Document scope

<!-- List the documents this PR changes. Write "None — non-documentation change"
for component, styling, script, workflow, or other site-plumbing work. -->
<!-- Name the one document changed by this author PR, or write "None — site/code change." Related source, assets, registry, and site changes may be included. -->

-
- Document:
- Document location (`doc_location`, or `-`):

## Related issue(s)

<!-- Link related issues. Use "Closes #N" to auto-close on merge. -->
<!-- Use "Closes #N" when appropriate. -->

## Pre-submission checklist
## Validation

- [ ] I have previewed these changes locally or via the PR preview URL
- [ ] My branch name uses an expected prefix — documentation: `docs/new/`, `docs/major/`, `docs/minor/`, `docs/fix/`, `docs/dev/`; everything else: `feature/`, `fix/`, `chore/`, `ci/`
- [ ] I have updated `00-version-history.mdx` if this change warrants a version entry
- [ ] I have assigned a specific peer reviewer via the Reviewers sidebar (if known)
- [ ] I previewed the change locally or through the PR preview
- [ ] I ran the checks appropriate to this change
- [ ] I updated version history when the document revision warrants it

## Technical edit (Lanes 1, 2, and 3)
## Review notes

<!-- Check the box below only after every technical edit comment has been addressed.
Lane 1 (new document) then advances to Director review.
Lanes 2 and 3 (major/minor revision) advance straight to ready-to-merge —
neither lane includes a Director review.
Non-documentation PRs can ignore this section entirely. -->

- [ ] Technical edit comments addressed

## Notes for reviewers

<!-- Anything reviewers should know. -->
<!-- Call out areas that need attention. The administrator records classification and assignments with /review commands after the PR opens. Authors do not advance stages by editing this template. -->
105 changes: 55 additions & 50 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
@@ -1,65 +1,70 @@
name: CI Build

run-name: 'Validate PR #${{ github.event.pull_request.number || inputs.pr }} at ${{ github.event.pull_request.head.sha || inputs.sha }}'
on:
pull_request:
types: [opened, synchronize, reopened]

workflow_dispatch:
inputs:
pr:
description: 'PR number to validate (used by review automation)'
required: true
type: string
sha:
description: 'Exact PR head revision to validate'
required: true
type: string
permissions:
contents: read
pull-requests: write
statuses: write

pull-requests: read
concurrency:
group: ci-${{ github.event.pull_request.number || inputs.pr }}
cancel-in-progress: true
jobs:
build:
name: CI Build
name: Build preview artifact
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- name: Resolve PR
id: pr
uses: actions/github-script@v7
with:
script: |
const n = context.payload.pull_request?.number || Number(context.payload.inputs?.pr);
if (!Number.isSafeInteger(n) || n < 1) throw new Error('Invalid PR number');
if (context.eventName === 'workflow_dispatch' && context.ref !== 'refs/heads/main') throw new Error('Dispatch from main only');
const {data: pr} = await github.rest.pulls.get({...context.repo, pull_number:n});
if (pr.state !== 'open') throw new Error('PR is closed');
const expected = context.payload.pull_request?.head.sha || context.payload.inputs?.sha;
if (expected !== pr.head.sha) throw new Error('PR changed before this build started; build the latest revision');
core.setOutput('number', String(n));
core.setOutput('sha', pr.head.sha);
core.setOutput('repository', pr.head.repo.full_name);
- uses: actions/checkout@v4
with:
repository: ${{ steps.pr.outputs.repository }}
ref: ${{ steps.pr.outputs.sha }}
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
node-version: '22'
cache: npm
- run: npm ci
- run: npm run build
- name: Signal admin-may-merge for non-docs PRs
if: success()
uses: actions/github-script@v7
- run: npm run test:review --if-present
- name: Build preview
run: npm run build
env:
DOCUSAURUS_URL: https://usace-rmc.github.io
DOCUSAURUS_BASE_URL: /RMC-Software-Documentation-Previews/pr-${{ steps.pr.outputs.number }}/
DOCUSAURUS_IS_PREVIEW: 'true'
- uses: actions/upload-artifact@v4
with:
script: |
const prNumber = context.payload.pull_request.number;
const files = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
per_page: 100,
});
// Branch naming for this path is conventional, not enforced:
// feature/, fix/, chore/, ci/. What actually decides the lane is
// content -- a PR touching nothing under docs/ has no review lane
// and needs only this build to pass.
const touchesDocs = files.some(f => f.filename.startsWith('docs/'));
if (touchesDocs) return; // docs PRs are handled by stage-progression.yml

// Flip the review-workflow commit status to success so branch
// protection allows merge. This is the non-docs counterpart to
// stage-progression.yml's status-setting for docs PRs.
const headSha = context.payload.pull_request.head.sha;
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: headSha,
state: 'success',
context: 'review-workflow',
description: 'No doc changes — admin may merge',
});

const marker = '<!-- ci-admin-merge-bot-comment -->';
const sha = headSha.substring(0, 7);
const body = `${marker}\n\n✅ **CI build passed** for commit \`${sha}\`\n\nThis PR changes no files under \`docs/\`, so it carries no review lane. **CI Build is the only gate** - there are no review stages to clear.\n\n@usace-rmc/docs-admin may merge.`;
const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber });
const existing = comments.data.find(c => c.user.type === 'Bot' && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existing.id, body });
} else {
await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: prNumber, body });
}
name: preview-${{ steps.pr.outputs.number }}-${{ steps.pr.outputs.sha }}
path: build/
if-no-files-found: error
retention-days: 7
outputs:
pr: ${{ steps.pr.outputs.number }}
sha: ${{ steps.pr.outputs.sha }}
16 changes: 9 additions & 7 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@ on:
- 'package.json'
- 'package-lock.json'
- 'scripts/**'
- '.github/workflows/deploy.yml'
workflow_dispatch:
inputs:
ref:
description: 'Branch or ref to deploy (leave blank for main)'
required: false
type: string

permissions:
contents: read
Expand All @@ -32,13 +28,19 @@ jobs:
build:
name: Build site
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Require main
if: github.ref != 'refs/heads/main'
run: echo 'Production builds must run from main.' >&2; exit 1
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref || github.ref }}
ref: ${{ github.sha }}
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '22'
cache: 'npm'
- run: npm ci
- run: npm run build
Expand Down
Loading
Loading