@okfit/cli 0.3.0 → 0.4.1

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
@@ -51,13 +51,16 @@ diagnostic (no file at all) prints `(bundle)` in place of `<file>`.
51
51
  Diagnostics sort by file (so `(bundle)` leads), then range-less before
52
52
  ranged, then by offset, then by code.
53
53
 
54
- `--skip-provenance` skips the `generated-at-drift` lint's git tier
55
- (`Provenance.lint`) for this one invocation, without touching the
56
- project's `[lint]` table — the same effect as `generated_at_drift = "off"`
57
- in config, scoped to a single run. The Claude Code plugin's PostToolUse
58
- hook passes it on every edit-time `validate` call so a git spawn per
59
- concept never runs on every keystroke-level edit; CI and the MCP
60
- `validate_bundle` tool omit the flag and keep the lint.
54
+ `--skip-provenance` skips the `generated-at-drift` lint's git tier for
55
+ this one invocation, without touching the project's `[lint]` table. That
56
+ is `Provenance.lint`'s tier 2 only — the git-derived date comparison used
57
+ for a concept stamped before `generated.body_sha256` existed. The digest
58
+ tier still runs: it compares the recorded digest against the body already
59
+ in memory, so it spawns nothing and still reports a body edited without a
60
+ re-stamp. The Claude Code plugin's PostToolUse hook passes the flag on
61
+ every edit-time `validate` call so a git spawn per concept never runs on
62
+ keystroke-level edits; CI and the MCP `validate_bundle` tool omit it and
63
+ keep both tiers.
61
64
 
62
65
  ### `okfit init`
63
66
 
@@ -7,11 +7,11 @@ import { Console, Effect, Option, Schema } from "effect";
7
7
 
8
8
  //#region src/commands/context.ts
9
9
  /** `[path]` is the PROJECT root (K-2), never the bundle root. Absolute at parse time (K-50). */
10
- const pathArg = Argument.path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
10
+ const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
11
11
  /** K-1: no `mustExist` — the handler stats the path itself, before building any layer. */
12
- const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
12
+ const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
13
13
  /** No `--profile` flag: M-15's exact ruling; that flag belongs to `init` alone. */
14
- const formatFlag = Flag.choice("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
14
+ const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
15
15
  /**
16
16
  * `okfit context [path] [--config <file>] [--format human|json]`.
17
17
  *
package/commands/init.js CHANGED
@@ -12,19 +12,19 @@ import { GitHistory, Profiles } from "@okfit/profiles";
12
12
  //#region src/commands/init.ts
13
13
  /**
14
14
  * `[path]` is the PROJECT root (K-2), never the bundle root — identical to
15
- * `validate`'s own argument (`Argument.path` resolves it absolute at the
15
+ * `validate`'s own argument (`Argument.Path` resolves it absolute at the
16
16
  * parse boundary, satisfying K-50).
17
17
  */
18
- const pathArg = Argument.path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
18
+ const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
19
19
  /** K-1: no `mustExist` — existence is checked by `provideConfig`, identical to `validate`'s flag. */
20
- const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
20
+ const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
21
21
  /**
22
- * K-3: `Flag.string`, deliberately not `Flag.choice` against
22
+ * K-3: `Flag.String`, deliberately not `Flag.Literals` against
23
23
  * `PROFILE_NAMES` (`PROFILES/Profile.ts:10`) — an unrecognised name is a
24
24
  * CLI-rendered warning (K-4), matching `Profiles.get`'s own `Option.none`
25
25
  * contract (P-38), not a parser-level `CliError.InvalidValue`.
26
26
  */
27
- const profileFlag = Flag.string("profile").pipe(Flag.optional, Flag.withDescription("profile to scaffold with (default: the config's bundle.profile or software-project)"));
27
+ const profileFlag = Flag.String("profile").pipe(Flag.optional, Flag.withDescription("profile to scaffold with (default: the config's bundle.profile or software-project)"));
28
28
  /**
29
29
  * Stands in for `profile.config` when `Profiles.get` returns `None`.
30
30
  * `OkfitConfig.merge` only visits `Object.keys(override)`
package/commands/sync.js CHANGED
@@ -10,11 +10,11 @@ import { GitHistory } from "@okfit/profiles";
10
10
 
11
11
  //#region src/commands/sync.ts
12
12
  /** K-2: `[path]` is the PROJECT root, byte-identical to validate/init/context/verify's. */
13
- const pathArg = Argument.path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory)"));
13
+ const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory)"));
14
14
  /** K-1: no `mustExist` — the handler stats it via `provideConfig`. */
