@jahanxu/trellis 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/configurators/workflow.d.ts.map +1 -1
  2. package/dist/configurators/workflow.js +58 -1
  3. package/dist/configurators/workflow.js.map +1 -1
  4. package/dist/constants/paths.d.ts +17 -0
  5. package/dist/constants/paths.d.ts.map +1 -1
  6. package/dist/constants/paths.js +19 -0
  7. package/dist/constants/paths.js.map +1 -1
  8. package/dist/templates/claude/commands/trellis/handoff.md +90 -387
  9. package/dist/templates/claude/commands/trellis/pick-task.md +74 -444
  10. package/dist/templates/claude/hooks/inject-subagent-context.py +17 -101
  11. package/dist/templates/claude/hooks/ralph-loop.py +1 -0
  12. package/dist/templates/claude/hooks/session-start.py +170 -54
  13. package/dist/templates/iflow/commands/trellis/handoff.md +148 -0
  14. package/dist/templates/iflow/commands/trellis/pick-task.md +145 -0
  15. package/dist/templates/iflow/hooks/inject-subagent-context.py +1 -0
  16. package/dist/templates/iflow/hooks/ralph-loop.py +1 -0
  17. package/dist/templates/iflow/hooks/session-start.py +171 -0
  18. package/dist/templates/markdown/index.d.ts +9 -0
  19. package/dist/templates/markdown/index.d.ts.map +1 -1
  20. package/dist/templates/markdown/index.js +10 -0
  21. package/dist/templates/markdown/index.js.map +1 -1
  22. package/dist/templates/markdown/spec/roles/designer/index.md.txt +57 -0
  23. package/dist/templates/markdown/spec/roles/designer/mock-data-standards.md.txt +63 -0
  24. package/dist/templates/markdown/spec/roles/designer/prototype-guidelines.md.txt +49 -0
  25. package/dist/templates/markdown/spec/roles/frontend-impl/api-integration.md.txt +63 -0
  26. package/dist/templates/markdown/spec/roles/frontend-impl/index.md.txt +57 -0
  27. package/dist/templates/markdown/spec/roles/frontend-impl/prototype-to-production.md.txt +57 -0
  28. package/dist/templates/markdown/spec/roles/pm/index.md.txt +45 -0
  29. package/dist/templates/markdown/spec/roles/pm/prd-template.md.txt +64 -0
  30. package/dist/templates/markdown/spec/roles/pm/requirement-checklist.md.txt +43 -0
  31. package/dist/templates/trellis/index.d.ts +1 -0
  32. package/dist/templates/trellis/index.d.ts.map +1 -1
  33. package/dist/templates/trellis/index.js +2 -0
  34. package/dist/templates/trellis/index.js.map +1 -1
  35. package/dist/templates/trellis/scripts/add_session.py +3 -2
  36. package/dist/templates/trellis/scripts/common/cli_adapter.py +4 -3
  37. package/dist/templates/trellis/scripts/common/developer.py +4 -3
  38. package/dist/templates/trellis/scripts/common/git_context.py +7 -7
  39. package/dist/templates/trellis/scripts/common/paths.py +64 -14
  40. package/dist/templates/trellis/scripts/common/phase.py +2 -2
  41. package/dist/templates/trellis/scripts/common/registry.py +16 -15
  42. package/dist/templates/trellis/scripts/common/task_queue.py +10 -10
  43. package/dist/templates/trellis/scripts/common/task_utils.py +5 -4
  44. package/dist/templates/trellis/scripts/common/worktree.py +8 -7
  45. package/dist/templates/trellis/scripts/pool.py +214 -265
  46. package/dist/templates/trellis/scripts/task.py +3 -116
  47. package/package.json +3 -3
  48. package/dist/templates/claude/commands/trellis/before-role-work.md +0 -364
  49. package/dist/templates/trellis/VERSION +0 -1
  50. package/dist/templates/trellis/deliverables/README.md +0 -51
  51. package/dist/templates/trellis/paths.README.md +0 -277
  52. package/dist/templates/trellis/paths.yaml +0 -41
  53. package/dist/templates/trellis/pool/implementations.json +0 -5
  54. package/dist/templates/trellis/pool/prototypes.json +0 -5
  55. package/dist/templates/trellis/pool/requirements.json +0 -5
  56. package/dist/templates/trellis/scripts/common/project_paths.py +0 -189
  57. package/dist/templates/trellis/scripts/handoff_generator.py +0 -380
  58. package/dist/templates/trellis/spec/roles/designer/index.md +0 -243
  59. package/dist/templates/trellis/spec/roles/designer/mock-data-standards.md +0 -481
  60. package/dist/templates/trellis/spec/roles/designer/prototype-guidelines.md +0 -429
  61. package/dist/templates/trellis/spec/roles/frontend-impl/api-integration.md +0 -565
  62. package/dist/templates/trellis/spec/roles/frontend-impl/index.md +0 -321
  63. package/dist/templates/trellis/spec/roles/frontend-impl/state-management.md +0 -599
  64. package/dist/templates/trellis/spec/roles/pm/index.md +0 -112
  65. package/dist/templates/trellis/spec/roles/pm/prd-template.md +0 -124
