Skip to content

Commit c08763d

Browse files
commit
1 parent 92bfd90 commit c08763d

File tree

2 files changed

+98
-11
lines changed

2 files changed

+98
-11
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Workflow logic:
6262

6363
- Check if open source = okay. If so proceed with this workflow
6464
- Truncated JSON goes to JSON branch here
65-
- JSON gets sent to agent who converts it into a more descriptive model card. This goes into the markdown branch
65+
- JSON gets sent to an agent which converts it into a more descriptive model card. These are now exported periodically as Markdown snapshots under `exports/<timestamp>/`.
6666

6767
---
6868

@@ -100,7 +100,7 @@ These are listed in `exports.md`. The latest is:
100100

101101
These prompts are mostly now populated from an N8N workflow.
102102

103-
**Markdown** versions are funneled to `system-prompts/md` and **JSON** versions to `system-prompts/json`.
103+
Markdown snapshots are generated under `exports/<timestamp>/`. JSON lives in `system-prompts/json`.
104104

105105
## Data Structure
106106

@@ -176,8 +176,8 @@ This updated data structure includes booleans for:
176176

177177
### Storage Formats
178178
System prompts are organized into two main formats:
179-
- **JSON Format**: Structured data with metadata (`system-prompts/json/` - 923 files)
180-
- **Markdown Format**: Human-readable documentation (`system-prompts/md/` - 851 files)
179+
- **JSON Format**: Structured data with metadata (`system-prompts/json/`)
180+
- **Markdown Snapshots**: Human-readable documentation generated on demand (`exports/<timestamp>/`)
181181

182182
## JSON Data Dictionary
183183

scripts/export_point_in_time_md.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
#!/usr/bin/env python3
22
"""
3-
Export system prompt JSON configs to a point-in-time Markdown snapshot.
3+
Export system prompt JSON configs to a point-in-time Markdown snapshot and archive it as a numbered release.
44
5-
Reads all JSON files from system-prompts/json (JSON fork) and writes a
6-
timestamped directory under exports/, generating one Markdown file per config
7-
following the general markdown template used in the MD fork.
5+
Reads all JSON files from system-prompts/json and writes a timestamped
6+
directory under exports/, generating one Markdown file per config following the
7+
general markdown model-card template used in this repo.
88
99
Usage:
1010
python3 scripts/export_point_in_time_md.py
1111
python3 scripts/export_point_in_time_md.py --out-dir exports/20250101-120000
12+
python3 scripts/export_point_in_time_md.py --archive-format zip
1213
1314
Notes:
1415
- Handles both JSON schemas observed in this repo (lowercase-with-hyphens and
1516
Title Case with spaces) by normalizing keys.
1617
- Missing values are rendered as "Not provided".
18+
- Produces an archive (tar.gz by default) and assigns an auto-incremented
19+
release number stored in exports/releases.json.
1720
"""
1821

1922
from __future__ import annotations
@@ -22,13 +25,16 @@
2225
import json
2326
import re
2427
from datetime import datetime
28+
import tarfile
29+
import zipfile
2530
from pathlib import Path
2631
from typing import Any, Dict, Optional
2732

2833

2934
REPO_ROOT = Path(__file__).resolve().parents[1]
3035
JSON_DIR = REPO_ROOT / "system-prompts" / "json"
3136
EXPORTS_DIR = REPO_ROOT / "exports"
37+
RELEASES_INDEX = EXPORTS_DIR / "releases.json"
3238

3339

3440
def as_bool(value: Any) -> bool:
@@ -249,8 +255,21 @@ def render_markdown(data: Dict[str, Any], json_filename: str) -> str:
249255

250256

