@blxzer/cursor-trellis 0.3.0 → 0.3.3

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 (196) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +51 -10
  3. package/README.zh-CN.md +21 -7
  4. package/bin/cstl.js +1 -1
  5. package/bin/smart-search.js +1 -1
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +17 -15
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/commands/capability-smoke.js +2 -2
  10. package/dist/commands/capability-smoke.js.map +1 -1
  11. package/dist/commands/channel/agent-loader.d.ts +1 -1
  12. package/dist/commands/channel/agent-loader.js +4 -4
  13. package/dist/commands/channel/agent-loader.js.map +1 -1
  14. package/dist/commands/channel/guard.d.ts +2 -2
  15. package/dist/commands/channel/guard.js +3 -3
  16. package/dist/commands/channel/guard.js.map +1 -1
  17. package/dist/commands/channel/index.js +3 -3
  18. package/dist/commands/channel/index.js.map +1 -1
  19. package/dist/commands/channel/list.d.ts +1 -1
  20. package/dist/commands/channel/list.js +1 -1
  21. package/dist/commands/channel/rm.d.ts +1 -1
  22. package/dist/commands/channel/rm.js +1 -1
  23. package/dist/commands/channel/store/lock.d.ts +1 -1
  24. package/dist/commands/channel/store/lock.js +1 -1
  25. package/dist/commands/channel/store/paths.js +1 -1
  26. package/dist/commands/channel/store/paths.js.map +1 -1
  27. package/dist/commands/init.d.ts.map +1 -1
  28. package/dist/commands/init.js +105 -59
  29. package/dist/commands/init.js.map +1 -1
  30. package/dist/commands/uninstall.d.ts +3 -3
  31. package/dist/commands/uninstall.d.ts.map +1 -1
  32. package/dist/commands/uninstall.js +69 -15
  33. package/dist/commands/uninstall.js.map +1 -1
  34. package/dist/commands/update.d.ts +6 -1
  35. package/dist/commands/update.d.ts.map +1 -1
  36. package/dist/commands/update.js +83 -28
  37. package/dist/commands/update.js.map +1 -1
  38. package/dist/commands/workflow.d.ts +4 -4
  39. package/dist/commands/workflow.d.ts.map +1 -1
  40. package/dist/commands/workflow.js +10 -9
  41. package/dist/commands/workflow.js.map +1 -1
  42. package/dist/configurators/index.d.ts.map +1 -1
  43. package/dist/configurators/index.js +1 -1
  44. package/dist/configurators/index.js.map +1 -1
  45. package/dist/configurators/shared.js +6 -6
  46. package/dist/configurators/shared.js.map +1 -1
  47. package/dist/configurators/workflow.d.ts +4 -4
  48. package/dist/configurators/workflow.js +1 -1
  49. package/dist/constants/paths.d.ts +24 -24
  50. package/dist/constants/paths.d.ts.map +1 -1
  51. package/dist/constants/paths.js +16 -16
  52. package/dist/constants/paths.js.map +1 -1
  53. package/dist/migrations/manifests/0.3.1.json +32 -0
  54. package/dist/templates/common/bundled-skills/cstl-cursor2plus-setup/SKILL.md +11 -11
  55. package/dist/templates/common/bundled-skills/cstl-meta/SKILL.md +15 -15
  56. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/add-project-local-conventions.md +12 -12
  57. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-agents.md +2 -2
  58. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-context-loading.md +21 -21
  59. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-hooks.md +9 -9
  60. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-skills-or-commands.md +7 -7
  61. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-spec-structure.md +15 -15
  62. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-task-lifecycle.md +27 -27
  63. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/change-workflow.md +7 -7
  64. package/dist/templates/common/bundled-skills/cstl-meta/references/customize-local/overview.md +11 -11
  65. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/context-injection.md +12 -12
  66. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/generated-files.md +21 -21
  67. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/overview.md +14 -14
  68. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/spec-system.md +12 -12
  69. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/task-system.md +23 -23
  70. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/workflow.md +3 -3
  71. package/dist/templates/common/bundled-skills/cstl-meta/references/local-architecture/workspace-memory.md +16 -16
  72. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/agents.md +2 -2
  73. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/hooks-and-settings.md +6 -6
  74. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/overview.md +5 -5
  75. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/platform-map.md +3 -3
  76. package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/skills-and-commands.md +5 -5
  77. package/dist/templates/common/bundled-skills/cstl-skill-creator/SKILL.md +2 -2
  78. package/dist/templates/common/bundled-skills/cstl-skill-creator/references/review-checklist.md +1 -1
  79. package/dist/templates/common/bundled-skills/cstl-spec-bootstrap/SKILL.md +5 -5
  80. package/dist/templates/common/bundled-skills/cstl-spec-bootstrap/references/repository-analysis.md +1 -1
  81. package/dist/templates/common/bundled-skills/cstl-spec-bootstrap/references/spec-task-planning.md +3 -3
  82. package/dist/templates/common/bundled-skills/cstl-spec-bootstrap/references/spec-writing.md +1 -1
  83. package/dist/templates/common/commands/continue.md +6 -6
  84. package/dist/templates/common/commands/finish-work.md +5 -5
  85. package/dist/templates/common/commands/start.md +8 -8
  86. package/dist/templates/common/skills/before-dev.md +4 -4
  87. package/dist/templates/common/skills/brainstorm.md +5 -5
  88. package/dist/templates/common/skills/break-loop.md +3 -3
  89. package/dist/templates/common/skills/check.md +5 -5
  90. package/dist/templates/common/skills/update-spec.md +4 -4
  91. package/dist/templates/cursor/agents/cstl-check.md +6 -6
  92. package/dist/templates/cursor/agents/cstl-implement.md +7 -7
  93. package/dist/templates/cursor/agents/cstl-research.md +9 -9
  94. package/dist/templates/cursor/commands/cursor2plus-setup.md +10 -10
  95. package/dist/templates/cursor/rules/cstl-subagent-dispatch.mdc +2 -2
  96. package/dist/templates/cursor/rules/cstl-triage.mdc +2 -2
  97. package/dist/templates/cursor/rules/retrieval-routing.mdc +4 -4
  98. package/dist/templates/extract.d.ts +1 -1
  99. package/dist/templates/extract.js +1 -1
  100. package/dist/templates/markdown/agents.md +11 -11
  101. package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +1 -1
  102. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +5 -5
  103. package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +3 -3
  104. package/dist/templates/markdown/spec/guides/cursor-semantic-compliance.md.txt +1 -1
  105. package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +11 -11
  106. package/dist/templates/markdown/spec/guides/cursor-trellis-release-coexistence-guide.md.txt +166 -0
  107. package/dist/templates/markdown/spec/guides/durable-learning-decision-guide.md.txt +8 -8
  108. package/dist/templates/markdown/spec/guides/execution-strategy.md.txt +3 -3
  109. package/dist/templates/markdown/spec/guides/index.md.txt +1 -0
  110. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +10 -10
  111. package/dist/templates/markdown/workspace-index.md +3 -3
  112. package/dist/templates/markdown/worktree.yaml.txt +1 -1
  113. package/dist/templates/shared-hooks/index.d.ts +1 -1
  114. package/dist/templates/shared-hooks/index.js +1 -1
  115. package/dist/templates/shared-hooks/inject-retrieval-plan.py +3 -3
  116. package/dist/templates/shared-hooks/inject-shell-session-context.py +7 -7
  117. package/dist/templates/shared-hooks/inject-subagent-context.py +1 -1
  118. package/dist/templates/shared-hooks/inject-workflow-state.py +11 -11
  119. package/dist/templates/shared-hooks/research-end-retrieval-pack.py +1 -1
  120. package/dist/templates/shared-hooks/session-start.py +13 -13
  121. package/dist/templates/trellis/config.yaml +2 -22
  122. package/dist/templates/trellis/index.d.ts +2 -2
  123. package/dist/templates/trellis/index.js +2 -2
  124. package/dist/templates/trellis/local/README.md +3 -3
  125. package/dist/templates/trellis/local/patch_wpelc8.py +4 -4
  126. package/dist/templates/trellis/scripts/add_session.py +20 -20
  127. package/dist/templates/trellis/scripts/common/active_task.py +2 -2
  128. package/dist/templates/trellis/scripts/common/artifact_search.py +587 -587
  129. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +6 -6
  130. package/dist/templates/trellis/scripts/common/config.py +3 -3
  131. package/dist/templates/trellis/scripts/common/developer.py +2 -2
  132. package/dist/templates/trellis/scripts/common/packages_context.py +23 -23
  133. package/dist/templates/trellis/scripts/common/parent_orchestration.py +16 -16
  134. package/dist/templates/trellis/scripts/common/paths.py +107 -107
  135. package/dist/templates/trellis/scripts/common/project_file_stats.py +1 -1
  136. package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +1 -1
  137. package/dist/templates/trellis/scripts/common/safe_commit.py +31 -31
  138. package/dist/templates/trellis/scripts/common/session_memory.py +360 -360
  139. package/dist/templates/trellis/scripts/common/smart_search_evidence.py +514 -514
  140. package/dist/templates/trellis/scripts/common/smart_search_resolve.py +1 -1
  141. package/dist/templates/trellis/scripts/common/subagent_dispatch.py +2 -2
  142. package/dist/templates/trellis/scripts/common/task_context.py +1 -1
  143. package/dist/templates/trellis/scripts/common/task_dashboard.py +140 -140
  144. package/dist/templates/trellis/scripts/common/task_gates.py +23 -23
  145. package/dist/templates/trellis/scripts/common/task_store.py +5 -5
  146. package/dist/templates/trellis/scripts/common/task_utils.py +3 -3
  147. package/dist/templates/trellis/scripts/common/tasks.py +1 -1
  148. package/dist/templates/trellis/scripts/common/trellis_config.py +3 -3
  149. package/dist/templates/trellis/scripts/common/workflow_phase.py +1 -1
  150. package/dist/templates/trellis/scripts/cursor_retrieval_probe.py +3 -3
  151. package/dist/templates/trellis/scripts/cursor_retrieval_probe_prompt.md +11 -11
  152. package/dist/templates/trellis/scripts/hooks/linear_sync.py +8 -8
  153. package/dist/templates/trellis/scripts/init_developer.py +2 -2
  154. package/dist/templates/trellis/scripts/retrieval_probe_matrix_template.json +4 -4
  155. package/dist/templates/trellis/scripts/route_codebase_retrieval.py +1 -1
  156. package/dist/templates/trellis/scripts/task.py +918 -918
  157. package/dist/templates/trellis/tasks/templates/release-readiness/implement.md +2 -2
  158. package/dist/templates/trellis/workflow.md +64 -64
  159. package/dist/types/migration.d.ts +1 -1
  160. package/dist/types/migration.d.ts.map +1 -1
  161. package/dist/utils/agents-md.d.ts +47 -0
  162. package/dist/utils/agents-md.d.ts.map +1 -0
  163. package/dist/utils/agents-md.js +107 -0
  164. package/dist/utils/agents-md.js.map +1 -0
  165. package/dist/utils/codebase-retrieval-router.js +5 -5
  166. package/dist/utils/codebase-retrieval-router.js.map +1 -1
  167. package/dist/utils/manifest-prune.d.ts +2 -2
  168. package/dist/utils/manifest-prune.js +4 -4
  169. package/dist/utils/manifest-prune.js.map +1 -1
  170. package/dist/utils/mirror-check.d.ts +3 -1
  171. package/dist/utils/mirror-check.d.ts.map +1 -1
  172. package/dist/utils/mirror-check.js +22 -11
  173. package/dist/utils/mirror-check.js.map +1 -1
  174. package/dist/utils/project-capabilities.js +5 -5
  175. package/dist/utils/project-capabilities.js.map +1 -1
  176. package/dist/utils/retrieval-agent-instructions.js +1 -1
  177. package/dist/utils/retrieval-agent-instructions.js.map +1 -1
  178. package/dist/utils/retrieval-execution-telemetry.js +1 -1
  179. package/dist/utils/retrieval-execution-telemetry.js.map +1 -1
  180. package/dist/utils/template-fetcher.js +1 -1
  181. package/dist/utils/template-fetcher.js.map +1 -1
  182. package/dist/utils/template-hash.d.ts +2 -2
  183. package/dist/utils/template-hash.d.ts.map +1 -1
  184. package/dist/utils/template-hash.js +51 -18
  185. package/dist/utils/template-hash.js.map +1 -1
  186. package/dist/utils/workflow-dir.d.ts +13 -0
  187. package/dist/utils/workflow-dir.d.ts.map +1 -0
  188. package/dist/utils/workflow-dir.js +35 -0
  189. package/dist/utils/workflow-dir.js.map +1 -0
  190. package/dist/utils/workflow-ownership.d.ts +36 -0
  191. package/dist/utils/workflow-ownership.d.ts.map +1 -0
  192. package/dist/utils/workflow-ownership.js +137 -0
  193. package/dist/utils/workflow-ownership.js.map +1 -0
  194. package/dist/utils/workflow-resolver.d.ts +1 -1
  195. package/dist/utils/workflow-resolver.js +1 -1
  196. package/package.json +2 -2
