@joshski/dust 0.1.55 → 0.1.56
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/types.d.ts +1 -0
- package/dist/dust.js +50 -17
- package/dist/workflow-tasks.js +2 -2
- package/package.json +1 -1
package/dist/cli/types.d.ts
CHANGED
package/dist/dust.js
CHANGED
|
@@ -1925,8 +1925,7 @@ function formatLoopEvent(event) {
|
|
|
1925
1925
|
case "loop.checking_tasks":
|
|
1926
1926
|
return null;
|
|
1927
1927
|
case "loop.no_tasks":
|
|
1928
|
-
return
|
|
1929
|
-
`;
|
|
1928
|
+
return "\uD83D\uDE34 No tasks available. Sleeping...";
|
|
1930
1929
|
case "loop.tasks_found":
|
|
1931
1930
|
return `✨ Found a task. Going to work!
|
|
1932
1931
|
`;
|
|
@@ -1973,7 +1972,18 @@ function createWireEventSender(eventsUrl, sessionId, postEvent, onError, getAgen
|
|
|
1973
1972
|
}
|
|
1974
1973
|
var log = createLogger("dust.cli.commands.loop");
|
|
1975
1974
|
var SLEEP_INTERVAL_MS = 30000;
|
|
1975
|
+
var SLEEP_STEP_MS = 1000;
|
|
1976
1976
|
var DEFAULT_MAX_ITERATIONS = 10;
|
|
1977
|
+
async function sleepWithProgress(sleep, totalMs, writeInline, writeLine) {
|
|
1978
|
+
let remainingMs = totalMs;
|
|
1979
|
+
while (remainingMs > 0) {
|
|
1980
|
+
const stepMs = Math.min(SLEEP_STEP_MS, remainingMs);
|
|
1981
|
+
await sleep(stepMs);
|
|
1982
|
+
writeInline(".");
|
|
1983
|
+
remainingMs -= stepMs;
|
|
1984
|
+
}
|
|
1985
|
+
writeLine("");
|
|
1986
|
+
}
|
|
1977
1987
|
async function gitPull(cwd, spawn) {
|
|
1978
1988
|
return new Promise((resolve) => {
|
|
1979
1989
|
const proc = spawn("git", ["pull"], {
|
|
@@ -2172,7 +2182,8 @@ async function loopClaude(dependencies, loopDependencies = createDefaultDependen
|
|
|
2172
2182
|
const result = await runOneIteration(dependencies, loopDependencies, onLoopEvent, onAgentEvent, iterationOptions);
|
|
2173
2183
|
if (result === "no_tasks") {
|
|
2174
2184
|
log("sleeping, no tasks");
|
|
2175
|
-
|
|
2185
|
+
const writeInline = context.stdoutInline ?? context.stdout;
|
|
2186
|
+
await sleepWithProgress(loopDependencies.sleep, SLEEP_INTERVAL_MS, writeInline, context.stdout);
|
|
2176
2187
|
} else {
|
|
2177
2188
|
completedIterations++;
|
|
2178
2189
|
log(`iteration ${completedIterations}/${maxIterations} complete, result=${result}`);
|
|
@@ -3706,17 +3717,15 @@ function validateIdeaOpenQuestions(filePath, content) {
|
|
|
3706
3717
|
const violations = [];
|
|
3707
3718
|
const lines = content.split(`
|
|
3708
3719
|
`);
|
|
3720
|
+
const topLevelStructureMessage = "Open Questions must use `### Question?` headings and `#### Option` headings at the top level. Put supporting markdown (including lists and code blocks) under an option heading. Run `dust new idea` to see the expected format.";
|
|
3709
3721
|
let inOpenQuestions = false;
|
|
3710
3722
|
let currentQuestionLine = null;
|
|
3723
|
+
let inOption = false;
|
|
3711
3724
|
let inCodeBlock = false;
|
|
3712
3725
|
for (let i = 0;i < lines.length; i++) {
|
|
3713
3726
|
const line = lines[i];
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
continue;
|
|
3717
|
-
}
|
|
3718
|
-
if (inCodeBlock)
|
|
3719
|
-
continue;
|
|
3727
|
+
const trimmedLine = line.trimEnd();
|
|
3728
|
+
const nonWhitespaceLine = line.trim();
|
|
3720
3729
|
if (line.startsWith("## ")) {
|
|
3721
3730
|
if (inOpenQuestions && currentQuestionLine !== null) {
|
|
3722
3731
|
violations.push({
|
|
@@ -3735,19 +3744,27 @@ function validateIdeaOpenQuestions(filePath, content) {
|
|
|
3735
3744
|
}
|
|
3736
3745
|
inOpenQuestions = line === "## Open Questions";
|
|
3737
3746
|
currentQuestionLine = null;
|
|
3747
|
+
inOption = false;
|
|
3748
|
+
inCodeBlock = false;
|
|
3738
3749
|
continue;
|
|
3739
3750
|
}
|
|
3740
3751
|
if (!inOpenQuestions)
|
|
3741
3752
|
continue;
|
|
3742
|
-
if (
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3753
|
+
if (line.startsWith("```")) {
|
|
3754
|
+
if (!inOption && !inCodeBlock) {
|
|
3755
|
+
violations.push({
|
|
3756
|
+
file: filePath,
|
|
3757
|
+
message: topLevelStructureMessage,
|
|
3758
|
+
line: i + 1
|
|
3759
|
+
});
|
|
3760
|
+
}
|
|
3761
|
+
inCodeBlock = !inCodeBlock;
|
|
3748
3762
|
continue;
|
|
3749
3763
|
}
|
|
3764
|
+
if (inCodeBlock)
|
|
3765
|
+
continue;
|
|
3750
3766
|
if (line.startsWith("### ")) {
|
|
3767
|
+
inOption = false;
|
|
3751
3768
|
if (currentQuestionLine !== null) {
|
|
3752
3769
|
violations.push({
|
|
3753
3770
|
file: filePath,
|
|
@@ -3755,7 +3772,7 @@ function validateIdeaOpenQuestions(filePath, content) {
|
|
|
3755
3772
|
line: currentQuestionLine
|
|
3756
3773
|
});
|
|
3757
3774
|
}
|
|
3758
|
-
if (!
|
|
3775
|
+
if (!trimmedLine.endsWith("?")) {
|
|
3759
3776
|
violations.push({
|
|
3760
3777
|
file: filePath,
|
|
3761
3778
|
message: 'Questions must end with "?" (e.g., "### Should we take our own payments?")',
|
|
@@ -3769,6 +3786,15 @@ function validateIdeaOpenQuestions(filePath, content) {
|
|
|
3769
3786
|
}
|
|
3770
3787
|
if (line.startsWith("#### ")) {
|
|
3771
3788
|
currentQuestionLine = null;
|
|
3789
|
+
inOption = true;
|
|
3790
|
+
continue;
|
|
3791
|
+
}
|
|
3792
|
+
if (nonWhitespaceLine && !inOption) {
|
|
3793
|
+
violations.push({
|
|
3794
|
+
file: filePath,
|
|
3795
|
+
message: topLevelStructureMessage,
|
|
3796
|
+
line: i + 1
|
|
3797
|
+
});
|
|
3772
3798
|
}
|
|
3773
3799
|
}
|
|
3774
3800
|
if (inOpenQuestions && currentQuestionLine !== null) {
|
|
@@ -5125,6 +5151,7 @@ async function wireEntry(fsPrimitives, processPrimitives, consolePrimitives) {
|
|
|
5125
5151
|
context: {
|
|
5126
5152
|
cwd: processPrimitives.cwd(),
|
|
5127
5153
|
stdout: consolePrimitives.log,
|
|
5154
|
+
stdoutInline: consolePrimitives.write,
|
|
5128
5155
|
stderr: consolePrimitives.error
|
|
5129
5156
|
},
|
|
5130
5157
|
fileSystem,
|
|
@@ -5140,4 +5167,10 @@ await wireEntry({ existsSync, statSync: statSync2, readFile: readFile2, writeFil
|
|
|
5140
5167
|
exit: (code) => {
|
|
5141
5168
|
process.exitCode = code;
|
|
5142
5169
|
}
|
|
5143
|
-
}, {
|
|
5170
|
+
}, {
|
|
5171
|
+
log: console.log,
|
|
5172
|
+
write: (message) => {
|
|
5173
|
+
process.stdout.write(message);
|
|
5174
|
+
},
|
|
5175
|
+
error: console.error
|
|
5176
|
+
});
|
package/dist/workflow-tasks.js
CHANGED
|
@@ -111,7 +111,7 @@ async function createIdeaTask(fileSystem, dustPath, prefix, ideaSlug, openingSen
|
|
|
111
111
|
return { filePath };
|
|
112
112
|
}
|
|
113
113
|
async function createRefineIdeaTask(fileSystem, dustPath, ideaSlug, description) {
|
|
114
|
-
return createIdeaTask(fileSystem, dustPath, "Refine Idea: ", ideaSlug, (ideaTitle) => `Thoroughly research this idea and refine it into a well-defined proposal. Read the idea file, explore the codebase for relevant context, and identify any ambiguity. Where aspects are unclear or could go multiple ways, add open questions to the idea file. Review \`.dust/goals/\` for alignment and \`.dust/facts/\` for relevant design decisions. See [${ideaTitle}](../ideas/${ideaSlug}.md). If you add open questions, use \`## Open Questions\` with \`### Question?\` headings and \`#### Option\` headings, and only add questions that are meaningful decisions worth asking.`, [
|
|
114
|
+
return createIdeaTask(fileSystem, dustPath, "Refine Idea: ", ideaSlug, (ideaTitle) => `Thoroughly research this idea and refine it into a well-defined proposal. Read the idea file, explore the codebase for relevant context, and identify any ambiguity. Where aspects are unclear or could go multiple ways, add open questions to the idea file. Review \`.dust/goals/\` for alignment and \`.dust/facts/\` for relevant design decisions. See [${ideaTitle}](../ideas/${ideaSlug}.md). If you add open questions, use \`## Open Questions\` with \`### Question?\` headings and one or more \`#### Option\` headings beneath each question, and only add questions that are meaningful decisions worth asking.`, [
|
|
115
115
|
"Idea is thoroughly researched with relevant codebase context",
|
|
116
116
|
"Open questions are added for any ambiguous or underspecified aspects",
|
|
117
117
|
"Open questions follow the required heading format and focus on high-value decisions",
|
|
@@ -175,7 +175,7 @@ ${description}
|
|
|
175
175
|
const ideaPath = `.dust/ideas/${ideaFilename}`;
|
|
176
176
|
const content = `# ${taskTitle}
|
|
177
177
|
|
|
178
|
-
Research this idea thoroughly, then create an idea file at \`${ideaPath}\`. Read the codebase for relevant context, flesh out the description, and identify any ambiguity. Where aspects are unclear or could go multiple ways, add open questions to the idea file. If you add open questions, use \`## Open Questions\` with \`### Question?\` headings and \`#### Option\` headings, and only add questions that are meaningful decisions worth asking. Review \`.dust/goals/\` and \`.dust/facts/\` for relevant context.
|
|
178
|
+
Research this idea thoroughly, then create an idea file at \`${ideaPath}\`. Read the codebase for relevant context, flesh out the description, and identify any ambiguity. Where aspects are unclear or could go multiple ways, add open questions to the idea file. If you add open questions, use \`## Open Questions\` with \`### Question?\` headings and one or more \`#### Option\` headings beneath each question, and only add questions that are meaningful decisions worth asking. Review \`.dust/goals/\` and \`.dust/facts/\` for relevant context.
|
|
179
179
|
|
|
180
180
|
## Idea Description
|
|
181
181
|
|