Merge pull request #2 from LucasErcolano/codex/github-management-infra

Add GitHub management infrastructure
This commit is contained in:
Joaquín Cadeiras 2026-04-14 20:01:06 -03:00 committed by GitHub
commit 5c824b66a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 441 additions and 0 deletions

53
.github/ISSUE_TEMPLATE/bug.yml vendored Normal file
View File

@ -0,0 +1,53 @@
name: Bug
description: Report a defect that needs investigation or a fix
title: "[Bug] "
labels:
- "type:bug"
body:
- type: markdown
attributes:
value: |
Use this template for broken or incorrect behavior. Include enough detail to reproduce the issue.
- type: textarea
id: current_behavior
attributes:
label: Current behavior
description: What is happening now?
placeholder: Describe the observed behavior.
validations:
required: true
- type: textarea
id: expected_behavior
attributes:
label: Expected behavior
description: What should happen instead?
placeholder: Describe the correct or intended behavior.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
description: How can someone reproduce the issue?
placeholder: |
1. Go to ...
2. Run ...
3. Observe ...
validations:
required: true
- type: textarea
id: impact
attributes:
label: Impact
description: Who or what is affected, and how severe is it?
placeholder: Explain user impact, system impact, or urgency.
validations:
required: true
- type: textarea
id: done_criteria
attributes:
label: Done criteria
description: What confirms the bug is fixed?
placeholder: Define the validation or acceptance conditions.
validations:
required: true

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions about setup or usage
url: https://github.com/LucasErcolano/MiroFish/blob/main/README.md
about: Check the project README before opening a workflow issue for general usage questions.
- name: Community chat on Discord
url: http://discord.gg/ePf5aPaHnA
about: Use Discord for broad questions, discussions, or community support.

60
.github/ISSUE_TEMPLATE/epic.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Epic
description: Coordinating issue for a larger body of work
title: "[Epic] "
labels:
- "type:epic"
body:
- type: markdown
attributes:
value: |
Use this template for a larger initiative that will be split into smaller issues.
- type: textarea
id: objective
attributes:
label: Objective
description: What outcome should this epic deliver?
placeholder: Describe the main goal and the value this epic should create.
validations:
required: true
- type: textarea
id: scope
attributes:
label: Scope
description: What is included in this epic?
placeholder: List the work this epic should cover.
validations:
required: true
- type: textarea
id: out_of_scope
attributes:
label: Out of scope
description: What is explicitly not part of this epic?
placeholder: Capture boundaries to keep the work focused.
validations:
required: true
- type: textarea
id: dependencies
attributes:
label: Dependencies
description: What work, systems, or decisions does this depend on?
placeholder: Reference related issues, external dependencies, or blockers.
validations:
required: false
- type: textarea
id: done_criteria
attributes:
label: Done criteria
description: How will we know this epic is complete?
placeholder: Define the conditions required to close this epic.
validations:
required: true
- type: textarea
id: subissues
attributes:
label: Sub-issues checklist
description: List the issues that should roll up into this epic.
placeholder: |
- [ ] #123
- [ ] Create issue for ...
validations:
required: true

50
.github/ISSUE_TEMPLATE/spike.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: Spike
description: Time-boxed investigation or research task
title: "[Spike] "
labels:
- "type:spike"
body:
- type: markdown
attributes:
value: |
Use this template for research or technical exploration that should end with a recommendation.
- type: textarea
id: question
attributes:
label: Question to answer
description: What decision or uncertainty is this spike meant to resolve?
placeholder: State the main question as clearly as possible.
validations:
required: true
- type: textarea
id: options
attributes:
label: Options to evaluate
description: Which alternatives should be compared?
placeholder: List the candidate approaches or tools to investigate.
validations:
required: true
- type: textarea
id: deliverable
attributes:
label: Expected deliverable
description: What output should this spike produce?
placeholder: "Example: recommendation, benchmark, decision memo, or migration notes."
validations:
required: true
- type: textarea
id: done_criteria
attributes:
label: Done criteria
description: What needs to happen before this spike can be closed?
placeholder: Define the minimum evidence or conclusion expected.
validations:
required: true
- type: input
id: deadline
attributes:
label: Target date
description: Optional deadline for the spike
placeholder: YYYY-MM-DD
validations:
required: false

52
.github/ISSUE_TEMPLATE/task.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: Task
description: Actionable implementation task
title: "[Task] "
labels:
- "type:task"
body:
- type: markdown
attributes:
value: |
Use this template for a focused piece of work that should usually land in a single pull request.
- type: textarea
id: context
attributes:
label: Context
description: What problem or opportunity is this task addressing?
placeholder: Summarize the relevant context and why this task matters.
validations:
required: true
- type: textarea
id: expected_result
attributes:
label: Expected result
description: What should be true once this task is complete?
placeholder: Describe the intended outcome in concrete terms.
validations:
required: true
- type: textarea
id: acceptance_criteria
attributes:
label: Acceptance criteria
description: What conditions must be met before this can be closed?
placeholder: |
- [ ] ...
- [ ] ...
validations:
required: true
- type: textarea
id: dependencies
attributes:
label: Dependencies
description: What related issues, decisions, or blockers affect this task?
placeholder: Reference anything this task needs before it can start or finish.
validations:
required: false
- type: textarea
id: technical_notes
attributes:
label: Technical notes
description: Optional implementation notes, caveats, or pointers
placeholder: Include technical details that will help the implementer.
validations:
required: false