@@ -2,7 +2,7 @@
2
2
  """
3
3
  Resolve how to invoke the smart-search CLI (argv prefix for subprocess).
4
4
 
5
- No writes under .trellis/.runtime/. Optional per-machine override:
5
+ No writes under .cstl/.runtime/. Optional per-machine override:
6
6
  TRELLIS_SMART_SEARCH_COMMAND or smart_search.command in config.yaml.
7
7
  """
8
8
 
@@ -15,7 +15,7 @@ from typing import Literal
15
15
  from .io import read_json
16
16
  from .paths import FILE_TASK_JSON
17
17
 
18
- DIR_WORKFLOW = ".trellis"
18
+ DIR_WORKFLOW = ".cstl"
19
19
  DIR_SPEC = "spec"
20
20
 
21
21
  AGENT_IMPLEMENT = "cstl-implement"
@@ -369,7 +369,7 @@ Conversations get compacted; files do not. Every research topic MUST be written
369
369
 
370
370
  ## Write FORBIDDEN
371
371
 
372
- - Code, `.trellis/spec/`, platform config, git operations"""
372
+ - Code, `.cstl/spec/`, platform config, git operations"""
373
373
 
374
374
 
375
375
  def _repo_relative(task_dir: Path, repo_root: Path) -> str:
