♻️ refactor(cook-it-through): move workflow engine into skill
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+58
-28
@@ -15,6 +15,7 @@ ORDER = [
|
||||
"install_skills",
|
||||
"format_md",
|
||||
]
|
||||
RULES_WORKFLOW_SKILL = "cook-it-through"
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
PLAYBOOK_ROOT = SCRIPT_DIR.parent
|
||||
DOCS_INDEX_SECTION_HEADINGS = {
|
||||
@@ -142,10 +143,6 @@ def resolve_docs_prefix(context: dict) -> str:
|
||||
return join_playbook_subpath(resolve_playbook_root(context), "docs")
|
||||
|
||||
|
||||
def resolve_playbook_scripts(context: dict) -> str:
|
||||
return join_playbook_subpath(resolve_playbook_root(context), "scripts")
|
||||
|
||||
|
||||
def read_git_commit(root: Path) -> str:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
@@ -404,7 +401,6 @@ def replace_placeholders(
|
||||
text: str,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
playbook_scripts: str | None,
|
||||
playbook_root: str | None,
|
||||
) -> str:
|
||||
result = text.replace("{{DATE}}", date_value)
|
||||
@@ -412,8 +408,6 @@ def replace_placeholders(
|
||||
result = result.replace("{{PROJECT_NAME}}", project_name)
|
||||
if playbook_root:
|
||||
result = result.replace("{{PLAYBOOK_ROOT}}", playbook_root)
|
||||
if playbook_scripts:
|
||||
result = result.replace("{{PLAYBOOK_SCRIPTS}}", playbook_scripts)
|
||||
return result
|
||||
|
||||
|
||||
@@ -430,15 +424,12 @@ def replace_placeholders_in_file(
|
||||
file_path: Path,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
playbook_scripts: str | None,
|
||||
playbook_root: str | None,
|
||||
) -> None:
|
||||
if file_path.suffix != ".md":
|
||||
return
|
||||
text = file_path.read_text(encoding="utf-8")
|
||||
updated = replace_placeholders(
|
||||
text, project_name, date_value, playbook_scripts, playbook_root
|
||||
)
|
||||
updated = replace_placeholders(text, project_name, date_value, playbook_root)
|
||||
if updated != text:
|
||||
file_path.write_text(updated, encoding="utf-8", newline="\n")
|
||||
|
||||
@@ -464,7 +455,6 @@ def sync_directory(
|
||||
target_dir: Path,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
playbook_scripts: str | None,
|
||||
playbook_root: str | None,
|
||||
force: bool,
|
||||
no_backup: bool,
|
||||
@@ -488,7 +478,6 @@ def sync_directory(
|
||||
target_file,
|
||||
project_name,
|
||||
date_value,
|
||||
playbook_scripts,
|
||||
playbook_root,
|
||||
)
|
||||
written += 1
|
||||
@@ -570,12 +559,11 @@ def update_agents_section(
|
||||
end_marker: str,
|
||||
project_name: str | None,
|
||||
date_value: str,
|
||||
playbook_scripts: str | None,
|
||||
playbook_root: str | None,
|
||||
) -> None:
|
||||
template_text = template_path.read_text(encoding="utf-8")
|
||||
template_text = replace_placeholders(
|
||||
template_text, project_name, date_value, playbook_scripts, playbook_root
|
||||
template_text, project_name, date_value, playbook_root
|
||||
)
|
||||
block = extract_block_lines(template_text, start_marker, end_marker)
|
||||
if not block:
|
||||
@@ -640,7 +628,6 @@ def sync_agents_template(context: dict) -> int:
|
||||
return 0
|
||||
|
||||
project_name = resolve_project_name(context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
playbook_root = resolve_playbook_root(context)
|
||||
date_value = resolve_template_date(context)
|
||||
|
||||
@@ -651,7 +638,6 @@ def sync_agents_template(context: dict) -> int:
|
||||
"<!-- playbook:framework:end -->",
|
||||
project_name,
|
||||
date_value,
|
||||
playbook_scripts,
|
||||
playbook_root,
|
||||
)
|
||||
sync_claude_md(project_root, context.get("config", {}))
|
||||
@@ -767,15 +753,12 @@ def sync_rules_action(config: dict, context: dict) -> int:
|
||||
force = bool(config.get("force", False))
|
||||
|
||||
project_name = resolve_project_name(context)
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
playbook_root = resolve_playbook_root(context)
|
||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
|
||||
text = rules_src.read_text(encoding="utf-8")
|
||||
text = replace_placeholders(
|
||||
text, project_name, date_value, playbook_scripts, playbook_root
|
||||
)
|
||||
text = replace_placeholders(text, project_name, date_value, playbook_root)
|
||||
|
||||
if rules_dst.exists() and not force:
|
||||
# The process itself is Playbook-owned, so keep it upgradable: refresh the
|
||||
@@ -846,7 +829,6 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||
return 2
|
||||
|
||||
project_name = config.get("project_name")
|
||||
playbook_scripts = resolve_playbook_scripts(context)
|
||||
playbook_root = resolve_playbook_root(context)
|
||||
date_value = config.get("date") or datetime.now().strftime("%Y-%m-%d")
|
||||
force = bool(config.get("force", False))
|
||||
@@ -859,7 +841,6 @@ def sync_memory_bank_action(config: dict, context: dict) -> int:
|
||||
memory_dst,
|
||||
project_name,
|
||||
date_value,
|
||||
playbook_scripts,
|
||||
playbook_root,
|
||||
force,
|
||||
no_backup,
|
||||
@@ -1208,6 +1189,45 @@ def normalize_names(raw: object, label: str) -> list[str]:
|
||||
return cleaned
|
||||
|
||||
|
||||
def parse_skill_install_options(config: dict) -> tuple[str, set[str]]:
|
||||
if not isinstance(config, dict):
|
||||
raise ValueError("[install_skills] must be a table")
|
||||
mode = str(config.get("mode", "list")).lower()
|
||||
if mode not in ("all", "list"):
|
||||
raise ValueError("mode must be list or all")
|
||||
raw_exclude = config.get("exclude")
|
||||
excluded = (
|
||||
set(normalize_names(raw_exclude, "exclude"))
|
||||
if raw_exclude not in (None, [])
|
||||
else set()
|
||||
)
|
||||
return mode, excluded
|
||||
|
||||
|
||||
def validate_rules_workflow_skill(config: dict) -> None:
|
||||
if "sync_rules" not in config:
|
||||
return
|
||||
if "install_skills" not in config:
|
||||
raise ValueError(
|
||||
f"[sync_rules] requires [install_skills] to install "
|
||||
f"{RULES_WORKFLOW_SKILL}"
|
||||
)
|
||||
install_config = config["install_skills"]
|
||||
mode, excluded = parse_skill_install_options(install_config)
|
||||
if RULES_WORKFLOW_SKILL in excluded:
|
||||
raise ValueError(
|
||||
f"[sync_rules] requires {RULES_WORKFLOW_SKILL}; "
|
||||
"remove it from [install_skills].exclude"
|
||||
)
|
||||
if mode == "list":
|
||||
selected = set(normalize_names(install_config.get("skills"), "skills"))
|
||||
if RULES_WORKFLOW_SKILL not in selected:
|
||||
raise ValueError(
|
||||
f"[sync_rules] requires {RULES_WORKFLOW_SKILL} in "
|
||||
"[install_skills].skills"
|
||||
)
|
||||
|
||||
|
||||
def normalize_globs(raw: object) -> list[str]:
|
||||
if raw is None:
|
||||
return ["**/*.md"]
|
||||
@@ -1220,7 +1240,11 @@ def normalize_globs(raw: object) -> list[str]:
|
||||
|
||||
|
||||
def install_skills_action(config: dict, context: dict) -> int:
|
||||
mode = str(config.get("mode", "list")).lower()
|
||||
try:
|
||||
mode, excluded = parse_skill_install_options(config)
|
||||
except ValueError as exc:
|
||||
print(f"ERROR: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
agents_home = Path(config.get("agents_home", "~/.agents")).expanduser()
|
||||
if not agents_home.is_absolute():
|
||||
agents_home = (context["project_root"] / agents_home).resolve()
|
||||
@@ -1261,9 +1285,14 @@ def install_skills_action(config: dict, context: dict) -> int:
|
||||
else:
|
||||
print(f"ERROR: skill not found: {name}", file=sys.stderr)
|
||||
return 2
|
||||
else:
|
||||
print("ERROR: mode must be list or all", file=sys.stderr)
|
||||
return 2
|
||||
selected_exclusions = sorted(
|
||||
{name for name, _src_root, _origin in skill_entries} & excluded
|
||||
)
|
||||
skill_entries = [
|
||||
entry for entry in skill_entries if entry[0] not in excluded
|
||||
]
|
||||
for name in selected_exclusions:
|
||||
log(f"Excluded: {name}")
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
no_backup = bool(config.get("no_backup", False))
|
||||
@@ -1397,7 +1426,8 @@ def main(argv: list[str]) -> int:
|
||||
|
||||
try:
|
||||
install_mode = resolve_install_mode(config)
|
||||
except ValueError as exc:
|
||||
validate_rules_workflow_skill(config)
|
||||
except (TypeError, ValueError) as exc:
|
||||
print(f"ERROR: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
Reference in New Issue
Block a user