Skip to content

feat(workflows): automate GitHub backlog grooming - #2778

Open
Chris Montazer (rezatnoMsirhC) wants to merge 32 commits into
mainfrom
feat/2558-automated-backlog-grooming
Open

feat(workflows): automate GitHub backlog grooming#2778
Chris Montazer (rezatnoMsirhC) wants to merge 32 commits into
mainfrom
feat/2558-automated-backlog-grooming

Conversation

@rezatnoMsirhC

@rezatnoMsirhC Chris Montazer (rezatnoMsirhC) commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

This PR added an advisory backlog-grooming system that assesses the complete open issue inventory in bounded, immutable waves while keeping model-facing jobs read-only. Digest-bound manifests and checkpoints authenticate continuation and recovery, and a separate publisher remains the only workflow with issue-write authority.

Orchestration and publication

  • Added a first-Monday monthly orchestrator that snapshots eligible issues, processes ten issues per wave across two five-issue shards, validates exact coverage, and resumes from the first missing checkpoint.
  • Added canonical and generated gh-aw worker workflows with read-only repository access, bounded AIC, structured safe output, and authenticated bot continuation.
  • Added terminal publication that revalidates aggregate provenance, updates one trusted compact tracker, and persists escaped HTML and JSON history on the backlog-grooming-reports branch.
  • Extended the existing Docusaurus Pages deployment to stage an exact report commit at /backlog-grooming/ without replacing the production site root.

Policy, validation, and distribution

  • Added the non-interactive Backlog Grooming agent and policy for repository-grounded, advisory issue dispositions.
  • Restricted later interactive handoffs to one explicitly approved, non-closing update or comment per issue with field allowlists and freshness revalidation.
  • Added deterministic wave validation and zero-model hosted proofs for ordinary completion, duplicate dispatch, failed-wave recovery, and conflicting artifacts.
  • Added behavior evals, generated reference documentation, plugin membership, and 71 focused workflow security and recovery contracts.

Related Issue(s)

Related to #2558

Type of Change

Select all that apply:

Code & Documentation:

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Infrastructure & Configuration:

  • GitHub Actions workflow
  • Linting configuration (markdown, PowerShell, etc.)
  • Security configuration
  • DevContainer configuration
  • Dependency update