@@ -11,7 +11,7 @@ Note:
11
11
  ``cmd_init_context`` was removed in v0.5.0-beta.12. JSONL context files
12
12
  are now seeded at ``task.py create`` time with a self-describing
13
13
  ``_example`` line; the AI agent curates real entries during planning when
14
- the task needs sub-agent/spec context. See ``.trellis/workflow.md`` for the
14
+ the task needs sub-agent/spec context. See ``.cstl/workflow.md`` for the
15
15
  current planning artifact contract.
16
16
  """
17
17
 
@@ -1,140 +1,140 @@
1
- #!/usr/bin/env python3
2
- """Task dashboard rendering for framework entry routing."""
3
-
4
- from __future__ import annotations
5
-
6
- from pathlib import Path
7
-
8
- from .active_task import resolve_selected_task
9
- from .paths import DIR_TASKS, DIR_WORKFLOW, get_developer, get_repo_root, get_tasks_dir
10
- from .task_map import get_child_state
11
- from .tasks import (
12
- children_progress,
13
- format_child_task_display,
14
- iter_active_tasks,
15
- load_parent_child_integration_states,
16
- )
17
-
18
-
19
- _STATUS_ORDER = ("planning", "in_progress", "review", "blocked")
20
-
21
-
22
- def _task_path(dir_name: str) -> str:
23
- return f"{DIR_WORKFLOW}/{DIR_TASKS}/{dir_name}"
24
-
25
-
26
- def _selected_line(
27
- repo_root: Path,
28
- platform_input: dict | None = None,
29
- platform: str | None = None,
30
- ) -> str:
31
- selected = resolve_selected_task(repo_root, platform_input, platform)
32
- if selected.task_path:
33
- suffix = f" ({selected.source})" if selected.source else ""
34
- return f"Selected task: {selected.task_path}{suffix}"
35
- return (
36
- "Selected task: none "
37
- "(no session pointer — use task.py select <task> or task.py list)"
38
- )
39
-
40
-
41
- def render_task_dashboard(
42
- repo_root: Path | None = None,
43
- platform_input: dict | None = None,
44
- platform: str | None = None,
45
- ) -> str:
46
- """Render a compact, non-mutating Task Dashboard."""
47
- if repo_root is None:
48
- repo_root = get_repo_root()
49
-
50
- tasks_dir = get_tasks_dir(repo_root)
51
- developer = get_developer(repo_root)
52
- all_tasks = {task.dir_name: task for task in iter_active_tasks(tasks_dir)}
53
- all_statuses = {name: task.status for name, task in all_tasks.items()}
54
-
55
- lines: list[str] = [
56
- "Task Dashboard",
57
- "Trellis framework: active",
58
- _selected_line(repo_root, platform_input, platform),
59
- "",
60
- ]
61
-
62
- if not all_tasks:
63
- lines.append("Tasks: none")
64
- else:
65
- printed: set[str] = set()
66
- for status in _STATUS_ORDER:
67
- names = [
68
- name
69
- for name, task in sorted(all_tasks.items())
70
- if task.status == status and not task.parent
71
- ]
72
- if not names:
73
- continue
74
- title = status.replace("_", " ").title()
75
- lines.append(f"{title}:")
76
- for name in names:
77
- _append_task(lines, name, all_tasks, all_statuses, printed)
78
- lines.append("")
79
-
80
- other_names = [
81
- name
82
- for name, task in sorted(all_tasks.items())
83
- if name not in printed and not task.parent
84
- ]
85
- if other_names:
86
- lines.append("Other:")
87
- for name in other_names:
88
- _append_task(lines, name, all_tasks, all_statuses, printed)
89
- lines.append("")
90
-
91
- lines.append("Suggested actions:")
92
- lines.append(" - Select a task: python ./.trellis/scripts/task.py select <task>")
93
- lines.append(" - Create a task: python ./.trellis/scripts/task.py create \"<title>\" --slug <slug>")
94
- lines.append(" - Inspect raw list: python ./.trellis/scripts/task.py list")
95
- lines.append(" - Continue without a task only for No Task or Micro-Grill work")
96
- if developer:
97
- lines.append(f"Developer: {developer}")
98
-
99
- return "\n".join(line.rstrip() for line in lines).rstrip()
100
-
101
-
102
- def _append_task(
103
- lines: list[str],
104
- name: str,
105
- all_tasks: dict,
106
- all_statuses: dict[str, str],
107
- printed: set[str],
108
- indent: int = 0,
109
- parent_dir: Path | None = None,
110
- ) -> None:
111
- task = all_tasks[name]
112
- printed.add(name)
113
- integration_states = None
114
- if task.children:
115
- integration_states = load_parent_child_integration_states(
116
- task.directory, task.children
117
- )
118
- progress = children_progress(
119
- task.children, all_statuses, integration_states
120
- )
121
- integration_state = None
122
- if parent_dir is not None:
123
- integration_state = get_child_state(parent_dir, name)
124
- status_display = format_child_task_display(task.status, integration_state)
125
- assignee = task.assignee or "-"
126
- prefix = " " * indent + " - "
127
- lines.append(
128
- f"{prefix}{_task_path(name)} ({status_display}){progress} [{assignee}]"
129
- )
130
- for child_name in task.children:
131
- if child_name in all_tasks:
132
- _append_task(
133
- lines,
134
- child_name,
135
- all_tasks,
136
- all_statuses,
137
- printed,
138
- indent + 1,
139
- parent_dir=task.directory,
140
- )
1
+ #!/usr/bin/env python3
2
+ """Task dashboard rendering for framework entry routing."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+
8
+ from .active_task import resolve_selected_task
9
+ from .paths import DIR_TASKS, DIR_WORKFLOW, get_developer, get_repo_root, get_tasks_dir
10
+ from .task_map import get_child_state
11
+ from .tasks import (
12
+ children_progress,
13
+ format_child_task_display,
14
+ iter_active_tasks,
15
+ load_parent_child_integration_states,
16
+ )
17
+
18
+
19
+ _STATUS_ORDER = ("planning", "in_progress", "review", "blocked")
20
+
21
+
22
+ def _task_path(dir_name: str) -> str:
23
+ return f"{DIR_WORKFLOW}/{DIR_TASKS}/{dir_name}"
24
+
25
+
26
+ def _selected_line(
27
+ repo_root: Path,
28
+ platform_input: dict | None = None,
29
+ platform: str | None = None,
30
+ ) -> str:
31
+ selected = resolve_selected_task(repo_root, platform_input, platform)
32
+ if selected.task_path:
33
+ suffix = f" ({selected.source})" if selected.source else ""
34
+ return f"Selected task: {selected.task_path}{suffix}"
35
+ return (
36
+ "Selected task: none "
37
+ "(no session pointer — use task.py select <task> or task.py list)"
38
+ )
39
+
40
+
41
+ def render_task_dashboard(
42
+ repo_root: Path | None = None,
43
+ platform_input: dict | None = None,
44
+ platform: str | None = None,
45
+ ) -> str:
46
+ """Render a compact, non-mutating Task Dashboard."""
47
+ if repo_root is None:
48
+ repo_root = get_repo_root()
49
+
50
+ tasks_dir = get_tasks_dir(repo_root)
51
+ developer = get_developer(repo_root)
52
+ all_tasks = {task.dir_name: task for task in iter_active_tasks(tasks_dir)}
53
+ all_statuses = {name: task.status for name, task in all_tasks.items()}
54
+
55
+ lines: list[str] = [
56
+ "Task Dashboard",
57
+ "Trellis framework: active",
58
+ _selected_line(repo_root, platform_input, platform),
59
+ "",
60
+ ]
61
+
62
+ if not all_tasks:
63
+ lines.append("Tasks: none")
64
+ else:
65
+ printed: set[str] = set()
66
+ for status in _STATUS_ORDER:
67
+ names = [
68
+ name
69
+ for name, task in sorted(all_tasks.items())
70
+ if task.status == status and not task.parent
71
+ ]
72
+ if not names:
73
+ continue
74
+ title = status.replace("_", " ").title()
75
+ lines.append(f"{title}:")
76
+ for name in names:
77
+ _append_task(lines, name, all_tasks, all_statuses, printed)
78
+ lines.append("")
79
+
80
+ other_names = [
81
+ name
82
+ for name, task in sorted(all_tasks.items())
83
+ if name not in printed and not task.parent
84
+ ]
85
+ if other_names:
86
+ lines.append("Other:")
87
+ for name in other_names:
88
+ _append_task(lines, name, all_tasks, all_statuses, printed)
89
+ lines.append("")
90
+
91
+ lines.append("Suggested actions:")
92
+ lines.append(" - Select a task: python ./.cstl/scripts/task.py select <task>")
93
+ lines.append(" - Create a task: python ./.cstl/scripts/task.py create \"<title>\" --slug <slug>")
94
+ lines.append(" - Inspect raw list: python ./.cstl/scripts/task.py list")
95
+ lines.append(" - Continue without a task only for No Task or Micro-Grill work")
96
+ if developer:
97
+ lines.append(f"Developer: {developer}")
98
+
99
+ return "\n".join(line.rstrip() for line in lines).rstrip()
100
+
101
+
102
+ def _append_task(
103
+ lines: list[str],
104
+ name: str,
105
+ all_tasks: dict,
106
+ all_statuses: dict[str, str],
107
+ printed: set[str],
108
+ indent: int = 0,
109
+ parent_dir: Path | None = None,
110
+ ) -> None:
111
+ task = all_tasks[name]
112
+ printed.add(name)
113
+ integration_states = None
114
+ if task.children:
115
+ integration_states = load_parent_child_integration_states(
116
+ task.directory, task.children
117
+ )
118
+ progress = children_progress(
119
+ task.children, all_statuses, integration_states
120
+ )
121
+ integration_state = None
122
+ if parent_dir is not None:
123
+ integration_state = get_child_state(parent_dir, name)
124
+ status_display = format_child_task_display(task.status, integration_state)
125
+ assignee = task.assignee or "-"
126
+ prefix = " " * indent + " - "
127
+ lines.append(
128
+ f"{prefix}{_task_path(name)} ({status_display}){progress} [{assignee}]"
129
+ )
130
+ for child_name in task.children:
131
+ if child_name in all_tasks:
132
+ _append_task(
133
+ lines,
134
+ child_name,
135
+ all_tasks,
136
+ all_statuses,
137
+ printed,
138
+ indent + 1,
139
+ parent_dir=task.directory,
140
+ )
@@ -1150,7 +1150,7 @@ def durable_learning_decision_status(content: str) -> dict[str, bool]:
1150
1150
  def suggest_spec_targets(repo_root: Path, task_dir: Path, task_data: dict) -> list[str]:
