Skip to content
Open
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
18 changes: 18 additions & 0 deletions .github/workflows/openspec-badge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: OpenSpec Badge

on:
push:
branches: [main]

Comment on lines +3 to +6
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify workflow file current state and check for manual trigger documentation
echo "=== Current workflow trigger configuration ==="
cat -n .github/workflows/openspec-badge.yml | head -20

echo -e "\n=== Searching for manual trigger mentions in documentation ==="
# Search broadly in the repository for manual trigger references
rg -i 'manually trigger|manual trigger|run the workflow' --type md || echo "No matches found in markdown files"

echo -e "\n=== Searching for workflow_dispatch in workflow files ==="
rg 'workflow_dispatch' .github/workflows/ || echo "No workflow_dispatch found in any workflows"

echo -e "\n=== Checking if openspec-badge.yml exists and is as described ==="
ls -la .github/workflows/openspec-badge.yml
wc -l .github/workflows/openspec-badge.yml

Repository: Fission-AI/OpenSpec

Length of output: 1826


Add workflow_dispatch trigger for manual runs from Actions UI.

The task explicitly requires "Manually trigger or wait for the badge workflow to run on main branch" (task 4.2), but the workflow currently only supports automatic runs on push. Add workflow_dispatch to enable manual triggering from the GitHub Actions UI.

Suggested change
 on:
   push:
     branches: [main]
+  workflow_dispatch:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
push:
branches: [main]
on:
push:
branches: [main]
workflow_dispatch:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/openspec-badge.yml around lines 3 - 6, The workflow
currently only triggers on push to main; add a manual trigger by updating the
"on" triggers in the openspec-badge.yml to include workflow_dispatch alongside
push so the badge workflow can be invoked from the Actions UI (modify the
top-level "on" block in the existing file to include workflow_dispatch).

jobs:
badge:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: weAretechnative/openspec-badge-action@main
Copy link

Choose a reason for hiding this comment

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

using @main reference could introduce breaking changes if the action is updated

Suggested change
- uses: weAretechnative/openspec-badge-action@main
- uses: weAretechnative/openspec-badge-action@v1

consider pinning to a specific version tag or commit SHA for stability

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +13 to +14
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and read the relevant lines
if [ -f ".github/workflows/openspec-badge.yml" ]; then
  echo "=== File exists, showing full content ==="
  cat -n ".github/workflows/openspec-badge.yml"
else
  echo "File not found, searching for similar files:"
  find . -name "*openspec*" -o -name "*badge*" | head -20
fi

Repository: Fission-AI/OpenSpec

Length of output: 607


🏁 Script executed:

# Also run the provided verification script
rg -nP '^\s*-\s*uses:\s*[^@]+@(main|master|v\d+)$' .github/workflows

Repository: Fission-AI/OpenSpec

Length of output: 461


🌐 Web query:

GitHub Actions best practices action pinning security v4 major version tag

💡 Result:

Best practice: don’t rely on @v4 for security—pin to a commit SHA

Why actions/checkout@v4 (major tag) is risky

  • A major tag like @v4 is a floating reference that can be moved to a newer commit, so your workflow can start running new code without review. [1]
  • Even “more specific” tags (like v4.1.1) can be force-moved if the publisher retags them, unless you’re using a truly immutable mechanism; SHA pinning avoids tag-move attacks. [2]
  • GitHub’s own guidance: the most reliable immutable reference is a full-length commit SHA (and immutable tags can be disabled by repo owners). [1]

Recommended pattern (secure + maintainable)

Pin to the full commit SHA, and keep the human-readable version as a comment:

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

This is explicitly recommended by GitHub’s security guidance (and helps tooling like Dependabot track upgrades when you pin a SHA that corresponds to a tagged release). [1]

If you run GitHub at org/enterprise scale

  • GitHub policies can require actions to be pinned to a full-length commit SHA (so unpinned workflows fail). [3]
  • GitHub also added explicit “enforce SHA pinning” support in the allowed-actions policy controls. [4]

