@mindfoldhq/trellis 0.5.0-beta.8 → 0.5.0-rc.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.
- package/README.md +60 -95
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +474 -210
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +295 -54
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/antigravity.d.ts.map +1 -1
- package/dist/configurators/antigravity.js +2 -8
- package/dist/configurators/antigravity.js.map +1 -1
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +4 -10
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/codebuddy.d.ts.map +1 -1
- package/dist/configurators/codebuddy.js +3 -3
- package/dist/configurators/codebuddy.js.map +1 -1
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +5 -13
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/copilot.d.ts.map +1 -1
- package/dist/configurators/copilot.js +5 -19
- package/dist/configurators/copilot.js.map +1 -1
- package/dist/configurators/cursor.d.ts.map +1 -1
- package/dist/configurators/cursor.js +3 -3
- package/dist/configurators/cursor.js.map +1 -1
- package/dist/configurators/droid.d.ts.map +1 -1
- package/dist/configurators/droid.js +3 -3
- package/dist/configurators/droid.js.map +1 -1
- package/dist/configurators/gemini.d.ts.map +1 -1
- package/dist/configurators/gemini.js +3 -5
- package/dist/configurators/gemini.js.map +1 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +44 -55
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/kilo.d.ts.map +1 -1
- package/dist/configurators/kilo.js +2 -8
- package/dist/configurators/kilo.js.map +1 -1
- package/dist/configurators/kiro.d.ts.map +1 -1
- package/dist/configurators/kiro.js +3 -3
- package/dist/configurators/kiro.js.map +1 -1
- package/dist/configurators/opencode.d.ts.map +1 -1
- package/dist/configurators/opencode.js +7 -4
- package/dist/configurators/opencode.js.map +1 -1
- package/dist/configurators/pi.d.ts +3 -0
- package/dist/configurators/pi.d.ts.map +1 -0
- package/dist/configurators/pi.js +44 -0
- package/dist/configurators/pi.js.map +1 -0
- package/dist/configurators/qoder.d.ts +7 -6
- package/dist/configurators/qoder.d.ts.map +1 -1
- package/dist/configurators/qoder.js +18 -12
- package/dist/configurators/qoder.js.map +1 -1
- package/dist/configurators/shared.d.ts +30 -6
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +65 -15
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/windsurf.d.ts.map +1 -1
- package/dist/configurators/windsurf.js +2 -8
- package/dist/configurators/windsurf.js.map +1 -1
- package/dist/constants/paths.d.ts +2 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +2 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.5.0-beta.0.json +2 -0
- package/dist/migrations/manifests/0.5.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.15.json +116 -0
- package/dist/migrations/manifests/0.5.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.17.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.18.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.19.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.5.json +2 -0
- package/dist/migrations/manifests/0.5.0-beta.9.json +48 -0
- package/dist/migrations/manifests/0.5.0-rc.0.json +9 -0
- package/dist/templates/claude/agents/trellis-research.md +1 -1
- package/dist/templates/claude/settings.json +0 -4
- package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
- package/dist/templates/codex/agents/trellis-research.toml +3 -2
- package/dist/templates/codex/hooks/session-start.py +126 -26
- package/dist/templates/codex/skills/finish-work/SKILL.md +41 -109
- package/dist/templates/codex/skills/start/SKILL.md +12 -9
- package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +73 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +54 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +81 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +78 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +90 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +64 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +55 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +51 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +101 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +75 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +79 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +69 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +59 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +74 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +83 -0
- package/dist/templates/common/commands/continue.md +9 -5
- package/dist/templates/common/commands/finish-work.md +34 -10
- package/dist/templates/common/index.d.ts +22 -2
- package/dist/templates/common/index.d.ts.map +1 -1
- package/dist/templates/common/index.js +53 -4
- package/dist/templates/common/index.js.map +1 -1
- package/dist/templates/common/skills/brainstorm.md +50 -4
- package/dist/templates/copilot/hooks/session-start.py +127 -30
- package/dist/templates/copilot/prompts/finish-work.prompt.md +44 -112
- package/dist/templates/copilot/prompts/start.prompt.md +12 -9
- package/dist/templates/cursor/agents/trellis-check.md +1 -1
- package/dist/templates/cursor/agents/trellis-implement.md +1 -1
- package/dist/templates/cursor/agents/trellis-research.md +2 -2
- package/dist/templates/cursor/hooks.json +7 -1
- package/dist/templates/droid/droids/trellis-research.md +1 -1
- package/dist/templates/extract.d.ts +6 -0
- package/dist/templates/extract.d.ts.map +1 -1
- package/dist/templates/extract.js +14 -0
- package/dist/templates/extract.js.map +1 -1
- package/dist/templates/gemini/agents/trellis-research.md +1 -1
- package/dist/templates/kiro/agents/trellis-research.json +1 -1
- package/dist/templates/markdown/agents.md +19 -12
- package/dist/templates/markdown/gitignore.txt +3 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +24 -0
- package/dist/templates/opencode/agents/trellis-check.md +1 -1
- package/dist/templates/opencode/agents/trellis-implement.md +7 -4
- package/dist/templates/opencode/agents/trellis-research.md +2 -2
- package/dist/templates/opencode/lib/trellis-context.js +100 -13
- package/dist/templates/opencode/plugins/inject-subagent-context.js +70 -5
- package/dist/templates/opencode/plugins/inject-workflow-state.js +38 -44
- package/dist/templates/opencode/plugins/session-start.js +76 -31
- package/dist/templates/pi/agents/trellis-check.md +28 -0
- package/dist/templates/pi/agents/trellis-implement.md +33 -0
- package/dist/templates/pi/agents/trellis-research.md +25 -0
- package/dist/templates/pi/extensions/trellis/index.ts.txt +997 -0
- package/dist/templates/pi/index.d.ts +5 -0
- package/dist/templates/pi/index.d.ts.map +1 -0
- package/dist/templates/pi/index.js +12 -0
- package/dist/templates/pi/index.js.map +1 -0
- package/dist/templates/pi/settings.json +12 -0
- package/dist/templates/qoder/agents/trellis-research.md +1 -1
- package/dist/templates/shared-hooks/index.d.ts +31 -0
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +59 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-shell-session-context.py +180 -0
- package/dist/templates/shared-hooks/inject-subagent-context.py +156 -27
- package/dist/templates/shared-hooks/inject-workflow-state.py +85 -92
- package/dist/templates/shared-hooks/session-start.py +232 -36
- package/dist/templates/trellis/config.yaml +6 -0
- package/dist/templates/trellis/gitignore.txt +3 -0
- package/dist/templates/trellis/index.d.ts +1 -1
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +2 -2
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/common/__init__.py +8 -0
- package/dist/templates/trellis/scripts/common/active_task.py +593 -0
- package/dist/templates/trellis/scripts/common/cli_adapter.py +72 -14
- package/dist/templates/trellis/scripts/common/paths.py +61 -58
- package/dist/templates/trellis/scripts/common/session_context.py +12 -0
- package/dist/templates/trellis/scripts/common/task_context.py +27 -194
- package/dist/templates/trellis/scripts/common/task_store.py +102 -26
- package/dist/templates/trellis/scripts/common/tasks.py +4 -1
- package/dist/templates/trellis/scripts/common/types.py +0 -2
- package/dist/templates/trellis/scripts/common/workflow_phase.py +15 -3
- package/dist/templates/trellis/scripts/task.py +99 -34
- package/dist/templates/trellis/workflow.md +332 -64
- package/dist/types/ai-tools.d.ts +12 -3
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +29 -0
- package/dist/types/ai-tools.js.map +1 -1
- package/dist/utils/file-writer.d.ts.map +1 -1
- package/dist/utils/file-writer.js +7 -2
- package/dist/utils/file-writer.js.map +1 -1
- package/dist/utils/posix.d.ts +13 -0
- package/dist/utils/posix.d.ts.map +1 -0
- package/dist/utils/posix.js +15 -0
- package/dist/utils/posix.js.map +1 -0
- package/dist/utils/project-detector.d.ts +2 -0
- package/dist/utils/project-detector.d.ts.map +1 -1
- package/dist/utils/project-detector.js +120 -11
- package/dist/utils/project-detector.js.map +1 -1
- package/dist/utils/task-json.d.ts +46 -0
- package/dist/utils/task-json.d.ts.map +1 -0
- package/dist/utils/task-json.js +49 -0
- package/dist/utils/task-json.js.map +1 -0
- package/dist/utils/template-fetcher.d.ts +22 -6
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +405 -27
- package/dist/utils/template-fetcher.js.map +1 -1
- package/dist/utils/template-hash.d.ts +22 -3
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +99 -19
- package/dist/utils/template-hash.js.map +1 -1
- package/package.json +7 -7
- package/dist/templates/markdown/spec/backend/directory-structure.md +0 -292
- package/dist/templates/markdown/spec/backend/index.md +0 -40
- package/dist/templates/markdown/spec/backend/script-conventions.md +0 -742
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md +0 -118
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md +0 -394
- package/dist/templates/shared-hooks/statusline.py +0 -218
- package/dist/templates/trellis/scripts/create_bootstrap.py +0 -298
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Trellis UserPromptSubmit hook: inject per-turn workflow breadcrumb.
|
|
3
3
|
|
|
4
|
-
Runs on every user prompt.
|
|
5
|
-
and emits a short <workflow-state>
|
|
6
|
-
is active and its expected flow.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
Runs on every user prompt. Resolves the active task through Trellis'
|
|
5
|
+
session-aware active task resolver and emits a short <workflow-state>
|
|
6
|
+
block reminding the main AI what task is active and its expected flow.
|
|
7
|
+
Breadcrumb text is pulled exclusively from workflow.md
|
|
8
|
+
[workflow-state:STATUS] tag blocks — workflow.md is the single source of
|
|
9
|
+
truth. There are no fallback dicts in this script: when workflow.md is
|
|
10
|
+
missing or a tag is absent, the breadcrumb degrades to a generic
|
|
11
|
+
"Refer to workflow.md for current step." line so users see (and fix)
|
|
12
|
+
the broken state instead of the hook silently masking it.
|
|
10
13
|
|
|
11
14
|
Shared across all hook-capable platforms (Claude, Cursor, Codex, Qoder,
|
|
12
15
|
CodeBuddy, Droid, Gemini, Copilot). Kiro is not wired (no per-turn
|
|
@@ -15,12 +18,7 @@ writeSharedHooks() at init time.
|
|
|
15
18
|
|
|
16
19
|
Silent exit 0 cases (no output):
|
|
17
20
|
- No .trellis/ directory found (not a Trellis project)
|
|
18
|
-
- No .current-task file, or it's empty
|
|
19
21
|
- task.json malformed or missing status
|
|
20
|
-
|
|
21
|
-
Unknown status (no tag + no hardcoded fallback) emits a generic
|
|
22
|
-
breadcrumb rather than silent-exiting, so custom statuses surface in
|
|
23
|
-
the UI instead of appearing as "randomly broken".
|
|
24
22
|
"""
|
|
25
23
|
from __future__ import annotations
|
|
26
24
|
|
|
@@ -29,7 +27,7 @@ import os
|
|
|
29
27
|
import re
|
|
30
28
|
import sys
|
|
31
29
|
from pathlib import Path
|
|
32
|
-
from typing import Optional
|
|
30
|
+
from typing import Optional
|
|
33
31
|
|
|
34
32
|
|
|
35
33
|
# ---------------------------------------------------------------------------
|
|
@@ -54,48 +52,63 @@ def find_trellis_root(start: Path) -> Optional[Path]:
|
|
|
54
52
|
# Active task discovery
|
|
55
53
|
# ---------------------------------------------------------------------------
|
|
56
54
|
|
|
57
|
-
def
|
|
58
|
-
""
|
|
55
|
+
def _detect_platform(input_data: dict) -> str | None:
|
|
56
|
+
if isinstance(input_data.get("cursor_version"), str):
|
|
57
|
+
return "cursor"
|
|
58
|
+
env_map = {
|
|
59
|
+
"CLAUDE_PROJECT_DIR": "claude",
|
|
60
|
+
"CURSOR_PROJECT_DIR": "cursor",
|
|
61
|
+
"CODEBUDDY_PROJECT_DIR": "codebuddy",
|
|
62
|
+
"FACTORY_PROJECT_DIR": "droid",
|
|
63
|
+
"GEMINI_PROJECT_DIR": "gemini",
|
|
64
|
+
"QODER_PROJECT_DIR": "qoder",
|
|
65
|
+
"KIRO_PROJECT_DIR": "kiro",
|
|
66
|
+
"COPILOT_PROJECT_DIR": "copilot",
|
|
67
|
+
}
|
|
68
|
+
for env_name, platform in env_map.items():
|
|
69
|
+
if os.environ.get(env_name):
|
|
70
|
+
return platform
|
|
71
|
+
script_parts = set(Path(sys.argv[0]).parts)
|
|
72
|
+
if ".claude" in script_parts:
|
|
73
|
+
return "claude"
|
|
74
|
+
if ".cursor" in script_parts:
|
|
75
|
+
return "cursor"
|
|
76
|
+
if ".codex" in script_parts:
|
|
77
|
+
return "codex"
|
|
78
|
+
if ".gemini" in script_parts:
|
|
79
|
+
return "gemini"
|
|
80
|
+
if ".qoder" in script_parts:
|
|
81
|
+
return "qoder"
|
|
82
|
+
if ".codebuddy" in script_parts:
|
|
83
|
+
return "codebuddy"
|
|
84
|
+
if ".factory" in script_parts:
|
|
85
|
+
return "droid"
|
|
86
|
+
if ".kiro" in script_parts:
|
|
87
|
+
return "kiro"
|
|
88
|
+
return None
|
|
59
89
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if normalized.startswith("tasks/"):
|
|
75
|
-
normalized = f".trellis/{normalized}"
|
|
76
|
-
return normalized
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def get_active_task(root: Path) -> Optional[Tuple[str, str]]:
|
|
80
|
-
"""Return (task_id, status) from the current active task, else None.
|
|
81
|
-
|
|
82
|
-
Reads .trellis/.current-task (a path relative to root, e.g.
|
|
83
|
-
".trellis/tasks/04-17-foo") then that task's task.json.
|
|
84
|
-
Normalizes backslashes so Windows paths work on Unix and vice versa.
|
|
85
|
-
"""
|
|
86
|
-
ref_file = root / ".trellis" / ".current-task"
|
|
87
|
-
if not ref_file.is_file():
|
|
88
|
-
return None
|
|
89
|
-
try:
|
|
90
|
-
raw = ref_file.read_text(encoding="utf-8").strip()
|
|
91
|
-
except OSError:
|
|
92
|
-
return None
|
|
93
|
-
task_ref = _normalize_task_ref(raw)
|
|
94
|
-
if not task_ref:
|
|
90
|
+
|
|
91
|
+
def _resolve_active_task(root: Path, input_data: dict):
|
|
92
|
+
scripts_dir = root / ".trellis" / "scripts"
|
|
93
|
+
if str(scripts_dir) not in sys.path:
|
|
94
|
+
sys.path.insert(0, str(scripts_dir))
|
|
95
|
+
from common.active_task import resolve_active_task # type: ignore[import-not-found]
|
|
96
|
+
|
|
97
|
+
return resolve_active_task(root, input_data, platform=_detect_platform(input_data))
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_active_task(root: Path, input_data: dict) -> Optional[tuple[str, str, str]]:
|
|
101
|
+
"""Return (task_id, status, source) from the current active task."""
|
|
102
|
+
active = _resolve_active_task(root, input_data)
|
|
103
|
+
if not active.task_path:
|
|
95
104
|
return None
|
|
96
105
|
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
task_dir = Path(active.task_path)
|
|
107
|
+
if not task_dir.is_absolute():
|
|
108
|
+
task_dir = root / task_dir
|
|
109
|
+
if active.stale:
|
|
110
|
+
return task_dir.name, f"stale_{active.source_type}", active.source
|
|
111
|
+
|
|
99
112
|
task_json = task_dir / "task.json"
|
|
100
113
|
if not task_json.is_file():
|
|
101
114
|
return None
|
|
@@ -108,7 +121,7 @@ def get_active_task(root: Path) -> Optional[Tuple[str, str]]:
|
|
|
108
121
|
status = data.get("status", "")
|
|
109
122
|
if not isinstance(status, str) or not status:
|
|
110
123
|
return None
|
|
111
|
-
return task_id, status
|
|
124
|
+
return task_id, status, active.source
|
|
112
125
|
|
|
113
126
|
|
|
114
127
|
# ---------------------------------------------------------------------------
|
|
@@ -122,51 +135,24 @@ _TAG_RE = re.compile(
|
|
|
122
135
|
re.DOTALL,
|
|
123
136
|
)
|
|
124
137
|
|
|
125
|
-
# Hardcoded defaults for built-in Trellis statuses. Used when workflow.md is
|
|
126
|
-
# missing, malformed, or lacks the tag for this status.
|
|
127
|
-
#
|
|
128
|
-
# `no_task` is a pseudo-status emitted when .current-task is missing — it keeps
|
|
129
|
-
# the Next-Action reminder flowing per-turn even without an active task.
|
|
130
|
-
_FALLBACK_BREADCRUMBS = {
|
|
131
|
-
"no_task": (
|
|
132
|
-
"No active task. If the user describes multi-step work, load "
|
|
133
|
-
"trellis-brainstorm skill to clarify requirements and create a task "
|
|
134
|
-
"via `python3 ./.trellis/scripts/task.py create`. Simple one-off "
|
|
135
|
-
"questions or trivial edits don't need a task — just answer directly."
|
|
136
|
-
),
|
|
137
|
-
"planning": (
|
|
138
|
-
"Complete prd.md via trellis-brainstorm skill; "
|
|
139
|
-
"then run task.py start."
|
|
140
|
-
),
|
|
141
|
-
"in_progress": (
|
|
142
|
-
"Flow: implement → check → update-spec → finish\n"
|
|
143
|
-
"Check conversation history + git status to determine current step; "
|
|
144
|
-
"do NOT skip check."
|
|
145
|
-
),
|
|
146
|
-
"completed": (
|
|
147
|
-
"User commits changes; then run task.py archive."
|
|
148
|
-
),
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
138
|
def load_breadcrumbs(root: Path) -> dict[str, str]:
|
|
153
139
|
"""Parse workflow.md for [workflow-state:STATUS] blocks.
|
|
154
140
|
|
|
155
|
-
Returns {status: body_text}.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
141
|
+
Returns {status: body_text}. workflow.md is the single source of
|
|
142
|
+
truth — there are no fallback dicts in this script. Missing tags
|
|
143
|
+
(or a missing/unreadable workflow.md) fall back to a generic line
|
|
144
|
+
in build_breadcrumb so users see the broken state and fix
|
|
145
|
+
workflow.md, rather than the hook silently masking the issue.
|
|
159
146
|
"""
|
|
160
|
-
result = dict(_FALLBACK_BREADCRUMBS)
|
|
161
|
-
|
|
162
147
|
workflow = root / ".trellis" / "workflow.md"
|
|
163
148
|
if not workflow.is_file():
|
|
164
|
-
return
|
|
149
|
+
return {}
|
|
165
150
|
try:
|
|
166
151
|
content = workflow.read_text(encoding="utf-8")
|
|
167
152
|
except OSError:
|
|
168
|
-
return
|
|
153
|
+
return {}
|
|
169
154
|
|
|
155
|
+
result: dict[str, str] = {}
|
|
170
156
|
for match in _TAG_RE.finditer(content):
|
|
171
157
|
status = match.group(1)
|
|
172
158
|
body = match.group(2).strip()
|
|
@@ -176,18 +162,24 @@ def load_breadcrumbs(root: Path) -> dict[str, str]:
|
|
|
176
162
|
|
|
177
163
|
|
|
178
164
|
def build_breadcrumb(
|
|
179
|
-
task_id: Optional[str],
|
|
165
|
+
task_id: Optional[str],
|
|
166
|
+
status: str,
|
|
167
|
+
templates: dict[str, str],
|
|
168
|
+
source: str | None = None,
|
|
180
169
|
) -> str:
|
|
181
170
|
"""Build the <workflow-state>...</workflow-state> block.
|
|
182
171
|
|
|
183
|
-
- Known status (
|
|
184
|
-
- Unknown status (no tag
|
|
172
|
+
- Known status (tag present in workflow.md) → detailed template body
|
|
173
|
+
- Unknown status (no tag, or workflow.md missing) → generic
|
|
174
|
+
"Refer to workflow.md for current step." line
|
|
185
175
|
- `no_task` pseudo-status (task_id is None) → header omits task info
|
|
186
176
|
"""
|
|
187
177
|
body = templates.get(status)
|
|
188
178
|
if body is None:
|
|
189
179
|
body = "Refer to workflow.md for current step."
|
|
190
180
|
header = f"Status: {status}" if task_id is None else f"Task: {task_id} ({status})"
|
|
181
|
+
if source:
|
|
182
|
+
header = f"{header}\nSource: {source}"
|
|
191
183
|
return f"<workflow-state>\n{header}\n{body}\n</workflow-state>"
|
|
192
184
|
|
|
193
185
|
|
|
@@ -209,13 +201,14 @@ def main() -> int:
|
|
|
209
201
|
return 0 # not a Trellis project
|
|
210
202
|
|
|
211
203
|
templates = load_breadcrumbs(root)
|
|
212
|
-
task = get_active_task(root)
|
|
204
|
+
task = get_active_task(root, data)
|
|
213
205
|
if task is None:
|
|
214
206
|
# No active task — still emit a breadcrumb nudging AI toward
|
|
215
207
|
# trellis-brainstorm + task.py create when user describes real work.
|
|
216
208
|
breadcrumb = build_breadcrumb(None, "no_task", templates)
|
|
217
209
|
else:
|
|
218
|
-
|
|
210
|
+
task_id, status, source = task
|
|
211
|
+
breadcrumb = build_breadcrumb(task_id, status, templates, source)
|
|
219
212
|
|
|
220
213
|
output = {
|
|
221
214
|
"hookSpecificOutput": {
|