@pennixrv/trellis 0.6.45 → 0.7.0-beta.11

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 (117) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +21 -3
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/channel/adapters/codex.d.ts +2 -1
  5. package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
  6. package/dist/commands/channel/adapters/codex.js +10 -7
  7. package/dist/commands/channel/adapters/codex.js.map +1 -1
  8. package/dist/commands/channel/adapters/index.d.ts +2 -0
  9. package/dist/commands/channel/adapters/index.d.ts.map +1 -1
  10. package/dist/commands/channel/adapters/index.js +1 -1
  11. package/dist/commands/channel/adapters/index.js.map +1 -1
  12. package/dist/commands/channel/index.d.ts.map +1 -1
  13. package/dist/commands/channel/index.js +6 -0
  14. package/dist/commands/channel/index.js.map +1 -1
  15. package/dist/commands/channel/profiles.d.ts +26 -0
  16. package/dist/commands/channel/profiles.d.ts.map +1 -0
  17. package/dist/commands/channel/profiles.js +186 -0
  18. package/dist/commands/channel/profiles.js.map +1 -0
  19. package/dist/commands/channel/spawn.d.ts +3 -0
  20. package/dist/commands/channel/spawn.d.ts.map +1 -1
  21. package/dist/commands/channel/spawn.js +22 -3
  22. package/dist/commands/channel/spawn.js.map +1 -1
  23. package/dist/commands/channel/supervisor.d.ts +8 -0
  24. package/dist/commands/channel/supervisor.d.ts.map +1 -1
  25. package/dist/commands/channel/supervisor.js +19 -0
  26. package/dist/commands/channel/supervisor.js.map +1 -1
  27. package/dist/commands/mem.d.ts.map +1 -1
  28. package/dist/commands/mem.js +6 -13
  29. package/dist/commands/mem.js.map +1 -1
  30. package/dist/commands/workflow.d.ts +17 -0
  31. package/dist/commands/workflow.d.ts.map +1 -1
  32. package/dist/commands/workflow.js +222 -0
  33. package/dist/commands/workflow.js.map +1 -1
  34. package/dist/configurators/claude.d.ts.map +1 -1
  35. package/dist/configurators/claude.js.map +1 -1
  36. package/dist/configurators/dsh.d.ts +16 -19
  37. package/dist/configurators/dsh.d.ts.map +1 -1
  38. package/dist/configurators/dsh.js +38 -26
  39. package/dist/configurators/dsh.js.map +1 -1
  40. package/dist/configurators/gemini.d.ts.map +1 -1
  41. package/dist/configurators/gemini.js.map +1 -1
  42. package/dist/configurators/opencode.d.ts.map +1 -1
  43. package/dist/configurators/opencode.js +4 -0
  44. package/dist/configurators/opencode.js.map +1 -1
  45. package/dist/migrations/manifests/0.6.17.json +2 -2
  46. package/dist/migrations/manifests/0.7.0-beta.10.json +9 -0
  47. package/dist/migrations/manifests/0.7.0-beta.11.json +9 -0
  48. package/dist/migrations/manifests/0.7.0-beta.4.json +9 -0
  49. package/dist/migrations/manifests/0.7.0-beta.4.pennix.1.json +9 -0
  50. package/dist/migrations/manifests/0.7.0-beta.5.json +9 -0
  51. package/dist/migrations/manifests/0.7.0-beta.6.json +9 -0
  52. package/dist/migrations/manifests/0.7.0-beta.7.json +9 -0
  53. package/dist/migrations/manifests/0.7.0-beta.8.json +9 -0
  54. package/dist/migrations/manifests/0.7.0-beta.9.json +9 -0
  55. package/dist/templates/claude/hooks/statusline.py +7 -0
  56. package/dist/templates/claude/settings.json +22 -0
  57. package/dist/templates/codex/hooks/session-start.py +20 -1
  58. package/dist/templates/codex/hooks.json +25 -0
  59. package/dist/templates/common/bundled-skills/trellis-channel/references/subnode-work.md +32 -3
  60. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +2 -2
  61. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +1 -0
  62. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +2 -1
  63. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +3 -2
  64. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +1 -1
  65. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +5 -4
  66. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +1 -0
  67. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +2 -2
  68. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +3 -2
  69. package/dist/templates/common/commands/continue.md +4 -2
  70. package/dist/templates/common/skills/brainstorm.md +14 -6
  71. package/dist/templates/copilot/hooks/session-start.py +20 -1
  72. package/dist/templates/copilot/prompts/brainstorm.prompt.md +16 -6
  73. package/dist/templates/dsh/DSH.md +61 -37
  74. package/dist/templates/dsh/agents/trellis-check.md +99 -0
  75. package/dist/templates/dsh/agents/trellis-implement.md +106 -0
  76. package/dist/templates/dsh/agents/trellis-research.md +134 -0
  77. package/dist/templates/dsh/index.d.ts +12 -11
  78. package/dist/templates/dsh/index.d.ts.map +1 -1
  79. package/dist/templates/dsh/index.js +14 -12
  80. package/dist/templates/dsh/index.js.map +1 -1
  81. package/dist/templates/opencode/plugins/inject-spec-context.js +121 -0
  82. package/dist/templates/opencode/plugins/inject-workflow-state.js +111 -10
  83. package/dist/templates/pi/extensions/trellis/index.ts.txt +164 -10
  84. package/dist/templates/shared-hooks/index.d.ts +8 -2
  85. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  86. package/dist/templates/shared-hooks/index.js +13 -1
  87. package/dist/templates/shared-hooks/index.js.map +1 -1
  88. package/dist/templates/shared-hooks/inject-shell-session-context.py +3 -3
  89. package/dist/templates/shared-hooks/inject-spec-context.py +844 -0
  90. package/dist/templates/shared-hooks/inject-workflow-state.py +35 -9
  91. package/dist/templates/shared-hooks/session-start.py +22 -1
  92. package/dist/templates/trellis/agents/subnode-profiles.json +14 -0
  93. package/dist/templates/trellis/agents/subnode.md +11 -4
  94. package/dist/templates/trellis/config.yaml +49 -0
  95. package/dist/templates/trellis/index.d.ts +4 -0
  96. package/dist/templates/trellis/index.d.ts.map +1 -1
  97. package/dist/templates/trellis/index.js +8 -0
  98. package/dist/templates/trellis/index.js.map +1 -1
  99. package/dist/templates/trellis/scripts/common/active_task.py +26 -4
  100. package/dist/templates/trellis/scripts/common/cli_adapter.py +38 -6
  101. package/dist/templates/trellis/scripts/common/config.py +18 -0
  102. package/dist/templates/trellis/scripts/common/context_projection.py +2 -2
  103. package/dist/templates/trellis/scripts/common/git_context.py +34 -2
  104. package/dist/templates/trellis/scripts/common/paths.py +28 -0
  105. package/dist/templates/trellis/scripts/common/spec_inject.py +439 -0
  106. package/dist/templates/trellis/scripts/common/spec_match.py +395 -0
  107. package/dist/templates/trellis/scripts/common/task_store.py +88 -1
  108. package/dist/templates/trellis/scripts/common/trellis_config.py +46 -7
  109. package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -2
  110. package/dist/templates/trellis/scripts/common/workflow_selection.py +177 -0
  111. package/dist/templates/trellis/scripts/subnode_artifact.py +416 -15
  112. package/dist/templates/trellis/scripts/task.py +160 -0
  113. package/dist/templates/trellis/workflow.md +49 -34
  114. package/dist/types/ai-tools.d.ts.map +1 -1
  115. package/dist/types/ai-tools.js +26 -13
  116. package/dist/types/ai-tools.js.map +1 -1
  117. package/package.json +2 -2
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Per-task workflow selection.
4
+
5
+ Resolves which workflow markdown file consumers should read. A task may pin
6
+ a workflow variant by storing `"workflow": "<id>"` in its task.json; the
7
+ variant body lives at `.trellis/workflows/<id>.md` (user-managed library).
8
+
9
+ Resolution precedence (single source of truth for all consumers), highest
10
+ to lowest — each layer resolves an id to `.trellis/workflows/<id>.md` and
11
+ falls through when unset, invalid, or pointing at a missing file:
12
+ 1. Per-task pin - active task's task.json `workflow` (session-bound,
13
+ explicit; a bad id or missing file warns once on stderr, then falls
14
+ through rather than aborting).
15
+ 2. Personal - `.developer` `workflow=<id>` (gitignored, per-developer;
16
+ outranks the team default). Silent on miss.
17
+ 3. Team default - config.yaml `default_workflow` (git-tracked, shared).
18
+ Silent on miss.
19
+ 4. Global - `.trellis/workflow.md`.
20
+ With neither a per-task pin nor the personal/team keys set, this is identical
21
+ to reading the global `.trellis/workflow.md`. Never raises.
22
+
23
+ Provides:
24
+ workflow_md_for_task - Full precedence for an already-resolved task dir
25
+ resolve_workflow_md - Session-aware wrapper via the active task resolver
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ import json
31
+ import re
32
+ import sys
33
+ from pathlib import Path
34
+
35
+ from .paths import DIR_WORKFLOW, FILE_TASK_JSON
36
+
37
+ # Workflow variant library directory under .trellis/ (plural on purpose:
38
+ # `.trellis/workflow/` is reserved by the YAML-manifest migration).
39
+ DIR_WORKFLOWS = "workflows"
40
+
41
+ # Workflow ids must be plain slugs; anything else (path separators, dots)
42
+ # is rejected so a task.json value can never escape .trellis/workflows/.
43
+ WORKFLOW_ID_RE = re.compile(r"^[A-Za-z0-9_-]+$")
44
+
45
+
46
+ def _global_workflow_md(repo_root: Path) -> Path:
47
+ return repo_root / DIR_WORKFLOW / "workflow.md"
48
+
49
+
50
+ def _library_variant(repo_root: Path, workflow_id: str | None) -> Path | None:
51
+ """Map a workflow id to its library file if valid and present, else None.
52
+
53
+ Shared by every layer (per-task pin, personal, team). An id with path
54
+ separators/dots/blanks, or one whose `.trellis/workflows/<id>.md` file does
55
+ not exist, returns None so the caller falls through. Never raises.
56
+ """
57
+ if not isinstance(workflow_id, str) or not workflow_id:
58
+ return None
59
+ if not WORKFLOW_ID_RE.match(workflow_id):
60
+ return None
61
+ variant = repo_root / DIR_WORKFLOW / DIR_WORKFLOWS / f"{workflow_id}.md"
62
+ return variant if variant.is_file() else None
63
+
64
+
65
+ def _developer_workflow_id(repo_root: Path) -> str | None:
66
+ """Personal override id from the gitignored .developer file (fail-open)."""
67
+ try:
68
+ from .paths import get_developer_workflow
69
+
70
+ return get_developer_workflow(repo_root)
71
+ except Exception:
72
+ return None
73
+
74
+
75
+ def _config_default_id(repo_root: Path) -> str | None:
76
+ """Team-shared default id from config.yaml `default_workflow` (fail-open)."""
77
+ try:
78
+ from .config import get_default_workflow
79
+
80
+ return get_default_workflow(repo_root)
81
+ except Exception:
82
+ return None
83
+
84
+
85
+ def _default_workflow_md(repo_root: Path) -> Path:
86
+ """Resolve the non-per-task default: personal -> team -> global.
87
+
88
+ Personal (`.developer` `workflow=`) outranks the team-shared
89
+ (config.yaml `default_workflow`) layer; both fall through to the global
90
+ `.trellis/workflow.md` when unset, invalid, or naming a missing file. These
91
+ layers are silent on miss (they are defaults, not an explicit per-task
92
+ choice — a per-turn warning would be noise).
93
+ """
94
+ for get_id in (_developer_workflow_id, _config_default_id):
95
+ variant = _library_variant(repo_root, get_id(repo_root))
96
+ if variant is not None:
97
+ return variant
98
+ return _global_workflow_md(repo_root)
99
+
100
+
101
+ def _task_pin_variant(repo_root: Path, task_dir: Path | None) -> Path | None:
102
+ """Return the per-task pinned variant path, or None to fall through.
103
+
104
+ Emits a stderr warning on an invalid id or a missing variant file (an
105
+ explicit per-task choice that cannot be honored), then returns None so
106
+ resolution continues with the personal/team defaults. Never raises.
107
+ """
108
+ if task_dir is None:
109
+ return None
110
+
111
+ try:
112
+ raw = json.loads((task_dir / FILE_TASK_JSON).read_text(encoding="utf-8"))
113
+ if not isinstance(raw, dict):
114
+ return None
115
+
116
+ workflow_id = raw.get("workflow")
117
+ if not isinstance(workflow_id, str) or not workflow_id:
118
+ return None
119
+
120
+ if not WORKFLOW_ID_RE.match(workflow_id):
121
+ print(
122
+ f"Warning: task '{task_dir.name}' has invalid workflow id "
123
+ f"{workflow_id!r}; using default workflow resolution",
124
+ file=sys.stderr,
125
+ )
126
+ return None
127
+
128
+ variant = _library_variant(repo_root, workflow_id)
129
+ if variant is not None:
130
+ return variant
131
+
132
+ print(
133
+ f"Warning: task '{task_dir.name}' selects workflow '{workflow_id}' but "
134
+ f"{DIR_WORKFLOW}/{DIR_WORKFLOWS}/{workflow_id}.md is missing; "
135
+ f"using default workflow resolution",
136
+ file=sys.stderr,
137
+ )
138
+ return None
139
+ except Exception:
140
+ return None
141
+
142
+
143
+ def workflow_md_for_task(repo_root: Path, task_dir: Path | None) -> Path:
144
+ """Return the workflow.md path for an already-resolved task dir (or None).
145
+
146
+ Applies the full precedence documented in the module docstring:
147
+ per-task pin -> personal (.developer) -> team (config.yaml) -> global.
148
+ Never raises; any failure falls through toward the global workflow path.
149
+ """
150
+ pin = _task_pin_variant(repo_root, task_dir)
151
+ if pin is not None:
152
+ return pin
153
+ return _default_workflow_md(repo_root)
154
+
155
+
156
+ def resolve_workflow_md(
157
+ repo_root: Path,
158
+ input_data: dict | None = None,
159
+ platform: str | None = None,
160
+ ) -> Path:
161
+ """Resolve the session-aware active task, then apply the resolution rule.
162
+
163
+ ``input_data`` is the raw hook payload (session/conversation identity);
164
+ CLI callers may omit it — the active-task resolver then falls back to
165
+ environment context. Never raises; any failure resolves to the global
166
+ `.trellis/workflow.md`.
167
+ """
168
+ try:
169
+ from .active_task import resolve_active_task, resolve_task_ref
170
+
171
+ active = resolve_active_task(repo_root, input_data, platform)
172
+ task_dir: Path | None = None
173
+ if active.task_path:
174
+ task_dir = resolve_task_ref(active.task_path, repo_root)
175
+ return workflow_md_for_task(repo_root, task_dir)
176
+ except Exception:
177
+ return _global_workflow_md(repo_root)