Uploaded files
This commit is contained in:
23
.claude/settings.json
Normal file
23
.claude/settings.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(date:*)",
|
||||
"Bash(echo:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(mkdir:*)",
|
||||
"Bash(wc:*)",
|
||||
"Bash(head:*)",
|
||||
"Bash(tail:*)",
|
||||
"Bash(sort:*)",
|
||||
"Bash(grep:*)",
|
||||
"Bash(tr:*)",
|
||||
"Bash(git add:*)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git status:*)",
|
||||
"Bash(git log:*)",
|
||||
"Bash(git diff:*)",
|
||||
"Bash(git tag:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
14
.claude/skills/check/SKILL.md
Normal file
14
.claude/skills/check/SKILL.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: check
|
||||
description: Run repo checks (ruff + pytest).
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
Run:
|
||||
- Windows: powershell -ExecutionPolicy Bypass -File scripts/check.ps1
|
||||
- Linux/WSL: bash scripts/check.sh
|
||||
|
||||
If a check fails:
|
||||
- capture the error output
|
||||
- propose the smallest safe fix
|
||||
- re-run checks
|
||||
13
.claude/skills/contextpack/SKILL.md
Normal file
13
.claude/skills/contextpack/SKILL.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: contextpack
|
||||
description: Generate a repo snapshot for LLMs (.planning/CONTEXTPACK.md).
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
Run:
|
||||
- python scripts/contextpack.py
|
||||
|
||||
Then read:
|
||||
- .planning/CONTEXTPACK.md
|
||||
|
||||
Use this before planning work or when resuming after a break.
|
||||
11
.editorconfig
Normal file
11
.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# venv
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
# tooling
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# generated
|
||||
.planning/CONTEXTPACK.md
|
||||
1
.planning/.gitkeep
Normal file
1
.planning/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
(placeholder)
|
||||
1
.planning/research/.gitkeep
Normal file
1
.planning/research/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
(placeholder)
|
||||
7
.pre-commit-config.yaml
Normal file
7
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.9
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix"]
|
||||
- id: ruff-format
|
||||
31
CLAUDE.md
Normal file
31
CLAUDE.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Project Rules (auto-loaded)
|
||||
|
||||
## What matters most
|
||||
- Keep changes small and safe.
|
||||
- Prefer incremental improvements over rewrites.
|
||||
- Add/adjust tests when behavior changes.
|
||||
- Keep commits atomic and descriptive.
|
||||
|
||||
## GSD workflow
|
||||
- Use GSD as the source of truth generator:
|
||||
- /gsd:new-project creates PROJECT.md, REQUIREMENTS.md, ROADMAP.md, STATE.md, and .planning/research/
|
||||
- /gsd:discuss-phase -> /gsd:plan-phase -> /gsd:execute-phase -> /gsd:verify-work
|
||||
|
||||
## Repo quick commands
|
||||
- Bootstrap:
|
||||
- Windows: powershell -ExecutionPolicy Bypass -File scripts/bootstrap.ps1
|
||||
- Linux/WSL: bash scripts/bootstrap.sh
|
||||
|
||||
- Run checks:
|
||||
- Windows: powershell -ExecutionPolicy Bypass -File scripts/check.ps1
|
||||
- Linux/WSL: bash scripts/check.sh
|
||||
|
||||
- Generate LLM context snapshot:
|
||||
- python scripts/contextpack.py
|
||||
- output: .planning/CONTEXTPACK.md
|
||||
|
||||
## Definition of done
|
||||
- ruff check .
|
||||
- ruff format --check .
|
||||
- pytest
|
||||
- Update STATE.md if progress changed
|
||||
15
PROJECT.md
Normal file
15
PROJECT.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Project
|
||||
|
||||
(Generated/maintained by GSD)
|
||||
|
||||
## One-liner
|
||||
-
|
||||
|
||||
## Purpose
|
||||
-
|
||||
|
||||
## Users
|
||||
-
|
||||
|
||||
## Non-goals
|
||||
-
|
||||
17
REQUIREMENTS.md
Normal file
17
REQUIREMENTS.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Requirements
|
||||
|
||||
(Generated/maintained by GSD)
|
||||
|
||||
## Must-have (v1)
|
||||
- [ ]
|
||||
|
||||
## Nice-to-have (v2)
|
||||
- [ ]
|
||||
|
||||
## Constraints
|
||||
- Platform:
|
||||
- Performance:
|
||||
- Privacy/security:
|
||||
|
||||
## Acceptance tests
|
||||
- [ ] Given ____, when ____, then ____
|
||||
12
ROADMAP.md
Normal file
12
ROADMAP.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Roadmap
|
||||
|
||||
(Generated/maintained by GSD)
|
||||
|
||||
## Phase 1
|
||||
- [ ]
|
||||
|
||||
## Phase 2
|
||||
- [ ]
|
||||
|
||||
## Phase 3
|
||||
- [ ]
|
||||
20
STATE.md
Normal file
20
STATE.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# State
|
||||
|
||||
(Generated/maintained by GSD)
|
||||
|
||||
## Current focus
|
||||
-
|
||||
|
||||
## What works
|
||||
-
|
||||
|
||||
## What’s broken
|
||||
-
|
||||
|
||||
## Next 3 tasks
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Decisions
|
||||
- (date) decision -> why
|
||||
12
docs/CHECKLIST.md
Normal file
12
docs/CHECKLIST.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Checklists
|
||||
|
||||
## Pre-merge
|
||||
- [ ] ruff check .
|
||||
- [ ] ruff format --check .
|
||||
- [ ] pytest
|
||||
- [ ] docs updated if requirements/decisions changed
|
||||
|
||||
## Release
|
||||
- [ ] version bump
|
||||
- [ ] changelog notes
|
||||
- [ ] basic smoke test
|
||||
0
docs/CONTEXTPACK.md
Normal file
0
docs/CONTEXTPACK.md
Normal file
13
docs/PROJECT.md
Normal file
13
docs/PROJECT.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Project
|
||||
|
||||
## One-liner
|
||||
What is this?
|
||||
|
||||
## Purpose
|
||||
Why does it exist?
|
||||
|
||||
## Users
|
||||
Who is it for?
|
||||
|
||||
## Non-goals
|
||||
What are we intentionally NOT doing?
|
||||
15
docs/REQUIREMENTS.md
Normal file
15
docs/REQUIREMENTS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Requirements
|
||||
|
||||
## Must-have (v1)
|
||||
- [ ]
|
||||
|
||||
## Nice-to-have (v2)
|
||||
- [ ]
|
||||
|
||||
## Constraints
|
||||
- Platform:
|
||||
- Performance:
|
||||
- Privacy/security:
|
||||
|
||||
## Acceptance tests
|
||||
- [ ] Given ____, when ____, then ____
|
||||
10
docs/ROADMAP.md
Normal file
10
docs/ROADMAP.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Roadmap
|
||||
|
||||
## Phase 1: MVP
|
||||
- [ ]
|
||||
|
||||
## Phase 2: Quality + UX
|
||||
- [ ]
|
||||
|
||||
## Phase 3: Scale + polish
|
||||
- [ ]
|
||||
18
docs/STATE.md
Normal file
18
docs/STATE.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# State
|
||||
|
||||
## Current focus
|
||||
-
|
||||
|
||||
## What works
|
||||
-
|
||||
|
||||
## What’s broken
|
||||
-
|
||||
|
||||
## Next 3 tasks
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Recent decisions
|
||||
- (date) decision -> why
|
||||
25
pyproject.toml
Normal file
25
pyproject.toml
Normal file
@@ -0,0 +1,25 @@
|
||||
[project]
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
description = "GSD-native Python template"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0",
|
||||
"ruff>=0.6",
|
||||
"pre-commit>=3.0",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
target-version = "py311"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "B", "UP"]
|
||||
ignore = []
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
9
scripts/bootstrap.ps1
Normal file
9
scripts/bootstrap.ps1
Normal file
@@ -0,0 +1,9 @@
|
||||
python -m venv .venv
|
||||
.\.venv\Scripts\Activate.ps1
|
||||
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -e ".[dev]"
|
||||
|
||||
pre-commit install
|
||||
|
||||
Write-Host "✅ Bootstrapped (.venv created, dev deps installed)"
|
||||
15
scripts/bootstrap.sh
Normal file
15
scripts/bootstrap.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PY=python
|
||||
command -v python >/dev/null 2>&1 || PY=python3
|
||||
|
||||
$PY -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -e ".[dev]"
|
||||
|
||||
pre-commit install || true
|
||||
|
||||
echo "✅ Bootstrapped (.venv created, dev deps installed)"
|
||||
7
scripts/check.ps1
Normal file
7
scripts/check.ps1
Normal file
@@ -0,0 +1,7 @@
|
||||
.\.venv\Scripts\Activate.ps1
|
||||
|
||||
ruff check .
|
||||
ruff format --check .
|
||||
pytest -q
|
||||
|
||||
Write-Host "✅ Checks passed"
|
||||
10
scripts/check.sh
Normal file
10
scripts/check.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
source .venv/bin/activate
|
||||
|
||||
ruff check .
|
||||
ruff format --check .
|
||||
pytest -q
|
||||
|
||||
echo "✅ Checks passed"
|
||||
86
scripts/contextpack.py
Normal file
86
scripts/contextpack.py
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
ROOT = Path(".").resolve()
|
||||
OUT = ROOT / ".planning" / "CONTEXTPACK.md"
|
||||
|
||||
IGNORE_DIRS = {
|
||||
".git",
|
||||
".venv",
|
||||
"venv",
|
||||
"__pycache__",
|
||||
".pytest_cache",
|
||||
".ruff_cache",
|
||||
"dist",
|
||||
"build",
|
||||
"node_modules",
|
||||
}
|
||||
|
||||
KEY_FILES = [
|
||||
"CLAUDE.md",
|
||||
"PROJECT.md",
|
||||
"REQUIREMENTS.md",
|
||||
"ROADMAP.md",
|
||||
"STATE.md",
|
||||
"pyproject.toml",
|
||||
".pre-commit-config.yaml",
|
||||
]
|
||||
|
||||
def run(cmd: list[str]) -> str:
|
||||
try:
|
||||
return subprocess.check_output(cmd, cwd=ROOT, stderr=subprocess.STDOUT, text=True).strip()
|
||||
except Exception as e:
|
||||
return f"(failed: {' '.join(cmd)}): {e}"
|
||||
|
||||
def tree(max_depth: int = 3) -> str:
|
||||
lines: list[str] = []
|
||||
|
||||
def walk(path: Path, depth: int) -> None:
|
||||
if depth > max_depth:
|
||||
return
|
||||
for p in sorted(path.iterdir(), key=lambda x: (x.is_file(), x.name.lower())):
|
||||
if p.name in IGNORE_DIRS:
|
||||
continue
|
||||
rel = p.relative_to(ROOT)
|
||||
indent = " " * depth
|
||||
if p.is_dir():
|
||||
lines.append(f"{indent}📁 {rel}/")
|
||||
walk(p, depth + 1)
|
||||
else:
|
||||
lines.append(f"{indent}📄 {rel}")
|
||||
|
||||
walk(ROOT, 0)
|
||||
return "\n".join(lines)
|
||||
|
||||
def head(path: Path, n: int = 160) -> str:
|
||||
try:
|
||||
return "\n".join(path.read_text(encoding="utf-8", errors="replace").splitlines()[:n])
|
||||
except Exception as e:
|
||||
return f"(failed reading {path}): {e}"
|
||||
|
||||
def main() -> None:
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
parts: list[str] = []
|
||||
parts.append("# Context Pack")
|
||||
parts.append(f"_Generated: {datetime.now().isoformat(timespec='seconds')}_\n")
|
||||
|
||||
parts.append("## Repo tree\n```text\n" + tree() + "\n```")
|
||||
parts.append("## Git status\n```text\n" + run(["git", "status"]) + "\n```")
|
||||
parts.append("## Recent commits\n```text\n" + run(["git", "--no-pager", "log", "-10", "--oneline"]) + "\n```")
|
||||
|
||||
parts.append("## Key files (head)")
|
||||
for f in KEY_FILES:
|
||||
p = ROOT / f
|
||||
if p.exists():
|
||||
parts.append(f"### {f}\n```text\n{head(p)}\n```")
|
||||
|
||||
OUT.write_text("\n\n".join(parts) + "\n", encoding="utf-8")
|
||||
print(f"✅ Wrote {OUT.relative_to(ROOT)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
src/app/__init__.py
Normal file
1
src/app/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__all__ = []
|
||||
6
src/app/__main__.py
Normal file
6
src/app/__main__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
def main() -> None:
|
||||
print("Hello from app!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
6
src/app/main.py
Normal file
6
src/app/main.py
Normal file
@@ -0,0 +1,6 @@
|
||||
def main() -> None:
|
||||
print("Hello from app!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
2
tests/test_smoke.py
Normal file
2
tests/test_smoke.py
Normal file
@@ -0,0 +1,2 @@
|
||||
def test_smoke() -> None:
|
||||
assert True
|
||||
Reference in New Issue
Block a user