@programinglive/dev-workflow-mcp-server 1.13.15 → 1.14.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/workflow-state.js CHANGED
@@ -4,6 +4,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from
4
4
  import path from "path";
5
5
  import { assertSafeKnowledge } from './security/policy.js';
6
6
  import { sanitize } from './security/sanitizer.js';
7
+ import { normalizeItems as normalizeDodItems, mergeDefinitionOfDone as mergeDodItems } from './tools/handler-modules/dod.js';
7
8
  import { fileURLToPath } from "url";
8
9
 
9
10
  const __filename = fileURLToPath(import.meta.url);
@@ -658,6 +659,14 @@ export class WorkflowState {
658
659
  projectDir: "",
659
660
  featureFlowCreated: false,
660
661
  featureFlowDescription: "",
662
+ // Definition of Done milik task ini. Aturan dan bentuk itemnya ada di
663
+ // tools/handler-modules/dod.js; di sini hanya disimpan.
664
+ definitionOfDone: [],
665
+ dodSource: "",
666
+ dodFactoryTaskId: "",
667
+ // Naik setiap ada perubahan kerja baru setelah commit tercatat, sehingga
668
+ // bukti item `done` yang lama otomatis tidak lagi berlaku.
669
+ dodRevision: 0,
661
670
  history: [],
662
671
  taskType: "",
663
672
  };
@@ -702,6 +711,14 @@ export class WorkflowState {
702
711
  projectDir: "",
703
712
  featureFlowCreated: false,
704
713
  featureFlowDescription: "",
714
+ // Definition of Done milik task ini. Aturan dan bentuk itemnya ada di
715
+ // tools/handler-modules/dod.js; di sini hanya disimpan.
716
+ definitionOfDone: [],
717
+ dodSource: "",
718
+ dodFactoryTaskId: "",
719
+ // Naik setiap ada perubahan kerja baru setelah commit tercatat, sehingga
720
+ // bukti item `done` yang lama otomatis tidak lagi berlaku.
721
+ dodRevision: 0,
705
722
  history: [],
706
723
  taskType: "",
707
724
  };
@@ -768,6 +785,21 @@ export class WorkflowState {
768
785
  if (typeof this.state.featureFlowDescription !== "string") {
769
786
  this.state.featureFlowDescription = "";
770
787
  }
788
+ // Berkas state yang ditulis sebelum fitur DoD ada tidak punya field ini.
789
+ // Ia harus muncul sebagai "belum punya DoD", bukan undefined yang membuat
790
+ // gerbang melempar TypeError.
791
+ this.state.definitionOfDone = normalizeDodItems(this.state.definitionOfDone);
792
+ if (typeof this.state.dodSource !== "string") {
793
+ this.state.dodSource = "";
794
+ }
795
+ if (typeof this.state.dodFactoryTaskId !== "string") {
796
+ this.state.dodFactoryTaskId = "";
797
+ }
798
+ if (!Number.isFinite(Number(this.state.dodRevision)) || Number(this.state.dodRevision) < 0) {
799
+ this.state.dodRevision = 0;
800
+ } else {
801
+ this.state.dodRevision = Math.trunc(Number(this.state.dodRevision));
802
+ }
771
803
  } catch (error) {
772
804
  if (error?.code !== "ENOENT") {
773
805
  throw error;
@@ -887,6 +919,48 @@ export class WorkflowState {
887
919
  }
888
920
  }
889
921
 
922
+ /**
923
+ * Gabungkan item DoD dengan milik disk bila task-nya sama.
924
+ *
925
+ * Sama seperti `mergeMonotonicProgress`, ini hanya berlaku untuk task yang
926
+ * SAMA. `start_task` mengganti task, dan pada saat itu DoD memang harus mulai
927
+ * dari nol - bukan mewarisi bukti task sebelumnya.
928
+ *
929
+ * Bedanya, DoD digabung per item dengan aturan "yang lebih kuat menang",
930
+ * bukan OR boolean: dua proses MCP bisa melayani task yang sama, dan proses
931
+ * yang memegang state basi tidak boleh menghapus bukti item yang baru dicatat
932
+ * proses lain.
933
+ */
934
+ mergeDefinitionOfDone(reconciled) {
935
+ const diskTask = (reconciled?.diskTask || "").trim();
936
+ const ourTask = (this.state.taskDescription || "").trim();
937
+ if (!diskTask || !ourTask || diskTask !== ourTask) {
938
+ return 0;
939
+ }
940
+ if ((reconciled?.diskPhase || "idle") === "idle") {
941
+ return 0;
942
+ }
943
+
944
+ const disk = reconciled?.diskState;
945
+ if (!disk) {
946
+ return 0;
947
+ }
948
+
949
+ const before = Array.isArray(this.state.definitionOfDone) ? this.state.definitionOfDone : [];
950
+ const merged = mergeDodItems(before, normalizeDodItems(disk.definitionOfDone));
951
+ this.state.definitionOfDone = merged;
952
+
953
+ // Revisi hanya boleh maju: revisi yang lebih tinggi berarti ada perubahan
954
+ // kerja baru yang sudah diketahui proses lain. Mundur berarti bukti basi
955
+ // diam-diam dihidupkan kembali.
956
+ const diskRevision = Number(disk.dodRevision);
957
+ if (Number.isFinite(diskRevision) && diskRevision > Number(this.state.dodRevision || 0)) {
958
+ this.state.dodRevision = Math.trunc(diskRevision);
959
+ }
960
+
961
+ return merged.length - before.length;
962
+ }
963
+
890
964
  async save(options = {}) {
891
965
  assertSafeKnowledge(this.state);
892
966
  const reconciled = await this.reconcileWithDisk();
@@ -918,6 +992,7 @@ export class WorkflowState {
918
992
  // disk memang task yang sama. `start_task` mengganti task, dan pada saat itu
919
993
  // flag harus benar-benar direset, bukan dihidupkan kembali.
920
994
  this.mergeMonotonicProgress(reconciled);
995
+ this.mergeDefinitionOfDone(reconciled);
921
996
 
922
997
  this.state.owner = {
923
998
  processMarker: PROCESS_TOKEN,
@@ -1272,6 +1347,14 @@ export class WorkflowState {
1272
1347
  projectDir: "",
1273
1348
  featureFlowCreated: false,
1274
1349
  featureFlowDescription: "",
1350
+ // Definition of Done milik task ini. Aturan dan bentuk itemnya ada di
1351
+ // tools/handler-modules/dod.js; di sini hanya disimpan.
1352
+ definitionOfDone: [],
1353
+ dodSource: "",
1354
+ dodFactoryTaskId: "",
1355
+ // Naik setiap ada perubahan kerja baru setelah commit tercatat, sehingga
1356
+ // bukti item `done` yang lama otomatis tidak lagi berlaku.
1357
+ dodRevision: 0,
1275
1358
  history,
1276
1359
  taskType: "",
1277
1360
  };