Note on “immutable releases/tags”

GitHub supports “immutable releases,” but Git tags in general can be force-moved (GitHub even documents force-updating tags), which is exactly why SHA pinning is the safest default for consumers. [5]

Bottom line: treat @v4 as convenience, not a security control—use @<full sha> for third-party actions, and automate updates/reviews. [1][2]

Sources: [1] GitHub Well-Architected Actions security guidance, [2] OpenSSF workflow attack vectors, [3] GitHub Docs (enterprise policy requiring SHA pinning), [4] GitHub Changelog (SHA pinning enforcement), [5] GitHub Docs on managing releases/tags (force-updating tags).


🌐 Web query:

actions/checkout@v4 pinning commit SHA security recommendation GitHub

💡 Result:

GitHub’s security guidance is to pin GitHub Actions (including actions/checkout@v4) to an immutable, full-length commit SHA instead of a mutable tag like v4, to reduce supply-chain risk (e.g., a tag being moved to different code). (wellarchitected.github.com)

Example:

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

This keeps builds reproducible and avoids silently picking up changes if the v4 tag moves. GitHub also supports enforcing SHA pinning via Actions policy so workflows fail if actions aren’t pinned. (github.blog)

Citations:


🌐 Web query:

GitHub Actions reproducibility mutable action references major version tags 2024 2025

💡 Result:

  • Major version tags (e.g., owner/action@v4) are intentionally “moving” references: action authors are expected to update the vN tag to point at the latest compatible minor/patch release, so your workflow is not reproducible over time if you rely on @vN. GitHub’s own guidance for action authors explicitly describes moving major (and minor) tags by force-updating tags. [1]
  • Any Git tag (even @v4.1.1) can be mutable unless the repo uses GitHub “immutable releases.” Without immutability, an attacker (or maintainer) can retarget an existing tag to a different commit, breaking both security and reproducibility; the OpenSSF notes this explicitly and recommends SHA pinning as the robust mitigation. [2]
  • Best practice for reproducibility + supply-chain safety (2024–2025 guidance): pin to a full commit SHA (optionally with a comment noting the human version), e.g. uses: actions/checkout@<full_sha> # v4.1.7. GitHub’s Well-Architected guidance calls full-SHA pinning the most reliable immutable reference. [3]
  • If you want “version semantics” without SHAs, use tags from an immutable release (where the release’s tag can’t be moved). GitHub Docs: immutable releases lock the tag to a commit and generate release attestations. [4]
  • Org/enterprise enforcement (added in 2025): GitHub Actions policy can now require SHA pinning (and also block specific actions/versions), causing workflows that use non-SHA action refs to fail. [5]
  • Why this mattered in 2025: real incidents showed attackers repointing many existing tags to malicious commits (e.g., tj-actions/changed-files), which immediately impacted users who referenced tags. [6]

Rule of thumb:

  • For maximum reproducibility: pin every third-party action to a full commit SHA. [3]
  • For easier updates with guardrails: use SHA pinning + Dependabot/Renovate to propose upgrades (so updates are reviewed), or only trust immutable releases where available. [3][4]

Sources
[1] GitHub Docs — “Using immutable releases and tags to manage your action’s releases” (docs.github.com)
[2] OpenSSF — “Mitigating Attack Vectors in GitHub Workflows” (openssf.org)
[3] GitHub Well-Architected — “Securing GitHub Actions Workflows” (wellarchitected.github.com)
[4] GitHub Docs — “Immutable releases” (docs.github.com)
[5] GitHub Changelog (2025-08-15) — Actions policy supports blocking + SHA pinning (github.blog)
[6] StepSecurity — incident writeup referencing tag repointing compromises (Mar 2025) (stepsecurity.io)

Citations:


Pin actions to immutable commit SHAs.