@@ -0,0 +1,57 @@
1
+ # Frontend Implementation Role Guidelines
2
+
3
+ > Standards for converting prototypes to production code.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ This directory contains guidelines for the Frontend Implementation role in the three-role collaboration pipeline. Fill in each file with your project's specific conventions.
10
+
11
+ ---
12
+
13
+ ## Guidelines Index
14
+
15
+ | Guide | Description | Status |
16
+ |-------|-------------|--------|
17
+ | [API Integration](./api-integration.md) | How to replace mock data with real APIs | To fill |
18
+ | [Prototype to Production](./prototype-to-production.md) | Checklist for converting prototypes | To fill |
19
+
20
+ ---
21
+
22
+ ## Workflow
23
+
24
+ 1. Pick a prototype from the pool: `/trellis:pick-task prototypes <id>`
25
+ 2. Read the upstream HANDOFF.md carefully - it lists all TODOs
26
+ 3. Replace mock data with real API calls
27
+ 4. Add error handling, loading states, and edge case handling
28
+ 5. Write tests for critical paths
29
+ 6. Run `/trellis:handoff` to complete
30
+
31
+ ---
32
+
33
+ ## Output Directory
34
+
35
+ Production code goes directly into the project source tree (e.g., `src/features/<feature>/`).
36
+
37
+ A copy or reference is also placed in: `deliverables/production/<feature-id>/`
38
+
39
+ ---
40
+
41
+ ## Key Principle
42
+
43
+ > **Preserve the prototype's UX, replace the data layer.**
44
+ >
45
+ > The Designer's prototype defines the look and interaction.
46
+ > Your job is to make it work with real data and handle all edge cases.
47
+
48
+ ---
49
+
50
+ ## Also Read
51
+
52
+ - `spec/frontend/` - Project frontend conventions (components, hooks, state management)
53
+ - `spec/backend/` - API conventions (if applicable)
54
+
55
+ ---
56
+
57
+ **Language**: All documentation should be written in **English**.
@@ -0,0 +1,57 @@
1
+ # Prototype to Production Checklist
2
+
3
+ > Step-by-step checklist for converting a Designer's prototype to production code.
4
+
5
+ ---
6
+
7
+ ## Pre-Implementation
8
+
9
+ - [ ] Read HANDOFF.md thoroughly - note all "Logic for Frontend to Implement" items
10
+ - [ ] Identify all mock data locations (search for `// TODO:`, `// Mock:`, `mock` prefix)
11
+ - [ ] Review prototype component structure - decide what to keep vs refactor
12
+ - [ ] Check if prototype components follow project conventions (if not, note adjustments)
13
+
14
+ ## Data Layer
15
+
16
+ - [ ] Replace all mock data with API calls or store connections
17
+ - [ ] Add proper TypeScript types for API responses
18
+ - [ ] Implement data fetching hooks (or use existing patterns)
19
+ - [ ] Add caching strategy if needed (React Query, SWR, etc.)
20
+
21
+ ## Error Handling
22
+
23
+ - [ ] Add error boundaries for component-level errors
24
+ - [ ] Handle API errors with user-friendly messages
25
+ - [ ] Implement retry logic for transient failures
26
+ - [ ] Add fallback UI for error states
27
+
28
+ ## State Management
29
+
30
+ - [ ] Connect to global state (auth, theme, etc.) as needed
31
+ - [ ] Implement form state management
32
+ - [ ] Handle optimistic updates if applicable
33
+ - [ ] Clean up state on unmount
34
+
35
+ ## UX Polish
36
+
37
+ - [ ] Loading skeletons for async content
38
+ - [ ] Smooth transitions between states
39
+ - [ ] Keyboard navigation works correctly
40
+ - [ ] Focus management for modals/dialogs
41
+
42
+ ## Testing
43
+
44
+ - [ ] Unit tests for business logic
45
+ - [ ] Integration tests for API interactions
46
+ - [ ] Accessibility testing (screen reader, keyboard-only)
47
+
48
+ ## Final Check
49
+
50
+ - [ ] All TODO comments from prototype are resolved
51
+ - [ ] No mock data remains in production code
52
+ - [ ] Lint and type check pass
53
+ - [ ] Visual diff with prototype (should look identical)
54
+
55
+ ---
56
+
57
+ **Language**: All documentation should be written in **English**.
@@ -0,0 +1,45 @@
1
+ # PM (Product Manager) Role Guidelines
2
+
3
+ > Standards for product requirements and feature specification.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ This directory contains guidelines for the PM role in the three-role collaboration pipeline. Fill in each file with your project's specific conventions.
10
+
11
+ ---
12
+
13
+ ## Guidelines Index
14
+
15
+ | Guide | Description | Status |
16
+ |-------|-------------|--------|
17
+ | [PRD Template](./prd-template.md) | Standard PRD structure and content requirements | To fill |
18
+ | [Requirement Checklist](./requirement-checklist.md) | Quality checklist before handoff | To fill |
19
+
20
+ ---
21
+
22
+ ## Workflow
23
+
24
+ 1. Create a task with `/trellis:start`
25
+ 2. Write PRD and supporting documents in `deliverables/requirements/<feature-id>/`
26
+ 3. Run `/trellis:handoff` to generate HANDOFF.md and add to pool
27
+ 4. Downstream Designer picks from the `requirements` pool
28
+
29
+ ---
30
+
31
+ ## Output Directory
32
+
33
+ All PM deliverables go to: `deliverables/requirements/<feature-id>/`
34
+
35
+ Required files:
36
+ - `prd.md` - Product requirements document
37
+
38
+ Optional files:
39
+ - `user-stories.md` - Detailed user stories
40
+ - `wireframes/` - Low-fidelity wireframes
41
+ - `acceptance-criteria.md` - Detailed acceptance criteria
42
+
43
+ ---
44
+
45
+ **Language**: All documentation should be written in **English**.
@@ -0,0 +1,64 @@
1
+ # PRD Template
2
+
3
+ > Standard structure for Product Requirements Documents.
4
+
5
+ ---
6
+
7
+ ## Template
8
+
9
+ ```markdown
10
+ # Feature: {Feature Name}
11
+
12
+ ## Background
13
+ Why this feature is needed. Business context and user pain points.
14
+
15
+ ## Goals
16
+ - Primary goal
17
+ - Secondary goals
18
+
19
+ ## User Stories
20
+ As a [user type], I want to [action] so that [benefit].
21
+
22
+ ## Requirements
23
+
24
+ ### Functional Requirements
25
+ 1. ...
26
+ 2. ...
27
+
28
+ ### Non-Functional Requirements
29
+ - Performance: ...
30
+ - Security: ...
31
+ - Accessibility: ...
32
+
33
+ ## UI/UX Requirements
34
+ - Layout description
35
+ - Key interactions
36
+ - Error states
37
+
38
+ ## API Requirements (if applicable)
39
+ - Endpoints needed
40
+ - Data format expectations
41
+
42
+ ## Acceptance Criteria
43
+ - [ ] Criterion 1
44
+ - [ ] Criterion 2
45
+
46
+ ## Out of Scope
47
+ - Items explicitly excluded from this feature
48
+
49
+ ## Open Questions
50
+ - Questions that need resolution
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Guidelines
56
+
57
+ 1. **Be specific**: Avoid vague language like "should be fast" - specify measurable criteria
58
+ 2. **Include edge cases**: Document what happens with empty data, errors, permission issues
59
+ 3. **Reference designs**: Link to Figma/mockups when available
60
+ 4. **Scope clearly**: Explicitly state what is NOT included
61
+
62
+ ---
63
+
64
+ **Language**: All documentation should be written in **English**.
@@ -0,0 +1,43 @@
1
+ # Requirement Checklist
2
+
3
+ > Quality checklist before handing off requirements to the Designer.
4
+
5
+ ---
6
+
7
+ ## Pre-Handoff Checklist
8
+
9
+ ### Completeness
10
+ - [ ] All user stories are written with clear acceptance criteria
11
+ - [ ] Edge cases are documented (empty states, error states, loading states)
12
+ - [ ] UI/UX requirements include layout descriptions and key interactions
13
+ - [ ] API requirements are specified (if applicable)
14
+ - [ ] Non-functional requirements are defined (performance, security, accessibility)
15
+
16
+ ### Clarity
17
+ - [ ] No ambiguous language (e.g., "fast", "nice", "user-friendly" without metrics)
18
+ - [ ] Technical constraints are explicitly stated
19
+ - [ ] Out-of-scope items are listed
20
+ - [ ] Open questions are resolved or explicitly deferred
21
+
22
+ ### Consistency
23
+ - [ ] Feature aligns with existing product patterns
24
+ - [ ] Naming conventions match existing features
25
+ - [ ] No contradictions between requirements sections
26
+
27
+ ### Downstream Readiness
28
+ - [ ] Designer can start prototyping without needing clarification meetings
29
+ - [ ] All referenced resources (Figma links, API docs) are accessible
30
+ - [ ] Priority and scope are clear
31
+
32
+ ---
33
+
34
+ ## Common Issues to Avoid
35
+
36
+ 1. **Missing error states**: Every user action should have a defined failure path
37
+ 2. **Implicit assumptions**: State all assumptions explicitly
38
+ 3. **Feature creep**: Keep scope tight - add "future considerations" for nice-to-haves
39
+ 4. **Missing data requirements**: Specify what data the UI needs and where it comes from
40
+
41
+ ---
42
+
43
+ **Language**: All documentation should be written in **English**.
@@ -39,6 +39,7 @@ export declare const taskScript: string;
39
39
  export declare const getContextScript: string;
40
40
  export declare const addSessionScript: string;
41
41
  export declare const createBootstrapScript: string;
42
+ export declare const poolScript: string;
42
43
  export declare const workflowMdTemplate: string;
43
44
  export declare const worktreeYamlTemplate: string;
44
45
  export declare const gitignoreTemplate: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,cAAc,QAA6C,CAAC;AACzE,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,cAAc,QAA6C,CAAC;AACzE,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,cAAc,QAAkD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,kBAAkB,QAAmD,CAAC;AACnF,eAAO,MAAM,cAAc,QAA8C,CAAC;AAG1E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,qBAAqB,QAA8C,CAAC;AAGjF,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,oBAAoB,QAAgC,CAAC;AAClE,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAmCnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,cAAc,QAA6C,CAAC;AACzE,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,cAAc,QAA6C,CAAC;AACzE,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,cAAc,QAAkD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,kBAAkB,QAE9B,CAAC;AACF,eAAO,MAAM,cAAc,QAA8C,CAAC;AAG1E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,UAAU,QAAkC,CAAC;AAG1D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,oBAAoB,QAAgC,CAAC;AAClE,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoCnD"}
@@ -51,6 +51,7 @@ export const taskScript = readTemplate("scripts/task.py");
51
51
  export const getContextScript = readTemplate("scripts/get_context.py");
52
52
  export const addSessionScript = readTemplate("scripts/add_session.py");
53
53
  export const createBootstrapScript = readTemplate("scripts/create_bootstrap.py");
54
+ export const poolScript = readTemplate("scripts/pool.py");
54
55
  // Configuration files
55
56
  export const workflowMdTemplate = readTemplate("workflow.md");
56
57
  export const worktreeYamlTemplate = readTemplate("worktree.yaml");
@@ -87,6 +88,7 @@ export function getAllScripts() {
87
88
  scripts.set("get_context.py", getContextScript);
88
89
  scripts.set("add_session.py", addSessionScript);
89
90
  scripts.set("create_bootstrap.py", createBootstrapScript);
91
+ scripts.set("pool.py", poolScript);
90
92
  return scripts;
91
93
  }
92
94
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ Usage:
8
8
  echo "content" | python3 add_session.py --title "Title" --commit "hash"
9
9
  """
10
10
 
11
+ from __future__ import annotations
11
12
 
12
13
  import sys
13
14
 
@@ -42,13 +43,13 @@ MAX_LINES = 2000
42
43
  # Helper Functions
43
44
  # =============================================================================
44
45
 
45
- def get_latest_journal_info(dev_dir: Path) -> tuple[Optional[Path], int, int]:
46
+ def get_latest_journal_info(dev_dir: Path) -> tuple[Path | None, int, int]:
46
47
  """Get latest journal file info.
47
48
 
48
49
  Returns:
49
50
  Tuple of (file_path, file_number, line_count).
50
51
  """
51
- latest_file: Optional[Path] = None
52
+ latest_file: Path | None = None
52
53
  latest_num = -1
53
54
 
54
55
  for f in dev_dir.glob(f"{FILE_JOURNAL_PREFIX}*.md"):
@@ -25,6 +25,7 @@ Usage:
25
25
  )
26
26
  """
27
27
 
28
+ from __future__ import annotations
28
29
 
29
30
  from dataclasses import dataclass
30
31
  from pathlib import Path
@@ -215,7 +216,7 @@ class CLIAdapter:
215
216
  self,
216
217
  agent: str,
217
218
  prompt: str,
218
- session_id: Optional[str] = None,
219
+ session_id: str | None = None,
219
220
  skip_permissions: bool = True,
220
221
  verbose: bool = True,
221
222
  json_output: bool = True,
@@ -311,7 +312,7 @@ class CLIAdapter:
311
312
  else:
312
313
  return ["claude", "--resume", session_id]
313
314
 
314
- def get_resume_command_str(self, session_id: str, cwd: Optional[str] = None) -> str:
315
+ def get_resume_command_str(self, session_id: str, cwd: str | None = None) -> str:
315
316
  """Get human-readable resume command string.
316
317
 
317
318
  Args:
@@ -388,7 +389,7 @@ class CLIAdapter:
388
389
  """
389
390
  return self.platform == "claude"
390
391
 
391
- def extract_session_id_from_log(self, log_content: str) -> Optional[str]:
392
+ def extract_session_id_from_log(self, log_content: str) -> str | None:
392
393
  """Extract session ID from log output (OpenCode only).
393
394
 
394
395
  OpenCode generates session IDs in format: ses_xxx
@@ -8,6 +8,7 @@ Provides:
8
8
  show_developer_info - Show developer information
9
9
  """
10
10
 
11
+ from __future__ import annotations
11
12
 
12
13
  import sys
13
14
  from datetime import datetime
@@ -29,7 +30,7 @@ from .paths import (
29
30
  # Developer Initialization
30
31
  # =============================================================================
31
32
 
32
- def init_developer(name: str, repo_root: Optional[Path] = None) -> bool:
33
+ def init_developer(name: str, repo_root: Path | None = None) -> bool:
33
34
  """Initialize developer.
34
35
 
35
36
  Creates:
@@ -147,7 +148,7 @@ def init_developer(name: str, repo_root: Optional[Path] = None) -> bool:
147
148
  return True
148
149
 
149
150
 
150
- def ensure_developer(repo_root: Optional[Path] = None) -> None:
151
+ def ensure_developer(repo_root: Path | None = None) -> None:
151
152
  """Ensure developer is initialized, exit if not.
152
153
 
153
154
  Args:
@@ -162,7 +163,7 @@ def ensure_developer(repo_root: Optional[Path] = None) -> None:
162
163
  sys.exit(1)
163
164
 
164
165
 
165
- def show_developer_info(repo_root: Optional[Path] = None) -> None:
166
+ def show_developer_info(repo_root: Path | None = None) -> None:
166
167
  """Show developer information.
167
168
 
168
169
  Args:
@@ -8,6 +8,7 @@ Provides:
8
8
  output_text - Output context in text format
9
9
  """
10
10
 
11
+ from __future__ import annotations
11
12
 
12
13
  import sys
13
14
 
@@ -23,7 +24,6 @@ if sys.platform == "win32":
23
24
  import json
24
25
  import subprocess
25
26
  from pathlib import Path
26
- from typing import Optional
27
27
 
28
28
  from .paths import (
29
29
  DIR_SCRIPTS,
@@ -45,7 +45,7 @@ from .paths import (
45
45
  # =============================================================================
46
46
 
47
47
 
48
- def _run_git_command(args: list[str], cwd: Optional[Path] = None) -> tuple[int, str, str]:
48
+ def _run_git_command(args: list[str], cwd: Path | None = None) -> tuple[int, str, str]:
49
49
  """Run a git command and return (returncode, stdout, stderr).
50
50
 
51
51
  Uses UTF-8 encoding with -c i18n.logOutputEncoding=UTF-8 to ensure
@@ -67,7 +67,7 @@ def _run_git_command(args: list[str], cwd: Optional[Path] = None) -> tuple[int,
67
67
  return 1, "", str(e)
68
68
 
69
69
 
70
- def _read_json_file(path: Path) -> Optional[dict]:
70
+ def _read_json_file(path: Path) -> dict | None:
71
71
  """Read and parse a JSON file."""
72
72
  try:
73
73
  return json.loads(path.read_text(encoding="utf-8"))
@@ -80,7 +80,7 @@ def _read_json_file(path: Path) -> Optional[dict]:
80
80
  # =============================================================================
81
81
 
82
82
 
83
- def get_context_json(repo_root: Optional[Path] = None) -> dict:
83
+ def get_context_json(repo_root: Path | None = None) -> dict:
84
84
  """Get context as a dictionary.
85
85
 
86
86
  Args:
@@ -160,7 +160,7 @@ def get_context_json(repo_root: Optional[Path] = None) -> dict:
160
160
  }
161
161
 
162
162
 
163
- def output_json(repo_root: Optional[Path] = None) -> None:
163
+ def output_json(repo_root: Path | None = None) -> None:
164
164
  """Output context in JSON format.
165
165
 
166
166
  Args:
@@ -175,7 +175,7 @@ def output_json(repo_root: Optional[Path] = None) -> None:
175
175
  # =============================================================================
176
176
 
177
177
 
178
- def get_context_text(repo_root: Optional[Path] = None) -> str:
178
+ def get_context_text(repo_root: Path | None = None) -> str:
179
179
  """Get context as formatted text.
180
180
 
181
181
  Args:
@@ -345,7 +345,7 @@ def get_context_text(repo_root: Optional[Path] = None) -> str:
345
345
  return "\n".join(lines)
346
346
 
347
347
 
348
- def output_text(repo_root: Optional[Path] = None) -> None:
348
+ def output_text(repo_root: Path | None = None) -> None:
349
349
  """Output context in text format.
350
350
 
351
351
  Args:
@@ -10,10 +10,11 @@ Provides:
10
10
  get_active_journal_file - Get current journal file
11
11
  """
12
12
 
13
+ from __future__ import annotations
14
+
13
15
  import re
14
16
  from datetime import datetime
15
17
  from pathlib import Path
16
- from typing import Optional
17
18
 
18
19
 
19
20
  # =============================================================================
@@ -27,19 +28,23 @@ DIR_TASKS = "tasks"
27
28
  DIR_ARCHIVE = "archive"
28
29
  DIR_SPEC = "spec"
29
30
  DIR_SCRIPTS = "scripts"
31
+ DIR_POOL = "pool"
32
+ DIR_DELIVERABLES = "deliverables"
30
33
 
31
34
  # File names
32
35
  FILE_DEVELOPER = ".developer"
33
36
  FILE_CURRENT_TASK = ".current-task"
34
37
  FILE_TASK_JSON = "task.json"
35
38
  FILE_JOURNAL_PREFIX = "journal-"
39
+ FILE_SOURCE_JSON = "source.json"
40
+ FILE_HANDOFF_MD = "HANDOFF.md"
36
41
 
37
42
 
38
43
  # =============================================================================
39
44
  # Repository Root
40
45
  # =============================================================================
41
46
 
42
- def get_repo_root(start_path: Optional[Path] = None) -> Path:
47
+ def get_repo_root(start_path: Path | None = None) -> Path:
43
48
  """Find the nearest directory containing .trellis/ folder.
44
49
 
45
50
  This handles nested git repos correctly (e.g., test project inside another repo).
@@ -65,7 +70,7 @@ def get_repo_root(start_path: Optional[Path] = None) -> Path:
65
70
  # Developer
66
71
  # =============================================================================
67
72
 
68
- def get_developer(repo_root: Optional[Path] = None) -> Optional[str]:
73
+ def get_developer(repo_root: Path | None = None) -> str | None:
69
74
  """Get developer name from .developer file.
70
75
 
71
76
  Args:
@@ -93,7 +98,7 @@ def get_developer(repo_root: Optional[Path] = None) -> Optional[str]:
93
98
  return None
94
99
 
95
100
 
96
- def check_developer(repo_root: Optional[Path] = None) -> bool:
101
+ def check_developer(repo_root: Path | None = None) -> bool:
97
102
  """Check if developer is initialized.
98
103
 
99
104
  Args:
@@ -109,7 +114,7 @@ def check_developer(repo_root: Optional[Path] = None) -> bool:
109
114
  # Tasks Directory
110
115
  # =============================================================================
111
116
 
112
- def get_tasks_dir(repo_root: Optional[Path] = None) -> Path:
117
+ def get_tasks_dir(repo_root: Path | None = None) -> Path:
113
118
  """Get tasks directory path.
114
119
 
115
120
  Args:
@@ -127,7 +132,7 @@ def get_tasks_dir(repo_root: Optional[Path] = None) -> Path:
127
132
  # Workspace Directory
128
133
  # =============================================================================
129
134
 
130
- def get_workspace_dir(repo_root: Optional[Path] = None) -> Optional[Path]:
135
+ def get_workspace_dir(repo_root: Path | None = None) -> Path | None:
131
136
  """Get developer workspace directory.
132
137
 
133
138
  Args:
@@ -149,7 +154,7 @@ def get_workspace_dir(repo_root: Optional[Path] = None) -> Optional[Path]:
149
154
  # Journal File
150
155
  # =============================================================================
151
156
 
152
- def get_active_journal_file(repo_root: Optional[Path] = None) -> Optional[Path]:
157
+ def get_active_journal_file(repo_root: Path | None = None) -> Path | None:
153
158
  """Get the current active journal file.
154
159
 
155
160
  Args:
@@ -165,7 +170,7 @@ def get_active_journal_file(repo_root: Optional[Path] = None) -> Optional[Path]:
165
170
  if workspace_dir is None or not workspace_dir.is_dir():
166
171
  return None
167
172
 
168
- latest: Optional[Path] = None
173
+ latest: Path | None = None
169
174
  highest = 0
170
175
 
171
176
  for f in workspace_dir.glob(f"{FILE_JOURNAL_PREFIX}*.md"):
@@ -206,7 +211,7 @@ def count_lines(file_path: Path) -> int:
206
211
  # Current Task Management
207
212
  # =============================================================================
208
213
 
209
- def _get_current_task_file(repo_root: Optional[Path] = None) -> Path:
214
+ def _get_current_task_file(repo_root: Path | None = None) -> Path:
210
215
  """Get .current-task file path.
211
216
 
212
217
  Args:
@@ -220,7 +225,7 @@ def _get_current_task_file(repo_root: Optional[Path] = None) -> Path:
220
225
  return repo_root / DIR_WORKFLOW / FILE_CURRENT_TASK
221
226
 
222
227
 
223
- def get_current_task(repo_root: Optional[Path] = None) -> Optional[str]:
228
+ def get_current_task(repo_root: Path | None = None) -> str | None:
224
229
  """Get current task directory path (relative to repo_root).
225
230
 
226
231
  Args:
@@ -240,7 +245,7 @@ def get_current_task(repo_root: Optional[Path] = None) -> Optional[str]:
240
245
  return None
241
246
 
242
247
 
243
- def get_current_task_abs(repo_root: Optional[Path] = None) -> Optional[Path]:
248
+ def get_current_task_abs(repo_root: Path | None = None) -> Path | None:
244
249
  """Get current task directory absolute path.
245
250
 
246
251
  Args:
@@ -258,7 +263,7 @@ def get_current_task_abs(repo_root: Optional[Path] = None) -> Optional[Path]:
258
263
  return None
259
264
 
260
265
 
261
- def set_current_task(task_path: str, repo_root: Optional[Path] = None) -> bool:
266
+ def set_current_task(task_path: str, repo_root: Path | None = None) -> bool:
262
267
  """Set current task.
263
268
 
264
269
  Args:
@@ -288,7 +293,7 @@ def set_current_task(task_path: str, repo_root: Optional[Path] = None) -> bool:
288
293
  return False
289
294
 
290
295
 
291
- def clear_current_task(repo_root: Optional[Path] = None) -> bool:
296
+ def clear_current_task(repo_root: Path | None = None) -> bool:
292
297
  """Clear current task.
293
298
 
294
299
  Args:
@@ -307,7 +312,7 @@ def clear_current_task(repo_root: Optional[Path] = None) -> bool:
307
312
  return False
308
313
 
309
314
 
310
- def has_current_task(repo_root: Optional[Path] = None) -> bool:
315
+ def has_current_task(repo_root: Path | None = None) -> bool:
311
316
  """Check if has current task.
312
317
 
313
318
  Args:
@@ -319,6 +324,51 @@ def has_current_task(repo_root: Optional[Path] = None) -> bool:
319
324
  return get_current_task(repo_root) is not None
320
325
 
321
326
 
327
+ # =============================================================================
328
+ # Pool Directory
329
+ # =============================================================================
330
+
331
+ def get_pool_dir(repo_root: Path | None = None) -> Path:
332
+ """Get pool directory path.
333
+
334
+ Args:
335
+ repo_root: Repository root path. Defaults to auto-detected.
336
+
337
+ Returns:
338
+ Path to pool directory.
339
+ """
340
+ if repo_root is None:
341
+ repo_root = get_repo_root()
342
+ return repo_root / DIR_WORKFLOW / DIR_POOL
343
+
344
+
345
+ def get_pool_file(pool_name: str, repo_root: Path | None = None) -> Path:
346
+ """Get pool JSON file path.
347
+
348
+ Args:
349
+ pool_name: Pool name (e.g., 'requirements').
350
+ repo_root: Repository root path. Defaults to auto-detected.
351
+
352
+ Returns:
353
+ Path to pool JSON file.
354
+ """
355
+ return get_pool_dir(repo_root) / f"{pool_name}.json"
356
+
357
+
358
+ def get_deliverables_dir(repo_root: Path | None = None) -> Path:
359
+ """Get deliverables directory path (at project root).
360
+
361
+ Args:
362
+ repo_root: Repository root path. Defaults to auto-detected.
363
+
364
+ Returns:
365
+ Path to deliverables directory.
366
+ """
367
+ if repo_root is None:
368
+ repo_root = get_repo_root()
369
+ return repo_root / DIR_DELIVERABLES
370
+
371
+
322
372
  # =============================================================================
323
373
  # Task ID Generation
324
374
  # =============================================================================