| <!-- GSD:project-start source:PROJECT.md --> |
| ## Project |
|
|
| **FATHOM β First RL-Trained Recursive Language Model** |
|
|
| FATHOM is an OpenEnv environment + GRPO training pipeline that teaches a small open-source language model (Qwen2.5-Coder-1.5B-Instruct, 4-bit + LoRA) to *use* a Recursive Language Model (RLM) scaffold well: slice long contexts with Python, grep for relevant regions, delegate to sub-LM calls only when needed, and answer questions about documents that are 50Γ larger than its own context window. It is our submission to the Meta Γ PyTorch Γ Hugging Face OpenEnv Hackathon Grand Finale (Scaler School of Technology, Bangalore, April 25β26, 2026). |
|
|
| **Core Value:** A 1.5B model trained on our environment solves 200K-token QA tasks its own 4K context cannot hold β demonstrated with a clean reward curve, a selective recursion-tree visualization, and a Pareto frontier of accuracy-vs-tokens. If only one thing ships, it is this single demo. |
|
|
| ### Constraints |
|
|
| - **Timeline**: ~40 usable hours of building across 4 days β every phase must produce a committed, demonstrable artifact before moving on, because there is no slack for context-lost rebuilds. |
| - **Tech stack**: TRL (trainer) + Unsloth (efficiency + inference) + OpenEnv (environment standard) + Hugging Face Spaces (deployment). Dictated by hackathon rubric β deviating costs "judge goodwill" points. |
| - **Algorithm**: GRPO specifically (not PPO/DPO) β hackathon rubric names GRPO as canonical, public reproductions exist to crib from, TRL `GRPOTrainer` is the first-class path. |
| - **Base model**: Qwen2.5-Coder-1.5B-Instruct (4-bit via `unsloth/Qwen2.5-Coder-1.5B-Instruct-bnb-4bit`). 3B cut post-research-synthesis β venue A100 flavor unknown, 3B would eat the 40-hour budget for uncertain upside. 1.5B with clean curve beats 3B with partial curve on judging. |
| - **Pre-event hardware**: Laptop RTX 4060, 8 GB VRAM. Can only run CPU/0.5B smoke tests locally β 1.5B+ runs are venue-only. |
| - **Reward verifier must be deterministic**: No LLM-as-judge in the training loop. Every task has an exact-match or short-span gold answer. |
| - **Context window**: Train at 16 K, claim generalization to 200 K at eval. Rollout latency at 200 K is prohibitive for GRPO. |
| - **Recursion depth in training**: β€ 2. Deeper recursion is demo-only at inference time. |
| - **Judging criteria (hard)**: Submissions are scored on clear env design + objective rewards + demonstrable improvement + anti-reward-hacking + reproducible deployment + sharp demo. Every phase must produce an artifact mapping to at least one criterion. |
| - **Pitch**: 3 minutes, 30% of judging weight goes to storytelling. The Pareto chart and recursion-tree viz must exist before the last 4 hours, not after. |
| <!-- GSD:project-end --> |
|
|
| <!-- GSD:stack-start source:research/STACK.md --> |
| ## Technology Stack |
|
|
| ## 1. Versions by Role (April 2026 pins) |
| | Role | Package | Version pin | Confidence | Source | |
| |------|---------|-------------|------------|--------| |
| | **OpenEnv core/CLI** | `openenv-core[core]` | `>=0.2.3,<0.3` | HIGH | [meta-pytorch/OpenEnv v0.2.3, Mar 28 2026](https://github.com/meta-pytorch/OpenEnv) | |
| | **TRL (GRPOTrainer + OpenEnv integration)** | `trl` | `==1.2.0` | HIGH | [PyPI trl 1.2.0, Apr 17 2026](https://pypi.org/project/trl/); [TRL OpenEnv guide](https://huggingface.co/docs/trl/main/en/openenv) | |
| | **Unsloth (efficiency + save)** | `unsloth` | `==2026.4.8` (v0.1.36-beta tag, whatever passes Thu smoke test) | MEDIUM | [unslothai/unsloth releases, v0.1.36-beta Apr 8 2026](https://github.com/unslothai/unsloth/releases) | |
| | **Unsloth Zoo** | `unsloth-zoo` | latest-compatible (Unsloth resolves) | MEDIUM | β | |
| | **Torch (CUDA 12.4 for A100)** | `torch` | `==2.6.0` | HIGH | PyTorch 2.6+ is Unsloth-supported; 2.6 ships cu124 wheel | |
| | **Transformers** | `transformers` | `==4.49.0` | HIGH | Pinned by TRL 1.2 requirements | |
| | **Accelerate** | `accelerate` | `==1.5.2` | HIGH | Pinned by TRL 1.2 | |
| | **PEFT** | `peft` | `==0.14.0` | HIGH | Pinned by TRL 1.2 | |
| | **bitsandbytes** | `bitsandbytes` | `==0.45.1` | HIGH | 0.45+ required for cu124 + Ampere+Hopper paths | |
| | **vLLM (for colocate inference)** | `vllm` | `==0.7.3` | HIGH | Matches TRL 1.2 server + colocate contract; Unsloth fast_inference path compatible | |
| | **Datasets** | `datasets` | `==3.3.2` | HIGH | Transformers 4.49 pair | |
| | **HF Hub** | `huggingface_hub` | `>=0.28,<1.0` | HIGH | Space push + snapshot_download | |
| | **FastAPI (env server)** | `fastapi` | `>=0.115,<0.120` | HIGH | OpenEnv scaffold generates FastAPI app | |
| | **Uvicorn** | `uvicorn[standard]` | `>=0.32,<1.0` | HIGH | β | |
| | **Pydantic** | `pydantic` | `>=2.9,<3.0` | HIGH | OpenEnv + TRL both on Pydantic 2 | |
| | **W&B** | `wandb` | `>=0.18,<1.0` | HIGH | Default TRL callback | |
| | **Streamlit (viz + tree)** | `streamlit` | `>=1.39,<2.0` | HIGH | Richer than Gradio for recursion-tree D3 embed (see Β§1.1) | |
| | **Plotly (Pareto chart)** | `plotly` | `>=5.24,<6.0` | HIGH | β | |
| | **Matplotlib (quick plots, W&B)** | `matplotlib` | `>=3.9,<4.0` | HIGH | β | |
| | **RestrictedPython (REPL AST filter)** | `RestrictedPython` | `>=7.4,<8.0` | HIGH | [zopefoundation/RestrictedPython docs](https://restrictedpython.readthedocs.io/) | |
| | **Claude API (SFT data gen)** | `anthropic` | `>=0.40,<1.0` | HIGH | SFT trace generator only; not a runtime dep | |
| ### 1.1 Streamlit vs Gradio β decided |
| ## 2. Canonical Install β Single Block |
| # Step 0: CUDA 12.4 sanity check |
| # Step 1: create env (uv preferred; pip fallback below) |
| # Step 2: torch first (CUDA 12.4 wheel), own line to avoid resolver confusion |
| # Step 3: core training stack |
| # Step 4: Unsloth (pin to Thu-smoke-test version; DO NOT -U at venue) |
| # Step 5: env server + tooling |
| # Step 6: observability + viz + data gen |
| # Step 7: flash-attention (optional but big speedup for generation) |
| ## 3. Qwen2.5-Coder Specifics |
| ### 3.1 Primary: Qwen2.5-Coder-1.5B-Instruct |
| | Attribute | Value | Source | |
| |-----------|-------|--------| |
| | HF ID (base) | `Qwen/Qwen2.5-Coder-1.5B-Instruct` | [HF model card](https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct) | |
| | HF ID (Unsloth-preferred for faster load) | `unsloth/Qwen2.5-Coder-1.5B-Instruct` | [unsloth/Qwen2.5-Coder-1.5B-Instruct](https://huggingface.co/unsloth/Qwen2.5-Coder-1.5B-Instruct) | |
| | HF ID (Unsloth 4-bit bnb pre-quant) | `unsloth/Qwen2.5-Coder-1.5B-Instruct-bnb-4bit` | [Unsloth Qwen 2.5 Coder collection](https://huggingface.co/collections/unsloth/qwen-25-coder) | |
| | Parameters | 1.54B total / 1.31B non-embedding | HF card | |
| | BF16 size on disk | ~3.1 GB | HF card | |
| | 4-bit bnb size on disk | ~1.1 GB | Unsloth card | |
| | Context length (native) | 32,768 tokens | HF card config.json | |
| | Context length (with YaRN scaling) | 131,072 tokens (factor 4.0) | HF card long-context section | |
| | Architecture | 28 layers, 12 Q-heads, 2 KV-heads (GQA), SwiGLU, RMSNorm, RoPE | HF card | |
| | Chat template | ChatML-derived with `<|im_start|>` / `<|im_end|>` + system/user/assistant | HF card | |
| ### 3.2 Stretch: Qwen2.5-Coder-3B-Instruct |
| | Attribute | Value | |
| |-----------|-------| |
| | HF ID | `Qwen/Qwen2.5-Coder-3B-Instruct` | |
| | HF ID (Unsloth 4-bit) | `unsloth/Qwen2.5-Coder-3B-Instruct-bnb-4bit` | |
| | BF16 size on disk | ~6.2 GB | |
| | 4-bit + LoRA (rank 32) VRAM @ 16K context + 8 generations | ~38-45 GB (**fits A100-80GB with headroom; tight/no-go on A100-40GB**) | |
| | Context length (native) | 32,768 tokens | |
| ### 3.3 Chat template β one source of truth (prevents H6) |
| # For training (SFT with assistant response to learn): |
| # For rollout/eval (model to generate): |
| - Use `Qwen2.5-Coder-1.5B-Instruct` (has chat template baked in), never the non-Instruct base. |
| - Do NOT try `return_assistant_tokens_mask=True` β broken on Qwen2.5 per transformers #34172. Full-sequence SFT loss is fine for our scale. |
| - TRL 1.2's OpenEnv integration applies the tokenizer's chat template internally for multi-turn tool calls. Do not hand-concatenate `<|im_start|>` strings anywhere in our code. |
| - Diff-test the smoke test: tokenize one SFT example with our prep code; tokenize the same example through `GRPOTrainer._prepare_inputs` (set a breakpoint); confirm zero token-ID drift. |
| ## 4. GRPOTrainer Config β Minimum Viable |
| ### Passing per-sample reward functions |
| ### `reward_weights` vs compose-in-fn |
| ## 5. Unsloth vs vLLM for Rollouts β Resolved |
| ## 6. LoRA Save Sequence β Verbatim Snippet |
| # === AT END OF GRPO TRAINING (after trainer.train() returns) === |
| # (1) ALWAYS save adapter-only first. Small (~15MB), never hits the broken merge paths. |
| # This is our reproducibility artifact and our safety net. |
| # (2) Push adapter to HF Hub immediately β cheap and protects against local-disk loss. |
| # (3) Save a merged 16-bit model for fast inference at demo time. |
| # save_method="merged_16bit" is the ONE safe choice. Never use: |
| # - "merged_4bit" β corrupt under QLoRA (#1267, #2339) |
| # - "merged_4bit_forced" β silently emits 16bit (#2339) or size-mismatched (#1791) |
| # If the call fails inside Docker with an empty dir (#3882), fall back to |
| # step (4) manual merge via peft. |
| # trainer.model is already an Unsloth-patched PeftModel |
| # (4) Sanity check BEFORE declaring training done: load the merged model, |
| # run 3 eval questions, assert non-empty output. |
| ### Loading back for eval |
| ### RoPE scaling for 200K eval |
| ## 7. Python REPL Sandbox β Choice + Safety Checklist |
| - **Plain subprocess with timeout only** β no AST filter means attribute-access escape paths (`__subclasses__`, `catch_warnings`, traceback walk) still work inside the subprocess. Model can escape to subprocess.Popen within our own subprocess. |
| - **Pyodide-via-subprocess** β spawns a browser-grade WASM runtime per call; 500ms+ startup per REPL action, kills rollout throughput at 8 generations Γ multiple turns. |
| - **OpenEnv built-in** β OpenEnv ships tool primitives but no Python REPL sandbox; the scaffold expects us to write `env/server/repl.py` (confirmed in ARCHITECTURE.md Β§1). |
| - RestrictedPython AST-rewrites at compile time: blocks `__class__`, `__subclasses__`, `__globals__`, attribute access into dunders, star imports. Not a full sandbox but stops 90% of trivial Python-sandbox-escape CTF payloads. |
| - Subprocess isolation handles the remaining 10%: if a tricky escape produces an import or system call, it hits the OS-level wall (no network, read-only cwd, ulimit'd CPU/memory, seccomp deny-list). Subprocess crashes don't kill the env server. |
| - `RestrictedPython>=7.4` is actively maintained by zopefoundation and mature. |
| ### Safety checklist (implement as `tests/test_repl_sandbox.py` before shipping) |
| - [ ] `open` β no file I/O |
| - [ ] `exec` β no dynamic code |
| - [ ] `eval` β no dynamic eval |
| - [ ] `compile` β no AST manipulation |
| - [ ] `__import__` β whitelist via custom import hook (see below) |
| - [ ] `__builtins__` β set to a minimal dict; never pass through the raw module |
| - [ ] `input` / `breakpoint` / `help` / `exit` / `quit` β exit paths and interactive prompts |
| - [ ] `re`, `json`, `math`, `statistics`, `collections`, `itertools`, `string`, `functools`, `operator` |
| - [ ] **NO** `os`, `sys`, `subprocess`, `socket`, `urllib`, `http`, `requests`, `pathlib`, `io`, `ctypes`, `threading`, `multiprocessing`, `pickle`, `marshal`, `importlib` |
| - [ ] Separate `subprocess.Popen` with `start_new_session=True` |
| - [ ] `ulimit -v 524288` (512MB RAM) via `preexec_fn` / `resource.setrlimit` |
| - [ ] `ulimit -t 5` (5s CPU), `ulimit -f 0` (no file writes) |
| - [ ] `cwd=/tmp/episode-{uuid}` (ephemeral, wiped on `reset()`) |
| - [ ] Non-root user (venue A100 containers default to uid 1000 β verify at setup) |
| - [ ] Network: `unshare -n` if available, else seccomp deny `socket`, `connect`, `sendto` |
| - [ ] Timeout: hard-kill at 30s wall-clock (`subprocess.wait(timeout=30)`, then `Popen.kill()`) |
| - [ ] `().__class__.__base__.__subclasses__()` β attribute access blocked by RestrictedPython |
| - [ ] `e.__traceback__.tb_frame.f_back.f_builtins` β traceback walk after a raise |
| - [ ] `warnings.catch_warnings()` builtins trick β import blocked by whitelist |
| - [ ] `__import__('os')` β whitelist rejects |
| - [ ] `getattr(__builtins__, 'open')` β `__builtins__` replaced with minimal dict |
| - [ ] 30s-infinite-loop β subprocess killed, env continues |
| - [ ] 1GB memory bomb β rlimit kills, env continues |
| ## 8. `openenv init` Scaffold Workflow |
| ### 8.1 Scaffold |
| # From repo root |
| # or with explicit typed-action template (v0.2.3+): |
| ### 8.2 Edits we make (post-init) |
| - Add to `src/envs/fathom/server/app.py`: |
| - In `environment.py`, declare `SUPPORTS_CONCURRENT_SESSIONS: bool = True` at module scope (required for TRL's 8 parallel generations β confirmed in [TRL OpenEnv guide Β§Server concurrency](https://huggingface.co/docs/trl/main/en/openenv#server-concurrency)). |
| - Implement REPL + `llm()` primitive per ARCHITECTURE.md Β§1. |
| ### 8.3 Local run |
| # In another terminal: |
| ### 8.4 Deploy to HF Space |
| # Login once (prerequisite): |
| # Push (creates or updates the Space): |
| # Manual push via huggingface_hub: |
| ## 9. SFT Library Choice |
| - `unsloth.UnslothTrainer` β custom trainer, fewer public examples, harder to swap to GRPO afterward. |
| - Raw training loop β pointless reinvention; SFTTrainer is ~20 LoC of setup. |
| - Same model object then passes to `GRPOTrainer` with zero re-init cost (PITFALLS.md H6 prevention). |
| - TRL 1.2 `SFTTrainer` accepts Unsloth-patched models without special handling. |
| - We keep the chat-template formatting in one place (`formatting_func`) β same template used later in GRPO. |
| ### Snippet β adapting Claude-generated conversations to SFT format |
| # (1) Load base model with LoRA adapters attached (Unsloth patch) |
| # (2) Claude traces on disk look like this (one line of JSONL per trajectory): |
| # {"system": "...", "messages": [{"role":"user","content":"..."}, |
| # {"role":"assistant","content":"..."}, |
| # {"role":"tool","content":"..."}, |
| # {"role":"assistant","content":"..."}]} |
| # (3) formatting_func β apply_chat_template (single source of truth, Β§3.3 rule) |
| # (4) SFT config β light touch so we don't overfit (PITFALLS.md M7) |
| # Save SFT adapter β GRPO will load from here |
| ## 10. Anti-Patterns β Stack-Specific |
| ### 10.1 `save_pretrained_merged(save_method="merged_4bit")` on a QLoRA model |
| ### 10.2 Mismatched chat template between SFT prep and GRPO rollouts |
| ### 10.3 `max_completion_length > 2048` before the smoke test has run |
| ### 10.4 `vllm_mode="server"` for multi-turn OpenEnv training |
| ### 10.5 `pip install -U unsloth` at the venue |
| ### 10.6 Running REPL subprocess in the env server's cwd |
| ### 10.7 Logging only the composite reward to W&B |
| ### 10.8 Passing raw `<|im_start|>user\n...` strings to GRPOTrainer |
| ### 10.9 Saving merged model without sanity-checking the output |
| ### 10.10 Using `Qwen2.5-Coder-1.5B` (base) instead of `-Instruct` |
| ### 10.11 Trusting `trl vllm-serve` in server mode as a separate process |
| ### 10.12 `gradient_checkpointing=False` "to go fast" |
| ## 11. Prerequisite Setup β One-Time Commands at Venue |
| # ββ G1: GPU alive, CUDA visible |
| # expect: CUDA Version 12.4+, A100-SXM4-40GB or A100-80GB, 0 MiB used |
| # ββ G2: CUDA toolkit version compatible with torch cu124 wheel |
| # ββ G3: Python + uv |
| # ββ G4: Install FATHOM env (single pip block from Β§2 above) |
| # run the Β§2 commands here |
| # ββ G5: Verify torch sees the A100 |
| # expect: True NVIDIA A100-... |
| # ββ G6: HF login (write token from hf.co/settings/tokens) |
| # paste token; verify: |
| # ββ G7: W&B login (API key from wandb.ai/authorize) |
| # paste key; verify: |
| # ββ G8: OpenEnv CLI alive |
| # ββ G9: Pre-pull the model into HF cache (avoid mid-training download stalls) |
| # ββ G10: Smoke-test GRPOTrainer imports (catches version-skew issues) |
| # ββ G11: Sandbox unit tests (these MUST pass before env server goes public) |
| # ββ G12: End-to-end smoke β 1 GRPO step |
| ## 12. Confidence & Verification Matrix |
| | Recommendation | Confidence | Basis | If LOW β 10-min venue verification | |
| |---------------|------------|-------|------------------------------------| |
| | TRL == 1.2.0 | HIGH | PyPI dated 2026-04-17 | β | |
| | Unsloth == 2026.4.8 (v0.1.36-beta) | MEDIUM | GitHub releases page; rapid iteration | `python -c "import unsloth; print(unsloth.__version__)"` then run G12 smoke test | |
| | OpenEnv-core >= 0.2.3 | HIGH | GitHub tag + TRL guide references 0.2.1+ | β | |
| | torch 2.6 cu124 | HIGH | PyTorch wheel index stable | `torch.version.cuda` == '12.4' | |
| | vllm 0.7.3 | HIGH | TRL 1.2 OpenEnv examples target it | `vllm --version` | |
| | `vllm_mode="colocate"` for multi-turn | HIGH | TRL OpenEnv guide Wordle example + PITFALLS #4543 | Run G12 smoke with 1 turn, then with 2 turns β advantage should look normal | |
| | `beta=0.04` KL floor | MEDIUM | EDGE-GRPO paper + PITFALLS H1; TRL default is 0.0 | Train 50 steps with Ξ²=0.0; if group_std drops <0.05 β switch to 0.04 | |
| | `num_generations=8` | HIGH | TRL default; all OpenEnv examples | β | |
| | `learning_rate=5e-6` with 4-bit | MEDIUM | PITFALLS M1 "4-bit safe band 5e-6 to 1e-5" | First 20 steps β if loss NaN, drop to 3e-6; if flat, raise to 1e-5 | |
| | `max_grad_norm=0.5` | MEDIUM | PITFALLS M1 conservative | Widen to 1.0 only if training too conservative and loss plateaus | |
| | Unsloth Qwen2.5-Coder-1.5B-Instruct-bnb-4bit | HIGH | HF Unsloth collection page | β | |
| | YaRN factor=4.0 for 200K eval | MEDIUM | HF model card long-context section; PITFALLS M8 warns | At eval time, test 50K β 100K β 150K β 200K; note first OOM point, cap claim there | |
| | Merged-16bit save as the only trusted path | HIGH | PITFALLS R4 (5 issue numbers); Β§6 snippet follows Unsloth docs | β | |
| | RestrictedPython + subprocess sandbox | HIGH | Canonical pattern; dida.do / tianpan.co verified | Run the 7 adversarial unit tests in Β§7 β if any pass, patch before shipping | |
| | Streamlit (not Gradio) for demo Space | MEDIUM | Our override on FEATURES.md TS-DEM-2 rationale | Build both skeletons Thu; pick the one that renders the D3 tree cleaner in 30 min | |
| | `SFTTrainer` + Unsloth model | HIGH | Unsloth notebook collection; TRL 1.2 supports Unsloth models | β | |
| | `openenv push` for HF Space | MEDIUM | OpenEnv CLI 0.2.3 docs; new CLI | Try `push` Thu; if it fails, use the manual `git push` fallback in Β§8.4 | |
| | Chat template one-source-of-truth | HIGH | PITFALLS H6 + HF Qwen card | Diff-test token IDs in smoke β zero drift is the gate | |
| - Unsloth exact version pin (re-run G10 smoke after pinning) |
| - vLLM colocate memory fraction β `vllm_gpu_memory_utilization=0.45` may need tuning on A100-40GB vs 80GB; watch `nvidia-smi` during the first 10 GRPO steps |
| - Ξ² (KL coefficient) β if group_std stays healthy at 0.0, save the 1% throughput; if collapse appears, bump to 0.04. Cheap to toggle mid-run via config. |
| ## 13. Sources |
| - [TRL 1.2.0 on PyPI (2026-04-17)](https://pypi.org/project/trl/) β HIGH |
| - [TRL OpenEnv Integration guide](https://huggingface.co/docs/trl/main/en/openenv) β HIGH |
| - [TRL GRPOConfig on GitHub main](https://github.com/huggingface/trl/blob/main/trl/trainer/grpo_config.py) β HIGH |
| - [Unsloth releases on GitHub](https://github.com/unslothai/unsloth/releases) β HIGH |
| - [Unsloth RL Guide](https://unsloth.ai/docs/get-started/reinforcement-learning-rl-guide) β HIGH |
| - [Unsloth Qwen 2.5 Coder collection](https://huggingface.co/collections/unsloth/qwen-25-coder) β HIGH |
| - [Qwen2.5-Coder-1.5B-Instruct HF card](https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct) β HIGH |
| - [Unsloth/Qwen2.5-Coder-1.5B-Instruct HF card](https://huggingface.co/unsloth/Qwen2.5-Coder-1.5B-Instruct) β HIGH |
| - [meta-pytorch/OpenEnv GitHub v0.2.3](https://github.com/meta-pytorch/OpenEnv) β HIGH |
| - [vLLM training/trl docs](https://docs.vllm.ai/en/latest/training/trl/) β HIGH |
| - [RestrictedPython docs](https://restrictedpython.readthedocs.io/) β HIGH |
| - Unsloth LoRA save bug issues: #1791, #2339, #1267, #3882, #1877 (PITFALLS.md R4) β HIGH |
| - TRL multi-turn bug: #4543 (PITFALLS.md H2) β HIGH |
| - Chat template gotcha: transformers #34172 (PITFALLS.md N2) β HIGH |
| - Qwen2.5 + RoPE scaling for 200K: HF card + Unsloth #3083 (PITFALLS.md M8) β HIGH |
| - OpenEnv env server design: ARCHITECTURE.md Β§1, Β§8 β HIGH |
| - Reward decomposition pattern: ARCHITECTURE.md Β§6 Pattern 1 β HIGH |
| - Sandbox pattern choice: dida.do + tianpan.co via PITFALLS.md H3 β HIGH |
| <!-- GSD:stack-end --> |
| |
| <!-- GSD:conventions-start source:CONVENTIONS.md --> |
| ## Conventions |
| |
| Conventions not yet established. Will populate as patterns emerge during development. |
| <!-- GSD:conventions-end --> |
| |
| <!-- GSD:architecture-start source:ARCHITECTURE.md --> |
| ## Architecture |
| |
| Architecture not yet mapped. Follow existing patterns found in the codebase. |
| <!-- GSD:architecture-end --> |
| |
| <!-- GSD:skills-start source:skills/ --> |
| ## Project Skills |
| |
| No project skills found. Add skills to any of: `.claude/skills/`, `.agents/skills/`, `.cursor/skills/`, or `.github/skills/` with a `SKILL.md` index file. |
| <!-- GSD:skills-end --> |
| |
| <!-- GSD:workflow-start source:GSD defaults --> |
| ## GSD Workflow Enforcement |
| |
| Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync. |
| |
| Use these entry points: |
| - `/gsd-quick` for small fixes, doc updates, and ad-hoc tasks |
| - `/gsd-debug` for investigation and bug fixing |
| - `/gsd-execute-phase` for planned phase work |
| |
| Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it. |
| <!-- GSD:workflow-end --> |
| |
| |
| |
| <!-- GSD:profile-start --> |
| ## Developer Profile |
| |
| > Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile. |
| > This section is managed by `generate-claude-profile` -- do not edit manually. |
| <!-- GSD:profile-end --> |
| |