@ktpartners/dgs-platform 2.6.3 → 2.7.1

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.
Files changed (30) hide show
  1. package/agents/dgs-executor.md +51 -0
  2. package/commands/dgs/sync.md +70 -0
  3. package/deliver-great-systems/bin/dgs-tools.cjs +290 -4
  4. package/deliver-great-systems/bin/lib/config.cjs +259 -67
  5. package/deliver-great-systems/bin/lib/core.cjs +49 -8
  6. package/deliver-great-systems/bin/lib/core.test.cjs +35 -14
  7. package/deliver-great-systems/bin/lib/init.cjs +61 -6
  8. package/deliver-great-systems/bin/lib/init.test.cjs +9 -9
  9. package/deliver-great-systems/bin/lib/migration.cjs +1 -1
  10. package/deliver-great-systems/bin/lib/migration.test.cjs +7 -9
  11. package/deliver-great-systems/bin/lib/path-audit.test.cjs +1 -1
  12. package/deliver-great-systems/bin/lib/paths.cjs +32 -22
  13. package/deliver-great-systems/bin/lib/paths.test.cjs +16 -6
  14. package/deliver-great-systems/bin/lib/projects.cjs +1 -1
  15. package/deliver-great-systems/bin/lib/projects.test.cjs +1 -1
  16. package/deliver-great-systems/bin/lib/repos.cjs +29 -10
  17. package/deliver-great-systems/bin/lib/state.cjs +2 -2
  18. package/deliver-great-systems/bin/lib/sync.cjs +878 -0
  19. package/deliver-great-systems/bin/lib/test-helpers.cjs +44 -12
  20. package/deliver-great-systems/references/git-integration.md +81 -0
  21. package/deliver-great-systems/references/planning-config.md +154 -31
  22. package/deliver-great-systems/references/sync-cadence.md +191 -0
  23. package/deliver-great-systems/references/sync-hooks.md +96 -0
  24. package/deliver-great-systems/test/cadence.test.cjs +160 -0
  25. package/deliver-great-systems/test/sync-workflow.test.cjs +562 -0
  26. package/deliver-great-systems/workflows/execute-phase.md +111 -4
  27. package/deliver-great-systems/workflows/init-product.md +6 -2
  28. package/deliver-great-systems/workflows/run-job.md +77 -2
  29. package/deliver-great-systems/workflows/settings.md +82 -1
  30. package/package.json +1 -1
@@ -709,15 +709,29 @@ function cmdDetectLayout(cwd, raw) {
709
709
 
710
710
  // Signal 1: .planning/ directory with config files
711
711
  if (
712
- fs.existsSync(path.join(dotPlanning, 'dgs.config.json')) ||
713
- fs.existsSync(path.join(dotPlanning, 'config.json'))
712
+ fs.existsSync(path.join(dotPlanning, 'config.json')) ||
713
+ fs.existsSync(path.join(dotPlanning, 'config.local.json')) ||
714
+ fs.existsSync(path.join(dotPlanning, 'dgs.config.json'))
714
715
  ) {
715
716
  signals.push('existing .planning/ directory with config files');
716
717
  output({ suggested: 'dotplanning', signals }, raw);
717
718
  return;
718
719
  }
719
720
 
720
- // Signal 2: dgs.config.json at root with planningRoot: '.'
721
+ // Signal 2: config.local.json at root with planningRoot: '.'
722
+ const rootLocalConfigPath = path.join(cwd, 'config.local.json');
723
+ if (fs.existsSync(rootLocalConfigPath)) {
724
+ try {
725
+ const config = JSON.parse(fs.readFileSync(rootLocalConfigPath, 'utf-8'));
726
+ if (config.planningRoot === '.') {
727
+ signals.push('config.local.json at root with planningRoot: "."');
728
+ output({ suggested: 'root', signals }, raw);
729
+ return;
730
+ }
731
+ } catch { /* malformed config -- continue detection */ }
732
+ }
733
+
734
+ // Signal 2b: Legacy dgs.config.json at root with planningRoot: '.'
721
735
  const rootConfigPath = path.join(cwd, 'dgs.config.json');
722
736
  if (fs.existsSync(rootConfigPath)) {
723
737
  try {
@@ -727,7 +741,7 @@ function cmdDetectLayout(cwd, raw) {
727
741
  output({ suggested: 'root', signals }, raw);
728
742
  return;
729
743
  }
730
- } catch { /* malformed config continue detection */ }
744
+ } catch { /* malformed config -- continue detection */ }
731
745
  }
