✨ feat(playbook): version durable scratch workflow state
This commit is contained in:
+75
-1
@@ -339,7 +339,12 @@ def install_snapshot(config: dict, context: dict) -> int:
|
||||
if templates_ci.is_dir():
|
||||
copytree(templates_ci, templates_dst / "ci")
|
||||
|
||||
for name in ("AGENTS.template.md", "AGENT_RULES.template.md", "README.md"):
|
||||
for name in (
|
||||
"AGENTS.template.md",
|
||||
"AGENT_RULES.template.md",
|
||||
"gitignore.template",
|
||||
"README.md",
|
||||
):
|
||||
src = templates_root / name
|
||||
if src.is_file():
|
||||
copy2(src, templates_dst / name)
|
||||
@@ -510,6 +515,8 @@ _AGENTS_BLOCK_START = "<!-- playbook:agents:start -->"
|
||||
_AGENTS_BLOCK_END = "<!-- playbook:agents:end -->"
|
||||
_RULES_BLOCK_START = "<!-- playbook:rules:start -->"
|
||||
_RULES_BLOCK_END = "<!-- playbook:rules:end -->"
|
||||
_GITIGNORE_BLOCK_START = "# BEGIN playbook .scratch runtime"
|
||||
_GITIGNORE_BLOCK_END = "# END playbook .scratch runtime"
|
||||
|
||||
|
||||
def replace_marked_block(
|
||||
@@ -751,6 +758,10 @@ def sync_rules_action(config: dict, context: dict) -> int:
|
||||
if not rules_src.is_file():
|
||||
print(f"ERROR: template not found: {rules_src}", file=sys.stderr)
|
||||
return 2
|
||||
gitignore_src = templates_dir / "gitignore.template"
|
||||
if not gitignore_src.is_file():
|
||||
print(f"ERROR: template not found: {gitignore_src}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
rules_dst = project_root / "AGENT_RULES.md"
|
||||
force = bool(config.get("force", False))
|
||||
@@ -809,6 +820,16 @@ def sync_rules_action(config: dict, context: dict) -> int:
|
||||
)
|
||||
log("Created: AGENT_RULES.local.md")
|
||||
|
||||
try:
|
||||
sync_gitignore_block(
|
||||
gitignore_src,
|
||||
project_root / ".gitignore",
|
||||
no_backup,
|
||||
)
|
||||
except ValueError as exc:
|
||||
print(f"ERROR: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1046,6 +1067,59 @@ def sync_gitattributes_block(src: Path, dst: Path, no_backup: bool) -> None:
|
||||
log("Synced .gitattributes from standards (block).")
|
||||
|
||||
|
||||
def sync_gitignore_block(src: Path, dst: Path, no_backup: bool) -> None:
|
||||
source_lines = src.read_text(encoding="utf-8").splitlines()
|
||||
block_lines = [
|
||||
_GITIGNORE_BLOCK_START,
|
||||
*source_lines,
|
||||
_GITIGNORE_BLOCK_END,
|
||||
]
|
||||
|
||||
original_text = dst.read_text(encoding="utf-8") if dst.exists() else ""
|
||||
if dst.exists():
|
||||
original_lines = original_text.splitlines()
|
||||
start_positions = [
|
||||
index
|
||||
for index, line in enumerate(original_lines)
|
||||
if line.strip() == _GITIGNORE_BLOCK_START
|
||||
]
|
||||
end_positions = [
|
||||
index
|
||||
for index, line in enumerate(original_lines)
|
||||
if line.strip() == _GITIGNORE_BLOCK_END
|
||||
]
|
||||
if (
|
||||
len(start_positions) != len(end_positions)
|
||||
or len(start_positions) > 1
|
||||
or (
|
||||
start_positions
|
||||
and start_positions[0] >= end_positions[0]
|
||||
)
|
||||
):
|
||||
raise ValueError(".gitignore has an invalid playbook .scratch block")
|
||||
if start_positions:
|
||||
updated_text = replace_marked_block(
|
||||
original_text,
|
||||
block_lines,
|
||||
_GITIGNORE_BLOCK_START,
|
||||
_GITIGNORE_BLOCK_END,
|
||||
)
|
||||
else:
|
||||
content = original_text.rstrip("\n")
|
||||
if content:
|
||||
content += "\n\n"
|
||||
updated_text = content + "\n".join(block_lines) + "\n"
|
||||
else:
|
||||
updated_text = "\n".join(block_lines) + "\n"
|
||||
|
||||
if dst.exists() and updated_text == original_text:
|
||||
log("Unchanged: .gitignore (playbook .scratch block)")
|
||||
return
|
||||
backup_path(dst, no_backup)
|
||||
dst.write_text(updated_text, encoding="utf-8", newline="\n")
|
||||
log("Synced: .gitignore (playbook .scratch block)")
|
||||
|
||||
|
||||
def sync_standards_action(config: dict, context: dict) -> int:
|
||||
if "langs" not in config:
|
||||
print("ERROR: langs is required for sync_standards", file=sys.stderr)
|
||||
|
||||
Reference in New Issue
Block a user