Line 13 uses @v4 (a mutable major tag that moves with releases), and Line 14 uses @main (explicitly mutable). GitHub's security guidance recommends pinning both actions to full commit SHAs to improve reproducibility and reduce supply-chain risk.

Suggested change
-      - uses: actions/checkout@v4
-      - uses: weAretechnative/openspec-badge-action@main
+      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
+      - uses: weAretechnative/openspec-badge-action@<full_commit_sha>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/openspec-badge.yml around lines 13 - 14, Replace mutable
action references with immutable commit SHAs: change uses: actions/checkout@v4
to uses: actions/checkout@<commit-sha> and uses:
weAretechnative/openspec-badge-action@main to uses:
weAretechnative/openspec-badge-action@<commit-sha>; locate the two lines
containing actions/checkout and weAretechnative/openspec-badge-action in the
workflow file and update them to the exact commit SHAs (not tags or branches),
ensuring you pick the intended release commit for each action and verify the SHA
on the action repository before committing.

with:
metric_types: number_of_specs,open_changes,tasks_status
badge_style: classic
show_label: true
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
<a href="https://discord.gg/YctCnvvshC"><img alt="Discord" src="https://img.shields.io/discord/1411657095639601154?style=flat-square&logo=discord&logoColor=white&label=Discord&suffix=%20online" /></a>
</p>

<p align="center">
<img alt="Specs" src="https://raw.githubusercontent.com/Fission-AI/OpenSpec/gh-pages/badges/number_of_specs.svg" />
<img alt="Open Changes" src="https://raw.githubusercontent.com/Fission-AI/OpenSpec/gh-pages/badges/open_changes.svg" />
<img alt="Tasks Status" src="https://raw.githubusercontent.com/Fission-AI/OpenSpec/gh-pages/badges/tasks_status.svg" />
</p>

<details>
<summary><strong>The most loved spec framework.</strong></summary>

Expand Down
2 changes: 2 additions & 0 deletions openspec/changes/add-openspec-badges/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-26
58 changes: 58 additions & 0 deletions openspec/changes/add-openspec-badges/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
## Context

The OpenSpec README currently displays standard project badges (CI status, npm version, license, Discord) in a centered paragraph block. We want to add OpenSpec-specific metric badges using the weAretechnative/openspec-badge-action GitHub Action.

The action generates SVG badges and publishes them to the gh-pages branch. Badges are then referenced via raw.githubusercontent.com URLs.

## Goals / Non-Goals

**Goals:**
- Add three OpenSpec metric badges to README: number_of_specs, number_of_open_changes, number_of_open_tasks
- Configure GitHub Action workflow to generate badges on push to main
- Use classic style with labels enabled for visual consistency

**Non-Goals:**
- Modifying existing badge styling or arrangement
- Adding all available badge types (number_of_requirements, tasks_status)
- Custom badge colors or branding
Comment on lines +10 to +17
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Resolve metric-name contradictions in Goals/Non-Goals.

Goals/Non-Goals conflict with the actual decision and workflow (open_changes, tasks_status).

Suggested consistency fix
- - Add three OpenSpec metric badges to README: number_of_specs, number_of_open_changes, number_of_open_tasks
+ - Add three OpenSpec metric badges to README: number_of_specs, open_changes, tasks_status
...
- - Adding all available badge types (number_of_requirements, tasks_status)
+ - Adding additional badge types beyond the selected three (e.g., number_of_requirements)

