@tarcisiopgs/lisa 1.12.1 → 1.12.2

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.
package/README.md CHANGED
@@ -12,6 +12,13 @@
12
12
  Lisa is an autonomous issue resolver that turns your backlog into pull requests — no babysitting required.
13
13
  </p>
14
14
 
15
+ <p align="center">
16
+ <a href="https://www.npmjs.com/package/@tarcisiopgs/lisa"><img src="https://img.shields.io/npm/v/@tarcisiopgs/lisa.svg" alt="npm version" /></a>
17
+ <a href="https://www.npmjs.com/package/@tarcisiopgs/lisa"><img src="https://img.shields.io/npm/dm/@tarcisiopgs/lisa.svg" alt="npm downloads" /></a>
18
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" /></a>
19
+ <img src="https://img.shields.io/node/v/%40tarcisiopgs%2Flisa" alt="Node.js version" />
20
+ </p>
21
+
15
22
  ---
16
23
 
17
24
  ## Quickstart
@@ -24,6 +31,8 @@ lisa run
24
31
 
25
32
  That's it. Lisa picks up the next labeled issue, implements it, pushes a branch, opens a pull request, and moves the ticket to "In Review" — all without you touching it.
26
33
 
34
+ `lisa init` offers pre-defined templates for the most common source + provider combinations (GitHub Issues + Claude, Linear + Claude, Jira + Claude, and more). Select a template to pre-fill sensible defaults, or choose "Configure manually" for full control.
35
+
27
36
  ## Try it safely first
28
37
 
29
38
  Before letting Lisa touch real issues, verify your configuration with `--dry-run`. No issues will be fetched, no code will be written, no PRs will be created.
@@ -53,11 +62,11 @@ Lisa follows a deterministic pipeline:
53
62
  └─────────┘ └──────────┘ └───────────┘ └──────────┘ └────┘ └────────┘
54
63
  ```
55
64
 
56
- 1. **Fetch** — Pulls the next issue from Linear, Trello, Plane, Shortcut, GitLab Issues, GitHub Issues, or Jira matching the configured label, team, and project. Issues are sorted by priority. Blocked issues are skipped.
65
+ 1. **Fetch** — Pulls the next issue from your project tracker matching the configured label, team, and project. Issues are sorted by priority. Blocked issues are skipped.
57
66
  2. **Activate** — Moves the issue to `in_progress` so your team knows it's being worked on.
58
67
  3. **Implement** — Builds a structured prompt with full issue context and sends it to the AI agent. The agent works in a worktree or branch, implements the change, runs tests, and commits.
59
68
  4. **Validate** — If the agent's tests pass and pre-push hooks succeed, the branch is pushed. If hooks fail, Lisa re-invokes the agent with the error output and retries.
60
- 5. **PR** — Pushes the branch and creates a pull request referencing the original issue.
69
+ 5. **PR** — Pushes the branch and creates a pull request (or merge request) referencing the original issue.
61
70
  6. **Update** — Moves the issue to the `done` status and removes the pickup label.
62
71
  7. **Next** — Picks the next issue. When there are no more matching issues, Lisa stops.
63
72
 
@@ -71,7 +80,29 @@ Lisa follows a deterministic pipeline:
71
80
  - **Self-healing** — Orphan issues stuck in "In Progress" are recovered on startup. Pre-push failures trigger the agent to fix and retry.
72
81
  - **Guardrails** — Past failures are logged and injected into future prompts so the agent avoids repeating mistakes.
73
82
 
74
- ## Providers
83
+ ---
84
+
85
+ ## Issue Sources
86
+
87
+ Lisa integrates with **7 project trackers** out of the box:
88
+
89
+ | Source | Key | Notes |
90
+ |--------|-----|-------|
91
+ | Linear | `linear` | GraphQL API — priority-sorted, project-scoped, blocker-aware |
92
+ | GitHub Issues | `github-issues` | Native GitHub issues with label-based pickup |
93
+ | Jira | `jira` | Atlassian Jira via REST API (cloud and self-hosted) |
94
+ | GitLab Issues | `gitlab-issues` | GitLab issues with label transitions |
95
+ | Trello | `trello` | Card-based workflow via Trello REST API |
96
+ | Plane | `plane` | Open-source project management (cloud and self-hosted) |
97
+ | Shortcut | `shortcut` | Story-based tracking (formerly Clubhouse) |
98
+
99
+ Each source supports label filtering, priority ordering, and status transitions out of the box. See [Source-Specific Fields](#source-specific-fields) for configuration details.
100
+
101
+ ---
102
+
103
+ ## AI Providers
104
+
105
+ Lisa supports **8 AI coding agents** as implementation backends:
75
106
 
76
107
  | Provider | Key | Command |
77
108
  |----------|-----|---------|
@@ -102,6 +133,33 @@ models:
102
133
  - claude-haiku-4-5 # fallback 2
103
134
  ```
