@mindfoldhq/trellis 0.6.0-beta.2 → 0.6.0-beta.20
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 +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +58 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/channel/adapters/claude.d.ts +29 -0
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
- package/dist/commands/channel/adapters/claude.js +203 -0
- package/dist/commands/channel/adapters/claude.js.map +1 -0
- package/dist/commands/channel/adapters/codex.d.ts +85 -0
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
- package/dist/commands/channel/adapters/codex.js +505 -0
- package/dist/commands/channel/adapters/codex.js.map +1 -0
- package/dist/commands/channel/adapters/index.d.ts +84 -0
- package/dist/commands/channel/adapters/index.d.ts.map +1 -0
- package/dist/commands/channel/adapters/index.js +115 -0
- package/dist/commands/channel/adapters/index.js.map +1 -0
- package/dist/commands/channel/adapters/types.d.ts +33 -0
- package/dist/commands/channel/adapters/types.d.ts.map +1 -0
- package/dist/commands/channel/adapters/types.js +2 -0
- package/dist/commands/channel/adapters/types.js.map +1 -0
- package/dist/commands/channel/agent-loader.d.ts +32 -0
- package/dist/commands/channel/agent-loader.d.ts.map +1 -0
- package/dist/commands/channel/agent-loader.js +154 -0
- package/dist/commands/channel/agent-loader.js.map +1 -0
- package/dist/commands/channel/context-loader.d.ts +26 -0
- package/dist/commands/channel/context-loader.d.ts.map +1 -0
- package/dist/commands/channel/context-loader.js +290 -0
- package/dist/commands/channel/context-loader.js.map +1 -0
- package/dist/commands/channel/context.d.ts +16 -0
- package/dist/commands/channel/context.d.ts.map +1 -0
- package/dist/commands/channel/context.js +83 -0
- package/dist/commands/channel/context.js.map +1 -0
- package/dist/commands/channel/create.d.ts +27 -0
- package/dist/commands/channel/create.d.ts.map +1 -0
- package/dist/commands/channel/create.js +39 -0
- package/dist/commands/channel/create.js.map +1 -0
- package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
- package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
- package/dist/commands/channel/dev-parse-trace.js +70 -0
- package/dist/commands/channel/dev-parse-trace.js.map +1 -0
- package/dist/commands/channel/guard.d.ts +150 -0
- package/dist/commands/channel/guard.d.ts.map +1 -0
- package/dist/commands/channel/guard.js +474 -0
- package/dist/commands/channel/guard.js.map +1 -0
- package/dist/commands/channel/index.d.ts +3 -0
- package/dist/commands/channel/index.d.ts.map +1 -0
- package/dist/commands/channel/index.js +531 -0
- package/dist/commands/channel/index.js.map +1 -0
- package/dist/commands/channel/interrupt.d.ts +10 -0
- package/dist/commands/channel/interrupt.d.ts.map +1 -0
- package/dist/commands/channel/interrupt.js +22 -0
- package/dist/commands/channel/interrupt.js.map +1 -0
- package/dist/commands/channel/kill.d.ts +7 -0
- package/dist/commands/channel/kill.d.ts.map +1 -0
- package/dist/commands/channel/kill.js +121 -0
- package/dist/commands/channel/kill.js.map +1 -0
- package/dist/commands/channel/list.d.ts +17 -0
- package/dist/commands/channel/list.d.ts.map +1 -0
- package/dist/commands/channel/list.js +233 -0
- package/dist/commands/channel/list.js.map +1 -0
- package/dist/commands/channel/messages.d.ts +15 -0
- package/dist/commands/channel/messages.d.ts.map +1 -0
- package/dist/commands/channel/messages.js +245 -0
- package/dist/commands/channel/messages.js.map +1 -0
- package/dist/commands/channel/rm.d.ts +27 -0
- package/dist/commands/channel/rm.d.ts.map +1 -0
- package/dist/commands/channel/rm.js +216 -0
- package/dist/commands/channel/rm.js.map +1 -0
- package/dist/commands/channel/run.d.ts +30 -0
- package/dist/commands/channel/run.d.ts.map +1 -0
- package/dist/commands/channel/run.js +130 -0
- package/dist/commands/channel/run.js.map +1 -0
- package/dist/commands/channel/send.d.ts +11 -0
- package/dist/commands/channel/send.d.ts.map +1 -0
- package/dist/commands/channel/send.js +24 -0
- package/dist/commands/channel/send.js.map +1 -0
- package/dist/commands/channel/spawn.d.ts +40 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -0
- package/dist/commands/channel/spawn.js +244 -0
- package/dist/commands/channel/spawn.js.map +1 -0
- package/dist/commands/channel/store/events.d.ts +39 -0
- package/dist/commands/channel/store/events.d.ts.map +1 -0
- package/dist/commands/channel/store/events.js +87 -0
- package/dist/commands/channel/store/events.js.map +1 -0
- package/dist/commands/channel/store/filter.d.ts +3 -0
- package/dist/commands/channel/store/filter.d.ts.map +1 -0
- package/dist/commands/channel/store/filter.js +2 -0
- package/dist/commands/channel/store/filter.js.map +1 -0
- package/dist/commands/channel/store/lock.d.ts +23 -0
- package/dist/commands/channel/store/lock.d.ts.map +1 -0
- package/dist/commands/channel/store/lock.js +99 -0
- package/dist/commands/channel/store/lock.js.map +1 -0
- package/dist/commands/channel/store/paths.d.ts +63 -0
- package/dist/commands/channel/store/paths.d.ts.map +1 -0
- package/dist/commands/channel/store/paths.js +246 -0
- package/dist/commands/channel/store/paths.js.map +1 -0
- package/dist/commands/channel/store/schema.d.ts +27 -0
- package/dist/commands/channel/store/schema.d.ts.map +1 -0
- package/dist/commands/channel/store/schema.js +34 -0
- package/dist/commands/channel/store/schema.js.map +1 -0
- package/dist/commands/channel/store/thread-state.d.ts +5 -0
- package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
- package/dist/commands/channel/store/thread-state.js +16 -0
- package/dist/commands/channel/store/thread-state.js.map +1 -0
- package/dist/commands/channel/store/watch.d.ts +19 -0
- package/dist/commands/channel/store/watch.d.ts.map +1 -0
- package/dist/commands/channel/store/watch.js +146 -0
- package/dist/commands/channel/store/watch.js.map +1 -0
- package/dist/commands/channel/supervisor/idle.d.ts +46 -0
- package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/idle.js +72 -0
- package/dist/commands/channel/supervisor/idle.js.map +1 -0
- package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
- package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/inbox.js +160 -0
- package/dist/commands/channel/supervisor/inbox.js.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.js +146 -0
- package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
- package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/stdout.js +121 -0
- package/dist/commands/channel/supervisor/stdout.js.map +1 -0
- package/dist/commands/channel/supervisor/turns.d.ts +31 -0
- package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/turns.js +45 -0
- package/dist/commands/channel/supervisor/turns.js.map +1 -0
- package/dist/commands/channel/supervisor/warning.d.ts +48 -0
- package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/warning.js +77 -0
- package/dist/commands/channel/supervisor/warning.js.map +1 -0
- package/dist/commands/channel/supervisor.d.ts +59 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -0
- package/dist/commands/channel/supervisor.js +344 -0
- package/dist/commands/channel/supervisor.js.map +1 -0
- package/dist/commands/channel/text-body.d.ts +13 -0
- package/dist/commands/channel/text-body.d.ts.map +1 -0
- package/dist/commands/channel/text-body.js +47 -0
- package/dist/commands/channel/text-body.js.map +1 -0
- package/dist/commands/channel/threads.d.ts +39 -0
- package/dist/commands/channel/threads.d.ts.map +1 -0
- package/dist/commands/channel/threads.js +106 -0
- package/dist/commands/channel/threads.js.map +1 -0
- package/dist/commands/channel/title.d.ts +12 -0
- package/dist/commands/channel/title.d.ts.map +1 -0
- package/dist/commands/channel/title.js +24 -0
- package/dist/commands/channel/title.js.map +1 -0
- package/dist/commands/channel/wait.d.ts +17 -0
- package/dist/commands/channel/wait.d.ts.map +1 -0
- package/dist/commands/channel/wait.js +75 -0
- package/dist/commands/channel/wait.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +97 -42
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mem.d.ts +13 -117
- package/dist/commands/mem.d.ts.map +1 -1
- package/dist/commands/mem.js +168 -1074
- package/dist/commands/mem.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +28 -2
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +31 -111
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upgrade.d.ts +28 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +84 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/workflow.d.ts +35 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +219 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +1 -0
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +5 -3
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/shared.js +4 -4
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/workflow.d.ts +8 -0
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +3 -2
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/migrations/manifests/0.5.10.json +9 -0
- package/dist/migrations/manifests/0.5.11.json +16 -0
- package/dist/migrations/manifests/0.5.12.json +9 -0
- package/dist/migrations/manifests/0.5.13.json +9 -0
- package/dist/migrations/manifests/0.5.14.json +9 -0
- package/dist/migrations/manifests/0.5.15.json +9 -0
- package/dist/migrations/manifests/0.5.16.json +9 -0
- package/dist/migrations/manifests/0.5.17.json +9 -0
- package/dist/migrations/manifests/0.5.18.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
- package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
- package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
- package/dist/templates/claude/agents/trellis-check.md +13 -7
- package/dist/templates/claude/agents/trellis-implement.md +8 -7
- package/dist/templates/claude/settings.json +4 -4
- package/dist/templates/codebuddy/agents/trellis-check.md +13 -7
- package/dist/templates/codebuddy/agents/trellis-implement.md +8 -7
- package/dist/templates/codebuddy/settings.json +4 -4
- package/dist/templates/codex/agents/trellis-check.toml +4 -4
- package/dist/templates/codex/agents/trellis-implement.toml +4 -4
- package/dist/templates/codex/config.toml +5 -3
- package/dist/templates/codex/hooks/session-start.py +205 -119
- package/dist/templates/codex/hooks.json +2 -2
- package/dist/templates/codex/skills/before-dev/SKILL.md +12 -6
- package/dist/templates/codex/skills/brainstorm/SKILL.md +69 -457
- package/dist/templates/codex/skills/check/SKILL.md +86 -18
- package/dist/templates/codex/skills/start/SKILL.md +33 -323
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +7 -4
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +3 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +5 -5
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +35 -6
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +5 -4
- package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/SKILL.md +41 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/mcp-setup.md +90 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/repository-analysis.md +59 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-task-planning.md +61 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstarp/references/spec-writing.md +70 -0
- package/dist/templates/common/commands/continue.md +6 -5
- package/dist/templates/common/commands/start.md +9 -6
- package/dist/templates/common/skills/before-dev.md +12 -6
- package/dist/templates/common/skills/brainstorm.md +68 -504
- package/dist/templates/common/skills/check.md +7 -1
- package/dist/templates/copilot/hooks/session-start.py +219 -101
- package/dist/templates/copilot/hooks.json +2 -2
- package/dist/templates/copilot/prompts/before-dev.prompt.md +12 -6
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +69 -457
- package/dist/templates/copilot/prompts/check.prompt.md +86 -18
- package/dist/templates/copilot/prompts/parallel.prompt.md +16 -8
- package/dist/templates/copilot/prompts/start.prompt.md +33 -367
- package/dist/templates/cursor/agents/trellis-check.md +13 -7
- package/dist/templates/cursor/agents/trellis-implement.md +8 -7
- package/dist/templates/cursor/hooks.json +1 -7
- package/dist/templates/droid/droids/trellis-check.md +13 -7
- package/dist/templates/droid/droids/trellis-implement.md +8 -7
- package/dist/templates/droid/settings.json +4 -4
- package/dist/templates/gemini/agents/trellis-check.md +11 -5
- package/dist/templates/gemini/agents/trellis-implement.md +7 -6
- package/dist/templates/gemini/settings.json +2 -2
- package/dist/templates/kiro/agents/trellis-check.json +1 -1
- package/dist/templates/kiro/agents/trellis-implement.json +1 -1
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +171 -6
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +333 -43
- package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
- package/dist/templates/opencode/agents/trellis-check.md +13 -7
- package/dist/templates/opencode/agents/trellis-implement.md +9 -8
- package/dist/templates/opencode/lib/session-utils.js +212 -123
- package/dist/templates/opencode/lib/trellis-context.js +73 -11
- package/dist/templates/opencode/plugins/inject-subagent-context.js +131 -29
- package/dist/templates/opencode/plugins/inject-workflow-state.js +9 -5
- package/dist/templates/opencode/plugins/session-start.js +9 -1
- package/dist/templates/pi/agents/trellis-check.md +5 -4
- package/dist/templates/pi/agents/trellis-implement.md +5 -4
- package/dist/templates/pi/extensions/trellis/index.ts.txt +1357 -754
- package/dist/templates/qoder/agents/trellis-check.md +11 -5
- package/dist/templates/qoder/agents/trellis-implement.md +7 -6
- package/dist/templates/qoder/settings.json +4 -4
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +0 -1
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-subagent-context.py +36 -14
- package/dist/templates/shared-hooks/inject-workflow-state.py +40 -42
- package/dist/templates/shared-hooks/session-start.py +222 -171
- package/dist/templates/trellis/config.yaml +38 -0
- package/dist/templates/trellis/index.d.ts +1 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +2 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/add_session.py +50 -24
- package/dist/templates/trellis/scripts/common/config.py +57 -1
- package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
- package/dist/templates/trellis/scripts/common/session_context.py +384 -137
- package/dist/templates/trellis/scripts/common/task_context.py +3 -3
- package/dist/templates/trellis/scripts/common/task_store.py +161 -15
- package/dist/templates/trellis/scripts/common/workflow_phase.py +7 -10
- package/dist/templates/trellis/scripts/task.py +3 -3
- package/dist/templates/trellis/workflow.md +119 -98
- package/dist/utils/cwd-guard.d.ts +38 -0
- package/dist/utils/cwd-guard.d.ts.map +1 -0
- package/dist/utils/cwd-guard.js +62 -0
- package/dist/utils/cwd-guard.js.map +1 -0
- package/dist/utils/file-writer.d.ts +13 -0
- package/dist/utils/file-writer.d.ts.map +1 -1
- package/dist/utils/file-writer.js +59 -1
- package/dist/utils/file-writer.js.map +1 -1
- package/dist/utils/manifest-prune.d.ts +61 -0
- package/dist/utils/manifest-prune.d.ts.map +1 -0
- package/dist/utils/manifest-prune.js +136 -0
- package/dist/utils/manifest-prune.js.map +1 -0
- package/dist/utils/task-json.d.ts +9 -42
- package/dist/utils/task-json.d.ts.map +1 -1
- package/dist/utils/task-json.js +8 -45
- package/dist/utils/task-json.js.map +1 -1
- package/dist/utils/template-hash.d.ts +32 -6
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +53 -31
- package/dist/utils/template-hash.js.map +1 -1
- package/dist/utils/uninstall-scrubbers.d.ts +1 -0
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +21 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/dist/utils/workflow-resolver.d.ts +86 -0
- package/dist/utils/workflow-resolver.d.ts.map +1 -0
- package/dist/utils/workflow-resolver.js +265 -0
- package/dist/utils/workflow-resolver.js.map +1 -0
- package/package.json +9 -8
|
@@ -23,7 +23,6 @@ from __future__ import annotations
|
|
|
23
23
|
|
|
24
24
|
import argparse
|
|
25
25
|
import re
|
|
26
|
-
import subprocess
|
|
27
26
|
import sys
|
|
28
27
|
from datetime import datetime
|
|
29
28
|
from pathlib import Path
|
|
@@ -37,9 +36,15 @@ from common.paths import (
|
|
|
37
36
|
)
|
|
38
37
|
from common.developer import ensure_developer
|
|
39
38
|
from common.git import run_git
|
|
39
|
+
from common.safe_commit import (
|
|
40
|
+
print_gitignore_warning,
|
|
41
|
+
safe_git_add,
|
|
42
|
+
safe_trellis_paths_to_add,
|
|
43
|
+
)
|
|
40
44
|
from common.tasks import load_task
|
|
41
45
|
from common.config import (
|
|
42
46
|
get_packages,
|
|
47
|
+
get_session_auto_commit,
|
|
43
48
|
get_session_commit_message,
|
|
44
49
|
get_max_journal_lines,
|
|
45
50
|
is_monorepo,
|
|
@@ -314,36 +319,57 @@ def update_index(
|
|
|
314
319
|
# =============================================================================
|
|
315
320
|
|
|
316
321
|
def _auto_commit_workspace(repo_root: Path) -> None:
|
|
317
|
-
"""Stage
|
|
322
|
+
"""Stage Trellis-owned workspace + task paths and commit.
|
|
323
|
+
|
|
324
|
+
Path scope is restricted to specific products (journal files, index.md,
|
|
325
|
+
active task dirs, the archive subtree). We never `git add` the whole
|
|
326
|
+
`.trellis/` tree, and if `.gitignore` blocks the specific paths we
|
|
327
|
+
warn + skip — never retry with ``-f``.
|
|
328
|
+
|
|
329
|
+
Honors ``session_auto_commit`` in ``.trellis/config.yaml``: when set to
|
|
330
|
+
``false``, this function returns immediately without touching git
|
|
331
|
+
(journal/index files are still written to disk by the caller).
|
|
332
|
+
"""
|
|
333
|
+
if not get_session_auto_commit(repo_root):
|
|
334
|
+
print(
|
|
335
|
+
"[OK] session_auto_commit: false — skipping git stage/commit.",
|
|
336
|
+
file=sys.stderr,
|
|
337
|
+
)
|
|
338
|
+
return
|
|
339
|
+
|
|
318
340
|
commit_msg = get_session_commit_message(repo_root)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
)
|
|
325
|
-
if
|
|
326
|
-
|
|
327
|
-
|
|
341
|
+
paths = safe_trellis_paths_to_add(repo_root)
|
|
342
|
+
if not paths:
|
|
343
|
+
print("[OK] No workspace changes to commit.", file=sys.stderr)
|
|
344
|
+
return
|
|
345
|
+
|
|
346
|
+
success, _, err = safe_git_add(paths, repo_root)
|
|
347
|
+
if not success:
|
|
348
|
+
if err and "ignored by" in err.lower():
|
|
349
|
+
print_gitignore_warning(paths)
|
|
350
|
+
else:
|
|
351
|
+
print(
|
|
352
|
+
f"[WARN] git add failed: {err.strip() if err else 'unknown error'}",
|
|
353
|
+
file=sys.stderr,
|
|
354
|
+
)
|
|
328
355
|
return
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
cwd=repo_root
|
|
356
|
+
|
|
357
|
+
# Check if there are staged changes for the paths we just staged.
|
|
358
|
+
rc, _, _ = run_git(
|
|
359
|
+
["diff", "--cached", "--quiet", "--", *paths], cwd=repo_root
|
|
333
360
|
)
|
|
334
|
-
if
|
|
361
|
+
if rc == 0:
|
|
335
362
|
print("[OK] No workspace changes to commit.", file=sys.stderr)
|
|
336
363
|
return
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
capture_output=True,
|
|
341
|
-
text=True,
|
|
342
|
-
)
|
|
343
|
-
if commit_result.returncode == 0:
|
|
364
|
+
|
|
365
|
+
rc, _, commit_err = run_git(["commit", "-m", commit_msg], cwd=repo_root)
|
|
366
|
+
if rc == 0:
|
|
344
367
|
print(f"[OK] Auto-committed: {commit_msg}", file=sys.stderr)
|
|
345
368
|
else:
|
|
346
|
-
print(
|
|
369
|
+
print(
|
|
370
|
+
f"[WARN] Auto-commit failed: {commit_err.strip()}",
|
|
371
|
+
file=sys.stderr,
|
|
372
|
+
)
|
|
347
373
|
|
|
348
374
|
|
|
349
375
|
def add_session(
|
|
@@ -36,6 +36,29 @@ def _unquote(s: str) -> str:
|
|
|
36
36
|
return s
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
def _strip_inline_comment(value: str) -> str:
|
|
40
|
+
"""Strip ` # …` inline comments while preserving `#` inside quoted strings.
|
|
41
|
+
|
|
42
|
+
YAML treats ` #` (space-hash) as a comment opener; bare `#` inside a token
|
|
43
|
+
is part of the value. Quoted strings are immune.
|
|
44
|
+
|
|
45
|
+
Mirrors :func:`common.trellis_config._strip_inline_comment` so both
|
|
46
|
+
parsers handle ``key: value # comment`` identically.
|
|
47
|
+
"""
|
|
48
|
+
in_quote: str | None = None
|
|
49
|
+
for idx, ch in enumerate(value):
|
|
50
|
+
if in_quote:
|
|
51
|
+
if ch == in_quote:
|
|
52
|
+
in_quote = None
|
|
53
|
+
continue
|
|
54
|
+
if ch in ('"', "'"):
|
|
55
|
+
in_quote = ch
|
|
56
|
+
continue
|
|
57
|
+
if ch == "#" and (idx == 0 or value[idx - 1].isspace()):
|
|
58
|
+
return value[:idx]
|
|
59
|
+
return value
|
|
60
|
+
|
|
61
|
+
|
|
39
62
|
def parse_simple_yaml(content: str) -> dict:
|
|
40
63
|
"""Parse simple YAML with nested dict support (no dependencies).
|
|
41
64
|
|
|
@@ -93,7 +116,8 @@ def _parse_yaml_block(
|
|
|
93
116
|
elif ":" in stripped:
|
|
94
117
|
key, _, value = stripped.partition(":")
|
|
95
118
|
key = key.strip()
|
|
96
|
-
value =
|
|
119
|
+
value = _strip_inline_comment(value).strip()
|
|
120
|
+
value = _unquote(value)
|
|
97
121
|
current_list = None
|
|
98
122
|
|
|
99
123
|
if value:
|
|
@@ -142,6 +166,7 @@ def _next_content_line(lines: list[str], start: int) -> tuple[int, str]:
|
|
|
142
166
|
# Defaults
|
|
143
167
|
DEFAULT_SESSION_COMMIT_MESSAGE = "chore: record journal"
|
|
144
168
|
DEFAULT_MAX_JOURNAL_LINES = 2000
|
|
169
|
+
DEFAULT_SESSION_AUTO_COMMIT = True
|
|
145
170
|
|
|
146
171
|
CONFIG_FILE = "config.yaml"
|
|
147
172
|
|
|
@@ -187,6 +212,37 @@ def get_max_journal_lines(repo_root: Path | None = None) -> int:
|
|
|
187
212
|
return DEFAULT_MAX_JOURNAL_LINES
|
|
188
213
|
|
|
189
214
|
|
|
215
|
+
def get_session_auto_commit(repo_root: Path | None = None) -> bool:
|
|
216
|
+
"""Whether scripts should auto-stage + auto-commit session/task changes.
|
|
217
|
+
|
|
218
|
+
Governs both ``add_session.py:_auto_commit_workspace`` and
|
|
219
|
+
``task_store.py:_auto_commit_archive``.
|
|
220
|
+
|
|
221
|
+
Default: ``True`` (existing behavior — auto-stage + auto-commit).
|
|
222
|
+
Set ``session_auto_commit: false`` in ``.trellis/config.yaml`` to skip
|
|
223
|
+
auto-staging entirely; the journal/archive files are still written to
|
|
224
|
+
disk, but the user manages ``git add`` / ``git commit`` themselves.
|
|
225
|
+
|
|
226
|
+
Accepts native YAML booleans (``true`` / ``false``) and the string
|
|
227
|
+
aliases ``true / false / yes / no / 1 / 0 / on / off`` (case-insensitive).
|
|
228
|
+
Invalid values fall back to ``True`` with a stderr warning.
|
|
229
|
+
"""
|
|
230
|
+
config = _load_config(repo_root)
|
|
231
|
+
raw = config.get("session_auto_commit", DEFAULT_SESSION_AUTO_COMMIT)
|
|
232
|
+
if isinstance(raw, bool):
|
|
233
|
+
return raw
|
|
234
|
+
s = str(raw).strip().lower()
|
|
235
|
+
if s in ("true", "yes", "1", "on"):
|
|
236
|
+
return True
|
|
237
|
+
if s in ("false", "no", "0", "off"):
|
|
238
|
+
return False
|
|
239
|
+
print(
|
|
240
|
+
f"[WARN] invalid session_auto_commit value: {raw!r}; using true (default)",
|
|
241
|
+
file=sys.stderr,
|
|
242
|
+
)
|
|
243
|
+
return DEFAULT_SESSION_AUTO_COMMIT
|
|
244
|
+
|
|
245
|
+
|
|
190
246
|
def get_hooks(event: str, repo_root: Path | None = None) -> list[str]:
|
|
191
247
|
"""Get hook commands for a lifecycle event.
|
|
192
248
|
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Safe git-add helpers for Trellis-owned paths.
|
|
3
|
+
|
|
4
|
+
Why this module exists
|
|
5
|
+
----------------------
|
|
6
|
+
A real user incident: a project's `.gitignore` listed `.trellis/` (company-wide
|
|
7
|
+
template / personal habit). When `add_session.py` and `task.py archive` ran
|
|
8
|
+
their auto-commit and `git add` failed with `ignored by .gitignore`, the AI
|
|
9
|
+
agent driving the workflow "fixed" it by retrying with
|
|
10
|
+
`git add -f .trellis/` — which fan-out-included every ignored subtree
|
|
11
|
+
(`.trellis/.backup-*/`, `.trellis/worktrees/`, `.trellis/.template-hashes.json`,
|
|
12
|
+
`.trellis/.runtime/`), committing 548 files / 83474 lines of caches/backups.
|
|
13
|
+
|
|
14
|
+
Design
|
|
15
|
+
------
|
|
16
|
+
- Scripts only stage SPECIFIC product paths (journal files, index.md, the
|
|
17
|
+
current task dir, the archive dir). Never the whole `.trellis/` tree.
|
|
18
|
+
- If plain `git add <specific>` fails with "ignored by", DO NOT retry with
|
|
19
|
+
``-f``. The presence of `.trellis/` in `.gitignore` is treated as user
|
|
20
|
+
intent ("keep .trellis/ local-only"). The script warns and skips the
|
|
21
|
+
auto-commit; users who want auto-staging can either fix their `.gitignore`
|
|
22
|
+
or set ``session_auto_commit: false`` and manage git themselves.
|
|
23
|
+
- The warning includes a negative example: ``Do NOT use `git add -f .trellis/` ...``
|
|
24
|
+
so any AI rereading the log doesn't reinvent the bug.
|
|
25
|
+
|
|
26
|
+
History note: 0.5.10 introduced an automatic ``git add -f`` retry on the
|
|
27
|
+
specific paths. That was reverted in 0.5.11 — auto-forcing into a tree the
|
|
28
|
+
user had gitignored violates user intent even when the path list is narrow.
|
|
29
|
+
The wider-grain forbidden command stays forbidden, and the narrow-grain auto
|
|
30
|
+
``-f`` is gone too.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import sys
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
from .git import run_git
|
|
39
|
+
from .paths import (
|
|
40
|
+
DIR_ARCHIVE,
|
|
41
|
+
DIR_TASKS,
|
|
42
|
+
DIR_WORKFLOW,
|
|
43
|
+
DIR_WORKSPACE,
|
|
44
|
+
FILE_JOURNAL_PREFIX,
|
|
45
|
+
get_developer,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Paths under .trellis/ that must NEVER be auto-staged. Listed here so the
|
|
50
|
+
# warning to the user can show concrete subpaths to ignore individually
|
|
51
|
+
# instead of ignoring the whole `.trellis/` tree.
|
|
52
|
+
TRELLIS_IGNORED_SUBPATHS = (
|
|
53
|
+
".trellis/.backup-*",
|
|
54
|
+
".trellis/worktrees/",
|
|
55
|
+
".trellis/.template-hashes.json",
|
|
56
|
+
".trellis/.runtime/",
|
|
57
|
+
".trellis/.cache/",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def safe_trellis_paths_to_add(repo_root: Path) -> list[str]:
|
|
62
|
+
"""Return the list of repo-relative paths the auto-commit should stage.
|
|
63
|
+
|
|
64
|
+
Only includes paths that exist on disk so callers don't pass non-existent
|
|
65
|
+
arguments to git. The caller is responsible for `git diff --cached`
|
|
66
|
+
checking afterwards.
|
|
67
|
+
|
|
68
|
+
Included:
|
|
69
|
+
- .trellis/workspace/<developer>/journal-*.md
|
|
70
|
+
- .trellis/workspace/<developer>/index.md
|
|
71
|
+
- .trellis/tasks/<task-dir>/ (every active task directory)
|
|
72
|
+
- .trellis/tasks/archive/ (whole archive subtree, if present)
|
|
73
|
+
|
|
74
|
+
Excluded (intentionally — these must not be staged):
|
|
75
|
+
- .trellis/.backup-*, .trellis/worktrees/,
|
|
76
|
+
.trellis/.template-hashes.json, .trellis/.runtime/, .trellis/.cache/
|
|
77
|
+
"""
|
|
78
|
+
paths: list[str] = []
|
|
79
|
+
|
|
80
|
+
# Workspace journal files + index.md
|
|
81
|
+
developer = get_developer(repo_root)
|
|
82
|
+
if developer:
|
|
83
|
+
ws = repo_root / DIR_WORKFLOW / DIR_WORKSPACE / developer
|
|
84
|
+
if ws.is_dir():
|
|
85
|
+
for f in sorted(ws.glob(f"{FILE_JOURNAL_PREFIX}*.md")):
|
|
86
|
+
if f.is_file():
|
|
87
|
+
paths.append(
|
|
88
|
+
f"{DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/{f.name}"
|
|
89
|
+
)
|
|
90
|
+
index_md = ws / "index.md"
|
|
91
|
+
if index_md.is_file():
|
|
92
|
+
paths.append(
|
|
93
|
+
f"{DIR_WORKFLOW}/{DIR_WORKSPACE}/{developer}/index.md"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Active tasks: each direct child of tasks/ that is a directory and not
|
|
97
|
+
# the archive root. The archive subtree is added as a single path below.
|
|
98
|
+
tasks_dir = repo_root / DIR_WORKFLOW / DIR_TASKS
|
|
99
|
+
if tasks_dir.is_dir():
|
|
100
|
+
for child in sorted(tasks_dir.iterdir()):
|
|
101
|
+
if not child.is_dir():
|
|
102
|
+
continue
|
|
103
|
+
if child.name == DIR_ARCHIVE:
|
|
104
|
+
continue
|
|
105
|
+
paths.append(f"{DIR_WORKFLOW}/{DIR_TASKS}/{child.name}")
|
|
106
|
+
|
|
107
|
+
archive_dir = tasks_dir / DIR_ARCHIVE
|
|
108
|
+
if archive_dir.is_dir():
|
|
109
|
+
paths.append(f"{DIR_WORKFLOW}/{DIR_TASKS}/{DIR_ARCHIVE}")
|
|
110
|
+
|
|
111
|
+
return paths
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def safe_archive_paths_to_add(
|
|
115
|
+
repo_root: Path,
|
|
116
|
+
task_name: str | None = None,
|
|
117
|
+
modified_children: list[str] | None = None,
|
|
118
|
+
) -> list[str]:
|
|
119
|
+
"""Return paths to stage after `task.py archive`.
|
|
120
|
+
|
|
121
|
+
Scoped to ONLY the paths the archive operation actually touched:
|
|
122
|
+
|
|
123
|
+
- the archive subtree (where the freshly-moved task lives)
|
|
124
|
+
- the source task directory (for source-side deletes; caller pairs
|
|
125
|
+
this with `git rm --cached` since `git add` won't stage deletes
|
|
126
|
+
for a path that no longer exists in the working tree)
|
|
127
|
+
- any child task directories whose `task.json` was edited to drop
|
|
128
|
+
the archived parent (parent-children relationship update)
|
|
129
|
+
|
|
130
|
+
This narrow scope avoids "scope creep" — dirty changes in OTHER
|
|
131
|
+
active task dirs (parallel-window edits) are NOT bundled into the
|
|
132
|
+
archive commit. Callers handle each kind of change in its own
|
|
133
|
+
commit boundary.
|
|
134
|
+
|
|
135
|
+
Backwards-compat: with no arguments, the function walks the whole
|
|
136
|
+
`.trellis/tasks/` subtree the old way (active tasks + archive). New
|
|
137
|
+
callers should always pass `task_name`.
|
|
138
|
+
"""
|
|
139
|
+
paths: list[str] = []
|
|
140
|
+
tasks_dir = repo_root / DIR_WORKFLOW / DIR_TASKS
|
|
141
|
+
if not tasks_dir.is_dir():
|
|
142
|
+
return paths
|
|
143
|
+
|
|
144
|
+
archive_dir = tasks_dir / DIR_ARCHIVE
|
|
145
|
+
|
|
146
|
+
if task_name is not None:
|
|
147
|
+
# Narrow scope — only paths that still exist on disk (so
|
|
148
|
+
# `git add` doesn't choke on the moved-away source). The caller
|
|
149
|
+
# handles the source-side deletes via `git rm --cached`
|
|
150
|
+
# explicitly.
|
|
151
|
+
if archive_dir.is_dir():
|
|
152
|
+
paths.append(
|
|
153
|
+
f"{DIR_WORKFLOW}/{DIR_TASKS}/{DIR_ARCHIVE}"
|
|
154
|
+
)
|
|
155
|
+
for child_name in modified_children or []:
|
|
156
|
+
paths.append(f"{DIR_WORKFLOW}/{DIR_TASKS}/{child_name}")
|
|
157
|
+
return paths
|
|
158
|
+
|
|
159
|
+
# Legacy wide scope (no task_name): preserve old behavior so callers
|
|
160
|
+
# that have not been updated keep working.
|
|
161
|
+
if archive_dir.is_dir():
|
|
162
|
+
paths.append(f"{DIR_WORKFLOW}/{DIR_TASKS}/{DIR_ARCHIVE}")
|
|
163
|
+
for child in sorted(tasks_dir.iterdir()):
|
|
164
|
+
if not child.is_dir():
|
|
165
|
+
continue
|
|
166
|
+
if child.name == DIR_ARCHIVE:
|
|
167
|
+
continue
|
|
168
|
+
paths.append(f"{DIR_WORKFLOW}/{DIR_TASKS}/{child.name}")
|
|
169
|
+
return paths
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _stderr_indicates_ignored(stderr: str) -> bool:
|
|
173
|
+
"""git add error indicates the path is excluded by .gitignore."""
|
|
174
|
+
if not stderr:
|
|
175
|
+
return False
|
|
176
|
+
lowered = stderr.lower()
|
|
177
|
+
return "ignored by" in lowered
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def safe_git_add(
|
|
181
|
+
paths: list[str], repo_root: Path
|
|
182
|
+
) -> tuple[bool, bool, str]:
|
|
183
|
+
"""Run `git add` on specific paths; never retry with -f.
|
|
184
|
+
|
|
185
|
+
Returns ``(success, used_force, stderr)``. The ``used_force`` field is
|
|
186
|
+
kept for signature compatibility with the 0.5.10 implementation but is
|
|
187
|
+
always ``False`` — we never auto-force.
|
|
188
|
+
|
|
189
|
+
Behavior:
|
|
190
|
+
- No paths passed → success, no force, empty stderr.
|
|
191
|
+
- Plain ``git add -- <paths>`` succeeds → return success.
|
|
192
|
+
- Plain fails (any reason — ignored or otherwise) → return failure with
|
|
193
|
+
the stderr. Callers should inspect the stderr (see
|
|
194
|
+
:func:`print_gitignore_warning`) and skip the auto-commit.
|
|
195
|
+
"""
|
|
196
|
+
if not paths:
|
|
197
|
+
return True, False, ""
|
|
198
|
+
|
|
199
|
+
rc, _, err = run_git(["add", "--", *paths], cwd=repo_root)
|
|
200
|
+
if rc == 0:
|
|
201
|
+
return True, False, ""
|
|
202
|
+
return False, False, err
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def print_gitignore_warning(paths: list[str]) -> None:
|
|
206
|
+
"""Explain to the user (and any AI reading the log) what to do.
|
|
207
|
+
|
|
208
|
+
CRITICAL: includes the negative example
|
|
209
|
+
``Do NOT use `git add -f .trellis/``` — agents reading the warning are
|
|
210
|
+
known to invent that command, which fans out to ignored caches/backups.
|
|
211
|
+
"""
|
|
212
|
+
print(
|
|
213
|
+
"[WARN] git add failed because .trellis/ paths are ignored by your .gitignore.",
|
|
214
|
+
file=sys.stderr,
|
|
215
|
+
)
|
|
216
|
+
print(
|
|
217
|
+
"[WARN] Skipping auto-commit. The journal/task files were still written to disk;",
|
|
218
|
+
file=sys.stderr,
|
|
219
|
+
)
|
|
220
|
+
print(
|
|
221
|
+
"[WARN] git was not touched.",
|
|
222
|
+
file=sys.stderr,
|
|
223
|
+
)
|
|
224
|
+
print("[WARN]", file=sys.stderr)
|
|
225
|
+
print(
|
|
226
|
+
"[WARN] Trellis manages these specific paths and they should be tracked:",
|
|
227
|
+
file=sys.stderr,
|
|
228
|
+
)
|
|
229
|
+
if paths:
|
|
230
|
+
for p in paths:
|
|
231
|
+
print(f"[WARN] {p}", file=sys.stderr)
|
|
232
|
+
else:
|
|
233
|
+
print(
|
|
234
|
+
"[WARN] .trellis/workspace/<developer>/{journal-*.md,index.md}",
|
|
235
|
+
file=sys.stderr,
|
|
236
|
+
)
|
|
237
|
+
print(
|
|
238
|
+
"[WARN] .trellis/tasks/<task-dir>/",
|
|
239
|
+
file=sys.stderr,
|
|
240
|
+
)
|
|
241
|
+
print(
|
|
242
|
+
"[WARN] .trellis/tasks/archive/",
|
|
243
|
+
file=sys.stderr,
|
|
244
|
+
)
|
|
245
|
+
print("[WARN]", file=sys.stderr)
|
|
246
|
+
print(
|
|
247
|
+
"[WARN] Recommended: change your .gitignore from `.trellis/` to specific",
|
|
248
|
+
file=sys.stderr,
|
|
249
|
+
)
|
|
250
|
+
print(
|
|
251
|
+
"[WARN] subpaths that should remain ignored, e.g.:",
|
|
252
|
+
file=sys.stderr,
|
|
253
|
+
)
|
|
254
|
+
for sub in TRELLIS_IGNORED_SUBPATHS:
|
|
255
|
+
print(f"[WARN] {sub}", file=sys.stderr)
|
|
256
|
+
print("[WARN]", file=sys.stderr)
|
|
257
|
+
print(
|
|
258
|
+
"[WARN] Or, if you intentionally keep .trellis/ local-only, set in",
|
|
259
|
+
file=sys.stderr,
|
|
260
|
+
)
|
|
261
|
+
print(
|
|
262
|
+
"[WARN] .trellis/config.yaml:",
|
|
263
|
+
file=sys.stderr,
|
|
264
|
+
)
|
|
265
|
+
print(
|
|
266
|
+
"[WARN] session_auto_commit: false",
|
|
267
|
+
file=sys.stderr,
|
|
268
|
+
)
|
|
269
|
+
print(
|
|
270
|
+
"[WARN] so the scripts skip git entirely and you can review / commit",
|
|
271
|
+
file=sys.stderr,
|
|
272
|
+
)
|
|
273
|
+
print(
|
|
274
|
+
"[WARN] manually with `git status` / `git add` / `git commit`.",
|
|
275
|
+
file=sys.stderr,
|
|
276
|
+
)
|
|
277
|
+
print("[WARN]", file=sys.stderr)
|
|
278
|
+
print(
|
|
279
|
+
"[WARN] Do NOT use `git add -f .trellis/` — it pulls in backups, worktrees,",
|
|
280
|
+
file=sys.stderr,
|
|
281
|
+
)
|
|
282
|
+
print(
|
|
283
|
+
"[WARN] and runtime caches that should never be committed.",
|
|
284
|
+
file=sys.stderr,
|
|
285
|
+
)
|