37
.github/labels.yml vendored Normal file
View File

@ -0,0 +1,37 @@
labels:
- name: "type:epic"
color: "5319e7"
description: "Large coordinating issue that groups related work"
- name: "type:task"
color: "0e8a16"
description: "Actionable implementation task"
- name: "type:spike"
color: "fbca04"
description: "Time-boxed research or technical investigation"
- name: "type:bug"
color: "d73a4a"
description: "Defect or incorrect behavior that requires a fix"
- name: "area:llm"
color: "1d76db"
description: "Work related to LLM providers, routing, or inference"
- name: "area:memory"
color: "0052cc"
description: "Work related to conversation memory or persistence"
- name: "area:rag"
color: "0e4e8a"
description: "Work related to retrieval, indexing, or knowledge access"
- name: "area:planning"
color: "5319e7"
description: "Work related to planning, orchestration, or agent coordination"
- name: "area:infra"
color: "c2e0c6"
description: "Repository, tooling, CI, or operational infrastructure work"
- name: "area:eval"
color: "bfdadc"
description: "Benchmarks, experiments, or evaluation work"
- name: "blocked"
color: "b60205"
description: "Cannot progress until a dependency or blocker is resolved"
- name: "good first issue"
color: "7057ff"
description: "Good candidate for a newcomer to the project"

15
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,15 @@
## Linked issue
Closes #
## What changed
Describe the changes in this pull request.
## How to test
Describe the verification steps. If no runtime test applies, explain why.
## Risks
List known risks, follow-up work, or rollout considerations.

57
.github/workflows/pr-hygiene.yml vendored Normal file
View File

@ -0,0 +1,57 @@
name: PR Hygiene
on:
pull_request:
types:
- opened
- edited
- reopened
- synchronize
permissions:
contents: read
pull-requests: read
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Validate pull request body
uses: actions/github-script@v7
with:
script: |
const body = context.payload.pull_request.body || "";
function getSection(title) {
const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const regex = new RegExp(`##\\s+${escaped}\\s*\\n([\\s\\S]*?)(?=\\n##\\s+|$)`, "i");
const match = body.match(regex);
return match ? match[1].trim() : "";
}
const linkedIssue = getSection("Linked issue");
const howToTest = getSection("How to test");
const hasIssueReference =
/#\d+/.test(linkedIssue) ||
/https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/issues\/\d+/i.test(linkedIssue);
const sanitizedHowToTest = howToTest
.replace(/Describe the verification steps\. If no runtime test applies, explain why\./i, "")
.trim();
const failures = [];
if (!hasIssueReference) {
failures.push("Add an issue reference under `## Linked issue` (for example `Closes #123`).");
}
if (!sanitizedHowToTest) {
failures.push("Fill in `## How to test` with verification steps or explain why no runtime test applies.");
}
if (failures.length > 0) {
core.setFailed(failures.join("\n"));
} else {
core.info("Pull request body passed hygiene checks.");
}

109
.github/workflows/sync-labels.yml vendored Normal file
View File

@ -0,0 +1,109 @@
name: Sync Labels
on:
workflow_dispatch:
push:
paths:
- ".github/labels.yml"
permissions:
contents: read
issues: write
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: python -m pip install --disable-pip-version-check pyyaml
- name: Sync labels
env:
GITHUB_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
python - <<'PY'
import json
import os
import urllib.error
import urllib.parse
import urllib.request
import yaml
token = os.environ["GITHUB_TOKEN"]
owner_repo = os.environ["GITHUB_REPOSITORY"]
base_url = f"https://api.github.com/repos/{owner_repo}"
with open(".github/labels.yml", "r", encoding="utf-8") as fh:
config = yaml.safe_load(fh) or {}
desired_labels = config.get("labels", [])
desired_by_name = {label["name"]: label for label in desired_labels}
headers = {
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"X-GitHub-Api-Version": "2022-11-28",
"User-Agent": "mirofish-label-sync",
}
def request(method, url, payload=None):
data = None
if payload is not None:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req) as response:
raw = response.read()
return json.loads(raw.decode("utf-8")) if raw else None
existing = []
page = 1
while True:
url = f"{base_url}/labels?per_page=100&page={page}"
batch = request("GET", url)
if not batch:
break
existing.extend(batch)
if len(batch) < 100:
break
page += 1
existing_by_name = {label["name"]: label for label in existing}
for name, desired in desired_by_name.items():
payload = {
"new_name": desired["name"],
"color": desired["color"],
"description": desired["description"],
}
if name in existing_by_name:
url = f"{base_url}/labels/{urllib.parse.quote(name, safe='')}"
request("PATCH", url, payload)
print(f"updated {name}")
else:
url = f"{base_url}/labels"
request("POST", url, {
"name": desired["name"],
"color": desired["color"],
"description": desired["description"],
})
print(f"created {name}")
for name in sorted(existing_by_name):
if name not in desired_by_name:
url = f"{base_url}/labels/{urllib.parse.quote(name, safe='')}"
try:
request("DELETE", url)
print(f"deleted {name}")
except urllib.error.HTTPError as exc:
raise RuntimeError(f"Failed to delete label '{name}': {exc.read().decode('utf-8')}") from exc
PY