Skip to content

Commit 5ca70fa

Browse files
committed
Initial public commit: method-kit
0 parents  commit 5ca70fa

99 files changed

Lines changed: 18578 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* text=auto
2+
*.sh text eol=lf

.github/required-checks.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"required": ["quality", "tests", "security", "Analyze (python)"],
3+
"decisional": ["quality", "tests", "security"]
4+
}

.github/rulesets/main.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "main: require pull request",
3+
"target": "branch",
4+
"enforcement": "active",
5+
"conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] } },
6+
"rules": [
7+
{ "type": "pull_request" },
8+
{ "type": "non_fast_forward" },
9+
{ "type": "deletion" }
10+
]
11+
}

.github/workflows/action-drift.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: action-drift
2+
3+
# Detector, not gate (METHOD section 8): a determinism-pinned action is
4+
# monitored, never silently refreshed. On drift this workflow opens an issue;
5+
# it never edits workflow files and never blocks a merge. The job stays green
6+
# even when it files an issue, so drift surfaces in the Issues tab (the chosen
7+
# signal channel) rather than as a redundant red run + email.
8+
9+
on:
10+
schedule:
11+
- cron: "0 6 * * 1" # every Monday 06:00 UTC
12+
workflow_dispatch: {} # manual trigger for testing
13+
14+
permissions:
15+
contents: read
16+
issues: write
17+
18+
jobs:
19+
drift:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
23+
24+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
25+
with:
26+
python-version: "3.13"
27+
28+
- name: Check action-pin drift
29+
id: drift
30+
run: |
31+
set +e
32+
report="$(python scripts/check_action_drift.py .github/workflows/)"
33+
code=$?
34+
echo "$report"
35+
{
36+
echo "report<<DRIFT_EOF"
37+
echo "$report"
38+
echo "DRIFT_EOF"
39+
echo "code=$code"
40+
} >> "$GITHUB_OUTPUT"
41+
exit 0
42+
43+
- name: Open an issue on drift
44+
if: steps.drift.outputs.code != '0'
45+
env:
46+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47+
run: |
48+
set -e
49+
title="Action-pin drift detected"
50+
# Anti-spam: do not stack a second issue if one is already open.
51+
existing="$(gh issue list --state open --search "$title in:title" --json number --jq 'length')"
52+
if [ "$existing" -gt 0 ]; then
53+
echo "An open drift issue already exists; not filing a duplicate."
54+
exit 0
55+
fi
56+
body="$(printf 'The scheduled drift check found action pins that no longer match their upstream tags.\n\n```\n%s\n```\n\nThis is a *detector*: review each finding and re-pin manually (resolve the tag with `git ls-remote`, never auto-refresh). See METHOD section 8.' "${{ steps.drift.outputs.report }}")"
57+
gh issue create --title "$title" --body "$body"

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# ci.yml — quality gate. Required check name: "quality".
2+
# Reproduces the three local sweeps so a green local run means the PR passes
3+
# first time: ruff check -> ruff format --check -> compileall.
4+
name: ci
5+
6+
on:
7+
pull_request:
8+
push:
9+
branches: [main]
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
quality:
16+
name: quality
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
20+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
21+
with:
22+
python-version: "3.12"
23+
# Exact-version pin: determinism + exact CI<->local parity. Bump at instantiation.
24+
- run: python -m pip install --upgrade pip && pip install --group lint --group runtime
25+
# Gate commands: single-sourced in scripts/gates/quality.sh, run
26+
# identically by a contributor (METHOD section 6 "retire le canal" /
27+
# S31). Setup stays in YAML (job-specific); commands live in the script.
28+
- run: bash scripts/gates/quality.sh

.github/workflows/codeql.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# codeql.yml — CodeQL advanced setup, query suite "security-extended".
2+
# Check name: "Analyze (python)".
3+
#
4+
# IMPORTANT (METHOD §7): this workflow only RUNS the analysis and uploads alerts.
5+
# A green "Analyze (python)" means "CodeQL ran", never "nothing serious found".
6+
# The merge content-gate ("block if an alert >= threshold sits in the PR diff")
7+
# is a code_scanning rule of a ruleset — LAYER B — created with `gh api` at
8+
# bootstrap, not a file here. Do NOT enable the default setup as well: advanced
9+
# and default setups are mutually exclusive.
10+
name: codeql
11+
12+
on:
13+
pull_request:
14+
push:
15+
branches: [main]
16+
schedule:
17+
- cron: "0 6 * * 1" # weekly, Monday 06:00 UTC
18+
19+
jobs:
20+
analyze:
21+
name: Analyze
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
25+
security-events: write # required to upload CodeQL results
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
language: ["python"]
30+
steps:
31+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
32+
- uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
33+
with:
34+
languages: ${{ matrix.language }}
35+
queries: security-extended
36+
- uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
37+
with:
38+
category: "/language:${{ matrix.language }}"

