User Story: As a user, I want to be able to scroll up to review previous messages while the AI is streaming or adding new content, without being constantly dragged back to the bottom. Implementation: - Replaced position-based threshold detection with user-intent tracking - Detects when user scrolls UP and disables auto-scroll completely - Auto-scroll only re-enables when user manually returns to bottom (<5px) - Uses refs to track scroll position and direction for smooth operation - Works seamlessly during rapid token streaming and tool execution Technical Details: - lastScrollTopRef: Tracks previous scroll position to detect direction - userScrolledUpRef: Flag set when upward scrolling is detected - Direct scrollTop manipulation for instant, non-fighting scroll behavior - Threshold of 5px from absolute bottom to re-enable auto-scroll Spec Updates: - Added comprehensive Smart Auto-Scroll section to UI_UX.md - Documented the problem, solution, requirements, and implementation - Includes code examples and edge case handling Acceptance Criteria Met: ✅ Auto-scroll disabled when scrolling up ✅ Auto-scroll resumes when returning to bottom ✅ Works normally when already at bottom ✅ Smooth detection without flickering ✅ Works during streaming and tool execution Files Changed: - src/components/Chat.tsx: Implemented user-intent tracking - .living_spec/specs/functional/UI_UX.md: Added Smart Auto-Scroll spec - .living_spec/stories/22_smart_autoscroll.md: Marked complete
The Story-Driven Spec Workflow (SDSW)
Target Audience: Large Language Models (LLMs) acting as Senior Engineers. Goal: To maintain long-term project coherence, prevent context window exhaustion, and ensure high-quality, testable code generation in large software projects.
1. The Philosophy
We treat the codebase as the implementation of a "Living Specification." Instead of ephemeral chat prompts ("Fix this", "Add that"), we work through persistent artifacts.
- Stories define the Change.
- Specs define the Truth.
- Code defines the Reality.
The Golden Rule: You are not allowed to write code until the Spec reflects the new reality requested by the Story.
2. Directory Structure
When initializing a new project under this workflow, create the following structure immediately:
project_root/
.living_spec
|-- README.md # This document
├── stories/ # The "Inbox" of feature requests.
├── specs/ # The "Brain" of the project.
│ ├── README.md # Explains this workflow to future sessions.
│ ├── 00_CONTEXT.md # High-level goals, domain definition, and glossary.
│ ├── tech/ # Implementation details (Stack, Architecture, Constraints).
│ │ └── STACK.md # The "Constitution" (Languages, Libs, Patterns).
│ └── functional/ # Domain logic (Platform-agnostic behavior).
│ ├── 01_CORE.md
│ └── ...
└── src/ # The Code.
3. The Cycle (The "Loop")
When the user asks for a feature, follow this 4-step loop strictly:
Step 1: The Story (Ingest)
- User Input: "I want the robot to dance."
- Action: Create a file
stories/XX_robot_dance.md. - Content:
- User Story: "As a user, I want..."
- Acceptance Criteria: Bullet points of observable success.
- Out of scope: Things that are out of scope so that the LLM doesn't go crazy
- Git: The Assistant initiates a new local feature branch (e.g.,
feature/story-name) immediately.
Step 2: The Spec (Digest)
- Action: Update the files in
specs/. - Logic:
- Does
specs/functional/LOCOMOTION.mdexist? If no, create it. - Add the "Dance" state to the state machine definition in the spec.
- Check
specs/tech/STACK.md: Do we have an approved animation library? If no, propose adding one to the Stack or reject the feature.
- Does
- Output: Show the user the diff of the Spec. Wait for approval.
Step 3: The Implementation (Code)
- Action: Write the code to match the Spec (not just the Story).
- Constraint: adhere strictly to
specs/tech/STACK.md(e.g., if it says "Nounwrap()", you must not useunwrap()).
Step 4: Verification (Close)
- Action: Write a test case that maps directly to the Acceptance Criteria in the Story.
- Action: Run compilation and make sure it succeeds without errors. Fix warnings if possible. Run tests and make sure they all pass before proceeding. Ask questions here if needed.
- Action: Ask the user to accept the story. Wait for user acceptance.
- Action: When the user accepts:
- Mark the acceptance criteria as complete (change
[ ]to[x]) - Move the story file to
stories/archive/(e.g.,mv stories/XX_story_name.md stories/archive/) - Commit both changes to the feature branch
- Perform the squash merge:
git merge --squash feature/story-name - Commit to master with a comprehensive commit message
- Delete the feature branch:
git branch -D feature/story-name
- Mark the acceptance criteria as complete (change
- Important: Do NOT mark acceptance criteria as complete before user acceptance. Only mark them complete when the user explicitly accepts the story.
4. Context Reset Protocol
When the LLM context window fills up (or the chat gets slow/confused):
- Stop Coding.
- Instruction: Tell the user to open a new chat.
- Handoff: The only context the new LLM needs is in the
specs/folder.- Prompt for New Session: "I am working on Project X. Read
specs/00_CONTEXT.mdandspecs/tech/STACK.md. Then look atstories/to see what is pending."
- Prompt for New Session: "I am working on Project X. Read
5. Setup Instructions (For the LLM)
If a user hands you this document and says "Apply this process to my project":
- Analyze the Request: Ask for the high-level goal ("What are we building?") and the tech preferences ("Rust or Python?").
- Git Check: Check if the directory is a git repository (
git status). If not, rungit init. - Scaffold: Run commands to create the
specs/andstories/folders. - Draft Context: Write
specs/00_CONTEXT.mdbased on the user's answer. - Draft Stack: Write
specs/tech/STACK.mdbased on best practices for that language. - Wait: Ask the user for "Story #1".
6. Code Quality Tools
MANDATORY: Before completing Step 4 (Verification) of any story, you MUST run all applicable linters and fix ALL errors and warnings. Zero tolerance for warnings or errors.
TypeScript/JavaScript: Biome
- Tool: Biome - Fast formatter and linter
- Check Command:
npx @biomejs/biome check src/ - Fix Command:
npx @biomejs/biome check --write src/ - Unsafe Fixes:
npx @biomejs/biome check --write --unsafe src/ - Configuration:
biome.jsonin project root - When to Run:
- After every code change to TypeScript/React files
- Before committing any frontend changes
- During Step 4 (Verification) - must show 0 errors, 0 warnings
Biome Rules to Follow:
- No
anytypes (use proper TypeScript types orunknown) - No array index as
keyin React (use stable IDs) - No assignments in expressions (extract to separate statements)
- All buttons must have explicit
typeprop (button,submit, orreset) - Mouse events must be accompanied by keyboard events for accessibility
- Use template literals instead of string concatenation
- Import types with
import type { }syntax - Organize imports automatically
Rust: Clippy
- Tool: Clippy - Rust linter
- Check Command:
cargo clippy --all-targets --all-features - Fix Command:
cargo clippy --fix --allow-dirty --allow-staged - When to Run:
- After every code change to Rust files
- Before committing any backend changes
- During Step 4 (Verification) - must show 0 errors, 0 warnings
Clippy Rules to Follow:
- No unused variables (prefix with
_if intentionally unused) - No dead code (remove or mark with
#[allow(dead_code)]if used conditionally) - Use
?operator instead of explicit error handling where possible - Prefer
if letovermatchfor single-pattern matches - Use meaningful variable names
- Follow Rust idioms and best practices
Build Verification Checklist
Before asking for user acceptance in Step 4:
- Run
cargo clippy(Rust) - 0 errors, 0 warnings - Run
cargo check(Rust) - successful compilation - Run
cargo test(Rust) - all tests pass - Run
npx @biomejs/biome check src/(TypeScript) - 0 errors, 0 warnings - Run
npm run build(TypeScript) - successful build - Manually test the feature works as expected
- All acceptance criteria verified
Failure to meet these criteria means the story is NOT ready for acceptance.