@lmzhen/dsh-evolution-commands 0.22.0 → 0.24.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.
@@ -12,6 +12,8 @@ declare module '@deepseek-ai/dsh-llm' {
12
12
  } & ContextFormed;
13
13
  }
14
14
  }
15
+ import { atomicWriteFiles } from '@lmzhen/dsh-evolution-core';
16
+ export { atomicWriteFiles };
15
17
  export declare const name = "evolution-commands";
16
18
  export interface Config {
17
19
  /** Skill-tree root for maintain/restructure; empty uses the default tree.
@@ -71,46 +73,4 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
71
73
  threatExemptLabels: z<string[], string[], "defined">;
72
74
  }>>, "plain">;
73
75
  export declare function apply(ctx: Context, rawConfig?: Config): void;
74
- /** F-211: the fs surface atomicWriteFiles uses — injectable so the commit-phase
75
- * rename-failure path is deterministically testable. Defaults to node:fs.
76
- * `mtime` (optional) probes a path's last-write time so the failed-commit
77
- * recovery message can name the generation it restored from. */
78
- interface FsOps {
79
- writeFileSync(path: string, data: string | Uint8Array): void;
80
- existsSync(path: string): boolean;
81
- copyFileSync(from: string, to: string): void;
82
- renameSync(from: string, to: string): void;
83
- rmSync(path: string, options?: {
84
- force?: boolean;
85
- recursive?: boolean;
86
- }): void;
87
- mtime?(path: string): number | null;
88
- }
89
- /**
90
- * S6.3 (E-40): atomically replace a set of files within one directory.
91
- * Each file is staged to a sibling `<name>.tmp`, then renamed into place
92
- * (atomic on the same filesystem); a pre-existing file keeps a single
93
- * `<name>.bak`. A failure at ANY staging step removes the staged temps and
94
- * leaves the previous files untouched — a half-written target is impossible
95
- * up to the staging and backup phases.
96
- *
97
- * F-211: the rename COMMIT phase does not carry the same guarantee. When a
98
- * filesystem refuses to overwrite the destination, the code removes it and
99
- * retries the rename; if the retry ALSO fails the destination is gone. The
100
- * single `.bak` created above still holds the previous content, so the target
101
- * is restored from it (best-effort) before the original rename error is
102
- * rethrown, so a failed commit never leaves the file missing.
103
- *
104
- * V4-17: the `.bak` is refreshed to the committed content after every
105
- * successful commit, so a later failed commit always recovers to the most
106
- * recent good generation (a once-at-first-install `.bak` could otherwise
107
- * restore content several installs old). The recovery error names the `.bak`
108
- * source (and mtime when available) so the caller knows the generation it
109
- * restored from.
110
- */
111
- export declare function atomicWriteFiles(targetDir: string, writes: Array<{
112
- name: string;
113
- content: string | Uint8Array;
114
- }>, fs?: FsOps, logger?: (message: string) => void): void;
115
- export {};
116
76
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,65 @@
1
+ /**
2
+ * F-4/G7.4 (C7): the ONE parser for the /evolution command surface.
3
+ *
4
+ * The surface used to answer each subcommand with its own regex (`^params(?: --group ([a-z-]+))?(?: --json)?$`
5
+ * and nine siblings), so `params --json --group review` and `params --group=review` were refused as
6
+ * "not a subcommand", while a sibling regex accepted `=` — and a mistyped group name degraded into the
7
+ * generic error instead of the one that lists the known groups.
8
+ *
9
+ * This parser is order- and `=`-tolerant, matches the subcommand name case-insensitively, keeps a flag
10
+ * VALUE's case intact (the domain layer is the one that validates it), and answers a SYNTAX failure when a
11
+ * declared value flag is left without its value (F-3: `policy set a.b --expect 3` must not read
12
+ * `--expect 3` as the value).
13
+ *
14
+ * @module @lmzhen/dsh-evolution-commands/parse
15
+ */
16
+ /** The flags whose declared form takes a value (`--group <name>`, `--expect <revision>`, …). */
17
+ /**
18
+ * Exported so the command-table gate can tie it to the table's usage lines (P2: two declarations of
19
+ * "which flags take a value" would otherwise be free to drift apart).
20
+ */
21
+ export declare const VALUE_FLAGS: readonly string[];
22
+ /** One parsed command line. */
23
+ export interface ParsedCommand {
24
+ /** The subcommand name, lower-cased (the table stores it lower-case too). */
25
+ readonly name: string;
26
+ /** Declared flags: a value when the flag takes one, `true` when it is bare. */
27
+ readonly flags: ReadonlyMap<string, string | true>;
28
+ /** Everything that was neither the name nor a flag, in order. */
29
+ readonly positionals: readonly string[];
30
+ }
31
+ /** A SYNTAX failure — the caller answers it as a usage error, never as a domain error. */
32
+ export interface ParseFailure {
33
+ /** Which syntax rule was broken. */
34
+ readonly kind: 'unknown-subcommand' | 'unknown-flag' | 'missing-value';
35
+ /** The subcommand name the caller saw (empty when the line was empty). */
36
+ readonly name: string;
37
+ /** The flag involved, for the two flag failures. */
38
+ readonly flag?: string;
39
+ }
40
+ /**
41
+ * Narrow a parse result: true when it is the syntax failure rather than a command.
42
+ * @param result - what {@link parseSubcommand} answered.
43
+ * @returns whether the line was refused.
44
+ */
45
+ export declare function isParseFailure(result: ParsedCommand | ParseFailure): result is ParseFailure;
46
+ /**
47
+ * Read one SUB-FORM line: `maintain status`, `maintain report`, … — the shape the regexes used to own.
48
+ *
49
+ * A sub-form matches only when: the line parses, the name matches, the first positional is the sub-form,
50
+ * and every flag the line carries is DECLARED by the table (an undeclared flag keeps the old
51
+ * "unknown arguments" answer instead of silently becoming a bare flag).
52
+ * @param input - the text after `/evolution`.
53
+ * @param name - the subcommand name the table declares (e.g. `maintain`).
54
+ * @param sub - the sub-form word (e.g. `status`).
55
+ * @param declaredFlags - the flags the table declares for `name` (`flagsOf(name)`).
56
+ * @returns the parsed command, or null when this line is not that sub-form.
57
+ */
58
+ export declare function subcommandOf(input: string, name: string, sub: string, declaredFlags: readonly string[]): ParsedCommand | null;
59
+ /**
60
+ * Parse one command line into its name, flags and positionals.
61
+ * @param input - the text after `/evolution`.
62
+ * @returns the parsed command, or the syntax failure that refused it.
63
+ */
64
+ export declare function parseSubcommand(input: string): ParsedCommand | ParseFailure;
65
+ //# sourceMappingURL=parse.d.ts.map
@@ -12,9 +12,17 @@
12
12
  export interface CommandEntry {
13
13
  /** The subcommand as typed after `/evolution`. Variants use `|` (curator run|pause). */
14
14
  usage: string;
15
+ /** C7: true when the subcommand only READS (no skill/param write). Stored: not derivable. */
16
+ readonly: boolean;
15
17
  /** One-line purpose rendered in the help output. */
16
18
  summary: string;
17
19
  }
20
+ /** The flags the TABLE declares for one subcommand (name → `--flag`), DERIVED from its usage. */
21
+ export declare function flagsOf(name: string): string[];
22
+ /** C7 shape, DERIVED: the subcommand name is the first token of `usage` (variants use `|`). */
23
+ export declare function entryName(entry: CommandEntry): string;
24
+ /** C7 shape, DERIVED: the flags a `usage` declares, in the form `--flag` (value flags keep their name). */
25
+ export declare function entryFlags(entry: CommandEntry): string[];
18
26
  export declare const COMMAND_ENTRIES: CommandEntry[];
19
27
  /** The input-declaration hint (single line, ` | `-separated). */
20
28
  export declare function renderHint(): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-commands",
3
3
  "description": "Human commands for the evolution family (/evolution pending|curator|maintain|doctor) (community build)",
4
- "version": "0.22.0",
4
+ "version": "0.24.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,17 +27,18 @@
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
29
  "@deepseek-ai/schemastery": "^3.18.4",
30
- "@lmzhen/dsh-evolution-approval": "^0.22.0",
31
- "@lmzhen/dsh-evolution-core": "^0.22.0",
32
- "@lmzhen/dsh-evolution-maintenance": "^0.22.0"
30
+ "@lmzhen/dsh-evolution-approval": "^0.24.0",
31
+ "@lmzhen/dsh-evolution-core": "^0.24.0",
32
+ "@lmzhen/dsh-evolution-maintenance": "^0.24.0"
33
33
  },
34
34
  "optionalDependencies": {
35
- "@lmzhen/dsh-evolution-agent-preset": "^0.22.0"
35
+ "@lmzhen/dsh-evolution-agent-preset": "^0.24.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@deepseek-ai/cordis": "^4.0.1",
39
39
  "@deepseek-ai/dsh-commands": "^0.2.0-rc.1",
40
- "@deepseek-ai/dsh-llm": "^0.2.0-rc.1"
40
+ "@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
41
+ "@lmzhen/dsh-evolution-io": "^0.24.0"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@deepseek-ai/dsh-commands": "^0.2.0-rc.1"