15
- const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
15
+ const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
16
16
  /**
17
- * S-13: a REPEATED `Flag.choice`, not a comma-separated `Flag.string`.
17
+ * S-13: a REPEATED `Flag.Literals`, not a comma-separated `Flag.String`.
18
18
  * `Flag.atLeast(0)` allows zero occurrences (all three modes run) up
19
19
  * through any number. Each occurrence is independently validated by the
20
20
  * underlying `Choice` primitive, so a bad token (`--only badmode`) is a
@@ -22,22 +22,22 @@ const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription(
22
22
  * existing 64 remap — no new error class, no hand-built `ShowHelp`
23
23
  * (contract §11, S-13, judge note 9).
24
24
  *
25
- * Note: `Flag.choice`'s installed signature (`effect/unstable/cli/Flag.d.ts:161`)
26
- * takes `(name: string, choices: ReadonlyArray<string>)`, matching
25
+ * Note: `Flag.Literals`'s installed signature (`effect/unstable/cli/Flag.ts:169-172`)
26
+ * takes `(name: string, literals: ReadonlyArray<string>)`, matching
27
27
  * `formatFlag` below — not the `[value, label]` tuple-pair form
28
- * `Flag.choiceWithValue` takes. The contract's own `onlyFlag` sketch
28
+ * `Flag.ChoiceWithValue` takes. The contract's own `onlyFlag` sketch
29
29
  * writes tuple pairs; since every pair's two elements are identical
30
30
  * (`["generated", "generated"]`, etc.), the plain string-array form
31
31
  * below is the same flag, verified against the installed primitive
32
32
  * rather than copied byte-for-byte from the contract's prose.
33
33
  */
