clawspec 1.0.15 → 1.0.16

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawspec",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin that orchestrates OpenSpec project workflows with visible main-agent execution.",
6
6
  "keywords": [
@@ -1,3 +1,4 @@
1
+
1
2
  export type ClawSpecKeywordKind =
2
3
  | "plan"
3
4
  | "work"
@@ -59,11 +60,26 @@ export function extractEmbeddedClawSpecKeyword(text: string): ClawSpecKeywordInt
59
60
  return direct;
60
61
  }
61
62
 
62
- for (const line of text.split(/\r?\n/)) {
63
- const parsed = parseClawSpecKeyword(line.trim());
63
+ const lines = text.split(/\r?\n/);
64
+ for (const line of lines) {
65
+ const trimmed = line.trim();
66
+ if (!trimmed) continue;
67
+
68
+
69
+ // Try parsing the whole line first
70
+ const parsed = parseClawSpecKeyword(trimmed);
64
71
  if (parsed) {
65
72
  return parsed;
66
73
  }
74
+
75
+ // Try each word in the line
76
+ const words = trimmed.split(/\s+/);
77
+ for (const word of words) {
78
+ const wordParsed = parseClawSpecKeyword(word);
79
+ if (wordParsed) {
80
+ return wordParsed;
81
+ }
82
+ }
67
83
  }
68
84
 
69
85
  return null;
@@ -6,7 +6,6 @@ import type {
6
6
  PluginCommandResult,
7
7
  PluginLogger,
8
8
  } from "openclaw/plugin-sdk";
9
- import { debugLog } from "../utils/debug-log.ts";
10
9
  import { ProjectMemoryStore } from "../memory/store.ts";
11
10
  import { OpenSpecClient, OpenSpecCommandError } from "../openspec/cli.ts";
12
11
  import { parseTasksFile } from "../openspec/tasks.ts";
@@ -250,9 +249,7 @@ export class ClawSpecService {
250
249
  event: PromptBuildEvent,
251
250
  ctx: PromptBuildContext,
252
251
  ): Promise<{ prependContext?: string; prependSystemContext?: string } | void> {
253
- debugLog(`[handleBeforePromptBuild] prompt="${event.prompt}", trigger=${ctx.trigger}`);
254
252
  if (!shouldHandleUserVisiblePrompt(ctx.trigger)) {
255
- debugLog(`[handleBeforePromptBuild] Skipped: non-user trigger`);
256
253
  this.logger.debug?.(
257
254
  `[clawspec] skipping prompt injection for non-user trigger "${ctx.trigger ?? "unknown"}".`,
258
255
  );
@@ -260,7 +257,6 @@ export class ClawSpecService {
260
257
  }
261
258
 
262
259
  const keyword = extractEmbeddedClawSpecKeyword(event.prompt);
263
- debugLog(`[handleBeforePromptBuild] keyword=${keyword?.command}`);
264
260
  if (keyword) {
265
261
  this.logger.debug?.(
266
262
  `[clawspec] detected control keyword "${keyword.command}" for prompt build (session=${ctx.sessionKey ?? "unknown"}).`,
@@ -320,21 +316,16 @@ export class ClawSpecService {
320
316
 
321
317
  switch (keyword.kind) {
322
318
  case "plan": {
323
- debugLog(`[cs-plan] Triggered for project: ${match?.project.changeName}`);
324
319
  if (!match?.project.repoPath || !match.project.changeName) {
325
- debugLog(`[cs-plan] Missing repoPath or changeName`);
326
320
  return this.buildPluginReplyInjection(
327
321
  event.prompt,
328
322
  "Select a project and create a change first with `/clawspec use <project-name>` and `/clawspec proposal <change-name> [description]`.",
329
323
  );
330
324
  }
331
- debugLog(`[cs-plan] Calling startVisiblePlanningSync`);
332
325
  const planningSync = await this.startVisiblePlanningSync(match.channelKey, match.project, ctx, event.prompt, "apply");
333
326
  if ("prependContext" in planningSync || "prependSystemContext" in planningSync) {
334
- debugLog(`[cs-plan] Returning prompt injection`);
335
327
  return planningSync;
336
328
  }
337
- debugLog(`[cs-plan] Returning plugin reply`);
338
329
  return this.buildPluginReplyInjection(event.prompt, planningSync.text ?? "");
339
330
  }
340
331
  case "work":
@@ -767,19 +758,16 @@ export class ClawSpecService {
767
758
  userPrompt: string,
768
759
  mode: ExecutionMode,
769
760
  ): Promise<{ prependContext?: string; prependSystemContext?: string } | PluginCommandResult> {
770
- debugLog(`[startVisiblePlanningSync] Called for ${project.changeName}`);
771
761
  this.logger.info(`[clawspec] startVisiblePlanningSync called for ${project.changeName}`);
772
762
  void project;
773
763
  void mode;
774
764
 
775
765
  const prepared = await this.preparePlanningSync(channelKey);
776
766
  if ("result" in prepared) {
777
- debugLog(`[startVisiblePlanningSync] preparePlanningSync failed`);
778
767
  this.logger.warn(`[clawspec] preparePlanningSync returned error: ${prepared.result.text}`);
779
768
  return prepared.result;
780
769
  }
781
770
 
782
- debugLog(`[startVisiblePlanningSync] Updating state to planning`);
783
771
  const startedAt = new Date().toISOString();
784
772
  const runningProject = await this.stateStore.updateProject(channelKey, (current) => ({
785
773
  ...current,
@@ -793,7 +781,6 @@ export class ClawSpecService {
793
781
  execution: undefined,
794
782
  lastExecutionAt: startedAt,
795
783
  }));
796
- debugLog(`[startVisiblePlanningSync] State updated: status=${runningProject.status}, phase=${runningProject.phase}, sessionKey=${runningProject.boundSessionKey}`);
797
784
  this.logger.info(`[clawspec] Project state updated: status=planning, phase=planning_sync, boundSessionKey=${runningProject.boundSessionKey}`);
798
785
 
799
786
  return await this.buildPlanningSyncInjection(runningProject, userPrompt, prepared.instructionResults);
@@ -912,7 +899,6 @@ export class ClawSpecService {
912
899
  }
913
900
 
914
901
  async handleAgentEnd(event: AgentEndEvent, ctx: PromptBuildContext): Promise<void> {
915
- debugLog(`[agent_end] Called, sessionKey=${ctx.sessionKey}`);
916
902
  const runningProject = await this.findRunningProjectBySessionKey(ctx.sessionKey);
917
903
  if (runningProject?.repoPath && runningProject.changeName) {
918
904
  const project = runningProject;
@@ -977,9 +963,7 @@ export class ClawSpecService {
977
963
 
978
964
  const planningProject = await this.findPlanningProjectBySessionKey(ctx.sessionKey)
979
965
  ?? await this.findPlanningProjectByContext(ctx);
980
- debugLog(`[agent_end] Planning project: ${planningProject?.changeName}, status=${planningProject?.status}, phase=${planningProject?.phase}`);
981
966
  if (planningProject) {
982
- debugLog(`[agent_end] Calling finalizePlanningTurn`);
983
967
  this.logger.info(`[clawspec] agent_end: found planning project ${planningProject.changeName}, calling finalizePlanningTurn`);
984
968
  await this.finalizePlanningTurn(planningProject, event);
985
969
  return;
@@ -2428,10 +2412,8 @@ export class ClawSpecService {
2428
2412
  }
2429
2413
 
2430
2414
  private async finalizePlanningTurn(project: ProjectState, event: AgentEndEvent): Promise<void> {
2431
- debugLog(`[finalizePlanningTurn] Called for ${project.changeName}, success=${event.success}`);
2432
2415
  this.logger.info(`[clawspec] finalizePlanningTurn called for ${project.changeName}, success=${event.success}`);
2433
2416
  if (!project.repoPath || !project.changeName) {
2434
- debugLog(`[finalizePlanningTurn] Skipped: missing repoPath or changeName`);
2435
2417
  this.logger.warn(`[clawspec] finalizePlanningTurn skipped: missing repoPath or changeName`);
2436
2418
  return;
2437
2419
  }
@@ -2491,9 +2473,7 @@ export class ClawSpecService {
2491
2473
  }
2492
2474
  }
2493
2475
 
2494
- debugLog(`[finalizePlanningTurn] Writing snapshot`);
2495
2476
  const snapshot = await journalStore.writeSnapshot(repoStatePaths.planningJournalSnapshotFile, project.changeName, timestamp);
2496
- debugLog(`[finalizePlanningTurn] Snapshot written: entryCount=${snapshot.entryCount}, lastEntryAt=${snapshot.lastEntryAt}`);
2497
2477
  this.logger.info(`[clawspec] Planning snapshot written for ${project.changeName}: entryCount=${snapshot.entryCount}, lastEntryAt=${snapshot.lastEntryAt}`);
2498
2478
  this.logger.info(`[clawspec] Updating project state: status=${status}, phase=${phase}, dirty=${journalDirty}`);
2499
2479
  await this.writeLatestSummary(repoStatePaths, latestSummary);
@@ -50,6 +50,7 @@ export class ClawSpecNotifier {
50
50
  });
51
51
  return;
52
52
  default:
53
+ // Webchat and other channels: log only (no direct API available)
53
54
  this.logger.info(`[clawspec] watcher update (${route.channel} ${route.channelId}): ${text}`);
54
55
  }
55
56
  } catch (error) {
@@ -1,14 +0,0 @@
1
- import { appendFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import path from "node:path";
4
-
5
- const LOG_FILE = path.join(homedir(), ".openclaw", "clawspec-debug.log");
6
-
7
- export function debugLog(message: string): void {
8
- try {
9
- const timestamp = new Date().toISOString();
10
- appendFileSync(LOG_FILE, `${timestamp} ${message}\n`);
11
- } catch {
12
- // ignore
13
- }
14
- }