AI Artifacts:

  • Reviewed contribution with hve-builder and addressed all actionable findings
  • Copilot instructions (.github/instructions/*.instructions.md)
  • Copilot prompt (.github/prompts/*.prompt.md)
  • Copilot agent (.github/agents/*.agent.md)
  • Copilot skill (.github/skills/*/SKILL.md)
  • Copilot hook (.github/hooks/*/*.json)
  • Eval spec added/updated for changed AI artifacts (evals/)

Note for AI Artifact Contributors:

  • Agents: Research, indexing/referencing other project (using standard VS Code GitHub Copilot/MCP tools), planning, and general implementation agents likely already exist. Review .github/agents/ before creating new ones.
  • Skills: Must include both bash and PowerShell scripts. See Skills.
  • Model Versions: Contributions MUST target models listed in the model catalog (scripts/linting/model-catalog.json) whose provider appears in providerAllowlist and whose status is ga or preview. Run npm run lint:models to validate references.
  • See Agents Not Accepted and Model Version Requirements.

Other:

  • Script/automation (.ps1, .sh, .py)
  • Other (please describe):

Sample Prompts (for AI Artifact Contributions)

None

Testing

Local validation

Validation Result Evidence
Focused backlog-grooming Pester suite Passed 71 of 71 tests passed after merging current main
Documentation validation Passed 10 suites and 78 tests passed
Plugin manifest validation Passed 56 agents, 48 commands, 58 rules, and 73 skills were in sync
Spell checking Passed 826 files checked with zero issues
Workflow permission policy Passed 282 checks passed; publication remains the only issue-write boundary
Workflow runner policy Passed 158 checks passed
Dependency pinning Passed 765 dependencies inspected with zero violations
Workflow syntax Passed actionlint 1.7.10 validated all 72 workflows
Direct proof tests Passed 14 of 14 Node tests passed
Rendered report verification Passed 299 rows, 299 unique issue IDs, and zero duplicates
Markdown link validation Blocked outside PR scope One unchanged Microsoft Learn URL returns 404 in .github/skills/project-planning/security-planning/references/data-classification.md
Local validation aggregate Blocked by link validation Earlier aggregate stages passed before the same unchanged link failure

Hosted proof artifacts

Artifact Result Direct link
Disposable test repository Production-shaped isolated host hve-core-backlog-grooming-test
Production-shaped orchestrator 299 issues across 30 waves Workflow source
Terminal sweep run Passed Run 32294365143
Authenticated publisher replay Passed Run 32304524842
Corrected Pages deployment Passed Run 32750455136
Report-history landing page Live Backlog grooming history
Immutable sweep report 299 unique issue rows Sweep 2026-08-19-fdc243a2
Multi-wave proof workflow Checked-in validation asset Workflow source
Artifact-conflict proof workflow Checked-in validation asset Workflow source

The hosted sweep produced aggregate digest fca5892445cd51baad953ca8df4b16a2278478c96d2cd5289e6c138e0b36eecd. Report-history commit 9d5341f73f7371aade32305be04849fe83a079f2 was deployed by the successful Pages run.

Manual exploratory testing was limited to the disposable repository and its rendered Pages surfaces. No production issues were mutated during validation.

Checklist

Required Checks

  • Documentation is updated (if applicable)
  • Files follow existing naming conventions
  • Changes are backwards compatible (if applicable)
  • Tests added for new functionality (if applicable)

AI Artifact Contributions

  • Used hve-builder review mode to review contribution
  • Addressed all actionable findings from the hve-builder review
  • Verified contribution follows common standards and type-specific requirements

Required Local Checks

The following local-safe validation commands must pass before merging:

  • Local validation aggregate: npm run validate:local (blocked by the unchanged link noted above)
  • Documentation validation (if docs changed): npm run validate:docs
  • Spell checking: npm run spell-check
  • Link validation: npm run lint:md-links (blocked by the unchanged link noted above)

Security Considerations

  • This PR does not contain any sensitive or NDA information
  • Any new dependencies have been reviewed for security issues
  • Security-related scripts follow the principle of least privilege (N/A: no security scripts were modified)

GHCP Membership Changes

File Type Membership change
.github/agents/github/backlog-grooming.agent.md Agent Added
.github/instructions/project-planning/github-backlog-grooming.instructions.md Instruction Added

npm run plugin:sync regenerated the root manifest, and npm run plugin:validate passed after the merge.

Additional Notes

The disposable repository used a standalone Pages deployment and root redirect because it had no Docusaurus site. Neither test-only surface is present in this PR. Production report history is staged only beneath /backlog-grooming/ in the existing Docusaurus deployment.

- add weekly advisory backlog assessment
- persist cursor state in a validated tracker
- add approved interactive writeback
- cover continuation and documentation behavior

🧹 - Generated by Copilot
- create the tracker when absent
- replace and reopen the sole existing tracker
- fail closed on ambiguous marker matches
- align grooming policy and agent behavior
- add tracker lifecycle and persistence tests

🔄 - Generated by Copilot
- reconcile issues with code, PRs, commits, and releases
- validate structured tracker reports and supersession lineage
- expand publisher, continuation, and mutation-safety tests

🔍 - Generated by Copilot
- align workflow and policy cursor semantics
- cover priority-only assessment cohorts

🐛 - Generated by Copilot
- add deterministic manifest and read-only shard result contracts
- bound aggregate AI credits and reusable worker permissions
- align agent policy and focused regression coverage

⚙️ - Generated by Copilot
- pass the existing Copilot engine secret to the reusable worker
- assert the secret boundary in the owning regression suite

🔐 - Generated by Copilot
- interpolate trusted caller inputs into the agent prompt
- regenerate the gh-aw lock and assert candidate binding

🧭 - Generated by Copilot
- validate prior cursor as bounded proof provenance
- include it in the immutable manifest and regression contract

🧭 - Generated by Copilot
- fan out deterministic read-only shard workers
- validate complete artifacts and injected conflicts

🧪 - Generated by Copilot
- bind workflow and generated job concurrency to shard identity
- assert canonical and compiled concurrency groups

🧭 - Generated by Copilot
- enforce measured sharding and aggregate credit ceilings
- reject invalid fan-in before constructing a canonical aggregate
- preserve manifest order and last-assessed cursor semantics

🧭 - Generated by Copilot
- orchestrate authenticated snapshot waves and checkpoint recovery
- add fail-closed proof, reduction, and manual publication paths
- document limits and cover contracts with focused tests

🧭 - Generated by Copilot
- preserve role checks with a provenance-bound bot grant
- use binary-safe artifact downloads and focused contracts

🔒 - Generated by Copilot
- persist authenticated reports on a durable history branch
- deploy report history through the existing Docusaurus Pages workflow
- schedule first-Monday monthly sweeps and retain manual recovery

⚙️  - Generated by Copilot
@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.15068% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.18%. Comparing base (3c3dc02) to head (88f8cf5).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...ipts/security/Invoke-BacklogGroomWaveValidator.ps1 92.59% 20 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2778      +/-   ##
==========================================
+ Coverage   82.98%   83.18%   +0.19%     
==========================================
  Files         183      184       +1     
  Lines       33787    34378     +591     
  Branches       25       25              
==========================================
+ Hits        28038    28597     +559     
- Misses       5746     5778      +32     
  Partials        3        3              
Flag Coverage Δ
docusaurus 89.92% <ø> (ø)
pester 84.10% <93.15%> (+0.63%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
scripts/docs/Generate-AssetDocs.ps1 87.58% <100.00%> (+0.22%) ⬆️
scripts/docs/Modules/DocsHelpers.psm1 96.92% <100.00%> (+0.06%) ⬆️
scripts/security/Test-ActionVersionConsistency.ps1 94.41% <100.00%> (+0.32%) ⬆️
...ipts/security/Invoke-BacklogGroomWaveValidator.ps1 92.59% <92.59%> (ø)

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Eval Execution

Status: Passed — no merge-blocking failures (40 advisory assertion failure(s) present)

  • Artifacts evaluated: 4
  • Specs run: 4
  • Assertions passed: 10
  • Assertions failed (blocking): 0
  • Assertions failed (advisory): 40
  • Failed specs (merge-blocking): 0
Artifact Kind Status Specs Passed Failed (blocking) Failed (advisory)
backlog-manager agent ⚠️ advisory-fail 1 5 0 20
github-backlog-executor agent ⚠️ advisory-fail 1 0 0 20
backlog-grooming agent ✅ pass 1 5 0 0
github-backlog-grooming instruction ❌ fail 1 0 0 0

Legend — ✅ clean · ⚠️ advisory failures only (non-blocking) · ⏭️ skipped · ❌ merge-blocking failure

Only Failed specs (merge-blocking) gates this PR. Advisory assertion failures are signal-quality checks captured during iteration; review them, but they do not block merge and may be acceptable.

- preserve cursor, deferred-state, and comment safety contracts
- restore docs migration and deterministic eval coverage
- scope Poutine acknowledgement to the generated workflow

🔒 - Generated by Copilot
- align synthetic grooming prompts with read-only evidence retrieval
- validate compiler-owned action pins through the gh-aw manifest

🔧 - Generated by Copilot
- provide exact report headers in the synthetic shard contract
- require canonical run and issues JSON keys

🧪 - Generated by Copilot
- delete proof-only workflows, helper, and tests
- retain production workflow documentation and contract checks

🧹 - Generated by Copilot

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The immutable sweep, provenance, and read-only assessment design is substantial, I do have some comments and suggestions. Please also separate reusable project-planning grooming behavior from workflow-only shard/publication mechanics and reconcile issue #2558 plus the PR description with the delivered orchestrator/worker/publisher architecture. Docusaurus should remain optional/TBC rather than a core dependency.

One thing I've reflected on, and may be visible in some comments is the reflection on shipping the sub-agent/instructions into the Plugins/Extension, while the full value becomes its integration with AW and the workflows, which are always HVE Core specific. I wonder if there is a version where we first test it within repo, and then add it to existing backlog manager as well as release the subagent. What do you think? Does it provide clear usage pattern without the workflows?

Finally, please upgrade the gh-aw CLI to v0.86.2 and run bare gh aw compile to regenerate and consistency-check ALL agentic Markdown workflows and their generated locks; backlog-groom.lock.yml is still v0.83.4 while the other six locks already report v0.86.2.

Additional non-inline comments:

  • Reconcile issue #2558 with the delivered first-Monday orchestrator, reusable worker, publisher, report branch, tracker body replacement, and optional Pages output. Either update and approve its criteria for this architecture or split the publication work from the core assessment scope.
  • Update the PR description so its summary, changed areas, validation evidence, and rollout notes describe the actual orchestrator/worker/publisher architecture and distinguish core tracker delivery from optional/TBC report-history and Docusaurus publication.

Comment thread .github/workflows/backlog-groom.md
Comment thread .github/workflows/backlog-groom-orchestrator.yml Outdated
Comment thread .github/workflows/deploy-docs.yml Outdated
Comment thread .github/workflows/backlog-groom-publisher.yml Outdated
Comment thread .github/workflows/backlog-groom.md
Comment thread .github/workflows/backlog-groom-publisher.yml Outdated
Comment thread .github/workflows/README.md Outdated
Comment thread .github/workflows/README.md
Comment thread .github/instructions/project-planning/github-backlog-grooming.instructions.md Outdated
Comment thread docs/reference/instructions/project-planning/github-backlog-grooming.md Outdated
- invoke validation directly in the existing job
- preserve canonical digests, schemas, outputs, and permissions
- add focused Pester coverage and remove the composite action

♻️ - Generated by Copilot
- correct trust, ordering, deferral, and tracker freshness checks
- isolate optional report publication behind an exact repository variable
- separate reusable policy and compile generated locks with gh-aw v0.86.2

🔒 - Generated by Copilot
📐 - Generated by Copilot
@rezatnoMsirhC

Copy link
Copy Markdown
Contributor Author

The immutable sweep, provenance, and read-only assessment design is substantial, I do have some comments and suggestions. Please also separate reusable project-planning grooming behavior from workflow-only shard/publication mechanics and reconcile issue #2558 plus the PR description with the delivered orchestrator/worker/publisher architecture. Docusaurus should remain optional/TBC rather than a core dependency.

I've separated the reusable grooming policy from the repository-specific automation. The shared instruction now owns workflow-neutral evidence gathering, similarity assessment, advisory dispositions, compact reporting, and approved handoff behavior. Shard inputs, cursor state, safe-output schema, deterministic digesting, artifacts, checkpoints, and publication remain in the repository-only worker and workflows. Backlog Manager now applies the reusable policy directly to ordinary issue inventory instead of dispatching the workflow-bound worker. Plugin, extension, and generated-documentation validation confirm that the worker is no longer distributed while the reusable instruction remains available.

One thing I've reflected on, and may be visible in some comments is the reflection on shipping the sub-agent/instructions into the Plugins/Extension, while the full value becomes its integration with AW and the workflows, which are always HVE Core specific. I wonder if there is a version where we first test it within repo, and then add it to existing backlog manager as well as release the subagent. What do you think? Does it provide clear usage pattern without the workflows?

That concern makes sense. In this PR, I've kept the workflow-bound worker repository-only and removed it from the plugin and extension. Backlog Manager now applies the reusable grooming instruction directly, which provides a workflow-independent usage pattern. It can assess ordinary issue inventory, produce evidence-backed advisory findings, and hand off only explicitly approved Update or Comment operations. The reusable instruction remains distributed, but I don't think the workflow-bound subagent yet demonstrates enough standalone value without the HVE Core workflows to justify releasing it. My preference is to test that worker within this repository first and distribute a standalone subagent only after we can demonstrate a clear workflow-neutral contract and usage pattern.

Finally, please upgrade the gh-aw CLI to v0.86.2 and run bare gh aw compile to regenerate and consistency-check ALL agentic Markdown workflows and their generated locks; backlog-groom.lock.yml is still v0.83.4 while the other six locks already report v0.86.2.

I've upgraded gh-aw to v0.86.2 and run bare gh aw compile across all agentic Markdown workflows. This regenerated backlog-groom.lock.yml at v0.86.2 and consistency-checked the other six generated locks. Their only resulting changes were compiler setup-action version normalization. Follow-up validation passed for workflow YAML, generated-lock consistency, permissions, runner policy, and dangerous-workflow checks.

Additional non-inline comments:

  • Reconcile issue feat(agents): add automated backlog grooming workflow #2558 with the delivered first-Monday orchestrator, reusable worker, publisher, report branch, tracker body replacement, and optional Pages output. Either update and approve its criteria for this architecture or split the publication work from the core assessment scope.

Issue #2558 described a different execution and publication architecture. I've reconciled it with the delivered first-Monday orchestrator, repository-only worker, authenticated publisher, and compact tracker-body replacement as the core delivery path. Report history, the report branch, and Pages deployment are now documented as a separate, default-off capability enabled only when BACKLOG_GROOM_PUBLISH_GH_PAGES is true.

  • Update the PR description so its summary, changed areas, validation evidence, and rollout notes describe the actual orchestrator/worker/publisher architecture and distinguish core tracker delivery from optional/TBC report-history and Docusaurus publication.

I've updated the PR description to reflect the delivered orchestrator, repository-only worker, deterministic validation and reduction, authenticated publisher, and compact tracker-body architecture. It now distinguishes core tracker delivery from the default-off report-history and Docusaurus Pages path, and includes the current validation evidence and separate rollout requirements for each mode.

@WilliamBerryiii

Copy link
Copy Markdown
Member

Chris Montazer (@rezatnoMsirhC) - MONSTER ... love this ... will review tomorrow and thanks for the swing at this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for the extensive follow-up, I really like the approach of first validating this and then reviewing what to expose in the plugin and distributions.

Most original comments are resolved, including scheduled activation, manual replay authentication, tracker freshness, deferred semantics, accessibility, distribution boundaries, issue scope, and the PR narrative. My reviewer found two blocking paths remain: cursor-prioritized wraparound order reaches the manifest but is still rejected by the worker and PowerShell validator, and optional Pages deployment trusts the mutable report-branch head without proving publisher provenance. Duplicate continuation dispatches also enter validation after omitting the manifest. I left smaller follow-ups for validator schema parity, PowerShell help, the core rollout checklist, and the stale gh-aw version in the runbook. The latter are smaller ones.

Really keen to see this merged in and learnings we get from the usage. Thanks for your work on this!

}
if (!Array.isArray(orderedCandidateIds) || orderedCandidateIds.some(
(issue, index) => !Number.isInteger(issue) || issue <= 0 ||
(index > 0 && issue <= orderedCandidateIds[index - 1]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The planned sequence can legitimately wrap or put priority issues first, so this ascending-order check rejects valid input such as [105, 1, 2]. Please validate positive unique IDs while preserving their order, then compare cohort and report coverage as sets. For example:

const candidateSet = new Set(orderedCandidateIds);
const validCandidates = Array.isArray(orderedCandidateIds) &&
  orderedCandidateIds.every((issue) => Number.isInteger(issue) && issue > 0) &&
  candidateSet.size === orderedCandidateIds.length;

const cohortSet = new Set([...priorityCandidateIds, ...roundRobinCandidateIds]);
const sameMembers = cohortSet.size === candidateSet.size &&
  [...cohortSet].every((issue) => candidateSet.has(issue));

Apply the same order-versus-membership distinction in the PowerShell validator and regenerate the lock.

}
await github.rest.git.getCommit({ ...context.repo, commit_sha: requestedRef });
}
const authenticatedRef = requestedRef || reportRef.object.sha;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This proves only that the requested SHA equals the current mutable report-branch head; it does not prove that the authenticated publisher created that commit. A collaborator can update the branch and have an ordinary main docs push publish its subtree. Please consume and authenticate an immutable publisher artifact (workflow path, successful run, default-branch source SHA, artifact identity, and digest). At minimum, do not stage reports when report-ref is empty and enforce a ruleset that only the publisher identity can update this branch.

- assess
if: >-
${{ always() && needs.plan.result == 'success' &&
needs.plan.outputs.mode != 'calendar-noop' &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

An accepted duplicate checkpoint returns complete-noop without uploading a manifest, but this job still runs and downloads an empty artifact ID. Exclude that terminal mode here:

Suggested change
needs.plan.outputs.mode != 'calendar-noop' &&
needs.plan.outputs.mode != 'calendar-noop' &&
needs.plan.outputs.mode != 'complete-noop' &&

$Issue = $Row.GetProperty('issue')
$IssueId = if (Test-SafeJsonInteger -Element $Issue -Minimum 1) { $Issue.GetInt64() } else { -1 }
$AssessmentStatus = $Row.GetProperty('assessment_status').GetString()
if (-not (Test-ExactJsonKeys -Element $Row -Keys $RowKeys) -or

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Exact keys alone do not reproduce the producer's row contract. This boundary still accepts shapes the worker rejects, including array-valued acceptance_signals and empty repository_evidence. Please mirror the canonical field types, bounds, enum/disposition relationships, and non-empty evidence requirements here, and make the validator fixtures valid producer outputs.

$ErrorActionPreference = 'Stop'

#region Functions
function ConvertTo-JavaScriptJsonString {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Repository PowerShell guidance requires block comment-based help for every function (ExportedOnly = $false, BlockComment = $true). Please add concise help to all eleven helpers. For example, this first one could start with:

Suggested change
function ConvertTo-JavaScriptJsonString {
<#
.SYNOPSIS
Converts a value to a JavaScript-compatible JSON string.
.PARAMETER Value
The string value to encode.
.OUTPUTS
System.String
#>
function ConvertTo-JavaScriptJsonString {


The workflow rejects capacity or AIC values that exceed safe integer
arithmetic. `max-parallel: 2` bounds concurrent model workers. gh-aw is pinned
at `v0.83.4`; its worker uses the Copilot engine, a 20-minute timeout, and at

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All seven generated locks and the action lock now identify gh-aw v0.86.2.

Suggested change
at `v0.83.4`; its worker uses the Copilot engine, a 20-minute timeout, and at
at `v0.86.2`; its worker uses the Copilot engine, a 20-minute timeout, and at

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.

4 participants