34
- const onlyFlag = Flag.choice("only", [
34
+ const onlyFlag = Flag.Literals("only", [
35
35
  "generated",
36
36
  "index",
37
37
  "log"
38
38
  ]).pipe(Flag.atLeast(0), Flag.withDescription("restrict the run to these modes (repeatable: --only generated --only index); default: all three"));
39
- const dryRunFlag = Flag.boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("compute every result and write nothing"));
40
- const formatFlag = Flag.choice("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
39
+ const dryRunFlag = Flag.Boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("compute every result and write nothing"));
40
+ const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
41
41
  /**
42
42
  * `okfit sync [path] [--config <file>] [--only <mode>]... [--dry-run]
43
43
  * [--format human|json]`.
@@ -11,13 +11,13 @@ import { GitHistory } from "@okfit/profiles";
11
11
 
12
12
  //#region src/commands/validate.ts
13
13
  /** `[path]` is the PROJECT root (K-2), never the bundle root. Absolute at parse time (K-50). */
14
- const pathArg = Argument.path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
14
+ const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
15
15
  /** K-1: no `mustExist` — the handler stats the path itself, before building any layer. */
16
- const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
16
+ const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
17
17
  /** K-6: `--format` is on `validate` only. */
18
- const formatFlag = Flag.choice("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
18
+ const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
19
19
  /** S-31: skips `Provenance.lint`'s git tier for this invocation, without touching `[lint]`. */
20
- const skipProvenanceFlag = Flag.boolean("skip-provenance").pipe(Flag.withDefault(false), Flag.withDescription("skip the generated-at-drift lint's git tier for this run"));
20
+ const skipProvenanceFlag = Flag.Boolean("skip-provenance").pipe(Flag.withDefault(false), Flag.withDescription("skip the generated-at-drift lint's git tier for this run"));
21
21
  /**
22
22
  * `okfit validate [path] [--config <file>] [--format human|json] [--skip-provenance]`.
23
23
  *
@@ -9,17 +9,17 @@ import { Git } from "@effected/git";
9
9
  import { Timestamp } from "@okfit/core";
10
10
 
11
11
  //#region src/commands/verify.ts
12
- /** V-6: tolerant id, normalised through `ConceptId.normalize`; never `Argument.path`. */
13
- const idArg = Argument.string("id").pipe(Argument.withDescription("concept id to verify, with or without a leading slash or trailing .md"));
12
+ /** V-6: tolerant id, normalised through `ConceptId.normalize`; never `Argument.Path`. */
13
+ const idArg = Argument.String("id").pipe(Argument.withDescription("concept id to verify, with or without a leading slash or trailing .md"));
14
14
  /** K-2: `[path]` is the PROJECT root, byte-identical to validate/init/context's. */
15
- const pathArg = Argument.path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
15
+ const pathArg = Argument.Path("path", { pathType: "directory" }).pipe(Argument.optional, Argument.withDescription("project root to start config discovery from (default: current directory); never the bundle root"));
16
16
  /** K-1: no `mustExist`; the handler stats it via `provideConfig`. */
17
- const configFlag = Flag.file("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
18
- /** V-6: `Flag.string`, decoded through core's `Timestamp` — never `Flag.date`, which yields a bare Date. */
19
- const atFlag = Flag.string("at").pipe(Flag.optional, Flag.withDescription("ISO 8601 timestamp with an explicit offset to record instead of now"));
17
+ const configFlag = Flag.File("config").pipe(Flag.optional, Flag.withDescription("explicit config file; skips discovery"));
18
+ /** V-6: `Flag.String`, decoded through core's `Timestamp` — never `Flag.Date`, which yields a bare Date. */
19
+ const atFlag = Flag.String("at").pipe(Flag.optional, Flag.withDescription("ISO 8601 timestamp with an explicit offset to record instead of now"));
20
20
  /** V-6/V-8: the preview is a flag, never a prompt. */
21
- const dryRunFlag = Flag.boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("print the exact fragment a real run would splice in; write nothing"));
22
- const formatFlag = Flag.choice("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
21
+ const dryRunFlag = Flag.Boolean("dry-run").pipe(Flag.withDefault(false), Flag.withDescription("print the exact fragment a real run would splice in; write nothing"));
22
+ const formatFlag = Flag.Literals("format", ["human", "json"]).pipe(Flag.withDefault("human"), Flag.withDescription("output format: human (default) or json"));
23
23
  /**
24
24
  * `okfit verify <id> [path] [--config <file>] [--at <iso>] [--dry-run]
25
25
  * [--format human|json]`.
package/index.d.ts CHANGED
@@ -20,7 +20,7 @@ import "effect";
20
20
  *
21
21
  * @public
22
22
  */
23
- export declare const rootCommand: Command.Command<"okfit", {} | {}, {}, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/config-file").ConfigCodecError | import("@effected/config-file").ConfigFileReadError | import("@okfit/engine").ConfigMalformedError | import("@okfit/engine").ConfigPathNotFoundError | import("@effected/config-file").ConfigValidationError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@effected/git").NotARepositoryError | import("effect/PlatformError").PlatformError | import("effect/Schema").SchemaError | import("@effected/git").UnknownRefError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("@effected/xdg").Xdg>;
23
+ export declare const rootCommand: Command.Command<"okfit", {} | {}, {}, import("@okfit/profiles").AgentActorUnconfiguredError | import("@okfit/core").BundleDepthExceededError | import("@okfit/core").BundleReadError | import("@okfit/core").BundleRootNotFoundError | import("@effected/config-file").ConfigCodecError | import("@effected/config-file").ConfigFileReadError | import("@okfit/engine").ConfigMalformedError | import("@okfit/engine").ConfigPathNotFoundError | import("@effected/config-file").ConfigValidationError | import("@effected/markdown").FrontmatterEncodeError | import("@effected/markdown").FrontmatterFormatMismatchError | import("@effected/markdown").FrontmatterValidationError | import("@effected/git").GitCommandError | import("@okfit/profiles").GitHistoryError | import("@okfit/profiles").HumanActorUnresolvedError | import("@okfit/engine").InitOverwriteError | import("@effected/markdown").MarkdownParseError | import("@effected/git").NotARepositoryError | import("effect/PlatformError").PlatformError | import("effect/Schema").SchemaError | import("@effected/git").UnknownRefError | import("@okfit/engine").VerifyConceptNotFoundError | import("@okfit/engine").VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError, import("@effected/xdg").AppDirs | import("effect/unstable/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/Crypto").Crypto | import("effect/FileSystem").FileSystem | import("@okfit/engine").Now | import("effect/Path").Path | import("@effected/xdg").Xdg>;
24
24
  //#endregion
25
25
  //#region src/errors.d.ts
26
26
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okfit/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "private": false,
5
5
  "description": "The okfit command line: validate, lint, index, and inspect Open Knowledge Format (OKF) bundles.",
6
6
  "keywords": [
@@ -42,20 +42,20 @@
42
42
  "okfit": "bin/okfit.js"
43
43
  },
44
44
  "dependencies": {
45
- "@effect/platform-node": "4.0.0-rc.112",
46
- "@effected/cli": "^0.3.1",
47
- "@effected/config-file": "^0.7.0",
48
- "@effected/git": "^0.12.0",
49
- "@effected/glob": "^0.5.0",
50
- "@effected/jsonc": "^0.9.0",
51
- "@effected/markdown": "^0.9.1",
52
- "@effected/toml": "^0.6.0",
53
- "@effected/walker": "^0.7.0",
54
- "@effected/yaml": "^0.14.0",
55
- "@okfit/core": "0.2.0",
56
- "@okfit/engine": "0.1.0",
57
- "@okfit/profiles": "0.2.0",
58
- "effect": "4.0.0-rc.112"
45
+ "@effect/platform-node": "4.0.0-rc.115",
46
+ "@effected/cli": "^0.4.0",
47
+ "@effected/config-file": "^0.8.0",
48
+ "@effected/git": "^0.15.0",
49
+ "@effected/glob": "^0.6.0",
50
+ "@effected/jsonc": "^0.11.0",
51
+ "@effected/markdown": "^0.10.0",
52
+ "@effected/toml": "^0.7.0",
53
+ "@effected/walker": "^0.8.0",
54
+ "@effected/yaml": "^0.15.0",
55
+ "@okfit/core": "0.3.1",
56
+ "@okfit/engine": "0.2.1",
57
+ "@okfit/profiles": "0.3.1",
58
+ "effect": "4.0.0-rc.115"
59
59
  },
60
60
  "engines": {
61
61
  "node": ">=24.11.0"
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.59.0"
8
+ "packageVersion": "7.59.1"
9
9
  }
10
10
  ]
11
11
  }
package/version.js CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @public
10
10
  */
11
- const CLI_VERSION = "0.3.0";
11
+ const CLI_VERSION = "0.4.1";
12
12
 
13
13
  //#endregion
14
14
  export { CLI_VERSION };