@waycraft/waypoint-mcp 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 +110 -0
- package/dist/context.js +79 -0
- package/dist/index.js +46 -0
- package/dist/tools/audit.js +311 -0
- package/dist/tools/build.js +112 -0
- package/dist/tools/compare.js +92 -0
- package/dist/tools/debug.js +148 -0
- package/dist/tools/design.js +276 -0
- package/dist/tools/document.js +107 -0
- package/dist/tools/fix.js +103 -0
- package/dist/tools/goal.js +94 -0
- package/dist/tools/improve.js +99 -0
- package/dist/tools/measure.js +101 -0
- package/dist/tools/plan.js +107 -0
- package/dist/tools/research.js +104 -0
- package/dist/tools/review.js +123 -0
- package/dist/tools/test.js +107 -0
- package/package.json +38 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_fix",
|
|
4
|
+
description: "Targeted bug patches with minimal footprint.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
bug: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Description of the bug to fix (optional). Omit to review existing fix.md.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ["workspacePath"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export async function run(args) {
|
|
21
|
+
const { workspacePath, bug } = args;
|
|
22
|
+
const ctx = await getBaseContext(workspacePath);
|
|
23
|
+
const buildArtifact = await getArtifact(workspacePath, "build.md");
|
|
24
|
+
const goalArtifact = await getArtifact(workspacePath, "goal.md");
|
|
25
|
+
const existingFix = await getArtifact(workspacePath, "fix.md");
|
|
26
|
+
if (!bug && !existingFix) {
|
|
27
|
+
return [
|
|
28
|
+
"## waypoint_fix — No bug description provided",
|
|
29
|
+
"",
|
|
30
|
+
"Call `waypoint_fix` with a `bug` parameter describing the problem.",
|
|
31
|
+
"Example: _\"Tool returns isError:true when workspacePath has spaces\"_",
|
|
32
|
+
"",
|
|
33
|
+
!buildArtifact ? "Run `waypoint_build` first to establish a build baseline." : "",
|
|
34
|
+
]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join("\n");
|
|
37
|
+
}
|
|
38
|
+
const bugStatement = bug ?? existingFix?.match(/^## Bug\n+(.+)/m)?.[1] ?? "(bug not parsed)";
|
|
39
|
+
const goalLine = goalArtifact?.match(/^# Goal\n+(.+)/m)?.[1] ?? "(goal not parsed)";
|
|
40
|
+
const hasBuild = !!buildArtifact;
|
|
41
|
+
const artifact = [
|
|
42
|
+
"# Fix",
|
|
43
|
+
"",
|
|
44
|
+
`## Bug`,
|
|
45
|
+
bugStatement,
|
|
46
|
+
"",
|
|
47
|
+
`**Goal context:** ${goalLine}`,
|
|
48
|
+
!hasBuild ? "\n> ⚠️ No build.md found — fix has no established baseline." : "",
|
|
49
|
+
"",
|
|
50
|
+
"## Root cause hypothesis",
|
|
51
|
+
"<!-- What is causing this bug? Be specific. -->",
|
|
52
|
+
"- ",
|
|
53
|
+
"",
|
|
54
|
+
"## Fix approach",
|
|
55
|
+
"**Principle:** minimal footprint — change only what is necessary to fix this bug.",
|
|
56
|
+
"",
|
|
57
|
+
"### AI fix prompt",
|
|
58
|
+
"```",
|
|
59
|
+
`Fix the following bug: ${bugStatement}`,
|
|
60
|
+
"",
|
|
61
|
+
"Constraints:",
|
|
62
|
+
"- Change only the code required to fix this specific bug",
|
|
63
|
+
"- Do not refactor surrounding code",
|
|
64
|
+
"- Do not add features or improve unrelated behavior",
|
|
65
|
+
"- Verify the fix does not break adjacent functionality",
|
|
66
|
+
"```",
|
|
67
|
+
"",
|
|
68
|
+
"## Changes made",
|
|
69
|
+
"<!-- List exact files and lines changed -->",
|
|
70
|
+
"| File | Line(s) | Change |",
|
|
71
|
+
"|------|---------|--------|",
|
|
72
|
+
"| | | |",
|
|
73
|
+
"",
|
|
74
|
+
"## Verification",
|
|
75
|
+
"- [ ] Bug no longer reproduced with original steps",
|
|
76
|
+
"- [ ] No regressions in adjacent functionality",
|
|
77
|
+
"- [ ] Fix is the minimum change required",
|
|
78
|
+
"",
|
|
79
|
+
`_Generated by waypoint_fix — ${new Date().toISOString()}_`,
|
|
80
|
+
]
|
|
81
|
+
.filter((l) => l !== undefined)
|
|
82
|
+
.join("\n");
|
|
83
|
+
await saveArtifact(workspacePath, "fix.md", artifact);
|
|
84
|
+
return [
|
|
85
|
+
"## waypoint_fix — Fix guide generated",
|
|
86
|
+
"",
|
|
87
|
+
`**Bug:** ${bugStatement}`,
|
|
88
|
+
!hasBuild ? "\n> No build.md found — fix has no baseline context." : "",
|
|
89
|
+
"",
|
|
90
|
+
"### Approach",
|
|
91
|
+
"- Minimal footprint: only change what fixes this bug",
|
|
92
|
+
"- AI fix prompt included — paste into Claude Code or Cursor",
|
|
93
|
+
"- Verification checklist: confirm no regressions",
|
|
94
|
+
"",
|
|
95
|
+
"### Artifact saved",
|
|
96
|
+
"`fix.md` written to `.waypoint/fix.md`.",
|
|
97
|
+
"",
|
|
98
|
+
"### Suggested next step",
|
|
99
|
+
"Run `waypoint_test` after applying the fix to confirm no regressions.",
|
|
100
|
+
]
|
|
101
|
+
.filter((l) => l !== undefined)
|
|
102
|
+
.join("\n");
|
|
103
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_goal",
|
|
4
|
+
description: "Define or refine the project goal. Analyzes existing code and business logic if present.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
goal: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "The goal to define or refine. Omit to review an existing goal.md.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ["workspacePath"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export async function run(args) {
|
|
21
|
+
const { workspacePath, goal } = args;
|
|
22
|
+
const ctx = await getBaseContext(workspacePath);
|
|
23
|
+
const existing = await getArtifact(workspacePath, "goal.md");
|
|
24
|
+
const goalStatement = goal ?? existing?.match(/^# Goal\n+(.+)/m)?.[1] ?? null;
|
|
25
|
+
const workspaceSummary = [
|
|
26
|
+
`**Path:** ${workspacePath}`,
|
|
27
|
+
ctx.packageJson
|
|
28
|
+
? `**Package:** ${(() => {
|
|
29
|
+
try {
|
|
30
|
+
const p = JSON.parse(ctx.packageJson);
|
|
31
|
+
return `${p.name ?? "unnamed"} v${p.version ?? "?"}`;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return "present (unparseable)";
|
|
35
|
+
}
|
|
36
|
+
})()}`
|
|
37
|
+
: "**Package:** none detected",
|
|
38
|
+
`**Files (2 levels):**\n\`\`\`\n${ctx.fileTree}\n\`\`\``,
|
|
39
|
+
Object.keys(ctx.waypointArtifacts).length > 0
|
|
40
|
+
? `**Existing .waypoint artifacts:** ${Object.keys(ctx.waypointArtifacts).join(", ")}`
|
|
41
|
+
: "**Existing .waypoint artifacts:** none",
|
|
42
|
+
].join("\n");
|
|
43
|
+
if (!goalStatement) {
|
|
44
|
+
return [
|
|
45
|
+
"## waypoint_goal — No goal defined yet",
|
|
46
|
+
"",
|
|
47
|
+
"### Workspace snapshot",
|
|
48
|
+
workspaceSummary,
|
|
49
|
+
"",
|
|
50
|
+
"### Next step",
|
|
51
|
+
"Call `waypoint_goal` again with a `goal` parameter describing what you want to achieve.",
|
|
52
|
+
"Example: _\"Add user authentication with email/password and OAuth\"_",
|
|
53
|
+
"",
|
|
54
|
+
"A clear goal should answer:",
|
|
55
|
+
"- What capability or outcome are we delivering?",
|
|
56
|
+
"- Who benefits and how?",
|
|
57
|
+
"- What does done look like?",
|
|
58
|
+
].join("\n");
|
|
59
|
+
}
|
|
60
|
+
const artifact = [
|
|
61
|
+
"# Goal",
|
|
62
|
+
"",
|
|
63
|
+
goalStatement,
|
|
64
|
+
"",
|
|
65
|
+
"## Success criteria",
|
|
66
|
+
"<!-- Define 2-4 measurable outcomes that confirm this goal is met -->",
|
|
67
|
+
"- [ ] ",
|
|
68
|
+
"",
|
|
69
|
+
"## Out of scope",
|
|
70
|
+
"<!-- Explicitly list what this goal does NOT cover -->",
|
|
71
|
+
"- ",
|
|
72
|
+
"",
|
|
73
|
+
"## Workspace observations",
|
|
74
|
+
workspaceSummary,
|
|
75
|
+
"",
|
|
76
|
+
`_Generated by waypoint_goal — ${new Date().toISOString()}_`,
|
|
77
|
+
].join("\n");
|
|
78
|
+
await saveArtifact(workspacePath, "goal.md", artifact);
|
|
79
|
+
return [
|
|
80
|
+
"## waypoint_goal — Goal captured",
|
|
81
|
+
"",
|
|
82
|
+
`**Goal:** ${goalStatement}`,
|
|
83
|
+
"",
|
|
84
|
+
"### Workspace snapshot",
|
|
85
|
+
workspaceSummary,
|
|
86
|
+
"",
|
|
87
|
+
"### Artifact saved",
|
|
88
|
+
"`goal.md` written to `.waypoint/goal.md`.",
|
|
89
|
+
"Fill in **Success criteria** and **Out of scope** before moving to `waypoint_research`.",
|
|
90
|
+
"",
|
|
91
|
+
"### Suggested next step",
|
|
92
|
+
"Run `waypoint_research` to surface best practices and open questions for this goal.",
|
|
93
|
+
].join("\n");
|
|
94
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_improve",
|
|
4
|
+
description: "Propose refinements. Distinguish must-haves from optional enhancements.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
area: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Specific area to improve (optional). Omit to generate improvements across all areas.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ["workspacePath"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export async function run(args) {
|
|
21
|
+
const { workspacePath, area } = args;
|
|
22
|
+
const ctx = await getBaseContext(workspacePath);
|
|
23
|
+
const goalArtifact = await getArtifact(workspacePath, "goal.md");
|
|
24
|
+
const measureArtifact = await getArtifact(workspacePath, "measure.md");
|
|
25
|
+
const buildArtifact = await getArtifact(workspacePath, "build.md");
|
|
26
|
+
if (!goalArtifact) {
|
|
27
|
+
return [
|
|
28
|
+
"## waypoint_improve — No goal found",
|
|
29
|
+
"",
|
|
30
|
+
"Run `waypoint_goal` first — improvements require a defined goal to improve toward.",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
33
|
+
const goalLine = goalArtifact.match(/^# Goal\n+(.+)/m)?.[1] ?? "(goal not parsed)";
|
|
34
|
+
const hasMeasure = !!measureArtifact;
|
|
35
|
+
const artifact = [
|
|
36
|
+
"# Improve",
|
|
37
|
+
"",
|
|
38
|
+
`**Goal:** ${goalLine}`,
|
|
39
|
+
area ? `**Area:** ${area}` : "",
|
|
40
|
+
!hasMeasure
|
|
41
|
+
? "\n> ⚠️ No measure.md found — running `waypoint_measure` first gives better improvement signals."
|
|
42
|
+
: "",
|
|
43
|
+
"",
|
|
44
|
+
"## Must-have improvements",
|
|
45
|
+
"<!-- Fixes that affect correctness, reliability, or core usability — do these now -->",
|
|
46
|
+
"- [ ] ",
|
|
47
|
+
"",
|
|
48
|
+
"## Should-have improvements",
|
|
49
|
+
"<!-- Meaningful quality improvements — do before next major release -->",
|
|
50
|
+
"- [ ] ",
|
|
51
|
+
"",
|
|
52
|
+
"## Nice-to-have enhancements",
|
|
53
|
+
"<!-- Optional upgrades — only if time and priority allow -->",
|
|
54
|
+
"- [ ] ",
|
|
55
|
+
"",
|
|
56
|
+
"## Out of scope",
|
|
57
|
+
"<!-- Improvements explicitly not being pursued and why -->",
|
|
58
|
+
"- ",
|
|
59
|
+
"",
|
|
60
|
+
"## Improvement prompts for AI coding tools",
|
|
61
|
+
"",
|
|
62
|
+
"### Refactor prompt",
|
|
63
|
+
"```",
|
|
64
|
+
`Improve the following area without changing behavior: ${area ?? goalLine}`,
|
|
65
|
+
"",
|
|
66
|
+
"Constraints:",
|
|
67
|
+
"- Do not change externally observable behavior",
|
|
68
|
+
"- Keep changes focused on the area being improved",
|
|
69
|
+
"- Prefer simplicity over cleverness",
|
|
70
|
+
"```",
|
|
71
|
+
"",
|
|
72
|
+
`_Generated by waypoint_improve — ${new Date().toISOString()}_`,
|
|
73
|
+
]
|
|
74
|
+
.filter((l) => l !== undefined)
|
|
75
|
+
.join("\n");
|
|
76
|
+
await saveArtifact(workspacePath, "improve.md", artifact);
|
|
77
|
+
return [
|
|
78
|
+
"## waypoint_improve — Improvement plan generated",
|
|
79
|
+
"",
|
|
80
|
+
`**Goal:** ${goalLine}`,
|
|
81
|
+
area ? `**Area:** ${area}` : "",
|
|
82
|
+
!hasMeasure
|
|
83
|
+
? "\n> No measure.md found — run `waypoint_measure` for data-driven improvements."
|
|
84
|
+
: "",
|
|
85
|
+
"",
|
|
86
|
+
"### Three tiers",
|
|
87
|
+
"- **Must-have** — correctness and reliability issues; do these now",
|
|
88
|
+
"- **Should-have** — meaningful quality improvements; do before next release",
|
|
89
|
+
"- **Nice-to-have** — optional enhancements; defer unless time allows",
|
|
90
|
+
"",
|
|
91
|
+
"### Artifact saved",
|
|
92
|
+
"`improve.md` written to `.waypoint/improve.md`.",
|
|
93
|
+
"",
|
|
94
|
+
"### Suggested next step",
|
|
95
|
+
"Run `waypoint_document` to document the improved state, or `waypoint_review` for a final quality check.",
|
|
96
|
+
]
|
|
97
|
+
.filter((l) => l !== undefined)
|
|
98
|
+
.join("\n");
|
|
99
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_measure",
|
|
4
|
+
description: "Evaluate overall project success against defined goals.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ["workspacePath"],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
export async function run(args) {
|
|
17
|
+
const { workspacePath } = args;
|
|
18
|
+
const ctx = await getBaseContext(workspacePath);
|
|
19
|
+
const goalArtifact = await getArtifact(workspacePath, "goal.md");
|
|
20
|
+
const buildArtifact = await getArtifact(workspacePath, "build.md");
|
|
21
|
+
const testArtifact = await getArtifact(workspacePath, "test.md");
|
|
22
|
+
if (!goalArtifact) {
|
|
23
|
+
return [
|
|
24
|
+
"## waypoint_measure — No goal found",
|
|
25
|
+
"",
|
|
26
|
+
"Run `waypoint_goal` first — measurement requires a defined goal to evaluate against.",
|
|
27
|
+
].join("\n");
|
|
28
|
+
}
|
|
29
|
+
const goalLine = goalArtifact.match(/^# Goal\n+(.+)/m)?.[1] ?? "(goal not parsed)";
|
|
30
|
+
const successCriteriaBlock = goalArtifact.match(/## Success criteria\n([\s\S]*?)(?=\n##|$)/)?.[1]?.trim() ?? "";
|
|
31
|
+
const criteriaLines = successCriteriaBlock
|
|
32
|
+
.split("\n")
|
|
33
|
+
.filter((l) => l.trim().startsWith("- ["))
|
|
34
|
+
.map((l) => l.trim());
|
|
35
|
+
const criteriaRows = criteriaLines.length > 0
|
|
36
|
+
? criteriaLines.map((c) => `| ${c} | | |`)
|
|
37
|
+
: ["| - (no criteria defined in goal.md) | | |"];
|
|
38
|
+
const missing = [
|
|
39
|
+
!buildArtifact && "build.md",
|
|
40
|
+
!testArtifact && "test.md",
|
|
41
|
+
].filter(Boolean);
|
|
42
|
+
const artifact = [
|
|
43
|
+
"# Measure",
|
|
44
|
+
"",
|
|
45
|
+
`**Goal:** ${goalLine}`,
|
|
46
|
+
missing.length > 0
|
|
47
|
+
? `\n> ⚠️ Missing: ${missing.join(", ")} — measurement may be incomplete.`
|
|
48
|
+
: "",
|
|
49
|
+
"",
|
|
50
|
+
"## Success criteria scorecard",
|
|
51
|
+
"| Criterion | Status | Evidence |",
|
|
52
|
+
"|-----------|--------|----------|",
|
|
53
|
+
...criteriaRows,
|
|
54
|
+
"",
|
|
55
|
+
"## Overall verdict",
|
|
56
|
+
"<!-- One of: ✅ Goal met | ⚠️ Partially met | ❌ Not met -->",
|
|
57
|
+
"**Verdict:** ",
|
|
58
|
+
"**Summary:** ",
|
|
59
|
+
"",
|
|
60
|
+
"## What worked well",
|
|
61
|
+
"- ",
|
|
62
|
+
"",
|
|
63
|
+
"## What fell short",
|
|
64
|
+
"- ",
|
|
65
|
+
"",
|
|
66
|
+
"## Quantitative signals",
|
|
67
|
+
"<!-- Add any measurable data: test pass rate, latency, bundle size, etc. -->",
|
|
68
|
+
"| Metric | Target | Actual | Pass? |",
|
|
69
|
+
"|--------|--------|--------|-------|",
|
|
70
|
+
"| | | | |",
|
|
71
|
+
"",
|
|
72
|
+
`_Generated by waypoint_measure — ${new Date().toISOString()}_`,
|
|
73
|
+
]
|
|
74
|
+
.filter((l) => l !== undefined)
|
|
75
|
+
.join("\n");
|
|
76
|
+
await saveArtifact(workspacePath, "measure.md", artifact);
|
|
77
|
+
return [
|
|
78
|
+
"## waypoint_measure — Measurement framework generated",
|
|
79
|
+
"",
|
|
80
|
+
`**Goal:** ${goalLine}`,
|
|
81
|
+
missing.length > 0 ? `\n> Missing: ${missing.join(", ")} — add these for fuller measurement.` : "",
|
|
82
|
+
"",
|
|
83
|
+
criteriaLines.length > 0
|
|
84
|
+
? `**${criteriaLines.length} success criteria** pulled from goal.md into scorecard.`
|
|
85
|
+
: "**No success criteria found in goal.md.** Fill in the scorecard manually.",
|
|
86
|
+
"",
|
|
87
|
+
"### How to use measure.md",
|
|
88
|
+
"1. Score each criterion: ✅ met / ⚠️ partial / ❌ not met",
|
|
89
|
+
"2. Add evidence for each",
|
|
90
|
+
"3. Record quantitative signals where available",
|
|
91
|
+
"4. Write the overall verdict",
|
|
92
|
+
"",
|
|
93
|
+
"### Artifact saved",
|
|
94
|
+
"`measure.md` written to `.waypoint/measure.md`.",
|
|
95
|
+
"",
|
|
96
|
+
"### Suggested next step",
|
|
97
|
+
"Run `waypoint_improve` to identify refinements based on what fell short.",
|
|
98
|
+
]
|
|
99
|
+
.filter((l) => l !== undefined)
|
|
100
|
+
.join("\n");
|
|
101
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_plan",
|
|
4
|
+
description: "Create a structured plan for new features or significant changes only.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
scope: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Specific scope or milestone to plan (optional). Omit to plan the full goal.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ["workspacePath"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export async function run(args) {
|
|
21
|
+
const { workspacePath, scope } = args;
|
|
22
|
+
const ctx = await getBaseContext(workspacePath);
|
|
23
|
+
const goalArtifact = await getArtifact(workspacePath, "goal.md");
|
|
24
|
+
const optionsArtifact = await getArtifact(workspacePath, "compare.md");
|
|
25
|
+
const researchArtifact = await getArtifact(workspacePath, "research.md");
|
|
26
|
+
if (!goalArtifact) {
|
|
27
|
+
return [
|
|
28
|
+
"## waypoint_plan — No goal found",
|
|
29
|
+
"",
|
|
30
|
+
"Run `waypoint_goal` before planning.",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
33
|
+
const goalLine = goalArtifact.match(/^# Goal\n+(.+)/m)?.[1] ?? "(goal not parsed)";
|
|
34
|
+
const missing = [
|
|
35
|
+
!researchArtifact && "research.md",
|
|
36
|
+
!optionsArtifact && "compare.md",
|
|
37
|
+
].filter(Boolean);
|
|
38
|
+
const artifact = [
|
|
39
|
+
"# Plan",
|
|
40
|
+
"",
|
|
41
|
+
`**Goal:** ${goalLine}`,
|
|
42
|
+
scope ? `**Scope:** ${scope}` : "",
|
|
43
|
+
missing.length > 0
|
|
44
|
+
? `\n> ⚠️ Missing prior artifacts: ${missing.join(", ")}. Plan may be incomplete.`
|
|
45
|
+
: "",
|
|
46
|
+
"",
|
|
47
|
+
"## Milestones",
|
|
48
|
+
"<!-- Break the work into 2–5 ordered milestones -->",
|
|
49
|
+
"",
|
|
50
|
+
"### Milestone 1 — Foundation",
|
|
51
|
+
"**Deliverable:** ",
|
|
52
|
+
"**Done when:** ",
|
|
53
|
+
"**Steps:**",
|
|
54
|
+
"- [ ] ",
|
|
55
|
+
"",
|
|
56
|
+
"### Milestone 2 — Core feature",
|
|
57
|
+
"**Deliverable:** ",
|
|
58
|
+
"**Done when:** ",
|
|
59
|
+
"**Steps:**",
|
|
60
|
+
"- [ ] ",
|
|
61
|
+
"",
|
|
62
|
+
"### Milestone 3 — Polish & ship",
|
|
63
|
+
"**Deliverable:** ",
|
|
64
|
+
"**Done when:** ",
|
|
65
|
+
"**Steps:**",
|
|
66
|
+
"- [ ] ",
|
|
67
|
+
"",
|
|
68
|
+
"## Dependencies",
|
|
69
|
+
"<!-- External dependencies or blockers between milestones -->",
|
|
70
|
+
"- ",
|
|
71
|
+
"",
|
|
72
|
+
"## Out of scope for this plan",
|
|
73
|
+
"- ",
|
|
74
|
+
"",
|
|
75
|
+
"## Risk register",
|
|
76
|
+
"| Risk | Likelihood | Impact | Mitigation |",
|
|
77
|
+
"|------|-----------|--------|------------|",
|
|
78
|
+
"| | | | |",
|
|
79
|
+
"",
|
|
80
|
+
`_Generated by waypoint_plan — ${new Date().toISOString()}_`,
|
|
81
|
+
]
|
|
82
|
+
.filter((l) => l !== undefined)
|
|
83
|
+
.join("\n");
|
|
84
|
+
await saveArtifact(workspacePath, "plan.md", artifact);
|
|
85
|
+
return [
|
|
86
|
+
"## waypoint_plan — Plan generated",
|
|
87
|
+
"",
|
|
88
|
+
`**Goal:** ${goalLine}`,
|
|
89
|
+
scope ? `**Scope:** ${scope}` : "",
|
|
90
|
+
missing.length > 0
|
|
91
|
+
? `\n> Missing: ${missing.join(", ")} — plan may be incomplete.`
|
|
92
|
+
: "",
|
|
93
|
+
"",
|
|
94
|
+
"### Structure",
|
|
95
|
+
"- **3 milestones** scaffolded — fill in deliverables, done-when criteria, and steps",
|
|
96
|
+
"- **Risk register** — add any known risks before building",
|
|
97
|
+
"- **Dependencies** — note anything that must be resolved first",
|
|
98
|
+
"",
|
|
99
|
+
"### Artifact saved",
|
|
100
|
+
"`plan.md` written to `.waypoint/plan.md`.",
|
|
101
|
+
"",
|
|
102
|
+
"### Suggested next step",
|
|
103
|
+
"Run `waypoint_build` to scaffold implementation from this plan.",
|
|
104
|
+
]
|
|
105
|
+
.filter((l) => l !== undefined)
|
|
106
|
+
.join("\n");
|
|
107
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { getBaseContext, getArtifact, saveArtifact } from "../context.js";
|
|
2
|
+
export const definition = {
|
|
3
|
+
name: "waypoint_research",
|
|
4
|
+
description: "Gather best practices, surface the right questions, explore the solution space.",
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
workspacePath: {
|
|
9
|
+
type: "string",
|
|
10
|
+
description: "Absolute path to the workspace root.",
|
|
11
|
+
},
|
|
12
|
+
topic: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Specific research focus (optional). Omit to research the full goal.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ["workspacePath"],
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
export async function run(args) {
|
|
21
|
+
const { workspacePath, topic } = args;
|
|
22
|
+
const ctx = await getBaseContext(workspacePath);
|
|
23
|
+
const goalArtifact = await getArtifact(workspacePath, "goal.md");
|
|
24
|
+
if (!goalArtifact) {
|
|
25
|
+
return [
|
|
26
|
+
"## waypoint_research — No goal found",
|
|
27
|
+
"",
|
|
28
|
+
"Run `waypoint_goal` first to define the project goal before researching.",
|
|
29
|
+
].join("\n");
|
|
30
|
+
}
|
|
31
|
+
const goalLine = goalArtifact.match(/^# Goal\n+(.+)/m)?.[1] ?? "(goal not parsed)";
|
|
32
|
+
const focus = topic ?? goalLine;
|
|
33
|
+
const artifact = [
|
|
34
|
+
"# Research",
|
|
35
|
+
"",
|
|
36
|
+
`**Goal:** ${goalLine}`,
|
|
37
|
+
topic ? `**Focus:** ${topic}` : "",
|
|
38
|
+
"",
|
|
39
|
+
"## Key questions to answer",
|
|
40
|
+
"<!-- What must be understood before committing to a design? -->",
|
|
41
|
+
"- What existing solutions or libraries handle this well?",
|
|
42
|
+
"- What constraints (performance, security, compatibility) apply?",
|
|
43
|
+
"- What has failed in similar past attempts?",
|
|
44
|
+
"- What unknowns could invalidate the plan?",
|
|
45
|
+
"",
|
|
46
|
+
"## Areas to investigate",
|
|
47
|
+
"",
|
|
48
|
+
"### Prior art & libraries",
|
|
49
|
+
"- [ ] Survey existing libraries and tools relevant to the goal",
|
|
50
|
+
"- [ ] Review documentation and known limitations",
|
|
51
|
+
"",
|
|
52
|
+
"### Architecture & patterns",
|
|
53
|
+
"- [ ] Identify applicable design patterns",
|
|
54
|
+
"- [ ] Assess integration points with existing code",
|
|
55
|
+
"",
|
|
56
|
+
"### Risks & constraints",
|
|
57
|
+
"- [ ] List technical risks",
|
|
58
|
+
"- [ ] Note hard constraints (runtime, platform, team)",
|
|
59
|
+
"",
|
|
60
|
+
"### Open decisions",
|
|
61
|
+
"<!-- Questions that will need to be resolved in waypoint_compare -->",
|
|
62
|
+
"- [ ] ",
|
|
63
|
+
"",
|
|
64
|
+
"## Workspace observations",
|
|
65
|
+
`**Path:** ${workspacePath}`,
|
|
66
|
+
ctx.packageJson
|
|
67
|
+
? (() => {
|
|
68
|
+
try {
|
|
69
|
+
const p = JSON.parse(ctx.packageJson);
|
|
70
|
+
return `**Package:** ${p.name ?? "unnamed"} v${p.version ?? "?"}`;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return "**Package:** present (unparseable)";
|
|
74
|
+
}
|
|
75
|
+
})()
|
|
76
|
+
: "**Package:** none detected",
|
|
77
|
+
"",
|
|
78
|
+
`_Generated by waypoint_research — ${new Date().toISOString()}_`,
|
|
79
|
+
]
|
|
80
|
+
.filter((l) => l !== undefined)
|
|
81
|
+
.join("\n");
|
|
82
|
+
await saveArtifact(workspacePath, "research.md", artifact);
|
|
83
|
+
return [
|
|
84
|
+
"## waypoint_research — Research brief generated",
|
|
85
|
+
"",
|
|
86
|
+
`**Goal:** ${goalLine}`,
|
|
87
|
+
topic ? `**Focus:** ${topic}` : "",
|
|
88
|
+
"",
|
|
89
|
+
"### What to investigate",
|
|
90
|
+
"1. **Prior art & libraries** — survey what exists, note limitations",
|
|
91
|
+
"2. **Architecture & patterns** — find applicable patterns, assess fit",
|
|
92
|
+
"3. **Risks & constraints** — surface blockers early",
|
|
93
|
+
"4. **Open decisions** — list what must be resolved before planning",
|
|
94
|
+
"",
|
|
95
|
+
"### Artifact saved",
|
|
96
|
+
"`research.md` written to `.waypoint/research.md`.",
|
|
97
|
+
"Fill in findings before moving forward.",
|
|
98
|
+
"",
|
|
99
|
+
"### Suggested next step",
|
|
100
|
+
"Run `waypoint_compare` to turn research findings into concrete decision tradeoffs.",
|
|
101
|
+
]
|
|
102
|
+
.filter((l) => l !== undefined)
|
|
103
|
+
.join("\n");
|
|
104
|
+
}
|