chore: migrate from opencode to trellis 0.5.0-rc.6
- Remove legacy .opencode/ directory and configuration - Update .trellis/ to v0.5.0-rc.6 structure - Refactor scripts: modularize common/, remove multi_agent/ - Add new common modules: git.py, io.py, log.py, types.py, etc. - Update workflow.md and AGENTS.md - Archive completed migration tasks
This commit is contained in:
+111
-13
@@ -4,8 +4,19 @@
|
||||
Add a new session to journal file and update index.md.
|
||||
|
||||
Usage:
|
||||
python3 add_session.py --title "Title" --commit "hash" --summary "Summary"
|
||||
echo "content" | python3 add_session.py --title "Title" --commit "hash"
|
||||
python3 add_session.py --title "Title" --commit "hash" --summary "Summary" [--package cli]
|
||||
python3 add_session.py --title "Title" --branch "feat/my-branch"
|
||||
|
||||
# Pipe detailed content via stdin (use --stdin to opt in):
|
||||
cat << 'EOF' | python3 add_session.py --stdin --title "Title" --summary "Summary"
|
||||
<session content here>
|
||||
EOF
|
||||
|
||||
Branch resolution order:
|
||||
1. --branch CLI arg (explicit)
|
||||
2. task.json branch field (from active task)
|
||||
3. git branch --show-current (auto-detect)
|
||||
4. None (omitted gracefully)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -20,11 +31,21 @@ from pathlib import Path
|
||||
from common.paths import (
|
||||
FILE_JOURNAL_PREFIX,
|
||||
get_repo_root,
|
||||
get_current_task,
|
||||
get_developer,
|
||||
get_workspace_dir,
|
||||
)
|
||||
from common.developer import ensure_developer
|
||||
from common.config import get_session_commit_message, get_max_journal_lines
|
||||
from common.git import run_git
|
||||
from common.tasks import load_task
|
||||
from common.config import (
|
||||
get_packages,
|
||||
get_session_commit_message,
|
||||
get_max_journal_lines,
|
||||
is_monorepo,
|
||||
resolve_package,
|
||||
validate_package,
|
||||
)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -123,7 +144,9 @@ def generate_session_content(
|
||||
commit: str,
|
||||
summary: str,
|
||||
extra_content: str,
|
||||
today: str
|
||||
today: str,
|
||||
package: str | None = None,
|
||||
branch: str | None = None,
|
||||
) -> str:
|
||||
"""Generate session content."""
|
||||
if commit and commit != "-":
|
||||
@@ -135,12 +158,15 @@ def generate_session_content(
|
||||
else:
|
||||
commit_table = "(No commits - planning session)"
|
||||
|
||||
package_line = f"\n**Package**: {package}" if package else ""
|
||||
branch_line = f"\n**Branch**: `{branch}`" if branch else ""
|
||||
|
||||
return f"""
|
||||
|
||||
## Session {session_num}: {title}
|
||||
|
||||
**Date**: {today}
|
||||
**Task**: {title}
|
||||
**Task**: {title}{package_line}{branch_line}
|
||||
|
||||
### Summary
|
||||
|
||||
@@ -175,7 +201,8 @@ def update_index(
|
||||
commit: str,
|
||||
new_session: int,
|
||||
active_file: str,
|
||||
today: str
|
||||
today: str,
|
||||
branch: str | None = None,
|
||||
) -> bool:
|
||||
"""Update index.md with new session info."""
|
||||
# Format commit for display
|
||||
@@ -254,10 +281,25 @@ def update_index(
|
||||
continue
|
||||
|
||||
if in_session_history:
|
||||
new_lines.append(line)
|
||||
if re.match(r"^\|\s*-", line) and not header_written:
|
||||
new_lines.append(f"| {new_session} | {today} | {title} | {commit_display} |")
|
||||
# Migrate old 4/6-column headers to 5-column Branch-only history.
|
||||
if re.match(
|
||||
r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*Branch\s*\|\s*Base Branch\s*\|\s*$",
|
||||
line,
|
||||
):
|
||||
new_lines.append("| # | Date | Title | Commits | Branch |")
|
||||
continue
|
||||
if re.match(r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*Branch\s*\|\s*$", line):
|
||||
new_lines.append("| # | Date | Title | Commits | Branch |")
|
||||
continue
|
||||
if re.match(r"^\|\s*#\s*\|\s*Date\s*\|\s*Title\s*\|\s*Commits\s*\|\s*$", line):
|
||||
new_lines.append("| # | Date | Title | Commits | Branch |")
|
||||
continue
|
||||
if re.match(r"^\|[-| ]+\|\s*$", line) and not header_written:
|
||||
new_lines.append("|---|------|-------|---------|--------|")
|
||||
new_lines.append(f"| {new_session} | {today} | {title} | {commit_display} | `{branch or '-'}` |")
|
||||
header_written = True
|
||||
continue
|
||||
new_lines.append(line)
|
||||
continue
|
||||
|
||||
new_lines.append(line)
|
||||
@@ -274,11 +316,16 @@ def update_index(
|
||||
def _auto_commit_workspace(repo_root: Path) -> None:
|
||||
"""Stage .trellis/workspace and .trellis/tasks, then commit with a configured message."""
|
||||
commit_msg = get_session_commit_message(repo_root)
|
||||
subprocess.run(
|
||||
add_result = subprocess.run(
|
||||
["git", "add", "-A", ".trellis/workspace", ".trellis/tasks"],
|
||||
cwd=repo_root,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if add_result.returncode != 0:
|
||||
print(f"[WARN] git add failed (exit {add_result.returncode}): {add_result.stderr.strip()}", file=sys.stderr)
|
||||
print("[WARN] Please commit .trellis/ changes manually: git add .trellis && git commit", file=sys.stderr)
|
||||
return
|
||||
# Check if there are staged changes
|
||||
result = subprocess.run(
|
||||
["git", "diff", "--cached", "--quiet", "--", ".trellis/workspace", ".trellis/tasks"],
|
||||
@@ -305,6 +352,8 @@ def add_session(
|
||||
summary: str = "(Add summary)",
|
||||
extra_content: str = "(Add details)",
|
||||
auto_commit: bool = True,
|
||||
package: str | None = None,
|
||||
branch: str | None = None,
|
||||
) -> int:
|
||||
"""Add a new session."""
|
||||
repo_root = get_repo_root()
|
||||
@@ -330,7 +379,8 @@ def add_session(
|
||||
new_session = current_session + 1
|
||||
|
||||
session_content = generate_session_content(
|
||||
new_session, title, commit, summary, extra_content, today
|
||||
new_session, title, commit, summary, extra_content, today, package,
|
||||
branch,
|
||||
)
|
||||
content_lines = len(session_content.splitlines())
|
||||
|
||||
@@ -367,7 +417,16 @@ def add_session(
|
||||
|
||||
# Update index.md
|
||||
active_file = f"{FILE_JOURNAL_PREFIX}{target_num}.md"
|
||||
if not update_index(index_file, dev_dir, title, commit, new_session, active_file, today):
|
||||
if not update_index(
|
||||
index_file,
|
||||
dev_dir,
|
||||
title,
|
||||
commit,
|
||||
new_session,
|
||||
active_file,
|
||||
today,
|
||||
branch,
|
||||
):
|
||||
return 1
|
||||
|
||||
print("", file=sys.stderr)
|
||||
@@ -400,8 +459,12 @@ def main() -> int:
|
||||
parser.add_argument("--commit", default="-", help="Comma-separated commit hashes")
|
||||
parser.add_argument("--summary", default="(Add summary)", help="Brief summary")
|
||||
parser.add_argument("--content-file", help="Path to file with detailed content")
|
||||
parser.add_argument("--package", help="Package name tag (e.g., cli, docs-site)")
|
||||
parser.add_argument("--branch", help="Branch name (auto-detected if omitted)")
|
||||
parser.add_argument("--no-commit", action="store_true",
|
||||
help="Skip auto-commit of workspace changes")
|
||||
parser.add_argument("--stdin", action="store_true",
|
||||
help="Read extra content from stdin (explicit opt-in)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -410,12 +473,47 @@ def main() -> int:
|
||||
content_path = Path(args.content_file)
|
||||
if content_path.is_file():
|
||||
extra_content = content_path.read_text(encoding="utf-8")
|
||||
elif not sys.stdin.isatty():
|
||||
elif args.stdin:
|
||||
extra_content = sys.stdin.read()
|
||||
|
||||
# Load active task once — shared by package and branch resolution
|
||||
repo_root = get_repo_root()
|
||||
current = get_current_task(repo_root)
|
||||
task_data = load_task(repo_root / current) if current else None
|
||||
|
||||
package = args.package
|
||||
if package:
|
||||
# CLI source: fail-fast in monorepo, ignore in single-repo
|
||||
if not is_monorepo(repo_root):
|
||||
print("Warning: --package ignored in single-repo project", file=sys.stderr)
|
||||
package = None
|
||||
elif not validate_package(package, repo_root):
|
||||
packages = get_packages(repo_root)
|
||||
available = ", ".join(sorted(packages.keys())) if packages else "(none)"
|
||||
print(f"Error: unknown package '{package}'. Available: {available}", file=sys.stderr)
|
||||
return 1
|
||||
else:
|
||||
# Inferred: active task's task.json.package → default_package → None
|
||||
task_package = task_data.package if task_data else None
|
||||
package = resolve_package(task_package, repo_root)
|
||||
|
||||
# Resolve branch: CLI → task.json → git auto-detect → None
|
||||
branch = args.branch
|
||||
|
||||
if not branch:
|
||||
if task_data and task_data.raw.get("branch"):
|
||||
branch = task_data.raw["branch"]
|
||||
else:
|
||||
_, branch_out, _ = run_git(["branch", "--show-current"], cwd=repo_root)
|
||||
detected = branch_out.strip()
|
||||
if detected:
|
||||
branch = detected
|
||||
|
||||
return add_session(
|
||||
args.title, args.commit, args.summary, extra_content,
|
||||
auto_commit=not args.no_commit,
|
||||
package=package,
|
||||
branch=branch,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user