732
746
 
733
747
  // Signal 3: Empty-ish repo (no source code indicators at depth 1)
@@ -832,8 +846,8 @@ function generateRootGitignore(cwd) {
832
846
  '*.swo',
833
847
  '*~',
834
848
  '',
835
- '# DGS config (may contain API keys)',
836
- 'dgs.config.json',
849
+ '# DGS local config (per-machine state)',
850
+ 'config.local.json',
837
851
  '',
838
852
  '# DGS review keys (contains API keys)',
839
853
  'review-keys.json',
@@ -1129,9 +1143,14 @@ function cmdReposInitProduct(cwd, options, raw) {
1129
1143
 
1130
1144
  // ── Root-mode: Config-first pattern ───────────────────────────────────────
1131
1145
  if (isRootMode) {
1132
- // Write dgs.config.json FIRST so getPlanningRoot returns repo root
1133
- const rootConfigPath = path.join(cwd, 'dgs.config.json');
1134
- fs.writeFileSync(rootConfigPath, JSON.stringify({ planningRoot: '.' }, null, 2));
1146
+ // Write config.local.json FIRST so getPlanningRoot returns repo root
1147
+ const rootLocalConfigPath = path.join(cwd, 'config.local.json');
1148
+ fs.writeFileSync(rootLocalConfigPath, JSON.stringify({ planningRoot: '.' }, null, 2));
1149
+ // Write empty shared config.json at root
1150
+ const rootSharedConfigPath = path.join(cwd, 'config.json');
1151
+ if (!fs.existsSync(rootSharedConfigPath)) {
1152
+ fs.writeFileSync(rootSharedConfigPath, JSON.stringify({}, null, 2));
1153
+ }
1135
1154
  resetPaths(); // Clear stale cache so getPlanningRoot resolves to cwd
1136
1155
 
1137
1156
  // Check if already initialized (idempotency)
@@ -1271,7 +1290,7 @@ function cmdReposInitProduct(cwd, options, raw) {
1271
1290
  ideas_dirs_created: true,
1272
1291
  specs_dir_created: true,
1273
1292
  docs_dir_created: true,
1274
- files_created: ['dgs.config.json', 'REPOS.md', 'PROJECTS.md', 'ideas/', 'specs/', 'docs/', '.gitignore', 'review-keys.json'],
1293
+ files_created: ['config.json', 'config.local.json', 'REPOS.md', 'PROJECTS.md', 'ideas/', 'specs/', 'docs/', '.gitignore', 'review-keys.json'],
1275
1294
  }, raw);
1276
1295
  } else {
1277
1296
  // Standard layout: sync .gitignore for local repo paths
@@ -571,7 +571,7 @@ function cmdStateSnapshot(cwd, raw) {
571
571
  function getMilestonePhaseFilter(cwd) {
572
572
  const milestonePhaseNums = new Set();
573
573
  try {
574
- const roadmap = fs.readFileSync(path.join(cwd, '.planning', 'ROADMAP.md'), 'utf-8');
574
+ const roadmap = fs.readFileSync(path.join(getPlanningRoot(cwd), 'ROADMAP.md'), 'utf-8');
575
575
  const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
576
576
  let m;
577
577
  while ((m = phasePattern.exec(roadmap)) !== null) {
@@ -632,7 +632,7 @@ function buildStateFrontmatter(bodyContent, cwd) {
632
632
 
633
633
  if (cwd) {
634
634
  try {
635
- const phasesDir = path.join(cwd, '.planning', 'phases');
635
+ const phasesDir = path.join(getPlanningRoot(cwd), 'phases');
636
636
  if (fs.existsSync(phasesDir)) {
637
637
  const isDirInMilestone = getMilestonePhaseFilter(cwd);
638
638
  const phaseDirs = fs.readdirSync(phasesDir, { withFileTypes: true })