clawspec 1.0.6 → 1.0.7
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/package.json
CHANGED
|
@@ -587,6 +587,7 @@ export class ClawSpecService {
|
|
|
587
587
|
scaffoldOnly: planningContext.scaffoldOnly,
|
|
588
588
|
mode: "sync",
|
|
589
589
|
prefetchedInstructions: instructionResults.map((result) => result.parsed!).filter(Boolean),
|
|
590
|
+
prefetchedInstructionCommands: instructionResults.map((result) => result.command).filter(Boolean),
|
|
590
591
|
}),
|
|
591
592
|
};
|
|
592
593
|
}
|
package/src/worker/prompts.ts
CHANGED
|
@@ -179,6 +179,7 @@ export function buildPlanningPrependContext(params: {
|
|
|
179
179
|
mode: "discussion" | "sync";
|
|
180
180
|
nextActionHint?: "plan" | "work";
|
|
181
181
|
prefetchedInstructions?: OpenSpecInstructionsResponse[];
|
|
182
|
+
prefetchedInstructionCommands?: string[];
|
|
182
183
|
}): string {
|
|
183
184
|
const project = params.project;
|
|
184
185
|
|
|
@@ -198,6 +199,7 @@ export function buildPlanningPrependContext(params: {
|
|
|
198
199
|
"10. Stop after planning artifacts are refreshed and apply-ready. Do not implement code in this turn.",
|
|
199
200
|
"11. End with a concise summary and a mandatory final line exactly in this shape: `Next: run `cs-work` to start implementation.`",
|
|
200
201
|
"12. Never scan sibling directories under `openspec/changes`, never switch to another change, and never restore or rewrite unrelated files.",
|
|
202
|
+
"13. Do not claim that OpenSpec instructions were skipped in this sync turn. The plugin already executed those commands before this turn began.",
|
|
201
203
|
]
|
|
202
204
|
: [
|
|
203
205
|
"Discussion rules for this turn:",
|
|
@@ -243,6 +245,15 @@ export function buildPlanningPrependContext(params: {
|
|
|
243
245
|
`- ${instruction.artifactId}: ${displayPath(resolveProjectScopedPath(project, instruction.outputPath))}`,
|
|
244
246
|
)
|
|
245
247
|
: []),
|
|
248
|
+
...(params.mode === "sync"
|
|
249
|
+
? (params.prefetchedInstructions ?? []).flatMap((instruction) => [
|
|
250
|
+
"",
|
|
251
|
+
formatPrefetchedInstructionBlock(project, instruction),
|
|
252
|
+
])
|
|
253
|
+
: []),
|
|
254
|
+
params.mode === "sync" ? "" : "",
|
|
255
|
+
params.mode === "sync" ? "OpenSpec commands already executed by the plugin before this turn:" : "",
|
|
256
|
+
...(params.mode === "sync" ? (params.prefetchedInstructionCommands ?? []).map((command) => `- ${command}`) : []),
|
|
246
257
|
params.scaffoldOnly ? "" : "",
|
|
247
258
|
params.scaffoldOnly ? "Only the change scaffold exists right now. That is expected before planning sync generates the first artifacts." : "",
|
|
248
259
|
"",
|
|
@@ -503,3 +514,17 @@ function relativeChangeFile(project: ProjectState, targetPath: string): string {
|
|
|
503
514
|
function displayPath(targetPath: string): string {
|
|
504
515
|
return targetPath.split(path.sep).join("/");
|
|
505
516
|
}
|
|
517
|
+
|
|
518
|
+
function formatPrefetchedInstructionBlock(
|
|
519
|
+
project: ProjectState,
|
|
520
|
+
instruction: OpenSpecInstructionsResponse,
|
|
521
|
+
): string {
|
|
522
|
+
const outputPath = displayPath(resolveProjectScopedPath(project, instruction.outputPath));
|
|
523
|
+
return [
|
|
524
|
+
`Artifact ${instruction.artifactId} (output: ${outputPath})`,
|
|
525
|
+
"Instruction:",
|
|
526
|
+
fence(instruction.instruction || "(empty)", "markdown"),
|
|
527
|
+
"Template:",
|
|
528
|
+
fence(instruction.template || "(empty)", "markdown"),
|
|
529
|
+
].join("\n");
|
|
530
|
+
}
|
|
@@ -133,7 +133,7 @@ test("apply reports no new planning notes when the chat context is detached", as
|
|
|
133
133
|
|
|
134
134
|
test("cs-plan runs visible planning sync and writes a fresh snapshot", async () => {
|
|
135
135
|
const harness = await createServiceHarness("clawspec-visible-plan-");
|
|
136
|
-
const { service, stateStore, repoPath } = harness;
|
|
136
|
+
const { service, stateStore, repoPath, openSpec } = harness;
|
|
137
137
|
const channelKey = "discord:visible-plan:default:main";
|
|
138
138
|
const promptContext = {
|
|
139
139
|
trigger: "user",
|
|
@@ -149,6 +149,13 @@ test("cs-plan runs visible planning sync and writes a fresh snapshot", async ()
|
|
|
149
149
|
await service.proposalProject(channelKey, "demo-change Demo change");
|
|
150
150
|
await service.recordPlanningMessageFromContext(promptContext, "add another API endpoint");
|
|
151
151
|
|
|
152
|
+
const instructionCalls: string[] = [];
|
|
153
|
+
const originalInstructionsArtifact = openSpec.instructionsArtifact;
|
|
154
|
+
openSpec.instructionsArtifact = async (...args: unknown[]) => {
|
|
155
|
+
instructionCalls.push(String(args[1]));
|
|
156
|
+
return await originalInstructionsArtifact(...args);
|
|
157
|
+
};
|
|
158
|
+
|
|
152
159
|
const injected = await service.handleBeforePromptBuild(
|
|
153
160
|
{ prompt: "cs-plan", messages: [] },
|
|
154
161
|
promptContext,
|
|
@@ -157,7 +164,10 @@ test("cs-plan runs visible planning sync and writes a fresh snapshot", async ()
|
|
|
157
164
|
|
|
158
165
|
assert.match(injected?.prependContext ?? "", /ClawSpec planning sync is active for this turn/);
|
|
159
166
|
assert.match(injected?.prependContext ?? "", /Prefetched OpenSpec instructions for this turn/);
|
|
167
|
+
assert.match(injected?.prependContext ?? "", /OpenSpec commands already executed by the plugin before this turn/);
|
|
168
|
+
assert.match(injected?.prependContext ?? "", /openspec instructions proposal --change demo-change --json/);
|
|
160
169
|
assert.match(injected?.prependContext ?? "", /planning-instructions[\\/]+proposal\.json/);
|
|
170
|
+
assert.deepEqual(instructionCalls, ["proposal", "specs", "design", "tasks"]);
|
|
161
171
|
assert.match(injected?.prependContext ?? "", /mandatory final line exactly in this shape/i);
|
|
162
172
|
assert.equal(runningProject?.status, "planning");
|
|
163
173
|
assert.equal(runningProject?.phase, "planning_sync");
|