@wkronmiller/lisa 0.1.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/LICENSE +21 -0
- package/README.md +407 -0
- package/bin/lisa-runtime.js +8797 -0
- package/bin/lisa.js +21 -0
- package/completion.ts +58 -0
- package/install.ps1 +51 -0
- package/install.sh +93 -0
- package/lisa.ts +6 -0
- package/package.json +66 -0
- package/skills/README.md +28 -0
- package/skills/claude-code/CLAUDE.md +151 -0
- package/skills/codex/AGENTS.md +151 -0
- package/skills/gemini/GEMINI.md +151 -0
- package/skills/opencode/AGENTS.md +152 -0
- package/src/cli.ts +85 -0
- package/src/harness/base-adapter.ts +47 -0
- package/src/harness/claude-code.ts +106 -0
- package/src/harness/codex.ts +80 -0
- package/src/harness/command.ts +173 -0
- package/src/harness/gemini.ts +74 -0
- package/src/harness/opencode.ts +84 -0
- package/src/harness/registry.ts +29 -0
- package/src/harness/runner.ts +19 -0
- package/src/harness/types.ts +73 -0
- package/src/output-mode.ts +32 -0
- package/src/skill/artifacts.ts +174 -0
- package/src/skill/cli.ts +29 -0
- package/src/skill/install.ts +317 -0
- package/src/spec/agent-guidance.ts +466 -0
- package/src/spec/cli.ts +151 -0
- package/src/spec/commands/check.ts +1 -0
- package/src/spec/commands/config.ts +146 -0
- package/src/spec/commands/diff.ts +1 -0
- package/src/spec/commands/generate.ts +1 -0
- package/src/spec/commands/guide.ts +1 -0
- package/src/spec/commands/harness-list.ts +36 -0
- package/src/spec/commands/implement.ts +1 -0
- package/src/spec/commands/import.ts +1 -0
- package/src/spec/commands/init.ts +1 -0
- package/src/spec/commands/status.ts +87 -0
- package/src/spec/config.ts +63 -0
- package/src/spec/diff.ts +791 -0
- package/src/spec/extensions/benchmark.ts +347 -0
- package/src/spec/extensions/registry.ts +59 -0
- package/src/spec/extensions/types.ts +56 -0
- package/src/spec/grammar/index.ts +14 -0
- package/src/spec/grammar/parser.ts +443 -0
- package/src/spec/grammar/types.ts +70 -0
- package/src/spec/grammar/validator.ts +104 -0
- package/src/spec/loader.ts +174 -0
- package/src/spec/local-config.ts +59 -0
- package/src/spec/parser.ts +226 -0
- package/src/spec/path-utils.ts +73 -0
- package/src/spec/planner.ts +299 -0
- package/src/spec/prompt-renderer.ts +318 -0
- package/src/spec/skill-content.ts +119 -0
- package/src/spec/types.ts +239 -0
- package/src/spec/validator.ts +443 -0
- package/src/spec/workflows/check.ts +1534 -0
- package/src/spec/workflows/diff.ts +209 -0
- package/src/spec/workflows/generate.ts +1270 -0
- package/src/spec/workflows/guide.ts +190 -0
- package/src/spec/workflows/implement.ts +797 -0
- package/src/spec/workflows/import.ts +986 -0
- package/src/spec/workflows/init.ts +548 -0
- package/src/spec/workflows/status.ts +22 -0
- package/src/spec/workspace.ts +541 -0
- package/uninstall.ps1 +21 -0
- package/uninstall.sh +22 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { DEFAULT_SPEC_DIFF_BASE_REF, collectSpecDiff, getSpecDiffRelativePath } from "../diff";
|
|
2
|
+
import { loadSpecWorkspace, loadSpecWorkspaceAtRef } from "../loader";
|
|
3
|
+
import { planSpecImplementation } from "../planner";
|
|
4
|
+
import type { ValidationIssue } from "../types";
|
|
5
|
+
import { resolveWorkspaceLayout, toLogicalPath } from "../workspace";
|
|
6
|
+
|
|
7
|
+
interface DiffCommandOptions {
|
|
8
|
+
base?: string;
|
|
9
|
+
head?: string;
|
|
10
|
+
help: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DiffCommandIO {
|
|
14
|
+
print(message: string): void;
|
|
15
|
+
error(message: string): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createConsoleIO(): DiffCommandIO {
|
|
19
|
+
return {
|
|
20
|
+
print(message: string): void {
|
|
21
|
+
console.log(message);
|
|
22
|
+
},
|
|
23
|
+
error(message: string): void {
|
|
24
|
+
console.error(message);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function printDiffHelp(io: DiffCommandIO): void {
|
|
30
|
+
io.print(`Lisa spec diff
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
lisa spec diff [options]
|
|
34
|
+
|
|
35
|
+
Options:
|
|
36
|
+
--base <rev> Diff base revision (default: HEAD)
|
|
37
|
+
--head <rev> Diff head revision (default: worktree)
|
|
38
|
+
--help, -h Show this help
|
|
39
|
+
`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseDiffArgs(args: string[]): DiffCommandOptions {
|
|
43
|
+
const options: DiffCommandOptions = { help: false };
|
|
44
|
+
|
|
45
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
46
|
+
const arg = args[index];
|
|
47
|
+
if (!arg) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (arg === "--help" || arg === "-h") {
|
|
52
|
+
options.help = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (arg === "--base" || arg === "--head") {
|
|
57
|
+
const value = args[index + 1];
|
|
58
|
+
if (!value) {
|
|
59
|
+
throw new Error(`${arg} requires a value.`);
|
|
60
|
+
}
|
|
61
|
+
index += 1;
|
|
62
|
+
if (arg === "--base") {
|
|
63
|
+
options.base = value;
|
|
64
|
+
} else {
|
|
65
|
+
options.head = value.toLowerCase() === "worktree" ? undefined : value;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw new Error(`Unknown lisa spec diff option: ${arg}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return options;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function formatIssuesForConsole(issues: ValidationIssue[], workspaceRoot: string): string[] {
|
|
77
|
+
const layout = resolveWorkspaceLayout(workspaceRoot);
|
|
78
|
+
return issues.map((issue) => `${issue.severity}: ${toLogicalPath(layout, issue.path)} - ${issue.message}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getBlockingValidationIssues(
|
|
82
|
+
workspace: ReturnType<typeof loadSpecWorkspace>,
|
|
83
|
+
diff: ReturnType<typeof collectSpecDiff>,
|
|
84
|
+
): ValidationIssue[] {
|
|
85
|
+
const changedSpecIds = new Set(diff.deltas.map((delta) => delta.specId));
|
|
86
|
+
const changedBaseSpecIds = new Set(
|
|
87
|
+
diff.deltas.flatMap((delta) => {
|
|
88
|
+
if (delta.kind === "base") {
|
|
89
|
+
return [delta.specId];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return delta.extendsSpecId ? [delta.extendsSpecId] : [];
|
|
93
|
+
}),
|
|
94
|
+
);
|
|
95
|
+
const referencedEnvironments = new Set(
|
|
96
|
+
diff.deltas.flatMap((delta) => {
|
|
97
|
+
const document = delta.nextDocument ?? delta.previousDocument;
|
|
98
|
+
return typeof document?.frontmatter.environment === "string" ? [document.frontmatter.environment] : [];
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
const relevantPaths = new Set<string>(diff.deltas.map((delta) => delta.path));
|
|
102
|
+
|
|
103
|
+
for (const document of workspace.documents) {
|
|
104
|
+
if (document.id && (changedSpecIds.has(document.id) || changedBaseSpecIds.has(document.id))) {
|
|
105
|
+
relevantPaths.add(document.path);
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (
|
|
110
|
+
document.kind !== "base" &&
|
|
111
|
+
typeof document.frontmatter.extends === "string" &&
|
|
112
|
+
changedBaseSpecIds.has(document.frontmatter.extends)
|
|
113
|
+
) {
|
|
114
|
+
relevantPaths.add(document.path);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for (const environment of workspace.environments) {
|
|
119
|
+
if (environment.name && referencedEnvironments.has(environment.name)) {
|
|
120
|
+
relevantPaths.add(environment.path);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return workspace.issues.filter((issue) => issue.severity === "error" && relevantPaths.has(issue.path));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function runSpecDiffCommand(
|
|
128
|
+
args: string[],
|
|
129
|
+
cwd = process.cwd(),
|
|
130
|
+
io: DiffCommandIO = createConsoleIO(),
|
|
131
|
+
): Promise<number> {
|
|
132
|
+
try {
|
|
133
|
+
const options = parseDiffArgs(args);
|
|
134
|
+
if (options.help) {
|
|
135
|
+
printDiffHelp(io);
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const layout = resolveWorkspaceLayout(cwd);
|
|
140
|
+
if (layout.storageMode === "external" && (args.includes("--base") || args.includes("--head"))) {
|
|
141
|
+
io.error("External Lisa workspaces do not support `--base` or `--head` for spec history yet.");
|
|
142
|
+
return 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const currentWorkspace = loadSpecWorkspace(cwd);
|
|
146
|
+
const diff = collectSpecDiff(cwd, {
|
|
147
|
+
baseRef: options.base,
|
|
148
|
+
headRef: options.head,
|
|
149
|
+
});
|
|
150
|
+
const workspace = options.head ? loadSpecWorkspaceAtRef(options.head, cwd) : currentWorkspace;
|
|
151
|
+
const plan = planSpecImplementation(workspace, diff);
|
|
152
|
+
const blockingValidationIssues = getBlockingValidationIssues(workspace, diff);
|
|
153
|
+
|
|
154
|
+
io.print("Lisa Spec Diff");
|
|
155
|
+
io.print(`Range: ${diff.baseRef} -> ${diff.headRef}`);
|
|
156
|
+
io.print(`Changed specs: ${diff.deltas.length}`);
|
|
157
|
+
io.print("");
|
|
158
|
+
|
|
159
|
+
if (workspace.issues.length > 0) {
|
|
160
|
+
io.print("Workspace Validation");
|
|
161
|
+
for (const issue of formatIssuesForConsole(workspace.issues, workspace.workspacePath)) {
|
|
162
|
+
io.print(`- ${issue}`);
|
|
163
|
+
}
|
|
164
|
+
io.print("");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (diff.deltas.length === 0) {
|
|
168
|
+
io.print("No spec changes detected.");
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (blockingValidationIssues.length > 0) {
|
|
173
|
+
io.error("Spec diff cannot produce a reliable plan until the changed specs validate cleanly.");
|
|
174
|
+
return 1;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
io.print("Deltas");
|
|
178
|
+
for (const delta of diff.deltas) {
|
|
179
|
+
io.print(`- ${delta.specId} (${delta.kind}, ${delta.fileChange}) at ${getSpecDiffRelativePath(diff, delta.path)}`);
|
|
180
|
+
if (delta.extendsSpecId) {
|
|
181
|
+
io.print(` extends: ${delta.extendsSpecId}`);
|
|
182
|
+
}
|
|
183
|
+
for (const change of delta.sectionChanges) {
|
|
184
|
+
io.print(` - ${change.section} [${change.changeType}]`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
io.print("");
|
|
188
|
+
|
|
189
|
+
io.print("Planned Tasks");
|
|
190
|
+
for (const task of plan.tasks) {
|
|
191
|
+
io.print(`- [${task.type}] ${task.description}`);
|
|
192
|
+
}
|
|
193
|
+
io.print("");
|
|
194
|
+
|
|
195
|
+
io.print("Mapped Test Commands");
|
|
196
|
+
if (plan.testCommands.length === 0) {
|
|
197
|
+
io.print("- none");
|
|
198
|
+
} else {
|
|
199
|
+
for (const command of plan.testCommands) {
|
|
200
|
+
io.print(`- ${command}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return 0;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
io.error(error instanceof Error ? error.message : String(error));
|
|
207
|
+
return 1;
|
|
208
|
+
}
|
|
209
|
+
}
|