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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,32 @@ Being honest about where this still has issues:
<details open>
<summary><strong>v7.x</strong></summary>

### v7.0.43
- Budget-friendly CI defaults for gitguardex-managed projects: live
workflows drop `push: main`, gate per-PR jobs on `pull_request.draft
== false`, add `concurrency: cancel-in-progress`, and split per-runtime
matrix coverage into a weekly `ci-full.yml`. CodeQL and Scorecard run
on the weekly schedule + `workflow_dispatch` only. Templates under
`templates/github/workflows/` carry the same posture so downstream
projects inherit it via `gx setup`.
- New `gx ci-init` subcommand scaffolds `ci.yml`, `ci-full.yml`, `cr.yml`,
and a `README.md` budget-posture guide into a target repo's
`.github/workflows/` directory. Supports `--target`, `--dry-run`,
`--force`, `--no-stage`, and `--json`.
- New `gx budget` subcommand wraps the new GitHub
`/settings/billing/usage` endpoint (the legacy
`/settings/billing/actions` endpoint was retired in early 2026) and
reports monthly Actions minute spend with warn/critical USD thresholds
per `--org` or `--user`.
- Per-PR label opt-in for `agent/*` lanes: `needs-review` runs AI code
review on an otherwise-skipped agent PR; `needs-ci-full` triggers the
full cross-runtime matrix without waiting for the weekly schedule.
- `gx branch finish` runs `scripts/agent-preflight.sh` in the worktree
before pushing. Default script auto-detects pnpm/npm, Rust, and Python
stacks and refuses the push on verification failure. After pre-flight
passes, draft PRs are promoted to ready-for-review so the
budget-friendly CI defaults fire once on a known-passing commit.

### v7.0.42
- Bumped `@imdeadpool/guardex` from `7.0.41` to `7.0.42` so the current
`main` payload can publish under a fresh npm version after `7.0.41` reached
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-14
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# agent-claude-fix-metadata-test-stale-assertions-2026-05-14-02-09 (minimal / T1)

Branch: `agent/<your-name>/<branch-slug>`

Describe the change in a sentence or two. Commit message is the spec of record.

## Handoff

- Handoff: change=`agent-claude-fix-metadata-test-stale-assertions-2026-05-14-02-09`; branch=`agent/<your-name>/<branch-slug>`; scope=`TODO`; action=`continue this sandbox or finish cleanup after a usage-limit/manual takeover`.
- Copy prompt: Continue `agent-claude-fix-metadata-test-stale-assertions-2026-05-14-02-09` on branch `agent/<your-name>/<branch-slug>`. Work inside the existing sandbox, review `openspec/changes/agent-claude-fix-metadata-test-stale-assertions-2026-05-14-02-09/notes.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`.

## Cleanup

- [ ] Run: `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`
- [ ] Record PR URL + `MERGED` state in the completion handoff.
- [ ] Confirm sandbox worktree is gone (`git worktree list`, `git branch -a`).
41 changes: 32 additions & 9 deletions test/metadata.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ test('release workflow publishes with provenance in CI', () => {
const workflow = fs.readFileSync(workflowPath, 'utf8');
assert.match(workflow, /name:\s+Checkout\s+uses:\s+actions\/checkout@[0-9a-f]{40}[^\n]*\n\s+with:\s*\n\s+fetch-depth:\s+0/s);
assert.match(workflow, /npm publish --provenance --access public/);
assert.match(workflow, /name:\s+Install Cosign\s+uses:\s+sigstore\/cosign-installer@[0-9a-f]{40}[^\n]*# v4\.1\.1/s);
// Cosign installer must be pinned to a 40-char SHA on the v4.1.x line.
// The patch version floats so a renovate/dependabot bump
// (e.g. v4.1.1 -> v4.1.2) doesn't break this gate; a major or minor
// bump still does.
assert.match(workflow, /name:\s+Install Cosign\s+uses:\s+sigstore\/cosign-installer@[0-9a-f]{40}[^\n]*# v4\.1\.\d+/s);
});

test('release workflow skips publish when the current version is already on npm', () => {
Expand Down Expand Up @@ -108,11 +112,19 @@ test('README advertises the repo skills installer path and root skills stay in s
}
});

test('README keeps canonical About copy and problem-solution visuals aligned', () => {
const readme = fs.readFileSync(readmePath, 'utf8');
test('package description stays aligned with about_description.txt', () => {
// The README "Package summary" paragraph and link to about_description.txt
// were intentionally removed in PR #564 to declutter the top of the file;
// this test no longer enforces their presence. What still matters: the npm
// package description and the standalone about_description.txt file are the
// canonical About copy and must not drift apart.
const aboutDescription = fs.readFileSync(aboutDescriptionPath, 'utf8').trim();
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
assert.equal(pkg.description, aboutDescription);
});

test('README keeps the problem-solution visuals aligned', () => {
const readme = fs.readFileSync(readmePath, 'utf8');
assert.match(
readme,
/## The problem\s+!\[Parallel agents colliding in the same files\]\(https:\/\/raw\.githubusercontent\.com\/recodeee\/gitguardex\/main\/docs\/images\/problem-agent-collision\.svg\)/s,
Expand All @@ -121,9 +133,6 @@ test('README keeps canonical About copy and problem-solution visuals aligned', (
readme,
/### Solution\s+!\[Agent branch\/worktree start protocol\]\(https:\/\/raw\.githubusercontent\.com\/recodeee\/gitguardex\/main\/docs\/images\/workflow-branch-start\.svg\)/s,
);
assert.match(readme, /\[about_description\.txt\]\(\.\/about_description\.txt\)/);
assert.match(readme, new RegExp(escapeRegexLiteral(aboutDescription)));
assert.equal(pkg.description, aboutDescription);
});

test('security workflows are present and use pinned GitHub Actions SHAs', () => {
Expand All @@ -143,11 +152,25 @@ test('security workflows are present and use pinned GitHub Actions SHAs', () =>
}
});

test('CI and CodeQL workflows run on pull requests targeting main', () => {
test('CI workflow runs on pull requests targeting main', () => {
const ciWorkflow = fs.readFileSync(path.join(repoRoot, '.github', 'workflows', 'ci.yml'), 'utf8');
const codeqlWorkflow = fs.readFileSync(path.join(repoRoot, '.github', 'workflows', 'codeql.yml'), 'utf8');
assert.match(ciWorkflow, /pull_request:\s*\n\s*branches:\s*\n\s*-\s*main/s);
assert.match(codeqlWorkflow, /pull_request:\s*\n\s*branches:\s*\n\s*-\s*main/s);
});

test('CodeQL workflow runs on a weekly schedule, not per-PR', () => {
// PR #571 dropped per-PR / per-push triggers from codeql.yml as part of
// the budget-friendly trim. CodeQL is the single most expensive workflow
// per run on this repo, and the weekly schedule + `workflow_dispatch`
// covers security coverage without compounding the monthly Actions bill
// across every agent PR. Re-add a `pull_request:` trigger here only if
// your project specifically needs per-PR CodeQL gating for compliance.
const codeqlWorkflow = fs.readFileSync(
path.join(repoRoot, '.github', 'workflows', 'codeql.yml'),
'utf8',
);
assert.match(codeqlWorkflow, /schedule:\s*\n\s*-\s*cron:/s);
assert.match(codeqlWorkflow, /workflow_dispatch:/);
assert.doesNotMatch(codeqlWorkflow, /\n\s*pull_request:\s*\n/s);
});

test('code review workflow does not gate startup on secrets context', () => {
Expand Down
Loading