104
135
 
136
+ ---
137
+
138
+ ## PR Delivery
139
+
140
+ Lisa delivers pull requests and merge requests to **4 platforms**:
141
+
142
+ | Platform | Key | Auth | Output |
143
+ |----------|-----|------|--------|
144
+ | GitHub CLI | `cli` | `gh auth login` | Pull Request |
145
+ | GitHub API | `token` | `GITHUB_TOKEN` | Pull Request |
146
+ | GitLab | `gitlab` | `GITLAB_TOKEN` | Merge Request |
147
+ | Bitbucket | `bitbucket` | `BITBUCKET_TOKEN` + `BITBUCKET_USERNAME` | Pull Request |
148
+
149
+ Set `github` in your config (or pass `--github` at runtime) to select the delivery method:
150
+
151
+ ```yaml
152
+ github: gitlab # or: cli, token, bitbucket
153
+ ```
154
+
155
+ ```bash
156
+ lisa run --github bitbucket # override at runtime
157
+ ```
158
+
159
+ Each platform appends a `🤖 Resolved by lisa` attribution comment to the PR/MR after creation.
160
+
161
+ ---
162
+
105
163
  ## Install
106
164
 
107
165
  ```bash
@@ -111,8 +169,11 @@ npm install -g @tarcisiopgs/lisa
111
169
  ## Environment Variables
112
170
 
113
171
  ```bash
114
- # Required for PR creation (at least one)
115
- export GITHUB_TOKEN="" # or have `gh` CLI authenticated
172
+ # PR/MR delivery set one based on your platform
173
+ export GITHUB_TOKEN="" # GitHub — or have `gh` CLI authenticated (github: cli or token)
174
+ export GITLAB_TOKEN="" # GitLab MR creation (github: gitlab)
175
+ export BITBUCKET_TOKEN="" # Bitbucket PR creation (github: bitbucket)
176
+ export BITBUCKET_USERNAME="" # Bitbucket username (required with BITBUCKET_TOKEN)
116
177
 
117
178
  # Required when source = linear
118
179
  export LINEAR_API_KEY=""
@@ -129,7 +190,7 @@ export PLANE_WORKSPACE="" # optional; fallback when team is not set in config
129
190
  # Required when source = shortcut
130
191
  export SHORTCUT_API_TOKEN=""
131
192
 
132
- # Required when source = gitlab-issues
193
+ # Required when source = gitlab-issues or github = gitlab
133
194
  export GITLAB_TOKEN=""
134
195
  export GITLAB_BASE_URL="" # optional; defaults to https://gitlab.com
135
196
 
@@ -140,6 +201,10 @@ export GITHUB_TOKEN="" # same token used for PR creation
140
201
  export JIRA_BASE_URL="" # e.g. https://yourcompany.atlassian.net
141
202
  export JIRA_EMAIL="" # Atlassian account email
142
203
  export JIRA_API_TOKEN="" # Atlassian API token
