-
Notifications
You must be signed in to change notification settings - Fork 43
Bootstrap formal specification infrastructure, agent skills, and codebase reference docs #1142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4b96892
3d1cfa6
0bab907
dac39f0
83f7607
5153256
88f1cb7
a06f418
26dd95c
f84ebc6
5084042
9efc2a6
36bfa68
5c92873
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Agent Skills | ||
|
|
||
| This directory contains agent skill descriptors for the SSVC repository. | ||
| Skills are Markdown files that describe capabilities an AI coding agent can | ||
| invoke to perform structured tasks. | ||
|
|
||
| ## Two-tier taxonomy | ||
|
|
||
| | Tier | Path | Audience | Purpose | | ||
| |------|------|----------|---------| | ||
| | **dev** | `.agents/skills/dev/` | Agents working on the SSVC codebase | Support SSVC development workflows (spec ingestion, codebase study, concern tracking, etc.) | | ||
| | **ssvc** | `.agents/skills/ssvc/` | Agents helping practitioners apply SSVC | SSVC domain work (evaluating decision points, building custom tables, etc.) | | ||
|
|
||
| ## Canonical SKILL.md format | ||
|
|
||
| Every skill directory must contain a `SKILL.md` file. Required front-matter: | ||
|
|
||
| ```yaml | ||
| --- | ||
| name: "skill-name" # unique, kebab-case | ||
| description: > | ||
| One or more sentences describing what the skill does and when to invoke it. | ||
| --- | ||
| ``` | ||
|
|
||
| Optional front-matter fields (add when stable): | ||
| `id`, `version`, `tags`, `runtime`, `capabilities`, `prerequisites`, `env`, | ||
| `usage_examples`. | ||
|
|
||
| After the front-matter, every `SKILL.md` must contain: | ||
|
|
||
| 1. `## Purpose` — one paragraph explaining what the skill is for | ||
| 2. At least one procedural section (`## Procedure` or `## Workflow`) | ||
|
|
||
| ## Adding a new skill | ||
|
|
||
| 1. Choose the correct tier (`dev/` or `ssvc/`). | ||
| 2. Create `<tier>/<skill-name>/SKILL.md` with required front-matter, a | ||
| `## Purpose` section, and at least one procedural section. | ||
| 3. Validate locally: | ||
| ```bash | ||
| python -c " | ||
| import pathlib, yaml, sys | ||
| errs = [] | ||
| for p in pathlib.Path('.agents/skills').rglob('SKILL.md'): | ||
| fm = yaml.safe_load(p.read_text().split('---', 2)[1]) | ||
| if not fm or not fm.get('name') or not fm.get('description'): | ||
| errs.append(str(p)) | ||
| print('FAIL:', errs) if errs else print('OK') | ||
| " | ||
| ``` | ||
| 4. Open a PR — the `validate_skills` CI job runs automatically. | ||
|
|
||
| ## CI validation | ||
|
|
||
| The workflow `.github/workflows/validate_skills.yml` runs on every PR and | ||
| push to `main` when any `SKILL.md` changes. It checks that every skill has | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure about this? |
||
| valid YAML front-matter with non-empty `name` and `description` fields. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,296 @@ | ||
| --- | ||
| name: ingest-idea | ||
| description: > | ||
| Process a raw design idea from a GitHub Idea-type issue into formal specs | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is a GitHub Idea? |
||
| and implementation notes, then close the idea issue, open a docs-only PR, | ||
| and create a GitHub implementation Issue as a sub-issue of the idea issue. | ||
| Runs a structured interview (grill-me), writes specs/<topic>.yaml and | ||
| notes/<topic>.md, archives the idea to plan/history/, opens a docs-only PR | ||
| with the specs-notes label, and creates a GitHub Issue tagged | ||
| group:unscheduled. Use when the user says "ingest idea", references a GitHub | ||
| Idea issue number, or wants to convert an idea into spec and notes files. | ||
| --- | ||
|
|
||
| # Skill: Ingest Idea | ||
|
|
||
| Convert a GitHub Idea-type issue into durable specs and notes, then close the | ||
| idea issue and open a docs-only PR. This is the full end-to-end workflow: | ||
| interview → write → archive → PR → implementation issue. | ||
|
|
||
| ## Workflow | ||
|
|
||
| ### 1. Identify the target idea | ||
|
|
||
| If the user specified a GitHub issue number (e.g., `#42` or just `42`), | ||
| skip to step 2. | ||
|
|
||
| Otherwise, query GitHub for open Idea-type issues and present them to the | ||
| user as a multiple-choice list using `ask_user`. Include a **"Create a new | ||
| idea"** option at the end. | ||
|
|
||
| ```bash | ||
| gh issue list --repo CERTCC/SSVC \ | ||
| --limit 200 \ | ||
| --json number,title,issueType \ | ||
| --jq '.[] | select(.issueType.name == "Idea") | "#\(.number): \(.title)"' | ||
| ``` | ||
|
|
||
| Build a `choices` array from the results (e.g. `["#42: Exploitation signal", | ||
| "#51: Decision point refactor", "Create a new idea"]`). Wait for the user's | ||
| selection before continuing. | ||
|
|
||
| #### 1a. Creating a new idea (if selected) | ||
|
|
||
| Ask the user to describe the idea in freeform text (using `ask_user`). | ||
| Synthesize a short, descriptive title from the description, then create | ||
| a GitHub Idea-type issue: | ||
|
|
||
| ```bash | ||
| IDEA_BODY="<freeform description from user>" | ||
| IDEA_TITLE="<synthesized title>" | ||
| REPO_NODE_ID="MDEwOlJlcG9zaXRvcnkyMzU4MDkzNTU=" | ||
| IDEA_TYPE_ID="IT_kwDOAjf0s84B_EoA" | ||
|
|
||
| TITLE_JSON=$(printf '%s' "${IDEA_TITLE}" \ | ||
| | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))") | ||
| BODY_JSON=$(printf '%s' "${IDEA_BODY}" \ | ||
| | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))") | ||
|
|
||
| IDEA_NUMBER=$(gh api graphql -f query=" | ||
| mutation { | ||
| createIssue(input: { | ||
| repositoryId: \"${REPO_NODE_ID}\" | ||
| title: ${TITLE_JSON} | ||
| body: ${BODY_JSON} | ||
| issueTypeId: \"${IDEA_TYPE_ID}\" | ||
| }) { | ||
| issue { number } | ||
| } | ||
| }" --jq '.data.createIssue.issue.number') | ||
| echo "Created idea issue #${IDEA_NUMBER}" | ||
| ``` | ||
|
|
||
| Continue with step 2 using `IDEA_NUMBER`. | ||
|
|
||
| ### 2. Read the idea | ||
|
|
||
| Fetch the idea from GitHub: | ||
|
|
||
| ```bash | ||
| gh issue view "${IDEA_NUMBER}" --repo CERTCC/SSVC --json number,title,body | ||
| ``` | ||
|
|
||
| Use the issue title and body as the idea content for all subsequent steps. | ||
|
|
||
| ### 3. Explore the codebase | ||
|
|
||
| Invoke the `study-project-docs` skill. It loads all specs, reads plan/, | ||
| docs/adr/, notes/, and docs/reference/code/, and scans src/ssvc/ and | ||
| src/test/. | ||
|
|
||
| Answer questions from exploration rather than asking the user where possible. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the LLM process this instruction well? |
||
|
|
||
| ### 4. Interview with grill-me | ||
|
|
||
| Invoke the `grill-me` skill. Follow its instructions to walk every design | ||
| decision branch one at a time using `ask_user`, providing a recommendation | ||
| for each question. Reach shared understanding before writing anything. | ||
|
|
||
| ### 5. Write the spec file | ||
|
|
||
| Create or modify `specs/<topic>.yaml` following `specs/meta-specifications.yaml` | ||
| conventions and the ID scheme already in use: | ||
|
|
||
| - Use a `FILE_PREFIX-SECTION_#-###` ID scheme (e.g., `EX-01-001`) | ||
| - Define requirements as YAML structures with RFC 2119 keywords | ||
| - Include an overview section with source reference and scope note | ||
| - Organize by category with clear section headings | ||
|
|
||
| ### 6. Write the notes file | ||
|
|
||
| Create or modify `notes/<topic>.md` with implementation guidance: | ||
|
|
||
| - Decision table (question → decision → rationale) | ||
| - Key design patterns and code examples | ||
| - Call-site migration guide if replacing existing patterns | ||
| - Testing pattern examples | ||
| - Layer / import rules relevant to the change | ||
|
|
||
| ### 7. Update specs/README.md | ||
|
|
||
| Add the new spec to both: | ||
|
|
||
| - The **Spec Files** table (file → ID → Kind → Topic) | ||
| - The **ID Prefix Convention** section if a new prefix is introduced | ||
|
|
||
| ### 8. Lint markdown | ||
|
|
||
| Invoke the `format-markdown` skill on all new/modified markdown files. Fix | ||
| any errors before proceeding. | ||
|
|
||
| ### 9. Archive the idea | ||
|
|
||
| Append a record to `plan/history/ideas.md` (create the file if it doesn't | ||
| exist). Include the full original idea text with a `**Processed**` line: | ||
|
|
||
| ```bash | ||
| DATE=$(date +%Y-%m-%d) | ||
| cat >> plan/history/ideas.md <<ENDOFENTRY | ||
|
|
||
| --- | ||
|
|
||
| ## IDEA-${IDEA_NUMBER}: <short idea title> | ||
|
|
||
| <full idea title and body here> | ||
|
|
||
| **Processed**: ${DATE} — design decisions captured in | ||
| \`specs/<topic>.yaml\` and \`notes/<topic>.md\`. | ||
| ENDOFENTRY | ||
| ``` | ||
|
|
||
| ### 10. Open a docs-only PR | ||
|
|
||
| Create a branch, commit all spec/notes/README changes, and open a PR | ||
| carrying the `specs-notes` label. Reference the originating idea issue in | ||
| the PR body so GitHub auto-links them: | ||
|
|
||
| ```bash | ||
| git switch -c ingest/idea-<IDEA_NUMBER>-<slug> | ||
| git add specs/<topic>.yaml notes/<topic>.md specs/README.md plan/history/ideas.md | ||
| git commit -m "specs: ingest idea #<IDEA_NUMBER> — <short title> | ||
|
|
||
| - Add specs/<topic>.yaml (ID-01 through ID-NN) | ||
| - Add notes/<topic>.md with implementation guidance | ||
| - Archive idea #<IDEA_NUMBER> to plan/history/ideas.md | ||
|
|
||
| Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this hardcode to copilot? |
||
| git push -u origin ingest/idea-<IDEA_NUMBER>-<slug> | ||
|
|
||
| gh pr create --repo CERTCC/SSVC \ | ||
| --title "specs: ingest idea #<IDEA_NUMBER> — <short title>" \ | ||
| --body "Docs-only PR: adds spec and notes for idea #<IDEA_NUMBER>. | ||
|
|
||
| Ref #<IDEA_NUMBER> | ||
|
|
||
| No .py files changed." \ | ||
| --label "specs-notes" | ||
| ``` | ||
|
|
||
| ### 11. Create a GitHub Issue for implementation | ||
|
|
||
| After opening the docs-only PR, create a GitHub Issue to track implementation. | ||
| Wire the idea issue as the **parent** of the new implementation issue: | ||
|
|
||
| ```bash | ||
| IMPL_ISSUE_NUMBER=$(gh api graphql -f query=" | ||
| mutation { | ||
| createIssue(input: { | ||
| repositoryId: \"MDEwOlJlcG9zaXRvcnkyMzU4MDkzNTU=\" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also looks like a problem for hardcoding. |
||
| title: \"<Implementation title from spec>\" | ||
| body: \"## Summary\n\n<Description from spec — one paragraph>\n\n## Acceptance Criteria\n\n- [ ] AC-1: <from spec>\n- [ ] AC-2: <from spec>\n\n## Reference\n\nSpec: \`specs/<topic>.yaml\`\nNotes: \`notes/<topic>.md\`\" | ||
| issueTypeId: \"IT_kwDOAjf0s84AcFLs\" | ||
| labelIds: [\"<group:unscheduled label node ID>\", \"<size: label node ID>\"] | ||
| }) { | ||
| issue { number } | ||
| } | ||
| }" --jq '.data.createIssue.issue.number') | ||
| ``` | ||
|
|
||
| If the GraphQL label approach is cumbersome, fall back to `gh issue create` | ||
| and then set the parent relationship and labels separately: | ||
|
|
||
| ```bash | ||
| IMPL_ISSUE_NUMBER=$(gh issue create --repo CERTCC/SSVC \ | ||
| --title "<Implementation title from spec>" \ | ||
| --body "## Summary | ||
|
|
||
| <Description from spec — one paragraph> | ||
|
|
||
| ## Acceptance Criteria | ||
|
|
||
| - [ ] AC-1: <from spec> | ||
| - [ ] AC-2: <from spec> | ||
|
|
||
| ## Reference | ||
|
|
||
| Spec: \`specs/<topic>.yaml\` | ||
| Notes: \`notes/<topic>.md\`" \ | ||
| --label "group:unscheduled,size:<S|M|L>" \ | ||
| | grep -oE '[0-9]+$') | ||
|
|
||
| # Wire idea as parent of implementation issue | ||
| gh api graphql -f query=" | ||
| mutation { | ||
| updateIssue(input: { | ||
| id: \"<impl_issue_node_id>\" | ||
| parentId: \"<idea_issue_node_id>\" | ||
| }) { issue { number } } | ||
| }" | ||
| ``` | ||
|
|
||
| Set the `size:` label based on AC checkbox count: | ||
| 1–2 ACs → `size:S`; 3–6 ACs → `size:M`; 7+ ACs → `size:L`. | ||
|
|
||
| The implementation Issue sits in `group:unscheduled` until a human runs | ||
| `review-priorities` to slot it into `plan/PRIORITIES.md`. | ||
|
|
||
| After creating the implementation issue, post the closing comment on the | ||
| idea issue and close it: | ||
|
|
||
| ```bash | ||
| gh issue comment "${IDEA_NUMBER}" --repo CERTCC/SSVC \ | ||
| --body "✅ Ingested. | ||
|
|
||
| - Docs PR: <PR_URL> | ||
| - Implementation issue: #${IMPL_ISSUE_NUMBER} | ||
|
|
||
| Design decisions captured in \`specs/<topic>.yaml\` and \`notes/<topic>.md\`." | ||
|
|
||
| gh issue close "${IDEA_NUMBER}" --repo CERTCC/SSVC | ||
| ``` | ||
|
|
||
| ## Checklist | ||
|
|
||
| - [ ] Target idea issue confirmed (specified by user, selected from list, or | ||
| created inline) | ||
| - [ ] Idea content fetched from GitHub issue | ||
| - [ ] Codebase explored via `study-project-docs` before grilling | ||
| - [ ] All design decision branches resolved via grill-me | ||
| - [ ] `specs/<topic>.yaml` created with correct ID scheme | ||
| - [ ] `notes/<topic>.md` created with decision table + examples | ||
| - [ ] `specs/README.md` updated (Spec Files table + ID Prefix section if new) | ||
| - [ ] Markdown lint clean | ||
| - [ ] Idea archived to `plan/history/ideas.md` | ||
| - [ ] Docs-only PR opened with `specs-notes` label and `Ref #<idea_number>` | ||
| in body | ||
| - [ ] Implementation GitHub Issue created with `group:unscheduled` and | ||
| `size:` labels; idea issue wired as parent | ||
| - [ ] Idea issue commented with links to PR and implementation issue, then | ||
| closed | ||
|
|
||
| ## Conventions | ||
|
|
||
| - **Spec file names**: use the topic name, lowercase hyphenated with `.yaml` | ||
| extension (e.g., `exploitation.yaml`, `decision-points.yaml`) | ||
| - **ID prefix**: derive from the topic abbreviation (e.g., `EX`, `DP`) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where are topic abbreviations defined? |
||
| - **Notes file name**: same slug as spec file with `.md` extension, in | ||
| `notes/` (e.g., `exploitation.md`, `decision-points.md`) | ||
| - **History archive**: append to `plan/history/ideas.md` using source ID | ||
| `IDEA-<github_issue_number>` | ||
|
|
||
| ## Label Naming Rules | ||
|
|
||
| All new Issues use `group:unscheduled` by default. If assigning a specific | ||
| `group:` label: | ||
|
|
||
| - **Never include a priority number** in the label name. | ||
| Use `group:architecture-hardening`, **not** `group:473-architecture-hardening`. | ||
| - **Derive the slug** from the priority group title in kebab-case. | ||
| - **Check for label existence** before assigning. Create it if missing: | ||
|
|
||
| ```bash | ||
| gh label create "group:<slug>" \ | ||
| --repo CERTCC/SSVC \ | ||
| --description "<Priority group title (no number)>" \ | ||
| --color "#1d76db" | ||
| ``` | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the agent skills have frontmatter not in this list.