lalph 0.1.15 → 0.1.17
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/dist/cli.mjs +35 -42
- package/package.json +3 -2
- package/src/Planner.ts +2 -2
- package/src/Prd.ts +8 -8
- package/src/PromptGen.ts +17 -17
- package/src/Runner.ts +1 -1
- package/src/domain/PrdIssue.ts +10 -26
package/dist/cli.mjs
CHANGED
|
@@ -59594,7 +59594,7 @@ const selectedCliAgentId = new Setting("selectedCliAgentId", Literals(allCliAgen
|
|
|
59594
59594
|
|
|
59595
59595
|
//#endregion
|
|
59596
59596
|
//#region src/domain/PrdIssue.ts
|
|
59597
|
-
var PrdIssue = class extends Class("PrdIssue")({
|
|
59597
|
+
var PrdIssue = class PrdIssue extends Class("PrdIssue")({
|
|
59598
59598
|
id: NullOr(String$1).annotate({ description: "The unique identifier of the issue. If null, it is considered a new issue." }),
|
|
59599
59599
|
title: String$1.annotate({ description: "The title of the issue" }),
|
|
59600
59600
|
description: String$1.annotate({ description: "The description of the issue in markdown format." }),
|
|
@@ -59607,8 +59607,13 @@ var PrdIssue = class extends Class("PrdIssue")({
|
|
|
59607
59607
|
}) {
|
|
59608
59608
|
static Array = Array$1(this);
|
|
59609
59609
|
static ArrayFromJson = toCodecJson(this.Array);
|
|
59610
|
-
static
|
|
59611
|
-
|
|
59610
|
+
static arrayToYaml(issues) {
|
|
59611
|
+
const json = encodeSync(this.ArrayFromJson)(issues);
|
|
59612
|
+
return import_dist.stringify(json, { blockQuote: "literal" });
|
|
59613
|
+
}
|
|
59614
|
+
static arrayFromYaml(yaml) {
|
|
59615
|
+
const json = import_dist.parse(yaml);
|
|
59616
|
+
return decodeSync(PrdIssue.ArrayFromJson)(json);
|
|
59612
59617
|
}
|
|
59613
59618
|
static jsonSchemaDoc = toJsonSchemaDocument(this);
|
|
59614
59619
|
static jsonSchema = {
|
|
@@ -59619,18 +59624,6 @@ var PrdIssue = class extends Class("PrdIssue")({
|
|
|
59619
59624
|
return this.title !== issue.title || this.description !== issue.description || this.stateId !== issue.stateId || !makeEquivalence$1(asEquivalence())(this.blockedBy, issue.blockedBy);
|
|
59620
59625
|
}
|
|
59621
59626
|
};
|
|
59622
|
-
var PrdList = class extends Class$1 {
|
|
59623
|
-
static fromJson(json) {
|
|
59624
|
-
return decodeSync(PrdIssue.ArrayFromJson)(JSON.parse(json));
|
|
59625
|
-
}
|
|
59626
|
-
toJson() {
|
|
59627
|
-
const issuesArray = fromIterable$2(this.issues.values());
|
|
59628
|
-
return PrdIssue.arrayToJson(issuesArray);
|
|
59629
|
-
}
|
|
59630
|
-
cast() {
|
|
59631
|
-
return this;
|
|
59632
|
-
}
|
|
59633
|
-
};
|
|
59634
59627
|
|
|
59635
59628
|
//#endregion
|
|
59636
59629
|
//#region src/IssueSource.ts
|
|
@@ -140371,9 +140364,9 @@ var CurrentIssueSource = class CurrentIssueSource extends Service()("lalph/Curre
|
|
|
140371
140364
|
var PromptGen = class extends Service()("lalph/PromptGen", { make: gen(function* () {
|
|
140372
140365
|
const sourceMeta = yield* CurrentIssueSource;
|
|
140373
140366
|
const states = yield* (yield* IssueSource).states;
|
|
140374
|
-
const prdNotes = `## prd.
|
|
140367
|
+
const prdNotes = `## prd.yml format
|
|
140375
140368
|
|
|
140376
|
-
Each item in the prd.
|
|
140369
|
+
Each item in the prd.yml file represents a task for the current project.
|
|
140377
140370
|
|
|
140378
140371
|
The \`stateId\` field indicates the current state of the task. The possible states
|
|
140379
140372
|
are:
|
|
@@ -140382,17 +140375,17 @@ ${Array.from(states.values(), (state) => `- **${state.name}** (stateId: \`${stat
|
|
|
140382
140375
|
|
|
140383
140376
|
### Adding tasks
|
|
140384
140377
|
|
|
140385
|
-
To add a new task, append a new item to the prd.
|
|
140378
|
+
To add a new task, append a new item to the prd.yml file with the id set to
|
|
140386
140379
|
\`null\`.
|
|
140387
140380
|
|
|
140388
140381
|
When adding a new task, it will take about 5 seconds for the system to update the
|
|
140389
|
-
prd.
|
|
140382
|
+
prd.yml file with a new id for the task.
|
|
140390
140383
|
|
|
140391
140384
|
### Removing tasks
|
|
140392
140385
|
|
|
140393
|
-
To remove a task, simply delete the item from the prd.
|
|
140386
|
+
To remove a task, simply delete the item from the prd.yml file.
|
|
140394
140387
|
|
|
140395
|
-
### prd.
|
|
140388
|
+
### prd.yml json schema
|
|
140396
140389
|
|
|
140397
140390
|
\`\`\`json
|
|
140398
140391
|
${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
|
|
@@ -140402,13 +140395,13 @@ ${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
|
|
|
140402
140395
|
The following instructions should be done without interaction or asking for
|
|
140403
140396
|
permission.
|
|
140404
140397
|
|
|
140405
|
-
1. Decide which single task to work on next from the prd.
|
|
140398
|
+
1. Decide which single task to work on next from the prd.yml file. This should
|
|
140406
140399
|
be the task YOU decide as the most important to work on next, not just the
|
|
140407
140400
|
first task in the list.
|
|
140408
140401
|
- Only start tasks that are in a "todo" state (i.e., not started yet).
|
|
140409
140402
|
- If the \`blockedBy\` field is not empty, skip the task.
|
|
140410
140403
|
2. **Before doing anything else**, mark the task as "in progress" by updating its
|
|
140411
|
-
\`stateId\` in the prd.
|
|
140404
|
+
\`stateId\` in the prd.yml file.
|
|
140412
140405
|
This prevents other people or agents from working on the same task simultaneously.
|
|
140413
140406
|
3. Check if there is an existing Github PR for the task, otherwise create a new
|
|
140414
140407
|
branch for the task.
|
|
@@ -140420,7 +140413,7 @@ permission.
|
|
|
140420
140413
|
- New branches should be named using the format \`{task id}/description\`.
|
|
140421
140414
|
- When checking for PR reviews, make sure to check the "reviews" field and read ALL unresolved comments.
|
|
140422
140415
|
4. Research the task. If it seems like too many steps are needed to complete the task,
|
|
140423
|
-
break it down into smaller tasks and add them to the prd.
|
|
140416
|
+
break it down into smaller tasks and add them to the prd.yml file, marking the
|
|
140424
140417
|
original task as "closed" by updating its \`stateId\`.
|
|
140425
140418
|
Otherwise, implement the task.
|
|
140426
140419
|
5. Run any checks / feedback loops, such as type checks, unit tests, or linting.
|
|
@@ -140428,9 +140421,9 @@ permission.
|
|
|
140428
140421
|
${sourceMeta.githubPrInstructions}
|
|
140429
140422
|
The PR description should include a summary of the changes made.
|
|
140430
140423
|
- None of the files in the \`.lalph\` directory should be committed.
|
|
140431
|
-
- You have permission to create or update the PR as needed.
|
|
140432
|
-
permission to push branches or create
|
|
140433
|
-
7. Update the prd.
|
|
140424
|
+
- You have permission to create or update the PR as needed. You have full
|
|
140425
|
+
permission to push branches, create PRs or create git commits.
|
|
140426
|
+
7. Update the prd.yml file to reflect any changes in task states.
|
|
140434
140427
|
- Add follow up tasks only if needed.
|
|
140435
140428
|
- Append to the \`description\` field with any notes or important discoveries.
|
|
140436
140429
|
- If you believe the task is complete, update the \`stateId\` for "review".
|
|
@@ -140442,7 +140435,7 @@ important to work on next.
|
|
|
140442
140435
|
## Important: Task sizing
|
|
140443
140436
|
|
|
140444
140437
|
If at any point you decide that a task is too large or complex to complete in a
|
|
140445
|
-
single iteration, break it down into smaller tasks and add them to the prd.
|
|
140438
|
+
single iteration, break it down into smaller tasks and add them to the prd.yml
|
|
140446
140439
|
file. Then, mark the original task as "closed" by updating its \`stateId\`.
|
|
140447
140440
|
|
|
140448
140441
|
Each task should be small and specific.
|
|
@@ -140464,17 +140457,17 @@ ${prdNotes}`;
|
|
|
140464
140457
|
Users idea / request: ${idea}
|
|
140465
140458
|
|
|
140466
140459
|
1. For the users idea / request above, break it down into multiple smaller tasks
|
|
140467
|
-
that can be added to the prd.
|
|
140460
|
+
that can be added to the prd.yml file.
|
|
140468
140461
|
- Make sure to research the codebase before creating any tasks, to ensure they
|
|
140469
140462
|
are relevant and feasible.
|
|
140470
|
-
- Check if similar tasks already exist in the prd.
|
|
140463
|
+
- Check if similar tasks already exist in the prd.yml file to avoid duplication.
|
|
140471
140464
|
2. Each task should have a id of \`null\`, a title, and a concise description that
|
|
140472
140465
|
includes a short summary of the task and a brief list of steps to complete it.
|
|
140473
140466
|
- The tasks should start in a "Todo" state (i.e., not started yet).
|
|
140474
140467
|
- Each task should be small and specific.
|
|
140475
140468
|
Instead of creating tasks like "Refactor the authentication system", create
|
|
140476
140469
|
smaller tasks like "Implement OAuth2 login endpoint", "Add JWT token refresh mechanism", etc.
|
|
140477
|
-
3. Add the new tasks to the prd.
|
|
140470
|
+
3. Add the new tasks to the prd.yml file.
|
|
140478
140471
|
4. Add a brief outline of the plan to a "lalph-plan.md" file, that will help guide future
|
|
140479
140472
|
iterations.
|
|
140480
140473
|
|
|
@@ -140484,7 +140477,7 @@ ${prdNotes}`;
|
|
|
140484
140477
|
planPrompt,
|
|
140485
140478
|
planContinuePrompt: `# Instructions
|
|
140486
140479
|
|
|
140487
|
-
1. Review the existing prd.
|
|
140480
|
+
1. Review the existing prd.yml file and lalph-plan.md file to understand the current
|
|
140488
140481
|
plan and tasks.
|
|
140489
140482
|
2. Ask the user for feedback to iterate on the existing plan.
|
|
140490
140483
|
|
|
@@ -140536,17 +140529,17 @@ var Prd = class extends Service()("lalph/Prd", { make: gen(function* () {
|
|
|
140536
140529
|
const fs = yield* FileSystem;
|
|
140537
140530
|
const source = yield* IssueSource;
|
|
140538
140531
|
const lalphDir = pathService.join(worktree.directory, `.lalph`);
|
|
140539
|
-
const prdFile = pathService.join(worktree.directory, `.lalph`, `prd.
|
|
140532
|
+
const prdFile = pathService.join(worktree.directory, `.lalph`, `prd.yml`);
|
|
140540
140533
|
let current = yield* source.issues;
|
|
140541
|
-
yield* fs.writeFileString(prdFile, PrdIssue.
|
|
140534
|
+
yield* fs.writeFileString(prdFile, PrdIssue.arrayToYaml(current));
|
|
140542
140535
|
const updatedIssues = /* @__PURE__ */ new Map();
|
|
140543
140536
|
yield* fs.watch(lalphDir).pipe(buffer({
|
|
140544
140537
|
capacity: 1,
|
|
140545
140538
|
strategy: "dropping"
|
|
140546
140539
|
}), runForEach((_) => ignore(sync$3)), retry$1(forever$1), forkScoped);
|
|
140547
140540
|
const sync$3 = gen(function* () {
|
|
140548
|
-
const
|
|
140549
|
-
const updated =
|
|
140541
|
+
const yaml = yield* fs.readFileString(prdFile);
|
|
140542
|
+
const updated = PrdIssue.arrayFromYaml(yaml);
|
|
140550
140543
|
if (!(updated.length !== current.length || updated.some((u, i) => u.isChangedComparedTo(current[i])))) return;
|
|
140551
140544
|
const githubPrs = /* @__PURE__ */ new Map();
|
|
140552
140545
|
const toRemove = new Set(current.filter((i) => i.id !== null).map((i) => i.id));
|
|
@@ -140581,7 +140574,7 @@ var Prd = class extends Service()("lalph/Prd", { make: gen(function* () {
|
|
|
140581
140574
|
}
|
|
140582
140575
|
yield* forEach$1(toRemove, (issueId) => source.cancelIssue(issueId), { concurrency: "unbounded" });
|
|
140583
140576
|
current = yield* source.issues;
|
|
140584
|
-
yield* fs.writeFileString(prdFile, PrdIssue.
|
|
140577
|
+
yield* fs.writeFileString(prdFile, PrdIssue.arrayToYaml(current.map((issue) => {
|
|
140585
140578
|
const prNumber = githubPrs.get(issue.id);
|
|
140586
140579
|
if (!prNumber) return issue;
|
|
140587
140580
|
return new PrdIssue({
|
|
@@ -140591,8 +140584,8 @@ var Prd = class extends Service()("lalph/Prd", { make: gen(function* () {
|
|
|
140591
140584
|
})));
|
|
140592
140585
|
}).pipe(uninterruptible);
|
|
140593
140586
|
const mergableGithubPrs = gen(function* () {
|
|
140594
|
-
const
|
|
140595
|
-
const updated =
|
|
140587
|
+
const yaml = yield* fs.readFileString(prdFile);
|
|
140588
|
+
const updated = PrdIssue.arrayFromYaml(yaml);
|
|
140596
140589
|
const prs = empty$11();
|
|
140597
140590
|
for (const issue of updated) {
|
|
140598
140591
|
const entry = updatedIssues.get(issue.id ?? "");
|
|
@@ -140646,7 +140639,7 @@ const run = fnUntraced(function* (options) {
|
|
|
140646
140639
|
const prd = yield* Prd;
|
|
140647
140640
|
const cliCommand = cliAgent.command({
|
|
140648
140641
|
prompt: promptGen.prompt,
|
|
140649
|
-
prdFilePath: pathService.join(".lalph", "prd.
|
|
140642
|
+
prdFilePath: pathService.join(".lalph", "prd.yml")
|
|
140650
140643
|
});
|
|
140651
140644
|
const handle = yield* make$22(cliCommand[0], cliCommand.slice(1), {
|
|
140652
140645
|
cwd: worktree.directory,
|
|
@@ -140698,7 +140691,7 @@ const plan = gen(function* () {
|
|
|
140698
140691
|
yield* scoped$1(fs.open(lalphPlanPath, { flag: "a+" }));
|
|
140699
140692
|
const cliCommand = cliAgent.commandPlan({
|
|
140700
140693
|
prompt: promptGen.planPrompt(idea),
|
|
140701
|
-
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.
|
|
140694
|
+
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.yml")
|
|
140702
140695
|
});
|
|
140703
140696
|
const exitCode$1 = yield* make$22(cliCommand[0], cliCommand.slice(1), {
|
|
140704
140697
|
cwd: worktree.directory,
|
|
@@ -140726,7 +140719,7 @@ const planContinue = gen(function* () {
|
|
|
140726
140719
|
yield* scoped$1(fs.open(lalphPlanPath, { flag: "a+" }));
|
|
140727
140720
|
const cliCommand = cliAgent.commandPlan({
|
|
140728
140721
|
prompt: promptGen.planContinuePrompt,
|
|
140729
|
-
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.
|
|
140722
|
+
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.yml")
|
|
140730
140723
|
});
|
|
140731
140724
|
const exitCode$1 = yield* make$22(cliCommand[0], cliCommand.slice(1), {
|
|
140732
140725
|
cwd: worktree.directory,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lalph",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.17",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"octokit": "^5.0.5",
|
|
32
32
|
"prettier": "^3.7.4",
|
|
33
33
|
"tsdown": "^0.19.0",
|
|
34
|
-
"typescript": "^5.9.3"
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"yaml": "^2.8.2"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
|
37
38
|
"check": "tsc --noEmit && prettier --check .",
|
package/src/Planner.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const plan = Effect.gen(function* () {
|
|
|
22
22
|
|
|
23
23
|
const cliCommand = cliAgent.commandPlan({
|
|
24
24
|
prompt: promptGen.planPrompt(idea),
|
|
25
|
-
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.
|
|
25
|
+
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.yml"),
|
|
26
26
|
})
|
|
27
27
|
const exitCode = yield* ChildProcess.make(
|
|
28
28
|
cliCommand[0]!,
|
|
@@ -60,7 +60,7 @@ export const planContinue = Effect.gen(function* () {
|
|
|
60
60
|
|
|
61
61
|
const cliCommand = cliAgent.commandPlan({
|
|
62
62
|
prompt: promptGen.planContinuePrompt,
|
|
63
|
-
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.
|
|
63
|
+
prdFilePath: pathService.join(worktree.directory, ".lalph", "prd.yml"),
|
|
64
64
|
})
|
|
65
65
|
const exitCode = yield* ChildProcess.make(
|
|
66
66
|
cliCommand[0]!,
|
package/src/Prd.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Stream,
|
|
10
10
|
} from "effect"
|
|
11
11
|
import { Worktree } from "./Worktree.ts"
|
|
12
|
-
import { PrdIssue
|
|
12
|
+
import { PrdIssue } from "./domain/PrdIssue.ts"
|
|
13
13
|
import { IssueSource } from "./IssueSource.ts"
|
|
14
14
|
|
|
15
15
|
export class Prd extends ServiceMap.Service<Prd>()("lalph/Prd", {
|
|
@@ -20,10 +20,10 @@ export class Prd extends ServiceMap.Service<Prd>()("lalph/Prd", {
|
|
|
20
20
|
const source = yield* IssueSource
|
|
21
21
|
|
|
22
22
|
const lalphDir = pathService.join(worktree.directory, `.lalph`)
|
|
23
|
-
const prdFile = pathService.join(worktree.directory, `.lalph`, `prd.
|
|
23
|
+
const prdFile = pathService.join(worktree.directory, `.lalph`, `prd.yml`)
|
|
24
24
|
|
|
25
25
|
let current = yield* source.issues
|
|
26
|
-
yield* fs.writeFileString(prdFile, PrdIssue.
|
|
26
|
+
yield* fs.writeFileString(prdFile, PrdIssue.arrayToYaml(current))
|
|
27
27
|
|
|
28
28
|
const updatedIssues = new Map<
|
|
29
29
|
string,
|
|
@@ -45,8 +45,8 @@ export class Prd extends ServiceMap.Service<Prd>()("lalph/Prd", {
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
const sync = Effect.gen(function* () {
|
|
48
|
-
const
|
|
49
|
-
const updated =
|
|
48
|
+
const yaml = yield* fs.readFileString(prdFile)
|
|
49
|
+
const updated = PrdIssue.arrayFromYaml(yaml)
|
|
50
50
|
const anyChanges =
|
|
51
51
|
updated.length !== current.length ||
|
|
52
52
|
updated.some((u, i) => u.isChangedComparedTo(current[i]!))
|
|
@@ -101,7 +101,7 @@ export class Prd extends ServiceMap.Service<Prd>()("lalph/Prd", {
|
|
|
101
101
|
current = yield* source.issues
|
|
102
102
|
yield* fs.writeFileString(
|
|
103
103
|
prdFile,
|
|
104
|
-
PrdIssue.
|
|
104
|
+
PrdIssue.arrayToYaml(
|
|
105
105
|
current.map((issue) => {
|
|
106
106
|
const prNumber = githubPrs.get(issue.id!)
|
|
107
107
|
if (!prNumber) return issue
|
|
@@ -112,8 +112,8 @@ export class Prd extends ServiceMap.Service<Prd>()("lalph/Prd", {
|
|
|
112
112
|
}).pipe(Effect.uninterruptible)
|
|
113
113
|
|
|
114
114
|
const mergableGithubPrs = Effect.gen(function* () {
|
|
115
|
-
const
|
|
116
|
-
const updated =
|
|
115
|
+
const yaml = yield* fs.readFileString(prdFile)
|
|
116
|
+
const updated = PrdIssue.arrayFromYaml(yaml)
|
|
117
117
|
const prs = Array.empty<number>()
|
|
118
118
|
for (const issue of updated) {
|
|
119
119
|
const entry = updatedIssues.get(issue.id ?? "")
|
package/src/PromptGen.ts
CHANGED
|
@@ -11,9 +11,9 @@ export class PromptGen extends ServiceMap.Service<PromptGen>()(
|
|
|
11
11
|
const source = yield* IssueSource
|
|
12
12
|
const states = yield* source.states
|
|
13
13
|
|
|
14
|
-
const prdNotes = `## prd.
|
|
14
|
+
const prdNotes = `## prd.yml format
|
|
15
15
|
|
|
16
|
-
Each item in the prd.
|
|
16
|
+
Each item in the prd.yml file represents a task for the current project.
|
|
17
17
|
|
|
18
18
|
The \`stateId\` field indicates the current state of the task. The possible states
|
|
19
19
|
are:
|
|
@@ -22,17 +22,17 @@ ${Array.from(states.values(), (state) => `- **${state.name}** (stateId: \`${stat
|
|
|
22
22
|
|
|
23
23
|
### Adding tasks
|
|
24
24
|
|
|
25
|
-
To add a new task, append a new item to the prd.
|
|
25
|
+
To add a new task, append a new item to the prd.yml file with the id set to
|
|
26
26
|
\`null\`.
|
|
27
27
|
|
|
28
28
|
When adding a new task, it will take about 5 seconds for the system to update the
|
|
29
|
-
prd.
|
|
29
|
+
prd.yml file with a new id for the task.
|
|
30
30
|
|
|
31
31
|
### Removing tasks
|
|
32
32
|
|
|
33
|
-
To remove a task, simply delete the item from the prd.
|
|
33
|
+
To remove a task, simply delete the item from the prd.yml file.
|
|
34
34
|
|
|
35
|
-
### prd.
|
|
35
|
+
### prd.yml json schema
|
|
36
36
|
|
|
37
37
|
\`\`\`json
|
|
38
38
|
${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
|
|
@@ -43,13 +43,13 @@ ${JSON.stringify(PrdIssue.jsonSchema, null, 2)}
|
|
|
43
43
|
The following instructions should be done without interaction or asking for
|
|
44
44
|
permission.
|
|
45
45
|
|
|
46
|
-
1. Decide which single task to work on next from the prd.
|
|
46
|
+
1. Decide which single task to work on next from the prd.yml file. This should
|
|
47
47
|
be the task YOU decide as the most important to work on next, not just the
|
|
48
48
|
first task in the list.
|
|
49
49
|
- Only start tasks that are in a "todo" state (i.e., not started yet).
|
|
50
50
|
- If the \`blockedBy\` field is not empty, skip the task.
|
|
51
51
|
2. **Before doing anything else**, mark the task as "in progress" by updating its
|
|
52
|
-
\`stateId\` in the prd.
|
|
52
|
+
\`stateId\` in the prd.yml file.
|
|
53
53
|
This prevents other people or agents from working on the same task simultaneously.
|
|
54
54
|
3. Check if there is an existing Github PR for the task, otherwise create a new
|
|
55
55
|
branch for the task.
|
|
@@ -61,7 +61,7 @@ permission.
|
|
|
61
61
|
- New branches should be named using the format \`{task id}/description\`.
|
|
62
62
|
- When checking for PR reviews, make sure to check the "reviews" field and read ALL unresolved comments.
|
|
63
63
|
4. Research the task. If it seems like too many steps are needed to complete the task,
|
|
64
|
-
break it down into smaller tasks and add them to the prd.
|
|
64
|
+
break it down into smaller tasks and add them to the prd.yml file, marking the
|
|
65
65
|
original task as "closed" by updating its \`stateId\`.
|
|
66
66
|
Otherwise, implement the task.
|
|
67
67
|
5. Run any checks / feedback loops, such as type checks, unit tests, or linting.
|
|
@@ -69,9 +69,9 @@ permission.
|
|
|
69
69
|
${sourceMeta.githubPrInstructions}
|
|
70
70
|
The PR description should include a summary of the changes made.
|
|
71
71
|
- None of the files in the \`.lalph\` directory should be committed.
|
|
72
|
-
- You have permission to create or update the PR as needed.
|
|
73
|
-
permission to push branches or create
|
|
74
|
-
7. Update the prd.
|
|
72
|
+
- You have permission to create or update the PR as needed. You have full
|
|
73
|
+
permission to push branches, create PRs or create git commits.
|
|
74
|
+
7. Update the prd.yml file to reflect any changes in task states.
|
|
75
75
|
- Add follow up tasks only if needed.
|
|
76
76
|
- Append to the \`description\` field with any notes or important discoveries.
|
|
77
77
|
- If you believe the task is complete, update the \`stateId\` for "review".
|
|
@@ -83,7 +83,7 @@ important to work on next.
|
|
|
83
83
|
## Important: Task sizing
|
|
84
84
|
|
|
85
85
|
If at any point you decide that a task is too large or complex to complete in a
|
|
86
|
-
single iteration, break it down into smaller tasks and add them to the prd.
|
|
86
|
+
single iteration, break it down into smaller tasks and add them to the prd.yml
|
|
87
87
|
file. Then, mark the original task as "closed" by updating its \`stateId\`.
|
|
88
88
|
|
|
89
89
|
Each task should be small and specific.
|
|
@@ -106,17 +106,17 @@ ${prdNotes}`
|
|
|
106
106
|
Users idea / request: ${idea}
|
|
107
107
|
|
|
108
108
|
1. For the users idea / request above, break it down into multiple smaller tasks
|
|
109
|
-
that can be added to the prd.
|
|
109
|
+
that can be added to the prd.yml file.
|
|
110
110
|
- Make sure to research the codebase before creating any tasks, to ensure they
|
|
111
111
|
are relevant and feasible.
|
|
112
|
-
- Check if similar tasks already exist in the prd.
|
|
112
|
+
- Check if similar tasks already exist in the prd.yml file to avoid duplication.
|
|
113
113
|
2. Each task should have a id of \`null\`, a title, and a concise description that
|
|
114
114
|
includes a short summary of the task and a brief list of steps to complete it.
|
|
115
115
|
- The tasks should start in a "Todo" state (i.e., not started yet).
|
|
116
116
|
- Each task should be small and specific.
|
|
117
117
|
Instead of creating tasks like "Refactor the authentication system", create
|
|
118
118
|
smaller tasks like "Implement OAuth2 login endpoint", "Add JWT token refresh mechanism", etc.
|
|
119
|
-
3. Add the new tasks to the prd.
|
|
119
|
+
3. Add the new tasks to the prd.yml file.
|
|
120
120
|
4. Add a brief outline of the plan to a "lalph-plan.md" file, that will help guide future
|
|
121
121
|
iterations.
|
|
122
122
|
|
|
@@ -124,7 +124,7 @@ ${prdNotes}`
|
|
|
124
124
|
|
|
125
125
|
const planContinuePrompt = `# Instructions
|
|
126
126
|
|
|
127
|
-
1. Review the existing prd.
|
|
127
|
+
1. Review the existing prd.yml file and lalph-plan.md file to understand the current
|
|
128
128
|
plan and tasks.
|
|
129
129
|
2. Ask the user for feedback to iterate on the existing plan.
|
|
130
130
|
|
package/src/Runner.ts
CHANGED
|
@@ -18,7 +18,7 @@ export const run = Effect.fnUntraced(
|
|
|
18
18
|
|
|
19
19
|
const cliCommand = cliAgent.command({
|
|
20
20
|
prompt: promptGen.prompt,
|
|
21
|
-
prdFilePath: pathService.join(".lalph", "prd.
|
|
21
|
+
prdFilePath: pathService.join(".lalph", "prd.yml"),
|
|
22
22
|
})
|
|
23
23
|
const handle = yield* ChildProcess.make(
|
|
24
24
|
cliCommand[0]!,
|
package/src/domain/PrdIssue.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Schema,
|
|
1
|
+
import { Schema, Array, Equal } from "effect"
|
|
2
|
+
import * as Yaml from "yaml"
|
|
2
3
|
|
|
3
4
|
export class PrdIssue extends Schema.Class<PrdIssue>("PrdIssue")({
|
|
4
5
|
id: Schema.NullOr(Schema.String).annotate({
|
|
@@ -36,12 +37,14 @@ export class PrdIssue extends Schema.Class<PrdIssue>("PrdIssue")({
|
|
|
36
37
|
}) {
|
|
37
38
|
static Array = Schema.Array(this)
|
|
38
39
|
static ArrayFromJson = Schema.toCodecJson(this.Array)
|
|
39
|
-
static
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
40
|
+
static arrayToYaml(issues: ReadonlyArray<PrdIssue>): string {
|
|
41
|
+
const json = Schema.encodeSync(this.ArrayFromJson)(issues)
|
|
42
|
+
return Yaml.stringify(json, { blockQuote: "literal" })
|
|
43
|
+
}
|
|
44
|
+
static arrayFromYaml(yaml: string): ReadonlyArray<PrdIssue> {
|
|
45
|
+
const json = Yaml.parse(yaml)
|
|
46
|
+
const issues = Schema.decodeSync(PrdIssue.ArrayFromJson)(json)
|
|
47
|
+
return issues
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
static jsonSchemaDoc = Schema.toJsonSchemaDocument(this)
|
|
@@ -62,22 +65,3 @@ export class PrdIssue extends Schema.Class<PrdIssue>("PrdIssue")({
|
|
|
62
65
|
)
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
export class PrdList<O = unknown> extends Data.Class<{
|
|
67
|
-
readonly issues: ReadonlyMap<string, PrdIssue>
|
|
68
|
-
readonly orignals: ReadonlyMap<string, O>
|
|
69
|
-
}> {
|
|
70
|
-
static fromJson(json: string): ReadonlyArray<PrdIssue> {
|
|
71
|
-
const issues = Schema.decodeSync(PrdIssue.ArrayFromJson)(JSON.parse(json))
|
|
72
|
-
return issues
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
toJson(): string {
|
|
76
|
-
const issuesArray = Array.fromIterable(this.issues.values())
|
|
77
|
-
return PrdIssue.arrayToJson(issuesArray)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
cast<T>(): PrdList<T> {
|
|
81
|
-
return this as any
|
|
82
|
-
}
|
|
83
|
-
}
|