@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/README.md +37 -70
- package/dist/__engine-probe__.js +1 -1
- package/dist/{chunk-K5X5TSUR.js → chunk-IU4AWQKF.js} +143 -77
- package/dist/{chunk-LJKEHO6F.js → chunk-IUXS75FH.js} +24 -1
- package/dist/cli.cjs +157 -70
- package/dist/cli.js +2 -2
- package/dist/index.cjs +177 -86
- package/dist/index.d.cts +69 -19
- package/dist/index.d.ts +69 -19
- package/dist/index.js +22 -18
- package/package.json +2 -2
- package/templates/SKILL.md +20 -7
package/dist/index.d.ts
CHANGED
|
@@ -1,36 +1,78 @@
|
|
|
1
1
|
export { main } from './cli.js';
|
|
2
2
|
|
|
3
|
-
declare const
|
|
4
|
-
declare const
|
|
5
|
-
|
|
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
|
|
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
|
|
19
|
-
readonly code: "
|
|
28
|
+
declare class ConfigVersionMismatchError extends Error {
|
|
29
|
+
readonly code: "CONFIG_VERSION_MISMATCH";
|
|
20
30
|
constructor(message?: string);
|
|
21
31
|
}
|
|
22
|
-
declare class
|
|
23
|
-
readonly code: "
|
|
32
|
+
declare class ConfigCorruptError extends Error {
|
|
33
|
+
readonly code: "CONFIG_CORRUPT";
|
|
24
34
|
constructor(message: string);
|
|
25
35
|
}
|
|
26
|
-
declare class
|
|
27
|
-
readonly code: "
|
|
36
|
+
declare class ConfigValidationError extends Error {
|
|
37
|
+
readonly code: "CONFIG_VALIDATION";
|
|
28
38
|
constructor(message: string);
|
|
29
39
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 `
|
|
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
|
|
73
|
-
* when a scope is already configured, it leaves
|
|
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
|
|
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 {
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
12
|
-
|
|
12
|
+
configExists,
|
|
13
|
+
deleteConfig,
|
|
13
14
|
ensureTraceDir,
|
|
14
15
|
expandDocScope,
|
|
15
16
|
getRepoRoot,
|
|
16
17
|
main,
|
|
17
|
-
|
|
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-
|
|
27
|
+
} from "./chunk-IU4AWQKF.js";
|
|
26
28
|
import {
|
|
27
29
|
init_esm_shims
|
|
28
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-IUXS75FH.js";
|
|
29
31
|
|
|
30
32
|
// src/index.ts
|
|
31
33
|
init_esm_shims();
|
|
32
34
|
export {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
43
|
-
|
|
45
|
+
configExists,
|
|
46
|
+
deleteConfig,
|
|
44
47
|
ensureTraceDir,
|
|
45
48
|
expandDocScope,
|
|
46
49
|
getRepoRoot,
|
|
47
50
|
main,
|
|
48
|
-
|
|
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.
|
|
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.
|
|
35
|
+
"@delfini/drift-engine": "0.3.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^22.10.2",
|
package/templates/SKILL.md
CHANGED
|
@@ -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
|
|
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
|
|
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 `
|
|
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/
|
|
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
|
|
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.
|