From copilot-cli-toolkit
Migrates markdown session logs to JSON format via Python scripts. Use for PRs with markdown logs needing schema conversion or batch-migrating historical sessions.
npx claudepluginhub rjmurillo/ai-agentsThis skill uses the workspace's default tool permissions.
Converts markdown session logs to JSON format for deterministic validation.
Migrates markdown session logs to JSON format for deterministic validation. Use for PRs with old markdown sessions or batch-migrating historical logs.
Creates protocol-compliant JSON session logs with git-derived state, auto-incremented numbers, and validation enforcement. Use when starting new sessions to ensure CI compliance.
Converts Claude Code JSONL conversation logs to Markdown for retrospectives, with incremental/full/project-specific options, index summaries, and analysis templates like growth tracking and bug patterns.
Share bugs, ideas, or general feedback.
Converts markdown session logs to JSON format for deterministic validation.
# Migrate single file
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/2026-01-09-session-385.md"
# Migrate all sessions in directory
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/"
# Dry run to preview changes
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --dry-run
# Force overwrite existing JSON
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --force
Use this skill when:
migrate session logs - Convert markdown to JSONconvert sessions to JSON - Format migrationPR has old markdown sessions - In-flight PR migrationsession validation failing - Regex issues with markdown formatbatch migrate sessions - Historical log conversionUse this skill when:
Use session-init instead when:
Use session-log-fixer instead when:
Markdown session logs required fragile regex patterns to validate:
**Branch**: vs Branch: vs Starting Branch:JSON provides:
JSON sessions follow the schema at:
.agents/schemas/session-log.schema.json
JSON sessions are validated by:
scripts/validate_session_json.py
┌─────────────────────────────────────────────────────────┐
│ 1. INPUT │
│ Markdown session log (.md) │
│ OR directory of .md files │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 2. PARSE │
│ • Extract session number from filename │
│ • Extract date from filename │
│ • Find branch, commit, objective in content │
│ • Parse checklist tables for completion status │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 3. TRANSFORM │
│ • Build session object (number, date, branch, etc.) │
│ • Build protocolCompliance object │
│ • Map checkbox [x] to complete: true │
│ • Extract evidence from table cells │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 4. OUTPUT │
│ Write .json file alongside .md │
│ (same name, different extension) │
└─────────────────────────────────────────────────────────┘
{
"session": {
"number": 385,
"date": "2026-01-09",
"branch": "feat/session-init-skill",
"startingCommit": "abc1234",
"objective": "Session protocol validation improvements"
},
"protocolCompliance": {
"sessionStart": {
"serenaActivated": { "level": "MUST", "complete": true, "evidence": "Tool output" },
"handoffRead": { "level": "MUST", "complete": true, "evidence": "Content in context" }
},
"sessionEnd": {
"checklistComplete": { "level": "MUST", "complete": true, "evidence": "All [x] checked" },
"validationPassed": { "level": "MUST", "complete": true, "evidence": "Exit code 0" }
}
},
"workLog": [],
"endingCommit": "",
"nextSteps": []
}
| Parameter | Type | Required | Description |
|---|---|---|---|
-Path | string | Yes | Path to .md file or directory |
-Force | switch | No | Overwrite existing .json files |
-DryRun | switch | No | Preview without writing files |
The script returns an array of migrated file paths (string[]) and prints a summary:
=== Migration Summary ===
Migrated: 356
Skipped (JSON exists): 0
Failed: 0
| Code | Meaning | Action |
|---|---|---|
0 | Success | All files migrated or skipped (expected behavior) |
1 | Failure | One or more files failed migration (check error output) |
The script prints migration summary and returns exit code 0 on success, 1 on failure.
For PRs with in-flight markdown sessions:
Check for markdown sessions in PR:
git diff origin/main --name-only | grep -E '\.agents/sessions/.*\.md$'
Run migration:
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/"
Validate migrated sessions:
for f in .agents/sessions/*.json; do python3 scripts/validate_session_json.py "$f"; done
Commit both formats (for transition period):
git add .agents/sessions/*.json
git commit -m "chore(session): migrate session logs to JSON format"
The migration script maps markdown checklist patterns to JSON keys.
| Regex Pattern | JSON Key | Level |
|---|---|---|
activate_project | serenaActivated | MUST |
initial_instructions | serenaInstructions | MUST |
HANDOFF\.md | handoffRead | MUST |
Create.*session.*log|session.*log.*exist|this.*file | sessionLogCreated | MUST |
skill.*script | skillScriptsListed | MUST |
usage-mandatory | usageMandatoryRead | MUST |
CONSTRAINTS | constraintsRead | MUST |
memor | memoriesLoaded | MUST |
verify.*branch|branch.*verif|declare.*branch | branchVerified | MUST |
not.*main|Confirm.*main | notOnMain | MUST |
git.*status | gitStatusVerified | SHOULD |
starting.*commit|Note.*commit | startingCommitNoted | SHOULD |
| Regex Pattern | JSON Key | Level |
|---|---|---|
Complete.*session.*log|session.*log.*complete|all.*section | checklistComplete | MUST |
HANDOFF.*read-only|Update.*HANDOFF | handoffPreserved | MUST |
Serena.*memory|Update.*memory|memory.*updat | serenaMemoryUpdated | MUST |
markdownlint|markdown.*lint|Run.*lint | markdownLintRun | MUST |
Commit.*change|change.*commit | changesCommitted | MUST |
Validate.*Session|validation.*pass|Route.*qa | validationPassed | MUST |
PROJECT-PLAN|task.*checkbox | tasksUpdated | SHOULD |
retrospective | retrospectiveInvoked | SHOULD |
| Avoid | Why | Instead |
|---|---|---|
| Manually converting markdown to JSON | Error-prone, misses edge cases | Use convert_session_to_json.py script |
| Deleting markdown files after migration | May need originals for reference | Keep both during transition period |
| Skipping validation after migration | Migrated JSON may still be incomplete | Always validate with validate_session_json.py |
Migrating without -DryRun first | Cannot preview changes | Use -DryRun to preview, then run for real |
After migration:
validate_session_json.pyUse -Force to overwrite:
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py ".agents/sessions/" --force
Expected for genuinely incomplete sessions. The migration preserves the actual state of checkboxes. Review failed sessions manually.
If a checklist item isn't detected, the markdown format may be non-standard. The script uses flexible regex but edge cases exist. Update the _find_checklist_item function patterns if needed.
Converts markdown session logs to JSON format.
python3 .claude/skills/session-migration/scripts/convert_session_to_json.py <input-file> [--output <output-file>]
| Skill | Purpose |
|---|---|
| session-init | Create new sessions in JSON format |
| session-log-fixer | Fix validation failures |
| Resource | Location | Purpose |
|---|---|---|
| JSON Schema | .agents/schemas/session-log.schema.json | Defines required structure |
| JSON Validator | scripts/validate_session_json.py | Validates migrated JSON files |
| Legacy Validator | scripts/validate_session_json.py | Validates markdown (deprecated) |