204
+
205
+ # Optional — anonymous crash reporting (disabled by default)
206
+ export LISA_TELEMETRY=1 # enable anonymous crash/error reporting
207
+ export LISA_NO_TELEMETRY=1 # disable reporting (overrides LISA_TELEMETRY and config)
143
208
  ```
144
209
 
145
210
  ## Commands
@@ -157,15 +222,16 @@ export JIRA_API_TOKEN="" # Atlassian API token
157
222
  | `lisa run --provider NAME` | Override AI provider |
158
223
  | `lisa run --source NAME` | Override issue source |
159
224
  | `lisa run --label NAME` | Override label filter |
160
- | `lisa run --github METHOD` | Override GitHub method (`cli` or `token`) |
225
+ | `lisa run --github METHOD` | Override PR platform (`cli`, `token`, `gitlab`, or `bitbucket`) |
161
226
  | `lisa run --no-bell` | Disable terminal bell on issue completion/failure |
162
- | `lisa init` | Create `.lisa/config.yaml` interactively |
227
+ | `lisa init` | Create `.lisa/config.yaml` interactively (offers pre-defined templates) |
163
228
  | `lisa config` | Edit config interactively |
164
229
  | `lisa config --show` | Print current config as JSON |
165
230
  | `lisa config --set key=value` | Set a single config value |
166
231
  | `lisa status` | Show session stats |
167
232
  | `lisa issue get <id>` | Fetch full issue details as JSON (for use inside worktrees) |
168
233
  | `lisa issue done <id> --pr-url <url>` | Complete issue, attach PR, update status, remove label |
234
+ | `lisa feedback --pr <url> --issue <id>` | Inject PR review comments from a closed-without-merge PR into guardrails |
169
235
 
170
236
  ## TUI
171
237
 
@@ -219,7 +285,7 @@ source_config:
219
285
  in_progress: In Progress
220
286
  done: In Review
221
287
 
222
- github: cli # "cli" (gh) or "token" (GITHUB_TOKEN)
288
+ github: cli # "cli" (gh), "token" (GITHUB_TOKEN), "gitlab" (GITLAB_TOKEN), or "bitbucket" (BITBUCKET_TOKEN)
223
289
  workspace: .
224
290
  base_branch: main
225
291
 
@@ -249,6 +315,10 @@ overseer:
249
315
  # Optional — validate issue spec before accepting
250
316
  validation:
251
317
  require_acceptance_criteria: true # skip issues without detectable acceptance criteria (default: true)
318
+
319
+ # Optional — anonymous crash/error reporting (disabled by default)
320
+ telemetry:
321
+ enabled: true # set via `lisa init` prompt or LISA_TELEMETRY=1; override with LISA_NO_TELEMETRY=1
252
322
  ```
253
323
 
254
324
  ### Source-Specific Fields
@@ -365,7 +435,8 @@ Lisa detects blocked issues using the `completedBlockerIds` from your issue trac
365
435
  - **Orphan recovery** — On startup, Lisa scans for issues stuck in `in_progress` from interrupted runs and reverts them to `pick_from`.
366
436
  - **Push recovery** — If `git push` fails due to pre-push hooks (linter, typecheck, tests), Lisa re-invokes the agent with the error output and retries the push.
367
437
  - **Signal handling** — SIGINT/SIGTERM gracefully revert the active issue to its previous status before exiting.
368
- - **Guardrails** — Failed sessions are logged to `.lisa/guardrails.md` and injected into future prompts so the agent avoids repeating the same mistakes.
438
+ - **Guardrails** — Failed sessions and rejected PR reviews are logged and injected into future prompts so the agent avoids repeating the same mistakes.
439
+ - **PR feedback injection** — When a PR created by Lisa is closed without merge, review comments are automatically captured and injected as guardrails for the next run of the same issue. Use `lisa feedback --pr <url> --issue <id>` to inject feedback manually.
369
440
 
370
441
  ### Overseer
