@okfit/engine 0.12.0 → 0.13.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.
@@ -1,5 +1,5 @@
1
1
  import { documentNewline, locate, locateTopLevelScalar, stripBom } from "../verify/locate.js";
2
- import { splice, spliceTopLevelScalar } from "../verify/splice.js";
2
+ import { orderVerifyEdits, splice, spliceTopLevelScalar } from "../verify/splice.js";
3
3
  import { DiagnosticRange } from "@okfit/core";
4
4
  import { Effect, Result, Runtime, Schema } from "effect";
5
5
  import { MarkdownDocument, MarkdownEdit } from "@effected/markdown";
@@ -29,6 +29,8 @@ const shift = (edit, by) => by === 0 ? edit : MarkdownEdit.make({
29
29
  length: edit.length,
30
30
  content: edit.content
31
31
  });
32
+ /** The value of a located scalar's raw source text, quotes removed. */
33
+ const unquote = (raw, quote) => quote === "plain" ? raw.trim() : raw.slice(1, -1);
32
34
  /**
33
35
  * A public facade over the `verify/locate.ts` and `verify/splice.ts`
34
36
  * machinery: byte-range `MarkdownEdit`s for a concept's top-level `status`
@@ -72,6 +74,31 @@ var FrontmatterEdits = class {
72
74
  return [shift(edit, bom.length)];
73
75
  });
74
76
  /**
77
+ * Edits that append one verified entry AND set top-level `status`, the combined write
78
+ * `okfit verify --stable` performs. A `status` scalar already equal to `status` makes no
79
+ * status edit, and equal-offset inserts are merged with `status:` first. Unlike the CLI,
80
+ * which reads the parsed status, this always locates `status`, so an unsupported shape
81
+ * on it fails even when its value already matches.
82
+ */
83
+ static verifiedWithStatus = (source, entry, status) => Effect.gen(function* () {
84
+ const { text, bom } = stripBom(source);
85
+ const located = yield* locate(text);
86
+ if (located._tag === "unsupported") return yield* new UnsupportedFrontmatterError({
87
+ key: "verified",
88
+ shape: located.shape
89
+ });
90
+ const newline = documentNewline(text);
91
+ const verifiedEdit = splice(located, entry, newline);
92
+ let statusEdit;
93
+ const target = yield* locateTopLevelScalar(text, "status");
94
+ if (target._tag === "unsupported") return yield* new UnsupportedFrontmatterError({
95
+ key: "status",
96
+ shape: target.shape
97
+ });
98
+ if (target._tag !== "replaceScalar" || unquote(text.slice(target.start, target.end), target.quote) !== status) statusEdit = spliceTopLevelScalar(target, "status", status, newline);
99
+ return orderVerifyEdits(verifiedEdit, statusEdit).map((edit) => shift(edit, bom.length));
100
+ });
101
+ /**
75
102
  * Edits that stamp `renders[i].body_sha256` with `digests[i]`: an existing value is replaced in
76
103
  * place, a missing key is inserted on the line after `renders[i].path` at that key's column.
77
104
  * Block-style `renders` only; flow style fails with `UnsupportedFrontmatterError`.
package/index.d.ts CHANGED
@@ -479,6 +479,17 @@ export declare class FrontmatterEdits {
479
479
  readonly by: string;
480
480
  readonly at: string;
481
481
  }) => Effect.Effect<ReadonlyArray<MarkdownEdit>, YamlParseError | UnsupportedFrontmatterError>;
482
+ /**
483
+ * Edits that append one verified entry AND set top-level `status`, the combined write
484
+ * `okfit verify --stable` performs. A `status` scalar already equal to `status` makes no
485
+ * status edit, and equal-offset inserts are merged with `status:` first. Unlike the CLI,
486
+ * which reads the parsed status, this always locates `status`, so an unsupported shape
487
+ * on it fails even when its value already matches.
488
+ */
489
+ static readonly verifiedWithStatus: (source: string, entry: {
490
+ readonly by: string;
491
+ readonly at: string;
492
+ }, status: Status) => Effect.Effect<ReadonlyArray<MarkdownEdit>, YamlParseError | UnsupportedFrontmatterError>;
482
493
  /**
483
494
  * Edits that stamp `renders[i].body_sha256` with `digests[i]`: an existing value is replaced in
484
495
  * place, a missing key is inserted on the line after `renders[i].path` at that key's column.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okfit/engine",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "private": false,
5
5
  "description": "The okfit engine: platform layer, config discovery, and the validate, verify, sync, init and context programs shared by the okfit CLI and MCP server.",
6
6
  "keywords": [
@@ -34,23 +34,23 @@
34
34
  "./package.json": "./package.json"
35
35
  },
36
36
  "dependencies": {
37
- "@effect/platform-node": "^4.0.0",
38
- "@effected/app": "^0.20.0",
39
- "@effected/config-file": "^0.14.0",
40
- "@effected/engine": "^0.3.0",
37
+ "@effect/platform-node": "^4.0.1",
38
+ "@effected/app": "^0.21.2",
39
+ "@effected/config-file": "^0.14.2",
40
+ "@effected/engine": "^0.4.0",
41
41
  "@effected/git": "^0.20.0",
42
42
  "@effected/glob": "^0.10.0",
43
- "@effected/jsonc": "^0.15.0",
44
- "@effected/markdown": "^0.15.0",
45
- "@effected/schemastore": "^0.20.0",
46
- "@effected/store": "^0.12.0",
47
- "@effected/toml": "^0.11.0",
43
+ "@effected/jsonc": "^0.15.1",
44
+ "@effected/markdown": "^0.15.1",
45
+ "@effected/schemastore": "^0.21.1",
46
+ "@effected/store": "^0.13.1",
47
+ "@effected/toml": "^0.11.1",
48
48
  "@effected/walker": "^0.15.0",
49
49
  "@effected/xdg": "^0.9.0",
50
- "@effected/yaml": "^0.19.0",
51
- "@okfit/core": "0.9.0",
50
+ "@effected/yaml": "^0.19.1",
51
+ "@okfit/core": "0.9.1",
52
52
  "@okfit/profiles": "0.9.0",
53
- "effect": "^4.0.0"
53
+ "effect": "^4.0.1"
54
54
  },
55
55
  "engines": {
56
56
  "node": ">=24.11.0"
package/verify/run.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { VerifyConceptNotFoundError, VerifyUnsupportedFrontmatterError } from "../errors.js";
2
2
  import { documentNewline, locate, locateTopLevelScalar, stripBom } from "./locate.js";
3
- import { mergeSameOffset, splice, spliceTopLevelScalar } from "./splice.js";
3
+ import { orderVerifyEdits, splice, spliceTopLevelScalar } from "./splice.js";
4
4
  import { resolveBatchTypes, selectAttestable, selectPickerCandidates } from "./select.js";
5
5
  import { Bundle, ConceptId, Timestamp } from "@okfit/core";
6
6
  import { Effect, FileSystem, Option, Path, Schema } from "effect";
@@ -52,7 +52,7 @@ const prepareVerify = Effect.fn("okfit/verify/prepareVerify")(function* (bundle,
52
52
  });
53
53
  statusEdit = spliceTopLevelScalar(target, "status", status, newline);
54
54
  }
55
- const edits = mergeSameOffset([verifiedEdit, ...statusEdit === void 0 ? [] : [statusEdit]].toSorted((a, b) => a.offset - b.offset || (a === statusEdit ? -1 : b === statusEdit ? 1 : 0)));
55
+ const edits = orderVerifyEdits(verifiedEdit, statusEdit);
56
56
  return {
57
57
  absolutePath,
58
58
  finalText: bom + MarkdownEdit.applyAll(text, edits),
package/verify/splice.js CHANGED
@@ -153,6 +153,16 @@ const mergeSameOffset = (edits) => {
153
153
  }
154
154
  return out;
155
155
  };
156
+ /**
157
+ * Fold a concept's `verified` edit and optional `status` edit into the ordered,
158
+ * merged edit list both `okfit verify --stable` and `FrontmatterEdits` apply:
159
+ * status first on equal offsets, so the merged insert emits `status:` before
160
+ * `verified:`. The tie-break is by object identity -- the two edits are
161
+ * otherwise indistinguishable.
162
+ *
163
+ * @internal
164
+ */
165
+ const orderVerifyEdits = (verifiedEdit, statusEdit) => mergeSameOffset([verifiedEdit, ...statusEdit === void 0 ? [] : [statusEdit]].toSorted((a, b) => a.offset - b.offset || (a === statusEdit ? -1 : b === statusEdit ? 1 : 0)));
156
166
 
157
167
  //#endregion
158
- export { mergeSameOffset, splice, spliceGenerated, spliceGeneratedBlock, spliceGeneratedFields, spliceTopLevelScalar };
168
+ export { mergeSameOffset, orderVerifyEdits, splice, spliceGenerated, spliceGeneratedBlock, spliceGeneratedFields, spliceTopLevelScalar };
package/version.js CHANGED
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @public
13
13
  */
14
- const ENGINE_VERSION = "0.12.0";
14
+ const ENGINE_VERSION = "0.13.0";
15
15
 
16
16
  //#endregion
17
17
  export { ENGINE_VERSION };