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
59 changes: 10 additions & 49 deletions .github/ISSUE_TEMPLATE/1-bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ body:
- type: markdown
attributes:
value: |
Lead with the error. A worked example lives in
[EXAMPLE.md](../blob/HEAD/.github/ISSUE_TEMPLATE/EXAMPLE.md).
CI pipeline failures go to
[l9-ci-debt-resolver](https://github.com/Quantum-L9/l9-ci-debt-resolver/issues/new)
instead — that component owns failure diagnosis.

- type: textarea
id: problem
attributes:
label: Problem
description: The symptom you observed, in one or two sentences. Not your theory.
placeholder: Agent runs abort at ~70% of the context limit with BudgetExceeded.
validations:
required: true

- type: textarea
id: evidence
attributes:
label: Error output
description: Full traceback, failing assertion, alert, or log line. Redact secrets.
description: Traceback, failing assertion, or log line. Redact secrets.
render: shell
validations:
required: true
Expand All @@ -31,75 +31,36 @@ body:
id: reproduce
attributes:
label: Reproduction
description: Exact commands from a clean checkout. A failing test is ideal.
value: |
1. `git clone … && cd …`
2. `uv sync`
3. `pytest tests/test_x.py::test_y`
description: Steps from a clean checkout. Best effort is fine.
render: shell
validations:
required: true

- type: input
id: expected
attributes:
label: Expected behavior
placeholder: Budget reports the actual measured token count.
validations:
required: true

- type: input
id: version
attributes:
label: Version / commit
description: Release tag or full commit SHA. "latest" is not a version.
placeholder: v0.9.3 or 4f2a1c9
validations:
required: true
description: Release tag or SHA if you have it.

- type: dropdown
id: severity
attributes:
label: Severity
description: This routes triage. Be honest; inflation gets ignored.
description: Routes triage. Advisory only — nothing is blocked by this.
options:
- S4 — cosmetic or minor annoyance
- S4 — cosmetic
- S3 — degraded, workaround exists
- S2 — major function broken, no workaround
- S1 — production down, data loss, or security exposure
validations:
required: true

- type: dropdown
id: env
attributes:
label: Environment
multiple: true
options: [local (macOS), local (Linux), CI (GitHub Actions), dev, staging, prod]
validations:
required: true

- type: input
id: regression
attributes:
label: Last known good version
description: Leave blank if it never worked. If set, a bisect range is implied.
placeholder: v0.9.1
description: If set, implies a bisect range. Leave blank if unknown.

- type: textarea
id: context
attributes:
label: Anything else
description: Suspected cause, related issues, screenshots, workaround in use.

- type: checkboxes
id: gates
attributes:
label: Before submitting
options:
- label: I searched open and closed issues for a duplicate.
required: true
- label: I reproduced this on the latest release or main.
required: true
- label: No secrets, tokens, or customer data appear anywhere above.
required: true
description: Suspected cause, related issues, workaround in use.
57 changes: 18 additions & 39 deletions .github/ISSUE_TEMPLATE/2-feature.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,52 @@ body:
id: problem
attributes:
label: Problem
description: The user-facing pain, not the solution. Who is blocked, and on what?
placeholder: Operators cannot tell which agent consumed a token budget, so cost overruns are diagnosed by guesswork.
description: The pain, not the solution. Who is blocked, and on what?
validations:
required: true

- type: textarea
id: today
attributes:
label: What you do today
description: The current workaround and its cost in time, money, or risk.
validations:
required: true
description: Current workaround and its cost.

- type: textarea
id: proposal
attributes:
label: Proposed behavior
description: What should exist. Include the interface — CLI flag, API shape, config key.
render: shell
description: What should exist. Include the interface if you know it.
validations:
required: true

- type: textarea
id: alternatives
- type: dropdown
id: owner
attributes:
label: Alternatives considered
description: Options you rejected and why. "None" usually means the problem is underexplored.
label: Which component should own this?
description: Prevents governance from absorbing CI concerns.
options:
- this repo (org governance / community health)
- l9-ci-sdk or l9-ci-core (test, lint, build execution)
- l9-ci-debt-resolver (CI failure diagnosis or remediation)
- l9-ci-debt-intelligence (CI debt measurement)
- unsure
validations:
required: true

- type: textarea
id: done
id: alternatives
attributes:
label: Definition of done
description: Observable, checkable outcomes. This becomes the acceptance criteria.
value: |
- [ ]
- [ ]
validations:
required: true
label: Alternatives considered
description: Options you rejected and why.

- type: dropdown
id: scope
attributes:
label: Scope
options:
- S — under a day, one file or module
- S — under a day
- M — a few days, one repo
- L — multi-repo or migration required
- L — multi-repo or migration
- XL — needs a design doc first
validations:
required: true

- type: dropdown
id: breaking
attributes:
label: Breaking change?
options: ["No", "Yes — behind a flag", "Yes — requires a major bump"]
validations:
required: true

- type: checkboxes
id: gates
attributes:
label: Before submitting
options:
- label: I searched for an existing request covering this.
required: true
- label: This is a concrete capability, not an open-ended question (those go to Discussions).
required: true
15 changes: 3 additions & 12 deletions .github/ISSUE_TEMPLATE/3-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ body:
id: problem
attributes:
label: Problem
description: Why this work exists. What breaks or degrades if it is never done?
description: Why this work exists. What degrades if it is never done?
validations:
required: true

- type: textarea
id: work
attributes:
label: Work
description: The steps. Each line should be independently verifiable.
value: |
- [ ]
- [ ]
Expand All @@ -26,20 +25,12 @@ body:
id: kind
attributes:
label: Kind
options: [chore, refactor, infra / IaC, CI / CD, docs, dependency bump, test coverage]
validations:
required: true

- type: textarea
id: risk
attributes:
label: Risk and rollback
description: Blast radius if this goes wrong, and how to undo it.
options: [chore, refactor, infra / IaC, governance, docs, dependency bump]
validations:
required: true

- type: input
id: blocks
attributes:
label: Blocks / blocked by
placeholder: "blocked by #1191, blocks #1204"
placeholder: "blocked by #12, blocks #34"
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ contact_links:
- name: 🔐 Report a security vulnerability
url: https://github.com/Quantum-L9/.github/security/advisories/new
about: Do NOT open a public issue. Use a private security advisory.
- name: 🔧 CI failure or flaky pipeline
url: https://github.com/Quantum-L9/l9-ci-debt-resolver/issues/new
about: CI diagnosis and remediation is owned by l9-ci-debt-resolver, not here.
- name: 💬 Question or design discussion
url: https://github.com/orgs/Quantum-L9/discussions
about: Open-ended questions, architecture debate, and "how do I…" belong in Discussions.
Expand Down
5 changes: 5 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
<!-- Canonical org-wide PR template. Correct path: .github/pull_request_template.md
inside the Quantum-L9/.github repo's own .github/ folder. A copy at repo ROOT
does NOT propagate org-wide — GitHub only reads the nested path.
See docs/AUDIT.md, finding #1. -->

## Problem

<!-- REQUIRED. The error, bug, or gap this fixes. Lead with the symptom a human saw.
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/governance-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ jobs:
body: `> [!CAUTION]\n> Possible **${hits.join(', ')}** in this issue. Edit it out and **rotate the credential** — edit history is public.` });
}
if (add.size) await github.rest.issues.addLabels({ ...context.repo, issue_number: context.payload.issue.number, labels: [...add] });
if (hits.length) core.setFailed('Possible credential: ' + hits.join(', '));
// ADVISORY: label + comment, never fail. Rotation is the remedy, not a red X.
if (hits.length) core.warning('Possible credential: ' + hits.join(', '));
11 changes: 8 additions & 3 deletions .github/workflows/governance-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ on:
inputs:
strict:
type: boolean
default: true
default: false # ADVISORY BY DEFAULT — young infrastructure.
# Callers opt in per repo with `with: {strict: true}`.
# See docs/ADVISORY.md for the promotion ladder.

