tasks ready

This commit is contained in:
2026-05-08 18:01:49 +03:00
parent 1b15fd3fa7
commit 344b47ca23
32 changed files with 3243 additions and 229 deletions

View File

@@ -1,17 +1,73 @@
# [DEF:MergeSpec:Module]
# @PURPOSE: Utility to merge specs
# @TIER: TRIVIAL
# @COMPLEXITY: 1
# @RELATION: [DEPENDS_ON] builtin
# @LAYER: Infra
# [DEF:merge_spec:Module]
# @PURPOSE: Utility script for merge_spec
# @TIER: TRIVIAL
# @COMPLEXITY: 1
import os
# @LAYER: Infra
import sys
from datetime import datetime
from pathlib import Path
REVIEW_PROMPT = (
"Другая LLM создала этот feature-пакет. Твоя задача - провести независимое "
"ортогональное spec review, оценить готовность спецификации, найти противоречия, "
"пробелы, риски реализации и подготовить структурированный отчет с корректировками. "
"Сфокусируйся именно на review пакета спецификации, а не на переписывании реализации."
)
CANONICAL_MD_STAGES = (
("exact", "spec.md"),
("exact", "ux_reference.md"),
("prefix", "checklists/"),
("exact", "plan.md"),
("exact", "research.md"),
("exact", "data-model.md"),
("prefix", "contracts/"),
("exact", "quickstart.md"),
("exact", "tasks.md"),
)
def relative_key(path: Path, root: Path) -> str:
return path.relative_to(root).as_posix()
def ordered_markdown_files(target_dir: Path) -> list[Path]:
markdown_files = [path for path in target_dir.rglob("*.md") if path.is_file()]
remaining = {relative_key(path, target_dir): path for path in markdown_files}
ordered: list[Path] = []
for stage_type, stage_value in CANONICAL_MD_STAGES:
if stage_type == "exact":
path = remaining.pop(stage_value, None)
if path is not None:
ordered.append(path)
continue
stage_matches = sorted(
[
path
for relative_path, path in remaining.items()
if relative_path.startswith(stage_value)
],
key=lambda path: relative_key(path, target_dir),
)
ordered.extend(stage_matches)
for path in stage_matches:
remaining.pop(relative_key(path, target_dir), None)
ordered.extend(
sorted(remaining.values(), key=lambda path: relative_key(path, target_dir))
)
return ordered
def merge_specs(feature_number):
specs_dir = Path("specs")
if not specs_dir.exists():
@@ -26,24 +82,30 @@ def merge_specs(feature_number):
break
if not target_dir:
print(f"Error: No directory found for feature number '{feature_number}' in 'specs/'.")
print(
f"Error: No directory found for feature number '{feature_number}' in 'specs/'."
)
return
feature_name = target_dir.name
now = datetime.now().strftime("%Y%m%d-%H%M%S")
output_filename = f"{feature_name}-{now}.md"
content_blocks = ["Мой коллега предложил такую фичу, оцени ее\n"]
# Recursively find all files
files_to_merge = sorted([f for f in target_dir.rglob("*") if f.is_file()])
content_blocks = [
REVIEW_PROMPT,
"",
"Порядок артефактов: spec -> ux_reference -> checklist -> plan -> research -> data-model -> contracts -> quickstart -> tasks -> remaining markdown.",
"",
]
files_to_merge = ordered_markdown_files(target_dir)
for file_path in files_to_merge:
relative_path = file_path.relative_to(target_dir)
try:
with open(file_path, "r", encoding="utf-8") as f:
file_content = f.read()
content_blocks.append(f"--- FILE: {relative_path} ---\n")
content_blocks.append(file_content)
content_blocks.append("\n")
@@ -55,11 +117,12 @@ def merge_specs(feature_number):
print(f"Successfully created: {output_filename}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python merge_spec.py <feature_number>")
sys.exit(1)
merge_specs(sys.argv[1])
# [/DEF:merge_spec:Module]