Merge branch 'long-consultation-desk'

This commit is contained in:
2026-04-30 10:36:25 +08:00
148 changed files with 2944 additions and 22718 deletions
-122
View File
@@ -1,122 +0,0 @@
---
name: check
description: |
Code quality check expert. Reviews code changes against specs and self-fixes issues.
tools: Read, Write, Edit, Bash, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
model: opus
---
# Check Agent
You are the Check Agent in the Trellis workflow.
## Context
Before checking, read:
- `.trellis/spec/` - Development guidelines
- Pre-commit checklist for quality standards
## Core Responsibilities
1. **Get code changes** - Use git diff to get uncommitted code
2. **Check against specs** - Verify code follows guidelines
3. **Self-fix** - Fix issues yourself, not just report them
4. **Run verification** - typecheck and lint
## Important
**Fix issues yourself**, don't just report them.
You have write and edit tools, you can modify code directly.
---
## Workflow
### Step 1: Get Changes
```bash
git diff --name-only # List changed files
git diff # View specific changes
```
### Step 2: Check Against Specs
Read relevant specs in `.trellis/spec/` to check code:
- Does it follow directory structure conventions
- Does it follow naming conventions
- Does it follow code patterns
- Are there missing types
- Are there potential bugs
### Step 3: Self-Fix
After finding issues:
1. Fix the issue directly (use edit tool)
2. Record what was fixed
3. Continue checking other issues
### Step 4: Run Verification
Run project's lint and typecheck commands to verify changes.
If failed, fix issues and re-run.
---
## Completion Markers (Ralph Loop)
**CRITICAL**: You are in a loop controlled by the Ralph Loop system.
The loop will NOT stop until you output ALL required completion markers.
Completion markers are generated from `check.jsonl` in the task directory.
Each entry's `reason` field becomes a marker: `{REASON}_FINISH`
For example, if check.jsonl contains:
```json
{"file": "...", "reason": "TypeCheck"}
{"file": "...", "reason": "Lint"}
{"file": "...", "reason": "CodeReview"}
```
You MUST output these markers when each check passes:
- `TYPECHECK_FINISH` - After typecheck passes
- `LINT_FINISH` - After lint passes
- `CODEREVIEW_FINISH` - After code review passes
If check.jsonl doesn't exist or has no reasons, output: `ALL_CHECKS_FINISH`
**The loop will block you from stopping until all markers are present in your output.**
---
## Report Format
```markdown
## Self-Check Complete
### Files Checked
- src/components/Feature.tsx
- src/hooks/useFeature.ts
### Issues Found and Fixed
1. `<file>:<line>` - <what was fixed>
2. `<file>:<line>` - <what was fixed>
### Issues Not Fixed
(If there are issues that cannot be self-fixed, list them here with reasons)
### Verification Results
- TypeCheck: Passed TYPECHECK_FINISH
- Lint: Passed LINT_FINISH
### Summary
Checked X files, found Y issues, all fixed.
ALL_CHECKS_FINISH
```
-106
View File
@@ -1,106 +0,0 @@
---
name: debug
description: |
Issue fixing expert. Understands issues, fixes against specs, and verifies fixes. Precise fixes only.
tools: Read, Write, Edit, Bash, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
model: opus
---
# Debug Agent
You are the Debug Agent in the Trellis workflow.
## Context
Before debugging, read:
- `.trellis/spec/` - Development guidelines
- Error messages or issue descriptions provided
## Core Responsibilities
1. **Understand issues** - Analyze error messages or reported issues
2. **Fix against specs** - Fix issues following dev specs
3. **Verify fixes** - Run typecheck to ensure no new issues
4. **Report results** - Report fix status
---
## Workflow
### Step 1: Understand Issues
Parse the issue, categorize by priority:
- `[P1]` - Must fix (blocking)
- `[P2]` - Should fix (important)
- `[P3]` - Optional fix (nice to have)
### Step 2: Research if Needed
If you need additional info:
```bash
# Check knowledge base
ls .trellis/big-question/
```
### Step 3: Fix One by One
For each issue:
1. Locate the exact position
2. Fix following specs
3. Run typecheck to verify
### Step 4: Verify
Run project's lint and typecheck commands to verify fixes.
If fix introduces new issues:
1. Revert the fix
2. Use a more complete solution
3. Re-verify
---
## Report Format
```markdown
## Fix Report
### Issues Fixed
1. `[P1]` `<file>:<line>` - <what was fixed>
2. `[P2]` `<file>:<line>` - <what was fixed>
### Issues Not Fixed
- `<file>:<line>` - <reason why not fixed>
### Verification
- TypeCheck: Pass
- Lint: Pass
### Summary
Fixed X/Y issues. Z issues require discussion.
```
---
## Guidelines
### DO
- Precise fixes for reported issues
- Follow specs
- Verify each fix
### DON'T
- Don't refactor surrounding code
- Don't add new features
- Don't modify unrelated files
- Don't use non-null assertion (`x!` operator)
- Don't execute git commit
-213
View File
@@ -1,213 +0,0 @@
---
name: dispatch
description: |
Multi-Agent Pipeline main dispatcher. Pure dispatcher. Only responsible for calling subagents and scripts in phase order.
tools: Read, Bash, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
model: opus
---
# Dispatch Agent
You are the Dispatch Agent in the Multi-Agent Pipeline (pure dispatcher).
## Working Directory Convention
Current Task is specified by `.trellis/.current-task` file, content is the relative path to task directory.
Task directory path format: `.trellis/tasks/{MM}-{DD}-{name}/`
This directory contains all context files for the current task:
- `task.json` - Task configuration
- `prd.md` - Requirements document
- `info.md` - Technical design (optional)
- `implement.jsonl` - Implement context
- `check.jsonl` - Check context
- `debug.jsonl` - Debug context
## Core Principles
1. **You are a pure dispatcher** - Only responsible for calling subagents and scripts in order
2. **You don't read specs/requirements** - Hook will auto-inject all context to subagents
3. **You don't need resume** - Hook injects complete context on each subagent call
4. **You only need simple commands** - Tell subagent "start working" is enough
---
## Startup Flow
### Step 1: Determine Current Task Directory
Read `.trellis/.current-task` to get current task directory path:
```bash
TASK_DIR=$(cat .trellis/.current-task)
# e.g.: .trellis/tasks/02-03-my-feature
```
### Step 2: Read Task Configuration
```bash
cat ${TASK_DIR}/task.json
```
Get the `next_action` array, which defines the list of phases to execute.
### Step 3: Execute in Phase Order
Execute each step in `phase` order.
> **Note**: You do NOT need to manually update `current_phase`. The Hook automatically updates it when you call Task with a subagent.
---
## Phase Handling
> Hook will auto-inject all specs, requirements, and technical design to subagent context.
> Dispatch only needs to issue simple call commands.
### action: "implement"
```
Task(
subagent_type: "implement",
prompt: "Implement the feature described in prd.md in the task directory",
model: "opus",
run_in_background: true
)
```
Hook will auto-inject:
- All spec files from implement.jsonl
- Requirements document (prd.md)
- Technical design (info.md)
Implement receives complete context and autonomously: read → understand → implement.
### action: "check"
```
Task(
subagent_type: "check",
prompt: "Check code changes, fix issues yourself",
model: "opus",
run_in_background: true
)
```
Hook will auto-inject:
- finish-work.md
- check-cross-layer.md
- check.md
- All spec files from check.jsonl
### action: "debug"
```
Task(
subagent_type: "debug",
prompt: "Fix the issues described in the task context",
model: "opus",
run_in_background: true
)
```
Hook will auto-inject:
- All spec files from debug.jsonl
- Error context if available
### action: "finish"
```
Task(
subagent_type: "check",
prompt: "[finish] Execute final completion check before PR",
model: "opus",
run_in_background: true
)
```
**Important**: The `[finish]` marker in prompt triggers different context injection:
- finish-work.md checklist
- update-spec.md (spec update process and templates)
- prd.md for verifying requirements are met
The finish agent actively updates spec docs when it detects new patterns or contracts in the changes. This is different from regular "check" which has full specs for self-fix loop.
### action: "create-pr"
This action creates a Pull Request from the feature branch. Run it via Bash:
```bash
python3 ./.trellis/scripts/multi_agent/create_pr.py
```
This will:
1. Stage and commit all changes (excluding workspace)
2. Push to origin
3. Create a Draft PR using `gh pr create`
4. Update task.json with status="review", pr_url, and current_phase
**Note**: This is the only action that performs git commit, as it's the final step after all implementation and checks are complete.
---
## Calling Subagents
### Basic Pattern
```
task_id = Task(
subagent_type: "implement", // or "check", "debug"
prompt: "Simple task description",
model: "opus",
run_in_background: true
)
// Poll for completion
for i in 1..N:
result = TaskOutput(task_id, block=true, timeout=300000)
if result.status == "completed":
break
```
### Timeout Settings
| Phase | Max Time | Poll Count |
|-------|----------|------------|
| implement | 30 min | 6 times |
| check | 15 min | 3 times |
| debug | 20 min | 4 times |
---
## Error Handling
### Timeout
If a subagent times out, notify the user and ask for guidance:
```
"Subagent {phase} timed out after {time}. Options:
1. Retry the same phase
2. Skip to next phase
3. Abort the pipeline"
```
### Subagent Failure
If a subagent reports failure, read the output and decide:
- If recoverable: call debug agent to fix
- If not recoverable: notify user and ask for guidance
---
## Key Constraints
1. **Do not read spec/requirement files directly** - Let Hook inject to subagents
2. **Only commit via create-pr action** - Use `multi_agent/create_pr.py` at the end of pipeline
3. **All subagents should use opus model for complex tasks**
4. **Keep dispatch logic simple** - Complex logic belongs in subagents
-95
View File
@@ -1,95 +0,0 @@
---
name: implement
description: |
Code implementation expert. Understands specs and requirements, then implements features. No git commit allowed.
tools: Read, Write, Edit, Bash, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
model: opus
---
# Implement Agent
You are the Implement Agent in the Trellis workflow.
## Context
Before implementing, read:
- `.trellis/workflow.md` - Project workflow
- `.trellis/spec/` - Development guidelines
- Task `prd.md` - Requirements document
- Task `info.md` - Technical design (if exists)
## Core Responsibilities
1. **Understand specs** - Read relevant spec files in `.trellis/spec/`
2. **Understand requirements** - Read prd.md and info.md
3. **Implement features** - Write code following specs and design
4. **Self-check** - Ensure code quality
5. **Report results** - Report completion status
## Forbidden Operations
**Do NOT execute these git commands:**
- `git commit`
- `git push`
- `git merge`
---
## Workflow
### 1. Understand Specs
Read relevant specs based on task type:
- Spec layers: `.trellis/spec/<package>/<layer>/`
- Shared guides: `.trellis/spec/guides/`
### 2. Understand Requirements
Read the task's prd.md and info.md:
- What are the core requirements
- Key points of technical design
- Which files to modify/create
### 3. Implement Features
- Write code following specs and technical design
- Follow existing code patterns
- Only do what's required, no over-engineering
### 4. Verify
Run project's lint and typecheck commands to verify changes.
---
## Report Format
```markdown
## Implementation Complete
### Files Modified
- `src/components/Feature.tsx` - New component
- `src/hooks/useFeature.ts` - New hook
### Implementation Summary
1. Created Feature component...
2. Added useFeature hook...
### Verification Results
- Lint: Passed
- TypeCheck: Passed
```
---
## Code Standards
- Follow existing code patterns
- Don't add unnecessary abstractions
- Only do what's required, no over-engineering
- Keep code readable
-396
View File
@@ -1,396 +0,0 @@
---
name: plan
description: |
Multi-Agent Pipeline planner. Analyzes requirements and produces a fully configured task directory ready for dispatch.
tools: Read, Bash, Glob, Grep, Task
model: opus
---
# Plan Agent
You are the Plan Agent in the Multi-Agent Pipeline.
**Your job**: Evaluate requirements and, if valid, transform them into a fully configured task directory.
**You have the power to reject** - If a requirement is unclear, incomplete, unreasonable, or potentially harmful, you MUST refuse to proceed and clean up.
---
## Step 0: Evaluate Requirement (CRITICAL)
Before doing ANY work, evaluate the requirement:
```
PLAN_REQUIREMENT = <the requirement from environment>
```
### Reject If:
1. **Unclear or Vague**
- "Make it better" / "Fix the bugs" / "Improve performance"
- No specific outcome defined
- Cannot determine what "done" looks like
2. **Incomplete Information**
- Missing critical details to implement
- References unknown systems or files
- Depends on decisions not yet made
3. **Out of Scope for This Project**
- Requirement doesn't match the project's purpose
- Requires changes to external systems
- Not technically feasible with current architecture
4. **Potentially Harmful**
- Security vulnerabilities (intentional backdoors, data exfiltration)
- Destructive operations without clear justification
- Circumventing access controls
5. **Too Large / Should Be Split**
- Multiple unrelated features bundled together
- Would require touching too many systems
- Cannot be completed in a reasonable scope
### If Rejecting:
1. **Update task.json status to "rejected"**:
```bash
jq '.status = "rejected"' "$PLAN_TASK_DIR/task.json" > "$PLAN_TASK_DIR/task.json.tmp" \
&& mv "$PLAN_TASK_DIR/task.json.tmp" "$PLAN_TASK_DIR/task.json"
```
2. **Write rejection reason to a file** (so user can see it):
```bash
cat > "$PLAN_TASK_DIR/REJECTED.md" << 'EOF'
# Plan Rejected
## Reason
<category from above>
## Details
<specific explanation of why this requirement cannot proceed>
## Suggestions
- <what the user should clarify or change>
- <how to make the requirement actionable>
## To Retry
1. Delete this directory:
rm -rf $PLAN_TASK_DIR
2. Run with revised requirement:
python3 ./.trellis/scripts/multi_agent/plan.py --name "<name>" --type "<type>" --requirement "<revised requirement>"
EOF
```
3. **Print summary to stdout** (will be captured in .plan-log):
```
=== PLAN REJECTED ===
Reason: <category>
Details: <brief explanation>
See: $PLAN_TASK_DIR/REJECTED.md
```
4. **Exit immediately** - Do not proceed to Step 1.
**The task directory is kept** with:
- `task.json` (status: "rejected")
- `REJECTED.md` (full explanation)
- `.plan-log` (execution log)
This allows the user to review why it was rejected.
### If Accepting:
Continue to Step 1. The requirement is:
- Clear and specific
- Has a defined outcome
- Is technically feasible
- Is appropriately scoped
---
## Input
You receive input via environment variables (set by plan.py):
```bash
PLAN_TASK_NAME # Task name (e.g., "user-auth")
PLAN_DEV_TYPE # Development type: backend | frontend | fullstack
PLAN_REQUIREMENT # Requirement description from user
PLAN_TASK_DIR # Pre-created task directory path
```
Read them at startup:
```bash
echo "Task: $PLAN_TASK_NAME"
echo "Type: $PLAN_DEV_TYPE"
echo "Requirement: $PLAN_REQUIREMENT"
echo "Directory: $PLAN_TASK_DIR"
```
## Output (if accepted)
A complete task directory containing:
```
${PLAN_TASK_DIR}/
├── task.json # Updated with branch, scope, dev_type
├── prd.md # Requirements document
├── implement.jsonl # Implement phase context
├── check.jsonl # Check phase context
└── debug.jsonl # Debug phase context
```
---
## Workflow (After Acceptance)
### Step 1: Initialize Context Files
```bash
python3 ./.trellis/scripts/task.py init-context "$PLAN_TASK_DIR" "$PLAN_DEV_TYPE"
```
This creates base jsonl files with standard specs for the dev type.
### Step 2: Analyze Codebase with Research Agent
Call research agent to find relevant specs and code patterns:
```
Task(
subagent_type: "research",
prompt: "Analyze what specs and code patterns are needed for this task.
Task: ${PLAN_REQUIREMENT}
Dev Type: ${PLAN_DEV_TYPE}
Instructions:
1. Search .trellis/spec/ for relevant spec files
2. Search the codebase for related modules and patterns
3. Identify files that should be added to jsonl context
Output format (use exactly this format):
## implement.jsonl
- path: <relative file path>, reason: <why needed>
- path: <relative file path>, reason: <why needed>
## check.jsonl
- path: <relative file path>, reason: <why needed>
## debug.jsonl
- path: <relative file path>, reason: <why needed>
## Suggested Scope
<single word for commit scope, e.g., auth, api, ui>
## Technical Notes
<any important technical considerations for prd.md>",
model: "opus"
)
```
### Step 3: Add Context Entries
Parse research agent output and add entries to jsonl files:
```bash
# For each entry in implement.jsonl section:
python3 ./.trellis/scripts/task.py add-context "$PLAN_TASK_DIR" implement "<path>" "<reason>"
# For each entry in check.jsonl section:
python3 ./.trellis/scripts/task.py add-context "$PLAN_TASK_DIR" check "<path>" "<reason>"
# For each entry in debug.jsonl section:
python3 ./.trellis/scripts/task.py add-context "$PLAN_TASK_DIR" debug "<path>" "<reason>"
```
### Step 4: Write prd.md
Create the requirements document:
```bash
cat > "$PLAN_TASK_DIR/prd.md" << 'EOF'
# Task: ${PLAN_TASK_NAME}
## Overview
[Brief description of what this feature does]
## Requirements
- [Requirement 1]
- [Requirement 2]
- ...
## Acceptance Criteria
- [ ] [Criterion 1]
- [ ] [Criterion 2]
- ...
## Technical Notes
[Any technical considerations from research agent]
## Out of Scope
- [What this feature does NOT include]
EOF
```
**Guidelines for prd.md**:
- Be specific and actionable
- Include acceptance criteria that can be verified
- Add technical notes from research agent
- Define what's out of scope to prevent scope creep
### Step 5: Configure Task Metadata
```bash
# Set branch name
python3 ./.trellis/scripts/task.py set-branch "$PLAN_TASK_DIR" "feature/${PLAN_TASK_NAME}"
# Set scope (from research agent suggestion)
python3 ./.trellis/scripts/task.py set-scope "$PLAN_TASK_DIR" "<scope>"
# Update dev_type in task.json
jq --arg type "$PLAN_DEV_TYPE" '.dev_type = $type' \
"$PLAN_TASK_DIR/task.json" > "$PLAN_TASK_DIR/task.json.tmp" \
&& mv "$PLAN_TASK_DIR/task.json.tmp" "$PLAN_TASK_DIR/task.json"
```
### Step 6: Validate Configuration
```bash
python3 ./.trellis/scripts/task.py validate "$PLAN_TASK_DIR"
```
If validation fails, fix the invalid paths and re-validate.
### Step 7: Output Summary
Print a summary for the caller:
```bash
echo "=== Plan Complete ==="
echo "Task Directory: $PLAN_TASK_DIR"
echo ""
echo "Files created:"
ls -la "$PLAN_TASK_DIR"
echo ""
echo "Context summary:"
python3 ./.trellis/scripts/task.py list-context "$PLAN_TASK_DIR"
echo ""
echo "Ready for: python3 ./.trellis/scripts/multi_agent/start.py $PLAN_TASK_DIR"
```
---
## Key Principles
1. **Reject early, reject clearly** - Don't waste time on bad requirements
2. **Research before configure** - Always call research agent to understand the codebase
3. **Validate all paths** - Every file in jsonl must exist
4. **Be specific in prd.md** - Vague requirements lead to wrong implementations
5. **Include acceptance criteria** - Check agent needs to verify something concrete
6. **Set appropriate scope** - This affects commit message format
---
## Error Handling
### Research Agent Returns No Results
If research agent finds no relevant specs:
- Use only the base specs from init-context
- Add a note in prd.md that this is a new area without existing patterns
### Path Not Found
If add-context fails because path doesn't exist:
- Skip that entry
- Log a warning
- Continue with other entries
### Validation Fails
If final validation fails:
- Read the error output
- Remove invalid entries from jsonl files
- Re-validate
---
## Examples
### Example: Accepted Requirement
```
Input:
PLAN_TASK_NAME = "add-rate-limiting"
PLAN_DEV_TYPE = "backend"
PLAN_REQUIREMENT = "Add rate limiting to API endpoints using a sliding window algorithm. Limit to 100 requests per minute per IP. Return 429 status when exceeded."
Result: ACCEPTED - Clear, specific, has defined behavior
Output:
.trellis/tasks/02-03-add-rate-limiting/
├── task.json # branch: feature/add-rate-limiting, scope: api
├── prd.md # Detailed requirements with acceptance criteria
├── implement.jsonl # Backend specs + existing middleware patterns
├── check.jsonl # Quality guidelines + API testing specs
└── debug.jsonl # Error handling specs
```
### Example: Rejected - Vague Requirement
```
Input:
PLAN_REQUIREMENT = "Make the API faster"
Result: REJECTED
=== PLAN REJECTED ===
Reason: Unclear or Vague
Details:
"Make the API faster" does not specify:
- Which endpoints need optimization
- Current performance baseline
- Target performance metrics
- Acceptable trade-offs (memory, complexity)
Suggestions:
- Identify specific slow endpoints with response times
- Define target latency (e.g., "GET /users should respond in <100ms")
- Specify if caching, query optimization, or architecture changes are acceptable
```
### Example: Rejected - Too Large
```
Input:
PLAN_REQUIREMENT = "Add user authentication, authorization, password reset, 2FA, OAuth integration, and audit logging"
Result: REJECTED
=== PLAN REJECTED ===
Reason: Too Large / Should Be Split
Details:
This requirement bundles 6 distinct features that should be implemented separately:
1. User authentication (login/logout)
2. Authorization (roles/permissions)
3. Password reset flow
4. Two-factor authentication
5. OAuth integration
6. Audit logging
Suggestions:
- Start with basic authentication first
- Create separate features for each capability
- Consider dependencies (auth before authz, etc.)
```
-120
View File
@@ -1,120 +0,0 @@
---
name: research
description: |
Code and tech search expert. Pure research, no code modifications. Finds files, patterns, and tech solutions.
tools: Read, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa, Skill, mcp__chrome-devtools__*
model: opus
---
# Research Agent
You are the Research Agent in the Trellis workflow.
## Core Principle
**You do one thing: find and explain information.**
You are a documenter, not a reviewer. Your job is to help get the information needed.
---
## Core Responsibilities
### 1. Internal Search (Project Code)
| Search Type | Goal | Tools |
|-------------|------|-------|
| **WHERE** | Locate files/components | Glob, Grep |
| **HOW** | Understand code logic | Read, Grep |
| **PATTERN** | Discover existing patterns | Grep, Read |
### 2. External Search (Tech Solutions)
Use web search for best practices and code examples.
---
## Strict Boundaries
### Only Allowed
- Describe **what exists**
- Describe **where it is**
- Describe **how it works**
- Describe **how components interact**
### Forbidden (unless explicitly asked)
- Suggest improvements
- Criticize implementation
- Recommend refactoring
- Modify any files
- Execute git commands
---
## Workflow
### Step 1: Understand Search Request
Analyze the query, determine:
- Search type (internal/external/mixed)
- Search scope (global/specific directory)
- Expected output (file list/code patterns/tech solutions)
### Step 2: Execute Search
Execute multiple independent searches in parallel for efficiency.
### Step 3: Organize Results
Output structured results in report format.
---
## Report Format
```markdown
## Search Results
### Query
{original query}
### Files Found
| File Path | Description |
|-----------|-------------|
| `src/services/xxx.ts` | Main implementation |
| `src/types/xxx.ts` | Type definitions |
### Code Pattern Analysis
{Describe discovered patterns, cite specific files and line numbers}
### Related Spec Documents
- `.trellis/spec/xxx.md` - {description}
### Not Found
{If some content was not found, explain}
```
---
## Guidelines
### DO
- Provide specific file paths and line numbers
- Quote actual code snippets
- Distinguish "definitely found" and "possibly related"
- Explain search scope and limitations
### DON'T
- Don't guess uncertain info
- Don't omit important search results
- Don't add improvement suggestions in report (unless explicitly asked)
- Don't modify any files
-29
View File
@@ -1,29 +0,0 @@
Read the relevant development guidelines before starting your task.
Execute these steps:
1. **Discover packages and their spec layers**:
```bash
python3 ./.trellis/scripts/get_context.py --mode packages
```
2. **Identify which specs apply** to your task based on:
- Which package you're modifying (e.g., `cli/`, `docs-site/`)
- What type of work (backend, frontend, unit-test, docs, etc.)
3. **Read the spec index** for each relevant module:
```bash
cat .trellis/spec/<package>/<layer>/index.md
```
Follow the **"Pre-Development Checklist"** section in the index.
4. **Read the specific guideline files** listed in the Pre-Development Checklist that are relevant to your task. The index is NOT the goal — it points you to the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`). Read those files to understand the coding standards and patterns.
5. **Always read shared guides**:
```bash
cat .trellis/spec/guides/index.md
```
6. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
This step is **mandatory** before writing any code.
-487
View File
@@ -1,487 +0,0 @@
# Brainstorm - Requirements Discovery (AI Coding Enhanced)
Guide AI through collaborative requirements discovery **before implementation**, optimized for AI coding workflows:
* **Task-first** (capture ideas immediately)
* **Action-before-asking** (reduce low-value questions)
* **Research-first** for technical choices (avoid asking users to invent options)
* **Diverge → Converge** (expand thinking, then lock MVP)
---
## When to Use
Triggered from `/trellis:start` when the user describes a development task, especially when:
* requirements are unclear or evolving
* there are multiple valid implementation paths
* trade-offs matter (UX, reliability, maintainability, cost, performance)
* the user might not know the best options up front
---
## Core Principles (Non-negotiable)
1. **Task-first (capture early)**
Always ensure a task exists at the start so the user's ideas are recorded immediately.
2. **Action before asking**
If you can derive the answer from repo code, docs, configs, conventions, or quick research — do that first.
3. **One question per message**
Never overwhelm the user with a list of questions. Ask one, update PRD, repeat.
4. **Prefer concrete options**
For preference/decision questions, present 23 feasible, specific approaches with trade-offs.
5. **Research-first for technical choices**
If the decision depends on industry conventions / similar tools / established patterns, do research first, then propose options.
6. **Diverge → Converge**
After initial understanding, proactively consider future evolution, related scenarios, and failure/edge cases — then converge to an MVP with explicit out-of-scope.
7. **No meta questions**
Do not ask "should I search?" or "can you paste the code so I can continue?"
If you need information: search/inspect. If blocked: ask the minimal blocking question.
---
## Step 0: Ensure Task Exists (ALWAYS)
Before any Q&A, ensure a task exists. If none exists, create one immediately.
* Use a **temporary working title** derived from the user's message.
* It's OK if the title is imperfect — refine later in PRD.
```bash
TASK_DIR=$(python3 ./.trellis/scripts/task.py create "brainstorm: <short goal>" --slug <auto>)
```
Create/seed `prd.md` immediately with what you know:
```markdown
# brainstorm: <short goal>
## Goal
<one paragraph: what + why>
## What I already know
* <facts from user message>
* <facts discovered from repo/docs>
## Assumptions (temporary)
* <assumptions to validate>
## Open Questions
* <ONLY Blocking / Preference questions; keep list short>
## Requirements (evolving)
* <start with what is known>
## Acceptance Criteria (evolving)
* [ ] <testable criterion>
## Definition of Done (team quality bar)
* Tests added/updated (unit/integration where appropriate)
* Lint / typecheck / CI green
* Docs/notes updated if behavior changes
* Rollout/rollback considered if risky
## Out of Scope (explicit)
* <what we will not do in this task>
## Technical Notes
* <files inspected, constraints, links, references>
* <research notes summary if applicable>
```
---
## Step 1: Auto-Context (DO THIS BEFORE ASKING QUESTIONS)
Before asking questions like "what does the code look like?", gather context yourself:
### Repo inspection checklist
* Identify likely modules/files impacted
* Locate existing patterns (similar features, conventions, error handling style)
* Check configs, scripts, existing command definitions
* Note any constraints (runtime, dependency policy, build tooling)
### Documentation checklist
* Look for existing PRDs/specs/templates
* Look for command usage examples, README, ADRs if any
Write findings into PRD:
* Add to `What I already know`
* Add constraints/links to `Technical Notes`
---
## Step 2: Classify Complexity (still useful, not gating task creation)
| Complexity | Criteria | Action |
| ------------ | ------------------------------------------------------ | ------------------------------------------- |
| **Trivial** | Single-line fix, typo, obvious change | Skip brainstorm, implement directly |
| **Simple** | Clear goal, 12 files, scope well-defined | Ask 1 confirm question, then implement |
| **Moderate** | Multiple files, some ambiguity | Light brainstorm (23 high-value questions) |
| **Complex** | Vague goal, architectural choices, multiple approaches | Full brainstorm |
> Note: Task already exists from Step 0. Classification only affects depth of brainstorming.
---
## Step 3: Question Gate (Ask ONLY high-value questions)
Before asking ANY question, run the following gate:
### Gate A — Can I derive this without the user?
If answer is available via:
* repo inspection (code/config)
* docs/specs/conventions
* quick market/OSS research
**Do not ask.** Fetch it, summarize, update PRD.
### Gate B — Is this a meta/lazy question?
Examples:
* "Should I search?"
* "Can you paste the code so I can proceed?"
* "What does the code look like?" (when repo is available)
**Do not ask.** Take action.
### Gate C — What type of question is it?
* **Blocking**: cannot proceed without user input
* **Preference**: multiple valid choices, depends on product/UX/risk preference
* **Derivable**: should be answered by inspection/research
→ Only ask **Blocking** or **Preference**.
---
## Step 4: Research-first Mode (Mandatory for technical choices)
### Trigger conditions (any → research-first)
* The task involves selecting an approach, library, protocol, framework, template system, plugin mechanism, or CLI UX convention
* The user asks for "best practice", "how others do it", "recommendation"
* The user can't reasonably enumerate options
### Research steps
1. Identify 24 comparable tools/patterns
2. Summarize common conventions and why they exist
3. Map conventions onto our repo constraints
4. Produce **23 feasible approaches** for our project
### Research output format (PRD)
Add a section in PRD (either within Technical Notes or as its own):
```markdown
## Research Notes
### What similar tools do
* ...
* ...
### Constraints from our repo/project
* ...
### Feasible approaches here
**Approach A: <name>** (Recommended)
* How it works:
* Pros:
* Cons:
**Approach B: <name>**
* How it works:
* Pros:
* Cons:
**Approach C: <name>** (optional)
* ...
```
Then ask **one** preference question:
* "Which approach do you prefer: A / B / C (or other)?"
---
## Step 5: Expansion Sweep (DIVERGE) — Required after initial understanding
After you can summarize the goal, proactively broaden thinking before converging.
### Expansion categories (keep to 12 bullets each)
1. **Future evolution**
* What might this feature become in 13 months?
* What extension points are worth preserving now?
2. **Related scenarios**
* What adjacent commands/flows should remain consistent with this?
* Are there parity expectations (create vs update, import vs export, etc.)?
3. **Failure & edge cases**
* Conflicts, offline/network failure, retries, idempotency, compatibility, rollback
* Input validation, security boundaries, permission checks
### Expansion message template (to user)
```markdown
I understand you want to implement: <current goal>.
Before diving into design, let me quickly diverge to consider three categories (to avoid rework later):
1. Future evolution: <12 bullets>
2. Related scenarios: <12 bullets>
3. Failure/edge cases: <12 bullets>
For this MVP, which would you like to include (or none)?
1. Current requirement only (minimal viable)
2. Add <X> (reserve for future extension)
3. Add <Y> (improve robustness/consistency)
4. Other: describe your preference
```
Then update PRD:
* What's in MVP → `Requirements`
* What's excluded → `Out of Scope`
---
## Step 6: Q&A Loop (CONVERGE)
### Rules
* One question per message
* Prefer multiple-choice when possible
* After each user answer:
* Update PRD immediately
* Move answered items from `Open Questions``Requirements`
* Update `Acceptance Criteria` with testable checkboxes
* Clarify `Out of Scope`
### Question priority (recommended)
1. **MVP scope boundary** (what is included/excluded)
2. **Preference decisions** (after presenting concrete options)
3. **Failure/edge behavior** (only for MVP-critical paths)
4. **Success metrics & Acceptance Criteria** (what proves it works)
### Preferred question format (multiple choice)
```markdown
For <topic>, which approach do you prefer?
1. **Option A** — <what it means + trade-off>
2. **Option B** — <what it means + trade-off>
3. **Option C** — <what it means + trade-off>
4. **Other** — describe your preference
```
---
## Step 7: Propose Approaches + Record Decisions (Complex tasks)
After requirements are clear enough, propose 23 approaches (if not already done via research-first):
```markdown
Based on current information, here are 23 feasible approaches:
**Approach A: <name>** (Recommended)
* How:
* Pros:
* Cons:
**Approach B: <name>**
* How:
* Pros:
* Cons:
Which direction do you prefer?
```
Record the outcome in PRD as an ADR-lite section:
```markdown
## Decision (ADR-lite)
**Context**: Why this decision was needed
**Decision**: Which approach was chosen
**Consequences**: Trade-offs, risks, potential future improvements
```
---
## Step 8: Final Confirmation + Implementation Plan
When open questions are resolved, confirm complete requirements with a structured summary:
### Final confirmation format
```markdown
Here's my understanding of the complete requirements:
**Goal**: <one sentence>
**Requirements**:
* ...
* ...
**Acceptance Criteria**:
* [ ] ...
* [ ] ...
**Definition of Done**:
* ...
**Out of Scope**:
* ...
**Technical Approach**:
<brief summary + key decisions>
**Implementation Plan (small PRs)**:
* PR1: <scaffolding + tests + minimal plumbing>
* PR2: <core behavior>
* PR3: <edge cases + docs + cleanup>
Does this look correct? If yes, I'll proceed with implementation.
```
### Subtask Decomposition (Complex Tasks)
For complex tasks with multiple independent work items, create subtasks:
```bash
# Create child tasks
CHILD1=$(python3 ./.trellis/scripts/task.py create "Child task 1" --slug child1 --parent "$TASK_DIR")
CHILD2=$(python3 ./.trellis/scripts/task.py create "Child task 2" --slug child2 --parent "$TASK_DIR")
# Or link existing tasks
python3 ./.trellis/scripts/task.py add-subtask "$TASK_DIR" "$CHILD_DIR"
```
---
## PRD Target Structure (final)
`prd.md` should converge to:
```markdown
# <Task Title>
## Goal
<why + what>
## Requirements
* ...
## Acceptance Criteria
* [ ] ...
## Definition of Done
* ...
## Technical Approach
<key design + decisions>
## Decision (ADR-lite)
Context / Decision / Consequences
## Out of Scope
* ...
## Technical Notes
<constraints, references, files, research notes>
```
---
## Anti-Patterns (Hard Avoid)
* Asking user for code/context that can be derived from repo
* Asking user to choose an approach before presenting concrete options
* Meta questions about whether to research
* Staying narrowly on the initial request without considering evolution/edges
* Letting brainstorming drift without updating PRD
---
## Integration with Start Workflow
After brainstorm completes (Step 8 confirmation approved), the flow continues to the Task Workflow's **Phase 2: Prepare for Implementation**:
```text
Brainstorm
Step 0: Create task directory + seed PRD
Step 17: Discover requirements, research, converge
Step 8: Final confirmation → user approves
Task Workflow Phase 2 (Prepare for Implementation)
Code-Spec Depth Check (if applicable)
→ Research codebase (based on confirmed PRD)
→ Configure code-spec context (jsonl files)
→ Activate task
Task Workflow Phase 3 (Execute)
Implement → Check → Complete
```
The task directory and PRD already exist from brainstorm, so Phase 1 of the Task Workflow is skipped entirely.
---
## Related Commands
| Command | When to Use |
|---------|-------------|
| `/trellis:start` | Entry point that triggers brainstorm |
| `/trellis:finish-work` | After implementation is complete |
| `/trellis:update-spec` | If new patterns emerge during work |
-125
View File
@@ -1,125 +0,0 @@
# Break the Loop - Deep Bug Analysis
When debug is complete, use this command for deep analysis to break the "fix bug -> forget -> repeat" cycle.
---
## Analysis Framework
Analyze the bug you just fixed from these 5 dimensions:
### 1. Root Cause Category
Which category does this bug belong to?
| Category | Characteristics | Example |
|----------|-----------------|---------|
| **A. Missing Spec** | No documentation on how to do it | New feature without checklist |
| **B. Cross-Layer Contract** | Interface between layers unclear | API returns different format than expected |
| **C. Change Propagation Failure** | Changed one place, missed others | Changed function signature, missed call sites |
| **D. Test Coverage Gap** | Unit test passes, integration fails | Works alone, breaks when combined |
| **E. Implicit Assumption** | Code relies on undocumented assumption | Timestamp seconds vs milliseconds |
### 2. Why Fixes Failed (if applicable)
If you tried multiple fixes before succeeding, analyze each failure:
- **Surface Fix**: Fixed symptom, not root cause
- **Incomplete Scope**: Found root cause, didn't cover all cases
- **Tool Limitation**: grep missed it, type check wasn't strict
- **Mental Model**: Kept looking in same layer, didn't think cross-layer
### 3. Prevention Mechanisms
What mechanisms would prevent this from happening again?
| Type | Description | Example |
|------|-------------|---------|
| **Documentation** | Write it down so people know | Update thinking guide |
| **Architecture** | Make the error impossible structurally | Type-safe wrappers |
| **Compile-time** | TypeScript strict, no any | Signature change causes compile error |
| **Runtime** | Monitoring, alerts, scans | Detect orphan entities |
| **Test Coverage** | E2E tests, integration tests | Verify full flow |
| **Code Review** | Checklist, PR template | "Did you check X?" |
### 4. Systematic Expansion
What broader problems does this bug reveal?
- **Similar Issues**: Where else might this problem exist?
- **Design Flaw**: Is there a fundamental architecture issue?
- **Process Flaw**: Is there a development process improvement?
- **Knowledge Gap**: Is the team missing some understanding?
### 5. Knowledge Capture
Solidify insights into the system:
- [ ] Update `.trellis/spec/guides/` thinking guides
- [ ] Update `.trellis/spec/backend/` or `frontend/` docs
- [ ] Create issue record (if applicable)
- [ ] Create feature ticket for root fix
- [ ] Update check commands if needed
---
## Output Format
Please output analysis in this format:
```markdown
## Bug Analysis: [Short Description]
### 1. Root Cause Category
- **Category**: [A/B/C/D/E] - [Category Name]
- **Specific Cause**: [Detailed description]
### 2. Why Fixes Failed (if applicable)
1. [First attempt]: [Why it failed]
2. [Second attempt]: [Why it failed]
...
### 3. Prevention Mechanisms
| Priority | Mechanism | Specific Action | Status |
|----------|-----------|-----------------|--------|
| P0 | ... | ... | TODO/DONE |
### 4. Systematic Expansion
- **Similar Issues**: [List places with similar problems]
- **Design Improvement**: [Architecture-level suggestions]
- **Process Improvement**: [Development process suggestions]
### 5. Knowledge Capture
- [ ] [Documents to update / tickets to create]
```
---
## Core Philosophy
> **The value of debugging is not in fixing the bug, but in making this class of bugs never happen again.**
Three levels of insight:
1. **Tactical**: How to fix THIS bug
2. **Strategic**: How to prevent THIS CLASS of bugs
3. **Philosophical**: How to expand thinking patterns
30 minutes of analysis saves 30 hours of future debugging.
---
## After Analysis: Immediate Actions
**IMPORTANT**: After completing the analysis above, you MUST immediately:
1. **Update spec/guides** - Don't just list TODOs, actually update the relevant files:
- If it's a cross-platform issue → update `cross-platform-thinking-guide.md`
- If it's a cross-layer issue → update `cross-layer-thinking-guide.md`
- If it's a code reuse issue → update `code-reuse-thinking-guide.md`
- If it's domain-specific → update `backend/*.md` or `frontend/*.md`
2. **Sync templates** - After updating `.trellis/spec/`, sync to `src/templates/markdown/spec/`
3. **Commit the spec updates** - This is the primary output, not just the analysis text
> **The analysis is worthless if it stays in chat. The value is in the updated specs.**
@@ -1,153 +0,0 @@
# Cross-Layer Check
Check if your changes considered all dimensions. Most bugs come from "didn't think of it", not lack of technical skill.
> **Note**: This is a **post-implementation** safety net. Ideally, read the [Pre-Implementation Checklist](.trellis/spec/guides/pre-implementation-checklist.md) **before** writing code.
---
## Related Documents
| Document | Purpose | Timing |
|----------|---------|--------|
| [Pre-Implementation Checklist](.trellis/spec/guides/pre-implementation-checklist.md) | Questions before coding | **Before** writing code |
| [Code Reuse Thinking Guide](.trellis/spec/guides/code-reuse-thinking-guide.md) | Pattern recognition | During implementation |
| **`/trellis:check-cross-layer`** (this) | Verification check | **After** implementation |
---
## Execution Steps
### 1. Identify Change Scope
```bash
git status
git diff --name-only
```
### 2. Select Applicable Check Dimensions
Based on your change type, execute relevant checks below:
---
## Dimension A: Cross-Layer Data Flow (Required when 3+ layers)
**Trigger**: Changes involve 3 or more layers
| Layer | Common Locations |
|-------|------------------|
| API/Routes | `routes/`, `api/`, `handlers/`, `controllers/` |
| Service/Business Logic | `services/`, `lib/`, `core/`, `domain/` |
| Database/Storage | `db/`, `models/`, `repositories/`, `schema/` |
| UI/Presentation | `components/`, `views/`, `templates/`, `pages/` |
| Utility | `utils/`, `helpers/`, `common/` |
**Checklist**:
- [ ] Read flow: Database -> Service -> API -> UI
- [ ] Write flow: UI -> API -> Service -> Database
- [ ] Types/schemas correctly passed between layers?
- [ ] Errors properly propagated to caller?
- [ ] Loading/pending states handled at each layer?
**Detailed Guide**: `.trellis/spec/guides/cross-layer-thinking-guide.md`
---
## Dimension B: Code Reuse (Required when modifying constants/config)
**Trigger**:
- Modifying UI constants (label, icon, color)
- Modifying any hardcoded value
- Seeing similar code in multiple places
- Creating a new utility/helper function
- Just finished batch modifications across files
**Checklist**:
- [ ] Search first: How many places define this value?
```bash
# Search in source files (adjust extensions for your project)
grep -r "value-to-change" src/
```
- [ ] If 2+ places define same value -> Should extract to shared constant
- [ ] After modification, all usage sites updated?
- [ ] If creating utility: Does similar utility already exist?
**Detailed Guide**: `.trellis/spec/guides/code-reuse-thinking-guide.md`
---
## Dimension B2: New Utility Functions
**Trigger**: About to create a new utility/helper function
**Checklist**:
- [ ] Search for existing similar utilities first
```bash
grep -r "functionNamePattern" src/
```
- [ ] If similar exists, can you extend it instead?
- [ ] If creating new, is it in the right location (shared vs domain-specific)?
---
## Dimension B3: After Batch Modifications
**Trigger**: Just modified similar patterns in multiple files
**Checklist**:
- [ ] Did you check ALL files with similar patterns?
```bash
grep -r "patternYouChanged" src/
```
- [ ] Any files missed that should also be updated?
- [ ] Should this pattern be abstracted to prevent future duplication?
---
## Dimension C: Import/Dependency Paths (Required when creating new files)
**Trigger**: Creating new source files
**Checklist**:
- [ ] Using correct import paths (relative vs absolute)?
- [ ] No circular dependencies?
- [ ] Consistent with project's module organization?
---
## Dimension D: Same-Layer Consistency
**Trigger**:
- Modifying display logic or formatting
- Same domain concept used in multiple places
**Checklist**:
- [ ] Search for other places using same concept
```bash
grep -r "ConceptName" src/
```
- [ ] Are these usages consistent?
- [ ] Should they share configuration/constants?
---
## Common Issues Quick Reference
| Issue | Root Cause | Prevention |
|-------|------------|------------|
| Changed one place, missed others | Didn't search impact scope | `grep` before changing |
| Data lost at some layer | Didn't check data flow | Trace data source to destination |
| Type/schema mismatch | Cross-layer types inconsistent | Use shared type definitions |
| UI/output inconsistent | Same concept in multiple places | Extract shared constants |
| Similar utility exists | Didn't search first | Search before creating |
| Batch fix incomplete | Didn't verify all occurrences | grep after fixing |
---
## Output
Report:
1. Which dimensions your changes involve
2. Check results for each dimension
3. Issues found and fix suggestions
-25
View File
@@ -1,25 +0,0 @@
Check if the code you just wrote follows the development guidelines.
Execute these steps:
1. **Identify changed files**:
```bash
git diff --name-only HEAD
```
2. **Determine which spec modules apply** based on the changed file paths:
```bash
python3 ./.trellis/scripts/get_context.py --mode packages
```
3. **Read the spec index** for each relevant module:
```bash
cat .trellis/spec/<package>/<layer>/index.md
```
Follow the **"Quality Check"** section in the index.
4. **Read the specific guideline files** referenced in the Quality Check section (e.g., `quality-guidelines.md`, `conventions.md`). The index is NOT the goal — it points you to the actual guideline files. Read those files and review your code against them.
5. **Run lint and typecheck** for the affected package.
6. **Report any violations** and fix them if found.
-154
View File
@@ -1,154 +0,0 @@
# Create New Slash Command
Create a new slash command in both `.cursor/commands/` (with `trellis-` prefix) and `.claude/commands/trellis/` directories based on user requirements.
## Usage
```
/trellis:create-command <command-name> <description>
```
**Example**:
```
/trellis:create-command review-pr Check PR code changes against project guidelines
```
## Execution Steps
### 1. Parse Input
Extract from user input:
- **Command name**: Use kebab-case (e.g., `review-pr`)
- **Description**: What the command should accomplish
### 2. Analyze Requirements
Determine command type based on description:
- **Initialization**: Read docs, establish context
- **Pre-development**: Read guidelines, check dependencies
- **Code check**: Validate code quality and guideline compliance
- **Recording**: Record progress, questions, structure changes
- **Generation**: Generate docs, code templates
### 3. Generate Command Content
Based on command type, generate appropriate content:
**Simple command** (1-3 lines):
```markdown
Concise instruction describing what to do
```
**Complex command** (with steps):
```markdown
# Command Title
Command description
## Steps
### 1. First Step
Specific action
### 2. Second Step
Specific action
## Output Format (if needed)
Template
```
### 4. Create Files
Create in both directories:
- `.cursor/commands/trellis-<command-name>.md`
- `.claude/commands/trellis/<command-name>.md`
### 5. Confirm Creation
Output result:
```
[OK] Created Slash Command: /<command-name>
File paths:
- .cursor/commands/trellis-<command-name>.md
- .claude/commands/trellis/<command-name>.md
Usage:
/trellis:<command-name>
Description:
<description>
```
## Command Content Guidelines
### [OK] Good command content
1. **Clear and concise**: Immediately understandable
2. **Executable**: AI can follow steps directly
3. **Well-scoped**: Clear boundaries of what to do and not do
4. **Has output**: Specifies expected output format (if needed)
### [X] Avoid
1. **Too vague**: e.g., "optimize code"
2. **Too complex**: Single command should not exceed 100 lines
3. **Duplicate functionality**: Check if similar command exists first
## Naming Conventions
| Command Type | Prefix | Example |
|--------------|--------|---------|
| Session Start | `start` | `start` |
| Pre-development | `before-` | `before-dev` |
| Check | `check-` | `check` |
| Record | `record-` | `record-session` |
| Generate | `generate-` | `generate-api-doc` |
| Update | `update-` | `update-changelog` |
| Other | Verb-first | `review-code`, `sync-data` |
## Example
### Input
```
/trellis:create-command review-pr Check PR code changes against project guidelines
```
### Generated Command Content
```markdown
# PR Code Review
Check current PR code changes against project guidelines.
## Steps
### 1. Get Changed Files
```bash
git diff main...HEAD --name-only
```
### 2. Categorized Review
**Frontend files** (`apps/web/`):
- Reference `.trellis/spec/frontend/index.md`
**Backend files** (`packages/api/`):
- Reference `.trellis/spec/backend/index.md`
### 3. Output Review Report
Format:
## PR Review Report
### Changed Files
- [file list]
### Check Results
- [OK] Passed items
- [X] Issues found
### Suggestions
- [improvement suggestions]
```
-153
View File
@@ -1,153 +0,0 @@
# Finish Work - Pre-Commit Checklist
Before submitting or committing, use this checklist to ensure work completeness.
**Timing**: After code is written and tested, before commit
---
## Checklist
### 1. Code Quality
```bash
# Must pass
pnpm lint
pnpm type-check
pnpm test
```
- [ ] `pnpm lint` passes with 0 errors?
- [ ] `pnpm type-check` passes with no type errors?
- [ ] Tests pass?
- [ ] No `console.log` statements (use logger)?
- [ ] No non-null assertions (the `x!` operator)?
- [ ] No `any` types?
### 1.5. Test Coverage
Check if your change needs new or updated tests (see `.trellis/spec/unit-test/conventions.md`):
- [ ] New pure function → unit test added?
- [ ] Bug fix → regression test added in `test/regression.test.ts`?
- [ ] Changed init/update behavior → integration test added/updated?
- [ ] No logic change (text/data only) → no test needed
### 2. Code-Spec Sync
**Code-Spec Docs**:
- [ ] Does `.trellis/spec/backend/` need updates?
- New patterns, new modules, new conventions
- [ ] Does `.trellis/spec/frontend/` need updates?
- New components, new hooks, new patterns
- [ ] Does `.trellis/spec/guides/` need updates?
- New cross-layer flows, lessons from bugs
**Key Question**:
> "If I fixed a bug or discovered something non-obvious, should I document it so future me (or others) won't hit the same issue?"
If YES -> Update the relevant code-spec doc.
### 2.5. Code-Spec Hard Block (Infra/Cross-Layer)
If this change touches infra or cross-layer contracts, this is a blocking checklist:
- [ ] Spec content is executable (real signatures/contracts), not principle-only text
- [ ] Includes file path + command/API name + payload field names
- [ ] Includes validation and error matrix
- [ ] Includes Good/Base/Bad cases
- [ ] Includes required tests and assertion points
**Block Rule**:
In pipeline mode, the finish agent will automatically detect and execute spec updates when gaps are found.
If running this checklist manually, ensure spec sync is complete before committing — run `/trellis:update-spec` if needed.
### 3. API Changes
If you modified API endpoints:
- [ ] Input schema updated?
- [ ] Output schema updated?
- [ ] API documentation updated?
- [ ] Client code updated to match?
### 4. Database Changes
If you modified database schema:
- [ ] Migration file created?
- [ ] Schema file updated?
- [ ] Related queries updated?
- [ ] Seed data updated (if applicable)?
### 5. Cross-Layer Verification
If the change spans multiple layers:
- [ ] Data flows correctly through all layers?
- [ ] Error handling works at each boundary?
- [ ] Types are consistent across layers?
- [ ] Loading states handled?
### 6. Manual Testing
- [ ] Feature works in browser/app?
- [ ] Edge cases tested?
- [ ] Error states tested?
- [ ] Works after page refresh?
---
## Quick Check Flow
```bash
# 1. Code checks
pnpm lint && pnpm type-check
# 2. View changes
git status
git diff --name-only
# 3. Based on changed files, check relevant items above
```
---
## Common Oversights
| Oversight | Consequence | Check |
|-----------|-------------|-------|
| Code-spec docs not updated | Others don't know the change | Check .trellis/spec/ |
| Spec text is abstract only | Easy regressions in infra/cross-layer changes | Require signature/contract/matrix/cases/tests |
| Migration not created | Schema out of sync | Check db/migrations/ |
| Types not synced | Runtime errors | Check shared types |
| Tests not updated | False confidence | Run full test suite |
| Console.log left in | Noisy production logs | Search for console.log |
---
## Relationship to Other Commands
```
Development Flow:
Write code -> Test -> /trellis:finish-work -> git commit -> /trellis:record-session
| |
Ensure completeness Record progress
Debug Flow:
Hit bug -> Fix -> /trellis:break-loop -> Knowledge capture
|
Deep analysis
```
- `/trellis:finish-work` - Check work completeness (this command)
- `/trellis:record-session` - Record session and commits
- `/trellis:break-loop` - Deep analysis after debugging
---
## Core Principle
> **Delivery includes not just code, but also documentation, verification, and knowledge capture.**
Complete work = Code + Docs + Tests + Verification
-219
View File
@@ -1,219 +0,0 @@
# Integrate Claude Skill into Project Guidelines
Adapt and integrate a Claude global skill into your project's development guidelines (not directly into project code).
## Usage
```
/trellis:integrate-skill <skill-name>
```
**Examples**:
```
/trellis:integrate-skill frontend-design
/trellis:integrate-skill mcp-builder
```
## Core Principle
> [!] **Important**: The goal of skill integration is to update **development guidelines**, not to generate project code directly.
>
> - Guidelines content -> Write to `.trellis/spec/{target}/doc.md`
> - Code examples -> Place in `.trellis/spec/{target}/examples/skills/<skill-name>/`
> - Example files -> Use `.template` suffix (e.g., `component.tsx.template`) to avoid IDE errors
>
> Where `{target}` is `frontend` or `backend`, determined by skill type.
## Execution Steps
### 1. Read Skill Content
```bash
openskills read <skill-name>
```
If the skill doesn't exist, prompt user to check available skills:
```bash
# Available skills are listed in AGENTS.md under <available_skills>
```
### 2. Determine Integration Target
Based on skill type, determine which guidelines to update:
| Skill Category | Integration Target |
|----------------|-------------------|
| UI/Frontend (`frontend-design`, `web-artifacts-builder`) | `.trellis/spec/frontend/` |
| Backend/API (`mcp-builder`) | `.trellis/spec/backend/` |
| Documentation (`doc-coauthoring`, `docx`, `pdf`) | `.trellis/` or create dedicated guidelines |
| Testing (`webapp-testing`) | `.trellis/spec/frontend/` (E2E) |
### 3. Analyze Skill Content
Extract from the skill:
- **Core concepts**: How the skill works and key concepts
- **Best practices**: Recommended approaches
- **Code patterns**: Reusable code templates
- **Caveats**: Common issues and solutions
### 4. Execute Integration
#### 4.1 Update Guidelines Document
Add a new section to the corresponding `doc.md`:
```markdown
@@@section:skill-<skill-name>
## # <Skill Name> Integration Guide
### Overview
[Core functionality and use cases of the skill]
### Project Adaptation
[How to use this skill in the current project]
### Usage Steps
1. [Step 1]
2. [Step 2]
### Caveats
- [Project-specific constraints]
- [Differences from default behavior]
### Reference Examples
See `examples/skills/<skill-name>/`
@@@/section:skill-<skill-name>
```
#### 4.2 Create Examples Directory (if code examples exist)
```bash
# Directory structure ({target} = frontend or backend)
.trellis/spec/{target}/
|-- doc.md # Add skill-related section
|-- index.md # Update index
+-- examples/
+-- skills/
+-- <skill-name>/
|-- README.md # Example documentation
|-- example-1.ts.template # Code example (use .template suffix)
+-- example-2.tsx.template
```
**File naming conventions**:
- Code files: `<name>.<ext>.template` (e.g., `component.tsx.template`)
- Config files: `<name>.config.template` (e.g., `tailwind.config.template`)
- Documentation: `README.md` (normal suffix)
#### 4.3 Update Index File
Add to the Quick Navigation table in `index.md`:
```markdown
| <Skill-related task> | <Section name> | `skill-<skill-name>` |
```
### 5. Generate Integration Report
---
## Skill Integration Report: `<skill-name>`
### # Overview
- **Skill description**: [Functionality description]
- **Integration target**: `.trellis/spec/{target}/`
### # Tech Stack Compatibility
| Skill Requirement | Project Status | Compatibility |
|-------------------|----------------|---------------|
| [Tech 1] | [Project tech] | [OK]/[!]/[X] |
### # Integration Locations
| Type | Path |
|------|------|
| Guidelines doc | `.trellis/spec/{target}/doc.md` (section: `skill-<name>`) |
| Code examples | `.trellis/spec/{target}/examples/skills/<name>/` |
| Index update | `.trellis/spec/{target}/index.md` |
> `{target}` = `frontend` or `backend`
### # Dependencies (if needed)
```bash
# Install required dependencies (adjust for your package manager)
npm install <package>
# or
pnpm add <package>
# or
yarn add <package>
```
### [OK] Completed Changes
- [ ] Added `@@@section:skill-<name>` section to `doc.md`
- [ ] Added index entry to `index.md`
- [ ] Created example files in `examples/skills/<name>/`
- [ ] Example files use `.template` suffix
### # Related Guidelines
- [Existing related section IDs]
---
## 6. Optional: Create Usage Command
If this skill is frequently used, create a shortcut command:
```bash
/trellis:create-command use-<skill-name> Use <skill-name> skill following project guidelines
```
## Common Skill Integration Reference
| Skill | Integration Target | Examples Directory |
|-------|-------------------|-------------------|
| `frontend-design` | `frontend` | `examples/skills/frontend-design/` |
| `mcp-builder` | `backend` | `examples/skills/mcp-builder/` |
| `webapp-testing` | `frontend` | `examples/skills/webapp-testing/` |
| `doc-coauthoring` | `.trellis/` | N/A (documentation workflow only) |
## Example: Integrating `mcp-builder` Skill
### Directory Structure
```
.trellis/spec/backend/
|-- doc.md # Add MCP section
|-- index.md # Add index entry
+-- examples/
+-- skills/
+-- mcp-builder/
|-- README.md
|-- server.ts.template
|-- tools.ts.template
+-- types.ts.template
```
### New Section in doc.md
```markdown
@@@section:skill-mcp-builder
## # MCP Server Development Guide
### Overview
Create LLM-callable tool services using MCP (Model Context Protocol).
### Project Adaptation
- Place services in a dedicated directory
- Follow existing TypeScript and type definition conventions
- Use project's logging system
### Reference Examples
See `examples/skills/mcp-builder/`
@@@/section:skill-mcp-builder
```
-358
View File
@@ -1,358 +0,0 @@
You are a senior developer onboarding a new team member to this project's AI-assisted workflow system.
YOUR ROLE: Be a mentor and teacher. Don't just list steps - EXPLAIN the underlying principles, why each command exists, what problem it solves at a fundamental level.
## CRITICAL INSTRUCTION - YOU MUST COMPLETE ALL SECTIONS
This onboarding has THREE equally important parts:
**PART 1: Core Concepts** (Sections: CORE PHILOSOPHY, SYSTEM STRUCTURE, COMMAND DEEP DIVE)
- Explain WHY this workflow exists
- Explain WHAT each command does and WHY
**PART 2: Real-World Examples** (Section: REAL-WORLD WORKFLOW EXAMPLES)
- Walk through ALL 5 examples in detail
- For EACH step in EACH example, explain:
- PRINCIPLE: Why this step exists
- WHAT HAPPENS: What the command actually does
- IF SKIPPED: What goes wrong without it
**PART 3: Customize Your Development Guidelines** (Section: CUSTOMIZE YOUR DEVELOPMENT GUIDELINES)
- Check if project guidelines are still empty templates
- If empty, guide the developer to fill them with project-specific content
- Explain the customization workflow
DO NOT skip any part. All three parts are essential:
- Part 1 teaches the concepts
- Part 2 shows how concepts work in practice
- Part 3 ensures the project has proper guidelines for AI to follow
After completing ALL THREE parts, ask the developer about their first task.
---
## CORE PHILOSOPHY: Why This Workflow Exists
AI-assisted development has three fundamental challenges:
### Challenge 1: AI Has No Memory
Every AI session starts with a blank slate. Unlike human engineers who accumulate project knowledge over weeks/months, AI forgets everything when a session ends.
**The Problem**: Without memory, AI asks the same questions repeatedly, makes the same mistakes, and can't build on previous work.
**The Solution**: The `.trellis/workspace/` system captures what happened in each session - what was done, what was learned, what problems were solved. The `/trellis:start` command reads this history at session start, giving AI "artificial memory."
### Challenge 2: AI Has Generic Knowledge, Not Project-Specific Knowledge
AI models are trained on millions of codebases - they know general patterns for React, TypeScript, databases, etc. But they don't know YOUR project's conventions.
**The Problem**: AI writes code that "works" but doesn't match your project's style. It uses patterns that conflict with existing code. It makes decisions that violate unwritten team rules.
**The Solution**: The `.trellis/spec/` directory contains project-specific guidelines. The `/before-*-dev` commands inject this specialized knowledge into AI context before coding starts.
### Challenge 3: AI Context Window Is Limited
Even after injecting guidelines, AI has limited context window. As conversation grows, earlier context (including guidelines) gets pushed out or becomes less influential.
**The Problem**: AI starts following guidelines, but as the session progresses and context fills up, it "forgets" the rules and reverts to generic patterns.
**The Solution**: The `/check-*` commands re-verify code against guidelines AFTER writing, catching drift that occurred during development. The `/trellis:finish-work` command does a final holistic review.
---
## SYSTEM STRUCTURE
```
.trellis/
|-- .developer # Your identity (gitignored)
|-- workflow.md # Complete workflow documentation
|-- workspace/ # "AI Memory" - session history
| |-- index.md # All developers' progress
| +-- {developer}/ # Per-developer directory
| |-- index.md # Personal progress index
| +-- journal-N.md # Session records (max 2000 lines)
|-- tasks/ # Task tracking (unified)
| +-- {MM}-{DD}-{slug}/ # Task directory
| |-- task.json # Task metadata
| +-- prd.md # Requirements doc
|-- spec/ # "AI Training Data" - project knowledge
| |-- frontend/ # Frontend conventions
| |-- backend/ # Backend conventions
| +-- guides/ # Thinking patterns
+-- scripts/ # Automation tools
```
### Understanding spec/ subdirectories
**frontend/** - Single-layer frontend knowledge:
- Component patterns (how to write components in THIS project)
- State management rules (Redux? Zustand? Context?)
- Styling conventions (CSS modules? Tailwind? Styled-components?)
- Hook patterns (custom hooks, data fetching)
**backend/** - Single-layer backend knowledge:
- API design patterns (REST? GraphQL? tRPC?)
- Database conventions (query patterns, migrations)
- Error handling standards
- Logging and monitoring rules
**guides/** - Cross-layer thinking guides:
- Code reuse thinking guide
- Cross-layer thinking guide
- Pre-implementation checklists
---
## COMMAND DEEP DIVE
### /trellis:start - Restore AI Memory
**WHY IT EXISTS**:
When a human engineer joins a project, they spend days/weeks learning: What is this project? What's been built? What's in progress? What's the current state?
AI needs the same onboarding - but compressed into seconds at session start.
**WHAT IT ACTUALLY DOES**:
1. Reads developer identity (who am I in this project?)
2. Checks git status (what branch? uncommitted changes?)
3. Reads recent session history from `workspace/` (what happened before?)
4. Identifies active features (what's in progress?)
5. Understands current project state before making any changes
**WHY THIS MATTERS**:
- Without /trellis:start: AI is blind. It might work on wrong branch, conflict with others' work, or redo already-completed work.
- With /trellis:start: AI knows project context, can continue where previous session left off, avoids conflicts.
---
### /trellis:before-dev - Inject Specialized Knowledge
**WHY IT EXISTS**:
AI models have "pre-trained knowledge" - general patterns from millions of codebases. But YOUR project has specific conventions that differ from generic patterns.
**WHAT IT ACTUALLY DOES**:
1. Discovers spec layers via `get_context.py --mode packages` and reads relevant guidelines
2. Loads project-specific patterns into AI's working context:
- Component naming conventions
- State management patterns
- Database query patterns
- Error handling standards
**WHY THIS MATTERS**:
- Without before-dev: AI writes generic code that doesn't match project style.
- With before-dev: AI writes code that looks like the rest of the codebase.
---
### /trellis:check - Combat Context Drift
**WHY IT EXISTS**:
AI context window has limited capacity. As conversation progresses, guidelines injected at session start become less influential. This causes "context drift."
**WHAT IT ACTUALLY DOES**:
1. Re-reads the guidelines that were injected earlier
2. Compares written code against those guidelines
3. Runs type checker and linter
4. Identifies violations and suggests fixes
**WHY THIS MATTERS**:
- Without check-*: Context drift goes unnoticed, code quality degrades.
- With check-*: Drift is caught and corrected before commit.
---
### /trellis:check-cross-layer - Multi-Dimension Verification
**WHY IT EXISTS**:
Most bugs don't come from lack of technical skill - they come from "didn't think of it":
- Changed a constant in one place, missed 5 other places
- Modified database schema, forgot to update the API layer
- Created a utility function, but similar one already exists
**WHAT IT ACTUALLY DOES**:
1. Identifies which dimensions your change involves
2. For each dimension, runs targeted checks:
- Cross-layer data flow
- Code reuse analysis
- Import path validation
- Consistency checks
---
### /trellis:finish-work - Holistic Pre-Commit Review
**WHY IT EXISTS**:
The `/check-*` commands focus on code quality within a single layer. But real changes often have cross-cutting concerns.
**WHAT IT ACTUALLY DOES**:
1. Reviews all changes holistically
2. Checks cross-layer consistency
3. Identifies broader impacts
4. Checks if new patterns should be documented
---
### /trellis:record-session - Persist Memory for Future
**WHY IT EXISTS**:
All the context AI built during this session will be lost when session ends. The next session's `/trellis:start` needs this information.
**WHAT IT ACTUALLY DOES**:
1. Records session summary to `workspace/{developer}/journal-N.md`
2. Captures what was done, learned, and what's remaining
3. Updates index files for quick lookup
---
## REAL-WORLD WORKFLOW EXAMPLES
### Example 1: Bug Fix Session
**[1/8] /trellis:start** - AI needs project context before touching code
**[2/8] python3 ./.trellis/scripts/task.py create "Fix bug" --slug fix-bug** - Track work for future reference
**[3/8] /trellis:before-dev** - Inject project-specific development guidelines
**[4/8] Investigate and fix the bug** - Actual development work
**[5/8] /trellis:check** - Re-verify code against guidelines
**[6/8] /trellis:finish-work** - Holistic cross-layer review
**[7/8] Human tests and commits** - Human validates before code enters repo
**[8/8] /trellis:record-session** - Persist memory for future sessions
### Example 2: Planning Session (No Code)
**[1/4] /trellis:start** - Context needed even for non-coding work
**[2/4] python3 ./.trellis/scripts/task.py create "Planning task" --slug planning-task** - Planning is valuable work
**[3/4] Review docs, create subtask list** - Actual planning work
**[4/4] /trellis:record-session (with --summary)** - Planning decisions must be recorded
### Example 3: Code Review Fixes
**[1/6] /trellis:start** - Resume context from previous session
**[2/6] /trellis:before-dev** - Re-inject guidelines before fixes
**[3/6] Fix each CR issue** - Address feedback with guidelines in context
**[4/6] /trellis:check** - Verify fixes did not introduce new issues
**[5/6] /trellis:finish-work** - Document lessons from CR
**[6/6] Human commits, then /trellis:record-session** - Preserve CR lessons
### Example 4: Large Refactoring
**[1/5] /trellis:start** - Clear baseline before major changes
**[2/5] Plan phases** - Break into verifiable chunks
**[3/5] Execute phase by phase with /trellis:check after each** - Incremental verification
**[4/5] /trellis:finish-work** - Check if new patterns should be documented
**[5/5] Record with multiple commit hashes** - Link all commits to one feature
### Example 5: Debug Session
**[1/6] /trellis:start** - See if this bug was investigated before
**[2/6] /trellis:before-dev** - Guidelines might document known gotchas
**[3/6] Investigation** - Actual debugging work
**[4/6] /trellis:check** - Verify debug changes do not break other things
**[5/6] /trellis:finish-work** - Debug findings might need documentation
**[6/6] Human commits, then /trellis:record-session** - Debug knowledge is valuable
---
## KEY RULES TO EMPHASIZE
1. **AI NEVER commits** - Human tests and approves. AI prepares, human validates.
2. **Guidelines before code** - /before-dev command injects project knowledge.
3. **Check after code** - /check-* commands catch context drift.
4. **Record everything** - /trellis:record-session persists memory.
---
# PART 3: Customize Your Development Guidelines
After explaining Part 1 and Part 2, check if the project's development guidelines need customization.
## Step 1: Check Current Guidelines Status
Check if `.trellis/spec/` contains empty templates or customized guidelines:
```bash
# Check if files are still empty templates (look for placeholder text)
grep -l "To be filled by the team" .trellis/spec/backend/*.md 2>/dev/null | wc -l
grep -l "To be filled by the team" .trellis/spec/frontend/*.md 2>/dev/null | wc -l
```
## Step 2: Determine Situation
**Situation A: First-time setup (empty templates)**
If guidelines are empty templates (contain "To be filled by the team"), this is the first time using Trellis in this project.
Explain to the developer:
"I see that the development guidelines in `.trellis/spec/` are still empty templates. This is normal for a new Trellis setup!
The templates contain placeholder text that needs to be replaced with YOUR project's actual conventions. Without this, `/before-*-dev` commands won't provide useful guidance.
**Your first task should be to fill in these guidelines:**
1. Look at your existing codebase
2. Identify the patterns and conventions already in use
3. Document them in the guideline files
For example, for `.trellis/spec/backend/database-guidelines.md`:
- What ORM/query library does your project use?
- How are migrations managed?
- What naming conventions for tables/columns?
Would you like me to help you analyze your codebase and fill in these guidelines?"
**Situation B: Guidelines already customized**
If guidelines have real content (no "To be filled" placeholders), this is an existing setup.
Explain to the developer:
"Great! Your team has already customized the development guidelines. You can start using `/before-*-dev` commands right away.
I recommend reading through `.trellis/spec/` to familiarize yourself with the team's coding standards."
## Step 3: Help Fill Guidelines (If Empty)
If the developer wants help filling guidelines, create a feature to track this:
```bash
python3 ./.trellis/scripts/task.py create "Fill spec guidelines" --slug fill-spec-guidelines
```
Then systematically analyze the codebase and fill each guideline file:
1. **Analyze the codebase** - Look at existing code patterns
2. **Document conventions** - Write what you observe, not ideals
3. **Include examples** - Reference actual files in the project
4. **List forbidden patterns** - Document anti-patterns the team avoids
Work through one file at a time:
- `backend/directory-structure.md`
- `backend/database-guidelines.md`
- `backend/error-handling.md`
- `backend/quality-guidelines.md`
- `backend/logging-guidelines.md`
- `frontend/directory-structure.md`
- `frontend/component-guidelines.md`
- `frontend/hook-guidelines.md`
- `frontend/state-management.md`
- `frontend/quality-guidelines.md`
- `frontend/type-safety.md`
---
## Completing the Onboard Session
After covering all three parts, summarize:
"You're now onboarded to the Trellis workflow system! Here's what we covered:
- Part 1: Core concepts (why this workflow exists)
- Part 2: Real-world examples (how to apply the workflow)
- Part 3: Guidelines status (empty templates need filling / already customized)
**Next steps** (tell user):
1. Run `/trellis:record-session` to record this onboard session
2. [If guidelines empty] Start filling in `.trellis/spec/` guidelines
3. [If guidelines ready] Start your first development task
What would you like to do first?"
-192
View File
@@ -1,192 +0,0 @@
# Multi-Agent Pipeline Orchestrator
You are the Multi-Agent Pipeline Orchestrator Agent, running in the main repository, responsible for collaborating with users to manage parallel development tasks.
## Role Definition
- **You are in the main repository**, not in a worktree
- **You don't write code directly** - code work is done by agents in worktrees
- **You are responsible for planning and dispatching**: discuss requirements, create plans, configure context, start worktree agents
- **Delegate complex analysis to research agent**: finding specs, analyzing code structure
---
## Operation Types
Operations in this document are categorized as:
| Marker | Meaning | Executor |
|--------|---------|----------|
| `[AI]` | Bash scripts or Task calls executed by AI | You (AI) |
| `[USER]` | Slash commands executed by user | User |
---
## Startup Flow
### Step 1: Understand Trellis Workflow `[AI]`
First, read the workflow guide to understand the development process:
```bash
cat .trellis/workflow.md # Development process, conventions, and quick start guide
```
### Step 2: Get Current Status `[AI]`
```bash
python3 ./.trellis/scripts/get_context.py
```
### Step 3: Read Project Guidelines `[AI]`
```bash
python3 ./.trellis/scripts/get_context.py --mode packages # Discover available spec layers
cat .trellis/spec/guides/index.md # Thinking guides
```
### Step 4: Ask User for Requirements
Ask the user:
1. What feature to develop?
2. Which modules are involved?
3. Development type? (backend / frontend / fullstack)
---
## Planning: Choose Your Approach
Based on requirement complexity, choose one of these approaches:
### Option A: Plan Agent (Recommended for complex features) `[AI]`
Use when:
- Requirements need analysis and validation
- Multiple modules or cross-layer changes
- Unclear scope that needs research
```bash
python3 ./.trellis/scripts/multi_agent/plan.py \
--name "<feature-name>" \
--type "<backend|frontend|fullstack>" \
--requirement "<user requirement description>"
```
Plan Agent will:
1. Evaluate requirement validity (may reject if unclear/too large)
2. Call research agent to analyze codebase
3. Create and configure task directory
4. Write prd.md with acceptance criteria
5. Output ready-to-use task directory
After plan.py completes, start the worktree agent:
```bash
python3 ./.trellis/scripts/multi_agent/start.py "$TASK_DIR"
```
### Option B: Manual Configuration (For simple/clear features) `[AI]`
Use when:
- Requirements are already clear and specific
- You know exactly which files are involved
- Simple, well-scoped changes
#### Step 1: Create Task Directory
```bash
# title is task description, --slug for task directory name
TASK_DIR=$(python3 ./.trellis/scripts/task.py create "<title>" --slug <task-name>)
```
#### Step 2: Configure Task
```bash
# Initialize jsonl context files
python3 ./.trellis/scripts/task.py init-context "$TASK_DIR" <dev_type>
# Set branch and scope
python3 ./.trellis/scripts/task.py set-branch "$TASK_DIR" feature/<name>
python3 ./.trellis/scripts/task.py set-scope "$TASK_DIR" <scope>
```
#### Step 3: Add Context (optional: use research agent)
```bash
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" implement "<path>" "<reason>"
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" check "<path>" "<reason>"
```
#### Step 4: Create prd.md
```bash
cat > "$TASK_DIR/prd.md" << 'EOF'
# Feature: <name>
## Requirements
- ...
## Acceptance Criteria
- ...
EOF
```
#### Step 5: Validate and Start
```bash
python3 ./.trellis/scripts/task.py validate "$TASK_DIR"
python3 ./.trellis/scripts/multi_agent/start.py "$TASK_DIR"
```
---
## After Starting: Report Status
Tell the user the agent has started and provide monitoring commands.
---
## User Available Commands `[USER]`
The following slash commands are for users (not AI):
| Command | Description |
|---------|-------------|
| `/trellis:parallel` | Start Multi-Agent Pipeline (this command) |
| `/trellis:start` | Start normal development mode (single process) |
| `/trellis:record-session` | Record session progress |
| `/trellis:finish-work` | Pre-completion checklist |
---
## Monitoring Commands (for user reference)
Tell the user they can use these commands to monitor:
```bash
python3 ./.trellis/scripts/multi_agent/status.py # Overview
python3 ./.trellis/scripts/multi_agent/status.py --log <name> # View log
python3 ./.trellis/scripts/multi_agent/status.py --watch <name> # Real-time monitoring
python3 ./.trellis/scripts/multi_agent/cleanup.py <branch> # Cleanup worktree
```
---
## Pipeline Phases
The dispatch agent in worktree will automatically execute:
1. implement → Implement feature
2. check → Check code quality
3. finish → Final verification
4. create-pr → Create PR
---
## Core Rules
- **Don't write code directly** - delegate to agents in worktree
- **Don't execute git commit** - agent does it via create-pr action
- **Delegate complex analysis to research** - finding specs, analyzing code structure
- **All sub agents use opus model** - ensure output quality
@@ -1,62 +0,0 @@
[!] **Prerequisite**: This command should only be used AFTER the human has tested and committed the code.
**Do NOT run `git commit` directly** — the scripts below handle their own commits for `.trellis/` metadata. You only need to read git history (`git log`, `git status`, `git diff`) and run the Python scripts.
---
## Record Work Progress
### Step 1: Get Context & Check Tasks
```bash
python3 ./.trellis/scripts/get_context.py --mode record
```
[!] Archive tasks whose work is **actually done** — judge by work status, not the `status` field in task.json:
- Code committed? → Archive it (don't wait for PR)
- All acceptance criteria met? → Archive it
- Don't skip archiving just because `status` still says `planning` or `in_progress`
```bash
python3 ./.trellis/scripts/task.py archive <task-name>
```
### Step 2: One-Click Add Session
```bash
# Method 1: Simple parameters
python3 ./.trellis/scripts/add_session.py \
--title "Session Title" \
--commit "hash1,hash2" \
--summary "Brief summary of what was done"
# Method 2: Pass detailed content via stdin
cat << 'EOF' | python3 ./.trellis/scripts/add_session.py --stdin --title "Title" --commit "hash"
| Feature | Description |
|---------|-------------|
| New API | Added user authentication endpoint |
| Frontend | Updated login form |
**Updated Files**:
- `packages/api/modules/auth/router.ts`
- `apps/web/modules/auth/components/login-form.tsx`
EOF
```
**Auto-completes**:
- [OK] Appends session to journal-N.md
- [OK] Auto-detects line count, creates new file if >2000 lines
- [OK] Auto-detects Branch context (`--branch` override; otherwise Branch = task.json -> current git branch; missing values are omitted gracefully)
- [OK] Updates index.md (Total Sessions +1, Last Active, line stats, history)
- [OK] Auto-commits .trellis/workspace and .trellis/tasks changes
---
## Script Command Reference
| Command | Purpose |
|---------|---------|
| `python3 ./.trellis/scripts/get_context.py --mode record` | Get context for record-session |
| `python3 ./.trellis/scripts/add_session.py --title "..." --commit "..."` | **One-click add session (recommended, branch auto-complete)** |
| `python3 ./.trellis/scripts/task.py archive <name>` | Archive completed task (auto-commits) |
| `python3 ./.trellis/scripts/task.py list` | List active tasks |
-393
View File
@@ -1,393 +0,0 @@
# Start Session
Initialize your AI development session and begin working on tasks.
---
## Operation Types
| Marker | Meaning | Executor |
|--------|---------|----------|
| `[AI]` | Bash scripts or Task calls executed by AI | You (AI) |
| `[USER]` | Slash commands executed by user | User |
---
## Initialization `[AI]`
### Step 1: Understand Development Workflow
First, read the workflow guide to understand the development process:
```bash
cat .trellis/workflow.md
```
**Follow the instructions in workflow.md** - it contains:
- Core principles (Read Before Write, Follow Standards, etc.)
- File system structure
- Development process
- Best practices
### Step 2: Get Current Context
```bash
python3 ./.trellis/scripts/get_context.py
```
This shows: developer identity, git status, current task (if any), active tasks.
### Step 3: Read Guidelines Index
```bash
python3 ./.trellis/scripts/get_context.py --mode packages
```
This shows available packages and their spec layers. Read the relevant spec indexes:
```bash
cat .trellis/spec/<package>/<layer>/index.md # Package-specific guidelines
cat .trellis/spec/guides/index.md # Thinking guides (always read)
```
> **Important**: The index files are navigation — they list the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`).
> At this step, just read the indexes to understand what's available.
> When you start actual development, you MUST go back and read the specific guideline files relevant to your task, as listed in the index's Pre-Development Checklist.
### Step 4: Report and Ask
Report what you learned and ask: "What would you like to work on?"
---
## Task Classification
When user describes a task, classify it:
| Type | Criteria | Workflow |
|------|----------|----------|
| **Question** | User asks about code, architecture, or how something works | Answer directly |
| **Trivial Fix** | Typo fix, comment update, single-line change | Direct Edit |
| **Simple Task** | Clear goal, 1-2 files, well-defined scope | Quick confirm → Implement |
| **Complex Task** | Vague goal, multiple files, architectural decisions | **Brainstorm → Task Workflow** |
### Classification Signals
**Trivial/Simple indicators:**
- User specifies exact file and change
- "Fix the typo in X"
- "Add field Y to component Z"
- Clear acceptance criteria already stated
**Complex indicators:**
- "I want to add a feature for..."
- "Can you help me improve..."
- Mentions multiple areas or systems
- No clear implementation path
- User seems unsure about approach
### Decision Rule
> **If in doubt, use Brainstorm + Task Workflow.**
>
> Task Workflow ensures code-spec context is injected to agents, resulting in higher quality code.
> The overhead is minimal, but the benefit is significant.
---
## Question / Trivial Fix
For questions or trivial fixes, work directly:
1. Answer question or make the fix
2. If code was changed, remind user to run `/trellis:finish-work`
---
## Simple Task
For simple, well-defined tasks:
1. Quick confirm: "I understand you want to [goal]. Shall I proceed?"
2. If no, clarify and confirm again
3. **If yes: execute ALL steps below without stopping. Do NOT ask for additional confirmation between steps.**
- Create task directory (Phase 1 Path B, Step 2)
- Write PRD (Step 3)
- Research codebase (Phase 2, Step 5)
- Configure context (Step 6)
- Activate task (Step 7)
- Implement (Phase 3, Step 8)
- Check quality (Step 9)
- Complete (Step 10)
---
## Complex Task - Brainstorm First
For complex or vague tasks, **automatically start the brainstorm process** — do NOT skip directly to implementation.
See `/trellis:brainstorm` for the full process. Summary:
1. **Acknowledge and classify** - State your understanding
2. **Create task directory** - Track evolving requirements in `prd.md`
3. **Ask questions one at a time** - Update PRD after each answer
4. **Propose approaches** - For architectural decisions
5. **Confirm final requirements** - Get explicit approval
6. **Proceed to Task Workflow** - With clear requirements in PRD
> **Subtask Decomposition**: If brainstorm reveals multiple independent work items,
> consider creating subtasks using `--parent` flag or `add-subtask` command.
> See `/trellis:brainstorm` Step 8 for details.
### Key Brainstorm Principles
| Principle | Description |
|-----------|-------------|
| **One question at a time** | Never overwhelm with multiple questions |
| **Update PRD immediately** | After each answer, update the document |
| **Prefer multiple choice** | Easier for users to answer |
| **YAGNI** | Challenge unnecessary complexity |
---
## Task Workflow (Development Tasks)
**Why this workflow?**
- Research Agent analyzes what code-spec files are needed
- Code-spec files are configured in jsonl files
- Implement Agent receives code-spec context via Hook injection
- Check Agent verifies against code-spec requirements
- Result: Code that follows project conventions automatically
### Overview: Two Entry Points
```
From Brainstorm (Complex Task):
PRD confirmed → Research → Configure Context → Activate → Implement → Check → Complete
From Simple Task:
Confirm → Create Task → Write PRD → Research → Configure Context → Activate → Implement → Check → Complete
```
**Key principle: Research happens AFTER requirements are clear (PRD exists).**
---
### Phase 1: Establish Requirements
#### Path A: From Brainstorm (skip to Phase 2)
PRD and task directory already exist from brainstorm. Skip directly to Phase 2.
#### Path B: From Simple Task
**Step 1: Confirm Understanding** `[AI]`
Quick confirm:
- What is the goal?
- What type of development? (frontend / backend / fullstack)
- Any specific requirements or constraints?
**Step 2: Create Task Directory** `[AI]`
```bash
TASK_DIR=$(python3 ./.trellis/scripts/task.py create "<title>" --slug <name>)
```
**Step 3: Write PRD** `[AI]`
Create `prd.md` in the task directory with:
```markdown
# <Task Title>
## Goal
<What we're trying to achieve>
## Requirements
- <Requirement 1>
- <Requirement 2>
## Acceptance Criteria
- [ ] <Criterion 1>
- [ ] <Criterion 2>
## Technical Notes
<Any technical decisions or constraints>
```
---
### Phase 2: Prepare for Implementation (shared)
> Both paths converge here. PRD and task directory must exist before proceeding.
**Step 4: Code-Spec Depth Check** `[AI]`
If the task touches infra or cross-layer contracts, do not start implementation until code-spec depth is defined.
Trigger this requirement when the change includes any of:
- New or changed command/API signatures
- Database schema or migration changes
- Infra integrations (storage, queue, cache, secrets, env contracts)
- Cross-layer payload transformations
Must-have before proceeding:
- [ ] Target code-spec files to update are identified
- [ ] Concrete contract is defined (signature, fields, env keys)
- [ ] Validation and error matrix is defined
- [ ] At least one Good/Base/Bad case is defined
**Step 5: Research the Codebase** `[AI]`
Based on the confirmed PRD, call Research Agent to find relevant specs and patterns:
```
Task(
subagent_type: "research",
prompt: "Analyze the codebase for this task:
Task: <goal from PRD>
Type: <frontend/backend/fullstack>
Please find:
1. Relevant code-spec files in .trellis/spec/
2. Existing code patterns to follow (find 2-3 examples)
3. Files that will likely need modification
Output:
## Relevant Code-Specs
- <path>: <why it's relevant>
## Code Patterns Found
- <pattern>: <example file path>
## Files to Modify
- <path>: <what change>",
model: "opus"
)
```
**Step 6: Configure Context** `[AI]`
Initialize default context:
```bash
python3 ./.trellis/scripts/task.py init-context "$TASK_DIR" <type>
# type: backend | frontend | fullstack
```
Add code-spec files found by Research Agent:
```bash
# For each relevant code-spec and code pattern:
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" implement "<path>" "<reason>"
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" check "<path>" "<reason>"
```
**Step 7: Activate Task** `[AI]`
```bash
python3 ./.trellis/scripts/task.py start "$TASK_DIR"
```
This sets `.current-task` so hooks can inject context.
---
### Phase 3: Execute (shared)
**Step 8: Implement** `[AI]`
Call Implement Agent (code-spec context is auto-injected by hook):
```
Task(
subagent_type: "implement",
prompt: "Implement the task described in prd.md.
Follow all code-spec files that have been injected into your context.
Run lint and typecheck before finishing.",
model: "opus"
)
```
**Step 9: Check Quality** `[AI]`
Call Check Agent (code-spec context is auto-injected by hook):
```
Task(
subagent_type: "check",
prompt: "Review all code changes against the code-spec requirements.
Fix any issues you find directly.
Ensure lint and typecheck pass.",
model: "opus"
)
```
**Step 10: Complete** `[AI]`
1. Verify lint and typecheck pass
2. Report what was implemented
3. Remind user to:
- Test the changes
- Commit when ready
- Run `/trellis:record-session` to record this session
---
## Continuing Existing Task
If `get_context.py` shows a current task:
1. Read the task's `prd.md` to understand the goal
2. Check `task.json` for current status and phase
3. Ask user: "Continue working on <task-name>?"
If yes, resume from the appropriate step (usually Step 7 or 8).
---
## Commands Reference
### User Commands `[USER]`
| Command | When to Use |
|---------|-------------|
| `/trellis:start` | Begin a session (this command) |
| `/trellis:brainstorm` | Clarify vague requirements (called from start) |
| `/trellis:parallel` | Complex tasks needing isolated worktree |
| `/trellis:finish-work` | Before committing changes |
| `/trellis:record-session` | After completing a task |
### AI Scripts `[AI]`
| Script | Purpose |
|--------|---------|
| `python3 ./.trellis/scripts/get_context.py` | Get session context |
| `python3 ./.trellis/scripts/task.py create` | Create task directory |
| `python3 ./.trellis/scripts/task.py init-context` | Initialize jsonl files |
| `python3 ./.trellis/scripts/task.py add-context` | Add code-spec/context file to jsonl |
| `python3 ./.trellis/scripts/task.py start` | Set current task |
| `python3 ./.trellis/scripts/task.py finish` | Clear current task |
| `python3 ./.trellis/scripts/task.py archive` | Archive completed task |
### Sub Agents `[AI]`
| Agent | Purpose | Hook Injection |
|-------|---------|----------------|
| research | Analyze codebase | No (reads directly) |
| implement | Write code | Yes (implement.jsonl) |
| check | Review & fix | Yes (check.jsonl) |
| debug | Fix specific issues | Yes (debug.jsonl) |
---
## Key Principle
> **Code-spec context is injected, not remembered.**
>
> The Task Workflow ensures agents receive relevant code-spec context automatically.
> This is more reliable than hoping the AI "remembers" conventions.
-354
View File
@@ -1,354 +0,0 @@
# Update Code-Spec - Capture Executable Contracts
When you learn something valuable (from debugging, implementing, or discussion), use this command to update the relevant code-spec documents.
**Timing**: After completing a task, fixing a bug, or discovering a new pattern
---
## Code-Spec First Rule (CRITICAL)
In this project, "spec" for implementation work means **code-spec**:
- Executable contracts (not principle-only text)
- Concrete signatures, payload fields, env keys, and boundary behavior
- Testable validation/error behavior
If the change touches infra or cross-layer contracts, code-spec depth is mandatory.
### Mandatory Triggers
Apply code-spec depth when the change includes any of:
- New/changed command or API signature
- Cross-layer request/response contract change
- Database schema/migration change
- Infra integration (storage, queue, cache, secrets, env wiring)
### Mandatory Output (7 Sections)
For triggered tasks, include all sections below:
1. Scope / Trigger
2. Signatures (command/API/DB)
3. Contracts (request/response/env)
4. Validation & Error Matrix
5. Good/Base/Bad Cases
6. Tests Required (with assertion points)
7. Wrong vs Correct (at least one pair)
---
## When to Update Code-Specs
| Trigger | Example | Target Spec |
|---------|---------|-------------|
| **Implemented a feature** | Added template download with giget | Relevant `backend/` or `frontend/` file |
| **Made a design decision** | Used type field + mapping table for extensibility | Relevant code-spec + "Design Decisions" section |
| **Fixed a bug** | Found a subtle issue with error handling | `backend/error-handling.md` |
| **Discovered a pattern** | Found a better way to structure code | Relevant `backend/` or `frontend/` file |
| **Hit a gotcha** | Learned that X must be done before Y | Relevant code-spec + "Common Mistakes" section |
| **Established a convention** | Team agreed on naming pattern | `quality-guidelines.md` |
| **New thinking trigger** | "Don't forget to check X before doing Y" | `guides/*.md` (as a checklist item, not detailed rules) |
**Key Insight**: Code-spec updates are NOT just for problems. Every feature implementation contains design decisions and contracts that future AI/developers need to execute safely.
---
## Spec Structure Overview
```
.trellis/spec/
├── backend/ # Backend coding standards
│ ├── index.md # Overview and links
│ └── *.md # Topic-specific guidelines
├── frontend/ # Frontend coding standards
│ ├── index.md # Overview and links
│ └── *.md # Topic-specific guidelines
└── guides/ # Thinking checklists (NOT coding specs!)
├── index.md # Guide index
└── *.md # Topic-specific guides
```
### CRITICAL: Code-Spec vs Guide - Know the Difference
| Type | Location | Purpose | Content Style |
|------|----------|---------|---------------|
| **Code-Spec** | `backend/*.md`, `frontend/*.md` | Tell AI "how to implement safely" | Signatures, contracts, matrices, cases, test points |
| **Guide** | `guides/*.md` | Help AI "what to think about" | Checklists, questions, pointers to specs |
**Decision Rule**: Ask yourself:
- "This is **how to write** the code" → Put in `backend/` or `frontend/`
- "This is **what to consider** before writing" → Put in `guides/`
**Example**:
| Learning | Wrong Location | Correct Location |
|----------|----------------|------------------|
| "Use `reconfigure()` not `TextIOWrapper` for Windows stdout" | ❌ `guides/cross-platform-thinking-guide.md` | ✅ `backend/script-conventions.md` |
| "Remember to check encoding when writing cross-platform code" | ❌ `backend/script-conventions.md` | ✅ `guides/cross-platform-thinking-guide.md` |
**Guides should be short checklists that point to specs**, not duplicate the detailed rules.
---
## Update Process
### Step 1: Identify What You Learned
Answer these questions:
1. **What did you learn?** (Be specific)
2. **Why is it important?** (What problem does it prevent?)
3. **Where does it belong?** (Which spec file?)
### Step 2: Classify the Update Type
| Type | Description | Action |
|------|-------------|--------|
| **Design Decision** | Why we chose approach X over Y | Add to "Design Decisions" section |
| **Project Convention** | How we do X in this project | Add to relevant section with examples |
| **New Pattern** | A reusable approach discovered | Add to "Patterns" section |
| **Forbidden Pattern** | Something that causes problems | Add to "Anti-patterns" or "Don't" section |
| **Common Mistake** | Easy-to-make error | Add to "Common Mistakes" section |
| **Convention** | Agreed-upon standard | Add to relevant section |
| **Gotcha** | Non-obvious behavior | Add warning callout |
### Step 3: Read the Target Code-Spec
Before editing, read the current code-spec to:
- Understand existing structure
- Avoid duplicating content
- Find the right section for your update
```bash
cat .trellis/spec/<category>/<file>.md
```
### Step 4: Make the Update
Follow these principles:
1. **Be Specific**: Include concrete examples, not just abstract rules
2. **Explain Why**: State the problem this prevents
3. **Show Contracts**: Add signatures, payload fields, and error behavior
4. **Show Code**: Add code snippets for key patterns
5. **Keep it Short**: One concept per section
### Step 5: Update the Index (if needed)
If you added a new section or the code-spec status changed, update the category's `index.md`.
---
## Update Templates
### Mandatory Template for Infra/Cross-Layer Work
```markdown
## Scenario: <name>
### 1. Scope / Trigger
- Trigger: <why this requires code-spec depth>
### 2. Signatures
- Backend command/API/DB signature(s)
### 3. Contracts
- Request fields (name, type, constraints)
- Response fields (name, type, constraints)
- Environment keys (required/optional)
### 4. Validation & Error Matrix
- <condition> -> <error>
### 5. Good/Base/Bad Cases
- Good: ...
- Base: ...
- Bad: ...
### 6. Tests Required
- Unit/Integration/E2E with assertion points
### 7. Wrong vs Correct
#### Wrong
...
#### Correct
...
```
### Adding a Design Decision
```markdown
### Design Decision: [Decision Name]
**Context**: What problem were we solving?
**Options Considered**:
1. Option A - brief description
2. Option B - brief description
**Decision**: We chose Option X because...
**Example**:
\`\`\`typescript
// How it's implemented
code example
\`\`\`
**Extensibility**: How to extend this in the future...
```
### Adding a Project Convention
```markdown
### Convention: [Convention Name]
**What**: Brief description of the convention.
**Why**: Why we do it this way in this project.
**Example**:
\`\`\`typescript
// How to follow this convention
code example
\`\`\`
**Related**: Links to related conventions or specs.
```
### Adding a New Pattern
```markdown
### Pattern Name
**Problem**: What problem does this solve?
**Solution**: Brief description of the approach.
**Example**:
\`\`\`
// Good
code example
// Bad
code example
\`\`\`
**Why**: Explanation of why this works better.
```
### Adding a Forbidden Pattern
```markdown
### Don't: Pattern Name
**Problem**:
\`\`\`
// Don't do this
bad code example
\`\`\`
**Why it's bad**: Explanation of the issue.
**Instead**:
\`\`\`
// Do this instead
good code example
\`\`\`
```
### Adding a Common Mistake
```markdown
### Common Mistake: Description
**Symptom**: What goes wrong
**Cause**: Why this happens
**Fix**: How to correct it
**Prevention**: How to avoid it in the future
```
### Adding a Gotcha
```markdown
> **Warning**: Brief description of the non-obvious behavior.
>
> Details about when this happens and how to handle it.
```
---
## Interactive Mode
If you're unsure what to update, answer these prompts:
1. **What did you just finish?**
- [ ] Fixed a bug
- [ ] Implemented a feature
- [ ] Refactored code
- [ ] Had a discussion about approach
2. **What did you learn or decide?**
- Design decision (why X over Y)
- Project convention (how we do X)
- Non-obvious behavior (gotcha)
- Better approach (pattern)
3. **Would future AI/developers need to know this?**
- To understand how the code works → Yes, update spec
- To maintain or extend the feature → Yes, update spec
- To avoid repeating mistakes → Yes, update spec
- Purely one-off implementation detail → Maybe skip
4. **Which area does it relate to?**
- [ ] Backend code
- [ ] Frontend code
- [ ] Cross-layer data flow
- [ ] Code organization/reuse
- [ ] Quality/testing
---
## Quality Checklist
Before finishing your code-spec update:
- [ ] Is the content specific and actionable?
- [ ] Did you include a code example?
- [ ] Did you explain WHY, not just WHAT?
- [ ] Did you include executable signatures/contracts?
- [ ] Did you include validation and error matrix?
- [ ] Did you include Good/Base/Bad cases?
- [ ] Did you include required tests with assertion points?
- [ ] Is it in the right code-spec file?
- [ ] Does it duplicate existing content?
- [ ] Would a new team member understand it?
---
## Relationship to Other Commands
```
Development Flow:
Learn something → /trellis:update-spec → Knowledge captured
↑ ↓
/trellis:break-loop ←──────────────────── Future sessions benefit
(deep bug analysis)
```
- `/trellis:break-loop` - Analyzes bugs deeply, often reveals spec updates needed
- `/trellis:update-spec` - Actually makes the updates (this command)
- `/trellis:finish-work` - Reminds you to check if specs need updates
---
## Core Philosophy
> **Code-specs are living documents. Every debugging session, every "aha moment" is an opportunity to make the implementation contract clearer.**
The goal is **institutional memory**:
- What one person learns, everyone benefits from
- What AI learns in one session, persists to future sessions
- Mistakes become documented guardrails
-803
View File
@@ -1,803 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Multi-Agent Pipeline Context Injection Hook
Core Design Philosophy:
- Dispatch becomes a pure dispatcher, only responsible for "calling subagents"
- Hook is responsible for injecting all context, subagent works autonomously with complete info
- Each agent has a dedicated jsonl file defining its context
- No resume needed, no segmentation, behavior controlled by code not prompt
Trigger: PreToolUse (before Task tool call)
Context Source: .trellis/.current-task points to task directory
- implement.jsonl - Implement agent dedicated context
- check.jsonl - Check agent dedicated context
- debug.jsonl - Debug agent dedicated context
- research.jsonl - Research agent dedicated context (optional, usually not needed)
- cr.jsonl - Code review dedicated context
- prd.md - Requirements document
- info.md - Technical design
- codex-review-output.txt - Code Review results
"""
# IMPORTANT: Suppress all warnings FIRST
import warnings
warnings.filterwarnings("ignore")
import json
import os
import sys
from pathlib import Path
# IMPORTANT: Force stdout to use UTF-8 on Windows
# This fixes UnicodeEncodeError when outputting non-ASCII characters
if sys.platform == "win32":
import io as _io
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
elif hasattr(sys.stdout, "detach"):
sys.stdout = _io.TextIOWrapper(sys.stdout.detach(), encoding="utf-8", errors="replace") # type: ignore[union-attr]
# =============================================================================
# Path Constants (change here to rename directories)
# =============================================================================
DIR_WORKFLOW = ".trellis"
DIR_WORKSPACE = "workspace"
DIR_TASKS = "tasks"
DIR_SPEC = "spec"
FILE_CURRENT_TASK = ".current-task"
FILE_TASK_JSON = "task.json"
# Agents that don't update phase (can be called at any time)
AGENTS_NO_PHASE_UPDATE = {"debug", "research"}
# =============================================================================
# Subagent Constants (change here to rename subagent types)
# =============================================================================
AGENT_IMPLEMENT = "implement"
AGENT_CHECK = "check"
AGENT_DEBUG = "debug"
AGENT_RESEARCH = "research"
# Agents that require a task directory
AGENTS_REQUIRE_TASK = (AGENT_IMPLEMENT, AGENT_CHECK, AGENT_DEBUG)
# All supported agents
AGENTS_ALL = (AGENT_IMPLEMENT, AGENT_CHECK, AGENT_DEBUG, AGENT_RESEARCH)
def find_repo_root(start_path: str) -> str | None:
"""
Find git repo root from start_path upwards
Returns:
Repo root path, or None if not found
"""
current = Path(start_path).resolve()
while current != current.parent:
if (current / ".git").exists():
return str(current)
current = current.parent
return None
def get_current_task(repo_root: str) -> str | None:
"""
Read current task directory path from .trellis/.current-task
Returns:
Task directory relative path (relative to repo_root)
None if not set
"""
current_task_file = os.path.join(repo_root, DIR_WORKFLOW, FILE_CURRENT_TASK)
if not os.path.exists(current_task_file):
return None
try:
with open(current_task_file, "r", encoding="utf-8") as f:
content = f.read().strip()
if not content:
return None
normalized = content.replace("\\", "/")
while normalized.startswith("./"):
normalized = normalized[2:]
if normalized.startswith("tasks/"):
normalized = f".trellis/{normalized}"
return normalized
except Exception:
return None
def update_current_phase(repo_root: str, task_dir: str, subagent_type: str) -> None:
"""
Update current_phase in task.json based on subagent_type.
This ensures phase tracking is always accurate, regardless of whether
dispatch agent remembers to update it.
Logic:
- Read next_action array from task.json
- Find the next phase whose action matches subagent_type
- Only move forward, never backward
- Some agents (debug, research) don't update phase
"""
if subagent_type in AGENTS_NO_PHASE_UPDATE:
return
task_json_path = os.path.join(repo_root, task_dir, FILE_TASK_JSON)
if not os.path.exists(task_json_path):
return
try:
with open(task_json_path, "r", encoding="utf-8") as f:
task_data = json.load(f)
current_phase = task_data.get("current_phase", 0)
next_actions = task_data.get("next_action", [])
# Map action names to subagent types
# "implement" -> "implement", "check" -> "check", "finish" -> "check"
action_to_agent = {
"implement": "implement",
"check": "check",
"finish": "check", # finish uses check agent
}
# Find the next phase that matches this subagent_type
new_phase = None
for action in next_actions:
phase_num = action.get("phase", 0)
action_name = action.get("action", "")
expected_agent = action_to_agent.get(action_name)
# Only consider phases after current_phase
if phase_num > current_phase and expected_agent == subagent_type:
new_phase = phase_num
break
if new_phase is not None:
task_data["current_phase"] = new_phase
with open(task_json_path, "w", encoding="utf-8") as f:
json.dump(task_data, f, indent=2, ensure_ascii=False)
except Exception:
# Don't fail the hook if phase update fails
pass
def read_file_content(base_path: str, file_path: str) -> str | None:
"""Read file content, return None if file doesn't exist"""
full_path = os.path.join(base_path, file_path)
if os.path.exists(full_path) and os.path.isfile(full_path):
try:
with open(full_path, "r", encoding="utf-8") as f:
return f.read()
except Exception:
return None
return None
def read_directory_contents(
base_path: str, dir_path: str, max_files: int = 20
) -> list[tuple[str, str]]:
"""
Read all .md files in a directory
Args:
base_path: Base path (usually repo_root)
dir_path: Directory relative path
max_files: Max files to read (prevent huge directories)
Returns:
[(file_path, content), ...]
"""
full_path = os.path.join(base_path, dir_path)
if not os.path.exists(full_path) or not os.path.isdir(full_path):
return []
results = []
try:
# Only read .md files, sorted by filename
md_files = sorted(
[
f
for f in os.listdir(full_path)
if f.endswith(".md") and os.path.isfile(os.path.join(full_path, f))
]
)
for filename in md_files[:max_files]:
file_full_path = os.path.join(full_path, filename)
relative_path = os.path.join(dir_path, filename)
try:
with open(file_full_path, "r", encoding="utf-8") as f:
content = f.read()
results.append((relative_path, content))
except Exception:
continue
except Exception:
pass
return results
def read_jsonl_entries(base_path: str, jsonl_path: str) -> list[tuple[str, str]]:
"""
Read all file/directory contents referenced in jsonl file
Schema:
{"file": "path/to/file.md", "reason": "..."}
{"file": "path/to/dir/", "type": "directory", "reason": "..."}
Returns:
[(path, content), ...]
"""
full_path = os.path.join(base_path, jsonl_path)
if not os.path.exists(full_path):
return []
results = []
try:
with open(full_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
item = json.loads(line)
file_path = item.get("file") or item.get("path")
entry_type = item.get("type", "file")
if not file_path:
continue
if entry_type == "directory":
# Read all .md files in directory
dir_contents = read_directory_contents(base_path, file_path)
results.extend(dir_contents)
else:
# Read single file
content = read_file_content(base_path, file_path)
if content:
results.append((file_path, content))
except json.JSONDecodeError:
continue
except Exception:
pass
return results
def get_agent_context(repo_root: str, task_dir: str, agent_type: str) -> str:
"""
Get complete context for specified agent
Prioritize agent-specific jsonl, fallback to spec.jsonl if not exists
"""
context_parts = []
# 1. Try agent-specific jsonl
agent_jsonl = f"{task_dir}/{agent_type}.jsonl"
agent_entries = read_jsonl_entries(repo_root, agent_jsonl)
# 2. If agent-specific jsonl doesn't exist or empty, fallback to spec.jsonl
if not agent_entries:
agent_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
# 3. Add all files from jsonl
for file_path, content in agent_entries:
context_parts.append(f"=== {file_path} ===\n{content}")
return "\n\n".join(context_parts)
def get_implement_context(repo_root: str, task_dir: str) -> str:
"""
Complete context for Implement Agent
Read order:
1. All files in implement.jsonl (dev specs)
2. prd.md (requirements)
3. info.md (technical design)
"""
context_parts = []
# 1. Read implement.jsonl (or fallback to spec.jsonl)
base_context = get_agent_context(repo_root, task_dir, "implement")
if base_context:
context_parts.append(base_context)
# 2. Requirements document
prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
if prd_content:
context_parts.append(f"=== {task_dir}/prd.md (Requirements) ===\n{prd_content}")
# 3. Technical design
info_content = read_file_content(repo_root, f"{task_dir}/info.md")
if info_content:
context_parts.append(
f"=== {task_dir}/info.md (Technical Design) ===\n{info_content}"
)
return "\n\n".join(context_parts)
def get_check_context(repo_root: str, task_dir: str) -> str:
"""
Complete context for Check Agent
Read order:
1. All files in check.jsonl (check specs + dev specs)
2. prd.md (for understanding task intent)
"""
context_parts = []
# 1. Read check.jsonl (or fallback to spec.jsonl + hardcoded check files)
check_entries = read_jsonl_entries(repo_root, f"{task_dir}/check.jsonl")
if check_entries:
for file_path, content in check_entries:
context_parts.append(f"=== {file_path} ===\n{content}")
else:
# Fallback: use hardcoded check files + spec.jsonl
check_files = [
(".claude/commands/trellis/finish-work.md", "Finish work checklist"),
(".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
(".claude/commands/trellis/check.md", "Code quality check spec"),
]
for file_path, description in check_files:
content = read_file_content(repo_root, file_path)
if content:
context_parts.append(f"=== {file_path} ({description}) ===\n{content}")
# Add spec.jsonl
spec_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
for file_path, content in spec_entries:
context_parts.append(f"=== {file_path} (Dev spec) ===\n{content}")
# 2. Requirements document (for understanding task intent)
prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
if prd_content:
context_parts.append(
f"=== {task_dir}/prd.md (Requirements - for understanding intent) ===\n{prd_content}"
)
return "\n\n".join(context_parts)
def get_finish_context(repo_root: str, task_dir: str) -> str:
"""
Complete context for Finish phase (final check before PR)
Read order:
1. All files in finish.jsonl (if exists)
2. Fallback to finish-work.md only (lightweight final check)
3. update-spec.md (for active spec sync)
4. prd.md (for verifying requirements are met)
"""
context_parts = []
# 1. Try finish.jsonl first
finish_entries = read_jsonl_entries(repo_root, f"{task_dir}/finish.jsonl")
if finish_entries:
for file_path, content in finish_entries:
context_parts.append(f"=== {file_path} ===\n{content}")
else:
# Fallback: only finish-work.md (lightweight)
finish_work = read_file_content(
repo_root, ".claude/commands/trellis/finish-work.md"
)
if finish_work:
context_parts.append(
f"=== .claude/commands/trellis/finish-work.md (Finish checklist) ===\n{finish_work}"
)
# 2. Spec update process (for active spec sync)
update_spec = read_file_content(
repo_root, ".claude/commands/trellis/update-spec.md"
)
if update_spec:
context_parts.append(
f"=== .claude/commands/trellis/update-spec.md (Spec update process) ===\n{update_spec}"
)
# 3. Requirements document (for verifying requirements are met)
prd_content = read_file_content(repo_root, f"{task_dir}/prd.md")
if prd_content:
context_parts.append(
f"=== {task_dir}/prd.md (Requirements - verify all met) ===\n{prd_content}"
)
return "\n\n".join(context_parts)
def get_debug_context(repo_root: str, task_dir: str) -> str:
"""
Complete context for Debug Agent
Read order:
1. All files in debug.jsonl (specs needed for fixing)
2. codex-review-output.txt (Codex Review results)
"""
context_parts = []
# 1. Read debug.jsonl (or fallback to spec.jsonl + hardcoded check files)
debug_entries = read_jsonl_entries(repo_root, f"{task_dir}/debug.jsonl")
if debug_entries:
for file_path, content in debug_entries:
context_parts.append(f"=== {file_path} ===\n{content}")
else:
# Fallback: use spec.jsonl + hardcoded check files
spec_entries = read_jsonl_entries(repo_root, f"{task_dir}/spec.jsonl")
for file_path, content in spec_entries:
context_parts.append(f"=== {file_path} (Dev spec) ===\n{content}")
check_files = [
(".claude/commands/trellis/check.md", "Code quality check spec"),
(".claude/commands/trellis/check-cross-layer.md", "Cross-layer check spec"),
]
for file_path, description in check_files:
content = read_file_content(repo_root, file_path)
if content:
context_parts.append(f"=== {file_path} ({description}) ===\n{content}")
# 2. Codex review output (if exists)
codex_output = read_file_content(repo_root, f"{task_dir}/codex-review-output.txt")
if codex_output:
context_parts.append(
f"=== {task_dir}/codex-review-output.txt (Codex Review Results) ===\n{codex_output}"
)
return "\n\n".join(context_parts)
def build_implement_prompt(original_prompt: str, context: str) -> str:
"""Build complete prompt for Implement"""
return f"""# Implement Agent Task
You are the Implement Agent in the Multi-Agent Pipeline.
## Your Context
All the information you need has been prepared for you:
{context}
---
## Your Task
{original_prompt}
---
## Workflow
1. **Understand specs** - All dev specs are injected above, understand them
2. **Understand requirements** - Read requirements document and technical design
3. **Implement feature** - Implement following specs and design
4. **Self-check** - Ensure code quality against check specs
## Important Constraints
- Do NOT execute git commit, only code modifications
- Follow all dev specs injected above
- Report list of modified/created files when done"""
def build_check_prompt(original_prompt: str, context: str) -> str:
"""Build complete prompt for Check"""
return f"""# Check Agent Task
You are the Check Agent in the Multi-Agent Pipeline (code and cross-layer checker).
## Your Context
All check specs and dev specs you need:
{context}
---
## Your Task
{original_prompt}
---
## Workflow
1. **Get changes** - Run `git diff --name-only` and `git diff` to get code changes
2. **Check against specs** - Check item by item against specs above
3. **Self-fix** - Fix issues directly, don't just report
4. **Run verification** - Run project's lint and typecheck commands
## Important Constraints
- Fix issues yourself, don't just report
- Must execute complete checklist in check specs
- Pay special attention to impact radius analysis (L1-L5)"""
def build_finish_prompt(original_prompt: str, context: str) -> str:
"""Build complete prompt for Finish (final check before PR)"""
return f"""# Finish Agent Task
You are performing the final check before creating a PR.
## Your Context
Finish checklist and requirements:
{context}
---
## Your Task
{original_prompt}
---
## Workflow
1. **Review changes** - Run `git diff --name-only` to see all changed files
2. **Verify requirements** - Check each requirement in prd.md is implemented
3. **Spec sync** - Analyze whether changes introduce new patterns, contracts, or conventions
- If new pattern/convention found: read target spec file → update it → update index.md if needed
- If infra/cross-layer change: follow the 7-section mandatory template from update-spec.md
- If pure code fix with no new patterns: skip this step
4. **Run final checks** - Execute lint and typecheck
5. **Confirm ready** - Ensure code is ready for PR
## Important Constraints
- You MAY update spec files when gaps are detected (use update-spec.md as guide)
- MUST read the target spec file BEFORE editing (avoid duplicating existing content)
- Do NOT update specs for trivial changes (typos, formatting, obvious fixes)
- If critical CODE issues found, report them clearly (fix specs, not code)
- Verify all acceptance criteria in prd.md are met"""
def build_debug_prompt(original_prompt: str, context: str) -> str:
"""Build complete prompt for Debug"""
return f"""# Debug Agent Task
You are the Debug Agent in the Multi-Agent Pipeline (issue fixer).
## Your Context
Dev specs and Codex Review results:
{context}
---
## Your Task
{original_prompt}
---
## Workflow
1. **Understand issues** - Analyze issues pointed out in Codex Review
2. **Locate code** - Find positions that need fixing
3. **Fix against specs** - Fix issues following dev specs
4. **Verify fixes** - Run typecheck to ensure no new issues
## Important Constraints
- Do NOT execute git commit, only code modifications
- Run typecheck after each fix to verify
- Report which issues were fixed and which files were modified"""
def get_research_context(repo_root: str, task_dir: str | None) -> str:
"""
Context for Research Agent
Research doesn't need much preset context, only needs:
1. Project structure overview (where spec directories are)
2. Optional research.jsonl (if there are specific search needs)
"""
context_parts = []
# 1. Project structure overview (dynamically discover spec directories)
spec_path = f"{DIR_WORKFLOW}/{DIR_SPEC}"
spec_root = Path(repo_root) / DIR_WORKFLOW / DIR_SPEC
# Build spec tree dynamically
tree_lines = [f"{spec_path}/"]
if spec_root.is_dir():
pkg_dirs = sorted(d for d in spec_root.iterdir() if d.is_dir())
for i, pkg_dir in enumerate(pkg_dirs):
is_last = i == len(pkg_dirs) - 1
prefix = "└── " if is_last else "├── "
layers = sorted(d.name for d in pkg_dir.iterdir() if d.is_dir())
layer_info = f" ({', '.join(layers)})" if layers else ""
tree_lines.append(f"{prefix}{pkg_dir.name}/{layer_info}")
spec_tree = "\n".join(tree_lines)
project_structure = f"""## Project Spec Directory Structure
```
{spec_tree}
```
To get structured package info, run: `python3 ./{DIR_WORKFLOW}/scripts/get_context.py --mode packages`
## Search Tips
- Spec files: `{spec_path}/**/*.md`
- Code search: Use Glob and Grep tools
- Tech solutions: Use mcp__exa__web_search_exa or mcp__exa__get_code_context_exa"""
context_parts.append(project_structure)
# 2. If task directory exists, try reading research.jsonl (optional)
if task_dir:
research_entries = read_jsonl_entries(repo_root, f"{task_dir}/research.jsonl")
if research_entries:
context_parts.append(
"\n## Additional Search Context (from research.jsonl)\n"
)
for file_path, content in research_entries:
context_parts.append(f"=== {file_path} ===\n{content}")
return "\n\n".join(context_parts)
def build_research_prompt(original_prompt: str, context: str) -> str:
"""Build complete prompt for Research"""
return f"""# Research Agent Task
You are the Research Agent in the Multi-Agent Pipeline (search researcher).
## Core Principle
**You do one thing: find and explain information.**
You are a documenter, not a reviewer.
## Project Info
{context}
---
## Your Task
{original_prompt}
---
## Workflow
1. **Understand query** - Determine search type (internal/external) and scope
2. **Plan search** - List search steps for complex queries
3. **Execute search** - Execute multiple independent searches in parallel
4. **Organize results** - Output structured report
## Search Tools
| Tool | Purpose |
|------|---------|
| Glob | Search by filename pattern |
| Grep | Search by content |
| Read | Read file content |
| mcp__exa__web_search_exa | External web search |
| mcp__exa__get_code_context_exa | External code/doc search |
## Strict Boundaries
**Only allowed**: Describe what exists, where it is, how it works
**Forbidden** (unless explicitly asked):
- Suggest improvements
- Criticize implementation
- Recommend refactoring
- Modify any files
## Report Format
Provide structured search results including:
- List of files found (with paths)
- Code pattern analysis (if applicable)
- Related spec documents
- External references (if any)"""
def main():
try:
input_data = json.load(sys.stdin)
except json.JSONDecodeError:
sys.exit(0)
tool_name = input_data.get("tool_name", "")
if tool_name not in ("Task", "Agent"):
sys.exit(0)
tool_input = input_data.get("tool_input", {})
subagent_type = tool_input.get("subagent_type", "")
original_prompt = tool_input.get("prompt", "")
cwd = input_data.get("cwd", os.getcwd())
# Only handle subagent types we care about
if subagent_type not in AGENTS_ALL:
sys.exit(0)
# Find repo root
repo_root = find_repo_root(cwd)
if not repo_root:
sys.exit(0)
# Get current task directory (research doesn't require it)
task_dir = get_current_task(repo_root)
# implement/check/debug need task directory
if subagent_type in AGENTS_REQUIRE_TASK:
if not task_dir:
sys.exit(0)
# Check if task directory exists
task_dir_full = os.path.join(repo_root, task_dir)
if not os.path.exists(task_dir_full):
sys.exit(0)
# Update current_phase in task.json (system-level enforcement)
update_current_phase(repo_root, task_dir, subagent_type)
# Check for [finish] marker in prompt (check agent with finish context)
is_finish_phase = "[finish]" in original_prompt.lower()
# Get context and build prompt based on subagent type
if subagent_type == AGENT_IMPLEMENT:
assert task_dir is not None # validated above
context = get_implement_context(repo_root, task_dir)
new_prompt = build_implement_prompt(original_prompt, context)
elif subagent_type == AGENT_CHECK:
assert task_dir is not None # validated above
if is_finish_phase:
# Finish phase: use finish context (lighter, focused on final verification)
context = get_finish_context(repo_root, task_dir)
new_prompt = build_finish_prompt(original_prompt, context)
else:
# Regular check phase: use check context (full specs for self-fix loop)
context = get_check_context(repo_root, task_dir)
new_prompt = build_check_prompt(original_prompt, context)
elif subagent_type == AGENT_DEBUG:
assert task_dir is not None # validated above
context = get_debug_context(repo_root, task_dir)
new_prompt = build_debug_prompt(original_prompt, context)
elif subagent_type == AGENT_RESEARCH:
# Research can work without task directory
context = get_research_context(repo_root, task_dir)
new_prompt = build_research_prompt(original_prompt, context)
else:
sys.exit(0)
if not context:
sys.exit(0)
# Return updated input with correct Claude Code PreToolUse format
output = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {**tool_input, "prompt": new_prompt},
}
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
if __name__ == "__main__":
main()
-396
View File
@@ -1,396 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ralph Loop - SubagentStop Hook for Check Agent Loop Control
Based on the Ralph Wiggum technique for autonomous agent loops.
Uses completion promises to control when the check agent can stop.
Mechanism:
- Intercepts when check subagent tries to stop (SubagentStop event)
- If verify commands configured in worktree.yaml, runs them to verify
- Otherwise, reads check.jsonl to get dynamic completion markers ({reason}_FINISH)
- Blocks stopping until verification passes or all markers found
- Has max iterations as safety limit
State file: .trellis/.ralph-state.json
- Tracks current iteration count per session
- Resets when task changes
"""
# IMPORTANT: Suppress all warnings FIRST
import warnings
warnings.filterwarnings("ignore")
import json
import os
import subprocess
import sys
from datetime import datetime
from pathlib import Path
# IMPORTANT: Force stdout to use UTF-8 on Windows
# This fixes UnicodeEncodeError when outputting non-ASCII characters
if sys.platform == "win32":
import io as _io
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
elif hasattr(sys.stdout, "detach"):
sys.stdout = _io.TextIOWrapper(sys.stdout.detach(), encoding="utf-8", errors="replace") # type: ignore[union-attr]
# =============================================================================
# Configuration
# =============================================================================
MAX_ITERATIONS = 5 # Safety limit to prevent infinite loops
STATE_TIMEOUT_MINUTES = 30 # Reset state if older than this
STATE_FILE = ".trellis/.ralph-state.json"
WORKTREE_YAML = ".trellis/worktree.yaml"
DIR_WORKFLOW = ".trellis"
FILE_CURRENT_TASK = ".current-task"
# Only control loop for check agent
TARGET_AGENT = "check"
def find_repo_root(start_path: str) -> str | None:
"""Find git repo root from start_path upwards"""
current = Path(start_path).resolve()
while current != current.parent:
if (current / ".git").exists():
return str(current)
current = current.parent
return None
def get_current_task(repo_root: str) -> str | None:
"""Read current task directory path"""
current_task_file = os.path.join(repo_root, DIR_WORKFLOW, FILE_CURRENT_TASK)
if not os.path.exists(current_task_file):
return None
try:
with open(current_task_file, "r", encoding="utf-8") as f:
content = f.read().strip()
if not content:
return None
normalized = content.replace("\\", "/")
while normalized.startswith("./"):
normalized = normalized[2:]
if normalized.startswith("tasks/"):
normalized = f".trellis/{normalized}"
return normalized
except Exception:
return None
def get_verify_commands(repo_root: str) -> list[str]:
"""
Read verify commands from worktree.yaml.
Returns list of commands to run, or empty list if not configured.
Uses simple YAML parsing without external dependencies.
"""
yaml_path = os.path.join(repo_root, WORKTREE_YAML)
if not os.path.exists(yaml_path):
return []
try:
with open(yaml_path, "r", encoding="utf-8") as f:
content = f.read()
# Simple YAML parsing for verify section
# Look for "verify:" followed by list items
lines = content.split("\n")
in_verify_section = False
commands = []
for line in lines:
stripped = line.strip()
# Check for section start
if stripped.startswith("verify:"):
in_verify_section = True
continue
# Check for new section (not indented, ends with :)
if (
not line.startswith(" ")
and not line.startswith("\t")
and stripped.endswith(":")
and stripped != ""
):
in_verify_section = False
continue
# If in verify section, look for list items
if in_verify_section:
# Skip comments and empty lines
if stripped.startswith("#") or stripped == "":
continue
# Parse list item (- command)
if stripped.startswith("- "):
cmd = stripped[2:].strip()
if cmd:
commands.append(cmd)
return commands
except Exception:
return []
def run_verify_commands(repo_root: str, commands: list[str]) -> tuple[bool, str]:
"""
Run verify commands and return (success, message).
All commands must pass for success.
"""
for cmd in commands:
try:
result = subprocess.run(
cmd,
shell=True,
cwd=repo_root,
capture_output=True,
timeout=120, # 2 minute timeout per command
)
if result.returncode != 0:
stderr = result.stderr.decode("utf-8", errors="replace")
stdout = result.stdout.decode("utf-8", errors="replace")
error_output = stderr or stdout
# Truncate long output
if len(error_output) > 500:
error_output = error_output[:500] + "..."
return False, f"Command failed: {cmd}\n{error_output}"
except subprocess.TimeoutExpired:
return False, f"Command timed out: {cmd}"
except Exception as e:
return False, f"Command error: {cmd} - {str(e)}"
return True, "All verify commands passed"
def get_completion_markers(repo_root: str, task_dir: str) -> list[str]:
"""
Read check.jsonl and generate completion markers from reasons.
Each entry's "reason" field becomes {REASON}_FINISH marker.
Example: {"file": "...", "reason": "TypeCheck"} -> "TYPECHECK_FINISH"
"""
check_jsonl_path = os.path.join(repo_root, task_dir, "check.jsonl")
markers = []
if not os.path.exists(check_jsonl_path):
# Fallback: if no check.jsonl, use default marker
return ["ALL_CHECKS_FINISH"]
try:
with open(check_jsonl_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
item = json.loads(line)
reason = item.get("reason", "")
if reason:
# Convert to uppercase and add _FINISH suffix
marker = f"{reason.upper().replace(' ', '_')}_FINISH"
if marker not in markers:
markers.append(marker)
except json.JSONDecodeError:
continue
except Exception:
pass
# If no markers found, use default
if not markers:
markers = ["ALL_CHECKS_FINISH"]
return markers
def load_state(repo_root: str) -> dict:
"""Load Ralph Loop state from file"""
state_path = os.path.join(repo_root, STATE_FILE)
if not os.path.exists(state_path):
return {"task": None, "iteration": 0, "started_at": None}
try:
with open(state_path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {"task": None, "iteration": 0, "started_at": None}
def save_state(repo_root: str, state: dict) -> None:
"""Save Ralph Loop state to file"""
state_path = os.path.join(repo_root, STATE_FILE)
try:
# Ensure directory exists
os.makedirs(os.path.dirname(state_path), exist_ok=True)
with open(state_path, "w", encoding="utf-8") as f:
json.dump(state, f, indent=2, ensure_ascii=False)
except Exception:
pass
def check_completion(agent_output: str, markers: list[str]) -> tuple[bool, list[str]]:
"""
Check if all completion markers are present in agent output.
Returns:
(all_complete, missing_markers)
"""
missing = []
for marker in markers:
if marker not in agent_output:
missing.append(marker)
return len(missing) == 0, missing
def main():
try:
input_data = json.load(sys.stdin)
except json.JSONDecodeError:
# If can't parse input, allow stop
sys.exit(0)
# Get event info
hook_event = input_data.get("hook_event_name", "")
# Only handle SubagentStop event
if hook_event != "SubagentStop":
sys.exit(0)
# Get subagent info
# Field names per Claude Code SubagentStop event schema:
# agent_type, last_assistant_message, agent_id, agent_transcript_path, cwd
# The event does NOT carry a `prompt` field, so finish-phase detection
# based on a `[finish]` marker in the user prompt is no longer possible
# here; finish-phase skip logic should be reintroduced via task.json
# state (e.g. current_phase) in a follow-up.
agent_type = input_data.get("agent_type", "")
last_assistant_message = input_data.get("last_assistant_message", "")
cwd = input_data.get("cwd", os.getcwd())
# Only control check agent
if agent_type != TARGET_AGENT:
sys.exit(0)
# Find repo root
repo_root = find_repo_root(cwd)
if not repo_root:
sys.exit(0)
# Get current task
task_dir = get_current_task(repo_root)
if not task_dir:
sys.exit(0)
# Load state
state = load_state(repo_root)
# Reset state if task changed or state is too old
should_reset = False
if state.get("task") != task_dir:
should_reset = True
elif state.get("started_at"):
try:
started = datetime.fromisoformat(state["started_at"])
if (datetime.now() - started).total_seconds() > STATE_TIMEOUT_MINUTES * 60:
should_reset = True
except (ValueError, TypeError):
should_reset = True
if should_reset:
state = {
"task": task_dir,
"iteration": 0,
"started_at": datetime.now().isoformat(),
}
# Increment iteration
state["iteration"] = state.get("iteration", 0) + 1
current_iteration = state["iteration"]
# Save state
save_state(repo_root, state)
# Safety check: max iterations
if current_iteration >= MAX_ITERATIONS:
# Allow stop, reset state for next run
state["iteration"] = 0
save_state(repo_root, state)
output = {
"decision": "allow",
"reason": f"Max iterations ({MAX_ITERATIONS}) reached. Stopping to prevent infinite loop.",
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
# Check if verify commands are configured
verify_commands = get_verify_commands(repo_root)
if verify_commands:
# Use programmatic verification
passed, message = run_verify_commands(repo_root, verify_commands)
if passed:
# All verify commands passed, allow stop
state["iteration"] = 0
save_state(repo_root, state)
output = {
"decision": "allow",
"reason": "All verify commands passed. Check phase complete.",
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
else:
# Verification failed, block stop
output = {
"decision": "block",
"reason": f"Iteration {current_iteration}/{MAX_ITERATIONS}. Verification failed:\n{message}\n\nPlease fix the issues and try again.",
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
else:
# No verify commands, fall back to completion markers
markers = get_completion_markers(repo_root, task_dir)
all_complete, missing = check_completion(last_assistant_message, markers)
if all_complete:
# All checks complete, allow stop
state["iteration"] = 0
save_state(repo_root, state)
output = {
"decision": "allow",
"reason": "All completion markers found. Check phase complete.",
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
else:
# Missing markers, block stop and continue
output = {
"decision": "block",
"reason": f"""Iteration {current_iteration}/{MAX_ITERATIONS}. Missing completion markers: {", ".join(missing)}.
IMPORTANT: You must ACTUALLY run the checks, not just output the markers.
- Did you run lint? What was the output?
- Did you run typecheck? What was the output?
- Did they actually pass with zero errors?
Only output a marker (e.g., LINT_FINISH) AFTER:
1. You have executed the corresponding command
2. The command completed with zero errors
3. You have shown the command output in your response
Do NOT output markers just to escape the loop. The loop exists to ensure quality.""",
}
print(json.dumps(output, ensure_ascii=False))
sys.exit(0)
if __name__ == "__main__":
main()
-414
View File
@@ -1,414 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Session Start Hook - Inject structured context
"""
# IMPORTANT: Suppress all warnings FIRST
import warnings
warnings.filterwarnings("ignore")
import json
import os
import subprocess
import sys
from io import StringIO
from pathlib import Path
# IMPORTANT: Force stdout to use UTF-8 on Windows
# This fixes UnicodeEncodeError when outputting non-ASCII characters
if sys.platform == "win32":
import io as _io
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore[union-attr]
elif hasattr(sys.stdout, "detach"):
sys.stdout = _io.TextIOWrapper(sys.stdout.detach(), encoding="utf-8", errors="replace") # type: ignore[union-attr]
def should_skip_injection() -> bool:
return (
os.environ.get("CLAUDE_NON_INTERACTIVE") == "1"
or os.environ.get("OPENCODE_NON_INTERACTIVE") == "1"
)
def read_file(path: Path, fallback: str = "") -> str:
try:
return path.read_text(encoding="utf-8")
except (FileNotFoundError, PermissionError):
return fallback
def run_script(script_path: Path) -> str:
try:
if script_path.suffix == ".py":
# Add PYTHONIOENCODING to force UTF-8 in subprocess
env = os.environ.copy()
env["PYTHONIOENCODING"] = "utf-8"
cmd = [sys.executable, "-W", "ignore", str(script_path)]
else:
env = os.environ
cmd = [str(script_path)]
result = subprocess.run(
cmd,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
timeout=5,
cwd=script_path.parent.parent.parent,
env=env,
)
return result.stdout if result.returncode == 0 else "No context available"
except (subprocess.TimeoutExpired, FileNotFoundError, PermissionError):
return "No context available"
def _normalize_task_ref(task_ref: str) -> str:
normalized = task_ref.strip()
if not normalized:
return ""
path_obj = Path(normalized)
if path_obj.is_absolute():
return str(path_obj)
normalized = normalized.replace("\\", "/")
while normalized.startswith("./"):
normalized = normalized[2:]
if normalized.startswith("tasks/"):
return f".trellis/{normalized}"
return normalized
def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
normalized = _normalize_task_ref(task_ref)
path_obj = Path(normalized)
if path_obj.is_absolute():
return path_obj
if normalized.startswith(".trellis/"):
return trellis_dir.parent / path_obj
return trellis_dir / "tasks" / path_obj
def _get_task_status(trellis_dir: Path) -> str:
"""Check current task status and return structured status string."""
current_task_file = trellis_dir / ".current-task"
if not current_task_file.is_file():
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
if not task_ref:
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
# Resolve task directory
task_dir = _resolve_task_dir(trellis_dir, task_ref)
if not task_dir.is_dir():
return f"Status: STALE POINTER\nTask: {task_ref}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
# Read task.json
task_json_path = task_dir / "task.json"
task_data = {}
if task_json_path.is_file():
try:
task_data = json.loads(task_json_path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, PermissionError):
pass
task_title = task_data.get("title", task_ref)
task_status = task_data.get("status", "unknown")
if task_status == "completed":
return f"Status: COMPLETED\nTask: {task_title}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
# Check if context is configured (jsonl files exist and non-empty)
has_context = False
for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
jsonl_path = task_dir / jsonl_name
if jsonl_path.is_file() and jsonl_path.stat().st_size > 0:
has_context = True
break
has_prd = (task_dir / "prd.md").is_file()
if not has_prd:
return f"Status: NOT READY\nTask: {task_title}\nMissing: prd.md not created\nNext: Write PRD, then research → init-context → start"
if not has_context:
return f"Status: NOT READY\nTask: {task_title}\nMissing: Context not configured (no jsonl files)\nNext: Complete Phase 2 (research → init-context → start) before implementing"
return f"Status: READY\nTask: {task_title}\nNext: Continue with implement or check"
def _load_trellis_config(trellis_dir: Path) -> tuple:
"""Load Trellis config for session-start decisions.
Returns:
(is_mono, packages_dict, spec_scope, task_pkg, default_pkg)
"""
scripts_dir = trellis_dir / "scripts"
if str(scripts_dir) not in sys.path:
sys.path.insert(0, str(scripts_dir))
try:
from common.config import get_default_package, get_packages, get_spec_scope, is_monorepo # type: ignore[import-not-found]
from common.paths import get_current_task # type: ignore[import-not-found]
repo_root = trellis_dir.parent
is_mono = is_monorepo(repo_root)
packages = get_packages(repo_root) or {}
scope = get_spec_scope(repo_root)
# Get active task's package
task_pkg = None
current = get_current_task(repo_root)
if current:
task_json = repo_root / current / "task.json"
if task_json.is_file():
try:
data = json.loads(task_json.read_text(encoding="utf-8"))
if isinstance(data, dict):
tp = data.get("package")
if isinstance(tp, str) and tp:
task_pkg = tp
except (json.JSONDecodeError, OSError):
pass
default_pkg = get_default_package(repo_root)
return is_mono, packages, scope, task_pkg, default_pkg
except Exception:
return False, {}, None, None, None
def _check_legacy_spec(trellis_dir: Path, is_mono: bool, packages: dict) -> str | None:
"""Check for legacy spec directory structure in monorepo.
Returns warning message if legacy structure detected, None otherwise.
"""
if not is_mono or not packages:
return None
spec_dir = trellis_dir / "spec"
if not spec_dir.is_dir():
return None
# Check for legacy flat spec dirs (spec/backend/, spec/frontend/ with index.md)
has_legacy = False
for legacy_name in ("backend", "frontend"):
legacy_dir = spec_dir / legacy_name
if legacy_dir.is_dir() and (legacy_dir / "index.md").is_file():
has_legacy = True
break
if not has_legacy:
return None
# Check which packages are missing spec/<pkg>/ directory
missing = [
name for name in sorted(packages.keys())
if not (spec_dir / name).is_dir()
]
if not missing:
return None # All packages have spec dirs
if len(missing) == len(packages):
return (
f"[!] Legacy spec structure detected: found `spec/backend/` or `spec/frontend/` "
f"but no package-scoped `spec/<package>/` directories.\n"
f"Monorepo packages: {', '.join(sorted(packages.keys()))}\n"
f"Please reorganize: `spec/backend/` -> `spec/<package>/backend/`"
)
return (
f"[!] Partial spec migration detected: packages {', '.join(missing)} "
f"still missing `spec/<pkg>/` directory.\n"
f"Please complete migration for all packages."
)
def _resolve_spec_scope(
is_mono: bool,
packages: dict,
scope,
task_pkg: str | None,
default_pkg: str | None,
) -> set | None:
"""Resolve which packages should have their specs injected.
Returns:
Set of package names to include, or None for full scan.
"""
if not is_mono or not packages:
return None # Single-repo: full scan
if scope is None:
return None # No scope configured: full scan
if isinstance(scope, str) and scope == "active_task":
if task_pkg and task_pkg in packages:
return {task_pkg}
if default_pkg and default_pkg in packages:
return {default_pkg}
return None # Fallback to full scan
if isinstance(scope, list):
valid = set()
for entry in scope:
if entry in packages:
valid.add(entry)
else:
print(
f"Warning: spec_scope contains unknown package: {entry}, ignoring",
file=sys.stderr,
)
if valid:
# Warn if active task is out of scope
if task_pkg and task_pkg not in valid:
print(
f"Warning: active task package '{task_pkg}' is out of configured spec_scope",
file=sys.stderr,
)
return valid
# All entries invalid: fallback chain
print(
"Warning: all spec_scope entries invalid, falling back to task/default/full",
file=sys.stderr,
)
if task_pkg and task_pkg in packages:
return {task_pkg}
if default_pkg and default_pkg in packages:
return {default_pkg}
return None # Full scan
return None # Unknown scope type: full scan
def _build_workflow_toc(workflow_path: Path) -> str:
"""Build a compact section index for workflow.md (lazy-load the full file on demand).
Replaces full-file injection to keep additionalContext payload small.
The full file is accessible via: Read tool on .trellis/workflow.md
"""
content = read_file(workflow_path)
if not content:
return "No workflow.md found"
toc_lines = [
"# Development Workflow — Section Index",
"Full guide: .trellis/workflow.md (read on demand)",
"",
]
for line in content.splitlines():
if line.startswith("## "):
toc_lines.append(line)
toc_lines += [
"",
"To read a section: use the Read tool on .trellis/workflow.md",
]
return "\n".join(toc_lines)
def main():
if should_skip_injection():
sys.exit(0)
project_dir = Path(os.environ.get("CLAUDE_PROJECT_DIR", ".")).resolve()
trellis_dir = project_dir / ".trellis"
# Load config for scope filtering and legacy detection
is_mono, packages, scope_config, task_pkg, default_pkg = _load_trellis_config(trellis_dir)
allowed_pkgs = _resolve_spec_scope(is_mono, packages, scope_config, task_pkg, default_pkg)
output = StringIO()
output.write("""<session-context>
You are starting a new session in a Trellis-managed project.
Read and follow all instructions below carefully.
</session-context>
""")
# Legacy migration warning
legacy_warning = _check_legacy_spec(trellis_dir, is_mono, packages)
if legacy_warning:
output.write(f"<migration-warning>\n{legacy_warning}\n</migration-warning>\n\n")
output.write("<current-state>\n")
context_script = trellis_dir / "scripts" / "get_context.py"
output.write(run_script(context_script))
output.write("\n</current-state>\n\n")
output.write("<workflow>\n")
output.write(_build_workflow_toc(trellis_dir / "workflow.md"))
output.write("\n</workflow>\n\n")
output.write("<guidelines>\n")
output.write("**Note**: The guidelines below are index files — they list available guideline documents and their locations.\n")
output.write("During actual development, you MUST read the specific guideline files listed in each index's Pre-Development Checklist.\n\n")
spec_dir = trellis_dir / "spec"
if spec_dir.is_dir():
for sub in sorted(spec_dir.iterdir()):
if not sub.is_dir() or sub.name.startswith("."):
continue
# Always include guides/ regardless of scope
if sub.name == "guides":
index_file = sub / "index.md"
if index_file.is_file():
output.write(f"## {sub.name}\n")
output.write(read_file(index_file))
output.write("\n\n")
continue
index_file = sub / "index.md"
if index_file.is_file():
# Flat spec dir (single-repo layer like spec/backend/)
output.write(f"## {sub.name}\n")
output.write(read_file(index_file))
output.write("\n\n")
else:
# Nested package dirs (monorepo: spec/<pkg>/<layer>/index.md)
# Apply scope filter
if allowed_pkgs is not None and sub.name not in allowed_pkgs:
continue
for nested in sorted(sub.iterdir()):
if not nested.is_dir():
continue
nested_index = nested / "index.md"
if nested_index.is_file():
output.write(f"## {sub.name}/{nested.name}\n")
output.write(read_file(nested_index))
output.write("\n\n")
output.write("</guidelines>\n\n")
# Check task status and inject structured tag
task_status = _get_task_status(trellis_dir)
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
output.write("""<ready>
Context loaded. Workflow index, project state, and guidelines are already injected above — do NOT re-read them.
Wait for the user's first message, then handle it following the workflow guide.
If there is an active task, ask whether to continue it.
</ready>""")
result = {
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": output.getvalue(),
}
}
# Output JSON - stdout is already configured for UTF-8
print(json.dumps(result, ensure_ascii=False), flush=True)
if __name__ == "__main__":
main()
-218
View File
@@ -1,218 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Trellis StatusLine — project-level status display for Claude Code.
Reads Claude Code session JSON from stdin + Trellis task data from filesystem.
Outputs 1-2 lines:
With active task: [P1] Task title (status) + info line
Without task: info line only
Info line: model · ctx% · branch · duration · developer · tasks · rate limits
"""
from __future__ import annotations
import io
import json
import re
import subprocess
import sys
from pathlib import Path
# Fix: Windows Python defaults to GBK encoding, which corrupts UTF-8
# characters like the middle dot (·). Wrap stdout/stderr with UTF-8.
if sys.platform == "win32":
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding="utf-8")
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding="utf-8")
def _read_text(path: Path) -> str:
try:
return path.read_text(encoding="utf-8").strip()
except (FileNotFoundError, PermissionError, OSError):
return ""
def _read_json(path: Path) -> dict:
text = _read_text(path)
if not text:
return {}
try:
return json.loads(text)
except (json.JSONDecodeError, ValueError):
return {}
def _normalize_task_ref(task_ref: str) -> str:
normalized = task_ref.strip()
if not normalized:
return ""
path_obj = Path(normalized)
if path_obj.is_absolute():
return str(path_obj)
normalized = normalized.replace("\\", "/")
while normalized.startswith("./"):
normalized = normalized[2:]
if normalized.startswith("tasks/"):
return f".trellis/{normalized}"
return normalized
def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
normalized = _normalize_task_ref(task_ref)
path_obj = Path(normalized)
if path_obj.is_absolute():
return path_obj
if normalized.startswith(".trellis/"):
return trellis_dir.parent / path_obj
return trellis_dir / "tasks" / path_obj
def _find_trellis_dir() -> Path | None:
"""Walk up from cwd to find .trellis/ directory."""
current = Path.cwd()
for parent in [current, *current.parents]:
candidate = parent / ".trellis"
if candidate.is_dir():
return candidate
return None
def _get_current_task(trellis_dir: Path) -> dict | None:
"""Load current task info. Returns dict with title/status/priority or None."""
task_ref = _normalize_task_ref(_read_text(trellis_dir / ".current-task"))
if not task_ref:
return None
# Resolve task directory
task_path = _resolve_task_dir(trellis_dir, task_ref)
task_data = _read_json(task_path / "task.json")
if not task_data:
return None
return {
"title": task_data.get("title") or task_data.get("name") or "unknown",
"status": task_data.get("status", "unknown"),
"priority": task_data.get("priority", "P2"),
}
def _count_active_tasks(trellis_dir: Path) -> int:
"""Count non-archived task directories with valid task.json."""
tasks_dir = trellis_dir / "tasks"
if not tasks_dir.is_dir():
return 0
count = 0
for d in tasks_dir.iterdir():
if d.is_dir() and d.name != "archive" and (d / "task.json").is_file():
count += 1
return count
def _get_developer(trellis_dir: Path) -> str:
content = _read_text(trellis_dir / ".developer")
if not content:
return "unknown"
for line in content.splitlines():
if line.startswith("name="):
return line[5:].strip()
return content.splitlines()[0].strip() or "unknown"
def _get_git_branch() -> str:
try:
result = subprocess.run(
["git", "branch", "--show-current"],
capture_output=True, text=True, timeout=3,
)
return result.stdout.strip() if result.returncode == 0 else ""
except (FileNotFoundError, subprocess.TimeoutExpired):
return ""
def _format_ctx_size(size: int) -> str:
if size >= 1_000_000:
return f"{size // 1_000_000}M"
if size >= 1_000:
return f"{size // 1_000}K"
return str(size)
def _format_duration(ms: int) -> str:
secs = ms // 1000
hours, remainder = divmod(secs, 3600)
mins = remainder // 60
if hours > 0:
return f"{hours}h{mins}m"
return f"{mins}m"
def main() -> None:
# Read Claude Code session JSON from stdin
try:
cc_data = json.loads(sys.stdin.read())
except (json.JSONDecodeError, ValueError):
cc_data = {}
trellis_dir = _find_trellis_dir()
SEP = " \033[90m·\033[0m "
# --- Trellis data ---
task = _get_current_task(trellis_dir) if trellis_dir else None
dev = _get_developer(trellis_dir) if trellis_dir else ""
task_count = _count_active_tasks(trellis_dir) if trellis_dir else 0
# --- CC session data ---
model = cc_data.get("model", {}).get("display_name", "?")
ctx_pct = int(cc_data.get("context_window", {}).get("used_percentage") or 0)
ctx_size = _format_ctx_size(cc_data.get("context_window", {}).get("context_window_size") or 0)
duration = _format_duration(cc_data.get("cost", {}).get("total_duration_ms") or 0)
branch = _get_git_branch()
# Avoid "Opus 4.6 (1M context) (1M)"
if re.search(r"\d+[KMG]\b", model, re.IGNORECASE):
model_label = model
else:
model_label = f"{model} ({ctx_size})"
# Context % with color
if ctx_pct >= 90:
ctx_color = "\033[31m"
elif ctx_pct >= 70:
ctx_color = "\033[33m"
else:
ctx_color = "\033[32m"
# Build info line: model · ctx · branch · duration · dev · tasks [· rate limits]
parts = [
model_label,
f"ctx {ctx_color}{ctx_pct}%\033[0m",
]
if branch:
parts.append(f"\033[35m{branch}\033[0m")
parts.append(duration)
if dev:
parts.append(f"\033[32m{dev}\033[0m")
if task_count:
parts.append(f"{task_count} task(s)")
five_hr = cc_data.get("rate_limits", {}).get("five_hour", {}).get("used_percentage")
if five_hr is not None:
parts.append(f"5h {int(five_hr)}%")
seven_day = cc_data.get("rate_limits", {}).get("seven_day", {}).get("used_percentage")
if seven_day is not None:
parts.append(f"7d {int(seven_day)}%")
info_line = SEP.join(parts)
# Output: task line (only if active) + info line
if task:
print(f"\033[36m[{task['priority']}]\033[0m {task['title']} \033[33m({task['status']})\033[0m")
print(info_line)
if __name__ == "__main__":
main()
-77
View File
@@ -1,77 +0,0 @@
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/session-start.py",
"timeout": 10
}
]
},
{
"matcher": "clear",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/session-start.py",
"timeout": 10
}
]
},
{
"matcher": "compact",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/session-start.py",
"timeout": 10
}
]
}
],
"PreToolUse": [
{
"matcher": "Task",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/inject-subagent-context.py",
"timeout": 30
}
]
},
{
"matcher": "Agent",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/inject-subagent-context.py",
"timeout": 30
}
]
}
],
"SubagentStop": [
{
"matcher": "check",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/ralph-loop.py",
"timeout": 10
}
]
}
]
},
"statusLine": {
"type": "command",
"command": "python3 .claude/hooks/statusline.py"
},
"enabledPlugins": {
"claude-mem@thedotmack": true
}
}