@mindfoldhq/trellis 0.3.8 → 0.3.10-beta.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 (174) hide show
  1. package/dist/cli/index.js +2 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/init.d.ts +1 -0
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +203 -31
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/update.d.ts.map +1 -1
  8. package/dist/commands/update.js +154 -6
  9. package/dist/commands/update.js.map +1 -1
  10. package/dist/configurators/workflow.d.ts +6 -2
  11. package/dist/configurators/workflow.d.ts.map +1 -1
  12. package/dist/configurators/workflow.js +88 -58
  13. package/dist/configurators/workflow.js.map +1 -1
  14. package/dist/migrations/index.d.ts +1 -0
  15. package/dist/migrations/index.d.ts.map +1 -1
  16. package/dist/migrations/index.js +2 -0
  17. package/dist/migrations/index.js.map +1 -1
  18. package/dist/migrations/manifests/0.3.9.json +9 -0
  19. package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
  20. package/dist/templates/claude/agents/dispatch.md +1 -2
  21. package/dist/templates/claude/agents/implement.md +2 -3
  22. package/dist/templates/claude/commands/trellis/before-dev.md +29 -0
  23. package/dist/templates/claude/commands/trellis/check.md +25 -0
  24. package/dist/templates/claude/commands/trellis/create-command.md +2 -2
  25. package/dist/templates/claude/commands/trellis/onboard.md +13 -13
  26. package/dist/templates/claude/commands/trellis/parallel.md +1 -2
  27. package/dist/templates/claude/commands/trellis/record-session.md +1 -1
  28. package/dist/templates/claude/commands/trellis/start.md +8 -4
  29. package/dist/templates/claude/hooks/inject-subagent-context.py +21 -13
  30. package/dist/templates/claude/hooks/session-start.py +170 -2
  31. package/dist/templates/codex/skills/before-dev/SKILL.md +34 -0
  32. package/dist/templates/codex/skills/check/SKILL.md +30 -0
  33. package/dist/templates/codex/skills/create-command/SKILL.md +2 -2
  34. package/dist/templates/codex/skills/onboard/SKILL.md +11 -11
  35. package/dist/templates/codex/skills/record-session/SKILL.md +1 -1
  36. package/dist/templates/codex/skills/start/SKILL.md +8 -3
  37. package/dist/templates/cursor/commands/trellis-before-dev.md +29 -0
  38. package/dist/templates/cursor/commands/trellis-check.md +25 -0
  39. package/dist/templates/cursor/commands/trellis-create-command.md +2 -2
  40. package/dist/templates/cursor/commands/trellis-onboard.md +13 -13
  41. package/dist/templates/cursor/commands/trellis-record-session.md +1 -1
  42. package/dist/templates/cursor/commands/trellis-start.md +7 -16
  43. package/dist/templates/gemini/commands/trellis/before-dev.toml +33 -0
  44. package/dist/templates/gemini/commands/trellis/check.toml +29 -0
  45. package/dist/templates/gemini/commands/trellis/create-command.toml +2 -2
  46. package/dist/templates/gemini/commands/trellis/onboard.toml +2 -2
  47. package/dist/templates/gemini/commands/trellis/record-session.toml +1 -1
  48. package/dist/templates/gemini/commands/trellis/start.toml +9 -4
  49. package/dist/templates/iflow/agents/dispatch.md +1 -2
  50. package/dist/templates/iflow/agents/implement.md +2 -3
  51. package/dist/templates/iflow/commands/trellis/before-dev.md +29 -0
  52. package/dist/templates/iflow/commands/trellis/check.md +25 -0
  53. package/dist/templates/iflow/commands/trellis/create-command.md +2 -2
  54. package/dist/templates/iflow/commands/trellis/onboard.md +13 -13
  55. package/dist/templates/iflow/commands/trellis/parallel.md +1 -2
  56. package/dist/templates/iflow/commands/trellis/record-session.md +1 -1
  57. package/dist/templates/iflow/commands/trellis/start.md +8 -4
  58. package/dist/templates/iflow/hooks/inject-subagent-context.py +21 -13
  59. package/dist/templates/iflow/hooks/session-start.py +156 -1
  60. package/dist/templates/iflow/settings.json +2 -2
  61. package/dist/templates/kilo/workflows/before-dev.md +29 -0
  62. package/dist/templates/kilo/workflows/check.md +25 -0
  63. package/dist/templates/kilo/workflows/create-command.md +2 -2
  64. package/dist/templates/kilo/workflows/onboard.md +13 -13
  65. package/dist/templates/kilo/workflows/parallel.md +1 -2
  66. package/dist/templates/kilo/workflows/record-session.md +1 -1
  67. package/dist/templates/kilo/workflows/start.md +8 -3
  68. package/dist/templates/kiro/skills/before-dev/SKILL.md +34 -0
  69. package/dist/templates/kiro/skills/check/SKILL.md +30 -0
  70. package/dist/templates/kiro/skills/create-command/SKILL.md +2 -2
  71. package/dist/templates/kiro/skills/onboard/SKILL.md +11 -11
  72. package/dist/templates/kiro/skills/record-session/SKILL.md +1 -1
  73. package/dist/templates/kiro/skills/start/SKILL.md +8 -3
  74. package/dist/templates/markdown/spec/backend/script-conventions.md +93 -0
  75. package/dist/templates/opencode/agents/dispatch.md +1 -2
  76. package/dist/templates/opencode/agents/implement.md +2 -2
  77. package/dist/templates/opencode/agents/research.md +1 -2
  78. package/dist/templates/opencode/commands/trellis/before-dev.md +29 -0
  79. package/dist/templates/opencode/commands/trellis/check.md +25 -0
  80. package/dist/templates/opencode/commands/trellis/create-command.md +2 -2
  81. package/dist/templates/opencode/commands/trellis/onboard.md +13 -13
  82. package/dist/templates/opencode/commands/trellis/parallel.md +1 -2
  83. package/dist/templates/opencode/commands/trellis/record-session.md +1 -1
  84. package/dist/templates/opencode/commands/trellis/start.md +8 -3
  85. package/dist/templates/opencode/plugin/inject-subagent-context.js +45 -18
  86. package/dist/templates/opencode/plugin/session-start.js +149 -1
  87. package/dist/templates/qoder/skills/before-dev/SKILL.md +34 -0
  88. package/dist/templates/qoder/skills/check/SKILL.md +30 -0
  89. package/dist/templates/qoder/skills/create-command/SKILL.md +2 -2
  90. package/dist/templates/qoder/skills/onboard/SKILL.md +13 -13
  91. package/dist/templates/qoder/skills/record-session/SKILL.md +1 -1
  92. package/dist/templates/qoder/skills/start/SKILL.md +8 -3
  93. package/dist/templates/trellis/config.yaml +20 -0
  94. package/dist/templates/trellis/index.d.ts +11 -0
  95. package/dist/templates/trellis/index.d.ts.map +1 -1
  96. package/dist/templates/trellis/index.js +22 -0
  97. package/dist/templates/trellis/index.js.map +1 -1
  98. package/dist/templates/trellis/scripts/add_session.py +52 -7
  99. package/dist/templates/trellis/scripts/common/cli_adapter.py +33 -45
  100. package/dist/templates/trellis/scripts/common/config.py +152 -0
  101. package/dist/templates/trellis/scripts/common/git.py +31 -0
  102. package/dist/templates/trellis/scripts/common/git_context.py +23 -586
  103. package/dist/templates/trellis/scripts/common/io.py +37 -0
  104. package/dist/templates/trellis/scripts/common/log.py +45 -0
  105. package/dist/templates/trellis/scripts/common/packages_context.py +233 -0
  106. package/dist/templates/trellis/scripts/common/paths.py +46 -0
  107. package/dist/templates/trellis/scripts/common/phase.py +50 -49
  108. package/dist/templates/trellis/scripts/common/registry.py +41 -72
  109. package/dist/templates/trellis/scripts/common/session_context.py +466 -0
  110. package/dist/templates/trellis/scripts/common/task_context.py +384 -0
  111. package/dist/templates/trellis/scripts/common/task_queue.py +27 -98
  112. package/dist/templates/trellis/scripts/common/task_store.py +534 -0
  113. package/dist/templates/trellis/scripts/common/task_utils.py +96 -6
  114. package/dist/templates/trellis/scripts/common/tasks.py +109 -0
  115. package/dist/templates/trellis/scripts/common/types.py +112 -0
  116. package/dist/templates/trellis/scripts/create_bootstrap.py +31 -26
  117. package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
  118. package/dist/templates/trellis/scripts/multi_agent/_bootstrap.py +17 -0
  119. package/dist/templates/trellis/scripts/multi_agent/cleanup.py +43 -48
  120. package/dist/templates/trellis/scripts/multi_agent/create_pr.py +336 -45
  121. package/dist/templates/trellis/scripts/multi_agent/plan.py +2 -26
  122. package/dist/templates/trellis/scripts/multi_agent/start.py +126 -57
  123. package/dist/templates/trellis/scripts/multi_agent/status.py +12 -753
  124. package/dist/templates/trellis/scripts/multi_agent/status_display.py +542 -0
  125. package/dist/templates/trellis/scripts/multi_agent/status_monitor.py +225 -0
  126. package/dist/templates/trellis/scripts/task.py +50 -975
  127. package/dist/templates/trellis/workflow.md +21 -34
  128. package/dist/types/migration.d.ts +3 -1
  129. package/dist/types/migration.d.ts.map +1 -1
  130. package/dist/utils/project-detector.d.ts +23 -0
  131. package/dist/utils/project-detector.d.ts.map +1 -1
  132. package/dist/utils/project-detector.js +364 -0
  133. package/dist/utils/project-detector.js.map +1 -1
  134. package/dist/utils/template-fetcher.d.ts +2 -2
  135. package/dist/utils/template-fetcher.d.ts.map +1 -1
  136. package/dist/utils/template-fetcher.js +5 -5
  137. package/dist/utils/template-fetcher.js.map +1 -1
  138. package/package.json +1 -1
  139. package/dist/templates/claude/commands/trellis/before-backend-dev.md +0 -13
  140. package/dist/templates/claude/commands/trellis/before-frontend-dev.md +0 -13
  141. package/dist/templates/claude/commands/trellis/check-backend.md +0 -13
  142. package/dist/templates/claude/commands/trellis/check-frontend.md +0 -13
  143. package/dist/templates/codex/skills/before-backend-dev/SKILL.md +0 -18
  144. package/dist/templates/codex/skills/before-frontend-dev/SKILL.md +0 -18
  145. package/dist/templates/codex/skills/check-backend/SKILL.md +0 -18
  146. package/dist/templates/codex/skills/check-frontend/SKILL.md +0 -18
  147. package/dist/templates/cursor/commands/trellis-before-backend-dev.md +0 -13
  148. package/dist/templates/cursor/commands/trellis-before-frontend-dev.md +0 -13
  149. package/dist/templates/cursor/commands/trellis-check-backend.md +0 -13
  150. package/dist/templates/cursor/commands/trellis-check-frontend.md +0 -13
  151. package/dist/templates/gemini/commands/trellis/before-backend-dev.toml +0 -17
  152. package/dist/templates/gemini/commands/trellis/before-frontend-dev.toml +0 -17
  153. package/dist/templates/gemini/commands/trellis/check-backend.toml +0 -17
  154. package/dist/templates/gemini/commands/trellis/check-frontend.toml +0 -17
  155. package/dist/templates/iflow/commands/trellis/before-backend-dev.md +0 -13
  156. package/dist/templates/iflow/commands/trellis/before-frontend-dev.md +0 -13
  157. package/dist/templates/iflow/commands/trellis/check-backend.md +0 -13
  158. package/dist/templates/iflow/commands/trellis/check-frontend.md +0 -13
  159. package/dist/templates/kilo/workflows/before-backend-dev.md +0 -13
  160. package/dist/templates/kilo/workflows/before-frontend-dev.md +0 -13
  161. package/dist/templates/kilo/workflows/check-backend.md +0 -13
  162. package/dist/templates/kilo/workflows/check-frontend.md +0 -13
  163. package/dist/templates/kiro/skills/before-backend-dev/SKILL.md +0 -18
  164. package/dist/templates/kiro/skills/before-frontend-dev/SKILL.md +0 -18
  165. package/dist/templates/kiro/skills/check-backend/SKILL.md +0 -18
  166. package/dist/templates/kiro/skills/check-frontend/SKILL.md +0 -18
  167. package/dist/templates/opencode/commands/trellis/before-backend-dev.md +0 -13
  168. package/dist/templates/opencode/commands/trellis/before-frontend-dev.md +0 -13
  169. package/dist/templates/opencode/commands/trellis/check-backend.md +0 -13
  170. package/dist/templates/opencode/commands/trellis/check-frontend.md +0 -13
  171. package/dist/templates/qoder/skills/before-backend-dev/SKILL.md +0 -18
  172. package/dist/templates/qoder/skills/before-frontend-dev/SKILL.md +0 -18
  173. package/dist/templates/qoder/skills/check-backend/SKILL.md +0 -18
  174. package/dist/templates/qoder/skills/check-frontend/SKILL.md +0 -18
