clawspec 1.0.11 → 1.0.13

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.11",
3
+ "version": "1.0.13",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin that orchestrates OpenSpec project workflows with visible main-agent execution.",
6
6
  "keywords": [
@@ -961,6 +961,7 @@ export class ClawSpecService {
961
961
  const planningProject = await this.findPlanningProjectBySessionKey(ctx.sessionKey)
962
962
  ?? await this.findPlanningProjectByContext(ctx);
963
963
  if (planningProject) {
964
+ this.logger.info(`[clawspec] agent_end: found planning project ${planningProject.changeName}, calling finalizePlanningTurn`);
964
965
  await this.finalizePlanningTurn(planningProject, event);
965
966
  return;
966
967
  }
@@ -2408,7 +2409,9 @@ export class ClawSpecService {
2408
2409
  }
2409
2410
 
2410
2411
  private async finalizePlanningTurn(project: ProjectState, event: AgentEndEvent): Promise<void> {
2412
+ this.logger.info(`[clawspec] finalizePlanningTurn called for ${project.changeName}, success=${event.success}`);
2411
2413
  if (!project.repoPath || !project.changeName) {
2414
+ this.logger.warn(`[clawspec] finalizePlanningTurn skipped: missing repoPath or changeName`);
2412
2415
  return;
2413
2416
  }
2414
2417
 
@@ -2467,12 +2470,9 @@ export class ClawSpecService {
2467
2470
  }
2468
2471
  }
2469
2472
 
2470
- await journalStore.writeSnapshot(repoStatePaths.planningJournalSnapshotFile, project.changeName, timestamp);
2471
- const writtenSnapshot = await journalStore.readSnapshot(repoStatePaths.planningJournalSnapshotFile);
2472
- const currentDigest = await journalStore.digest(project.changeName);
2473
- this.logger.info(`[clawspec] Planning snapshot written for ${project.changeName}:`);
2474
- this.logger.info(` - Snapshot: entryCount=${writtenSnapshot?.entryCount}, lastEntryAt=${writtenSnapshot?.lastEntryAt}, hash=${writtenSnapshot?.contentHash?.slice(0, 8)}`);
2475
- this.logger.info(` - Current digest: entryCount=${currentDigest.entryCount}, lastEntryAt=${currentDigest.lastEntryAt}, hash=${currentDigest.contentHash.slice(0, 8)}`);
2473
+ const snapshot = await journalStore.writeSnapshot(repoStatePaths.planningJournalSnapshotFile, project.changeName, timestamp);
2474
+ this.logger.info(`[clawspec] Planning snapshot written for ${project.changeName}: entryCount=${snapshot.entryCount}, lastEntryAt=${snapshot.lastEntryAt}`);
2475
+ this.logger.info(`[clawspec] Updating project state: status=${status}, phase=${phase}, dirty=${journalDirty}`);
2476
2476
  await this.writeLatestSummary(repoStatePaths, latestSummary);
2477
2477
 
2478
2478
  const finalized = await this.stateStore.updateProject(project.channelKey, (current) => ({
@@ -2489,8 +2489,8 @@ export class ClawSpecService {
2489
2489
  boundSessionKey: current.boundSessionKey,
2490
2490
  planningJournal: {
2491
2491
  dirty: journalDirty,
2492
- entryCount: current.planningJournal?.entryCount ?? 0,
2493
- lastEntryAt: current.planningJournal?.lastEntryAt,
2492
+ entryCount: snapshot.entryCount,
2493
+ lastEntryAt: snapshot.lastEntryAt,
2494
2494
  lastSyncedAt,
2495
2495
  },
2496
2496
  }));
@@ -122,3 +122,34 @@ test("snapshot correctly captures all journal entries including assistant messag
122
122
  assert.equal(snapshot.lastEntryAt, digest.lastEntryAt);
123
123
  assert.equal(snapshot.contentHash, digest.contentHash);
124
124
  });
125
+
126
+ test("snapshot sync after cs-plan, add requirement, cs-plan again", async () => {
127
+ const tempRoot = await mkdtemp(path.join(os.tmpdir(), "clawspec-replan-"));
128
+ const journalPath = path.join(tempRoot, "planning-journal.jsonl");
129
+ const snapshotPath = path.join(tempRoot, "planning-journal.snapshot.json");
130
+ const store = new PlanningJournalStore(journalPath);
131
+
132
+ await store.append({
133
+ timestamp: "2026-03-27T06:00:00.000Z",
134
+ changeName: "test",
135
+ role: "user",
136
+ text: "initial requirement",
137
+ });
138
+
139
+ const snapshot1 = await store.writeSnapshot(snapshotPath, "test", "2026-03-27T06:05:00.000Z");
140
+ assert.equal(snapshot1.entryCount, 1);
141
+ assert.equal(await store.hasUnsyncedChanges("test", snapshotPath), false);
142
+
143
+ await store.append({
144
+ timestamp: "2026-03-27T06:10:00.000Z",
145
+ changeName: "test",
146
+ role: "user",
147
+ text: "additional requirement",
148
+ });
149
+
150
+ assert.equal(await store.hasUnsyncedChanges("test", snapshotPath), true);
151
+
152
+ const snapshot2 = await store.writeSnapshot(snapshotPath, "test", "2026-03-27T06:15:00.000Z");
153
+ assert.equal(snapshot2.entryCount, 2);
154
+ assert.equal(await store.hasUnsyncedChanges("test", snapshotPath), false);
155
+ });