1151
1151
  """Suggest existing spec paths from task scope; does not invent new rules."""
1152
1152
  suggestions: list[str] = []
1153
- spec_root = repo_root / ".trellis" / "spec"
1153
+ spec_root = repo_root / ".cstl" / "spec"
1154
1154
  if not spec_root.is_dir():
1155
1155
  return suggestions
1156
1156
 
@@ -1158,7 +1158,7 @@ def suggest_spec_targets(repo_root: Path, task_dir: Path, task_data: dict) -> li
1158
1158
  if isinstance(package, str) and package.strip():
1159
1159
  pkg_index = spec_root / package.strip() / "index.md"
1160
1160
  if pkg_index.is_file():
1161
- suggestions.append(f".trellis/spec/{package.strip()}/index.md")
1161
+ suggestions.append(f".cstl/spec/{package.strip()}/index.md")
1162
1162
 
1163
1163
  scope = task_data.get("scope")
1164
1164
  if isinstance(scope, str) and scope.strip():
@@ -1168,7 +1168,7 @@ def suggest_spec_targets(repo_root: Path, task_dir: Path, task_data: dict) -> li
1168
1168
  index = scope_path / "index.md"
1169
1169
  if index.is_file():
1170
1170
  suggestions.append(
1171
- f".trellis/spec/{scope_path.relative_to(spec_root).as_posix()}/index.md"
1171
+ f".cstl/spec/{scope_path.relative_to(spec_root).as_posix()}/index.md"
1172
1172
  )
