Files
msd-core/gsd-core/workflows/inbox.md
Tom Boucher b6e6a22fce fix(#2402): honor response_language across orchestrator output + UAT checkpoint renderer (#2457)
* fix(#2402): honor response_language across orchestrator output + UAT checkpoint renderer

Replays the in-flight bot branch fix/2402-response-language-orchestrator-coverage
(seven commits, never pushed) onto current origin/next as a single squashed commit.
The original work was substantial and correct; this commit preserves its full scope,
trimmed where rebase conflicts + workflow size budgets required it.

Three independent layers where response_language was being dropped are closed:

Layer 1 — orchestrator-facing directives across workflows. Adds the strong
"All user-facing output in this workflow MUST be presented in {response_language};
technical terms, code, paths, and subagent prompts stay in English" directive
to ~40 workflows that previously either lacked it entirely (verify-work,
new-project, new-milestone, quick, manager, and ~35 more) or carried only
the weak subagent-prompt-only form (plan-phase, execute-phase). The directive
covers narration between tool calls and banner output, not just the
AskUserQuestion prompts.

Layer 2 — UAT checkpoint renderer (src/uat.cts). buildCheckpoint now accepts
an optional responseLanguage parameter and renders the frame strings
("CHECKPOINT: Verification Required", "Type `pass` or describe what's wrong.")
in any of 9 languages (English/Spanish/French/German/Portuguese/Japanese/
Chinese/Korean/Italian) with an alias table covering ~30 input variants
(en, es, español, ja, 日本語, etc.). cmdRenderCheckpoint reads
config.response_language via loadConfig(cwd) and passes it through, so the
byte-for-byte block verify-work.md reprints verbatim is already localized
when written — preserving the anti-injection hygiene rule at verify-work.md
(the model is forbidden to translate after the fact). CJK display width is
computed by East Asian Width property ranges (W/F) so the right ║ border of
the banner stays aligned for full-width characters. English fallback is
byte-identical to the pre-fix behavior when response_language is unset or
unrecognized.

Layer 3 — literal English report templates in execute-phase. The top-of-
workflow directive covers all template sites (templates are a structural
source, not literal output). Inline render-language notes that previously
sat at each template site were removed during the squash because they
pushed execute-phase.md over its frozen pre-phase-6 byte ceiling
(93600 — ADR-857 Phase 6 capstone). The single top directive covers the
same surface with fewer bytes.

Also extends src/docs.cts and src/init.cts to propagate response_language
into the init JSON bundle of the additional workflows so the directive can
read it.

Tests added:
- tests/uat.test.cjs: buildCheckpoint with unset/unrecognized language falls
  back to English default; recognized language swaps only the two frame
  strings while structural lines stay untouched; CJK display-width regression
  (independent recomputation of East Asian Width W/F ranges).
- tests/workspace.test.cjs, tests/docs-update.test.cjs: response_language
  wiring through docs.cts/init.cts.

References: #2402; reporter's three-layer triage + Layer-4 follow-up; the
byte-for-byte anti-injection hygiene rule at verify-work.md (the reason
Layer 2 must be renderer-side, not model-translated).

This is a squash of the in-flight bot branch — seven commits representing
the original implementation plus its subsequent fix/CJK-padding/test/
changeset/regen cycles, none of which were ever pushed or PR'd. The squash
captures the final coherent state.

* chore(#2402): backfill pr:2457 in .changeset/2402-response-language-orchestrator-coverage.md

* chore(#2402): regen golden + size baseline after rebase against #2315 (PR #2451)

Rebase conflicts were entirely in generated artifacts (golden-install-parity
fixtures + workflow-size-baseline.json). After taking theirs during rebase,
regenerated cleanly against the merged source tree.
2026-07-20 14:22:27 -04:00

19 KiB

Triage and review all open GitHub issues and PRs against project contribution templates. Produces a structured report showing compliance status for each item, flags missing required fields, identifies label gaps, and optionally takes action (label, comment, close).

<required_reading> Before starting, read these project files to understand the review criteria:

  • .github/ISSUE_TEMPLATE/feature_request.yml — required fields for feature issues
  • .github/ISSUE_TEMPLATE/enhancement.yml — required fields for enhancement issues
  • .github/ISSUE_TEMPLATE/chore.yml — required fields for chore issues
  • .github/ISSUE_TEMPLATE/bug_report.yml — required fields for bug reports
  • .github/PULL_REQUEST_TEMPLATE/feature.md — required checklist for feature PRs
  • .github/PULL_REQUEST_TEMPLATE/enhancement.md — required checklist for enhancement PRs
  • .github/PULL_REQUEST_TEMPLATE/fix.md — required checklist for fix PRs
  • CONTRIBUTING.md — the issue-first rule and approval gates </required_reading>
```bash _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi RESPONSE_LANGUAGE=$(gsd_run query config-get response_language --default "" 2>/dev/null || echo "") ```

If response_language is set: All user-facing questions, prompts, and explanations in this workflow MUST be presented in {response_language}. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.

Verify prerequisites:
  1. gh CLI available and authenticated?

    which gh && gh auth status 2>&1
    

    If not available: print setup instructions and exit.

  2. Detect repository: If --repo flag provided, use that. Otherwise:

    gh repo view --json nameWithOwner -q '.nameWithOwner' 2>/dev/null
    

    If no repo detected: error — must be in a git repo with a GitHub remote.

  3. Parse flags:

    • --issues → set REVIEW_ISSUES=true, REVIEW_PRS=false
    • --prs → set REVIEW_ISSUES=false, REVIEW_PRS=true
    • --label → set AUTO_LABEL=true
    • --close-incomplete → set AUTO_CLOSE=true
    • Default (no flags): review both issues and PRs, report only (no auto-actions)
Skip if REVIEW_ISSUES=false.

Fetch all open issues:

gh issue list --state open --json number,title,labels,body,author,createdAt,updatedAt --limit 100

For each issue, classify by labels and body content:

Label/Pattern Type Template
feature-request Feature feature_request.yml
enhancement Enhancement enhancement.yml
bug Bug bug_report.yml
type: chore Chore chore.yml
No matching label Unknown Flag for manual triage

If an issue has no type label, attempt to classify from the body content:

  • Contains "### Feature name" → likely Feature
  • Contains "### What existing feature" → likely Enhancement
  • Contains "### What happened?" → likely Bug
  • Contains "### What is the maintenance task?" → likely Chore
  • Cannot determine → mark as needs-triage
Skip if REVIEW_ISSUES=false.

For each classified issue, review against its template requirements.

Feature Request Review Checklist:

  • Pre-submission checklist present (4 checkboxes)
  • Feature name provided
  • Type of addition selected
  • Problem statement filled (not placeholder text)
  • What is being added described with examples
  • Full scope of changes listed (files created/modified/systems)
  • User stories present (minimum 2)
  • Acceptance criteria present (testable conditions)
  • Applicable runtimes selected
  • Breaking changes assessment present
  • Maintenance burden described
  • Alternatives considered (not empty)
  • Label check: Has needs-review label? Has approved-feature label?
  • Gate check: If PR exists linking this issue, does issue have approved-feature?

Enhancement Review Checklist:

  • Pre-submission checklist present (4 checkboxes)
  • What is being improved identified
  • Current behavior described with examples
  • Proposed behavior described with examples
  • Reason and benefit articulated (not vague)
  • Scope of changes listed
  • Breaking changes assessed
  • Alternatives considered
  • Area affected selected
  • Label check: Has needs-review label? Has approved-enhancement label?
  • Gate check: If PR exists linking this issue, does issue have approved-enhancement?

Bug Report Review Checklist:

  • GSD Version provided
  • Runtime selected
  • OS selected
  • Node.js version provided
  • Description of what happened
  • Expected behavior described
  • Steps to reproduce provided
  • Frequency selected
  • Severity/impact selected
  • PII checklist confirmed
  • Label check: Has needs-triage or confirmed-bug label?

Chore Review Checklist:

  • Pre-submission checklist confirmed (no user-facing changes)
  • Maintenance task described
  • Type of maintenance selected
  • Current state described with specifics
  • Proposed work listed
  • Acceptance criteria present
  • Area affected selected
  • Label check: Has needs-triage label?

Scoring: For each issue, calculate a completeness percentage:

  • Count required fields present vs. total required fields
  • Score = (present / total) * 100
  • Status: COMPLETE (100%), MOSTLY COMPLETE (75-99%), INCOMPLETE (50-74%), REJECT (<50%)
Skip if REVIEW_PRS=false.

Fetch all open PRs:

gh pr list --state open --json number,title,labels,body,author,headRefName,baseRefName,isDraft,createdAt,reviewDecision,statusCheckRollup --limit 100

For each PR, classify by body content and linked issue:

Body Pattern Type Template
Contains "## Feature PR" or "## Feature summary" Feature PR feature.md
Contains "## Enhancement PR" or "## What this enhancement improves" Enhancement PR enhancement.md
Contains "## Fix PR" or "## What was broken" Fix PR fix.md
Uses default template Wrong Template Flag — must use typed template
Cannot determine Unknown Flag for manual review

Also check for linked issues:

gh pr view {number} --json body -q '.body' | grep -oE '(Closes|Fixes|Resolves) #[0-9]+'
Skip if REVIEW_PRS=false.

For each classified PR, review against its template requirements.

Feature PR Review Checklist:

  • Uses feature PR template (not default)
  • Issue linked with Closes #NNN
  • Linked issue exists and has approved-feature label
  • Feature summary present
  • New files table filled
  • Modified files table filled
  • Implementation notes present
  • Spec compliance checklist present (acceptance criteria from issue)
  • Test coverage described
  • Platforms tested checked (macOS, Windows, Linux)
  • Runtimes tested checked
  • Scope confirmation checked
  • Full checklist completed
  • Breaking changes section filled
  • CI check: All status checks passing?
  • Review check: Has review approval?

Enhancement PR Review Checklist:

  • Uses enhancement PR template (not default)
  • Issue linked with Closes #NNN
  • Linked issue exists and has approved-enhancement label
  • What is improved described
  • Before/after provided
  • Implementation approach described
  • Verification method described
  • Platforms tested checked
  • Runtimes tested checked
  • Scope confirmation checked
  • Full checklist completed
  • Breaking changes section filled
  • CI check: All status checks passing?

Fix PR Review Checklist:

  • Uses fix PR template (not default)
  • Issue linked with Fixes #NNN
  • Linked issue exists and has confirmed-bug label
  • What was broken described
  • What the fix does described
  • Root cause explained
  • Verification method described
  • Regression test added (or explained why not)
  • Platforms tested checked
  • Runtimes tested checked
  • Full checklist completed
  • Breaking changes section filled
  • CI check: All status checks passing?

Cross-cutting PR Checks (all types):

  • PR title is descriptive (not just "fix" or "update")
  • One concern per PR (not mixing fix + enhancement)
  • No unrelated formatting changes visible in diff
  • .changeset/*.md fragment added for user-facing changes (or no-changelog label applied)
  • Not using --no-verify or skipping hooks

Scoring: Same as issues — completeness percentage per PR.

Cross-reference issues and PRs to enforce the issue-first rule:

For each open PR:

  1. Extract linked issue number from body
  2. If no linked issue: GATE VIOLATION — PR has no issue
  3. If linked issue exists, check its labels:
    • Feature PR → issue must have approved-feature
    • Enhancement PR → issue must have approved-enhancement
    • Fix PR → issue must have confirmed-bug
  4. If label is missing: GATE VIOLATION — PR opened before approval

Report gate violations prominently — these are the most important findings because the project auto-closes PRs without proper approval gates.

Produce a structured triage report:
===================================================================
  GSD INBOX TRIAGE — {repo} — {date}
===================================================================

SUMMARY
-------
Open issues: {count}    Open PRs: {count}
  Features:    {n}        Feature PRs:      {n}
  Enhancements:{n}        Enhancement PRs:  {n}
  Bugs:        {n}        Fix PRs:          {n}
  Chores:      {n}        Wrong template:   {n}
  Unclassified:{n}        No linked issue:  {n}

GATE VIOLATIONS (action required)
---------------------------------
{For each violation:}
  PR #{number}: {title}
    Problem: {description — e.g., "No approved-feature label on linked issue #45"}
    Action:  {what to do — e.g., "Close PR or approve issue #45 first"}

ISSUES NEEDING ATTENTION
------------------------
{For each issue sorted by completeness score, lowest first:}
  #{number} [{type}] {title}
    Score: {percentage}% complete
    Missing: {list of missing required fields}
    Labels: {current labels} → Suggested: {recommended labels}
    Age: {days since created}

PRS NEEDING ATTENTION
---------------------
{For each PR sorted by completeness score, lowest first:}
  #{number} [{type}] {title}
    Score: {percentage}% complete
    Missing: {list of missing checklist items}
    CI: {passing/failing/pending}
    Review: {approved/changes_requested/none}
    Linked issue: #{issue_number} ({issue_status})
    Age: {days since created}

READY TO MERGE
--------------
{PRs that are 100% complete, CI passing, approved:}
  #{number} {title} — ready

STALE ITEMS (>30 days, no activity)
------------------------------------
{Issues and PRs with no updates in 30+ days}

===================================================================

Write this report to .planning/INBOX-TRIAGE.md if a .planning/ directory exists, otherwise print to console only.

Only execute if `--label` or `--close-incomplete` flags were set.

If --label: For each issue/PR where labels are missing or incorrect:

gh issue edit {number} --add-label "{label}"

Or:

gh pr edit {number} --add-label "{label}"

Label recommendations:

  • Unclassified issues → add needs-triage
  • Feature issues without review → add needs-review
  • Enhancement issues without review → add needs-review
  • Bug reports without triage → add needs-triage
  • PRs with gate violations → add gate-violation

If --close-incomplete: For issues scoring below 50% completeness:

gh issue close {number} --comment "Closed by GSD inbox triage: this issue is missing required fields per the issue template. Missing: {list}. Please reopen with a complete submission. See CONTRIBUTING.md for requirements."

For PRs with gate violations:

gh pr close {number} --comment "Closed by GSD inbox triage: this PR does not meet the issue-first requirement. {specific violation}. See CONTRIBUTING.md for the correct process."

Always confirm with the user before closing anything:

Text mode (workflow.text_mode: true in config or --text flag): Set TEXT_MODE=true if --text is present in $ARGUMENTS OR text_mode from init JSON is true. When TEXT_MODE is active, replace every AskUserQuestion call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where AskUserQuestion is not available.

AskUserQuestion:
  question: "Found {N} items to close. Review the list above — proceed with closing?"
  options:
    - label: "Close all"
      description: "Close all {N} non-compliant items with explanation comments"
    - label: "Let me pick"
      description: "I'll choose which ones to close"
    - label: "Skip"
      description: "Don't close anything — report only"
``` ───────────────────────────────────────────────────────────────

Inbox Triage Complete

Reviewed: {issue_count} issues, {pr_count} PRs Gate violations: {violation_count} Ready to merge: {ready_count} Needing attention: {attention_count} Stale (30+ days): {stale_count} {If report saved: "Report saved to .planning/INBOX-TRIAGE.md"}

Next steps:

  • Review gate violations first — these block the contribution pipeline
  • Address incomplete submissions (comment or close)
  • Merge ready PRs
  • Triage unclassified issues

───────────────────────────────────────────────────────────────

</step>

</process>

<offer_next>
After triage:

- /gsd:review — Run cross-AI peer review on a specific phase plan
- /gsd:ship — Create a PR from completed work
- /gsd:progress — See overall project state
- /gsd:inbox --label — Re-run with auto-labeling enabled
</offer_next>

<success_criteria>
- [ ] All open issues fetched and classified by type
- [ ] Each issue reviewed against its template requirements
- [ ] All open PRs fetched and classified by type
- [ ] Each PR reviewed against its template checklist
- [ ] Issue-first gate violations identified
- [ ] Structured report generated with scores and action items
- [ ] Auto-actions executed only when flagged and user-confirmed
</success_criteria>