Also applies to: 23-23

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/add-openspec-badges/design.md` around lines 10 - 17, Update
the Goals and Non-Goals sections so metric names are consistent with the
decision and workflow; replace ambiguous or conflicting names—ensure Goals list
uses the exact metric identifiers used elsewhere (number_of_specs,
number_of_open_changes, number_of_open_tasks) and remove or rename Non-Goals
entries that reference different identifiers (number_of_requirements,
tasks_status) to match the chosen metrics (e.g., change tasks_status →
number_of_open_tasks or list it explicitly as out-of-scope), and reflect the
workflow names (open_changes) exactly where referenced to eliminate
contradictions between Goals/Non-Goals and the workflow/decision text.


## Decisions

### 1. Badge Selection

**Decision:** Use `number_of_specs`, `open_changes` (for open changes), and `tasks_status` (shows open tasks ratio)

**Rationale:** These three metrics provide meaningful insight into project health:
- `number_of_specs` - shows specification coverage
- `open_changes` - shows active development work
- `tasks_status` - shows completion progress (displays as X/Y format)

**Alternative considered:** Include `number_of_requirements` - decided against to keep the badge row concise.

### 2. Badge Placement

**Decision:** Add a new `<p align="center">` block after the existing badges section (line 15), creating a distinct row for OpenSpec-specific badges.

**Rationale:** Keeps OpenSpec metrics visually grouped and separate from standard project badges (CI, npm, license, Discord).

**Alternative considered:** Inline with existing badges - would make the line too long and mix different badge categories.

### 3. Workflow Trigger

**Decision:** Trigger badge generation on push to main branch only.

**Rationale:** Badges should reflect the current state of the main branch. Running on PRs would be wasteful since those badges wouldn't be used.

### 4. Badge Style

**Decision:** Use `classic` style with `show_label: true`

**Rationale:** Classic style provides gradient appearance matching the shield.io badges used elsewhere. Labels provide context for what each metric represents.

## Risks / Trade-offs

**[gh-pages branch required]** → The action publishes to gh-pages branch. If the branch doesn't exist, the action will create it. This is expected behavior.

**[Badge URLs depend on repository path]** → Badge image URLs are hardcoded to the repository path. If the repo is forked, badge URLs would point to the original repo. → This is acceptable for the main repository; forks can update URLs if needed.

**[Action permissions]** → Workflow requires `contents: write` permission. → Standard for actions that commit to branches.
37 changes: 37 additions & 0 deletions openspec/changes/add-openspec-badges/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Why

The README currently displays CI, npm, license, and Discord badges but lacks visibility into OpenSpec-specific project health metrics. Adding OpenSpec badges will showcase the framework's own capabilities and provide at-a-glance insight into the project's specification coverage and change activity.

## What Changes

- Add a new row of OpenSpec badges to the README header section
- Configure the openspec-badge-action GitHub Action to generate badges
- Display three metrics: number of specs, open changes, and open tasks
- Use classic style with labels for consistency and clarity
Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align metric wording with implementation (tasks_status).

Line 9 says “open tasks”, but the implemented metric is tasks_status (ratio). Please use the same term here to avoid ambiguity.

Suggested doc fix
-- Display three metrics: number of specs, open changes, and open tasks
+- Display three metrics: number_of_specs, open_changes, and tasks_status
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Display three metrics: number of specs, open changes, and open tasks
- Use classic style with labels for consistency and clarity
- Display three metrics: number_of_specs, open_changes, and tasks_status
- Use classic style with labels for consistency and clarity
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openspec/changes/add-openspec-badges/proposal.md` around lines 9 - 10, Change
the wording "open tasks" to match the implemented metric name `tasks_status` (or
"tasks_status (ratio)" for clarity) so the proposal and implementation use the
same term; update the list line that currently reads “open tasks” to instead
read `tasks_status` (or `tasks_status (ratio)`) to avoid ambiguity and ensure
consistency with the implemented metric.


## Capabilities

### New Capabilities

- `readme-badges`: Configuration and display of OpenSpec metric badges in project README

### Modified Capabilities

None - this change adds new content to the README without modifying existing OpenSpec behavior.

## Impact