251257
def main() -> int:
252-
parser = argparse.ArgumentParser(description="Export point-in-time Markdown snapshot from JSON configs")
258+
parser = argparse.ArgumentParser(description="Export point-in-time Markdown snapshot from JSON configs and package as a release")
253259
parser.add_argument("--out-dir", type=str, help="Output directory under exports/ (optional)")
260+
parser.add_argument(
261+
"--archive-format",
262+
type=str,
263+
choices=["tar.gz", "zip"],
264+
default="tar.gz",
265+
help="Archive format for the release (default: tar.gz)",
266+
)
267+
parser.add_argument(
268+
"--release-number",
269+
type=int,
270+
default=None,
271+
help="Override auto-incremented release number (advanced)",
272+
)
254273
args = parser.parse_args()
255274

256275
if not JSON_DIR.exists():
@@ -299,10 +318,78 @@ def main() -> int:
299318
print(f"ERROR: Failed writing {md_path.name}: {e}")
300319
continue
301320

302-
print(f"Exported {count} markdown files to {out_dir.relative_to(REPO_ROOT)}")
321+
# Determine release number
322+
releases = {"releases": []}
323+
if RELEASES_INDEX.exists():
324+
try:
325+
with open(RELEASES_INDEX, "r", encoding="utf-8") as f:
326+
releases = json.load(f) or {"releases": []}
327+
except Exception:
328+
releases = {"releases": []}
329+
330+
existing_numbers = [r.get("number", 0) for r in releases.get("releases", [])]
331+
next_number = (max(existing_numbers) if existing_numbers else 0) + 1
332+
if args.release_number is not None:
333+
next_number = int(args.release_number)
334+
335+
# Create archive
336+
timestamp = out_dir.name
337+
base_name = f"release-{next_number}_{timestamp}"
338+
archive_path: Path
339+
if args.archive_format == "tar.gz":
340+
archive_path = EXPORTS_DIR / f"{base_name}.tar.gz"
341+
# Avoid overwrite: append suffix if exists
342+
suffix = 1
343+
while archive_path.exists():
344+
archive_path = EXPORTS_DIR / f"{base_name}({suffix}).tar.gz"
345+
suffix += 1
346+
with tarfile.open(archive_path, "w:gz") as tar:
347+
tar.add(out_dir, arcname=timestamp)
348+
else:
349+
archive_path = EXPORTS_DIR / f"{base_name}.zip"
350+
suffix = 1
351+
while archive_path.exists():
352+
archive_path = EXPORTS_DIR / f"{base_name}({suffix}).zip"
353+
suffix += 1
354+
with zipfile.ZipFile(archive_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
355+
for p in out_dir.rglob("*"):
356+
if p.is_file():
357+
zf.write(p, arcname=str(Path(timestamp) / p.relative_to(out_dir)))
358+
359+
# Write release marker inside the folder
360+
try:
361+
with open(out_dir / "RELEASE.txt", "w", encoding="utf-8") as f:
362+
f.write(
363+
f"Release: {next_number}\n"
364+
f"Timestamp: {timestamp}\n"
365+
f"Files: {count}\n"
366+
f"Archive: {archive_path.name}\n"
367+
f"Format: {args.archive_format}\n"
368+
)
369+
except Exception:
370+
pass
371+
372+
# Update releases index
373+
entry = {
374+
"number": next_number,
375+
"timestamp": timestamp,
376+
"dir": str(out_dir.relative_to(REPO_ROOT)),
377+
"count": count,
378+
"archive": str(archive_path.relative_to(REPO_ROOT)),
379+
"format": args.archive_format,
380+
"created_at": datetime.now().isoformat(),
381+
}
382+
releases.setdefault("releases", []).append(entry)
383+
RELEASES_INDEX.parent.mkdir(parents=True, exist_ok=True)
384+
with open(RELEASES_INDEX, "w", encoding="utf-8") as f:
385+
json.dump(releases, f, indent=2)
386+
387+
print(
388+
f"Exported {count} markdown files to {out_dir.relative_to(REPO_ROOT)} | "
389+
f"Release #{next_number} -> {archive_path.relative_to(REPO_ROOT)}"
390+
)
303391
return 0
304392

305393

306394
if __name__ == "__main__":
307395
raise SystemExit(main())
308-

0 commit comments

Comments
 (0)