Files
ss-tools/merge_prompts.py
busya ec6421de35 rename ss-tools to superset-tools across the entire project
- Replace all occurrences of 'ss-tools' with 'superset-tools' in 104 files
- Rename git bundle file ss-tools.bundle → superset-tools.bundle
- Update .gitignore pattern accordingly
- Preserve variable names (hasSsTools etc.) and code identifiers
2026-06-16 11:15:19 +03:00

162 lines
6.9 KiB
Python

# #region MergePrompts [C:2] [TYPE Module]
# @LAYER Infra
# @BRIEF Merge all agent prompts, skills, constitution, and speckit commands into one file for external LLM review.
# @RATIONALE Other LLMs need the full protocol context to evaluate the prompt architecture. This script mirrors merge_spec.py pattern.
import sys
from datetime import datetime
from pathlib import Path
REVIEW_PROMPT = (
"Below is the complete GRACE-Poly semantic protocol for the superset-tools project — "
"agent prompts, skills, constitution, and speckit workflow commands.\n\n"
"Your task: independently review this protocol architecture. Evaluate:\n"
"1. Consistency across agents — do all agents follow the same structural pattern?\n"
"2. Attention optimization — are contracts optimized for MLA/CSA/HCA/DSA compression?\n"
"3. Cross-stack integrity — do Python and Svelte contracts align at API boundaries?\n"
"4. Decision memory coverage — are @RATIONALE/@REJECTED present where needed?\n"
"5. Gaps and contradictions — what is missing or inconsistent?\n"
"Focus on architectural review, not implementation details.\n"
)
# Canonical order for the merged output
CANONICAL_ORDER = [
# Layer 1: Constitution (project laws)
("file", ".specify/memory/constitution.md", "CONSTITUTION — Project Laws"),
# Layer 2: Skills (protocol reference)
("file", ".opencode/skills/semantics-core/SKILL.md", "SKILL — Semantics Core"),
("file", ".opencode/skills/semantics-contracts/SKILL.md", "SKILL — Semantics Contracts"),
("file", ".opencode/skills/semantics-python/SKILL.md", "SKILL — Semantics Python"),
("file", ".opencode/skills/semantics-svelte/SKILL.md", "SKILL — Semantics Svelte"),
("file", ".opencode/skills/semantics-testing/SKILL.md", "SKILL — Semantics Testing"),
("file", ".opencode/skills/molecular-cot-logging/SKILL.md", "SKILL — Molecular CoT Logging"),
# Layer 3: Agent Prompts (thin shims)
("file", ".opencode/agents/semantic-curator.md", "AGENT — Semantic Curator"),
("file", ".opencode/agents/python-coder.md", "AGENT — Python Coder"),
("file", ".opencode/agents/svelte-coder.md", "AGENT — Svelte Coder"),
("file", ".opencode/agents/fullstack-coder.md", "AGENT — Fullstack Coder"),
("file", ".opencode/agents/qa-tester.md", "AGENT — QA Tester"),
("file", ".opencode/agents/reflection-agent.md", "AGENT — Reflection Agent"),
("file", ".opencode/agents/swarm-master.md", "AGENT — Swarm Master"),
("file", ".opencode/agents/closure-gate.md", "AGENT — Closure Gate"),
("file", ".opencode/agents/speckit.md", "AGENT — Speckit Workflow"),
# Layer 4: Speckit Commands (workflow)
("file", ".opencode/command/speckit.specify.md", "COMMAND — speckit.specify"),
("file", ".opencode/command/speckit.clarify.md", "COMMAND — speckit.clarify"),
("file", ".opencode/command/speckit.plan.md", "COMMAND — speckit.plan"),
("file", ".opencode/command/speckit.tasks.md", "COMMAND — speckit.tasks"),
("file", ".opencode/command/speckit.implement.md", "COMMAND — speckit.implement"),
("file", ".opencode/command/speckit.analyze.md", "COMMAND — speckit.analyze"),
("file", ".opencode/command/speckit.test.md", "COMMAND — speckit.test"),
("file", ".opencode/command/speckit.checklist.md", "COMMAND — speckit.checklist"),
("file", ".opencode/command/speckit.constitution.md", "COMMAND — speckit.constitution"),
("file", ".opencode/command/speckit.semantics.md", "COMMAND — speckit.semantics"),
("file", ".opencode/command/speckit.taskstoissues.md", "COMMAND — speckit.taskstoissues"),
("file", ".opencode/command/read_semantics.md", "COMMAND — read_semantics"),
# Layer 5: Templates (what speckit generates)
("file", ".specify/templates/spec-template.md", "TEMPLATE — spec"),
("file", ".specify/templates/ux-reference-template.md", "TEMPLATE — ux-reference"),
("file", ".specify/templates/plan-template.md", "TEMPLATE — plan"),
("file", ".specify/templates/tasks-template.md", "TEMPLATE — tasks"),
("file", ".specify/templates/checklist-template.md", "TEMPLATE — checklist"),
("file", ".specify/templates/test-docs-template.md", "TEMPLATE — test-docs"),
("file", ".specify/templates/agent-file-template.md", "TEMPLATE — agent-file"),
]
def merge_prompts(root: Path = None) -> str:
"""Merge all prompts, skills, and workflow artifacts into one markdown file."""
if root is None:
root = Path.cwd()
now = datetime.now().strftime("%Y%m%d-%H%M%S")
output_filename = f"prompts-merged-{now}.md"
content_blocks = [
REVIEW_PROMPT,
"",
"=" * 80,
"",
"Artifact order: Constitution → Skills → Agents → Commands → Templates",
f"Generated: {datetime.now().isoformat()}",
f"Root: {root}",
"",
"=" * 80,
"",
]
files_merged = 0
files_skipped = 0
skipped_details = []
for entry_type, path_str, section_title in CANONICAL_ORDER:
file_path = root / path_str
if not file_path.exists():
files_skipped += 1
skipped_details.append(f" [MISSING] {path_str}")
continue
try:
content = file_path.read_text(encoding="utf-8")
except Exception as e:
files_skipped += 1
skipped_details.append(f" [ERROR] {path_str}: {e}")
continue
files_merged += 1
# Section header
content_blocks.append("")
content_blocks.append("=" * 80)
content_blocks.append(f"## {section_title}")
content_blocks.append(f"Source: {path_str}")
content_blocks.append("=" * 80)
content_blocks.append("")
content_blocks.append(content)
content_blocks.append("")
# Summary footer
content_blocks.append("")
content_blocks.append("=" * 80)
content_blocks.append("## MERGE SUMMARY")
content_blocks.append(f"Files merged: {files_merged}")
content_blocks.append(f"Files skipped: {files_skipped}")
if skipped_details:
content_blocks.append("Skipped:")
content_blocks.extend(skipped_details)
content_blocks.append("=" * 80)
merged = "\n".join(content_blocks)
output_path = root / output_filename
output_path.write_text(merged, encoding="utf-8")
return output_filename, files_merged, files_skipped
def main():
root = Path.cwd()
# Allow explicit root path
if len(sys.argv) > 1:
root = Path(sys.argv[1])
if not root.is_dir():
print(f"Error: '{sys.argv[1]}' is not a valid directory.")
sys.exit(1)
print(f"Merging prompts from: {root}")
print()
output_filename, merged, skipped = merge_prompts(root)
print(f"✓ Merged {merged} files → {output_filename}")
if skipped:
print(f"⚠ Skipped {skipped} files (see summary in output)")
if __name__ == "__main__":
main()
# #endregion MergePrompts