- **README.md**: New badge row added after the existing badges section
- **.github/workflows/**: New workflow file for badge generation
- **gh-pages branch**: Will store generated SVG badge files (created automatically by the action)
- **Repository settings**: Requires `contents: write` permission for the workflow

## Prerequisites for Project Owner

Before the badges will display correctly, the project owner must complete these steps after merging:

1. **Enable GitHub Pages**: Go to repository Settings → Pages → Set source to "Deploy from a branch" and select the `gh-pages` branch (root folder)
2. **Run the workflow**: The badge workflow must run at least once to generate the initial SVG files and create the gh-pages branch
3. **Verify permissions**: Ensure GitHub Actions has write access to the repository (Settings → Actions → General → Workflow permissions → "Read and write permissions")

Until these steps are completed, the badge images in the README will show as broken/missing.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## ADDED Requirements

### Requirement: OpenSpec badges displayed in README

The README SHALL display OpenSpec metric badges in a new row after the existing badges section, showing project health metrics generated by the openspec-badge-action.

#### Scenario: Badges visible in README
- **WHEN** a user views the README.md file
- **THEN** a row of three OpenSpec badges SHALL be visible below the existing CI/npm/license/Discord badges

#### Scenario: Badge row contains correct metrics
- **WHEN** the OpenSpec badge row is displayed
- **THEN** it SHALL contain badges for: number_of_specs, open_changes, and tasks_status metrics

### Requirement: Badge generation workflow

The repository SHALL include a GitHub Actions workflow that generates OpenSpec metric badges using the weAretechnative/openspec-badge-action.

#### Scenario: Workflow triggers on main branch push
- **WHEN** code is pushed to the main branch
- **THEN** the badge generation workflow SHALL execute

#### Scenario: Workflow generates specified metrics
- **WHEN** the badge workflow executes
- **THEN** it SHALL generate badges for: number_of_specs, open_changes, and tasks_status

#### Scenario: Workflow uses classic style with labels
- **WHEN** the badge workflow executes
- **THEN** it SHALL use `badge_style: classic` and `show_label: true` configuration

### Requirement: Badge images accessible via gh-pages

The generated badge SVG files SHALL be published to the gh-pages branch and accessible via raw.githubusercontent.com URLs.

#### Scenario: Badges published to gh-pages
- **WHEN** the badge workflow completes successfully
- **THEN** SVG badge files SHALL exist in the gh-pages branch under the badges/ directory

#### Scenario: README references correct badge URLs
- **WHEN** the README displays OpenSpec badges
- **THEN** each badge image URL SHALL follow the pattern: `https://raw.githubusercontent.com/Fission-AI/OpenSpec/gh-pages/badges/<metric_name>.svg`
29 changes: 29 additions & 0 deletions openspec/changes/add-openspec-badges/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## 1. GitHub Action Workflow

- [x] 1.1 Create `.github/workflows/openspec-badge.yml` workflow file
- [x] 1.2 Configure workflow to trigger on push to main branch
- [x] 1.3 Add checkout step with actions/checkout@v4
- [x] 1.4 Configure weAretechnative/openspec-badge-action with metric_types, badge_style, and show_label
- [x] 1.5 Set contents: write permission for the workflow

## 2. README Badge Integration

- [x] 2.1 Add new centered paragraph block after existing badges (line 15)
- [x] 2.2 Add number_of_specs badge with raw.githubusercontent.com URL
- [x] 2.3 Add open_changes badge with raw.githubusercontent.com URL
- [x] 2.4 Add tasks_status badge with raw.githubusercontent.com URL

## 3. Verification

- [x] 3.1 Verify workflow YAML syntax is valid
- [x] 3.2 Verify README markdown renders correctly

## 4. Post-Merge (Project Owner)

> **Note:** These tasks must be completed by the project owner after the PR is merged.
> Badges will appear broken until these steps are done.

- [ ] 4.1 Verify GitHub Actions workflow permissions allow write access (Settings → Actions → General → Workflow permissions)
- [ ] 4.2 Manually trigger or wait for the badge workflow to run on main branch
- [ ] 4.3 Enable GitHub Pages with gh-pages branch as source (Settings → Pages)
- [ ] 4.4 Verify badges display correctly in README
Loading