parallax-opencode 0.3.6 → 0.3.8

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/plugin.js CHANGED
@@ -96,7 +96,41 @@ function loadConfig() {
96
96
  // State persistence (Phase 2.1)
97
97
  // ---------------------------------------------------------------------------
98
98
  let stateDebounceTimer = null;
99
- function writeState() {
99
+ function flushState() {
100
+ try {
101
+ const s = getFriction();
102
+ const m = getMode();
103
+ const p = getProtocol();
104
+ const state = {
105
+ sessionId: currentSessionId,
106
+ sessionStart: getTrace(sessionId()).session.startedAt,
107
+ mode: m.mode,
108
+ friction: {
109
+ successes: s.successes,
110
+ trials: s.trials,
111
+ retriesLeft: s.retriesLeft,
112
+ lastObservation: s.lastObservation,
113
+ },
114
+ protocol: {
115
+ ambiguityDone: p.ambiguityDone,
116
+ invariantsDone: p.invariantsDone,
117
+ gateDone: p.gateDone,
118
+ designDone: p.designDone,
119
+ commitDone: p.commitDone,
120
+ summaryDone: p.summaryDone,
121
+ writesBeforeGate: p.writesBeforeGate,
122
+ gateBlocked: p.gateBlocked,
123
+ },
124
+ };
125
+ writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), "utf8");
126
+ }
127
+ catch { }
128
+ }
129
+ function writeState(immediate = false) {
130
+ if (immediate) {
131
+ flushState();
132
+ return;
133
+ }
100
134
  if (stateDebounceTimer)
101
135
  clearTimeout(stateDebounceTimer);
102
136
  stateDebounceTimer = setTimeout(() => {
@@ -104,7 +138,10 @@ function writeState() {
104
138
  try {
105
139
  const s = getFriction();
106
140
  const m = getMode();
107
- const p = getProtocol();
141
+ // Read from disk: OpenCode may load plugin in different contexts
142
+ // for tools vs hooks, causing separate in-memory Maps.
143
+ const diskState = readProtocolFromDisk();
144
+ const p = diskState || getProtocol();
108
145
  const state = {
109
146
  sessionId: currentSessionId,
110
147
  sessionStart: getTrace(sessionId()).session.startedAt,
@@ -134,6 +171,31 @@ function writeState() {
134
171
  }, STATE_DEBOUNCE_MS);
135
172
  }
136
173
  // ---------------------------------------------------------------------------
174
+ // Read protocol state from disk (write hook reads this, not in-memory Maps)
175
+ // ---------------------------------------------------------------------------
176
+ function readProtocolFromDisk() {
177
+ try {
178
+ if (existsSync(STATE_FILE)) {
179
+ const raw = readFileSync(STATE_FILE, "utf8");
180
+ const s = JSON.parse(raw);
181
+ if (s && s.protocol) {
182
+ return {
183
+ ambiguityDone: s.protocol.ambiguityDone === true,
184
+ invariantsDone: s.protocol.invariantsDone === true,
185
+ gateDone: s.protocol.gateDone === true,
186
+ designDone: s.protocol.designDone === true,
187
+ commitDone: s.protocol.commitDone === true,
188
+ summaryDone: s.protocol.summaryDone === true,
189
+ writesBeforeGate: typeof s.protocol.writesBeforeGate === "number" ? s.protocol.writesBeforeGate : 0,
190
+ gateBlocked: s.protocol.gateBlocked === true,
191
+ };
192
+ }
193
+ }
194
+ }
195
+ catch { }
196
+ return null;
197
+ }
198
+ // ---------------------------------------------------------------------------
137
199
  // Skill loader
138
200
  // ---------------------------------------------------------------------------
139
201
  const skillCache = {};
@@ -258,7 +320,7 @@ export default {
258
320
  if (step === "ambiguity" && !p.ambiguityDone) {
259
321
  p.ambiguityDone = true;
260
322
  addPhase(sid, "ambiguity_check");
261
- writeState();
323
+ writeState(true);
262
324
  return "[parallax] Step 1/6: Ambiguity Check marked complete.";
263
325
  }
264
326
  if (step === "invariants") {
@@ -267,7 +329,7 @@ export default {
267
329
  }
268
330
  p.invariantsDone = true;
269
331
  addPhase(sid, "four_invariants");
270
- writeState();
332
+ writeState(true);
271
333
  return "[parallax] Step 2/6: 4 Invariants marked complete.";
272
334
  }
273
335
  if (step === "gate") {
@@ -276,7 +338,7 @@ export default {
276
338
  }
277
339
  p.gateDone = true;
278
340
  addPhase(sid, "verification_gate");
279
- writeState();
341
+ writeState(true);
280
342
  return "[parallax] Step 3/6: Verification Gate marked complete.";
281
343
  }
282
344
  if (step === "design") {
@@ -285,19 +347,19 @@ export default {
285
347
  }
286
348
  p.designDone = true;
287
349
  addPhase(sid, "design_check");
288
- writeState();
350
+ writeState(true);
289
351
  return "[parallax] Step 4/6: Design Doc marked complete.";
290
352
  }
291
353
  if (step === "commit") {
292
354
  p.commitDone = true;
293
355
  addPhase(sid, "commit_decision");
294
- writeState();
356
+ writeState(true);
295
357
  return "[parallax] Step 5/6: Commit Decision marked complete.";
296
358
  }
297
359
  if (step === "summary") {
298
360
  p.summaryDone = true;
299
361
  addPhase(sid, "summary");
300
- writeState();
362
+ writeState(true);
301
363
  // Phase 2.3: Post-session retrospective
302
364
  const trace = getTrace(sid);
303
365
  const breakdown = computeCoherenceScore(trace);
@@ -287,14 +287,49 @@ function loadConfig() {
287
287
  return configCache || {};
288
288
  }
289
289
  var stateDebounceTimer = null;
290
- function writeState() {
290
+ function flushState() {
291
+ try {
292
+ const s = getFriction();
293
+ const m = getMode();
294
+ const p = getProtocol();
295
+ const state = {
296
+ sessionId: currentSessionId,
297
+ sessionStart: getTrace(sessionId()).session.startedAt,
298
+ mode: m.mode,
299
+ friction: {
300
+ successes: s.successes,
301
+ trials: s.trials,
302
+ retriesLeft: s.retriesLeft,
303
+ lastObservation: s.lastObservation
304
+ },
305
+ protocol: {
306
+ ambiguityDone: p.ambiguityDone,
307
+ invariantsDone: p.invariantsDone,
308
+ gateDone: p.gateDone,
309
+ designDone: p.designDone,
310
+ commitDone: p.commitDone,
311
+ summaryDone: p.summaryDone,
312
+ writesBeforeGate: p.writesBeforeGate,
313
+ gateBlocked: p.gateBlocked
314
+ }
315
+ };
316
+ writeFileSync2(STATE_FILE, JSON.stringify(state, null, 2), "utf8");
317
+ } catch {
318
+ }
319
+ }
320
+ function writeState(immediate = false) {
321
+ if (immediate) {
322
+ flushState();
323
+ return;
324
+ }
291
325
  if (stateDebounceTimer) clearTimeout(stateDebounceTimer);
292
326
  stateDebounceTimer = setTimeout(() => {
293
327
  stateDebounceTimer = null;
294
328
  try {
295
329
  const s = getFriction();
296
330
  const m = getMode();
297
- const p = getProtocol();
331
+ const diskState = readProtocolFromDisk();
332
+ const p = diskState || getProtocol();
298
333
  const state = {
299
334
  sessionId: currentSessionId,
300
335
  sessionStart: getTrace(sessionId()).session.startedAt,
@@ -321,6 +356,28 @@ function writeState() {
321
356
  }
322
357
  }, STATE_DEBOUNCE_MS);
323
358
  }
359
+ function readProtocolFromDisk() {
360
+ try {
361
+ if (existsSync3(STATE_FILE)) {
362
+ const raw = readFileSync2(STATE_FILE, "utf8");
363
+ const s = JSON.parse(raw);
364
+ if (s && s.protocol) {
365
+ return {
366
+ ambiguityDone: s.protocol.ambiguityDone === true,
367
+ invariantsDone: s.protocol.invariantsDone === true,
368
+ gateDone: s.protocol.gateDone === true,
369
+ designDone: s.protocol.designDone === true,
370
+ commitDone: s.protocol.commitDone === true,
371
+ summaryDone: s.protocol.summaryDone === true,
372
+ writesBeforeGate: typeof s.protocol.writesBeforeGate === "number" ? s.protocol.writesBeforeGate : 0,
373
+ gateBlocked: s.protocol.gateBlocked === true
374
+ };
375
+ }
376
+ }
377
+ } catch {
378
+ }
379
+ return null;
380
+ }
324
381
  var skillCache = {};
325
382
  function loadSkill(name) {
326
383
  if (name in skillCache) return skillCache[name];
@@ -432,7 +489,7 @@ Use grep and read to investigate ${args.topic} in the codebase, then proceed wit
432
489
  if (step === "ambiguity" && !p.ambiguityDone) {
433
490
  p.ambiguityDone = true;
434
491
  addPhase(sid, "ambiguity_check");
435
- writeState();
492
+ writeState(true);
436
493
  return "[parallax] Step 1/6: Ambiguity Check marked complete.";
437
494
  }
438
495
  if (step === "invariants") {
@@ -441,7 +498,7 @@ Use grep and read to investigate ${args.topic} in the codebase, then proceed wit
441
498
  }
442
499
  p.invariantsDone = true;
443
500
  addPhase(sid, "four_invariants");
444
- writeState();
501
+ writeState(true);
445
502
  return "[parallax] Step 2/6: 4 Invariants marked complete.";
446
503
  }
447
504
  if (step === "gate") {
@@ -450,7 +507,7 @@ Use grep and read to investigate ${args.topic} in the codebase, then proceed wit
450
507
  }
451
508
  p.gateDone = true;
452
509
  addPhase(sid, "verification_gate");
453
- writeState();
510
+ writeState(true);
454
511
  return "[parallax] Step 3/6: Verification Gate marked complete.";
455
512
  }
456
513
  if (step === "design") {
@@ -459,19 +516,19 @@ Use grep and read to investigate ${args.topic} in the codebase, then proceed wit
459
516
  }
460
517
  p.designDone = true;
461
518
  addPhase(sid, "design_check");
462
- writeState();
519
+ writeState(true);
463
520
  return "[parallax] Step 4/6: Design Doc marked complete.";
464
521
  }
465
522
  if (step === "commit") {
466
523
  p.commitDone = true;
467
524
  addPhase(sid, "commit_decision");
468
- writeState();
525
+ writeState(true);
469
526
  return "[parallax] Step 5/6: Commit Decision marked complete.";
470
527
  }
471
528
  if (step === "summary") {
472
529
  p.summaryDone = true;
473
530
  addPhase(sid, "summary");
474
- writeState();
531
+ writeState(true);
475
532
  const trace = getTrace(sid);
476
533
  const breakdown = computeCoherenceScore(trace);
477
534
  const s = getFriction();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "parallax-opencode",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "PARALLAX ENGINE plugin for OpenCode -- protocol enforcement, friction-loop verification, mode switching (plan/build/debug), trace recording, coherence scoring, CI gate, and PR-ready trace artifacts",
5
5
  "type": "module",
6
6
  "main": "./dist/plugin.js",