@delfini/cli 0.2.0 → 0.3.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/dist/index.d.ts CHANGED
@@ -1,36 +1,78 @@
1
1
  export { main } from './cli.js';
2
2
 
3
- declare const DOC_SCOPE_RELATIVE_PATH = ".claude/skills/delfini/doc-scope.json";
4
- declare const DOC_SCOPE_VERSION: 1;
5
- interface DocScope {
3
+ declare const DELFINI_CONFIG_RELATIVE_PATH = ".claude/skills/delfini/delfini-config.json";
4
+ declare const LEGACY_DOC_SCOPE_RELATIVE_PATH = ".claude/skills/delfini/doc-scope.json";
5
+ declare const DELFINI_CONFIG_VERSION: 1;
6
+ interface DelfiniConfig {
6
7
  version: 1;
7
8
  doc_scope: string[];
9
+ /** Always present after `readConfig` (defaulted to `[]` when absent on disk). */
10
+ ignore_code_scope: string[];
8
11
  }
9
- interface DocScopeWriteOptions {
12
+ interface ConfigWriteOptions {
10
13
  repoRoot?: string;
11
14
  }
15
+ /** Partial update applied on top of any existing config by `writeConfig`. */
16
+ interface ConfigUpdate {
17
+ /** Replace `doc_scope`. Must be non-empty after normalisation. */
18
+ doc_scope?: string[];
19
+ /** Replace `ignore_code_scope`. May be empty (means "ignore nothing"). */
20
+ ignore_code_scope?: string[];
21
+ }
12
22
  interface DocScopeExpansionResult {
13
23
  /** Absolute paths to files matched by the scope entries. Sorted, deduped. */
14
24
  files: string[];
15
25
  /** Original entries from `paths` that resolved to nothing on disk. */
16
26
  missingPaths: string[];
17
27
  }
18
- declare class DocScopeVersionMismatchError extends Error {
19
- readonly code: "DOC_SCOPE_VERSION_MISMATCH";
28
+ declare class ConfigVersionMismatchError extends Error {
29
+ readonly code: "CONFIG_VERSION_MISMATCH";
20
30
  constructor(message?: string);
21
31
  }
22
- declare class DocScopeCorruptError extends Error {
23
- readonly code: "DOC_SCOPE_CORRUPT";
32
+ declare class ConfigCorruptError extends Error {
33
+ readonly code: "CONFIG_CORRUPT";
24
34
  constructor(message: string);
25
35
  }
26
- declare class DocScopeValidationError extends Error {
27
- readonly code: "DOC_SCOPE_VALIDATION";
36
+ declare class ConfigValidationError extends Error {
37
+ readonly code: "CONFIG_VALIDATION";
28
38
  constructor(message: string);
29
39
  }
30
- declare function readDocScope(repoRoot?: string): Promise<DocScope | null>;
31
- declare function writeDocScope(paths: string[], options?: DocScopeWriteOptions): Promise<void>;
32
- declare function docScopeExists(repoRoot?: string): Promise<boolean>;
33
- declare function deleteDocScope(repoRoot?: string): Promise<void>;
40
+ /**
41
+ * Read the effective Delfini config, or null if none is configured.
42
+ *
43
+ * Resolution order: `delfini-config.json` first, then a legacy
44
+ * `doc-scope.json` fallback (read-only — migration to the new filename happens
45
+ * on the next `writeConfig`). `ignore_code_scope` is defaulted to `[]` when
46
+ * absent so callers never branch on undefined.
47
+ */
48
+ declare function readConfig(repoRoot?: string): Promise<DelfiniConfig | null>;
49
+ /**
50
+ * Persist a partial config update, merging over any existing config and
51
+ * preserving the scope not being edited. Writes `delfini-config.json` and
52
+ * removes a legacy `doc-scope.json` if present (one-time rename migration).
53
+ *
54
+ * `doc_scope` is required to be non-empty in the final config (a Delfini run
55
+ * with no docs is meaningless); `ignore_code_scope` may be empty.
56
+ */
57
+ declare function writeConfig(update: ConfigUpdate, options?: ConfigWriteOptions): Promise<void>;
58
+ /**
59
+ * Persist the doc scope, preserving any existing `ignore_code_scope`. Thin
60
+ * wrapper over `writeConfig` kept for the install / first-run callers whose
61
+ * only job is to seed the docs Delfini tracks.
62
+ */
63
+ declare function writeDocScope(paths: string[], options?: ConfigWriteOptions): Promise<void>;
64
+ /**
65
+ * True iff a Delfini config exists — the new `delfini-config.json` OR a legacy
66
+ * `doc-scope.json`. Used by `delfini install` to avoid clobbering an existing
67
+ * committed, team-shared config.
68
+ */
69
+ declare function configExists(repoRoot?: string): Promise<boolean>;
70
+ /**
71
+ * Delete the Delfini config — both the new `delfini-config.json` and any legacy
72
+ * `doc-scope.json` (`delfini --reset-scope`). Idempotent: absent files are a
73
+ * silent no-op.
74
+ */
75
+ declare function deleteConfig(repoRoot?: string): Promise<void>;
34
76
  declare function expandDocScope(paths: string[], repoRoot?: string): Promise<DocScopeExpansionResult>;
35
77
 
36
78
  declare class RepoRootNotFoundError extends Error {
@@ -66,11 +108,11 @@ interface RunInstallOptions {
66
108
  /**
67
109
  * Resolves the doc-scope path list. When provided, `runInstall` uses it
68
110
  * directly (the `--scope` CLI flag and the test seam) and never prompts —
69
- * a non-empty list is persisted to `doc-scope.json` (overwriting any
111
+ * a non-empty list is persisted to `delfini-config.json` doc_scope (overwriting any
70
112
  * existing file, since an explicit `--scope` is intent-to-overwrite); an
71
113
  * empty list is a no-op. When omitted, `runInstall` prompts interactively
72
- * on a TTY only if no `doc-scope.json` exists yet; on a non-TTY stdin, or
73
- * when a scope is already configured, it leaves `doc-scope.json` untouched.
114
+ * on a TTY only if no config exists yet; on a non-TTY stdin, or
115
+ * when a scope is already configured, it leaves the config untouched.
74
116
  * Invalid paths (rejected by `writeDocScope`) warn-and-skip — the scaffold
75
117
  * always completes; the SKILL.md first-run prompt re-seeds the scope later.
76
118
  */
@@ -88,10 +130,18 @@ declare const PROMPT_TOKEN_BUDGET = 150000;
88
130
  interface RunLocalPrepareOptions {
89
131
  /**
90
132
  * The `--scope <paths>` value. Accepts a comma-separated string OR a string[].
91
- * When provided, overrides the persisted `.claude/skills/delfini/doc-scope.json`
133
+ * When provided, overrides the persisted `delfini-config.json` doc_scope
92
134
  * WITHOUT modifying that file (FR144 per-run override invariant).
93
135
  */
94
136
  scope?: string | string[];
137
+ /**
138
+ * The `--ignore-code-scope <paths>` value. Accepts a comma-separated string
139
+ * OR a string[]. When provided, overrides the persisted `delfini-config.json`
140
+ * `ignore_code_scope` WITHOUT modifying that file (per-run override). Changed
141
+ * files matching any entry are dropped from the analysed diff. Empty/omitted
142
+ * → use the persisted `ignore_code_scope` (or none).
143
+ */
144
+ ignoreCodeScope?: string | string[];
95
145
  /**
96
146
  * The `--base <ref>` value. When provided, used as the diff base directly.
97
147
  * When omitted, defaults to `git merge-base HEAD origin/main`.
@@ -210,4 +260,4 @@ interface RunLocalFinalizeOptions {
210
260
  */
211
261
  declare function runLocalFinalize(options: RunLocalFinalizeOptions): Promise<number>;
212
262
 
213
- export { DOC_SCOPE_RELATIVE_PATH, DOC_SCOPE_VERSION, type DiffSource, type DiffStatus, type DocScope, DocScopeCorruptError, type DocScopeExpansionResult, DocScopeValidationError, DocScopeVersionMismatchError, type DocScopeWriteOptions, type InstallLogger, InstallToolNotSupportedError, PROMPT_TOKEN_BUDGET, RepoRootNotFoundError, type RunDiffStatusOptions, type RunInstallOptions, type RunLocalFinalizeOptions, type RunLocalPrepareOptions, appendToGitignore, deleteDocScope, docScopeExists, ensureTraceDir, expandDocScope, getRepoRoot, readDocScope, runDiffStatus, runInstall, runLocalFinalize, runLocalPrepare, writeDocScope, writeRetryAttemptFile, writeTraceFile };
263
+ export { ConfigCorruptError, type ConfigUpdate, ConfigValidationError, ConfigVersionMismatchError, type ConfigWriteOptions, DELFINI_CONFIG_RELATIVE_PATH, DELFINI_CONFIG_VERSION, type DelfiniConfig, type DiffSource, type DiffStatus, type DocScopeExpansionResult, type InstallLogger, InstallToolNotSupportedError, LEGACY_DOC_SCOPE_RELATIVE_PATH, PROMPT_TOKEN_BUDGET, RepoRootNotFoundError, type RunDiffStatusOptions, type RunInstallOptions, type RunLocalFinalizeOptions, type RunLocalPrepareOptions, appendToGitignore, configExists, deleteConfig, ensureTraceDir, expandDocScope, getRepoRoot, readConfig, runDiffStatus, runInstall, runLocalFinalize, runLocalPrepare, writeConfig, writeDocScope, writeRetryAttemptFile, writeTraceFile };
package/dist/index.js CHANGED
@@ -1,55 +1,59 @@
1
1
  import {
2
- DOC_SCOPE_RELATIVE_PATH,
3
- DOC_SCOPE_VERSION,
4
- DocScopeCorruptError,
5
- DocScopeValidationError,
6
- DocScopeVersionMismatchError,
2
+ ConfigCorruptError,
3
+ ConfigValidationError,
4
+ ConfigVersionMismatchError,
5
+ DELFINI_CONFIG_RELATIVE_PATH,
6
+ DELFINI_CONFIG_VERSION,
7
7
  InstallToolNotSupportedError,
8
+ LEGACY_DOC_SCOPE_RELATIVE_PATH,
8
9
  PROMPT_TOKEN_BUDGET,
9
10
  RepoRootNotFoundError,
10
11
  appendToGitignore,
11
- deleteDocScope,
12
- docScopeExists,
12
+ configExists,
13
+ deleteConfig,
13
14
  ensureTraceDir,
14
15
  expandDocScope,
15
16
  getRepoRoot,
16
17
  main,
17
- readDocScope,
18
+ readConfig,
18
19
  runDiffStatus,
19
20
  runInstall,
20
21
  runLocalFinalize,
21
22
  runLocalPrepare,
23
+ writeConfig,
22
24
  writeDocScope,
23
25
  writeRetryAttemptFile,
24
26
  writeTraceFile
25
- } from "./chunk-K5X5TSUR.js";
27
+ } from "./chunk-IU4AWQKF.js";
26
28
  import {
27
29
  init_esm_shims
28
- } from "./chunk-LJKEHO6F.js";
30
+ } from "./chunk-IUXS75FH.js";
29
31
 
30
32
  // src/index.ts
31
33
  init_esm_shims();
32
34
  export {
33
- DOC_SCOPE_RELATIVE_PATH,
34
- DOC_SCOPE_VERSION,
35
- DocScopeCorruptError,
36
- DocScopeValidationError,
37
- DocScopeVersionMismatchError,
35
+ ConfigCorruptError,
36
+ ConfigValidationError,
37
+ ConfigVersionMismatchError,
38
+ DELFINI_CONFIG_RELATIVE_PATH,
39
+ DELFINI_CONFIG_VERSION,
38
40
  InstallToolNotSupportedError,
41
+ LEGACY_DOC_SCOPE_RELATIVE_PATH,
39
42
  PROMPT_TOKEN_BUDGET,
40
43
  RepoRootNotFoundError,
41
44
  appendToGitignore,
42
- deleteDocScope,
43
- docScopeExists,
45
+ configExists,
46
+ deleteConfig,
44
47
  ensureTraceDir,
45
48
  expandDocScope,
46
49
  getRepoRoot,
47
50
  main,
48
- readDocScope,
51
+ readConfig,
49
52
  runDiffStatus,
50
53
  runInstall,
51
54
  runLocalFinalize,
52
55
  runLocalPrepare,
56
+ writeConfig,
53
57
  writeDocScope,
54
58
  writeRetryAttemptFile,
55
59
  writeTraceFile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delfini/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,7 +32,7 @@
32
32
  "simple-git": "^3.27.0",
33
33
  "tinyglobby": "^0.2.16",
34
34
  "zod": "^3.24.0",
35
- "@delfini/drift-engine": "0.2.0"
35
+ "@delfini/drift-engine": "0.3.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^22.10.2",
@@ -41,15 +41,28 @@ If `delfini` is not on PATH:
41
41
  3. On `y` → run `npm i -g @delfini/cli`, then re-verify with `delfini --version`.
42
42
  4. On `n` or on install failure → fall back to `npx @delfini/cli` for the rest of this session. Substitute `npx @delfini/cli` for every `delfini` invocation in the remaining steps.
43
43
 
44
- ## Load doc-scope
44
+ ## Load config
45
45
 
46
- Read `.claude/skills/delfini/doc-scope.json`.
46
+ Read `.claude/skills/delfini/delfini-config.json` (the committed, team-shared Delfini config). For repos set up before the rename, also accept a legacy `.claude/skills/delfini/doc-scope.json` — the CLI reads it as a fallback and migrates it to `delfini-config.json` on the next config write.
47
+
48
+ The config shape (v1) is:
49
+
50
+ ```json
51
+ {
52
+ "version": 1,
53
+ "doc_scope": ["docs/", "packages/*/README.md"],
54
+ "ignore_code_scope": ["src/generated/**", "db/migrations/"]
55
+ }
56
+ ```
57
+
58
+ - `doc_scope` — the source-of-truth docs Delfini analyses (directories scanned recursively for `.md`, single files, or globs).
59
+ - `ignore_code_scope` — **optional.** Code paths whose CHANGES Delfini ignores: a changed file matching any entry (directory, file, or glob — same dialect as `doc_scope`) is dropped from the analysed diff, as if it had not changed. Omit it (or leave it empty) to analyse all changed code.
47
60
 
48
61
  If the file exists, parse it and continue.
49
62
 
50
- If the file is missing AND the user did not pass `--scope <paths>` to `/delfini`, prompt the user in a single turn:
63
+ If no config exists AND the user did not pass `--scope <paths>` to `/delfini`, prompt the user in a single turn:
51
64
 
52
- > "No `doc-scope.json` found. Which docs should Delfini analyse? Provide one or more paths — directories (recursive `.md` scan), single files, or globs. Example: `docs/ specs/architecture.md packages/*/README.md`."
65
+ > "No `delfini-config.json` found. Which docs should Delfini analyse? Provide one or more paths — directories (recursive `.md` scan), single files, or globs. Example: `docs/ specs/architecture.md packages/*/README.md`."
53
66
 
54
67
  Validate each path the user supplies:
55
68
 
@@ -57,9 +70,9 @@ Validate each path the user supplies:
57
70
  - Reject any path that resolves outside the repo root.
58
71
  - For non-existent paths, warn the user but keep the path in scope (a teammate may have deleted a file in a different branch).
59
72
 
60
- Write the validated scope to `.claude/skills/delfini/doc-scope.json` in the shape `{"version": 1, "doc_scope": [<paths>]}`. The file is committed to git — team-shared by construction.
73
+ Write the validated scope to `.claude/skills/delfini/delfini-config.json` in the shape `{"version": 1, "doc_scope": [<paths>]}`. The file is committed to git — team-shared by construction. (`ignore_code_scope` is configured by hand-editing this file; the first-run prompt only seeds `doc_scope`.)
61
74
 
62
- If the user passed `--scope <paths>` to `/delfini`, run that invocation against the override list without touching the persisted file.
75
+ If the user passed `--scope <paths>` to `/delfini`, run that invocation against the override list without touching the persisted file. Likewise `--ignore-code-scope <paths>` overrides `ignore_code_scope` for a single run without modifying the file.
63
76
 
64
77
  ## Resolve the diff source
65
78
 
@@ -100,7 +113,7 @@ Run `delfini local-prepare --diff-source <resolved>` (the value resolved in "Res
100
113
 
101
114
  Branch on non-zero exit codes:
102
115
 
103
- - **Exit `2` (no doc-scope set AND no `--scope` provided)** → fall back to the "Load doc-scope" first-run prompt, write `doc-scope.json`, then re-run `delfini local-prepare --diff-source <resolved>`.
116
+ - **Exit `2` (no doc-scope set AND no `--scope` provided)** → fall back to the "Load config" first-run prompt, write `delfini-config.json`, then re-run `delfini local-prepare --diff-source <resolved>`.
104
117
  - **Exit `4` (non-doc prompt payload exceeds budget — diff + schema + instructions alone do not fit, or no doc section fits after ranked-fill)** → surface two options to the user:
105
118
  1. Re-invoke with a narrower scope: `/delfini --scope <narrower-paths>`.
106
119
  2. Split the PR into smaller changes.