@@ -7,6 +7,7 @@ Reads settings from .trellis/config.yaml with sensible defaults.
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
+ import sys
10
11
  from pathlib import Path
11
12
 
12
13
  from .paths import DIR_WORKFLOW, get_repo_root
@@ -70,3 +71,154 @@ def get_hooks(event: str, repo_root: Path | None = None) -> list[str]:
70
71
  if isinstance(commands, list):
71
72
  return [str(c) for c in commands]
72
73
  return []
74
+
75
+
76
+ # =============================================================================
77
+ # Monorepo / Packages
78
+ # =============================================================================
79
+
80
+
81
+ def get_packages(repo_root: Path | None = None) -> dict[str, dict] | None:
82
+ """Get monorepo package declarations.
83
+
84
+ Returns:
85
+ Dict mapping package name to its config (path, type, etc.),
86
+ or None if not configured (single-repo mode).
87
+
88
+ Example return:
89
+ {"cli": {"path": "packages/cli"}, "docs-site": {"path": "docs-site", "type": "submodule"}}
90
+ """
91
+ config = _load_config(repo_root)
92
+ packages = config.get("packages")
93
+ if not isinstance(packages, dict):
94
+ return None
95
+ # Ensure each value is a dict (filter out scalar entries)
96
+ filtered = {k: v for k, v in packages.items() if isinstance(v, dict)}
97
+ if not filtered:
98
+ return None
99
+ return filtered
100
+
101
+
102
+ def get_default_package(repo_root: Path | None = None) -> str | None:
103
+ """Get the default package name from config.
104
+
105
+ Returns:
106
+ Package name string, or None if not configured.
107
+ """
108
+ config = _load_config(repo_root)
109
+ value = config.get("default_package")
110
+ return str(value) if value else None
111
+
112
+
113
+ def get_submodule_packages(repo_root: Path | None = None) -> dict[str, str]:
114
+ """Get packages that are git submodules.
115
+
116
+ Returns:
117
+ Dict mapping package name to its path for submodule-type packages.
118
+ Empty dict if none configured.
119
+
120
+ Example return:
121
+ {"docs-site": "docs-site"}
122
+ """
123
+ packages = get_packages(repo_root)
124
+ if packages is None:
125
+ return {}
126
+ return {
127
+ name: cfg.get("path", name)
128
+ for name, cfg in packages.items()
129
+ if cfg.get("type") == "submodule"
130
+ }
131
+
132
+
133
+ def is_monorepo(repo_root: Path | None = None) -> bool:
134
+ """Check if the project is configured as a monorepo (has packages in config)."""
135
+ return get_packages(repo_root) is not None
136
+
137
+
138
+ def get_spec_base(package: str | None = None, repo_root: Path | None = None) -> str:
139
+ """Get the spec directory base path relative to .trellis/.
140
+
141
+ Single-repo: returns "spec"
142
+ Monorepo with package: returns "spec/<package>"
143
+ Monorepo without package: returns "spec" (caller should specify package)
144
+ """
145
+ if package and is_monorepo(repo_root):
146
+ return f"spec/{package}"
147
+ return "spec"
148
+
149
+
150
+ def validate_package(package: str, repo_root: Path | None = None) -> bool:
151
+ """Check if a package name is valid in this project.
152
+
153
+ Single-repo (no packages configured): always returns True.
154
+ Monorepo: returns True only if package exists in config.yaml packages.
155
+ """
156
+ packages = get_packages(repo_root)
157
+ if packages is None:
158
+ return True # Single-repo, no validation needed
159
+ return package in packages
160
+
161
+
162
+ def resolve_package(
163
+ task_package: str | None = None,
164
+ repo_root: Path | None = None,
165
+ ) -> str | None:
166
+ """Resolve package from inferred sources with validation.
167
+
168
+ Checks in order: task_package → default_package.
169
+ Invalid inferred values print a warning to stderr and are skipped.
170
+
171
+ Returns:
172
+ Resolved package name, or None if no valid package found.
173
+
174
+ Note:
175
+ CLI --package should be validated separately by the caller
176
+ (fail-fast with available packages list on error).
177
+ """
178
+ packages = get_packages(repo_root)
179
+ if packages is None:
180
+ return None # Single-repo, no package needed
181
+
182
+ # Try task_package (guard against non-string values from malformed JSON)
183
+ if task_package and isinstance(task_package, str):
184
+ if task_package in packages:
185
+ return task_package
186
+ print(
187
+ f"Warning: task.json package '{task_package}' not found in config, skipping",
188
+ file=sys.stderr,
189
+ )
190
+
191
+ # Try default_package
192
+ default = get_default_package(repo_root)
193
+ if default:
194
+ if default in packages:
195
+ return default
196
+ print(
197
+ f"Warning: default_package '{default}' not found in config, skipping",
198
+ file=sys.stderr,
199
+ )
200
+
201
+ return None
202
+
203
+
204
+ def get_spec_scope(repo_root: Path | None = None) -> list[str] | str | None:
205
+ """Get session.spec_scope configuration.
206
+
207
+ Returns:
208
+ list[str]: Package names to include in spec scanning.
209
+ str: "active_task" to use current task's package.
210
+ None: No scope configured (scan all packages).
211
+ """
212
+ config = _load_config(repo_root)
213
+ session = config.get("session")
214
+ if not isinstance(session, dict):
215
+ return None
216
+
217
+ scope = session.get("spec_scope")
218
+ if scope is None:
219
+ return None
220
+ if isinstance(scope, str):
221
+ return scope # e.g. "active_task"
222
+ if isinstance(scope, list):
223
+ return [str(s) for s in scope]
224
+ return None
@@ -0,0 +1,31 @@
1
+ """
2
+ Git command execution utility.
3
+
4
+ Single source of truth for running git commands across all Trellis scripts.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import subprocess
10
+ from pathlib import Path
11
+
12
+
13
+ def run_git(args: list[str], cwd: Path | None = None) -> tuple[int, str, str]:
14
+ """Run a git command and return (returncode, stdout, stderr).
15
+
16
+ Uses UTF-8 encoding with -c i18n.logOutputEncoding=UTF-8 to ensure
17
+ consistent output across all platforms (Windows, macOS, Linux).
18
+ """
19
+ try:
20
+ git_args = ["git", "-c", "i18n.logOutputEncoding=UTF-8"] + args
21
+ result = subprocess.run(
22
+ git_args,
23
+ cwd=cwd,
24
+ capture_output=True,
25
+ text=True,
26
+ encoding="utf-8",
27
+ errors="replace",
28
+ )
29
+ return result.returncode, result.stdout, result.stderr
30
+ except Exception as e:
31
+ return 1, "", str(e)