@joshski/dust 0.1.104 → 0.1.105
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/artifacts/index.d.ts +3 -3
- package/dist/artifacts/workflow-tasks.d.ts +3 -3
- package/dist/artifacts.js +30 -55
- package/dist/dust.js +179 -184
- package/dist/patch/task.d.ts +2 -1
- package/dist/patch.js +25 -27
- package/dist/types.d.ts +1 -1
- package/dist/validation.js +8 -7
- package/package.json +1 -1
|
@@ -5,11 +5,11 @@ import { extractTitle } from '../markdown/markdown-utilities';
|
|
|
5
5
|
import { type Principle } from './principles';
|
|
6
6
|
import { type Task } from './tasks';
|
|
7
7
|
import { type ParsedArtifact, type ParsedMarkdownLink, type ParsedSection, parseArtifact } from './parsed-artifact';
|
|
8
|
-
import { type AllWorkflowTasks, CAPTURE_IDEA_PREFIX, type CreateIdeaTransitionTaskResult, type DecomposeIdeaOptions, findAllWorkflowTasks, type IdeaInProgress, type OpenQuestionResponse, type ParsedCaptureIdeaTask, parseResolvedQuestions, type TaskType, type WorkflowTaskMatch
|
|
9
|
-
export type { AllWorkflowTasks, CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, Fact, Idea, IdeaOpenQuestion, IdeaOption, OpenQuestionResponse, ParsedArtifact, ParsedCaptureIdeaTask, ParsedIdeaContent, ParsedMarkdownLink, ParsedSection, Principle, Task, TaskType, WorkflowTaskMatch,
|
|
8
|
+
import { type AllWorkflowTasks, CAPTURE_IDEA_PREFIX, type CreateIdeaTransitionTaskResult, type DecomposeIdeaOptions, findAllWorkflowTasks, type IdeaInProgress, type OpenQuestionResponse, type ParsedCaptureIdeaTask, parseResolvedQuestions, type TaskType, type WorkflowTaskMatch } from './workflow-tasks';
|
|
9
|
+
export type { AllWorkflowTasks, CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, Fact, Idea, IdeaOpenQuestion, IdeaOption, OpenQuestionResponse, ParsedArtifact, ParsedCaptureIdeaTask, ParsedIdeaContent, ParsedMarkdownLink, ParsedSection, Principle, Task, TaskType, WorkflowTaskMatch, };
|
|
10
10
|
export interface TaskGraphNode {
|
|
11
11
|
task: Task;
|
|
12
|
-
workflowType:
|
|
12
|
+
workflowType: TaskType | null;
|
|
13
13
|
}
|
|
14
14
|
export interface TaskGraph {
|
|
15
15
|
nodes: TaskGraphNode[];
|
|
@@ -21,15 +21,15 @@ export interface ParsedCaptureIdeaTask {
|
|
|
21
21
|
* 6. Add .md extension
|
|
22
22
|
*/
|
|
23
23
|
export declare function titleToFilename(title: string): string;
|
|
24
|
-
export
|
|
24
|
+
export declare const VALID_TASK_TYPES: readonly ["implement", "capture", "refine", "decompose", "shelve"];
|
|
25
|
+
export type TaskType = (typeof VALID_TASK_TYPES)[number];
|
|
25
26
|
/**
|
|
26
27
|
* Extracts and validates the task type from the ## Task Type section.
|
|
27
28
|
* Returns the task type if found and valid, null otherwise.
|
|
28
29
|
*/
|
|
29
30
|
export declare function parseTaskType(content: string): TaskType | null;
|
|
30
|
-
export type WorkflowTaskType = 'refine-idea' | 'decompose-idea' | 'shelve-idea' | 'expedite-idea';
|
|
31
31
|
export interface WorkflowTaskMatch {
|
|
32
|
-
type:
|
|
32
|
+
type: TaskType;
|
|
33
33
|
ideaSlug: string;
|
|
34
34
|
taskSlug: string;
|
|
35
35
|
resolvedQuestions: OpenQuestionResponse[];
|
package/dist/artifacts.js
CHANGED
|
@@ -556,39 +556,25 @@ function parseTaskType(content) {
|
|
|
556
556
|
}
|
|
557
557
|
return null;
|
|
558
558
|
}
|
|
559
|
-
function taskTypeToWorkflowType(taskType) {
|
|
560
|
-
switch (taskType) {
|
|
561
|
-
case "refine":
|
|
562
|
-
return "refine-idea";
|
|
563
|
-
case "decompose":
|
|
564
|
-
return "decompose-idea";
|
|
565
|
-
case "shelve":
|
|
566
|
-
return "shelve-idea";
|
|
567
|
-
case "implement":
|
|
568
|
-
return "expedite-idea";
|
|
569
|
-
default:
|
|
570
|
-
return null;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
559
|
var WORKFLOW_HINT_PATHS = {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
560
|
+
refine: "config/hints/refine-idea.md",
|
|
561
|
+
decompose: "config/hints/decompose-idea.md",
|
|
562
|
+
shelve: "config/hints/shelve-idea.md",
|
|
563
|
+
capture: "config/hints/add-idea.md",
|
|
564
|
+
implement: "config/hints/expedite-idea.md"
|
|
579
565
|
};
|
|
580
|
-
async function readWorkflowHint(fileSystem, dustPath,
|
|
581
|
-
const hintPath = `${dustPath}/${WORKFLOW_HINT_PATHS[
|
|
566
|
+
async function readWorkflowHint(fileSystem, dustPath, taskType) {
|
|
567
|
+
const hintPath = `${dustPath}/${WORKFLOW_HINT_PATHS[taskType]}`;
|
|
582
568
|
if (!fileSystem.exists(hintPath)) {
|
|
583
569
|
return null;
|
|
584
570
|
}
|
|
585
571
|
return fileSystem.readFile(hintPath);
|
|
586
572
|
}
|
|
587
573
|
var WORKFLOW_SECTION_HEADINGS = [
|
|
588
|
-
{ type: "refine
|
|
589
|
-
{ type: "decompose
|
|
590
|
-
{ type: "shelve
|
|
591
|
-
{ type: "
|
|
574
|
+
{ type: "refine", heading: "Refines Idea" },
|
|
575
|
+
{ type: "decompose", heading: "Decomposes Idea" },
|
|
576
|
+
{ type: "shelve", heading: "Shelves Idea" },
|
|
577
|
+
{ type: "implement", heading: "Expedites Idea" }
|
|
592
578
|
];
|
|
593
579
|
function extractIdeaSlugFromSection(content, sectionHeading) {
|
|
594
580
|
const lines = content.split(`
|
|
@@ -700,11 +686,17 @@ async function findWorkflowTaskForIdea(fileSystem, dustPath, ideaSlug) {
|
|
|
700
686
|
function findWorkflowMatch(content, ideaSlug, taskSlug) {
|
|
701
687
|
const taskType = parseTaskType(content);
|
|
702
688
|
if (taskType) {
|
|
703
|
-
const
|
|
704
|
-
if (
|
|
705
|
-
const
|
|
706
|
-
if (
|
|
707
|
-
return
|
|
689
|
+
const heading = WORKFLOW_SECTION_HEADINGS.find((h) => h.type === taskType)?.heading;
|
|
690
|
+
if (heading) {
|
|
691
|
+
const linkedSlug = extractIdeaSlugFromSection(content, heading);
|
|
692
|
+
if (linkedSlug === ideaSlug) {
|
|
693
|
+
return {
|
|
694
|
+
type: taskType,
|
|
695
|
+
ideaSlug,
|
|
696
|
+
taskSlug,
|
|
697
|
+
resolvedQuestions: parseResolvedQuestions(content)
|
|
698
|
+
};
|
|
699
|
+
}
|
|
708
700
|
}
|
|
709
701
|
}
|
|
710
702
|
for (const { type, heading } of WORKFLOW_SECTION_HEADINGS) {
|
|
@@ -720,22 +712,6 @@ function findWorkflowMatch(content, ideaSlug, taskSlug) {
|
|
|
720
712
|
}
|
|
721
713
|
return null;
|
|
722
714
|
}
|
|
723
|
-
function findWorkflowMatchByType(content, ideaSlug, taskSlug, workflowType) {
|
|
724
|
-
for (const { type, heading } of WORKFLOW_SECTION_HEADINGS) {
|
|
725
|
-
if (type !== workflowType)
|
|
726
|
-
continue;
|
|
727
|
-
const linkedSlug = extractIdeaSlugFromSection(content, heading);
|
|
728
|
-
if (linkedSlug === ideaSlug) {
|
|
729
|
-
return {
|
|
730
|
-
type: workflowType,
|
|
731
|
-
ideaSlug,
|
|
732
|
-
taskSlug,
|
|
733
|
-
resolvedQuestions: parseResolvedQuestions(content)
|
|
734
|
-
};
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
return null;
|
|
738
|
-
}
|
|
739
715
|
async function readIdeaTitle(fileSystem, dustPath, ideaSlug) {
|
|
740
716
|
const ideaPath = `${dustPath}/ideas/${ideaSlug}.md`;
|
|
741
717
|
if (!fileSystem.exists(ideaPath)) {
|
|
@@ -845,15 +821,14 @@ ${definitionOfDone.map((item) => `- ${item}`).join(`
|
|
|
845
821
|
`)}
|
|
846
822
|
`;
|
|
847
823
|
}
|
|
848
|
-
async function createIdeaTransitionTask(fileSystem, dustPath,
|
|
824
|
+
async function createIdeaTransitionTask(fileSystem, dustPath, taskType, prefix, ideaSlug, openingSentenceTemplate, definitionOfDone, ideaSectionHeading, taskOptions) {
|
|
849
825
|
const ideaTitle = await readIdeaTitle(fileSystem, dustPath, ideaSlug);
|
|
850
826
|
const taskTitle = `${prefix}${ideaTitle}`;
|
|
851
827
|
const filename = titleToFilename(taskTitle);
|
|
852
828
|
const filePath = `${dustPath}/tasks/${filename}`;
|
|
853
829
|
const baseOpeningSentence = openingSentenceTemplate(ideaTitle);
|
|
854
|
-
const hint = await readWorkflowHint(fileSystem, dustPath,
|
|
830
|
+
const hint = await readWorkflowHint(fileSystem, dustPath, taskType);
|
|
855
831
|
const ideaSection = { heading: ideaSectionHeading, ideaTitle, ideaSlug };
|
|
856
|
-
const taskType = workflowType === "refine-idea" ? "refine" : workflowType === "decompose-idea" ? "decompose" : workflowType === "shelve-idea" ? "shelve" : "implement";
|
|
857
832
|
const content = renderTask(taskTitle, baseOpeningSentence, definitionOfDone, ideaSection, taskType, {
|
|
858
833
|
description: taskOptions?.description,
|
|
859
834
|
resolvedQuestions: taskOptions?.resolvedQuestions,
|
|
@@ -864,7 +839,7 @@ async function createIdeaTransitionTask(fileSystem, dustPath, workflowType, pref
|
|
|
864
839
|
}
|
|
865
840
|
async function createRefineIdeaTask(fileSystem, dustPath, ideaSlug, description, openQuestionResponses, dustCommand) {
|
|
866
841
|
const cmd = dustCommand ?? "dust";
|
|
867
|
-
return createIdeaTransitionTask(fileSystem, dustPath, "refine
|
|
842
|
+
return createIdeaTransitionTask(fileSystem, dustPath, "refine", "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. Run \`${cmd} principles\` for alignment and \`${cmd} 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.`, [
|
|
868
843
|
"Idea is thoroughly researched with relevant codebase context",
|
|
869
844
|
"Open questions are added for any ambiguous or underspecified aspects",
|
|
870
845
|
"Open questions follow the required heading format and focus on high-value decisions",
|
|
@@ -876,7 +851,7 @@ async function createRefineIdeaTask(fileSystem, dustPath, ideaSlug, description,
|
|
|
876
851
|
}
|
|
877
852
|
async function decomposeIdea(fileSystem, dustPath, options, dustCommand) {
|
|
878
853
|
const cmd = dustCommand ?? "dust";
|
|
879
|
-
return createIdeaTransitionTask(fileSystem, dustPath, "decompose
|
|
854
|
+
return createIdeaTransitionTask(fileSystem, dustPath, "decompose", "Decompose Idea: ", options.ideaSlug, (ideaTitle) => `Create one or more well-defined tasks from this idea. Prefer smaller, narrowly scoped tasks that each deliver a thin but complete vertical slice of working software -- a path through the system that can be tested end-to-end -- rather than component-oriented tasks (like "add schema" or "build endpoint") that only work once all tasks are done. Split the idea into multiple tasks if it covers more than one logical change. Run \`${cmd} principles\` to link relevant principles and \`${cmd} facts\` for design decisions that should inform the task. See [${ideaTitle}](../ideas/${options.ideaSlug}.md).`, [
|
|
880
855
|
"One or more new tasks are created in .dust/tasks/",
|
|
881
856
|
"Task's Principles section links to relevant principles from .dust/principles/",
|
|
882
857
|
"The original idea is deleted or updated to reflect remaining scope"
|
|
@@ -886,11 +861,11 @@ async function decomposeIdea(fileSystem, dustPath, options, dustCommand) {
|
|
|
886
861
|
});
|
|
887
862
|
}
|
|
888
863
|
async function createShelveIdeaTask(fileSystem, dustPath, ideaSlug, description, _dustCommand) {
|
|
889
|
-
return createIdeaTransitionTask(fileSystem, dustPath, "shelve
|
|
864
|
+
return createIdeaTransitionTask(fileSystem, dustPath, "shelve", "Shelve Idea: ", ideaSlug, (ideaTitle) => `Archive this idea and remove it from the active backlog. See [${ideaTitle}](../ideas/${ideaSlug}.md).`, ["Idea file is deleted", "Rationale is recorded in the commit message"], "Shelves Idea", { description });
|
|
890
865
|
}
|
|
891
866
|
async function createExpediteIdeaTask(fileSystem, dustPath, ideaSlug, description, dustCommand) {
|
|
892
867
|
const cmd = dustCommand ?? "dust";
|
|
893
|
-
return createIdeaTransitionTask(fileSystem, dustPath, "
|
|
868
|
+
return createIdeaTransitionTask(fileSystem, dustPath, "implement", "Expedite Idea: ", ideaSlug, (ideaTitle) => `Research this idea briefly. If confident the implementation is straightforward (clear scope, minimal risk, no open questions), implement directly and commit. Otherwise, create one or more narrowly-scoped task files in \`.dust/tasks/\`. Run \`${cmd} principles\` and \`${cmd} facts\` for relevant context. See [${ideaTitle}](../ideas/${ideaSlug}.md).`, [
|
|
894
869
|
"Idea is implemented directly OR one or more new tasks are created in `.dust/tasks/`",
|
|
895
870
|
"If tasks were created, they link to relevant principles from `.dust/principles/`",
|
|
896
871
|
"Changes are committed with a clear commit message"
|
|
@@ -910,7 +885,7 @@ async function createIdeaTask(fileSystem, dustPath, options) {
|
|
|
910
885
|
const filename2 = titleToFilename(taskTitle2);
|
|
911
886
|
const filePath2 = `${dustPath}/tasks/${filename2}`;
|
|
912
887
|
const baseOpeningSentence2 = `Research this idea briefly. If confident the implementation is straightforward (clear scope, minimal risk, no open questions), implement directly and commit. Otherwise, create one or more narrowly-scoped task files in \`.dust/tasks/\`. Run \`${cmd} principles\` and \`${cmd} facts\` for relevant context.`;
|
|
913
|
-
const hint2 = await readWorkflowHint(fileSystem, dustPath, "
|
|
888
|
+
const hint2 = await readWorkflowHint(fileSystem, dustPath, "implement");
|
|
914
889
|
const repositoryHintsSection2 = renderRepositoryHintsSection(hint2 ?? undefined);
|
|
915
890
|
const content2 = `# ${taskTitle2}
|
|
916
891
|
|
|
@@ -942,7 +917,7 @@ ${repositoryHintsSection2}
|
|
|
942
917
|
const filename = titleToFilename(taskTitle);
|
|
943
918
|
const filePath = `${dustPath}/tasks/${filename}`;
|
|
944
919
|
const baseOpeningSentence = `Research this idea thoroughly, then create one or more idea files in \`.dust/ideas/\`. 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. Run \`${cmd} principles\` and \`${cmd} facts\` for relevant context.`;
|
|
945
|
-
const hint = await readWorkflowHint(fileSystem, dustPath, "
|
|
920
|
+
const hint = await readWorkflowHint(fileSystem, dustPath, "capture");
|
|
946
921
|
const repositoryHintsSection = renderRepositoryHintsSection(hint ?? undefined);
|
|
947
922
|
const content = `# ${taskTitle}
|
|
948
923
|
|
package/dist/dust.js
CHANGED
|
@@ -7,7 +7,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
7
7
|
var require_package = __commonJS((exports, module) => {
|
|
8
8
|
module.exports = {
|
|
9
9
|
name: "@joshski/dust",
|
|
10
|
-
version: "0.1.
|
|
10
|
+
version: "0.1.105",
|
|
11
11
|
description: "Flow state for AI coding agents",
|
|
12
12
|
type: "module",
|
|
13
13
|
bin: {
|
|
@@ -712,7 +712,7 @@ async function loadSettings(cwd, fileSystem, runtime) {
|
|
|
712
712
|
}
|
|
713
713
|
|
|
714
714
|
// lib/version.ts
|
|
715
|
-
var DUST_VERSION = "0.1.
|
|
715
|
+
var DUST_VERSION = "0.1.105";
|
|
716
716
|
|
|
717
717
|
// lib/cli/middleware.ts
|
|
718
718
|
function applyMiddleware(middlewares, execute) {
|
|
@@ -5153,15 +5153,183 @@ function extractFirstSentence2(paragraph) {
|
|
|
5153
5153
|
return match ? match[1] : null;
|
|
5154
5154
|
}
|
|
5155
5155
|
|
|
5156
|
-
// lib/
|
|
5157
|
-
var
|
|
5158
|
-
var
|
|
5156
|
+
// lib/artifacts/workflow-tasks.ts
|
|
5157
|
+
var CAPTURE_IDEA_PREFIX = "Add Idea: ";
|
|
5158
|
+
var EXPEDITE_IDEA_PREFIX = "Expedite Idea: ";
|
|
5159
|
+
function titleToFilename(title) {
|
|
5160
|
+
return `${title.toLowerCase().replace(/\./g, "-").replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
5161
|
+
}
|
|
5162
|
+
var VALID_TASK_TYPES = [
|
|
5159
5163
|
"implement",
|
|
5160
5164
|
"capture",
|
|
5161
5165
|
"refine",
|
|
5162
5166
|
"decompose",
|
|
5163
5167
|
"shelve"
|
|
5164
|
-
]
|
|
5168
|
+
];
|
|
5169
|
+
function parseTaskType(content) {
|
|
5170
|
+
const lines = content.split(`
|
|
5171
|
+
`);
|
|
5172
|
+
let inSection = false;
|
|
5173
|
+
let inCodeFence = false;
|
|
5174
|
+
for (const line of lines) {
|
|
5175
|
+
if (line.startsWith("```")) {
|
|
5176
|
+
inCodeFence = !inCodeFence;
|
|
5177
|
+
continue;
|
|
5178
|
+
}
|
|
5179
|
+
if (inCodeFence)
|
|
5180
|
+
continue;
|
|
5181
|
+
if (line.startsWith("## ")) {
|
|
5182
|
+
inSection = line.trimEnd() === "## Task Type";
|
|
5183
|
+
continue;
|
|
5184
|
+
}
|
|
5185
|
+
if (!inSection)
|
|
5186
|
+
continue;
|
|
5187
|
+
if (line.startsWith("# "))
|
|
5188
|
+
break;
|
|
5189
|
+
const trimmed = line.trim();
|
|
5190
|
+
if (trimmed && VALID_TASK_TYPES.includes(trimmed)) {
|
|
5191
|
+
return trimmed;
|
|
5192
|
+
}
|
|
5193
|
+
}
|
|
5194
|
+
return null;
|
|
5195
|
+
}
|
|
5196
|
+
var WORKFLOW_SECTION_HEADINGS = [
|
|
5197
|
+
{ type: "refine", heading: "Refines Idea" },
|
|
5198
|
+
{ type: "decompose", heading: "Decomposes Idea" },
|
|
5199
|
+
{ type: "shelve", heading: "Shelves Idea" },
|
|
5200
|
+
{ type: "implement", heading: "Expedites Idea" }
|
|
5201
|
+
];
|
|
5202
|
+
function extractIdeaSlugFromSection(content, sectionHeading) {
|
|
5203
|
+
const lines = content.split(`
|
|
5204
|
+
`);
|
|
5205
|
+
let inSection = false;
|
|
5206
|
+
let inCodeFence = false;
|
|
5207
|
+
for (const line of lines) {
|
|
5208
|
+
if (line.startsWith("```")) {
|
|
5209
|
+
inCodeFence = !inCodeFence;
|
|
5210
|
+
continue;
|
|
5211
|
+
}
|
|
5212
|
+
if (inCodeFence)
|
|
5213
|
+
continue;
|
|
5214
|
+
if (line.startsWith("## ")) {
|
|
5215
|
+
inSection = line.trimEnd() === `## ${sectionHeading}`;
|
|
5216
|
+
continue;
|
|
5217
|
+
}
|
|
5218
|
+
if (!inSection)
|
|
5219
|
+
continue;
|
|
5220
|
+
if (line.startsWith("# "))
|
|
5221
|
+
break;
|
|
5222
|
+
const linkMatch = line.match(MARKDOWN_LINK_PATTERN);
|
|
5223
|
+
if (linkMatch) {
|
|
5224
|
+
const target = linkMatch[2];
|
|
5225
|
+
const slugMatch = target.match(/([^/]+)\.md$/);
|
|
5226
|
+
if (slugMatch) {
|
|
5227
|
+
return slugMatch[1];
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5231
|
+
return null;
|
|
5232
|
+
}
|
|
5233
|
+
async function findAllWorkflowTasks(fileSystem, dustPath) {
|
|
5234
|
+
const tasksPath = `${dustPath}/tasks`;
|
|
5235
|
+
const captureIdeaTasks = [];
|
|
5236
|
+
const workflowTasksByIdeaSlug = new Map;
|
|
5237
|
+
if (!fileSystem.exists(tasksPath)) {
|
|
5238
|
+
return { captureIdeaTasks, workflowTasksByIdeaSlug };
|
|
5239
|
+
}
|
|
5240
|
+
const files = await fileSystem.readdir(tasksPath);
|
|
5241
|
+
for (const file of files.filter((f) => f.endsWith(".md")).toSorted()) {
|
|
5242
|
+
const content = await fileSystem.readFile(`${tasksPath}/${file}`);
|
|
5243
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
5244
|
+
if (!titleMatch)
|
|
5245
|
+
continue;
|
|
5246
|
+
const title = titleMatch[1].trim();
|
|
5247
|
+
const taskSlug = file.replace(/\.md$/, "");
|
|
5248
|
+
const taskType = parseTaskType(content);
|
|
5249
|
+
if (taskType === "capture" || taskType === "implement") {
|
|
5250
|
+
let ideaTitle = null;
|
|
5251
|
+
if (title.startsWith(CAPTURE_IDEA_PREFIX)) {
|
|
5252
|
+
ideaTitle = title.slice(CAPTURE_IDEA_PREFIX.length);
|
|
5253
|
+
} else if (title.startsWith(EXPEDITE_IDEA_PREFIX)) {
|
|
5254
|
+
ideaTitle = title.slice(EXPEDITE_IDEA_PREFIX.length);
|
|
5255
|
+
}
|
|
5256
|
+
if (ideaTitle) {
|
|
5257
|
+
captureIdeaTasks.push({
|
|
5258
|
+
taskSlug,
|
|
5259
|
+
ideaTitle
|
|
5260
|
+
});
|
|
5261
|
+
}
|
|
5262
|
+
} else if (!taskType) {
|
|
5263
|
+
if (title.startsWith(CAPTURE_IDEA_PREFIX)) {
|
|
5264
|
+
captureIdeaTasks.push({
|
|
5265
|
+
taskSlug,
|
|
5266
|
+
ideaTitle: title.slice(CAPTURE_IDEA_PREFIX.length)
|
|
5267
|
+
});
|
|
5268
|
+
} else if (title.startsWith(EXPEDITE_IDEA_PREFIX)) {
|
|
5269
|
+
captureIdeaTasks.push({
|
|
5270
|
+
taskSlug,
|
|
5271
|
+
ideaTitle: title.slice(EXPEDITE_IDEA_PREFIX.length)
|
|
5272
|
+
});
|
|
5273
|
+
}
|
|
5274
|
+
}
|
|
5275
|
+
for (const { type, heading } of WORKFLOW_SECTION_HEADINGS) {
|
|
5276
|
+
const linkedSlug = extractIdeaSlugFromSection(content, heading);
|
|
5277
|
+
if (linkedSlug) {
|
|
5278
|
+
workflowTasksByIdeaSlug.set(linkedSlug, {
|
|
5279
|
+
type,
|
|
5280
|
+
ideaSlug: linkedSlug,
|
|
5281
|
+
taskSlug,
|
|
5282
|
+
resolvedQuestions: parseResolvedQuestions(content)
|
|
5283
|
+
});
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
return { captureIdeaTasks, workflowTasksByIdeaSlug };
|
|
5288
|
+
}
|
|
5289
|
+
function parseResolvedQuestions(content) {
|
|
5290
|
+
const lines = content.split(`
|
|
5291
|
+
`);
|
|
5292
|
+
const results = [];
|
|
5293
|
+
let inSection = false;
|
|
5294
|
+
let currentQuestion = null;
|
|
5295
|
+
let inCodeFence = false;
|
|
5296
|
+
for (const line of lines) {
|
|
5297
|
+
if (line.startsWith("```")) {
|
|
5298
|
+
inCodeFence = !inCodeFence;
|
|
5299
|
+
continue;
|
|
5300
|
+
}
|
|
5301
|
+
if (inCodeFence)
|
|
5302
|
+
continue;
|
|
5303
|
+
if (line.startsWith("## ")) {
|
|
5304
|
+
inSection = line.trimEnd() === "## Resolved Questions";
|
|
5305
|
+
currentQuestion = null;
|
|
5306
|
+
continue;
|
|
5307
|
+
}
|
|
5308
|
+
if (!inSection)
|
|
5309
|
+
continue;
|
|
5310
|
+
if (line.startsWith("# "))
|
|
5311
|
+
break;
|
|
5312
|
+
if (line.startsWith("### ")) {
|
|
5313
|
+
currentQuestion = line.slice(4).trimEnd();
|
|
5314
|
+
continue;
|
|
5315
|
+
}
|
|
5316
|
+
if (currentQuestion !== null) {
|
|
5317
|
+
const decisionMatch = line.match(/^\*\*Decision:\*\*\s*(.+)$/);
|
|
5318
|
+
if (decisionMatch) {
|
|
5319
|
+
results.push({
|
|
5320
|
+
question: currentQuestion,
|
|
5321
|
+
chosenOption: decisionMatch[1].trimEnd()
|
|
5322
|
+
});
|
|
5323
|
+
currentQuestion = null;
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
return results;
|
|
5328
|
+
}
|
|
5329
|
+
|
|
5330
|
+
// lib/lint/validators/content-validator.ts
|
|
5331
|
+
var REQUIRED_TASK_HEADINGS = ["Task Type", "Blocked By", "Definition of Done"];
|
|
5332
|
+
var ALLOWED_TASK_TYPES = new Set(VALID_TASK_TYPES);
|
|
5165
5333
|
var MAX_OPENING_SENTENCE_LENGTH = 150;
|
|
5166
5334
|
var NON_IMPERATIVE_STARTERS = new Set([
|
|
5167
5335
|
"the",
|
|
@@ -9586,180 +9754,6 @@ async function parsePrinciple(fileSystem, dustPath, slug) {
|
|
|
9586
9754
|
};
|
|
9587
9755
|
}
|
|
9588
9756
|
|
|
9589
|
-
// lib/artifacts/workflow-tasks.ts
|
|
9590
|
-
var CAPTURE_IDEA_PREFIX = "Add Idea: ";
|
|
9591
|
-
var EXPEDITE_IDEA_PREFIX = "Expedite Idea: ";
|
|
9592
|
-
function titleToFilename(title) {
|
|
9593
|
-
return `${title.toLowerCase().replace(/\./g, "-").replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
9594
|
-
}
|
|
9595
|
-
var VALID_TASK_TYPES = [
|
|
9596
|
-
"implement",
|
|
9597
|
-
"capture",
|
|
9598
|
-
"refine",
|
|
9599
|
-
"decompose",
|
|
9600
|
-
"shelve"
|
|
9601
|
-
];
|
|
9602
|
-
function parseTaskType(content) {
|
|
9603
|
-
const lines = content.split(`
|
|
9604
|
-
`);
|
|
9605
|
-
let inSection = false;
|
|
9606
|
-
let inCodeFence = false;
|
|
9607
|
-
for (const line of lines) {
|
|
9608
|
-
if (line.startsWith("```")) {
|
|
9609
|
-
inCodeFence = !inCodeFence;
|
|
9610
|
-
continue;
|
|
9611
|
-
}
|
|
9612
|
-
if (inCodeFence)
|
|
9613
|
-
continue;
|
|
9614
|
-
if (line.startsWith("## ")) {
|
|
9615
|
-
inSection = line.trimEnd() === "## Task Type";
|
|
9616
|
-
continue;
|
|
9617
|
-
}
|
|
9618
|
-
if (!inSection)
|
|
9619
|
-
continue;
|
|
9620
|
-
if (line.startsWith("# "))
|
|
9621
|
-
break;
|
|
9622
|
-
const trimmed = line.trim();
|
|
9623
|
-
if (trimmed && VALID_TASK_TYPES.includes(trimmed)) {
|
|
9624
|
-
return trimmed;
|
|
9625
|
-
}
|
|
9626
|
-
}
|
|
9627
|
-
return null;
|
|
9628
|
-
}
|
|
9629
|
-
var WORKFLOW_SECTION_HEADINGS = [
|
|
9630
|
-
{ type: "refine-idea", heading: "Refines Idea" },
|
|
9631
|
-
{ type: "decompose-idea", heading: "Decomposes Idea" },
|
|
9632
|
-
{ type: "shelve-idea", heading: "Shelves Idea" },
|
|
9633
|
-
{ type: "expedite-idea", heading: "Expedites Idea" }
|
|
9634
|
-
];
|
|
9635
|
-
function extractIdeaSlugFromSection(content, sectionHeading) {
|
|
9636
|
-
const lines = content.split(`
|
|
9637
|
-
`);
|
|
9638
|
-
let inSection = false;
|
|
9639
|
-
let inCodeFence = false;
|
|
9640
|
-
for (const line of lines) {
|
|
9641
|
-
if (line.startsWith("```")) {
|
|
9642
|
-
inCodeFence = !inCodeFence;
|
|
9643
|
-
continue;
|
|
9644
|
-
}
|
|
9645
|
-
if (inCodeFence)
|
|
9646
|
-
continue;
|
|
9647
|
-
if (line.startsWith("## ")) {
|
|
9648
|
-
inSection = line.trimEnd() === `## ${sectionHeading}`;
|
|
9649
|
-
continue;
|
|
9650
|
-
}
|
|
9651
|
-
if (!inSection)
|
|
9652
|
-
continue;
|
|
9653
|
-
if (line.startsWith("# "))
|
|
9654
|
-
break;
|
|
9655
|
-
const linkMatch = line.match(MARKDOWN_LINK_PATTERN);
|
|
9656
|
-
if (linkMatch) {
|
|
9657
|
-
const target = linkMatch[2];
|
|
9658
|
-
const slugMatch = target.match(/([^/]+)\.md$/);
|
|
9659
|
-
if (slugMatch) {
|
|
9660
|
-
return slugMatch[1];
|
|
9661
|
-
}
|
|
9662
|
-
}
|
|
9663
|
-
}
|
|
9664
|
-
return null;
|
|
9665
|
-
}
|
|
9666
|
-
async function findAllWorkflowTasks(fileSystem, dustPath) {
|
|
9667
|
-
const tasksPath = `${dustPath}/tasks`;
|
|
9668
|
-
const captureIdeaTasks = [];
|
|
9669
|
-
const workflowTasksByIdeaSlug = new Map;
|
|
9670
|
-
if (!fileSystem.exists(tasksPath)) {
|
|
9671
|
-
return { captureIdeaTasks, workflowTasksByIdeaSlug };
|
|
9672
|
-
}
|
|
9673
|
-
const files = await fileSystem.readdir(tasksPath);
|
|
9674
|
-
for (const file of files.filter((f) => f.endsWith(".md")).toSorted()) {
|
|
9675
|
-
const content = await fileSystem.readFile(`${tasksPath}/${file}`);
|
|
9676
|
-
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
9677
|
-
if (!titleMatch)
|
|
9678
|
-
continue;
|
|
9679
|
-
const title = titleMatch[1].trim();
|
|
9680
|
-
const taskSlug = file.replace(/\.md$/, "");
|
|
9681
|
-
const taskType = parseTaskType(content);
|
|
9682
|
-
if (taskType === "capture" || taskType === "implement") {
|
|
9683
|
-
let ideaTitle = null;
|
|
9684
|
-
if (title.startsWith(CAPTURE_IDEA_PREFIX)) {
|
|
9685
|
-
ideaTitle = title.slice(CAPTURE_IDEA_PREFIX.length);
|
|
9686
|
-
} else if (title.startsWith(EXPEDITE_IDEA_PREFIX)) {
|
|
9687
|
-
ideaTitle = title.slice(EXPEDITE_IDEA_PREFIX.length);
|
|
9688
|
-
}
|
|
9689
|
-
if (ideaTitle) {
|
|
9690
|
-
captureIdeaTasks.push({
|
|
9691
|
-
taskSlug,
|
|
9692
|
-
ideaTitle
|
|
9693
|
-
});
|
|
9694
|
-
}
|
|
9695
|
-
} else if (!taskType) {
|
|
9696
|
-
if (title.startsWith(CAPTURE_IDEA_PREFIX)) {
|
|
9697
|
-
captureIdeaTasks.push({
|
|
9698
|
-
taskSlug,
|
|
9699
|
-
ideaTitle: title.slice(CAPTURE_IDEA_PREFIX.length)
|
|
9700
|
-
});
|
|
9701
|
-
} else if (title.startsWith(EXPEDITE_IDEA_PREFIX)) {
|
|
9702
|
-
captureIdeaTasks.push({
|
|
9703
|
-
taskSlug,
|
|
9704
|
-
ideaTitle: title.slice(EXPEDITE_IDEA_PREFIX.length)
|
|
9705
|
-
});
|
|
9706
|
-
}
|
|
9707
|
-
}
|
|
9708
|
-
for (const { type, heading } of WORKFLOW_SECTION_HEADINGS) {
|
|
9709
|
-
const linkedSlug = extractIdeaSlugFromSection(content, heading);
|
|
9710
|
-
if (linkedSlug) {
|
|
9711
|
-
workflowTasksByIdeaSlug.set(linkedSlug, {
|
|
9712
|
-
type,
|
|
9713
|
-
ideaSlug: linkedSlug,
|
|
9714
|
-
taskSlug,
|
|
9715
|
-
resolvedQuestions: parseResolvedQuestions(content)
|
|
9716
|
-
});
|
|
9717
|
-
}
|
|
9718
|
-
}
|
|
9719
|
-
}
|
|
9720
|
-
return { captureIdeaTasks, workflowTasksByIdeaSlug };
|
|
9721
|
-
}
|
|
9722
|
-
function parseResolvedQuestions(content) {
|
|
9723
|
-
const lines = content.split(`
|
|
9724
|
-
`);
|
|
9725
|
-
const results = [];
|
|
9726
|
-
let inSection = false;
|
|
9727
|
-
let currentQuestion = null;
|
|
9728
|
-
let inCodeFence = false;
|
|
9729
|
-
for (const line of lines) {
|
|
9730
|
-
if (line.startsWith("```")) {
|
|
9731
|
-
inCodeFence = !inCodeFence;
|
|
9732
|
-
continue;
|
|
9733
|
-
}
|
|
9734
|
-
if (inCodeFence)
|
|
9735
|
-
continue;
|
|
9736
|
-
if (line.startsWith("## ")) {
|
|
9737
|
-
inSection = line.trimEnd() === "## Resolved Questions";
|
|
9738
|
-
currentQuestion = null;
|
|
9739
|
-
continue;
|
|
9740
|
-
}
|
|
9741
|
-
if (!inSection)
|
|
9742
|
-
continue;
|
|
9743
|
-
if (line.startsWith("# "))
|
|
9744
|
-
break;
|
|
9745
|
-
if (line.startsWith("### ")) {
|
|
9746
|
-
currentQuestion = line.slice(4).trimEnd();
|
|
9747
|
-
continue;
|
|
9748
|
-
}
|
|
9749
|
-
if (currentQuestion !== null) {
|
|
9750
|
-
const decisionMatch = line.match(/^\*\*Decision:\*\*\s*(.+)$/);
|
|
9751
|
-
if (decisionMatch) {
|
|
9752
|
-
results.push({
|
|
9753
|
-
question: currentQuestion,
|
|
9754
|
-
chosenOption: decisionMatch[1].trimEnd()
|
|
9755
|
-
});
|
|
9756
|
-
currentQuestion = null;
|
|
9757
|
-
}
|
|
9758
|
-
}
|
|
9759
|
-
}
|
|
9760
|
-
return results;
|
|
9761
|
-
}
|
|
9762
|
-
|
|
9763
9757
|
// lib/artifacts/index.ts
|
|
9764
9758
|
var ARTIFACT_TYPES = [
|
|
9765
9759
|
"facts",
|
|
@@ -11018,13 +11012,14 @@ function getCorePrinciplesPath() {
|
|
|
11018
11012
|
// lib/cli/commands/list.ts
|
|
11019
11013
|
function workflowTypeToStatus(type) {
|
|
11020
11014
|
switch (type) {
|
|
11021
|
-
case "refine
|
|
11015
|
+
case "refine":
|
|
11022
11016
|
return "refining";
|
|
11023
|
-
case "decompose
|
|
11017
|
+
case "decompose":
|
|
11024
11018
|
return "decomposing";
|
|
11025
|
-
case "shelve
|
|
11019
|
+
case "shelve":
|
|
11026
11020
|
return "shelving";
|
|
11027
|
-
case "
|
|
11021
|
+
case "implement":
|
|
11022
|
+
case "capture":
|
|
11028
11023
|
return "expediting";
|
|
11029
11024
|
}
|
|
11030
11025
|
}
|
package/dist/patch/task.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Task serialization and patch building functions.
|
|
3
3
|
*/
|
|
4
|
+
import type { TaskType } from '../artifacts/workflow-tasks';
|
|
4
5
|
export interface StandardTaskInput {
|
|
5
6
|
type?: undefined;
|
|
6
7
|
title: string;
|
|
@@ -10,7 +11,7 @@ export interface StandardTaskInput {
|
|
|
10
11
|
definitionOfDone: string[];
|
|
11
12
|
}
|
|
12
13
|
export interface WorkflowTaskInput {
|
|
13
|
-
type: 'capture
|
|
14
|
+
type: Extract<TaskType, 'capture' | 'refine' | 'decompose' | 'shelve'>;
|
|
14
15
|
ideaSlug: string;
|
|
15
16
|
definitionOfDone?: string[];
|
|
16
17
|
}
|
package/dist/patch.js
CHANGED
|
@@ -142,6 +142,13 @@ function extractFirstSentence(paragraph) {
|
|
|
142
142
|
function titleToFilename(title) {
|
|
143
143
|
return `${title.toLowerCase().replace(/\./g, "-").replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
144
144
|
}
|
|
145
|
+
var VALID_TASK_TYPES = [
|
|
146
|
+
"implement",
|
|
147
|
+
"capture",
|
|
148
|
+
"refine",
|
|
149
|
+
"decompose",
|
|
150
|
+
"shelve"
|
|
151
|
+
];
|
|
145
152
|
|
|
146
153
|
// lib/artifacts/index.ts
|
|
147
154
|
var ARTIFACT_TYPES = [
|
|
@@ -237,13 +244,7 @@ function validateAuditHeadings(artifact) {
|
|
|
237
244
|
|
|
238
245
|
// lib/lint/validators/content-validator.ts
|
|
239
246
|
var REQUIRED_TASK_HEADINGS = ["Task Type", "Blocked By", "Definition of Done"];
|
|
240
|
-
var ALLOWED_TASK_TYPES = new Set(
|
|
241
|
-
"implement",
|
|
242
|
-
"capture",
|
|
243
|
-
"refine",
|
|
244
|
-
"decompose",
|
|
245
|
-
"shelve"
|
|
246
|
-
]);
|
|
247
|
+
var ALLOWED_TASK_TYPES = new Set(VALID_TASK_TYPES);
|
|
247
248
|
var MAX_OPENING_SENTENCE_LENGTH = 150;
|
|
248
249
|
var NON_IMPERATIVE_STARTERS = new Set([
|
|
249
250
|
"the",
|
|
@@ -1115,30 +1116,28 @@ function buildPrincipleFiles(input, slug) {
|
|
|
1115
1116
|
|
|
1116
1117
|
// lib/patch/task.ts
|
|
1117
1118
|
var WORKFLOW_SECTION_HEADINGS = {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1119
|
+
capture: "Captures Idea",
|
|
1120
|
+
refine: "Refines Idea",
|
|
1121
|
+
decompose: "Decomposes Idea",
|
|
1122
|
+
shelve: "Shelves Idea"
|
|
1122
1123
|
};
|
|
1123
1124
|
var WORKFLOW_TITLE_PREFIXES = {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1125
|
+
capture: "Add Idea: ",
|
|
1126
|
+
refine: "Refine Idea: ",
|
|
1127
|
+
decompose: "Decompose Idea: ",
|
|
1128
|
+
shelve: "Shelve Idea: "
|
|
1128
1129
|
};
|
|
1129
1130
|
var WORKFLOW_OPENING_SENTENCES = {
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1131
|
+
capture: "Research this idea thoroughly and create an idea file.",
|
|
1132
|
+
refine: "Thoroughly research this idea and refine it into a well-defined proposal.",
|
|
1133
|
+
decompose: "Create one or more well-defined tasks from this idea.",
|
|
1134
|
+
shelve: "Archive this idea and remove it from the active backlog."
|
|
1134
1135
|
};
|
|
1135
1136
|
var WORKFLOW_DEFAULT_DEFINITION_OF_DONE = {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
]
|
|
1140
|
-
"decompose-idea": ["One or more new tasks are created in .dust/tasks/"],
|
|
1141
|
-
"shelve-idea": ["Idea file is deleted"]
|
|
1137
|
+
capture: ["Idea file is created in .dust/ideas/"],
|
|
1138
|
+
refine: ["Idea is thoroughly researched with relevant codebase context"],
|
|
1139
|
+
decompose: ["One or more new tasks are created in .dust/tasks/"],
|
|
1140
|
+
shelve: ["Idea file is deleted"]
|
|
1142
1141
|
};
|
|
1143
1142
|
function ideaSlugToTitle(slug) {
|
|
1144
1143
|
return slug.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -1200,7 +1199,6 @@ function serializeWorkflowTask(input) {
|
|
|
1200
1199
|
const ideaSection = `## ${sectionHeading}
|
|
1201
1200
|
|
|
1202
1201
|
- [${ideaTitle}](../ideas/${input.ideaSlug}.md)`;
|
|
1203
|
-
const taskType = input.type === "capture-idea" ? "capture" : input.type === "refine-idea" ? "refine" : input.type === "decompose-idea" ? "decompose" : "shelve";
|
|
1204
1202
|
return `# ${title}
|
|
1205
1203
|
|
|
1206
1204
|
${openingSentence}
|
|
@@ -1209,7 +1207,7 @@ ${ideaSection}
|
|
|
1209
1207
|
|
|
1210
1208
|
## Task Type
|
|
1211
1209
|
|
|
1212
|
-
${
|
|
1210
|
+
${input.type}
|
|
1213
1211
|
|
|
1214
1212
|
## Blocked By
|
|
1215
1213
|
|
package/dist/types.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type { AgentSessionEvent, EventMessage } from './agent-events';
|
|
|
8
8
|
export type { Idea, IdeaOpenQuestion, IdeaOption, ParsedIdeaContent, } from './artifacts/ideas';
|
|
9
9
|
export type { ArtifactType, TaskGraph, TaskGraphNode } from './artifacts/index';
|
|
10
10
|
export type { Task } from './artifacts/tasks';
|
|
11
|
-
export type { CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, IdeaInProgress, OpenQuestionResponse, ParsedCaptureIdeaTask, WorkflowTaskMatch,
|
|
11
|
+
export type { CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, IdeaInProgress, OpenQuestionResponse, ParsedCaptureIdeaTask, WorkflowTaskMatch, } from './artifacts/workflow-tasks';
|
|
12
12
|
export type { Repository } from './bucket/repository';
|
|
13
13
|
export type { ToolExecutionErrorResult, ToolExecutionRequestMessage, ToolExecutionResult, ToolExecutionResultMessage, ToolExecutionSuccessResult, ToolExecutionToolNotFoundResult, } from './bucket/tool-execution-protocol';
|
|
14
14
|
export { isToolExecutionRequestMessage, isToolExecutionResultMessage, } from './bucket/tool-execution-protocol';
|
package/dist/validation.js
CHANGED
|
@@ -207,6 +207,13 @@ function extractFirstSentence(paragraph) {
|
|
|
207
207
|
function titleToFilename(title) {
|
|
208
208
|
return `${title.toLowerCase().replace(/\./g, "-").replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}.md`;
|
|
209
209
|
}
|
|
210
|
+
var VALID_TASK_TYPES = [
|
|
211
|
+
"implement",
|
|
212
|
+
"capture",
|
|
213
|
+
"refine",
|
|
214
|
+
"decompose",
|
|
215
|
+
"shelve"
|
|
216
|
+
];
|
|
210
217
|
|
|
211
218
|
// lib/artifacts/index.ts
|
|
212
219
|
var ARTIFACT_TYPES = [
|
|
@@ -234,13 +241,7 @@ function validateAuditHeadings(artifact) {
|
|
|
234
241
|
|
|
235
242
|
// lib/lint/validators/content-validator.ts
|
|
236
243
|
var REQUIRED_TASK_HEADINGS = ["Task Type", "Blocked By", "Definition of Done"];
|
|
237
|
-
var ALLOWED_TASK_TYPES = new Set(
|
|
238
|
-
"implement",
|
|
239
|
-
"capture",
|
|
240
|
-
"refine",
|
|
241
|
-
"decompose",
|
|
242
|
-
"shelve"
|
|
243
|
-
]);
|
|
244
|
+
var ALLOWED_TASK_TYPES = new Set(VALID_TASK_TYPES);
|
|
244
245
|
var MAX_OPENING_SENTENCE_LENGTH = 150;
|
|
245
246
|
var NON_IMPERATIVE_STARTERS = new Set([
|
|
246
247
|
"the",
|