From ea4cfb386fc6ffb30883a0cc53d0e1a675129719 Mon Sep 17 00:00:00 2001 From: Igor Beylin <31744795+cryptoxdog@users.noreply.github.com> Date: Sun, 23 Aug 2026 19:15:22 -0400 Subject: [PATCH 1/4] chore(governance): auto-seed 18 org template file(s) --- .biomeignore | 6 + .github/ISSUE_TEMPLATE/1-bug.yml | 66 ++++++ .github/ISSUE_TEMPLATE/2-feature.yml | 58 +++++ .github/ISSUE_TEMPLATE/3-task.yml | 36 ++++ .github/ISSUE_TEMPLATE/4-incident.yml | 90 ++++++++ .github/ISSUE_TEMPLATE/ci-failure.yml | 86 ++++++++ .github/ISSUE_TEMPLATE/config.yml | 18 ++ .github/ISSUE_TEMPLATE/gov-violation.yml | 84 ++++++++ .github/ISSUE_TEMPLATE/seed-ci-failure.yml | 57 +++++ .github/PULL_REQUEST_TEMPLATE/agent.md | 66 ++++++ .../governance/semgrep-finding-policy.yaml | 11 + .github/pull_request_template.md | 81 +++++++ .github/workflows/governance.yml | 45 ++++ .github/workflows/l9-lint-test-node.yml | 198 ++++++++++++++++++ .vscode/extensions.json | 10 + CODE_OF_CONDUCT.md | 60 ++++++ CONTRIBUTING.md | 72 +++++++ biome.json | 169 +++++++++++++++ 18 files changed, 1213 insertions(+) create mode 100644 .biomeignore create mode 100644 .github/ISSUE_TEMPLATE/1-bug.yml create mode 100644 .github/ISSUE_TEMPLATE/2-feature.yml create mode 100644 .github/ISSUE_TEMPLATE/3-task.yml create mode 100644 .github/ISSUE_TEMPLATE/4-incident.yml create mode 100644 .github/ISSUE_TEMPLATE/ci-failure.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/gov-violation.yml create mode 100644 .github/ISSUE_TEMPLATE/seed-ci-failure.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE/agent.md create mode 100644 .github/governance/semgrep-finding-policy.yaml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/governance.yml create mode 100644 .github/workflows/l9-lint-test-node.yml create mode 100644 .vscode/extensions.json create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 biome.json diff --git a/.biomeignore b/.biomeignore new file mode 100644 index 00000000..bddc75c8 --- /dev/null +++ b/.biomeignore @@ -0,0 +1,6 @@ +# Biome path exclusions (gitignore syntax). +# Biome 2.5 reads files.includes in biome.json, not this file โ€” keep generated trees in both. + +coverage/ +dist/ +.l9/ diff --git a/.github/ISSUE_TEMPLATE/1-bug.yml b/.github/ISSUE_TEMPLATE/1-bug.yml new file mode 100644 index 00000000..25392040 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug.yml @@ -0,0 +1,66 @@ +name: ๐Ÿ› Bug +description: Something behaves incorrectly and you can show it. +title: "bug: " +labels: ["type:bug", "needs:triage"] +body: + - type: markdown + attributes: + value: | + 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. + validations: + required: true + + - type: textarea + id: evidence + attributes: + label: Error output + description: Traceback, failing assertion, or log line. Redact secrets. + render: shell + validations: + required: true + + - type: textarea + id: reproduce + attributes: + label: Reproduction + description: Steps from a clean checkout. Best effort is fine. + render: shell + + - type: input + id: version + attributes: + label: Version / commit + description: Release tag or SHA if you have it. + + - type: dropdown + id: severity + attributes: + label: Severity + description: Routes triage. Advisory only โ€” nothing is blocked by this. + options: + - S4 โ€” cosmetic + - S3 โ€” degraded, workaround exists + - S2 โ€” major function broken, no workaround + - S1 โ€” production down, data loss, or security exposure + validations: + required: true + + - type: input + id: regression + attributes: + label: Last known good version + description: If set, implies a bisect range. Leave blank if unknown. + + - type: textarea + id: context + attributes: + label: Anything else + description: Suspected cause, related issues, workaround in use. diff --git a/.github/ISSUE_TEMPLATE/2-feature.yml b/.github/ISSUE_TEMPLATE/2-feature.yml new file mode 100644 index 00000000..41df3116 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-feature.yml @@ -0,0 +1,58 @@ +name: โœจ Feature +description: Propose a capability that does not exist yet. +title: "feat: " +labels: ["type:feature", "needs:triage"] +body: + - type: textarea + id: problem + attributes: + label: Problem + 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: Current workaround and its cost. + + - type: textarea + id: proposal + attributes: + label: Proposed behavior + description: What should exist. Include the interface if you know it. + validations: + required: true + + - type: dropdown + id: owner + attributes: + 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: alternatives + attributes: + label: Alternatives considered + description: Options you rejected and why. + + - type: dropdown + id: scope + attributes: + label: Scope + options: + - S โ€” under a day + - M โ€” a few days, one repo + - L โ€” multi-repo or migration + - XL โ€” needs a design doc first + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/3-task.yml b/.github/ISSUE_TEMPLATE/3-task.yml new file mode 100644 index 00000000..b7705f92 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-task.yml @@ -0,0 +1,36 @@ +name: ๐Ÿ”ง Task +description: Known work with a known solution โ€” chore, refactor, infra, docs. +title: "chore: " +labels: ["type:task"] +body: + - type: textarea + id: problem + attributes: + label: Problem + description: Why this work exists. What degrades if it is never done? + validations: + required: true + + - type: textarea + id: work + attributes: + label: Work + value: | + - [ ] + - [ ] + validations: + required: true + + - type: dropdown + id: kind + attributes: + label: Kind + options: [chore, refactor, infra / IaC, governance, docs, dependency bump] + validations: + required: true + + - type: input + id: blocks + attributes: + label: Blocks / blocked by + placeholder: "blocked by #12, blocks #34" diff --git a/.github/ISSUE_TEMPLATE/4-incident.yml b/.github/ISSUE_TEMPLATE/4-incident.yml new file mode 100644 index 00000000..bf7247d2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-incident.yml @@ -0,0 +1,90 @@ +name: ๐Ÿšจ Incident +description: Production is degraded or down. File first, investigate second. +title: "incident: " +labels: ["type:incident", "sev:untriaged", "priority:P0"] +assignees: [] +body: + - type: markdown + attributes: + value: | + **Page first, file second.** If customers are affected and nobody is paged, + stop and page on-call. This issue is the written record, not the alarm. + If this is a security compromise, use a private advisory instead โ€” not this form. + + - type: input + id: started + attributes: + label: Detected at (UTC) + placeholder: "2026-07-28T15:04:00Z" + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Problem + description: Customer-visible symptom. What is broken, for whom, since when? + validations: + required: true + + - type: dropdown + id: severity + attributes: + label: Severity + options: + - S1 โ€” full outage, data loss, or security exposure + - S2 โ€” major degradation, no workaround + - S3 โ€” partial degradation, workaround in place + validations: + required: true + + - type: textarea + id: evidence + attributes: + label: Signal + description: Alert name, dashboard link, error rate, sample traceback. + render: shell + validations: + required: true + + - type: textarea + id: impact + attributes: + label: Blast radius + description: Services, regions, tenants, and estimated request or user count. + validations: + required: true + + - type: textarea + id: mitigation + attributes: + label: Mitigation in progress + description: What is being done right now. Update this field as it evolves. + validations: + required: true + + - type: input + id: suspect + attributes: + label: Suspected trigger + description: Deploy, PR, config change, or upstream provider. Link it. + placeholder: "#1184, deployed 14:52Z" + + - type: input + id: commander + attributes: + label: Incident commander + placeholder: "@handle" + validations: + required: true + + - type: checkboxes + id: gates + attributes: + label: Response checklist + options: + - label: On-call paged. + required: true + - label: Status page or stakeholder comms updated, or explicitly not needed. + - label: Timeline is being kept in the comments below. + - label: Postmortem issue will be opened within 48h of resolution. diff --git a/.github/ISSUE_TEMPLATE/ci-failure.yml b/.github/ISSUE_TEMPLATE/ci-failure.yml new file mode 100644 index 00000000..bc3a8929 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ci-failure.yml @@ -0,0 +1,86 @@ +name: CI Pipeline Failure +description: Report a CI pipeline failure for triage by the platform team +title: "[CI Failure]: " +labels: ["ci-failure", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Use this template for CI pipeline failures that are not explained by a code bug. + For code bugs that cause test failures, use the Bug Report template instead. + + - type: input + id: workflow-run-url + attributes: + label: Workflow Run URL + description: Paste the full URL of the failed GitHub Actions run. + placeholder: "https://github.com/Quantum-L9/l9-ci-core/actions/runs/XXXXXXXXX" + validations: + required: true + + - type: input + id: failed-job + attributes: + label: Failed Job Name + placeholder: "pr-pipeline / security-scan / scorecard" + validations: + required: true + + - type: dropdown + id: trigger + attributes: + label: Triggered By + options: + - Pull Request + - Push to main + - Scheduled (cron) + - Workflow Dispatch + - Tag push + validations: + required: true + + - type: textarea + id: error-output + attributes: + label: Error Output + description: Paste the relevant error section from the failed step. + render: shell + validations: + required: true + + - type: dropdown + id: bisect-attempted + attributes: + label: Bisect Attempted? + options: + - "No โ€” first occurrence" + - "No โ€” intermittent failure" + - "Yes โ€” narrowed to specific commit (paste SHA below)" + - "Yes โ€” cannot reproduce locally" + validations: + required: true + + - type: input + id: bisect-sha + attributes: + label: Bisect SHA (if applicable) + placeholder: "2b330a5aab90cd7781bef08f14c5e7904b61bc56" + + - type: dropdown + id: affected-kernel + attributes: + label: Affected Kernel + options: + - pr-pipeline.yml + - release-publish.yml + - nightly.yml + - pre-commit-ci.yml + - trio-governance.yml + - security.yml + - scorecard.yml + - sbom.yml + - l9-self-ci.yml (inline only) + - Not a kernel call (repo-local workflow) + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..41e3f401 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,18 @@ +# Quantum-L9 org-wide issue template chooser config. +# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository +# +# Advisory URL is rewritten per consumer by ops/build-seed-payload.js +# (same SSOT as SECURITY.md). Do not add a fourth security URL. + +blank_issues_enabled: false + +contact_links: + - name: Security Vulnerability Report + url: https://github.com/Quantum-L9/Cognitive.Engine.Graphs/security/advisories/new + about: Do not open a public issue for security vulnerabilities. Follow SECURITY.md instead. + - name: Governance / CANONICAL_LAW Question + url: https://github.com/Quantum-L9/Cursor-Governance/blob/main/CANONICAL_LAW.md + about: For questions about governance policy, symlink contracts, or CANONICAL_LAW.md, read the policy source of truth first. + - name: CI Kernel API Contract + url: https://github.com/Quantum-L9/.github/blob/main/workflow-interface-registry.yml + about: For questions about kernel inputs/outputs/versioning, check the machine-readable registry before filing an issue. diff --git a/.github/ISSUE_TEMPLATE/gov-violation.yml b/.github/ISSUE_TEMPLATE/gov-violation.yml new file mode 100644 index 00000000..5765ba38 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/gov-violation.yml @@ -0,0 +1,84 @@ +name: Governance Violation +description: Report a violation of CANONICAL_LAW.md policy +title: "[Gov Violation]: " +labels: ["governance", "violation", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Use this template to report a detected violation of [CANONICAL_LAW.md](https://github.com/Quantum-L9/Cursor-Governance/blob/main/CANONICAL_LAW.md). + The platform team will triage and enforce. Do NOT use this for general bugs โ€” use the Bug Report template. + + - type: dropdown + id: violation-type + attributes: + label: Violation Type + options: + - Symlink drift (ยง2 โ€” symlinks missing or broken) + - Anti-pattern detected (ยง7 โ€” forbidden patterns present) + - Trio separation breach (ยง3 โ€” model/service/interface cross-import) + - Policy gate failure (CI gate not enforcing policy) + - Workspace wiring failure (ยง8 โ€” workspace config broken) + - Kernel ref violation (@main used instead of @v1) + - Other (describe below) + validations: + required: true + + - type: dropdown + id: canonical-law-section + attributes: + label: CANONICAL_LAW.md Section Violated + options: + - "ยง1 โ€” Unknown/General" + - "ยง2 โ€” Symlink Contract" + - "ยง3 โ€” Trio Separation" + - "ยง4 โ€” Unknown" + - "ยง5 โ€” Unknown" + - "ยง6 โ€” Unknown" + - "ยง7 โ€” Anti-Patterns" + - "ยง8 โ€” Workspace Wiring" + - "ยง9 โ€” Unknown" + validations: + required: true + + - type: textarea + id: evidence + attributes: + label: Evidence + description: Paste command output, diff, or log that demonstrates the violation. + render: shell + validations: + required: true + + - type: dropdown + id: affected-repos + attributes: + label: Affected Repository + multiple: true + options: + - l9-ci-core + - Cursor-Governance + - l9-assurance + - .github (org backbone) + - Multiple repos + validations: + required: true + + - type: dropdown + id: severity + attributes: + label: Severity + options: + - Critical (active governance bypass / security impact) + - High (CI not enforcing policy) + - Medium (drift detected but not exploited) + - Low (documentation only) + validations: + required: true + + - type: textarea + id: proposed-fix + attributes: + label: Proposed Fix (optional) + description: If you know how to fix this, describe the resolution. diff --git a/.github/ISSUE_TEMPLATE/seed-ci-failure.yml b/.github/ISSUE_TEMPLATE/seed-ci-failure.yml new file mode 100644 index 00000000..b075b482 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/seed-ci-failure.yml @@ -0,0 +1,57 @@ +name: Seed / auto-seed CI failure +description: A red governance seed or auto-seed PR โ€” ticket, not a chat +title: "[Seed CI]: " +labels: ["ci-failure", "triage"] +assignees: [] +body: + - type: markdown + attributes: + value: | + Use this when an org seed / auto-seed PR is red (Biome, labels, Semgrep + install, lockfile cache, required-check collision). For a code bug that + happens to fail tests, use Bug Report. For a kernel failure on a + feature PR, use CI Pipeline Failure. + + - type: input + id: repository + attributes: + label: Repository + description: owner/name of the consumer that received the seed + placeholder: Quantum-L9/example-repo + validations: + required: true + + - type: input + id: sha + attributes: + label: SHA + description: Commit SHA of the failing seed head + placeholder: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + validations: + required: true + + - type: input + id: check_url + attributes: + label: Failing check URL + description: Full Actions run or check-run URL + placeholder: "https://github.com/Quantum-L9/example-repo/actions/runs/XXXXXXXXX" + validations: + required: true + + - type: input + id: check_name + attributes: + label: Failing check name + placeholder: "L9 Analysis / Biome (format + lint) โ€” SDK-owned / Node Test Suite" + validations: + required: true + + - type: textarea + id: error-output + attributes: + label: Error Output + description: Paste the relevant error section from the failed step. + render: shell + validations: + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE/agent.md b/.github/PULL_REQUEST_TEMPLATE/agent.md new file mode 100644 index 00000000..ee27af55 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/agent.md @@ -0,0 +1,66 @@ + + +## Problem + +Agent or chore change. Evidence is the gate receipt or Actions run linked below. + +Closes # + +## Fix + +Seed / pack / generated change. See Changes by intent. + +## Risk + +- [x] Low โ€” additive, reversible, no data or contract change +- [ ] Medium โ€” touches shared code, config, or a public interface +- [ ] High โ€” breaking change, migration, IAM/network, or irreversible + +Blast radius: seed dests only (missing-only; customized files kept). +Rollback: revert this PR; consumers keep files already written. + +## Evidence + + + +``` +n/a โ€” because this is a generated seed / chore PR; see the Actions run +``` + +https://github.com/${GITHUB_REPOSITORY}/actions + +## Gates + +- [ ] Regression test added that fails without this fix โ€” n/a โ€” because seed / chore, no product behavior change +- [x] No secrets, tokens, or customer data in code, tests, fixtures, or logs +- [ ] `semgrep` clean, or findings triaged below โ€” n/a โ€” because pack seed does not change product code +- [ ] New IAM / workflow permissions are least privilege and enumerated โ€” n/a โ€” because no new write scopes +- [ ] Third-party actions pinned to a full commit SHA โ€” n/a โ€” because caller pins are unchanged or SHA-pinned +- [ ] Public interface change is documented and versioned โ€” n/a โ€” because no public interface change +- [ ] Observability exists for the new path (metric, log, trace, or alert) โ€” n/a โ€” because no new runtime path + +## Reviewer focus + +Confirm dests are missing-only / replaceable-stock, and default categories +still omit LICENSE, FUNDING, labels.yml, and on-org-update.yml. + +## Changes by intent + + + +**Added** +- seed dests โ€” missing-only org pack + +**Modified** +- n/a + +**Deleted** +- n/a + +## Files touched + + +_pending โ€” the bot fills this in on push_ + diff --git a/.github/governance/semgrep-finding-policy.yaml b/.github/governance/semgrep-finding-policy.yaml new file mode 100644 index 00000000..2a218182 --- /dev/null +++ b/.github/governance/semgrep-finding-policy.yaml @@ -0,0 +1,11 @@ +{ + "schema": "l9.finding-policy/v1", + "metadata": { + "version": "1.0.0", + "status": "authoritative" + }, + "defaults": { + "mode": "unresolved" + }, + "rules": {} +} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..302ac5ce --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,81 @@ + + +## Problem + + + +``` +paste the error / failing output here, or delete this block and describe the gap +``` + +Closes # + +## Fix + + + +## Risk + + + +- [ ] Low โ€” additive, reversible, no data or contract change +- [ ] Medium โ€” touches shared code, config, or a public interface +- [ ] High โ€” breaking change, migration, IAM/network, or irreversible + +Blast radius: +Rollback: + +## Evidence + + + +``` +$ pytest -q +$ ruff check . && pyright +``` + +## Gates + + + +- [ ] Regression test added that fails without this fix +- [ ] No secrets, tokens, or customer data in code, tests, fixtures, or logs +- [ ] `semgrep` clean, or findings triaged below +- [ ] New IAM / workflow permissions are least privilege and enumerated +- [ ] Third-party actions pinned to a full commit SHA +- [ ] Public interface change is documented and versioned +- [ ] Observability exists for the new path (metric, log, trace, or alert) + +## Reviewer focus + + + +## Changes by intent + + + +**Added** +- `path/to/new_file.py` โ€” why this file needs to exist + +**Modified** +- `path/to/existing.py` โ€” what changed in it and why + +**Deleted** +- `path/to/dead.py` โ€” why it is safe to remove + +## Files touched + + + + +_pending โ€” the bot fills this in on push_ + diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml new file mode 100644 index 00000000..b22e02bc --- /dev/null +++ b/.github/workflows/governance.yml @@ -0,0 +1,45 @@ +# Managed by Quantum-L9/.github. Pinned to a tag so main can move safely. +# +# This file should never need editing again. Governance logic lives in +# Quantum-L9/.github/.github/workflows/governance-*.yml; shipping a change means +# force-moving the v1 tag there, not touching this file. +# +# Pin record (ops/governance-v1-pin.txt): +# Quantum-L9/.github/.github/workflows/governance-pr.yml@v1 +# Quantum-L9/.github/.github/workflows/governance-issue.yml@v1 +# tag SHA 7ed3ab8650583f6659a6caf061eae77dbd3ed1be +# Preflight: `git ls-remote https://github.com/Quantum-L9/.github.git refs/tags/v1` +# must match that SHA before re-seeding this caller. +# +# SECRETS: a called workflow does NOT inherit caller secrets automatically. +# Both callees use only GITHUB_TOKEN. Do not add blank `secrets: inherit`. +# If a callee later needs a real secret, add a named `secrets:` entry. +# +# Permission validation runs BEFORE `if:` skip. Both jobs must declare +# job-level permissions or a partial grant startup_fails on the unused job. +# +# ACCESS: if this caller fails before any step runs, check the Actions policy on +# THIS repo. `gh api repos/OWNER/REPO/actions/permissions` + +name: Governance + +on: + pull_request: + types: [opened, edited, synchronize, reopened, ready_for_review] + issues: + types: [opened, edited, reopened] + +jobs: + pr: + if: github.event_name == 'pull_request' + permissions: + contents: read + pull-requests: write + uses: Quantum-L9/.github/.github/workflows/governance-pr.yml@v1 + + issue: + if: github.event_name == 'issues' + permissions: + contents: read + issues: write + uses: Quantum-L9/.github/.github/workflows/governance-issue.yml@v1 diff --git a/.github/workflows/l9-lint-test-node.yml b/.github/workflows/l9-lint-test-node.yml new file mode 100644 index 00000000..3cb019a1 --- /dev/null +++ b/.github/workflows/l9-lint-test-node.yml @@ -0,0 +1,198 @@ +# L9 consumer lint + test workflow for Node.js / TypeScript +# +# Copy into the CONSUMER repo at `.github/workflows/l9-lint-test-node.yml`. +# Org-distributed copy of Quantum-L9/l9-ci-core presets/typescript +# `.github/workflows/l9-lint-test.yml`. Do not invent a second lint owner. +# +# Formatter/linter ownership: Biome owns JS/TS/JSON (format + lint) via the +# SDK-owned reusable workflow below. ESLint is NOT a second formatter owner +# here. Type checking (tsc) and the repository test suite stay in this repo. +# +# Org-seed safety (Cursor-Governance#276 remediating): +# - Biome always runs. It needs no Node package. +# - `typecheck` / `test` run only when a root `package.json` exists. +# `actions/setup-node` with `cache: npm` hard-fails +# ("Dependencies lock file is not found") before any skip guard, so those +# jobs must not start on Python-only / no-Node consumers. +# - The test job is named `Node Test Suite`, not `Test Suite`, so it cannot +# collide with a required Python pytest context. +# +# Conventions: +# - Immutable event-revision checkout (no floating action ref) +# - SDK reusable workflow pinned to a full 40-char commit SHA +# - Least privilege (contents: read only) +name: L9 Lint and Test (Node) +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +# โ”€โ”€ CONFIGURABLE: agent sets these during activation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ +env: + NODE_VERSION: "20" + PACKAGE_MANAGER: "npm" + SOURCE_DIR: "." + HAS_TYPESCRIPT: "true" + +permissions: + contents: read + +concurrency: + group: l9-lint-test-node-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # Biome (format + lint + import organization) is owned by the SDK reusable + # workflow โ€” a single read-only gate with a checksum-verified biome binary + # and zero external actions. Reusable-workflow inputs cannot read `env:`, so + # scan-path and the rollout flag are set literally here. + biome: + name: Biome (format + lint) โ€” SDK-owned + permissions: + contents: read + uses: Quantum-L9/l9-ci-sdk/.github/workflows/l9-biome-scan.yml@f546f122d33601ea5a4b2592e3482c5c39eddd82 + with: + scan-path: "." + # Advisory-to-blocking rollout: false = full scan + annotate + exit 0. + # Flip to true to make Biome findings blocking once the repo is clean. + enforce-biome: false + + detect-node: + name: Detect Node package + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: read + outputs: + has_package: ${{ steps.detect.outputs.has_package }} + steps: + - name: Checkout immutable event revision + env: + REPOSITORY: ${{ github.repository }} + REVISION: ${{ github.sha }} + TOKEN: ${{ github.token }} + run: | + set -euo pipefail + git init . + git remote add origin "https://github.com/${REPOSITORY}.git" + auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" + git -c protocol.version=2 \ + -c "http.https://github.com/.extraheader=${auth_header}" \ + fetch --depth=1 origin "${REVISION}" + git checkout --detach FETCH_HEAD + + - id: detect + name: Detect root package.json + run: | + set -euo pipefail + if [ -f package.json ]; then + echo "has_package=true" >> "$GITHUB_OUTPUT" + else + echo "has_package=false" >> "$GITHUB_OUTPUT" + echo "::notice::no root package.json; skipping Node typecheck and tests" + fi + + typecheck: + name: Type Check (tsc --noEmit) + needs: detect-node + if: needs.detect-node.outputs.has_package == 'true' + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + steps: + - name: Checkout immutable event revision + env: + REPOSITORY: ${{ github.repository }} + REVISION: ${{ github.sha }} + TOKEN: ${{ github.token }} + run: | + set -euo pipefail + git init . + git remote add origin "https://github.com/${REPOSITORY}.git" + # Authenticate with a per-fetch Authorization header instead of + # embedding the token in the remote URL, so the credential is never + # written to the remote URL or .git/config (mirrors actions/checkout). + auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" + git -c protocol.version=2 \ + -c "http.https://github.com/.extraheader=${auth_header}" \ + fetch --depth=1 origin "${REVISION}" + git checkout --detach FETCH_HEAD + + - name: Set up Node + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + with: + node-version: ${{ env.NODE_VERSION }} + # Do not set cache: here. setup-node cache hard-fails when the + # matching lockfile is absent. + + - name: Install dependencies + run: | + set -euo pipefail + case "${PACKAGE_MANAGER}" in + npm) if [ -f package-lock.json ]; then npm ci; else npm install; fi ;; + pnpm) corepack enable && (if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else pnpm install; fi) ;; + yarn) corepack enable && (if [ -f yarn.lock ]; then yarn install --frozen-lockfile; else yarn install; fi) ;; + *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; + esac + + - name: tsc --noEmit + if: env.HAS_TYPESCRIPT == 'true' + run: | + set -euo pipefail + if [ -f tsconfig.json ]; then + npx --yes tsc --noEmit -p tsconfig.json + else + echo "::notice::no tsconfig.json found, skipping type check" + fi + + test: + name: Node Test Suite + needs: detect-node + if: needs.detect-node.outputs.has_package == 'true' + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: read + steps: + - name: Checkout immutable event revision + env: + REPOSITORY: ${{ github.repository }} + REVISION: ${{ github.sha }} + TOKEN: ${{ github.token }} + run: | + set -euo pipefail + git init . + git remote add origin "https://github.com/${REPOSITORY}.git" + auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" + git -c protocol.version=2 \ + -c "http.https://github.com/.extraheader=${auth_header}" \ + fetch --depth=1 origin "${REVISION}" + git checkout --detach FETCH_HEAD + + - name: Set up Node + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Install dependencies + run: | + set -euo pipefail + case "${PACKAGE_MANAGER}" in + npm) if [ -f package-lock.json ]; then npm ci; else npm install; fi ;; + pnpm) corepack enable && (if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else pnpm install; fi) ;; + yarn) corepack enable && (if [ -f yarn.lock ]; then yarn install --frozen-lockfile; else yarn install; fi) ;; + *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; + esac + + - name: Run test suite + env: + CI: "true" + run: | + set -euo pipefail + if [ -f package.json ] && node -e "process.exit(require('./package.json').scripts && require('./package.json').scripts.test ? 0 : 1)" 2>/dev/null; then + ${PACKAGE_MANAGER} test + else + echo "::notice::no test script defined in package.json, skipping" + fi diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..af34433b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "biomejs.biome", + "charliermarsh.ruff" + ], + "unwantedRecommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ] +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..af40da17 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,60 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in the Quantum-L9 community +a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, +ethnicity, sex characteristics, gender identity and expression, level of experience, education, +socioeconomic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +The Quantum-L9 platform team (`@Quantum-L9/platform`) is responsible for clarifying and enforcing this Code of Conduct. +They will take appropriate and fair corrective action in response to any behavior deemed inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all community spaces and also applies when an individual is officially +representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior: + +- Open [`gov-violation.yml`](.github/ISSUE_TEMPLATE/gov-violation.yml) for a public, routable report. +- Use this repository's Security Advisory form for a confidential / reporter-privacy path (see SECURITY.md). + +Do not "mention @platform" in markdown as the enforcement action. The resolvable owner is the CODEOWNERS team `@Quantum-L9/platform` on `.github/`, `SECURITY.md`, and `CODEOWNERS` only. + +All complaints will be reviewed and investigated promptly and fairly. + +## Enforcement Guidelines + +**1. Correction** โ€” Private written warning, clarity on violation, request for public apology. +**2. Warning** โ€” Warning with consequences for continued behavior; no interaction with involved parties for a specified period. +**3. Temporary Ban** โ€” Temporary ban from community interaction. +**4. Permanent Ban** โ€” Permanent ban for sustained, severe, or repeated violations. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant v2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..be61af54 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,72 @@ +# Contributing to Quantum-L9 + +## Live activation (do this once per machine) + +Governance loads automatically. Do **not** clone Cursor-Governance into a +consumer workspace root, and do **not** create whole-directory Cursor +rules, skills, or commands symlinks โ€” that is the retired v2 ritual and +it creates a second governance tree. + +What actually wires: + +1. **sessionStart** โ€” `ops/hooks/session_start_bootstrap.sh` activates the + GitHub tip at `$HOME/.cursor-governance` (fast-forward or clone+swap). +2. **`l9-governance` plugin** โ€” `~/.cursor/plugins/local/l9-governance` โ†’ + the governance clone. Cursor discovers `rules/`, `skills/`, and + `commands/` under the plugin root. +3. **`.cursor-commands`** โ€” consumers only: a symlink to + `$HOME/.cursor-governance`. The SSOT clone must never self-alias. + +If a consumer workspace is missing those links: + +```bash +bash "$HOME/.cursor-governance/ops/scripts/ensure_workspace_wired.sh" "$(pwd)" +``` + +Read [CANONICAL_LAW.md](https://github.com/Quantum-L9/Cursor-Governance/blob/main/CANONICAL_LAW.md) +for the symlink contract and anti-patterns. + +## How an agent ships + +1. Local commits on a feature branch (L4 local autonomy). +2. Run `kernels/Recursive Alignment.md` then `kernels/Validate & Repair.md`. +3. Publish **only** with: + +```bash +PR_REMEDIATE=0 make pr +``` + +Do **not** `git push`, `gh pr create`, or `gh pr edit` to reach GitHub. +`make pr` runs the checkers; the alternatives skip them. + +Campaign PRs set `PR_BASE=origin/campaign/` and never target +`main`. Merge is a separate `/l9-pr-remediation` (Converge) step โ€” opening +a PR is not merge authorization. + +## CI gates + +Consumer CI is the org `l9-ci-pack` (missing-only seed): + +| Gate | When it runs | +| --- | --- | +| Biome | Always (JS/TS/JSON). Idle and green when the tree has no matching files. | +| Python lint + `Python Test Suite` | Only when `pyproject.toml` or `requirements.txt` exists. | +| Node typecheck + `Node Test Suite` | Only when a root `package.json` exists. | +| L9 Analysis | Semgrep + SDK publish. Fails with `governance-pack-missing` if `.github/governance/` is absent. | +| Governance caller | PR body / issue triage via `governance.yml@v1`. | + +Do not invent a second `biome.json` or a competing `ci.yml`. Extra Biome +excludes append to `files.includes` only. + +## Branch naming and commits + +- Branches: `feat/`, `fix/`, `chore/`, `docs/` +- Commits: Conventional Commits โ€” `feat(scope): message` +- Blast-radius paths (`.github/`, `infra/`, `SECURITY.md`, `CODEOWNERS`) + require the CODEOWNERS team plus the extra reviewer on those paths only. + +## Kernel authoring (l9-ci-core contributors only) + +- Kernels must use `on: workflow_call` only. +- Never reference `@main` from thin callers. +- See [workflow-interface-registry.yml](https://github.com/Quantum-L9/.github/blob/main/workflow-interface-registry.yml). diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..b1fe3951 --- /dev/null +++ b/biome.json @@ -0,0 +1,169 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json", + "root": true, + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + }, + "files": { + "ignoreUnknown": true, + "maxSize": 1048576, + "includes": [ + "**", + "!**/*.jsonc", + "!**/node_modules", + "!**/.venv", + "!**/venv", + "!**/__pycache__", + "!**/.git", + "!**/.ruff_cache", + "!**/.l9", + "!**/dist", + "!**/coverage", + "!**/package-lock.json", + "!**/npm-shrinkwrap.json" + ] + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "useEditorconfig": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "trailingNewline": true, + "bracketSpacing": true, + "bracketSameLine": false, + "attributePosition": "auto", + "expand": "auto", + "delimiterSpacing": false + }, + "linter": { + "enabled": true, + "rules": { + "preset": "recommended" + } + }, + "assist": { + "enabled": true, + "actions": { + "preset": "recommended", + "source": { + "organizeImports": "on", + "useSortedKeys": "off", + "useSortedAttributes": "off", + "useSortedInterfaceMembers": "off", + "useSortedEnumMembers": "on", + "useSortedPackageJson": "on", + "noDuplicateClasses": "on" + } + } + }, + "json": { + "parser": { + "allowComments": false, + "allowTrailingCommas": false + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "trailingNewline": true, + "trailingCommas": "none", + "bracketSpacing": true, + "expand": "auto", + "delimiterSpacing": false + }, + "linter": { + "enabled": true + }, + "assist": { + "enabled": false + } + }, + "javascript": { + "jsxRuntime": "transparent", + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "trailingNewline": true, + "quoteStyle": "double", + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingCommas": "all", + "semicolons": "always", + "arrowParentheses": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "attributePosition": "auto", + "operatorLinebreak": "after", + "expand": "auto", + "delimiterSpacing": false + }, + "linter": { + "enabled": true + }, + "assist": { + "enabled": true + } + }, + "css": { + "formatter": { + "enabled": false + }, + "linter": { + "enabled": false + }, + "assist": { + "enabled": false + } + }, + "graphql": { + "formatter": { + "enabled": false + }, + "linter": { + "enabled": false + }, + "assist": { + "enabled": false + } + }, + "html": { + "experimentalFullSupportEnabled": false, + "formatter": { + "enabled": false + }, + "linter": { + "enabled": false + }, + "assist": { + "enabled": false + } + }, + "overrides": [ + { + "includes": ["**/*.jsonc", "**/.vscode"], + "json": { + "parser": { + "allowComments": true, + "allowTrailingCommas": true + }, + "formatter": { + "enabled": false + }, + "linter": { + "enabled": false + } + } + } + ] +} From 462fab551c950aada46ff5565ae318988e83b4dd Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 23:27:40 +0000 Subject: [PATCH 2/4] fix(seed): harden seeded workflows and fix CODE_OF_CONDUCT whitespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remediates three failure classes on this PR without changing what the seed delivers: - CODE_OF_CONDUCT.md: the four enforcement entries used two-space markdown hard breaks, which the trailing-whitespace pre-commit hook strips in CI (the "Pre-commit Hooks" / "CI Gate" failure). They are now separate paragraphs with no trailing whitespace, rendering the same. - .github/workflows/governance.yml: added a top-level `permissions: contents: read` block (Scorecard Token-Permissions: "no topLevel permission defined") and pinned both reusable-workflow callees to the commit SHA the v1 tag points at โ€” 7ed3ab86, verified against the file's own preflight (`git ls-remote ... refs/tags/v1`) before pinning (Sonar S7637 x2, Scorecard Pinned-Dependencies). The header comment now describes SHA-bump-on-reseed instead of tag motion, and keeps the pin record and preflight. - .github/workflows/l9-lint-test-node.yml: installs now require a lockfile (no floating `npm install`/`pnpm install`/`yarn install` fallback) and run with --ignore-scripts, and the tsc step uses `npx --no-install` so it can only run the lockfile-resolved local compiler (Sonar S6505 x12, S8543 x3; Scorecard Pinned-Dependencies npmCommand findings). On this Python-only repo both Node jobs are skipped by the detect-node guard; the hardened defaults bind future Node consumers, which can relax per-repo where dependencies genuinely need install-time scripts. --- .github/workflows/governance.yml | 21 ++++++++----- .github/workflows/l9-lint-test-node.yml | 41 ++++++++++++++++++++----- CODE_OF_CONDUCT.md | 9 ++++-- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index b22e02bc..8c20a539 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -1,15 +1,17 @@ -# Managed by Quantum-L9/.github. Pinned to a tag so main can move safely. +# Managed by Quantum-L9/.github. # -# This file should never need editing again. Governance logic lives in -# Quantum-L9/.github/.github/workflows/governance-*.yml; shipping a change means -# force-moving the v1 tag there, not touching this file. +# Governance logic lives in Quantum-L9/.github/.github/workflows/governance-*.yml. +# This repo's security gates (Scorecard Pinned-Dependencies, Sonar S7637) require +# full-SHA pins, so both callees are pinned to the commit the v1 tag pointed at +# when this file was seeded. Shipping a governance change now means bumping the +# SHA below on re-seed, after the same preflight. # # Pin record (ops/governance-v1-pin.txt): # Quantum-L9/.github/.github/workflows/governance-pr.yml@v1 # Quantum-L9/.github/.github/workflows/governance-issue.yml@v1 -# tag SHA 7ed3ab8650583f6659a6caf061eae77dbd3ed1be +# tag SHA 7ed3ab8650583f6659a6caf061eae77dbd3ed1be (verified 2026-08-23) # Preflight: `git ls-remote https://github.com/Quantum-L9/.github.git refs/tags/v1` -# must match that SHA before re-seeding this caller. +# must match the pinned SHA before re-seeding this caller. # # SECRETS: a called workflow does NOT inherit caller secrets automatically. # Both callees use only GITHUB_TOKEN. Do not add blank `secrets: inherit`. @@ -23,6 +25,9 @@ name: Governance +permissions: + contents: read + on: pull_request: types: [opened, edited, synchronize, reopened, ready_for_review] @@ -35,11 +40,11 @@ jobs: permissions: contents: read pull-requests: write - uses: Quantum-L9/.github/.github/workflows/governance-pr.yml@v1 + uses: Quantum-L9/.github/.github/workflows/governance-pr.yml@7ed3ab8650583f6659a6caf061eae77dbd3ed1be # v1 issue: if: github.event_name == 'issues' permissions: contents: read issues: write - uses: Quantum-L9/.github/.github/workflows/governance-issue.yml@v1 + uses: Quantum-L9/.github/.github/workflows/governance-issue.yml@7ed3ab8650583f6659a6caf061eae77dbd3ed1be # v1 diff --git a/.github/workflows/l9-lint-test-node.yml b/.github/workflows/l9-lint-test-node.yml index 3cb019a1..172c3118 100644 --- a/.github/workflows/l9-lint-test-node.yml +++ b/.github/workflows/l9-lint-test-node.yml @@ -130,10 +130,22 @@ jobs: - name: Install dependencies run: | set -euo pipefail + # Lockfile required so installs resolve only pinned versions (Sonar S8543, + # Scorecard Pinned-Dependencies). --ignore-scripts blocks package lifecycle + # scripts during install (Sonar S6505); a consumer whose dependencies need + # install-time build scripts opts out here deliberately, per repo. case "${PACKAGE_MANAGER}" in - npm) if [ -f package-lock.json ]; then npm ci; else npm install; fi ;; - pnpm) corepack enable && (if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else pnpm install; fi) ;; - yarn) corepack enable && (if [ -f yarn.lock ]; then yarn install --frozen-lockfile; else yarn install; fi) ;; + npm) + [ -f package-lock.json ] || { echo "::error::package-lock.json is required โ€” commit a lockfile"; exit 1; } + npm ci --ignore-scripts ;; + pnpm) + corepack enable + [ -f pnpm-lock.yaml ] || { echo "::error::pnpm-lock.yaml is required โ€” commit a lockfile"; exit 1; } + pnpm install --frozen-lockfile --ignore-scripts ;; + yarn) + corepack enable + [ -f yarn.lock ] || { echo "::error::yarn.lock is required โ€” commit a lockfile"; exit 1; } + yarn install --frozen-lockfile --ignore-scripts ;; *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; esac @@ -142,7 +154,10 @@ jobs: run: | set -euo pipefail if [ -f tsconfig.json ]; then - npx --yes tsc --noEmit -p tsconfig.json + # --no-install runs the lockfile-resolved local tsc and never fetches a + # floating release from the registry (Sonar S6505/S8543). A repo with a + # tsconfig but no typescript devDependency fails here โ€” add the dep. + npx --no-install tsc --noEmit -p tsconfig.json else echo "::notice::no tsconfig.json found, skipping type check" fi @@ -179,10 +194,22 @@ jobs: - name: Install dependencies run: | set -euo pipefail + # Lockfile required so installs resolve only pinned versions (Sonar S8543, + # Scorecard Pinned-Dependencies). --ignore-scripts blocks package lifecycle + # scripts during install (Sonar S6505); a consumer whose dependencies need + # install-time build scripts opts out here deliberately, per repo. case "${PACKAGE_MANAGER}" in - npm) if [ -f package-lock.json ]; then npm ci; else npm install; fi ;; - pnpm) corepack enable && (if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; else pnpm install; fi) ;; - yarn) corepack enable && (if [ -f yarn.lock ]; then yarn install --frozen-lockfile; else yarn install; fi) ;; + npm) + [ -f package-lock.json ] || { echo "::error::package-lock.json is required โ€” commit a lockfile"; exit 1; } + npm ci --ignore-scripts ;; + pnpm) + corepack enable + [ -f pnpm-lock.yaml ] || { echo "::error::pnpm-lock.yaml is required โ€” commit a lockfile"; exit 1; } + pnpm install --frozen-lockfile --ignore-scripts ;; + yarn) + corepack enable + [ -f yarn.lock ] || { echo "::error::yarn.lock is required โ€” commit a lockfile"; exit 1; } + yarn install --frozen-lockfile --ignore-scripts ;; *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; esac diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index af40da17..ea84f337 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -50,9 +50,12 @@ All complaints will be reviewed and investigated promptly and fairly. ## Enforcement Guidelines -**1. Correction** โ€” Private written warning, clarity on violation, request for public apology. -**2. Warning** โ€” Warning with consequences for continued behavior; no interaction with involved parties for a specified period. -**3. Temporary Ban** โ€” Temporary ban from community interaction. +**1. Correction** โ€” Private written warning, clarity on violation, request for public apology. + +**2. Warning** โ€” Warning with consequences for continued behavior; no interaction with involved parties for a specified period. + +**3. Temporary Ban** โ€” Temporary ban from community interaction. + **4. Permanent Ban** โ€” Permanent ban for sustained, severe, or repeated violations. ## Attribution From bf635a55bef36ca6fee7a82409340865c5521dfa Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 23:27:51 +0000 Subject: [PATCH 3/4] chore(seed): move lint/test toolchain seeds to a follow-up PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR-size gate blocks at 1000 reviewable added lines and this seed carried 1213; the gate's required action is to split. The four lint/test toolchain files (biome.json, .biomeignore, .vscode/extensions.json, .github/workflows/l9-lint-test-node.yml โ€” ~383 lines) move to a sibling PR based on main, leaving this PR the governance, template, and community files at ~830 added lines. Nothing is dropped: the toolchain files land via the follow-up PR with the security hardening from the previous commit already applied. --- .biomeignore | 6 - .github/workflows/l9-lint-test-node.yml | 225 ------------------------ .vscode/extensions.json | 10 -- biome.json | 169 ------------------ 4 files changed, 410 deletions(-) delete mode 100644 .biomeignore delete mode 100644 .github/workflows/l9-lint-test-node.yml delete mode 100644 .vscode/extensions.json delete mode 100644 biome.json diff --git a/.biomeignore b/.biomeignore deleted file mode 100644 index bddc75c8..00000000 --- a/.biomeignore +++ /dev/null @@ -1,6 +0,0 @@ -# Biome path exclusions (gitignore syntax). -# Biome 2.5 reads files.includes in biome.json, not this file โ€” keep generated trees in both. - -coverage/ -dist/ -.l9/ diff --git a/.github/workflows/l9-lint-test-node.yml b/.github/workflows/l9-lint-test-node.yml deleted file mode 100644 index 172c3118..00000000 --- a/.github/workflows/l9-lint-test-node.yml +++ /dev/null @@ -1,225 +0,0 @@ -# L9 consumer lint + test workflow for Node.js / TypeScript -# -# Copy into the CONSUMER repo at `.github/workflows/l9-lint-test-node.yml`. -# Org-distributed copy of Quantum-L9/l9-ci-core presets/typescript -# `.github/workflows/l9-lint-test.yml`. Do not invent a second lint owner. -# -# Formatter/linter ownership: Biome owns JS/TS/JSON (format + lint) via the -# SDK-owned reusable workflow below. ESLint is NOT a second formatter owner -# here. Type checking (tsc) and the repository test suite stay in this repo. -# -# Org-seed safety (Cursor-Governance#276 remediating): -# - Biome always runs. It needs no Node package. -# - `typecheck` / `test` run only when a root `package.json` exists. -# `actions/setup-node` with `cache: npm` hard-fails -# ("Dependencies lock file is not found") before any skip guard, so those -# jobs must not start on Python-only / no-Node consumers. -# - The test job is named `Node Test Suite`, not `Test Suite`, so it cannot -# collide with a required Python pytest context. -# -# Conventions: -# - Immutable event-revision checkout (no floating action ref) -# - SDK reusable workflow pinned to a full 40-char commit SHA -# - Least privilege (contents: read only) -name: L9 Lint and Test (Node) -on: - pull_request: - push: - branches: [main] - workflow_dispatch: - -# โ”€โ”€ CONFIGURABLE: agent sets these during activation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -env: - NODE_VERSION: "20" - PACKAGE_MANAGER: "npm" - SOURCE_DIR: "." - HAS_TYPESCRIPT: "true" - -permissions: - contents: read - -concurrency: - group: l9-lint-test-node-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - # Biome (format + lint + import organization) is owned by the SDK reusable - # workflow โ€” a single read-only gate with a checksum-verified biome binary - # and zero external actions. Reusable-workflow inputs cannot read `env:`, so - # scan-path and the rollout flag are set literally here. - biome: - name: Biome (format + lint) โ€” SDK-owned - permissions: - contents: read - uses: Quantum-L9/l9-ci-sdk/.github/workflows/l9-biome-scan.yml@f546f122d33601ea5a4b2592e3482c5c39eddd82 - with: - scan-path: "." - # Advisory-to-blocking rollout: false = full scan + annotate + exit 0. - # Flip to true to make Biome findings blocking once the repo is clean. - enforce-biome: false - - detect-node: - name: Detect Node package - runs-on: ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read - outputs: - has_package: ${{ steps.detect.outputs.has_package }} - steps: - - name: Checkout immutable event revision - env: - REPOSITORY: ${{ github.repository }} - REVISION: ${{ github.sha }} - TOKEN: ${{ github.token }} - run: | - set -euo pipefail - git init . - git remote add origin "https://github.com/${REPOSITORY}.git" - auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" - git -c protocol.version=2 \ - -c "http.https://github.com/.extraheader=${auth_header}" \ - fetch --depth=1 origin "${REVISION}" - git checkout --detach FETCH_HEAD - - - id: detect - name: Detect root package.json - run: | - set -euo pipefail - if [ -f package.json ]; then - echo "has_package=true" >> "$GITHUB_OUTPUT" - else - echo "has_package=false" >> "$GITHUB_OUTPUT" - echo "::notice::no root package.json; skipping Node typecheck and tests" - fi - - typecheck: - name: Type Check (tsc --noEmit) - needs: detect-node - if: needs.detect-node.outputs.has_package == 'true' - runs-on: ubuntu-latest - timeout-minutes: 10 - permissions: - contents: read - steps: - - name: Checkout immutable event revision - env: - REPOSITORY: ${{ github.repository }} - REVISION: ${{ github.sha }} - TOKEN: ${{ github.token }} - run: | - set -euo pipefail - git init . - git remote add origin "https://github.com/${REPOSITORY}.git" - # Authenticate with a per-fetch Authorization header instead of - # embedding the token in the remote URL, so the credential is never - # written to the remote URL or .git/config (mirrors actions/checkout). - auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" - git -c protocol.version=2 \ - -c "http.https://github.com/.extraheader=${auth_header}" \ - fetch --depth=1 origin "${REVISION}" - git checkout --detach FETCH_HEAD - - - name: Set up Node - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 - with: - node-version: ${{ env.NODE_VERSION }} - # Do not set cache: here. setup-node cache hard-fails when the - # matching lockfile is absent. - - - name: Install dependencies - run: | - set -euo pipefail - # Lockfile required so installs resolve only pinned versions (Sonar S8543, - # Scorecard Pinned-Dependencies). --ignore-scripts blocks package lifecycle - # scripts during install (Sonar S6505); a consumer whose dependencies need - # install-time build scripts opts out here deliberately, per repo. - case "${PACKAGE_MANAGER}" in - npm) - [ -f package-lock.json ] || { echo "::error::package-lock.json is required โ€” commit a lockfile"; exit 1; } - npm ci --ignore-scripts ;; - pnpm) - corepack enable - [ -f pnpm-lock.yaml ] || { echo "::error::pnpm-lock.yaml is required โ€” commit a lockfile"; exit 1; } - pnpm install --frozen-lockfile --ignore-scripts ;; - yarn) - corepack enable - [ -f yarn.lock ] || { echo "::error::yarn.lock is required โ€” commit a lockfile"; exit 1; } - yarn install --frozen-lockfile --ignore-scripts ;; - *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; - esac - - - name: tsc --noEmit - if: env.HAS_TYPESCRIPT == 'true' - run: | - set -euo pipefail - if [ -f tsconfig.json ]; then - # --no-install runs the lockfile-resolved local tsc and never fetches a - # floating release from the registry (Sonar S6505/S8543). A repo with a - # tsconfig but no typescript devDependency fails here โ€” add the dep. - npx --no-install tsc --noEmit -p tsconfig.json - else - echo "::notice::no tsconfig.json found, skipping type check" - fi - - test: - name: Node Test Suite - needs: detect-node - if: needs.detect-node.outputs.has_package == 'true' - runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: read - steps: - - name: Checkout immutable event revision - env: - REPOSITORY: ${{ github.repository }} - REVISION: ${{ github.sha }} - TOKEN: ${{ github.token }} - run: | - set -euo pipefail - git init . - git remote add origin "https://github.com/${REPOSITORY}.git" - auth_header="Authorization: Basic $(printf 'x-access-token:%s' "${TOKEN}" | base64 | tr -d '\n')" - git -c protocol.version=2 \ - -c "http.https://github.com/.extraheader=${auth_header}" \ - fetch --depth=1 origin "${REVISION}" - git checkout --detach FETCH_HEAD - - - name: Set up Node - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Install dependencies - run: | - set -euo pipefail - # Lockfile required so installs resolve only pinned versions (Sonar S8543, - # Scorecard Pinned-Dependencies). --ignore-scripts blocks package lifecycle - # scripts during install (Sonar S6505); a consumer whose dependencies need - # install-time build scripts opts out here deliberately, per repo. - case "${PACKAGE_MANAGER}" in - npm) - [ -f package-lock.json ] || { echo "::error::package-lock.json is required โ€” commit a lockfile"; exit 1; } - npm ci --ignore-scripts ;; - pnpm) - corepack enable - [ -f pnpm-lock.yaml ] || { echo "::error::pnpm-lock.yaml is required โ€” commit a lockfile"; exit 1; } - pnpm install --frozen-lockfile --ignore-scripts ;; - yarn) - corepack enable - [ -f yarn.lock ] || { echo "::error::yarn.lock is required โ€” commit a lockfile"; exit 1; } - yarn install --frozen-lockfile --ignore-scripts ;; - *) echo "::error::unknown PACKAGE_MANAGER ${PACKAGE_MANAGER}" && exit 1 ;; - esac - - - name: Run test suite - env: - CI: "true" - run: | - set -euo pipefail - if [ -f package.json ] && node -e "process.exit(require('./package.json').scripts && require('./package.json').scripts.test ? 0 : 1)" 2>/dev/null; then - ${PACKAGE_MANAGER} test - else - echo "::notice::no test script defined in package.json, skipping" - fi diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index af34433b..00000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "recommendations": [ - "biomejs.biome", - "charliermarsh.ruff" - ], - "unwantedRecommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode" - ] -} diff --git a/biome.json b/biome.json deleted file mode 100644 index b1fe3951..00000000 --- a/biome.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json", - "root": true, - "vcs": { - "enabled": true, - "clientKind": "git", - "useIgnoreFile": true, - "defaultBranch": "main" - }, - "files": { - "ignoreUnknown": true, - "maxSize": 1048576, - "includes": [ - "**", - "!**/*.jsonc", - "!**/node_modules", - "!**/.venv", - "!**/venv", - "!**/__pycache__", - "!**/.git", - "!**/.ruff_cache", - "!**/.l9", - "!**/dist", - "!**/coverage", - "!**/package-lock.json", - "!**/npm-shrinkwrap.json" - ] - }, - "formatter": { - "enabled": true, - "formatWithErrors": false, - "useEditorconfig": true, - "indentStyle": "space", - "indentWidth": 2, - "lineEnding": "lf", - "lineWidth": 100, - "trailingNewline": true, - "bracketSpacing": true, - "bracketSameLine": false, - "attributePosition": "auto", - "expand": "auto", - "delimiterSpacing": false - }, - "linter": { - "enabled": true, - "rules": { - "preset": "recommended" - } - }, - "assist": { - "enabled": true, - "actions": { - "preset": "recommended", - "source": { - "organizeImports": "on", - "useSortedKeys": "off", - "useSortedAttributes": "off", - "useSortedInterfaceMembers": "off", - "useSortedEnumMembers": "on", - "useSortedPackageJson": "on", - "noDuplicateClasses": "on" - } - } - }, - "json": { - "parser": { - "allowComments": false, - "allowTrailingCommas": false - }, - "formatter": { - "enabled": true, - "indentStyle": "space", - "indentWidth": 2, - "lineEnding": "lf", - "lineWidth": 100, - "trailingNewline": true, - "trailingCommas": "none", - "bracketSpacing": true, - "expand": "auto", - "delimiterSpacing": false - }, - "linter": { - "enabled": true - }, - "assist": { - "enabled": false - } - }, - "javascript": { - "jsxRuntime": "transparent", - "formatter": { - "enabled": true, - "indentStyle": "space", - "indentWidth": 2, - "lineEnding": "lf", - "lineWidth": 100, - "trailingNewline": true, - "quoteStyle": "double", - "jsxQuoteStyle": "double", - "quoteProperties": "asNeeded", - "trailingCommas": "all", - "semicolons": "always", - "arrowParentheses": "always", - "bracketSpacing": true, - "bracketSameLine": false, - "attributePosition": "auto", - "operatorLinebreak": "after", - "expand": "auto", - "delimiterSpacing": false - }, - "linter": { - "enabled": true - }, - "assist": { - "enabled": true - } - }, - "css": { - "formatter": { - "enabled": false - }, - "linter": { - "enabled": false - }, - "assist": { - "enabled": false - } - }, - "graphql": { - "formatter": { - "enabled": false - }, - "linter": { - "enabled": false - }, - "assist": { - "enabled": false - } - }, - "html": { - "experimentalFullSupportEnabled": false, - "formatter": { - "enabled": false - }, - "linter": { - "enabled": false - }, - "assist": { - "enabled": false - } - }, - "overrides": [ - { - "includes": ["**/*.jsonc", "**/.vscode"], - "json": { - "parser": { - "allowComments": true, - "allowTrailingCommas": true - }, - "formatter": { - "enabled": false - }, - "linter": { - "enabled": false - } - } - } - ] -} From 0cce42be356b01e78e439608c938a54fa4091c2d Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 01:00:28 +0000 Subject: [PATCH 4/4] fix(governance): pin reusable workflows to peeled v1 commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous pin used 7ed3ab8650583f6659a6caf061eae77dbd3ed1be, which is the ANNOTATED TAG OBJECT for v1 โ€” not a commit. GitHub's commits API rejects it ("No commit found for SHA"), so both Governance runs on this branch failed before any job was created: conclusion=failure with total_count=0 jobs, and the run labelled by its raw path rather than `name: Governance`, because the file never parsed that far. `git ls-remote refs/tags/v1` returns the tag object; `refs/tags/v1^{}` returns the commit it peels to. Both callees now reference the peeled commit 3e841ea4f7f8be2a8c9fc45cad5bed46fe801d08 ("feat(governance): deploy advisory defaults v3.1 (#18)"), verified as a real commit object, with governance-pr.yml and governance-issue.yml both present there and both exposing `on: workflow_call`. The header comment now records the two SHAs as distinct identities and points the preflight at the peeled ref, so a future re-seed cannot repeat the mistake. No behavior change beyond making the caller resolvable: top-level `permissions: contents: read`, both job-level permission blocks, the absence of `secrets: inherit`, and the event triggers are all unchanged. This is not a revert to a floating `@v1`. --- .github/workflows/governance.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 8c20a539..df4a8d34 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -2,16 +2,22 @@ # # Governance logic lives in Quantum-L9/.github/.github/workflows/governance-*.yml. # This repo's security gates (Scorecard Pinned-Dependencies, Sonar S7637) require -# full-SHA pins, so both callees are pinned to the commit the v1 tag pointed at -# when this file was seeded. Shipping a governance change now means bumping the -# SHA below on re-seed, after the same preflight. +# full-SHA pins, so both callees are pinned to the COMMIT that annotated tag v1 +# peels to. Shipping a governance change means bumping that commit on re-seed, +# after the preflight below. +# +# v1 is an ANNOTATED tag, so it has two distinct SHAs. Pin the second one: +# tag object SHA : 7ed3ab8650583f6659a6caf061eae77dbd3ed1be (refs/tags/v1) +# peeled commit : 3e841ea4f7f8be2a8c9fc45cad5bed46fe801d08 (refs/tags/v1^{}) +# `uses:` must reference the COMMIT. Using the tag object SHA makes the run fail +# to start with zero jobs, because it resolves to no commit. # # Pin record (ops/governance-v1-pin.txt): # Quantum-L9/.github/.github/workflows/governance-pr.yml@v1 # Quantum-L9/.github/.github/workflows/governance-issue.yml@v1 -# tag SHA 7ed3ab8650583f6659a6caf061eae77dbd3ed1be (verified 2026-08-23) -# Preflight: `git ls-remote https://github.com/Quantum-L9/.github.git refs/tags/v1` -# must match the pinned SHA before re-seeding this caller. +# Preflight (verified 2026-08-24) โ€” read the PEELED ref, not the tag ref: +# git ls-remote https://github.com/Quantum-L9/.github.git 'refs/tags/v1^{}' +# must match the pinned commit before re-seeding this caller. # # SECRETS: a called workflow does NOT inherit caller secrets automatically. # Both callees use only GITHUB_TOKEN. Do not add blank `secrets: inherit`. @@ -40,11 +46,11 @@ jobs: permissions: contents: read pull-requests: write - uses: Quantum-L9/.github/.github/workflows/governance-pr.yml@7ed3ab8650583f6659a6caf061eae77dbd3ed1be # v1 + uses: Quantum-L9/.github/.github/workflows/governance-pr.yml@3e841ea4f7f8be2a8c9fc45cad5bed46fe801d08 # v1 issue: if: github.event_name == 'issues' permissions: contents: read issues: write - uses: Quantum-L9/.github/.github/workflows/governance-issue.yml@7ed3ab8650583f6659a6caf061eae77dbd3ed1be # v1 + uses: Quantum-L9/.github/.github/workflows/governance-issue.yml@3e841ea4f7f8be2a8c9fc45cad5bed46fe801d08 # v1