371
442
 
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/git/pr-feedback.ts
4
+ import { execa } from "execa";
5
+ function parsePrUrl(prUrl) {
6
+ const match = prUrl.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
7
+ if (!match) return null;
8
+ return { owner: match[1] ?? "", repo: match[2] ?? "", prNumber: match[3] ?? "" };
9
+ }
10
+ async function fetchPrFeedback(prUrl) {
11
+ const parsed = parsePrUrl(prUrl);
12
+ if (!parsed) {
13
+ throw new Error(`Invalid GitHub PR URL: ${prUrl}`);
14
+ }
15
+ const { owner, repo, prNumber } = parsed;
16
+ const { stdout: prJson } = await execa("gh", [
17
+ "pr",
18
+ "view",
19
+ prUrl,
20
+ "--json",
21
+ "title,state,mergedAt"
22
+ ]);
23
+ const { title, state, mergedAt } = JSON.parse(prJson);
24
+ let prState;
25
+ if (mergedAt) {
26
+ prState = "merged";
27
+ } else if (state === "CLOSED") {
28
+ prState = "closed";
29
+ } else {
30
+ prState = "open";
31
+ }
32
+ const { stdout: reviewsJson } = await execa("gh", [
33
+ "api",
34
+ `/repos/${owner}/${repo}/pulls/${prNumber}/reviews`
35
+ ]);
36
+ const rawReviews = JSON.parse(reviewsJson);
37
+ const reviews = rawReviews.filter((r) => r.body.trim()).map((r) => ({
38
+ author: r.user.login,
39
+ state: r.state,
40
+ body: r.body,
41
+ submittedAt: r.submitted_at
42
+ }));
43
+ const { stdout: commentsJson } = await execa("gh", [
44
+ "api",
45
+ `/repos/${owner}/${repo}/pulls/${prNumber}/comments`
46
+ ]);
47
+ const rawComments = JSON.parse(commentsJson);
48
+ const comments = rawComments.map((c) => ({
49
+ author: c.user.login,
50
+ body: c.body,
51
+ path: c.path,
52
+ line: c.line,
53
+ createdAt: c.created_at
54
+ }));
55
+ return { prUrl, title, state: prState, reviews, comments };
56
+ }
57
+ function formatPrFeedbackEntry(feedback, issueId, date) {
58
+ const lines = [
59
+ `## PR Feedback for Issue ${issueId} (${date})`,
60
+ `- PR: ${feedback.prUrl}`,
61
+ `- Title: ${feedback.title}`,
62
+ `- Status: Closed without merge`
63
+ ];
64
+ if (feedback.reviews.length > 0) {
65
+ lines.push("- Reviews:");
66
+ lines.push("```");
67
+ for (const review of feedback.reviews) {
68
+ lines.push(`[${review.author}] ${review.state}: ${review.body}`);
69
+ }
70
+ lines.push("```");
71
+ }
72
+ if (feedback.comments.length > 0) {
73
+ lines.push("- Inline comments:");
74
+ lines.push("```");
75
+ for (const comment of feedback.comments) {
76
+ const location = comment.path ? ` (${comment.path}${comment.line ? `:${comment.line}` : ""})` : "";
77
+ lines.push(`[${comment.author}]${location}: ${comment.body}`);
78
+ }
79
+ lines.push("```");
80
+ }
81
+ return lines.join("\n");
82
+ }
83
+
84
+ export {
85
+ parsePrUrl,
86
+ fetchPrFeedback,
87
+ formatPrFeedbackEntry
88
+ };
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getGuardrailsPath
4
+ } from "./chunk-OYQ6TOAG.js";
5
+
6
+ // src/session/guardrails.ts
7
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
8
+ import { dirname, join } from "path";
9
+ var LEGACY_GUARDRAILS_FILE = ".lisa/guardrails.md";
10
+ var MAX_ENTRIES = 20;
11
+ var CONTEXT_LINES = 20;
12
+ var writeLock = Promise.resolve();
13
+ function guardrailsPath(cwd) {
14
+ return getGuardrailsPath(cwd);
15
+ }
16
+ function migrateGuardrails(cwd) {
17
+ const legacyPath = join(cwd, LEGACY_GUARDRAILS_FILE);
18
+ if (!existsSync(legacyPath)) return;
19
+ const cachePath = getGuardrailsPath(cwd);
20
+ if (existsSync(cachePath)) return;
21
+ const cacheDir = dirname(cachePath);
22
+ if (!existsSync(cacheDir)) {
23
+ mkdirSync(cacheDir, { recursive: true });
24
+ }
25
+ copyFileSync(legacyPath, cachePath);
26
+ }
27
+ function readGuardrails(cwd) {
28
+ const path = getGuardrailsPath(cwd);
29
+ if (!existsSync(path)) return "";
30
+ try {
31
+ return readFileSync(path, "utf-8");
32
+ } catch {
33
+ return "";
34
+ }
35
+ }
36
+ function buildGuardrailsSection(cwd) {
37
+ const content = readGuardrails(cwd);
38
+ if (!content.trim()) return "";
39
+ return `
40
+ ## Guardrails \u2014 Avoid these known pitfalls
41
+
42
+ ${content}
43
+ `;
44
+ }
45
+ function extractContext(output) {
46
+ const lines = output.trim().split("\n");
47
+ return lines.slice(-CONTEXT_LINES).join("\n");
48
+ }
49
+ function extractErrorType(output) {
50
+ if (/429|rate.?limit|quota/i.test(output)) return "Rate limit / quota exceeded";
51
+ if (/ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND/.test(output)) return "Network error";
52
+ if (/timeout|timed?\s*out/i.test(output)) return "Timeout";
53
+ const exitMatch = output.match(/exit code[:\s]+(\d+)/i);
54
+ if (exitMatch) return `Exit code ${exitMatch[1]}`;
55
+ if (/exit(?:ed)? with/i.test(output)) return "Non-zero exit code";
56
+ return "Unknown error";
57
+ }
58
+ function appendEntry(dir, entry) {
59
+ writeLock = writeLock.then(() => appendEntrySync(dir, entry)).catch(() => {
60
+ });
61
+ }
62
+ function appendEntrySync(dir, entry) {
63
+ const path = guardrailsPath(dir);
64
+ const guardrailsDir = dirname(path);
65
+ if (!existsSync(guardrailsDir)) {
66
+ mkdirSync(guardrailsDir, { recursive: true });
67
+ }
68
+ const existing = existsSync(path) ? readFileSync(path, "utf-8") : "";
69
+ const newEntryText = formatEntry(entry);
70
+ let content;
71
+ if (!existing.trim()) {
72
+ content = `# Guardrails \u2014 Li\xE7\xF5es aprendidas
73
+
74
+ ${newEntryText}`;
75
+ } else {
76
+ const header = extractHeader(existing);
77
+ const entries = splitEntries(existing);
78
+ entries.push(newEntryText);
79
+ const rotated = entries.length > MAX_ENTRIES ? entries.slice(-MAX_ENTRIES) : entries;
80
+ content = `${header}
81
+
82
+ ${rotated.join("\n\n")}`;
83
+ }
84
+ writeFileSync(path, content, "utf-8");
85
+ }
86
+ function appendRawEntry(dir, entryText) {
87
+ writeLock = writeLock.then(() => appendRawEntrySync(dir, entryText)).catch(() => {
88
+ });
89
+ }
90
+ function appendRawEntrySync(dir, entryText) {
91
+ const path = guardrailsPath(dir);
92
+ const guardrailsDir = dirname(path);
93
+ if (!existsSync(guardrailsDir)) {
94
+ mkdirSync(guardrailsDir, { recursive: true });
95
+ }
96
+ const existing = existsSync(path) ? readFileSync(path, "utf-8") : "";
97
+ let content;
98
+ if (!existing.trim()) {
99
+ content = `# Guardrails \u2014 Li\xE7\xF5es aprendidas
100
+
101
+ ${entryText}`;
102
+ } else {
103
+ const header = extractHeader(existing);
104
+ const entries = splitEntries(existing);
105
+ entries.push(entryText);
106
+ const rotated = entries.length > MAX_ENTRIES ? entries.slice(-MAX_ENTRIES) : entries;
107
+ content = `${header}
108
+
109
+ ${rotated.join("\n\n")}`;
110
+ }
111
+ writeFileSync(path, content, "utf-8");
112
+ }
113
+ function formatEntry(entry) {
114
+ return [
115
+ `## Issue ${entry.issueId} (${entry.date})`,
116
+ `- Provider: ${entry.provider}`,
117
+ `- Erro: ${entry.errorType}`,
118
+ `- Contexto:`,
119
+ "```",
120
+ entry.context,
121
+ "```"
122
+ ].join("\n");
123
+ }
124
+ function extractHeader(content) {
125
+ const firstEntry = content.search(/^## /m);
126
+ if (firstEntry === -1) return content.trim();
127
+ return content.slice(0, firstEntry).trim();
128
+ }
129
+ function splitEntries(content) {
130
+ const positions = [];
131
+ const regex = /^## /gm;
132
+ for (const match of content.matchAll(regex)) {
133
+ positions.push(match.index);
134
+ }
135
+ return positions.map((start, i) => {
136
+ const end = positions[i + 1] ?? content.length;
137
+ return content.slice(start, end).trim();
138
+ });
139
+ }
140
+
141
+ export {
142
+ guardrailsPath,
143
+ migrateGuardrails,
144
+ readGuardrails,
145
+ buildGuardrailsSection,
146
+ extractContext,
147
+ extractErrorType,
148
+ appendEntry,
149
+ appendEntrySync,
150
+ appendRawEntry,
151
+ appendRawEntrySync
152
+ };
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/paths.ts
4
+ import { createHash } from "crypto";
5
+ import { existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from "fs";
6
+ import { homedir } from "os";
7
+ import { join, resolve } from "path";
8
+ var MAX_LOG_FILES = 20;
9
+ function projectHash(cwd) {
10
+ const absolute = resolve(cwd);
11
+ return createHash("sha256").update(absolute).digest("hex").slice(0, 12);
12
+ }
13
+ function getCacheDir(cwd) {
14
+ const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
15
+ return join(base, "lisa", projectHash(cwd));
16
+ }
17
+ function getLogsDir(cwd) {
18
+ return join(getCacheDir(cwd), "logs");
19
+ }
20
+ function getGuardrailsPath(cwd) {
21
+ return join(getCacheDir(cwd), "guardrails.md");
22
+ }
23
+ function getManifestPath(cwd, issueId) {
24
+ if (issueId) {
25
+ const safe = issueId.replace(/[^a-zA-Z0-9_-]/g, "_");
26
+ return join(getCacheDir(cwd), `manifest-${safe}.json`);
27
+ }
28
+ return join(getCacheDir(cwd), "manifest.json");
29
+ }
30
+ function getPrCachePath(cwd) {
31
+ return join(getCacheDir(cwd), "pr-cache.json");
32
+ }
33
+ function getPlanPath(cwd, issueId) {
34
+ if (issueId) {
35
+ const safe = issueId.replace(/[^a-zA-Z0-9_-]/g, "_");
36
+ return join(getCacheDir(cwd), `plan-${safe}.json`);
37
+ }
38
+ return join(getCacheDir(cwd), "plan.json");
39
+ }
40
+ function ensureCacheDir(cwd) {
41
+ const dir = getCacheDir(cwd);
42
+ if (!existsSync(dir)) {
43
+ mkdirSync(dir, { recursive: true });
44
+ }
45
+ }
46
+ function rotateLogFiles(cwd) {
47
+ const logsDir = getLogsDir(cwd);
48
+ if (!existsSync(logsDir)) return;
49
+ const files = readdirSync(logsDir).filter((f) => f.endsWith(".log")).map((f) => ({
50
+ name: f,
51
+ path: join(logsDir, f),
52
+ mtime: statSync(join(logsDir, f)).mtimeMs
53
+ })).sort((a, b) => a.mtime - b.mtime);
54
+ const excess = files.length - MAX_LOG_FILES;
55
+ if (excess <= 0) return;
56
+ for (const file of files.slice(0, excess)) {
57
+ try {
58
+ unlinkSync(file.path);
59
+ } catch {
60
+ }
61
+ }
62
+ }
63
+
64
+ export {
65
+ projectHash,
66
+ getCacheDir,
67
+ getLogsDir,
68
+ getGuardrailsPath,
69
+ getManifestPath,
70
+ getPrCachePath,
71
+ getPlanPath,
72
+ ensureCacheDir,
73
+ rotateLogFiles
74
+ };
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ appendEntry,
4
+ appendEntrySync,
5
+ appendRawEntry,
6
+ appendRawEntrySync,
7
+ buildGuardrailsSection,
8
+ extractContext,
9
+ extractErrorType,
10
+ guardrailsPath,
11
+ migrateGuardrails,
12
+ readGuardrails
13
+ } from "./chunk-NXGXGHS3.js";
14
+ import "./chunk-OYQ6TOAG.js";
15
+ export {
16
+ appendEntry,
17
+ appendEntrySync,
18
+ appendRawEntry,
19
+ appendRawEntrySync,
20
+ buildGuardrailsSection,
21
+ extractContext,
22
+ extractErrorType,
23
+ guardrailsPath,
24
+ migrateGuardrails,
25
+ readGuardrails
26
+ };