@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 +1 -1
- package/package.json +1 -1
- package/src/init.mjs +18 -2
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,
|
|
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
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 =
|
|
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 };
|