.github/workflows/release.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# release.yml — triggered ONLY on a v* tag push. Builds the .skill deliverable
2+
# and attaches it to a GitHub Release.
3+
#
4+
# Caveat (METHOD §7): a green PR does NOT exercise this workflow — it runs only
5+
# at the next v* tag. Validate the release path at that tag, never assume it.
6+
#
7+
# The version is never typed here: package_skill.py reads it from the suite's
8+
# metadata.version (SKILL.md frontmatter) and names the archive from it. The
9+
# guard below refuses to publish when the pushed tag and that version disagree —
10+
# so a release cannot advertise a version its artifact does not carry.
11+
name: release
12+
13+
on:
14+
push:
15+
tags: ["v*"]
16+
17+
permissions:
18+
contents: write # required to create a Release and upload assets
19+
20+
jobs:
21+
release:
22+
name: release
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
26+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
27+
with:
28+
python-version: "3.12"
29+
- name: Build the .skill and verify it matches the tag
30+
run: |
31+
set -euo pipefail
32+
# package_skill.py validates the suite, reads metadata.version from
33+
# SKILL.md (never typed), and writes the stamped archive into dist/
34+
# (git-ignored, so a clean checkout starts empty and exactly one
35+
# artifact is produced). It prints the archive path on stdout.
36+
artifact="$(python skills/project-pilot/modules/skill-packaging/scripts/package_skill.py skills/project-pilot --out-dir dist)"
37+
echo "Built: ${artifact}"
38+
# Guard (closes the channel S42 retires): the pushed tag must name the
39+
# same version the artifact carries. ${GITHUB_REF_NAME} is the tag,
40+
# e.g. v0.17.0; the artifact is project-pilot_v<version>_<date>.skill.
41+
# The quoted prefix is literal (tag metacharacters cannot glob); only
42+
# the date wildcard floats. On disagreement, abort BEFORE the release.
43+
case "$(basename "${artifact}")" in
44+
"project-pilot_${GITHUB_REF_NAME}_"*.skill) ;;
45+
*)
46+
echo "ERROR: tag ${GITHUB_REF_NAME} does not match built artifact $(basename "${artifact}")" >&2
47+
exit 1
48+
;;
49+
esac
50+
- name: Create release and attach the artifact
51+
env:
52+
GH_TOKEN: ${{ github.token }}
53+
run: gh release create "${GITHUB_REF_NAME}" dist/* --generate-notes

.github/workflows/security.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# security.yml — security gate. Required check name: "security".
2+
# Bandit SAST over the WHOLE repo, configured from pyproject.toml (single source).
3+
name: security
4+
5+
on:
6+
pull_request:
7+
push:
8+
branches: [main]
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
security:
15+
name: security
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
19+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
20+
with:
21+
python-version: "3.12"
22+
# Exact-version pin (determinism + CI<->local parity). [toml] extra reads pyproject.
23+
- run: python -m pip install --upgrade pip && pip install --group security
24+
# Gate command single-sourced in scripts/gates/security.sh (S31).
25+
- run: bash scripts/gates/security.sh

.github/workflows/tests.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# tests.yml — tests gate. Required check name: "tests".
2+
# Each skill ships a deterministic floor (exit 0/1, pure stdlib) — METHOD §7.
3+
# Floors are auto-discovered, not hard-listed: discover_floors.py runs every
4+
# Python file carrying the `# FLOOR` marker (ROADMAP G5). Adding a skill means
5+
# dropping a marked floor — this workflow is never edited again. pytest-style
6+
# floors under tests/ are found by `pytest tests/`.
7+
name: tests
8+
on:
9+
pull_request:
10+
push:
11+
branches: [main]
12+
permissions:
13+
contents: read
14+
jobs:
15+
tests:
16+
name: tests
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
20+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
21+
with:
22+
python-version: "3.12"
23+
# Exact-version pin (determinism + CI<->local parity) via the test group.
24+
- run: python -m pip install --upgrade pip && pip install --group test
25+
# Gate commands single-sourced in scripts/gates/tests.sh (S31).
26+
- run: bash scripts/gates/tests.sh

.gitignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# --- Build artifacts ---
2+
/dist/
3+
*.skill
4+
*.mcpb
5+
6+
# --- Local env / Python ---
7+
.venv/
8+
__pycache__/
9+
*.pyc
10+
11+
# --- Scratch / runtime ---
12+
outputs/
13+
/mnt/
14+
15+
# --- Reference scaffolding (not the product) ---
16+
_reference/
17+
18+
# --- Trust boundary: secrets and real data (METHOD 3/8) ---
19+
.env
20+
*.env
21+
CV_*.docx
22+
signature*.txt
23+
*_tracker*
24+
25+
# --- Stray stamped piloting copies (figes ROADMAP.md/JOURNAL.md/GLOSSAIRE.md NOT matched) ---
26+
ROADMAP_*.md
27+
JOURNAL_*.md
28+
GLOSSAIRE_*.md
29+
METHOD_HISTORY_*.md
30+
31+
# --- OS / editors ---
32+
.DS_Store
33+
Thumbs.db
34+
.idea/
35+
.vscode/
36+
37+
# --- Public scaffolds: carve the trinity templates back in (G8) ---
38+
# The broad nets above (lines 26-28) also swallow these scaffold names. They are
39+
# intentionally public; an instantiated private steering doc is named
40+
# <DOC>_<project>_<stamp>.md and stays ignored, so the safety net is unaffected.
41+
!ROADMAP_template.md
42+
!JOURNAL_template.md
43+
!GLOSSAIRE_template.md
44+
/method/METHOD.md
45+
46+
# --- De-lied frozen piloting vestiges (S50): untracked, pinned-ignored by EXACT
47+
# path so they cannot be re-added. Deliberately NOT a broad pilotage/ net, which
48+
# would swallow pilotage/journal-archive/ — kept tracked for durability (METHOD 5). ---
49+
/method/METHOD_HISTORY.md
50+
/pilotage/ROADMAP.md
51+
/pilotage/JOURNAL.md
52+
/pilotage/GLOSSAIRE.md

0 commit comments

Comments
 (0)