1173
1173
 
1174
1174
  guide_paths = (
@@ -1178,7 +1178,7 @@ def suggest_spec_targets(repo_root: Path, task_dir: Path, task_data: dict) -> li
1178
1178
  for rel in guide_paths:
1179
1179
  path = spec_root / rel
1180
1180
  if path.is_file():
1181
- suggestions.append(f".trellis/spec/{rel}")
1181
+ suggestions.append(f".cstl/spec/{rel}")
1182
1182
 
1183
1183
  return _dedupe_preserve_order(suggestions)[:6]
1184
1184
 
@@ -1192,7 +1192,7 @@ def build_spec_update_scaffold(
1192
1192
  ) -> str:
1193
1193
  """Markdown checklist for spec capture; user/reviewer must confirm before editing specs."""
1194
1194
  targets = suggest_spec_targets(repo_root, task_dir, task_data)
1195
- rel_task = f".trellis/tasks/{task_dir.name}"
1195
+ rel_task = f".cstl/tasks/{task_dir.name}"
1196
1196
  lines = [
1197
1197
  "## Spec update scaffold (reviewer-confirmed)",
1198
1198
  "",
@@ -1205,7 +1205,7 @@ def build_spec_update_scaffold(
1205
1205
  [
1206
1206
  "1. Decide outcome in verify.md:",
1207
1207
  " - Routine: `Durable learning decision: no durable learning`",
1208
- " - Reusable insight: `Spec update evidence: .trellis/spec/<path>` after edits",
1208
+ " - Reusable insight: `Spec update evidence: .cstl/spec/<path>` after edits",
1209
1209
  f" - Already documented: `Learning artifact: {rel_task}/handoff.md`",
1210
1210
  "",
1211
1211
  "2. Use `/cstl:update-spec` or `/cstl:break-loop` for depth; never auto-write specs.",
@@ -1219,11 +1219,11 @@ def build_spec_update_scaffold(
1219
1219
  lines.append("")
1220
1220
  else:
1221
1221
  lines.append(
1222
- "3. Browse `.trellis/spec/<package-or-layer>/index.md` for the right code-spec file."
1222
+ "3. Browse `.cstl/spec/<package-or-layer>/index.md` for the right code-spec file."
1223
1223
  )
1224
1224
  lines.append("")
1225
1225
  lines.append(
1226
- "4. Re-run `python ./.trellis/scripts/task.py archive <task> --check` after verify.md is final."
1226
+ "4. Re-run `python ./.cstl/scripts/task.py archive <task> --check` after verify.md is final."
1227
1227
  )
1228
1228
  lines.append("")
1229
1229
  return "\n".join(lines)
@@ -1233,13 +1233,13 @@ def _learning_decision_draft_lines(task_dir: Path, task_data: dict) -> list[str]
1233
1233
  """Default durable-learning block for prepare-archive-evidence."""
1234
1234
  repo_root = task_dir.parent.parent.parent
1235
1235
  targets = suggest_spec_targets(repo_root, task_dir, task_data)
1236
- target_hint = targets[0] if targets else ".trellis/spec/<layer>/index.md"
1236
+ target_hint = targets[0] if targets else ".cstl/spec/<layer>/index.md"
1237
1237
  return [
1238
1238
  "Durable learning decision: no durable learning for this task scope.",
1239
1239
  "",
1240
1240
  "# Replace the line above with ONE of these before archive:",
1241
1241
  f"# Spec update evidence: {target_hint}",
1242
- f"# Learning artifact: .trellis/tasks/{task_dir.name}/handoff.md",
1242
+ f"# Learning artifact: .cstl/tasks/{task_dir.name}/handoff.md",
1243
1243
  "# Spec update needed: (brief reason) — then run /cstl:update-spec and point Spec update evidence at the edited file",
1244
1244
  "",
1245
1245
  ]
@@ -1268,12 +1268,12 @@ def archive_repair_hints(
1268
1268
  """Map archive validation errors to actionable next-step hints."""
1269
1269
  hints: list[str] = []
1270
1270
  task_ref = task_dir.name
1271
- rel_task = f".trellis/tasks/{task_ref}"
1271
+ rel_task = f".cstl/tasks/{task_ref}"
1272
1272
 
1273
1273
  for error in errors:
1274
1274
  if error == "verify.md":
1275
1275
  hints.append(
1276
- f"Create verify.md, then run: python ./.trellis/scripts/task.py "
1276
+ f"Create verify.md, then run: python ./.cstl/scripts/task.py "
1277
1277
  f"prepare-archive-evidence {rel_task}"
1278
1278
  )
1279
1279
  continue
@@ -1281,7 +1281,7 @@ def archive_repair_hints(
1281
1281
  hints.append(
1282
1282
  "Add a grep-friendly line such as "
1283
1283
  "'Validation commands: <command> — <outcome>' to verify.md, "
1284
- f"or run: python ./.trellis/scripts/task.py prepare-archive-evidence {rel_task}"
1284
+ f"or run: python ./.cstl/scripts/task.py prepare-archive-evidence {rel_task}"
1285
1285
  )
1286
1286
  continue
1287
1287
  if error == "verify.md missing final acceptance evidence":
@@ -1295,9 +1295,9 @@ def archive_repair_hints(
1295
1295
  hints.append(
1296
1296
  "Durable learning decision (pick one grep-friendly line in verify.md): "
1297
1297
  "'Durable learning decision: no durable learning' for routine work; "
1298
- "'Spec update evidence: .trellis/spec/<path>' after /cstl:update-spec; "
1298
+ "'Spec update evidence: .cstl/spec/<path>' after /cstl:update-spec; "
1299
1299
  "'Learning artifact: <path>' when handoff/retrospective already captures the insight. "
1300
- f"Or run: python ./.trellis/scripts/task.py prepare-archive-evidence {rel_task}"
1300
+ f"Or run: python ./.cstl/scripts/task.py prepare-archive-evidence {rel_task}"
1301
1301
  )
1302
1302
  continue
1303
1303
  if error == "verify.md missing final integration evidence":
@@ -1313,21 +1313,21 @@ def archive_repair_hints(
1313
1313
  if transition == "parent-integrated":
1314
1314
  hints.append(
1315
1315
  f"Parent archive needs record-gate for parent-integrated/{gate}: "
1316
- f"python ./.trellis/scripts/task.py record-gate {rel_task} "
1316
+ f"python ./.cstl/scripts/task.py record-gate {rel_task} "
1317
1317
  f"--transition parent-integrated --gate {gate} --result PASS "
1318
1318
  f"--reviewer parent --evidence task-map.md"
1319
1319
  )
1320
1320
  elif transition == "child-review":
1321
1321
  hints.append(
1322
1322
  f"Full Child acceptance needs record-gate for child-review/{gate}: "
1323
- f"python ./.trellis/scripts/task.py record-gate {rel_task} "
1323
+ f"python ./.cstl/scripts/task.py record-gate {rel_task} "
1324
1324
  f"--transition child-review --gate {gate} --result PASS "
1325
1325
  f"--reviewer parent --evidence verify.md"
1326
1326
  )
1327
1327
  else:
1328
1328
  hints.append(
1329
1329
  f"Record reviewer gate after explicit review (never auto-PASS): "
1330
- f"python ./.trellis/scripts/task.py record-gate {rel_task} "
1330
+ f"python ./.cstl/scripts/task.py record-gate {rel_task} "
1331
1331
  f"--transition {transition} --gate {gate} --result PASS "
1332
1332
  f"--reviewer <reviewer-id> --evidence verify.md"
1333
1333
  )
@@ -1376,7 +1376,7 @@ def archive_repair_hints(
1376
1376
 
1377
1377
  if not hints and not guard.ok:
1378
1378
  hints.append(
1379
- f"Run: python ./.trellis/scripts/task.py prepare-archive-evidence {rel_task} "
1379
+ f"Run: python ./.cstl/scripts/task.py prepare-archive-evidence {rel_task} "
1380
1380
  "then archive --check again."
1381
1381
  )
1382
1382
 
@@ -1454,7 +1454,7 @@ def build_archive_evidence_draft(
1454
1454
  )
1455
1455
 
1456
1456
  if guard.is_full_task and guard.required_gates:
1457
- rel_task = f".trellis/tasks/{task_dir.name}"
1457
+ rel_task = f".cstl/tasks/{task_dir.name}"
1458
1458
  lines.extend(
1459
1459
  [
1460
1460
  "## Completion gate preparation (not recorded)",
@@ -1465,7 +1465,7 @@ def build_archive_evidence_draft(
1465
1465
  )
1466
1466
  for gate in guard.required_gates:
1467
1467
  lines.append(
1468
- f"- `python ./.trellis/scripts/task.py record-gate {rel_task} "
1468
+ f"- `python ./.cstl/scripts/task.py record-gate {rel_task} "
1469
1469
  f"--transition full-task-complete --gate {gate} --result PASS "
1470
1470
  f"--reviewer <reviewer-id> --evidence verify.md`"
1471
1471
  )
@@ -1900,7 +1900,7 @@ def start_execution_repair_hints(
1900
1900
  ) -> list[str]:
1901
1901
  """Map start-execution validation errors to actionable planning hints."""
1902
1902
  hints: list[str] = []
1903
- rel_task = f".trellis/tasks/{task_dir.name}"
1903
+ rel_task = f".cstl/tasks/{task_dir.name}"
1904
1904
  for error in errors:
1905
1905
  if error.startswith("missing gate record:"):
1906
1906
  _rest = error.split(":", 1)[1].strip()
@@ -1913,7 +1913,7 @@ def start_execution_repair_hints(
1913
1913
  )
1914
1914
  else:
1915
1915
  hints.append(
1916
- f"python ./.trellis/scripts/task.py record-gate {rel_task} "
1916
+ f"python ./.cstl/scripts/task.py record-gate {rel_task} "
1917
1917
  f"--transition start-execution --gate {gate} --result PASS "
1918
1918
  f"--reviewer <reviewer-id> --evidence verify.md"
1919
1919
  )
@@ -203,7 +203,7 @@ def _non_trellis_dirty_paths(repo_root: Path) -> list[str]:
203
203
  if " -> " in path:
204
204
  path = path.split(" -> ", 1)[1].strip()
205
205
  path = path.replace("\\", "/").strip('"')
206
- if path and path != ".trellis" and not path.startswith(".trellis/"):
206
+ if path and path != ".cstl" and not path.startswith(".cstl/"):
207
207
  dirty.append(path)
208
208
  return dirty
209
209
 
@@ -252,7 +252,7 @@ _SUBAGENT_CONFIG_DIRS: tuple[str, ...] = (
252
252
  _SEED_EXAMPLE = (
253
253
  "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. "
254
254
  "Put spec/research files only — no code paths. "
255
- "Run `python .trellis/scripts/get_context.py --mode packages` to list available specs. "
255
+ "Run `python .cstl/scripts/get_context.py --mode packages` to list available specs. "
256
256
  "Delete this line once real entries are added."
257
257
  )
258
258
 
@@ -460,7 +460,7 @@ def cmd_create(args: argparse.Namespace) -> int:
460
460
  print("", file=sys.stderr)
461
461
  print(colored("Next steps:", Colors.BLUE), file=sys.stderr)
462
462
  print(" - Fill prd.md with requirements and acceptance criteria", file=sys.stderr)
463
- print(f" - Select it when ready: python ./.trellis/scripts/task.py select {DIR_WORKFLOW}/{DIR_TASKS}/{dir_name}", file=sys.stderr)
463
+ print(f" - Select it when ready: python ./.cstl/scripts/task.py select {DIR_WORKFLOW}/{DIR_TASKS}/{dir_name}", file=sys.stderr)
464
464
  print(" - Lightweight task: PRD-only is valid", file=sys.stderr)
465
465
  print(" - Complex task: add design.md and implement.md before task.py start-execution --check", file=sys.stderr)
466
466
  if seeded_jsonl:
@@ -806,10 +806,10 @@ def _auto_commit_archive(
806
806
 
807
807
  If ``.gitignore`` blocks the paths, we warn + skip — we do NOT
808
808
  retry with ``git add -f``. The warning explicitly forbids
809
- ``git add -f .trellis/`` (which would fan out to caches/backups)
809
+ ``git add -f .cstl/`` (which would fan out to caches/backups)
810
810
  and points users at ``session_auto_commit: false``.
811
811
 
812
- Honors ``session_auto_commit`` in ``.trellis/config.yaml``: when
812
+ Honors ``session_auto_commit`` in ``.cstl/config.yaml``: when
813
813
  set to ``false``, this function returns immediately without
814
814
  touching git (the archive directory move on disk is unaffected).
815
815
  """
@@ -176,7 +176,7 @@ def resolve_task_dir(target_dir: str, repo_root: Path) -> Path:
176
176
 
177
177
  Supports:
178
178
  - Absolute path: /path/to/task
179
- - Relative path: .trellis/tasks/01-31-my-task
179
+ - Relative path: .cstl/tasks/01-31-my-task
180
180
  - Task name: my-task (uses find_task_by_name for lookup)
181
181
 
182
182
  Args:
@@ -198,7 +198,7 @@ def resolve_task_dir(target_dir: str, repo_root: Path) -> Path:
198
198
  return Path(target_dir)
199
199
 
200
200
  # Relative path (contains path separator or starts with .trellis)
201
- if "/" in normalized or normalized.startswith(".trellis"):
201
+ if "/" in normalized or normalized.startswith(".cstl"):
202
202
  return repo_root / Path(normalized)
203
203
 
204
204
  # Task name - try to find in tasks directory
@@ -270,5 +270,5 @@ if __name__ == "__main__":
270
270
  tasks = get_tasks_dir(repo)
271
271
 
272
272
  print(f"Tasks dir: {tasks}")
273
- print(f"is_safe_task_path('.trellis/tasks/test'): {is_safe_task_path('.trellis/tasks/test', repo)}")
273
+ print(f"is_safe_task_path('.cstl/tasks/test'): {is_safe_task_path('.cstl/tasks/test', repo)}")
274
274
  print(f"is_safe_task_path('../test'): {is_safe_task_path('../test', repo)}")
@@ -226,6 +226,6 @@ def parent_archive_child_followup_hint(
226
226
  return (
227
227
  f"Integrated child task dirs still active: {names}. "
228
228
  "Archive each child when ready: "
229
- f"python ./.trellis/scripts/task.py archive <child> "
229
+ f"python ./.cstl/scripts/task.py archive <child> "
230
230
  "(or parent archive with --archive-integrated-children after archive --check passes for each)."
231
231
  )
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Standalone reader for .trellis/config.yaml.
3
+ Standalone reader for .cstl/config.yaml.
4
4
 
5
5
  Mirrors a minimal subset of common.config so callers (hooks, workflow_phase)
6
6
  can read configuration without importing the full task/repo helpers. Returns
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
  from typing import Optional
14
14
 
15
15
 
16
- CONFIG_REL_PATH = ".trellis/config.yaml"
16
+ CONFIG_REL_PATH = ".cstl/config.yaml"
17
17
 
18
18
 
19
19
  def _unquote(value: str) -> str:
@@ -117,7 +117,7 @@ def parse_simple_yaml(content: str) -> dict:
117
117
 
118
118
 
119
119
  def read_trellis_config(repo_root: Optional[Path] = None) -> dict:
120
- """Read .trellis/config.yaml. Returns {} on missing or malformed file."""
120
+ """Read .cstl/config.yaml. Returns {} on missing or malformed file."""
121
121
  root = repo_root or Path.cwd()
122
122
  config_file = root / CONFIG_REL_PATH
123
123
  try:
@@ -3,7 +3,7 @@
3
3
  """
4
4
  Workflow Phase Extraction.
5
5
 
6
- Extracts step-level content from .trellis/workflow.md and optionally filters
6
+ Extracts step-level content from .cstl/workflow.md and optionally filters
7
7
  platform-specific blocks.
8
8
 
9
9
  Platform marker syntax in workflow.md:
@@ -76,10 +76,10 @@ def _probe_grep(repo_root: Path) -> dict[str, object]:
76
76
  """P-01: Grep a known literal in a known file under the repo.
77
77
 
78
78
  Known answer: 'TRELLIS_B2_WPeLc8' must appear in
79
- .trellis/local/cursor2plus/patch_wpelc8.py (the MARKER constant).
79
+ .cstl/local/cursor2plus/patch_wpelc8.py (the MARKER constant).
80
80
  """
81
81
  marker = "TRELLIS_B2_WPeLc8"
82
- target = repo_root / ".trellis" / "local" / "cursor2plus" / "patch_wpelc8.py"
82
+ target = repo_root / ".cstl" / "local" / "cursor2plus" / "patch_wpelc8.py"
83
83
  ok_file = target.is_file()
84
84
  found = False
85
85
  matches: list[str] = []
@@ -172,7 +172,7 @@ def _probe_smart_search(repo_root: Path) -> dict[str, object]:
172
172
  argv without running a network search. A separate `doctor` invocation is
173
173
  attempted if the resolved entrypoint is the smart-search package CLI.
174
174
  """
175
- scripts_dir = repo_root / ".trellis" / "scripts"
175
+ scripts_dir = repo_root / ".cstl" / "scripts"
176
176
  if str(scripts_dir) not in sys.path:
177
177
  sys.path.insert(0, str(scripts_dir))
178
178
  resolved: list[str] | None = None