ralphy-spec 0.1.1 → 0.2.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.
- package/README.ja.md +74 -130
- package/README.ko.md +74 -130
- package/README.md +75 -133
- package/README.zh.md +74 -130
- package/bin/ralphy-spec.js +0 -0
- package/dist/cli/checkpoint.d.ts +3 -0
- package/dist/cli/checkpoint.d.ts.map +1 -0
- package/dist/cli/checkpoint.js +23 -0
- package/dist/cli/checkpoint.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +66 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/report.d.ts +3 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +53 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/run.d.ts +3 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +79 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/status.d.ts +3 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +45 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/tail.d.ts +3 -0
- package/dist/cli/tail.d.ts.map +1 -0
- package/dist/cli/tail.js +46 -0
- package/dist/cli/tail.js.map +1 -0
- package/dist/cli/update.d.ts +3 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +62 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/validate.d.ts +3 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +83 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/core/backends/claude-code.d.ts +17 -0
- package/dist/core/backends/claude-code.d.ts.map +1 -0
- package/dist/core/backends/claude-code.js +75 -0
- package/dist/core/backends/claude-code.js.map +1 -0
- package/dist/core/backends/cursor.d.ts +17 -0
- package/dist/core/backends/cursor.d.ts.map +1 -0
- package/dist/core/backends/cursor.js +75 -0
- package/dist/core/backends/cursor.js.map +1 -0
- package/dist/core/backends/noop.d.ts +10 -0
- package/dist/core/backends/noop.d.ts.map +1 -0
- package/dist/core/backends/noop.js +17 -0
- package/dist/core/backends/noop.js.map +1 -0
- package/dist/core/backends/opencode.d.ts +16 -0
- package/dist/core/backends/opencode.d.ts.map +1 -0
- package/dist/core/backends/opencode.js +73 -0
- package/dist/core/backends/opencode.js.map +1 -0
- package/dist/core/backends/types.d.ts +21 -0
- package/dist/core/backends/types.d.ts.map +1 -0
- package/dist/core/backends/types.js +3 -0
- package/dist/core/backends/types.js.map +1 -0
- package/dist/core/budgets/manager.d.ts +21 -0
- package/dist/core/budgets/manager.d.ts.map +1 -0
- package/dist/core/budgets/manager.js +48 -0
- package/dist/core/budgets/manager.js.map +1 -0
- package/dist/core/budgets/state.d.ts +25 -0
- package/dist/core/budgets/state.d.ts.map +1 -0
- package/dist/core/budgets/state.js +33 -0
- package/dist/core/budgets/state.js.map +1 -0
- package/dist/core/budgets/tiers.d.ts +32 -0
- package/dist/core/budgets/tiers.d.ts.map +1 -0
- package/dist/core/budgets/tiers.js +67 -0
- package/dist/core/budgets/tiers.js.map +1 -0
- package/dist/core/engine/context-pack.d.ts +12 -0
- package/dist/core/engine/context-pack.d.ts.map +1 -0
- package/dist/core/engine/context-pack.js +45 -0
- package/dist/core/engine/context-pack.js.map +1 -0
- package/dist/core/engine/loop.d.ts +28 -0
- package/dist/core/engine/loop.d.ts.map +1 -0
- package/dist/core/engine/loop.js +366 -0
- package/dist/core/engine/loop.js.map +1 -0
- package/dist/core/engine/phases.d.ts +2 -0
- package/dist/core/engine/phases.d.ts.map +1 -0
- package/dist/core/engine/phases.js +3 -0
- package/dist/core/engine/phases.js.map +1 -0
- package/dist/core/engine/repair.d.ts +6 -0
- package/dist/core/engine/repair.d.ts.map +1 -0
- package/dist/core/engine/repair.js +23 -0
- package/dist/core/engine/repair.js.map +1 -0
- package/dist/core/folders.d.ts +26 -0
- package/dist/core/folders.d.ts.map +1 -0
- package/dist/core/folders.js +58 -0
- package/dist/core/folders.js.map +1 -0
- package/dist/core/memory/ledger.d.ts +13 -0
- package/dist/core/memory/ledger.d.ts.map +1 -0
- package/dist/core/memory/ledger.js +24 -0
- package/dist/core/memory/ledger.js.map +1 -0
- package/dist/core/memory/persistence.d.ts +45 -0
- package/dist/core/memory/persistence.d.ts.map +1 -0
- package/dist/core/memory/persistence.js +162 -0
- package/dist/core/memory/persistence.js.map +1 -0
- package/dist/core/reporting/spend.d.ts +40 -0
- package/dist/core/reporting/spend.d.ts.map +1 -0
- package/dist/core/reporting/spend.js +157 -0
- package/dist/core/reporting/spend.js.map +1 -0
- package/dist/core/spec/dag.d.ts +7 -0
- package/dist/core/spec/dag.d.ts.map +1 -0
- package/dist/core/spec/dag.js +65 -0
- package/dist/core/spec/dag.js.map +1 -0
- package/dist/core/spec/file-contract.d.ts +13 -0
- package/dist/core/spec/file-contract.d.ts.map +1 -0
- package/dist/core/spec/file-contract.js +29 -0
- package/dist/core/spec/file-contract.js.map +1 -0
- package/dist/core/spec/loader.d.ts +8 -0
- package/dist/core/spec/loader.d.ts.map +1 -0
- package/dist/core/spec/loader.js +51 -0
- package/dist/core/spec/loader.js.map +1 -0
- package/dist/core/spec/schemas.d.ts +278 -0
- package/dist/core/spec/schemas.d.ts.map +1 -0
- package/dist/core/spec/schemas.js +207 -0
- package/dist/core/spec/schemas.js.map +1 -0
- package/dist/core/spec/types.d.ts +71 -0
- package/dist/core/spec/types.d.ts.map +1 -0
- package/dist/core/spec/types.js +3 -0
- package/dist/core/spec/types.js.map +1 -0
- package/dist/core/validators/parsers/eslint.d.ts +3 -0
- package/dist/core/validators/parsers/eslint.d.ts.map +1 -0
- package/dist/core/validators/parsers/eslint.js +35 -0
- package/dist/core/validators/parsers/eslint.js.map +1 -0
- package/dist/core/validators/parsers/jest.d.ts +3 -0
- package/dist/core/validators/parsers/jest.d.ts.map +1 -0
- package/dist/core/validators/parsers/jest.js +16 -0
- package/dist/core/validators/parsers/jest.js.map +1 -0
- package/dist/core/validators/parsers/tsc.d.ts +3 -0
- package/dist/core/validators/parsers/tsc.d.ts.map +1 -0
- package/dist/core/validators/parsers/tsc.js +32 -0
- package/dist/core/validators/parsers/tsc.js.map +1 -0
- package/dist/core/validators/runner.d.ts +8 -0
- package/dist/core/validators/runner.d.ts.map +1 -0
- package/dist/core/validators/runner.js +85 -0
- package/dist/core/validators/runner.js.map +1 -0
- package/dist/core/validators/signatures.d.ts +3 -0
- package/dist/core/validators/signatures.d.ts.map +1 -0
- package/dist/core/validators/signatures.js +10 -0
- package/dist/core/validators/signatures.js.map +1 -0
- package/dist/core/validators/types.d.ts +27 -0
- package/dist/core/validators/types.d.ts.map +1 -0
- package/dist/core/validators/types.js +3 -0
- package/dist/core/validators/types.js.map +1 -0
- package/dist/core/workspace/contract-enforcer.d.ts +54 -0
- package/dist/core/workspace/contract-enforcer.d.ts.map +1 -0
- package/dist/core/workspace/contract-enforcer.js +128 -0
- package/dist/core/workspace/contract-enforcer.js.map +1 -0
- package/dist/core/workspace/manager.d.ts +28 -0
- package/dist/core/workspace/manager.d.ts.map +1 -0
- package/dist/core/workspace/manager.js +3 -0
- package/dist/core/workspace/manager.js.map +1 -0
- package/dist/core/workspace/merge.d.ts +38 -0
- package/dist/core/workspace/merge.d.ts.map +1 -0
- package/dist/core/workspace/merge.js +92 -0
- package/dist/core/workspace/merge.js.map +1 -0
- package/dist/core/workspace/patch-mode.d.ts +22 -0
- package/dist/core/workspace/patch-mode.d.ts.map +1 -0
- package/dist/core/workspace/patch-mode.js +91 -0
- package/dist/core/workspace/patch-mode.js.map +1 -0
- package/dist/core/workspace/worktree-mode.d.ts +28 -0
- package/dist/core/workspace/worktree-mode.d.ts.map +1 -0
- package/dist/core/workspace/worktree-mode.js +156 -0
- package/dist/core/workspace/worktree-mode.js.map +1 -0
- package/dist/index.js +14 -4
- package/dist/index.js.map +1 -1
- package/dist/templates/shared/openspec-tasks-template.md +23 -3
- package/dist/templates/shared/project-template.yml +232 -0
- package/dist/utils/installer.d.ts.map +1 -1
- package/dist/utils/installer.js +31 -1
- package/dist/utils/installer.js.map +1 -1
- package/dist/utils/validator.d.ts.map +1 -1
- package/dist/utils/validator.js +10 -0
- package/dist/utils/validator.js.map +1 -1
- package/package.json +11 -4
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PatchModeWorkspace = void 0;
|
|
7
|
+
exports.getPatchWorkspaceRoot = getPatchWorkspaceRoot;
|
|
8
|
+
const execa_1 = require("execa");
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const file_contract_1 = require("../spec/file-contract");
|
|
11
|
+
class PatchModeWorkspace {
|
|
12
|
+
repoRoot;
|
|
13
|
+
mode = "patch";
|
|
14
|
+
stateByTask = new Map();
|
|
15
|
+
constructor(repoRoot) {
|
|
16
|
+
this.repoRoot = repoRoot;
|
|
17
|
+
}
|
|
18
|
+
async prepare(taskId) {
|
|
19
|
+
const snapshotCommit = await this.git(["rev-parse", "HEAD"]);
|
|
20
|
+
this.stateByTask.set(taskId, { snapshotCommit });
|
|
21
|
+
return { taskId, workingDir: this.repoRoot };
|
|
22
|
+
}
|
|
23
|
+
getWorkingDir(_taskId) {
|
|
24
|
+
return this.repoRoot;
|
|
25
|
+
}
|
|
26
|
+
async getChangedFiles(_taskId) {
|
|
27
|
+
// name-status gives: A/M/D/R... <path> ...
|
|
28
|
+
const out = await this.git(["diff", "--name-status"]);
|
|
29
|
+
const lines = out
|
|
30
|
+
.split("\n")
|
|
31
|
+
.map((l) => l.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
const changed = [];
|
|
34
|
+
for (const line of lines) {
|
|
35
|
+
const parts = line.split(/\s+/);
|
|
36
|
+
const status = parts[0] ?? "";
|
|
37
|
+
const file = parts[1] ?? "";
|
|
38
|
+
if (!file)
|
|
39
|
+
continue;
|
|
40
|
+
changed.push({ file, isNew: status.startsWith("A") });
|
|
41
|
+
}
|
|
42
|
+
return changed;
|
|
43
|
+
}
|
|
44
|
+
async enforceContract(taskId, contract) {
|
|
45
|
+
const changedFiles = await this.getChangedFiles(taskId);
|
|
46
|
+
const violations = (0, file_contract_1.evaluateFileContract)({ changedFiles, contract });
|
|
47
|
+
if (violations.length) {
|
|
48
|
+
await this.revert(taskId);
|
|
49
|
+
}
|
|
50
|
+
return violations;
|
|
51
|
+
}
|
|
52
|
+
async checkpoint(taskId, message) {
|
|
53
|
+
// Best effort: commit all changes. If nothing to commit, return HEAD.
|
|
54
|
+
await this.git(["add", "-A"]);
|
|
55
|
+
const commitMsg = `[ralphy-spec] ${taskId}: ${message}`;
|
|
56
|
+
try {
|
|
57
|
+
await this.git(["commit", "-m", commitMsg]);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// likely "nothing to commit"
|
|
61
|
+
}
|
|
62
|
+
const ref = await this.git(["rev-parse", "HEAD"]);
|
|
63
|
+
return { ref };
|
|
64
|
+
}
|
|
65
|
+
async merge(_taskId) {
|
|
66
|
+
// Patch mode executes on main; merge is no-op.
|
|
67
|
+
}
|
|
68
|
+
async revert(taskId) {
|
|
69
|
+
const state = this.stateByTask.get(taskId);
|
|
70
|
+
if (!state)
|
|
71
|
+
return;
|
|
72
|
+
// Hard revert to snapshot; also remove untracked files.
|
|
73
|
+
await this.git(["reset", "--hard", state.snapshotCommit]);
|
|
74
|
+
await this.git(["clean", "-fd"]);
|
|
75
|
+
}
|
|
76
|
+
async cleanup(_taskId) {
|
|
77
|
+
// No-op for patch mode.
|
|
78
|
+
}
|
|
79
|
+
async git(args) {
|
|
80
|
+
const res = await (0, execa_1.execa)("git", args, {
|
|
81
|
+
cwd: this.repoRoot,
|
|
82
|
+
stdio: "pipe",
|
|
83
|
+
});
|
|
84
|
+
return res.stdout.trim();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.PatchModeWorkspace = PatchModeWorkspace;
|
|
88
|
+
function getPatchWorkspaceRoot(repoRoot) {
|
|
89
|
+
return node_path_1.default.resolve(repoRoot);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=patch-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-mode.js","sourceRoot":"","sources":["../../../src/core/workspace/patch-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FileContract } from "../spec/types";
|
|
2
|
+
import type { CheckpointRef, ContractViolation, WorkspaceContext, WorkspaceManager } from "./manager";
|
|
3
|
+
/**
|
|
4
|
+
* WorktreeModeWorkspace uses git worktrees for task isolation.
|
|
5
|
+
*
|
|
6
|
+
* Each task runs in its own worktree branch, providing complete isolation
|
|
7
|
+
* from the main working directory. Changes are merged back on success.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WorktreeModeWorkspace implements WorkspaceManager {
|
|
10
|
+
private readonly repoRoot;
|
|
11
|
+
mode: "worktree";
|
|
12
|
+
private readonly stateByTask;
|
|
13
|
+
private readonly worktreeBase;
|
|
14
|
+
constructor(repoRoot: string);
|
|
15
|
+
prepare(taskId: string): Promise<WorkspaceContext>;
|
|
16
|
+
getWorkingDir(taskId: string): string;
|
|
17
|
+
getChangedFiles(taskId: string): Promise<Array<{
|
|
18
|
+
file: string;
|
|
19
|
+
isNew: boolean;
|
|
20
|
+
}>>;
|
|
21
|
+
enforceContract(taskId: string, contract: FileContract): Promise<ContractViolation[]>;
|
|
22
|
+
checkpoint(taskId: string, message: string): Promise<CheckpointRef>;
|
|
23
|
+
merge(taskId: string): Promise<void>;
|
|
24
|
+
revert(taskId: string): Promise<void>;
|
|
25
|
+
cleanup(taskId: string): Promise<void>;
|
|
26
|
+
private git;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=worktree-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-mode.d.ts","sourceRoot":"","sources":["../../../src/core/workspace/worktree-mode.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,WAAW,CAAC;AAQnB;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,gBAAgB;IAKhD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,IAAI,EAAE,UAAU,CAAc;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAET,QAAQ,EAAE,MAAM;IAIvC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCxD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAK/B,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IA2BjF,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAYrF,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAoBnE,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBpC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAiB9B,GAAG;CAalB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WorktreeModeWorkspace = void 0;
|
|
7
|
+
const execa_1 = require("execa");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
10
|
+
const file_contract_1 = require("../spec/file-contract");
|
|
11
|
+
/**
|
|
12
|
+
* WorktreeModeWorkspace uses git worktrees for task isolation.
|
|
13
|
+
*
|
|
14
|
+
* Each task runs in its own worktree branch, providing complete isolation
|
|
15
|
+
* from the main working directory. Changes are merged back on success.
|
|
16
|
+
*/
|
|
17
|
+
class WorktreeModeWorkspace {
|
|
18
|
+
repoRoot;
|
|
19
|
+
mode = "worktree";
|
|
20
|
+
stateByTask = new Map();
|
|
21
|
+
worktreeBase;
|
|
22
|
+
constructor(repoRoot) {
|
|
23
|
+
this.repoRoot = repoRoot;
|
|
24
|
+
this.worktreeBase = node_path_1.default.join(repoRoot, ".ralphy", "worktrees");
|
|
25
|
+
}
|
|
26
|
+
async prepare(taskId) {
|
|
27
|
+
// Ensure worktree base directory exists
|
|
28
|
+
await promises_1.default.mkdir(this.worktreeBase, { recursive: true });
|
|
29
|
+
// Get current HEAD as base
|
|
30
|
+
const baseCommit = await this.git(["rev-parse", "HEAD"], this.repoRoot);
|
|
31
|
+
// Create a unique branch name for this task
|
|
32
|
+
const branchName = `ralphy/${taskId}/${Date.now()}`;
|
|
33
|
+
const worktreePath = node_path_1.default.join(this.worktreeBase, taskId.replace(/[^a-zA-Z0-9-_]/g, "_"));
|
|
34
|
+
// Clean up existing worktree if present
|
|
35
|
+
try {
|
|
36
|
+
await promises_1.default.rm(worktreePath, { recursive: true, force: true });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Ignore if doesn't exist
|
|
40
|
+
}
|
|
41
|
+
// Remove stale worktree entry if any
|
|
42
|
+
try {
|
|
43
|
+
await this.git(["worktree", "remove", "--force", worktreePath], this.repoRoot);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Ignore if doesn't exist
|
|
47
|
+
}
|
|
48
|
+
// Create new worktree with a new branch
|
|
49
|
+
await this.git(["worktree", "add", "-b", branchName, worktreePath, baseCommit], this.repoRoot);
|
|
50
|
+
this.stateByTask.set(taskId, { worktreePath, branchName, baseCommit });
|
|
51
|
+
return { taskId, workingDir: worktreePath };
|
|
52
|
+
}
|
|
53
|
+
getWorkingDir(taskId) {
|
|
54
|
+
const state = this.stateByTask.get(taskId);
|
|
55
|
+
return state?.worktreePath ?? this.repoRoot;
|
|
56
|
+
}
|
|
57
|
+
async getChangedFiles(taskId) {
|
|
58
|
+
const state = this.stateByTask.get(taskId);
|
|
59
|
+
if (!state)
|
|
60
|
+
return [];
|
|
61
|
+
// Get changes compared to base commit
|
|
62
|
+
const out = await this.git(["diff", "--name-status", state.baseCommit], state.worktreePath);
|
|
63
|
+
const lines = out
|
|
64
|
+
.split("\n")
|
|
65
|
+
.map((l) => l.trim())
|
|
66
|
+
.filter(Boolean);
|
|
67
|
+
const changed = [];
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
const parts = line.split(/\s+/);
|
|
70
|
+
const status = parts[0] ?? "";
|
|
71
|
+
const file = parts[1] ?? "";
|
|
72
|
+
if (!file)
|
|
73
|
+
continue;
|
|
74
|
+
changed.push({ file, isNew: status.startsWith("A") });
|
|
75
|
+
}
|
|
76
|
+
return changed;
|
|
77
|
+
}
|
|
78
|
+
async enforceContract(taskId, contract) {
|
|
79
|
+
const changedFiles = await this.getChangedFiles(taskId);
|
|
80
|
+
const violations = (0, file_contract_1.evaluateFileContract)({ changedFiles, contract });
|
|
81
|
+
if (violations.length) {
|
|
82
|
+
// Revert the worktree to base state
|
|
83
|
+
await this.revert(taskId);
|
|
84
|
+
}
|
|
85
|
+
return violations;
|
|
86
|
+
}
|
|
87
|
+
async checkpoint(taskId, message) {
|
|
88
|
+
const state = this.stateByTask.get(taskId);
|
|
89
|
+
if (!state) {
|
|
90
|
+
throw new Error(`No worktree state for task ${taskId}`);
|
|
91
|
+
}
|
|
92
|
+
// Stage and commit all changes in worktree
|
|
93
|
+
await this.git(["add", "-A"], state.worktreePath);
|
|
94
|
+
const commitMsg = `[ralphy-spec] ${taskId}: ${message}`;
|
|
95
|
+
try {
|
|
96
|
+
await this.git(["commit", "-m", commitMsg], state.worktreePath);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Likely nothing to commit
|
|
100
|
+
}
|
|
101
|
+
const ref = await this.git(["rev-parse", "HEAD"], state.worktreePath);
|
|
102
|
+
return { ref };
|
|
103
|
+
}
|
|
104
|
+
async merge(taskId) {
|
|
105
|
+
const state = this.stateByTask.get(taskId);
|
|
106
|
+
if (!state)
|
|
107
|
+
return;
|
|
108
|
+
// Get the current branch in main repo
|
|
109
|
+
const currentBranch = await this.git(["rev-parse", "--abbrev-ref", "HEAD"], this.repoRoot);
|
|
110
|
+
// Merge the task branch back using --squash for clean history
|
|
111
|
+
try {
|
|
112
|
+
await this.git(["merge", "--squash", state.branchName], this.repoRoot);
|
|
113
|
+
await this.git(["commit", "-m", `[ralphy-spec] Merge task ${taskId}`], this.repoRoot);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// If merge fails, user may need to resolve manually
|
|
117
|
+
throw new Error(`Failed to merge task ${taskId}: ${err?.message ?? String(err)}. Manual resolution may be required.`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async revert(taskId) {
|
|
121
|
+
const state = this.stateByTask.get(taskId);
|
|
122
|
+
if (!state)
|
|
123
|
+
return;
|
|
124
|
+
// Hard reset worktree to base commit
|
|
125
|
+
await this.git(["reset", "--hard", state.baseCommit], state.worktreePath);
|
|
126
|
+
await this.git(["clean", "-fd"], state.worktreePath);
|
|
127
|
+
}
|
|
128
|
+
async cleanup(taskId) {
|
|
129
|
+
const state = this.stateByTask.get(taskId);
|
|
130
|
+
if (!state)
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
// Remove the worktree
|
|
134
|
+
await this.git(["worktree", "remove", "--force", state.worktreePath], this.repoRoot);
|
|
135
|
+
// Delete the branch
|
|
136
|
+
await this.git(["branch", "-D", state.branchName], this.repoRoot);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Best effort cleanup
|
|
140
|
+
}
|
|
141
|
+
this.stateByTask.delete(taskId);
|
|
142
|
+
}
|
|
143
|
+
async git(args, cwd) {
|
|
144
|
+
const res = await (0, execa_1.execa)("git", args, {
|
|
145
|
+
cwd,
|
|
146
|
+
stdio: "pipe",
|
|
147
|
+
reject: false,
|
|
148
|
+
});
|
|
149
|
+
if (res.exitCode !== 0 && res.stderr) {
|
|
150
|
+
throw new Error(`git ${args.join(" ")} failed: ${res.stderr}`);
|
|
151
|
+
}
|
|
152
|
+
return res.stdout.trim();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.WorktreeModeWorkspace = WorktreeModeWorkspace;
|
|
156
|
+
//# sourceMappingURL=worktree-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-mode.js","sourceRoot":"","sources":["../../../src/core/workspace/worktree-mode.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const commander_1 = require("commander");
|
|
4
|
-
const init_1 = require("./
|
|
5
|
-
const validate_1 = require("./
|
|
6
|
-
const update_1 = require("./
|
|
4
|
+
const init_1 = require("./cli/init");
|
|
5
|
+
const validate_1 = require("./cli/validate");
|
|
6
|
+
const update_1 = require("./cli/update");
|
|
7
|
+
const run_1 = require("./cli/run");
|
|
8
|
+
const status_1 = require("./cli/status");
|
|
9
|
+
const report_1 = require("./cli/report");
|
|
10
|
+
const tail_1 = require("./cli/tail");
|
|
11
|
+
const checkpoint_1 = require("./cli/checkpoint");
|
|
7
12
|
function buildProgram() {
|
|
8
13
|
const program = new commander_1.Command();
|
|
9
14
|
program
|
|
10
15
|
.name("ralphy-spec")
|
|
11
16
|
.description("One-command setup for Ralph loop + OpenSpec workflows across Cursor, OpenCode, and Claude Code.")
|
|
12
|
-
.version("0.1.
|
|
17
|
+
.version("0.1.2");
|
|
13
18
|
(0, init_1.registerInitCommand)(program);
|
|
14
19
|
(0, validate_1.registerValidateCommand)(program);
|
|
15
20
|
(0, update_1.registerUpdateCommand)(program);
|
|
21
|
+
(0, run_1.registerRunCommand)(program);
|
|
22
|
+
(0, status_1.registerStatusCommand)(program);
|
|
23
|
+
(0, report_1.registerReportCommand)(program);
|
|
24
|
+
(0, tail_1.registerTailCommand)(program);
|
|
25
|
+
(0, checkpoint_1.registerCheckpointCommand)(program);
|
|
16
26
|
return program;
|
|
17
27
|
}
|
|
18
28
|
async function main() {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yCAAoC;AACpC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yCAAoC;AACpC,qCAAiD;AACjD,6CAAyD;AACzD,yCAAqD;AACrD,mCAA+C;AAC/C,yCAAqD;AACrD,yCAAqD;AACrD,qCAAiD;AACjD,iDAA6D;AAE7D,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,aAAa,CAAC;SACnB,WAAW,CACV,iGAAiG,CAClG;SACA,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;IAC5B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAC/B,IAAA,0BAAmB,EAAC,OAAO,CAAC,CAAC;IAC7B,IAAA,sCAAyB,EAAC,OAAO,CAAC,CAAC;IAEnC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAC/B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,mEAAmE;AACnE,IAAI,EAAE,CAAC"}
|
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
Use this structure for `openspec/changes/<change-name>/tasks.md`.
|
|
4
4
|
|
|
5
5
|
## 1. Planning / Scaffolding
|
|
6
|
-
- [ ] 1.1 Confirm scope and
|
|
6
|
+
- [ ] 1.1 Confirm scope, non-goals, and impacted modules
|
|
7
|
+
- Acceptance criteria:
|
|
8
|
+
- GIVEN the current `openspec/specs/` baseline
|
|
9
|
+
- WHEN this change is implemented
|
|
10
|
+
- THEN only the intended domains are affected
|
|
7
11
|
- Test plan: N/A
|
|
8
12
|
|
|
9
13
|
## 2. Implementation
|
|
10
|
-
- [ ] 2.1 Implement feature behavior
|
|
14
|
+
- [ ] 2.1 Implement feature behavior (spec-driven)
|
|
11
15
|
- Acceptance criteria:
|
|
12
16
|
- GIVEN ...
|
|
13
17
|
- WHEN ...
|
|
@@ -16,13 +20,29 @@ Use this structure for `openspec/changes/<change-name>/tasks.md`.
|
|
|
16
20
|
- Run: `npm test`
|
|
17
21
|
- Assert: ...
|
|
18
22
|
|
|
23
|
+
## 3. Validators / Budgets (v2+)
|
|
24
|
+
- [ ] 3.1 Define or update validators used by this change
|
|
25
|
+
- Notes:
|
|
26
|
+
- Validators are the ground truth (deterministic pass/fail)
|
|
27
|
+
- Prefer: `npm run typecheck`, `npm test`, `npm run lint`
|
|
28
|
+
- Test plan:
|
|
29
|
+
- Run the validator commands locally/CI
|
|
30
|
+
|
|
31
|
+
- [ ] 3.2 If the change introduces budgeted execution (v2.1+), document expected behavior
|
|
32
|
+
- Notes:
|
|
33
|
+
- Optimal → Warning → Hard tier expectations
|
|
34
|
+
- WARNING tier should shrink context + enforce repair-only constraints
|
|
35
|
+
- HARD tier should stop safely (no silent retries)
|
|
36
|
+
- Test plan:
|
|
37
|
+
- Run a small demo task that crosses WARNING tier and confirm behaviors
|
|
38
|
+
|
|
19
39
|
## 3. Validation
|
|
20
40
|
- [ ] 3.1 Add/adjust tests to cover all scenarios
|
|
21
41
|
- Test plan:
|
|
22
42
|
- Run: `npm test`
|
|
23
43
|
|
|
24
44
|
## 4. Documentation / Archive
|
|
25
|
-
- [ ] 4.1 Update
|
|
45
|
+
- [ ] 4.1 Update OpenSpec docs/spec deltas (if needed) and archive change
|
|
26
46
|
- Test plan:
|
|
27
47
|
- Run: `npm test`
|
|
28
48
|
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# ralphy-spec Project Configuration
|
|
2
|
+
# Generated by: ralphy-spec init
|
|
3
|
+
# Version: 2.1 (Budget Intelligence + Sprint Semantics)
|
|
4
|
+
|
|
5
|
+
version: "1.1"
|
|
6
|
+
|
|
7
|
+
project:
|
|
8
|
+
name: "my-project"
|
|
9
|
+
repoRoot: "."
|
|
10
|
+
language: "ts"
|
|
11
|
+
packageManager: "npm" # user-defined: npm | pnpm | yarn | bun
|
|
12
|
+
|
|
13
|
+
defaults:
|
|
14
|
+
backend: "cursor"
|
|
15
|
+
workspaceMode: "patch" # "worktree" | "patch"
|
|
16
|
+
checkpointMode: "commit" # "commit" | "patch"
|
|
17
|
+
validators:
|
|
18
|
+
- typecheck
|
|
19
|
+
- test
|
|
20
|
+
- lint
|
|
21
|
+
|
|
22
|
+
# Artifacts (IDE-friendly human interface)
|
|
23
|
+
# NOTE: These are defaults; users can override or disable.
|
|
24
|
+
artifacts:
|
|
25
|
+
enabled: true
|
|
26
|
+
rootDir: "ralphy-spec" # default; can be overridden via CLI: --artifact-dir
|
|
27
|
+
statusIcons: "emoji" # "emoji" | "ascii" | "none"
|
|
28
|
+
|
|
29
|
+
# Run-level budgets (hard limits for entire run)
|
|
30
|
+
budgets:
|
|
31
|
+
run:
|
|
32
|
+
money_usd: 20 # Max USD per run
|
|
33
|
+
tokens: 2000000 # Max tokens per run
|
|
34
|
+
wall_time_minutes: 90 # Max wall clock time
|
|
35
|
+
max_iterations_total: 80 # Max total iterations across all tasks
|
|
36
|
+
|
|
37
|
+
limits:
|
|
38
|
+
max_parallel_tasks: 1 # Concurrent tasks (v1: always 1)
|
|
39
|
+
max_parallel_validators: 2 # Concurrent validators
|
|
40
|
+
command_timeout_seconds: 900
|
|
41
|
+
|
|
42
|
+
# Sprint size defaults (applied when task has sprint.size but no explicit budget)
|
|
43
|
+
# Users can override per-task
|
|
44
|
+
sprint_defaults:
|
|
45
|
+
XS:
|
|
46
|
+
optimal: { usd: 0.20, tokens: 15000, time_minutes: 3 }
|
|
47
|
+
warning: { usd: 0.35, tokens: 25000, time_minutes: 5 }
|
|
48
|
+
hard: { usd: 0.50, tokens: 40000, time_minutes: 8, max_iterations: 3 }
|
|
49
|
+
S:
|
|
50
|
+
optimal: { usd: 0.50, tokens: 40000, time_minutes: 5 }
|
|
51
|
+
warning: { usd: 0.80, tokens: 65000, time_minutes: 8 }
|
|
52
|
+
hard: { usd: 1.20, tokens: 100000, time_minutes: 12, max_iterations: 5 }
|
|
53
|
+
M:
|
|
54
|
+
optimal: { usd: 1.20, tokens: 80000, time_minutes: 10 }
|
|
55
|
+
warning: { usd: 2.00, tokens: 150000, time_minutes: 15 }
|
|
56
|
+
hard: { usd: 3.00, tokens: 250000, time_minutes: 20, max_iterations: 8 }
|
|
57
|
+
L:
|
|
58
|
+
optimal: { usd: 2.50, tokens: 150000, time_minutes: 20 }
|
|
59
|
+
warning: { usd: 4.00, tokens: 280000, time_minutes: 35 }
|
|
60
|
+
hard: { usd: 6.00, tokens: 450000, time_minutes: 50, max_iterations: 12 }
|
|
61
|
+
XL:
|
|
62
|
+
optimal: { usd: 5.00, tokens: 300000, time_minutes: 40 }
|
|
63
|
+
warning: { usd: 8.00, tokens: 550000, time_minutes: 70 }
|
|
64
|
+
hard: { usd: 12.00, tokens: 900000, time_minutes: 100, max_iterations: 20 }
|
|
65
|
+
|
|
66
|
+
backends:
|
|
67
|
+
cursor:
|
|
68
|
+
command: "cursor"
|
|
69
|
+
modelTiers:
|
|
70
|
+
default: { hint: "balanced" }
|
|
71
|
+
cheap: { hint: "cheap" }
|
|
72
|
+
strong: { hint: "strong" }
|
|
73
|
+
opencode:
|
|
74
|
+
command: "opencode"
|
|
75
|
+
modelTiers:
|
|
76
|
+
default: {}
|
|
77
|
+
cheap: {}
|
|
78
|
+
claude_code:
|
|
79
|
+
command: "claude"
|
|
80
|
+
modelTiers:
|
|
81
|
+
default: {}
|
|
82
|
+
|
|
83
|
+
validators:
|
|
84
|
+
- id: "typecheck"
|
|
85
|
+
# Avoid hard-coding package manager. Choose commands that match your repo.
|
|
86
|
+
run: "npm run typecheck"
|
|
87
|
+
timeout_seconds: 600
|
|
88
|
+
parser: "tsc"
|
|
89
|
+
- id: "test"
|
|
90
|
+
run: "npm test"
|
|
91
|
+
timeout_seconds: 900
|
|
92
|
+
parser: "jest"
|
|
93
|
+
- id: "lint"
|
|
94
|
+
run: "npm run lint"
|
|
95
|
+
timeout_seconds: 600
|
|
96
|
+
parser: "eslint"
|
|
97
|
+
|
|
98
|
+
# Tasks - define your implementation tasks here
|
|
99
|
+
tasks: []
|
|
100
|
+
|
|
101
|
+
# ============================================================
|
|
102
|
+
# TASK EXAMPLES (uncomment and modify as needed)
|
|
103
|
+
# ============================================================
|
|
104
|
+
|
|
105
|
+
# Example 1: Simple fix (XS sprint, uses defaults)
|
|
106
|
+
# - id: "fix-typo-001"
|
|
107
|
+
# title: "Fix typo in error message"
|
|
108
|
+
# goal: "Correct spelling in validation error"
|
|
109
|
+
#
|
|
110
|
+
# sprint:
|
|
111
|
+
# size: XS # Uses XS defaults: $0.20 optimal, 3 max iter
|
|
112
|
+
# intent: "fix" # No refactoring allowed
|
|
113
|
+
#
|
|
114
|
+
# files_contract:
|
|
115
|
+
# allowed: ["src/utils/validation.ts"]
|
|
116
|
+
# forbidden: []
|
|
117
|
+
# allow_new_files: false
|
|
118
|
+
#
|
|
119
|
+
# acceptance:
|
|
120
|
+
# - id: "acc-1"
|
|
121
|
+
# text: "Error message spelled correctly"
|
|
122
|
+
# type: "behavior"
|
|
123
|
+
|
|
124
|
+
# Example 2: Feature (M sprint with custom budget)
|
|
125
|
+
# - id: "auth-001"
|
|
126
|
+
# title: "JWT middleware"
|
|
127
|
+
# goal: "Add JWT auth middleware for API routes"
|
|
128
|
+
#
|
|
129
|
+
# sprint:
|
|
130
|
+
# size: M
|
|
131
|
+
# intent: "feature" # Limited refactoring allowed
|
|
132
|
+
#
|
|
133
|
+
# budget: # Optional: override sprint defaults
|
|
134
|
+
# optimal:
|
|
135
|
+
# usd: 1.2
|
|
136
|
+
# tokens: 80000
|
|
137
|
+
# time_minutes: 10
|
|
138
|
+
# warning:
|
|
139
|
+
# usd: 2.0
|
|
140
|
+
# tokens: 150000
|
|
141
|
+
# time_minutes: 15
|
|
142
|
+
# hard:
|
|
143
|
+
# usd: 3.0
|
|
144
|
+
# tokens: 250000
|
|
145
|
+
# time_minutes: 20
|
|
146
|
+
# max_iterations: 8
|
|
147
|
+
#
|
|
148
|
+
# files_contract:
|
|
149
|
+
# allowed:
|
|
150
|
+
# - "src/middleware/**"
|
|
151
|
+
# - "src/api/**"
|
|
152
|
+
# forbidden:
|
|
153
|
+
# - "src/db/**"
|
|
154
|
+
# allow_new_files: true
|
|
155
|
+
#
|
|
156
|
+
# context:
|
|
157
|
+
# docs: ["README.md"]
|
|
158
|
+
# files: ["src/api/index.ts"]
|
|
159
|
+
#
|
|
160
|
+
# acceptance:
|
|
161
|
+
# - id: "acc-1"
|
|
162
|
+
# text: "Requests without token return 401"
|
|
163
|
+
# type: "behavior"
|
|
164
|
+
# - id: "acc-2"
|
|
165
|
+
# text: "Valid tokens allow access"
|
|
166
|
+
# type: "behavior"
|
|
167
|
+
# - id: "acc-3"
|
|
168
|
+
# text: "Unit tests added"
|
|
169
|
+
# type: "evidence"
|
|
170
|
+
# evidence:
|
|
171
|
+
# must_include_files: ["src/**/__tests__/**"]
|
|
172
|
+
#
|
|
173
|
+
# validators: ["typecheck", "test", "lint"]
|
|
174
|
+
# done_policy:
|
|
175
|
+
# require_all_validators_pass: true
|
|
176
|
+
# require_acceptance_evidence: true
|
|
177
|
+
|
|
178
|
+
# Example 3: Large refactor (L sprint)
|
|
179
|
+
# - id: "refactor-db-001"
|
|
180
|
+
# title: "Migrate to Prisma"
|
|
181
|
+
# goal: "Replace raw SQL with Prisma ORM"
|
|
182
|
+
# deps: ["auth-001"] # Depends on auth task
|
|
183
|
+
#
|
|
184
|
+
# sprint:
|
|
185
|
+
# size: L
|
|
186
|
+
# intent: "refactor" # Full refactoring allowed
|
|
187
|
+
#
|
|
188
|
+
# files_contract:
|
|
189
|
+
# allowed:
|
|
190
|
+
# - "src/db/**"
|
|
191
|
+
# - "prisma/**"
|
|
192
|
+
# forbidden:
|
|
193
|
+
# - "src/api/**" # Don't touch API layer
|
|
194
|
+
# allow_new_files: true
|
|
195
|
+
#
|
|
196
|
+
# acceptance:
|
|
197
|
+
# - id: "acc-1"
|
|
198
|
+
# text: "All database queries use Prisma"
|
|
199
|
+
# type: "behavior"
|
|
200
|
+
# - id: "acc-2"
|
|
201
|
+
# text: "Existing tests pass"
|
|
202
|
+
# type: "evidence"
|
|
203
|
+
|
|
204
|
+
# ============================================================
|
|
205
|
+
# BUDGET TIERS EXPLAINED
|
|
206
|
+
# ============================================================
|
|
207
|
+
#
|
|
208
|
+
# OPTIMAL: Expected cost for correct completion
|
|
209
|
+
# - Agent operates normally with full context
|
|
210
|
+
# - All features enabled (self-review, planning)
|
|
211
|
+
#
|
|
212
|
+
# WARNING: Still acceptable but attention needed
|
|
213
|
+
# - Context shrink: fewer files, only failing tests
|
|
214
|
+
# - Repair-only mode: "fix only, no refactor"
|
|
215
|
+
# - Optional calls disabled
|
|
216
|
+
# - STATUS.md shows pressure signals
|
|
217
|
+
#
|
|
218
|
+
# HARD: Must stop immediately
|
|
219
|
+
# - Task marked as BLOCKED
|
|
220
|
+
# - Workspace preserved for debugging
|
|
221
|
+
# - Failure summary written
|
|
222
|
+
# - No silent retries
|
|
223
|
+
#
|
|
224
|
+
# ============================================================
|
|
225
|
+
# SPRINT SIZES GUIDE
|
|
226
|
+
# ============================================================
|
|
227
|
+
#
|
|
228
|
+
# XS: Single file fix, typo, simple config change
|
|
229
|
+
# S: Small function, add a test, minor refactor
|
|
230
|
+
# M: Feature slice, new endpoint, component
|
|
231
|
+
# L: Multi-file feature, significant change
|
|
232
|
+
# XL: Infrastructure, major refactor, migration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/utils/installer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/utils/installer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAiBvC,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD9E;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GACvB,OAAO,CAAC,IAAI,CAAC,CA+Df"}
|