Status: Design approved, pending implementation Parent: CWS-81 Date: 2026-03-22 Linear: CWS-94
The PR workflow scripts (create-pr.sh, finalize-merge.sh) and the rollout governance CI
check were built for a single-branch, phase-based, gh-always-works model. CWS-93 removed
phase rollout support from the validator and active-plan.yaml, but left the scripts and CI
workflow referencing the removed phase_branch_pattern. Both make create-pr and
make finalize-merge are broken TODAY — the scripts require phase_branch_pattern from
active-plan.yaml but it was already removed. Additionally:
rollout-governance CI check (PR #46 blocked).gh CLI fails in Claude Code sandbox (TLS cert issue), with no fallback.finalize-merge.sh requires interactive confirmation, blocking agent execution.run-codex-checks.sh uses backtick shell interpolation (semgrep risk).docs/agent-context.md fresh after merges.repo-flow skill does not reflect the current workflow.actions/checkout@v4).Add exempt_branch_patterns list to active-plan.yaml. The validator skips branch-name
validation for branches matching any exempt pattern but still validates plan structure.
exempt_branch_patterns:
- '^dependabot/'
- '^renovate/'
- '^gh-pages$'
Remove phase_branch_pattern references from create-pr.sh and finalize-merge.sh.
Remove phase-specific gating (prior-phase-merged checks). Simplify both scripts to
task-branch-only mode.
gh CLI with curl fallbackNote: gh and gt are in the Claude Code sandbox allowlist, so gh should work
in most agent sessions. The curl fallback exists for CI environments where gh is
not installed, or environments where gh auth is not configured.
Both scripts attempt gh first. If gh fails (auth check or command execution), fall
back to curl + GitHub REST API. Token resolution order: (1) GITHUB_TOKEN env var,
(2) gh auth token output, (3) fail with clear error. Extract the fallback logic into
scripts/lib/github-api.sh as shared functions:
github_api_get <endpoint> — GET with authgithub_api_post <endpoint> <json_body> — POST/PATCH with authgh_or_curl_pr_view <branch> — view PR detailsgh_or_curl_pr_create <base> <head> <title> <body> — create PRgh_or_curl_pr_edit <pr> <title> <body> — edit PR metadatagh_or_curl_pr_merge <pr> <method> — merge PRfinalize-merge.sh accepts --yes or --no-interactive flag. When set, skip the
read -r confirm prompt and proceed directly. The flag is also honored by
make finalize-merge PR=... YES=1.
finalize-merge.sh detects Graphite stacks via gt log --stack. When a stack is
detected and --stack flag is passed:
gt merge for full-stack merge (preferred path)gt merge failsSingle-PR merge remains the default (no --stack flag).
Replace the hardcoded “Standardize the change…” body with dynamic content that
respects .github/pull_request_template.md for ALL PRs — single or stacked.
The template defines the canonical PR body structure; create-pr.sh must populate
its sections programmatically rather than bypassing it.
Generated body sections (mapped to template):
git log --oneline base..HEAD)cws/<id>-<slug>)make qa-local (pre-filled)For stacked PRs (gt submit --stack), the same template sections apply to each PR
in the stack. Graphite’s --no-interactive mode replaces the template body with
whatever create-pr.sh generates, so the script must produce template-compliant output.
Post-merge refresh (in finalize-merge.sh):
After successful merge, update the “Stale After” timestamp in docs/agent-context.md
to now + 24 hours. This is a mechanical timestamp bump, not a full content refresh.
Commit the update as part of the merge flow if on main.
Session-start staleness warning (Claude Code hook):
Add a SessionStart hook that reads the “Stale After” timestamp from
docs/agent-context.md and emits a warning if current time exceeds it. The hook
does NOT auto-refresh — it warns the agent to perform a Linear sync before executing.
Implementation: shell script at .claude/hooks/check-agent-context-staleness.sh that
parses the timestamp and outputs a warning message. Registered in
.claude/settings.json under hooks.SessionStart with matcher startup|resume|compact.
Must fail-closed (exit 2 on error, never fail-open).
codex → agent-agnostic renamingAs we modify files in this task, rename Codex-specific nomenclature:
run-codex-checks.sh → run-workflow-checks.shcodex-check → workflow-checkcodex → workflow or neutral terms.codex/ directory itself (larger change, separate ticket)Update .agents/skills/repo-flow/SKILL.md to:
make start-work → branch → commit →
make create-pr → CI → make finalize-mergegt create → gt submit --stack → gt mergecurl fallback: when and how to use it--yes flag for agent contextsfilePattern and bashPattern trigger on all workflow scripts
and git operations so agents automatically pick up the skillrun-workflow-checks.sh backtick interpolationReplace backtick git command interpolation with Open3.capture2 or IO.popen in the
inline Ruby within run-workflow-checks.sh (the backtick-interpolated git commands in
the governance change detection block). This prevents semgrep from flagging the file on
future edits.
Bump actions/checkout from @v4 to @v6 (latest as of March 2026, see
https://github.com/actions/checkout/releases/tag/v6.0.2) across all workflow files.
This resolves the Node.js 20 deprecation warning on PR #46.
.codex/ directory rename (separate, larger migration)start-phase.sh script (phase workflow deprecated, script can be removed later)create-pr.sh stack iteration (Graphite handles multi-branch submission via
gt submit --stack; create-pr.sh normalizes metadata for current branch only).codex/rollout/active-plan.yaml (add exempt_branch_patterns)scripts/validate-rollout-governance.rb (handle exempt patterns)scripts/tests/rollout_governance_test.rb (add exempt pattern tests)scripts/run-codex-checks.sh → scripts/run-workflow-checks.shscripts/run-workflow-checks.sh (remove phase refs, fix backticks, update
self-referencing target check from codex-check to workflow-check, update governance
change detection regex from run-codex-checks to run-workflow-checks)scripts/create-pr.sh (remove phase logic)scripts/finalize-merge.sh (remove phase logic)scripts/tests/finalize_merge_workflow_test.rb (remove phase pattern assertions)scripts/tests/repo_ruby_activation_test.rb (update CODEX_CHECK_PATH constant)Makefile (rename codex-check target to workflow-check).github/workflows/rollout-governance.yml (update script ref)scripts/run-local-qa.sh (update make codex-check to make workflow-check)scripts/site-audit.sh (update codex-check target validation).codex/docs/tooling.md (update codex-check references).codex/docs/multi-agent-orchestration.md (update codex-check references).codex/docs/multi-agent-rollout-checklist.md (update codex-check references).codex/rollout/evidence/cws-94-phase-removal-governance-fix.mdscripts/lib/github-api.sh (shared gh/curl fallback functions)scripts/create-pr.sh (use fallback lib, dynamic PR body)scripts/finalize-merge.sh (use fallback lib, --yes flag, --stack flag)Makefile (add YES=1 and STACK=1 variables)scripts/tests/rollout_governance_test.rb (if governance changes needed).codex/rollout/evidence/cws-94-fallback-and-flags.md.claude/hooks/check-agent-context-staleness.sh (SessionStart hook)scripts/finalize-merge.sh (post-merge staleness timestamp bump).agents/skills/repo-flow/SKILL.md (full rewrite of workflow docs).agents/skills/repo-flow/references/branch-pr-merge.md (update).codex/rollout/evidence/cws-94-staleness-and-skill.mddocs/tasks/CWS-94.md (task file)make qa-local passes on each PRmake workflow-check (renamed target) passesmake create-pr and make finalize-merge PR=... YES=1 work end-to-endfinalize-merge.sh --stack --yes works with Graphite stackscurl fallback token availability: In CI, GITHUB_TOKEN is available. In Claude
Code sandbox, gh auth token works. If neither is available, scripts fail with a clear
error rather than silently degrading.gt merge requires Graphite. If not installed, fall back
to individual PR merges. Scripts already check command -v gt.run-workflow-checks.sh inline Ruby uses backticks for
git commands. Must replace with Open3.capture2 or IO.popen to pass semgrep.