@okfit/cli 0.4.1 → 0.5.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 CHANGED
@@ -113,6 +113,34 @@ $ echo $?
113
113
  and names every colliding file in one error. An ancestor directory's config
114
114
  is a legitimate discovery hit, not a collision, and is never probed.
115
115
 
116
+ If the repository lints markdown, the bundle needs two exemptions from
117
+ markdownlint's defaults, and neither can be satisfied at the source: MD025
118
+ (one top-level heading) counts a concept's frontmatter `title:` as its H1,
119
+ so the body H1 the spec requires reads as a second one, and the spec shapes
120
+ every `index.md` as `# Section` groups, one H1 per concept type. `log.md`
121
+ is fine: `init` and `sync` both start it with `# Log`. Add this to a
122
+ `.markdownlint-cli2.jsonc` at the repository root, adjusting the bundle
123
+ path if `bundle.path` is not `okf`:
124
+
125
+ ```jsonc
126
+ "overrides": [
127
+ {
128
+ "combine": "merge",
129
+ "config": { "MD025": { "front_matter_title": "" } },
130
+ "filter": ["okf/**/*.md", "!okf/**/index.md"]
131
+ },
132
+ {
133
+ "combine": "merge",
134
+ "config": { "MD025": false },
135
+ "filter": ["okf/**/index.md"]
136
+ }
137
+ ]
138
+ ```
139
+
140
+ A repository whose lint config cannot express overrides can drop a nested
141
+ `okf/.markdownlint-cli2.jsonc` carrying `{ "config": { "MD025": false } }`
142
+ instead; the bundle loader ignores non-markdown files.
143
+
116
144
  `--profile <name>` picks the profile `init` scaffolds for (default: the
117
145
  config's `bundle.profile`, itself defaulting to `software-project`); an
118
146
  unrecognised name is a warning, not a failure — `init` continues with the
package/commands/init.js CHANGED
@@ -3,8 +3,7 @@ import { useColor } from "../internal/tty.js";
3
3
  import { displayRoot, human, summary } from "../render/human.js";
4
4
  import { Argument, Command, Flag } from "effect/unstable/cli";
5
5
  import { CONFIG_RELATIVE_PATH, InitOverwriteError, Now, SCHEMA_DIRECTIVE, collect, configValue, files, forDiagnostics, provideConfig, resolveBundleRoot, resolveProjectRoot, run, targetPaths } from "@okfit/engine";
6
- import { Console, DateTime, Effect, FileSystem, Layer, Option, Path, Schema } from "effect";
7
- import { TomlCodec } from "@effected/config-file";
6
+ import { Console, DateTime, Effect, FileSystem, Layer, Option, Path } from "effect";
8
7
  import { Git } from "@effected/git";
9
8
  import { OKF_SPEC_VERSION, OkfitConfig, OkfitConfigFile } from "@okfit/core";
10
9
  import { GitHistory, Profiles } from "@okfit/profiles";
@@ -100,7 +99,8 @@ const initCommand = Command.make("init", {
100
99
  explicitConfigPath: input.config,
101
100
  discoveryCwd
102
101
  })(Effect.gen(function* () {
103
- const winner = (yield* (yield* OkfitConfigFile).discover)[0];
102
+ const configFile = yield* OkfitConfigFile;
103
+ const winner = (yield* configFile.discover)[0];
104
104
  const fileConfig = winner === void 0 ? { extensions: {} } : winner.value;
105
105
  const profileName = Option.getOrElse(input.profile, () => fileConfig.bundle?.profile ?? DEFAULT_PROFILE_NAME);
106
106
  const profile = Profiles.get(profileName);
@@ -145,12 +145,10 @@ const initCommand = Command.make("init", {
145
145
  });
146
146
  for (const target of paths) yield* fs.makeDirectory(path.dirname(target), { recursive: true });
147
147
  const bundlePath = merged.bundle?.path ?? DEFAULT_BUNDLE_PATH;
148
- const encoded = yield* Schema.encodeEffect(OkfitConfig)(configValue({
148
+ yield* configFile.write(configValue({
149
149
  ...scaffoldOptions,
150
150
  bundlePath
151
- }));
152
- const toml = yield* TomlCodec.stringify(encoded);
153
- yield* fs.writeFileString(`${projectRoot}/${CONFIG_RELATIVE_PATH}`, `${SCHEMA_DIRECTIVE}${toml}`);
151
+ }), `${projectRoot}/${CONFIG_RELATIVE_PATH}`, { header: SCHEMA_DIRECTIVE });
154
152
  const scaffoldFiles = yield* files(scaffoldOptions);
155
153
  for (const file of scaffoldFiles) yield* fs.writeFileString(file.path, file.contents);
156
154
  yield* Console.log(`Initialized ${displayRoot(cwd, bundleRoot, path)} with the ${profileName} profile`);
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/Crypto").Crypto | 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("@effected/config-file").ConfigFileWriteError | 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
  /**
@@ -66,8 +66,9 @@ export declare const renderFailure: (error: unknown) => ReadonlyArray<string>;
66
66
  //#endregion
67
67
  //#region src/render/context.d.ts
68
68
  /**
69
- * The `human` format: a short header block, then one line per type and one
70
- * per tag. Pure; the caller pipes each line through `Console.log`.
69
+ * The `human` format: a short header block, then one line per type (plus
70
+ * its constraint lines, when it has any) and one per tag. Pure; the caller
71
+ * pipes each line through `Console.log`.
71
72
  *
72
73
  * The `profile:` line reads `profile: (none) (requested NAME, unknown)`
73
74
  * when `profile` and `profile_requested` disagree over an actually-unknown
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okfit/cli",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "description": "The okfit command line: validate, lint, index, and inspect Open Knowledge Format (OKF) bundles.",
6
6
  "keywords": [
@@ -43,18 +43,18 @@
43
43
  },
44
44
  "dependencies": {
45
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",
46
+ "@effected/cli": "^0.4.1",
47
+ "@effected/config-file": "^0.9.0",
48
+ "@effected/git": "^0.15.1",
49
49
  "@effected/glob": "^0.6.0",
50
50
  "@effected/jsonc": "^0.11.0",
51
51
  "@effected/markdown": "^0.10.0",
52
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",
53
+ "@effected/walker": "^0.9.0",
54
+ "@effected/yaml": "^0.15.1",
55
+ "@okfit/core": "0.4.0",
56
+ "@okfit/engine": "0.3.0",
57
+ "@okfit/profiles": "0.4.0",
58
58
  "effect": "4.0.0-rc.115"
59
59
  },
60
60
  "engines": {
package/render/context.js CHANGED
@@ -1,7 +1,20 @@
1
1
  //#region src/render/context.ts
2
+ /** `kind (a | b)` for an enum field, `resource (path)` for a path field, bare `layer` for free text. */
3
+ const renderField = (field) => field.values !== null ? `${field.name} (${field.values.map((v) => v.name).join(" | ")})` : field.kind !== null ? `${field.name} (${field.kind})` : field.name;
2
4
  /**
3
- * The `human` format: a short header block, then one line per type and one
4
- * per tag. Pure; the caller pipes each line through `Console.log`.
5
+ * The constraint lines under one type bullet (issue #33): what `validate`
6
+ * will require of a concept of this type, so an agent learns it here and
7
+ * not from a lint error. Empty for a type that declares none.
8
+ */
9
+ const constraintLines = (type) => [
10
+ ...type.required !== null && type.required.length > 0 ? [` required: ${type.required.join(", ")}`] : [],
11
+ ...type.require_verified === true ? [" verified: required"] : [],
12
+ ...type.fields.length > 0 ? [` fields: ${type.fields.map(renderField).join(", ")}`] : []
13
+ ];
14
+ /**
15
+ * The `human` format: a short header block, then one line per type (plus
16
+ * its constraint lines, when it has any) and one per tag. Pure; the caller
17
+ * pipes each line through `Console.log`.
5
18
  *
6
19
  * The `profile:` line reads `profile: (none) (requested NAME, unknown)`
7
20
  * when `profile` and `profile_requested` disagree over an actually-unknown
@@ -19,7 +32,7 @@ const humanContext = (envelope) => [
19
32
  `agent: ${envelope.actors.agent ?? "(unset)"}`,
20
33
  "",
21
34
  "types:",
22
- ...envelope.types.map((t) => ` ${t.name} ${t.description ?? ""}`),
35
+ ...envelope.types.flatMap((t) => [` ${t.name} ${t.description ?? ""}`, ...constraintLines(t)]),
23
36
  "",
24
37
  "tags:",
25
38
  ...envelope.tags.map((t) => ` ${t.name} ${t.description ?? ""}`)
package/version.js CHANGED
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * @public
10
10
  */
11
- const CLI_VERSION = "0.4.1";
11
+ const CLI_VERSION = "0.5.0";
12
12
 
13
13
  //#endregion
14
14
  export { CLI_VERSION };