permissions:
contents: read
Expand Down Expand Up @@ -40,6 +42,9 @@ jobs:

if (fail.length) {
core.summary.addHeading('Governance gates',2).addList(fail).write();
if (${{ inputs.strict }}) core.setFailed(`${fail.length} gate issue(s).`);
else core.warning(`${fail.length} gate issue(s) — advisory mode.`);
if (${{ inputs.strict }}) {
core.setFailed(`${fail.length} gate issue(s).`);
} else {
core.notice(`${fail.length} advisory gate finding(s) — not blocking. See job summary.`);
}
}
89 changes: 89 additions & 0 deletions .github/workflows/governance-report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Governance report (advisory)

# Read-only weekly posture report. Opens/updates ONE issue in this repo.
#
# SCOPE BOUNDARY: this workflow does NOT run tests, lint, typecheck, scan code, or
# parse build logs. It reads governance METADATA only. Test/lint/build execution is
# owned by l9-ci-sdk and l9-ci-core; CI failure diagnosis by l9-ci-debt-resolver.
# See docs/BOUNDARIES.md.

on:
schedule:
- cron: "23 13 * * 1"
workflow_dispatch:

permissions:
contents: read
issues: write

jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const ORG = 'Quantum-L9';
const repos = (await github.paginate(github.rest.repos.listForOrg, { org: ORG, type: 'all', per_page: 100 }))
.filter(r => !r.archived && !r.fork);

