@dotdotgod/cli 0.2.4 → 0.2.5

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/README.md CHANGED
@@ -33,7 +33,7 @@ dotdotgod graph impact . --changed <path> --compact
33
33
 
34
34
  ## What It Does
35
35
 
36
- - `init` creates `AGENTS.md`, thin agent entrypoints, docs indexes, active-plan space, archive map, and local cache ignores.
36
+ - `init` creates `AGENTS.md`, thin agent entrypoints, docs indexes, active-plan space, archive map, local cache ignores, and the complete editable default config.
37
37
  - `validate` checks the dotdotgod docs/project-memory structure, local links, traceability blocks, config validity, and optional index freshness.
38
38
  - `index` builds `.dotdotgod/manifest.json` and compact graph shards from maintained project files.
39
39
  - `load-snapshot` returns a bounded first-pass project map for AI agents, including files pinned through the `load.pinnedPaths`/`load.pinnedBodies` config so context such as code conventions stays visible on every load.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotdotgod/cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "CLI for dotdotgod validation, project memory snapshots, and graph indexing.",
5
5
  "type": "module",
6
6
  "license": "Elastic-2.0",
package/src/init.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { existsSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
2
2
  import { basename, dirname, join, resolve } from 'node:path';
3
+ import { defaultDotdotgodConfigText } from './memory/config.mjs';
3
4
 
4
5
  function action(status, path, extra = {}) {
5
6
  return { status, path, ...extra };
@@ -9,6 +10,7 @@ function formatAction(item) {
9
10
  const extras = [];
10
11
  if (item.backup) extras.push(`backup=${item.backup}`);
11
12
  if (item.add) extras.push(`add=${item.add}`);
13
+ if (item.existing) extras.push(`existing=${item.existing}`);
12
14
  return `${item.status.padEnd(13)} ${item.path}${extras.length > 0 ? ` ${extras.join(' ')}` : ''}`;
13
15
  }
14
16
 
@@ -48,6 +50,14 @@ function initError(options, code, message) {
48
50
  process.exit(2);
49
51
  }
50
52
 
53
+ function backupPathFor(target) {
54
+ const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z');
55
+ const base = `${target}.bak.${timestamp}`;
56
+ let candidate = base;
57
+ for (let suffix = 1; existsSync(candidate); suffix += 1) candidate = `${base}.${suffix}`;
58
+ return candidate;
59
+ }
60
+
51
61
  function writeInitFile(options, relativePath, content, actions) {
52
62
  const target = join(options.root, relativePath);
53
63
  if (existsSync(target) && !options.force) {
@@ -57,7 +67,7 @@ function writeInitFile(options, relativePath, content, actions) {
57
67
 
58
68
  let backup = '';
59
69
  if (existsSync(target) && options.force) {
60
- backup = `${target}.bak.${new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z')}`;
70
+ backup = backupPathFor(target);
61
71
  if (!options.dryRun) renameSync(target, backup);
62
72
  }
63
73
 
@@ -67,7 +77,7 @@ function writeInitFile(options, relativePath, content, actions) {
67
77
  }
68
78
 
69
79
  mkdirSync(dirname(target), { recursive: true });
70
- writeFileSync(target, `${content}\n`);
80
+ writeFileSync(target, content.endsWith('\n') ? content : `${content}\n`);
71
81
  actions.push(action(backup ? 'replaced' : 'created', target, backup ? { backup } : {}));
72
82
  }
73
83
 
@@ -298,6 +308,12 @@ export function runInit(argv, usage) {
298
308
 
299
309
  const actions = [];
300
310
  for (const [relativePath, content] of initFiles(options)) writeInitFile(options, relativePath, content, actions);
311
+
312
+ const configPath = join(options.root, 'dotdotgod.config.json');
313
+ const rcPath = join(options.root, '.dotdotgodrc.json');
314
+ if (existsSync(rcPath)) actions.push(action('conflict', configPath, { existing: rcPath }));
315
+ else writeInitFile(options, 'dotdotgod.config.json', defaultDotdotgodConfigText(), actions);
316
+
301
317
  for (const entry of ['docs/plan', 'docs/archive', '.dotdotgod']) ensureGitignoreEntry(options, entry, actions);
302
318
 
303
319
  const payload = { ok: true, command: 'init', root: options.root, projectName: options.projectName, dryRun: options.dryRun, force: options.force, dotdotSetting: options.dotdotSetting, actions };