agentic-forge 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.gitattributes +24 -0
  2. package/.github/workflows/ci.yml +70 -0
  3. package/.markdownlint-cli2.jsonc +16 -0
  4. package/.prettierignore +3 -0
  5. package/.prettierrc +6 -0
  6. package/.vscode/agentic-forge.code-workspace +26 -0
  7. package/CHANGELOG.md +100 -0
  8. package/CLAUDE.md +158 -0
  9. package/CONTRIBUTING.md +152 -0
  10. package/LICENSE +21 -0
  11. package/README.md +145 -0
  12. package/agentic-forge-banner.png +0 -0
  13. package/biome.json +21 -0
  14. package/package.json +5 -0
  15. package/scripts/copy-assets.js +21 -0
  16. package/src/agents/explorer.md +97 -0
  17. package/src/agents/reviewer.md +137 -0
  18. package/src/checkpoints/manager.ts +119 -0
  19. package/src/claude/.claude/skills/analyze/SKILL.md +241 -0
  20. package/src/claude/.claude/skills/analyze/references/bug.md +62 -0
  21. package/src/claude/.claude/skills/analyze/references/debt.md +76 -0
  22. package/src/claude/.claude/skills/analyze/references/doc.md +67 -0
  23. package/src/claude/.claude/skills/analyze/references/security.md +76 -0
  24. package/src/claude/.claude/skills/analyze/references/style.md +72 -0
  25. package/src/claude/.claude/skills/create-checkpoint/SKILL.md +88 -0
  26. package/src/claude/.claude/skills/create-log/SKILL.md +75 -0
  27. package/src/claude/.claude/skills/fix-analyze/SKILL.md +102 -0
  28. package/src/claude/.claude/skills/git-branch/SKILL.md +71 -0
  29. package/src/claude/.claude/skills/git-commit/SKILL.md +107 -0
  30. package/src/claude/.claude/skills/git-pr/SKILL.md +96 -0
  31. package/src/claude/.claude/skills/orchestrate/SKILL.md +120 -0
  32. package/src/claude/.claude/skills/sdlc-plan/SKILL.md +163 -0
  33. package/src/claude/.claude/skills/sdlc-plan/references/bug.md +115 -0
  34. package/src/claude/.claude/skills/sdlc-plan/references/chore.md +105 -0
  35. package/src/claude/.claude/skills/sdlc-plan/references/feature.md +130 -0
  36. package/src/claude/.claude/skills/sdlc-review/SKILL.md +215 -0
  37. package/src/claude/.claude/skills/workflow-builder/SKILL.md +185 -0
  38. package/src/claude/.claude/skills/workflow-builder/references/REFERENCE.md +487 -0
  39. package/src/claude/.claude/skills/workflow-builder/references/workflow-example.yaml +427 -0
  40. package/src/cli.ts +182 -0
  41. package/src/commands/config-cmd.ts +28 -0
  42. package/src/commands/index.ts +21 -0
  43. package/src/commands/init.ts +96 -0
  44. package/src/commands/release-notes.ts +85 -0
  45. package/src/commands/resume.ts +103 -0
  46. package/src/commands/run.ts +234 -0
  47. package/src/commands/shortcuts.ts +11 -0
  48. package/src/commands/skills-dir.ts +11 -0
  49. package/src/commands/status.ts +112 -0
  50. package/src/commands/update.ts +64 -0
  51. package/src/commands/version.ts +27 -0
  52. package/src/commands/workflows.ts +129 -0
  53. package/src/config.ts +129 -0
  54. package/src/console.ts +790 -0
  55. package/src/executor.ts +354 -0
  56. package/src/git/worktree.ts +236 -0
  57. package/src/logging/logger.ts +95 -0
  58. package/src/orchestrator.ts +815 -0
  59. package/src/parser.ts +225 -0
  60. package/src/progress.ts +306 -0
  61. package/src/prompts/agentic-system.md +31 -0
  62. package/src/ralph-loop.ts +260 -0
  63. package/src/renderer.ts +164 -0
  64. package/src/runner.ts +634 -0
  65. package/src/signal-manager.ts +55 -0
  66. package/src/steps/base.ts +71 -0
  67. package/src/steps/conditional-step.ts +144 -0
  68. package/src/steps/index.ts +15 -0
  69. package/src/steps/parallel-step.ts +213 -0
  70. package/src/steps/prompt-step.ts +121 -0
  71. package/src/steps/ralph-loop-step.ts +186 -0
  72. package/src/steps/serial-step.ts +84 -0
  73. package/src/templates/analysis/bug.md.j2 +35 -0
  74. package/src/templates/analysis/debt.md.j2 +38 -0
  75. package/src/templates/analysis/doc.md.j2 +45 -0
  76. package/src/templates/analysis/security.md.j2 +35 -0
  77. package/src/templates/analysis/style.md.j2 +44 -0
  78. package/src/templates/analysis-summary.md.j2 +58 -0
  79. package/src/templates/checkpoint.md.j2 +27 -0
  80. package/src/templates/implementation-report.md.j2 +81 -0
  81. package/src/templates/memory.md.j2 +16 -0
  82. package/src/templates/plan-bug.md.j2 +42 -0
  83. package/src/templates/plan-chore.md.j2 +27 -0
  84. package/src/templates/plan-feature.md.j2 +41 -0
  85. package/src/templates/progress.json.j2 +16 -0
  86. package/src/templates/ralph-report.md.j2 +45 -0
  87. package/src/types.ts +141 -0
  88. package/src/workflows/analyze-codebase-merge.yaml +328 -0
  89. package/src/workflows/analyze-codebase.yaml +196 -0
  90. package/src/workflows/analyze-single.yaml +56 -0
  91. package/src/workflows/demo.yaml +180 -0
  92. package/src/workflows/one-shot.yaml +54 -0
  93. package/src/workflows/plan-build-review.yaml +160 -0
  94. package/src/workflows/ralph-loop.yaml +73 -0
  95. package/tests/config.test.ts +219 -0
  96. package/tests/console.test.ts +506 -0
  97. package/tests/executor.test.ts +339 -0
  98. package/tests/init.test.ts +86 -0
  99. package/tests/logger.test.ts +110 -0
  100. package/tests/parser.test.ts +290 -0
  101. package/tests/progress.test.ts +345 -0
  102. package/tests/ralph-loop.test.ts +418 -0
  103. package/tests/renderer.test.ts +350 -0
  104. package/tests/runner.test.ts +497 -0
  105. package/tests/setup.test.ts +7 -0
  106. package/tests/signal-manager.test.ts +26 -0
  107. package/tests/steps.test.ts +412 -0
  108. package/tests/worktree.test.ts +411 -0
  109. package/tsconfig.json +18 -0
  110. package/vitest.config.ts +8 -0
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ <!-- markdownlint-disable MD033 MD041 -->
2
+ <p align="center">
3
+ <img src="agentic-forge-banner.png" alt="Agentic Forge" width="600">
4
+ </p>
5
+
6
+ <h1 align="center">Agentic Forge</h1>
7
+
8
+ <p align="center">
9
+ <a href="https://github.com/e-stpierre/agentic-forge/releases"><img src="https://img.shields.io/github/v/release/e-stpierre/agentic-forge?include_prereleases" alt="GitHub release"></a>
10
+ <a href="https://github.com/e-stpierre/agentic-forge/blob/main/LICENSE"><img src="https://img.shields.io/github/license/e-stpierre/agentic-forge" alt="License"></a>
11
+ </p>
12
+
13
+ <p align="center">
14
+ <strong>YAML-based agentic workflow engine</strong>
15
+ </p>
16
+
17
+ <p align="center">
18
+ Multi-step execution | Parallel orchestration | Error recovery | Short and long-running operations
19
+ </p>
20
+
21
+ ## Overview
22
+
23
+ Agentic Forge is a TypeScript/Node.js package that provides YAML-based workflow orchestration for Claude Code. It bundles skills, agents, and prompts as package data, enabling autonomous multi-step task execution with parallel execution, conditional logic, and retry mechanisms.
24
+
25
+ **Best for**: Autonomous development where you prefer Claude works independently.
26
+
27
+ ## Getting Started
28
+
29
+ ### Prerequisites
30
+
31
+ - Node.js 20+
32
+ - [pnpm](https://pnpm.io/) (recommended) or npm
33
+ - Claude Code CLI installed and configured
34
+
35
+ ### Installation
36
+
37
+ ```bash
38
+ # Install globally with npm
39
+ npm install -g agentic-forge
40
+
41
+ # Or install from source
42
+ git clone https://github.com/e-stpierre/agentic-forge.git
43
+ cd agentic-forge
44
+ pnpm install && pnpm build
45
+ npm install -g .
46
+ ```
47
+
48
+ ### Using Skills in Interactive Claude Sessions
49
+
50
+ Agentic Forge bundles 13 skills that extend Claude Code with slash commands like `/sdlc-plan`, `/analyze`, `/git-commit`, and more. To make them available in interactive sessions:
51
+
52
+ **Option 1: Pass `--add-dir` when launching Claude**
53
+
54
+ ```bash
55
+ claude --add-dir $(agentic-forge skills-dir)
56
+ ```
57
+
58
+ **Option 2: Add to `~/.claude/settings.json` permanently**
59
+
60
+ ```json
61
+ {
62
+ "additionalDirectories": ["<output of agentic-forge skills-dir>"]
63
+ }
64
+ ```
65
+
66
+ ## Workflows
67
+
68
+ ### plan-build-review (Full SDLC)
69
+
70
+ Plan -> Create Branch -> Implement (iterative) -> Review -> Fix Issues -> Create PR
71
+
72
+ ```bash
73
+ agentic-forge run plan-build-review --var "task=Add dark mode support"
74
+ ```
75
+
76
+ ### one-shot (Single Task)
77
+
78
+ Create Branch -> Execute Task -> Review -> Create PR
79
+
80
+ ```bash
81
+ agentic-forge run one-shot --var "task=Add user authentication"
82
+ ```
83
+
84
+ ### ralph-loop (Iterative Execution)
85
+
86
+ Generic iterative loop where each iteration runs in a fresh session.
87
+
88
+ ```bash
89
+ agentic-forge run ralph-loop --var "task=Follow the improvement plan" --var "max_iterations=20"
90
+ ```
91
+
92
+ ### analyze-codebase (Parallel Analysis)
93
+
94
+ Run 5 parallel analysis types (bug, debt, doc, security, style) with optional autofix.
95
+
96
+ ```bash
97
+ agentic-forge run analyze-codebase --var "autofix=true"
98
+ ```
99
+
100
+ ### All Commands
101
+
102
+ ```bash
103
+ # List available workflows
104
+ agentic-forge workflows
105
+
106
+ # Run a workflow with variables
107
+ agentic-forge run <workflow> --var "key=value"
108
+
109
+ # Print path to bundled skills directory
110
+ agentic-forge skills-dir
111
+
112
+ # Check current version
113
+ agentic-forge version
114
+
115
+ # Update to latest version
116
+ agentic-forge update
117
+ ```
118
+
119
+ ## Repository Structure
120
+
121
+ ```text
122
+ src/
123
+ agents/ # Bundled agent definitions (explorer, reviewer)
124
+ claude/.claude/ # Skills loaded via --add-dir
125
+ skills/ # 13 bundled skills
126
+ commands/ # CLI command implementations
127
+ prompts/ # System prompt templates
128
+ steps/ # Workflow step handlers
129
+ workflows/ # 7 bundled YAML workflow definitions
130
+ *.ts # Core TypeScript modules
131
+ tests/ # Vitest test suite
132
+ ```
133
+
134
+ ## Contributing
135
+
136
+ - **Bug reports and suggestions** - [Open an issue](https://github.com/e-stpierre/agentic-forge/issues) on GitHub
137
+ - **Code contributions** - See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and PR guidelines
138
+
139
+ ## Credits
140
+
141
+ - Original ralph-loop technique: [Geoffrey Huntley - Ralph Wiggum as a "software engineer"](https://ghuntley.com/ralph/)
142
+
143
+ ## License
144
+
145
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Binary file
package/biome.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
+ "organizeImports": {
4
+ "enabled": true
5
+ },
6
+ "linter": {
7
+ "enabled": true,
8
+ "rules": {
9
+ "recommended": true
10
+ }
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "tab",
15
+ "lineWidth": 100
16
+ },
17
+ "files": {
18
+ "include": ["src/**/*.ts", "tests/**/*.ts", "scripts/**/*.js", "vitest.config.ts"],
19
+ "ignore": ["node_modules", "dist", "src/agentic_forge"]
20
+ }
21
+ }
package/package.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "agentic-forge",
3
+ "version": "0.0.0",
4
+ "description": "YAML-based agentic workflow engine with multi-step execution, parallel orchestration, error recovery, and support for short and long-running operations"
5
+ }
@@ -0,0 +1,21 @@
1
+ import { cpSync, existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const root = join(__dirname, "..");
7
+ const src = join(root, "src");
8
+ const dist = join(root, "dist");
9
+
10
+ const assets = ["agents", "claude", "prompts", "templates", "workflows"];
11
+
12
+ for (const asset of assets) {
13
+ const srcPath = join(src, asset);
14
+ const distPath = join(dist, asset);
15
+ if (existsSync(srcPath)) {
16
+ cpSync(srcPath, distPath, { recursive: true });
17
+ console.log(`Copied ${asset} -> dist/${asset}`);
18
+ } else {
19
+ console.warn(`Warning: ${srcPath} not found, skipping`);
20
+ }
21
+ }
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: explorer
3
+ description: Efficiently explores codebase to find relevant files and code
4
+ tools: [Glob, Grep, Read, Task]
5
+ model: sonnet
6
+ color: blue
7
+ ---
8
+
9
+ # Explorer Agent
10
+
11
+ ## Purpose
12
+
13
+ Codebase exploration specialist that efficiently navigates and understands codebases to find information relevant to specific tasks. Invoked when exploring code structure, finding relevant files, tracing dependencies, or understanding architectural patterns.
14
+
15
+ ## Methodology
16
+
17
+ ### Start Broad
18
+
19
+ Use glob patterns to identify candidate files by name and location.
20
+
21
+ ### Filter by Content
22
+
23
+ Use grep to narrow down to relevant code within candidate files.
24
+
25
+ ### Trace Dependencies
26
+
27
+ Follow imports and references to understand relationships.
28
+
29
+ ### Map Architecture
30
+
31
+ Understand how components connect and interact.
32
+
33
+ ## Tools Available
34
+
35
+ - **Glob**: Find files by pattern. Use `**/*.ts` patterns to limit to relevant file types.
36
+ - **Grep**: Search file contents. Search for unique identifiers (function names, class names).
37
+ - **Read**: Read specific files. Use sparingly - prefer search tools first.
38
+ - **Task**: Delegate sub-explorations for parallel investigation.
39
+
40
+ ## Capabilities
41
+
42
+ - **File Discovery**: Find files relevant to a task using glob patterns and content search
43
+ - **Code Analysis**: Understand code structure, dependencies, and relationships
44
+ - **Pattern Recognition**: Identify conventions, patterns, and architectural decisions
45
+ - **Dependency Mapping**: Trace imports and references across files
46
+
47
+ ### Search Priorities
48
+
49
+ When exploring for a task, prioritize in this order:
50
+
51
+ 1. **Direct matches**: Files directly named after the feature/component
52
+ 2. **Related imports**: Files that import/export the target
53
+ 3. **Test files**: Tests often reveal usage patterns
54
+ 4. **Configuration**: Config files that affect behavior
55
+ 5. **Documentation**: READMEs, comments that explain design
56
+
57
+ ## Knowledge Base
58
+
59
+ - Code navigation patterns and techniques
60
+ - Common project structures (monorepos, microservices, etc.)
61
+ - Framework conventions (React, Express, Django, etc.)
62
+ - Dependency management across languages
63
+ - Git history analysis for context
64
+
65
+ ## Output Guidance
66
+
67
+ Return findings as structured JSON data:
68
+
69
+ ```json
70
+ {
71
+ "relevant_files": [
72
+ {
73
+ "path": "src/auth/handler.ts",
74
+ "relevance": "high",
75
+ "reason": "Contains authentication logic",
76
+ "key_lines": [42, 78, 156]
77
+ }
78
+ ],
79
+ "patterns_found": [
80
+ {
81
+ "name": "Error handling middleware",
82
+ "location": "src/middleware/error.ts",
83
+ "description": "Centralized error handling pattern"
84
+ }
85
+ ],
86
+ "dependencies": ["express", "jsonwebtoken"],
87
+ "architecture_notes": "Service layer pattern with repository abstraction"
88
+ }
89
+ ```
90
+
91
+ **Guidelines:**
92
+
93
+ - Minimize file reads - use search tools first
94
+ - Focus on finding the minimum set of files needed
95
+ - Note patterns and conventions for future reference
96
+ - Report uncertainty or ambiguity
97
+ - Provide line numbers for specific findings
@@ -0,0 +1,137 @@
1
+ ---
2
+ name: reviewer
3
+ description: Reviews code for quality, correctness, and best practices
4
+ tools: [Read, Grep, Glob, Bash]
5
+ model: sonnet
6
+ color: green
7
+ ---
8
+
9
+ # Reviewer Agent
10
+
11
+ ## Purpose
12
+
13
+ Code review specialist that validates code changes for correctness, quality, and adherence to best practices. Invoked when reviewing pull requests, validating implementations, running security analysis, or ensuring code quality standards.
14
+
15
+ ## Methodology
16
+
17
+ ### Understand Context
18
+
19
+ Read the plan or task description to understand what the code should accomplish.
20
+
21
+ ### Review Changes
22
+
23
+ Examine modified files systematically, checking each review dimension.
24
+
25
+ ### Run Tests
26
+
27
+ Verify tests pass and cover new code adequately.
28
+
29
+ ### Check Patterns
30
+
31
+ Ensure consistency with existing codebase patterns and conventions.
32
+
33
+ ### Report Findings
34
+
35
+ Categorize findings by severity (critical, major, minor, info).
36
+
37
+ ## Tools Available
38
+
39
+ - **Read**: Read source files to understand code structure and logic.
40
+ - **Grep**: Search for patterns across the codebase.
41
+ - **Glob**: Find files by pattern for systematic review.
42
+ - **Bash**: Run test suites and linting tools.
43
+
44
+ ## Capabilities
45
+
46
+ - **Code Review**: Validate code changes for correctness and quality
47
+ - **Test Validation**: Verify tests pass and coverage is adequate
48
+ - **Security Analysis**: Check for vulnerabilities and unsafe patterns
49
+ - **Convention Checking**: Ensure adherence to project patterns
50
+
51
+ ### Review Dimensions
52
+
53
+ 1. **Correctness**: Does the code do what it's supposed to?
54
+ 2. **Security**: Are there any security vulnerabilities?
55
+ 3. **Performance**: Are there obvious performance issues?
56
+ 4. **Maintainability**: Is the code readable and maintainable?
57
+ 5. **Testing**: Is there adequate test coverage?
58
+ 6. **Conventions**: Does it follow project patterns?
59
+
60
+ ### Severity Levels
61
+
62
+ - **Critical**: Must fix before merge (security holes, data loss risk)
63
+ - **Major**: Should fix before merge (bugs, significant issues)
64
+ - **Minor**: Nice to fix (code quality, minor improvements)
65
+ - **Info**: Informational (suggestions, alternatives)
66
+
67
+ ## Knowledge Base
68
+
69
+ ### Security Checklist
70
+
71
+ - No hardcoded secrets
72
+ - Input validation present
73
+ - Proper authentication/authorization
74
+ - No injection vulnerabilities
75
+ - Sensitive data handled properly
76
+
77
+ ### Quality Checklist
78
+
79
+ - No code duplication
80
+ - Clear naming conventions
81
+ - Proper error handling
82
+ - No dead code
83
+ - Reasonable complexity
84
+
85
+ ### Testing Checklist
86
+
87
+ - Tests exist for new code
88
+ - Edge cases covered
89
+ - Tests are meaningful (not just coverage)
90
+ - Mocks used appropriately
91
+
92
+ ### Conventions Checklist
93
+
94
+ - Follows project style guide
95
+ - Consistent with existing patterns
96
+ - Proper imports organization
97
+ - Documentation where needed
98
+
99
+ ## Output Guidance
100
+
101
+ Return findings as structured JSON data:
102
+
103
+ ```json
104
+ {
105
+ "review_passed": true,
106
+ "findings": [
107
+ {
108
+ "severity": "major",
109
+ "category": "security",
110
+ "file": "src/api/users.ts",
111
+ "line": 45,
112
+ "issue": "User input not sanitized before database query",
113
+ "suggestion": "Use parameterized query or ORM method"
114
+ }
115
+ ],
116
+ "tests": {
117
+ "passed": true,
118
+ "coverage": 85,
119
+ "missing_coverage": ["src/auth/refresh.ts:30-45"]
120
+ },
121
+ "summary": {
122
+ "critical": 0,
123
+ "major": 1,
124
+ "minor": 3,
125
+ "info": 5
126
+ },
127
+ "recommendation": "Address major security issue before merging"
128
+ }
129
+ ```
130
+
131
+ **Guidelines:**
132
+
133
+ - Be thorough but efficient
134
+ - Focus on substance over style
135
+ - Provide actionable feedback
136
+ - Explain the "why" behind suggestions
137
+ - Consider the broader context
@@ -0,0 +1,119 @@
1
+ /** Checkpoint management for workflow sessions. */
2
+
3
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
4
+ import path from "node:path";
5
+ import yaml from "js-yaml";
6
+
7
+ // --- Path helper ---
8
+
9
+ export function getCheckpointPath(workflowId: string, repoRoot?: string): string {
10
+ const root = repoRoot ?? process.cwd();
11
+ return path.join(root, "agentic", "outputs", workflowId, "checkpoint.md");
12
+ }
13
+
14
+ // --- Create checkpoint ---
15
+
16
+ export function createCheckpoint(
17
+ workflowId: string,
18
+ step: string,
19
+ context: string,
20
+ progress: string,
21
+ notes = "",
22
+ issues = "",
23
+ repoRoot?: string,
24
+ ): string {
25
+ const checkpointPath = getCheckpointPath(workflowId, repoRoot);
26
+ const dir = path.dirname(checkpointPath);
27
+ mkdirSync(dir, { recursive: true });
28
+
29
+ const existing = readCheckpoints(workflowId, repoRoot);
30
+ const checkpointNum = existing.length + 1;
31
+ const checkpointId = `chk-${String(checkpointNum).padStart(3, "0")}`;
32
+
33
+ const timestamp = new Date().toISOString();
34
+
35
+ const frontmatter: Record<string, unknown> = {
36
+ checkpoint_id: checkpointId,
37
+ step,
38
+ created: timestamp,
39
+ workflow_id: workflowId,
40
+ status: "in_progress",
41
+ };
42
+
43
+ const entryLines: string[] = [
44
+ "---",
45
+ yaml.dump(frontmatter, { flowLevel: -1 }).trim(),
46
+ "---",
47
+ "",
48
+ "## Context",
49
+ "",
50
+ context,
51
+ "",
52
+ "## Progress",
53
+ "",
54
+ progress,
55
+ "",
56
+ ];
57
+
58
+ if (notes) {
59
+ entryLines.push("## Notes for Next Session", "", notes, "");
60
+ }
61
+
62
+ if (issues) {
63
+ entryLines.push("## Issues Discovered", "", issues, "");
64
+ }
65
+
66
+ entryLines.push("---\n");
67
+ const entry = entryLines.join("\n");
68
+
69
+ appendFileSync(checkpointPath, entry, "utf-8");
70
+
71
+ return checkpointId;
72
+ }
73
+
74
+ // --- Read checkpoints ---
75
+
76
+ export function readCheckpoints(workflowId: string, repoRoot?: string): Record<string, unknown>[] {
77
+ const checkpointPath = getCheckpointPath(workflowId, repoRoot);
78
+
79
+ if (!existsSync(checkpointPath)) {
80
+ return [];
81
+ }
82
+
83
+ const content = readFileSync(checkpointPath, "utf-8");
84
+ const checkpoints: Record<string, unknown>[] = [];
85
+
86
+ const parts = content.split("---");
87
+
88
+ let i = 1;
89
+ while (i < parts.length - 1) {
90
+ const frontmatterStr = parts[i].trim();
91
+ const body = i + 1 < parts.length ? parts[i + 1].trim() : "";
92
+
93
+ if (frontmatterStr) {
94
+ try {
95
+ const frontmatter = yaml.load(frontmatterStr) as Record<string, unknown> | null;
96
+ if (frontmatter && "checkpoint_id" in frontmatter) {
97
+ frontmatter.content = body;
98
+ checkpoints.push(frontmatter);
99
+ }
100
+ } catch {
101
+ // Invalid YAML, skip
102
+ }
103
+ }
104
+
105
+ i += 2;
106
+ }
107
+
108
+ return checkpoints;
109
+ }
110
+
111
+ // --- Get latest checkpoint ---
112
+
113
+ export function getLatestCheckpoint(
114
+ workflowId: string,
115
+ repoRoot?: string,
116
+ ): Record<string, unknown> | null {
117
+ const checkpoints = readCheckpoints(workflowId, repoRoot);
118
+ return checkpoints.length > 0 ? checkpoints[checkpoints.length - 1] : null;
119
+ }