const has = async (repo, path) =>
github.rest.repos.getContent({ owner: ORG, repo, path }).then(() => true).catch(() => false);

const rows = [];
for (const r of repos) {
const [co, caller, dep] = await Promise.all([
has(r.name, '.github/CODEOWNERS'),
has(r.name, '.github/workflows/governance.yml'),
has(r.name, '.github/dependabot.yml'),
]);
let actions = '?';
try {
const p = await github.rest.actions.getGithubActionsPermissionsRepository({ owner: ORG, repo: r.name });
actions = p.data.enabled === false ? 'disabled'
: (p.data.allowed_actions === 'local_only' ? 'local_only' : 'ok');
} catch (e) { actions = 'unreadable'; }
rows.push({ name: r.name, co, caller, dep, actions });
}

const tick = b => b ? '✅' : '⬜';
const pct = k => Math.round(100 * rows.filter(r => r[k]).length / (rows.length || 1));
const blocked = rows.filter(r => r.actions === 'disabled' || r.actions === 'local_only');

const body = [
`_Advisory posture report. Nothing here blocks anything. Generated ${new Date().toISOString().slice(0,10)}._`,
'',
`**Coverage across ${rows.length} active repos** — CODEOWNERS ${pct('co')}% · governance caller ${pct('caller')}% · dependabot ${pct('dep')}%`,
'',
blocked.length
? `> [!NOTE]\n> ${blocked.length} repo(s) have an Actions policy that would prevent the governance caller from running: ` +
blocked.map(r => `\`${r.name}\` (${r.actions})`).join(', ') + '. See docs/DISTRIBUTION.md Appendix B.'
: '> [!NOTE]\n> All repos permit cross-repo reusable workflows.',
'',
'| Repo | CODEOWNERS | Caller | Dependabot | Actions |',
'| --- | :-: | :-: | :-: | :-: |',
...rows.map(r => `| \`${r.name}\` | ${tick(r.co)} | ${tick(r.caller)} | ${tick(r.dep)} | ${r.actions === 'ok' ? 'ok' : '⚠️ ' + r.actions} |`),
'',
'### Not measured here, on purpose',
'',
'Test results, lint findings, type errors, code scanning, and CI failure',
'diagnosis are owned by `l9-ci-sdk`, `l9-ci-core`, and `l9-ci-debt-resolver`.',
'This report deliberately does not recompute them — see `docs/BOUNDARIES.md`.',
'',
'### Promotion readiness',
'',
'Per `docs/ADVISORY.md`, rung 1 needs 4 consecutive weekly reports plus a',
'named highest-signal finding. Do not promote a gate without that evidence.',
].join('\n');

const TITLE = 'Governance posture (advisory, weekly)';
const open = await github.rest.issues.listForRepo({ ...context.repo, state: 'open', labels: 'advisory', per_page: 20 });
const existing = open.data.find(i => i.title === TITLE);
if (existing) {
await github.rest.issues.update({ ...context.repo, issue_number: existing.number, body });
await github.rest.issues.createComment({ ...context.repo, issue_number: existing.number,
body: `Refreshed ${new Date().toISOString().slice(0,10)} — CODEOWNERS ${pct('co')}%, caller ${pct('caller')}%, dependabot ${pct('dep')}%.` });
} else {
await github.rest.issues.create({ ...context.repo, title: TITLE, body, labels: ['advisory'] });
}
core.summary.addRaw(body).write();
Loading
Loading