@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/AGENTS.md +20 -8
- package/README.md +32 -2
- package/index.js +20 -15
- package/package.json +1 -1
- package/process-lock.js +63 -6
- package/tools/definitions.js +80 -1
- package/tools/handler-modules/commit-handlers.js +53 -1
- package/tools/handler-modules/dod-handlers.js +217 -0
- package/tools/handler-modules/dod.js +335 -0
- package/tools/handler-modules/factory-handlers.js +27 -1
- package/tools/handler-modules/index.js +7 -0
- package/tools/handler-modules/shared.js +5 -0
- package/tools/handler-modules/status-handlers.js +61 -3
- package/tools/handler-modules/workflow-handlers.js +35 -1
- package/workflow-state.js +83 -0
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
|
};
|