@okfit/engine 0.3.0 → 0.4.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/graph/run.js +20 -0
- package/index.d.ts +188 -3
- package/index.js +5 -1
- package/package.json +3 -3
- package/render/graph.js +77 -0
- package/render/json.js +7 -1
- package/render/stale.js +62 -0
- package/stale/run.js +22 -0
package/graph/run.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Bundle, Graph } from "@okfit/core";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/graph/run.ts
|
|
5
|
+
/**
|
|
6
|
+
* Load the bundle and build its link graph (D-6, D-26). Pure over the
|
|
7
|
+
* loaded bundle once loading succeeds; `okfit graph` always exits `0`.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
const runGraph = (options) => Effect.gen(function* () {
|
|
12
|
+
const bundle = yield* Bundle.load({ root: options.root });
|
|
13
|
+
return {
|
|
14
|
+
bundle,
|
|
15
|
+
graph: Graph.fromBundle(bundle)
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { runGraph };
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BundleLoadError, ConceptId, Diagnostic, DiagnosticRange, DiagnosticSeverity, LoadedBundle, OkfitConfig, OkfitConfigFile, ValidationReport } from "@okfit/core";
|
|
1
|
+
import { BundleLoadError, ConceptId, Diagnostic, DiagnosticRange, DiagnosticSeverity, GraphLink, GraphNode, LinkGraph, LoadedBundle, OkfitConfig, OkfitConfigFile, StaleConcept, ValidationReport } from "@okfit/core";
|
|
2
2
|
import { Context, Crypto, DateTime, Effect, FileSystem, Layer, Option, Path, PlatformError, Runtime, Schema } from "effect";
|
|
3
3
|
import { AppDirs, Xdg } from "@effected/xdg";
|
|
4
4
|
import { ConfigReadError } from "@effected/config-file";
|
|
@@ -331,6 +331,25 @@ interface ContextResult {
|
|
|
331
331
|
*/
|
|
332
332
|
export declare const runContext: (options: ContextRunOptions) => Effect.Effect<ContextResult, never, FileSystem.FileSystem | Path.Path>;
|
|
333
333
|
//#endregion
|
|
334
|
+
//#region src/graph/run.d.ts
|
|
335
|
+
/** @public */
|
|
336
|
+
interface GraphRunOptions {
|
|
337
|
+
/** Absolute bundle root; `Bundle.load` never reads cwd (D-8). */
|
|
338
|
+
readonly root: string;
|
|
339
|
+
}
|
|
340
|
+
/** @public */
|
|
341
|
+
interface GraphRunResult {
|
|
342
|
+
readonly bundle: LoadedBundle;
|
|
343
|
+
readonly graph: LinkGraph;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Load the bundle and build its link graph (D-6, D-26). Pure over the
|
|
347
|
+
* loaded bundle once loading succeeds; `okfit graph` always exits `0`.
|
|
348
|
+
*
|
|
349
|
+
* @public
|
|
350
|
+
*/
|
|
351
|
+
export declare const runGraph: (options: GraphRunOptions) => Effect.Effect<GraphRunResult, BundleLoadError, FileSystem.FileSystem | Path.Path>;
|
|
352
|
+
//#endregion
|
|
334
353
|
//#region src/init/scaffold.d.ts
|
|
335
354
|
/** `.config/okfit.toml`, relative to the project root (C-10). @public */
|
|
336
355
|
export declare const CONFIG_RELATIVE_PATH = ".config/okfit.toml";
|
|
@@ -626,6 +645,79 @@ export declare const tally: (diagnostics: ReadonlyArray<RenderedDiagnostic>) =>
|
|
|
626
645
|
*/
|
|
627
646
|
export declare const forDiagnostics: (diagnostics: ReadonlyArray<RenderedDiagnostic>) => 0 | 1 | 2;
|
|
628
647
|
//#endregion
|
|
648
|
+
//#region src/render/graph.d.ts
|
|
649
|
+
/** One entry of the `nodes` array. @public */
|
|
650
|
+
export declare const GraphNodeEnvelope: Schema.Struct<{
|
|
651
|
+
readonly id: Schema.String;
|
|
652
|
+
readonly kind: Schema.Literals<readonly ["concept", "file", "missing"]>;
|
|
653
|
+
}>;
|
|
654
|
+
/** @public */
|
|
655
|
+
export type GraphNodeEnvelope = typeof GraphNodeEnvelope.Type;
|
|
656
|
+
/** One entry of the `edges` array; `field` is omitted, never `null` (exactOptionalPropertyTypes). @public */
|
|
657
|
+
export declare const GraphEdgeEnvelope: Schema.Struct<{
|
|
658
|
+
readonly from: Schema.String;
|
|
659
|
+
readonly to: Schema.String;
|
|
660
|
+
readonly source: Schema.Literals<readonly ["body", "frontmatter"]>;
|
|
661
|
+
readonly field: Schema.optionalKey<Schema.String>;
|
|
662
|
+
readonly raw: Schema.String;
|
|
663
|
+
}>;
|
|
664
|
+
/** @public */
|
|
665
|
+
export type GraphEdgeEnvelope = typeof GraphEdgeEnvelope.Type;
|
|
666
|
+
/** @public */
|
|
667
|
+
export declare const GraphSummary: Schema.Struct<{
|
|
668
|
+
readonly nodes: Schema.Number;
|
|
669
|
+
readonly edges: Schema.Number;
|
|
670
|
+
}>;
|
|
671
|
+
/** @public */
|
|
672
|
+
export type GraphSummary = typeof GraphSummary.Type;
|
|
673
|
+
/**
|
|
674
|
+
* `okfit graph --format json`'s envelope, schema 1, snake_case — the same
|
|
675
|
+
* convention as `render/json.ts`'s `JsonEnvelope`. Built from
|
|
676
|
+
* `LinkGraph.nodes`/`LinkGraph.edges` (D-26).
|
|
677
|
+
*
|
|
678
|
+
* @public
|
|
679
|
+
*/
|
|
680
|
+
export declare const GraphEnvelope: Schema.Struct<{
|
|
681
|
+
readonly schema: Schema.Literal<1>;
|
|
682
|
+
readonly okfit_version: Schema.String;
|
|
683
|
+
readonly producer: Schema.String;
|
|
684
|
+
readonly okf_version: Schema.String;
|
|
685
|
+
readonly root: Schema.String;
|
|
686
|
+
readonly profile: Schema.NullOr<Schema.String>;
|
|
687
|
+
readonly summary: Schema.Struct<{
|
|
688
|
+
readonly nodes: Schema.Number;
|
|
689
|
+
readonly edges: Schema.Number;
|
|
690
|
+
}>;
|
|
691
|
+
readonly nodes: Schema.$Array<Schema.Struct<{
|
|
692
|
+
readonly id: Schema.String;
|
|
693
|
+
readonly kind: Schema.Literals<readonly ["concept", "file", "missing"]>;
|
|
694
|
+
}>>;
|
|
695
|
+
readonly edges: Schema.$Array<Schema.Struct<{
|
|
696
|
+
readonly from: Schema.String;
|
|
697
|
+
readonly to: Schema.String;
|
|
698
|
+
readonly source: Schema.Literals<readonly ["body", "frontmatter"]>;
|
|
699
|
+
readonly field: Schema.optionalKey<Schema.String>;
|
|
700
|
+
readonly raw: Schema.String;
|
|
701
|
+
}>>;
|
|
702
|
+
}>;
|
|
703
|
+
/** @public */
|
|
704
|
+
export type GraphEnvelope = typeof GraphEnvelope.Type;
|
|
705
|
+
/**
|
|
706
|
+
* Build the envelope from a loaded `LinkGraph`'s own `nodes`/`edges`
|
|
707
|
+
* arrays.
|
|
708
|
+
*
|
|
709
|
+
* @public
|
|
710
|
+
*/
|
|
711
|
+
export declare const graphEnvelope: (input: {
|
|
712
|
+
readonly okfitVersion: string;
|
|
713
|
+
readonly producer: string;
|
|
714
|
+
readonly okfVersion: string;
|
|
715
|
+
readonly root: string;
|
|
716
|
+
readonly profile: string | null;
|
|
717
|
+
readonly nodes: ReadonlyArray<GraphNode>;
|
|
718
|
+
readonly edges: ReadonlyArray<GraphLink>;
|
|
719
|
+
}) => GraphEnvelope;
|
|
720
|
+
//#endregion
|
|
629
721
|
//#region src/render/json.d.ts
|
|
630
722
|
/** One entry of the `diagnostics` array (K-21). @public */
|
|
631
723
|
export declare const JsonDiagnostic: Schema.Struct<{
|
|
@@ -652,13 +744,18 @@ export type JsonSummary = typeof JsonSummary.Type;
|
|
|
652
744
|
/**
|
|
653
745
|
* K-21's success envelope, snake_case. `exit_code` is `0 | 1 | 2` only: an
|
|
654
746
|
* infrastructure failure never produces this envelope, it produces the
|
|
655
|
-
* `JsonErrorEnvelope` (K-22).
|
|
747
|
+
* `JsonErrorEnvelope` (K-22). `okfit_version` names the version of the
|
|
748
|
+
* package that produced the report (J-2), so the CLI and the MCP server
|
|
749
|
+
* legitimately report different numbers over one bundle; `producer` names
|
|
750
|
+
* that package (`okfit` or `@okfit/mcp`) so the difference reads as two
|
|
751
|
+
* producers, not as drift (okfit #75).
|
|
656
752
|
*
|
|
657
753
|
* @public
|
|
658
754
|
*/
|
|
659
755
|
export declare const JsonEnvelope: Schema.Struct<{
|
|
660
756
|
readonly schema: Schema.Literal<1>;
|
|
661
757
|
readonly okfit_version: Schema.String;
|
|
758
|
+
readonly producer: Schema.String;
|
|
662
759
|
readonly okf_version: Schema.String;
|
|
663
760
|
readonly root: Schema.String;
|
|
664
761
|
readonly profile: Schema.NullOr<Schema.String>;
|
|
@@ -707,6 +804,7 @@ export type JsonErrorEnvelope = typeof JsonErrorEnvelope.Type;
|
|
|
707
804
|
*/
|
|
708
805
|
export declare const json: (input: {
|
|
709
806
|
readonly okfitVersion: string;
|
|
807
|
+
readonly producer: string;
|
|
710
808
|
readonly okfVersion: string;
|
|
711
809
|
readonly root: string;
|
|
712
810
|
readonly profile: string | null;
|
|
@@ -717,6 +815,69 @@ export declare const json: (input: {
|
|
|
717
815
|
/** K-22. `tag` is the error's `_tag` when it has one, else its constructor name. @public */
|
|
718
816
|
export declare const jsonError: (error: unknown, okfitVersion: string) => JsonErrorEnvelope;
|
|
719
817
|
//#endregion
|
|
818
|
+
//#region src/render/stale.d.ts
|
|
819
|
+
/** One entry of the `items` array. @public */
|
|
820
|
+
export declare const StaleItem: Schema.Struct<{
|
|
821
|
+
readonly id: Schema.String;
|
|
822
|
+
readonly stale_after: Schema.String;
|
|
823
|
+
readonly days_past: Schema.Number;
|
|
824
|
+
}>;
|
|
825
|
+
/** @public */
|
|
826
|
+
export type StaleItem = typeof StaleItem.Type;
|
|
827
|
+
/** @public */
|
|
828
|
+
export declare const StaleSummary: Schema.Struct<{
|
|
829
|
+
readonly concepts: Schema.Number;
|
|
830
|
+
readonly stale: Schema.Number;
|
|
831
|
+
}>;
|
|
832
|
+
/** @public */
|
|
833
|
+
export type StaleSummary = typeof StaleSummary.Type;
|
|
834
|
+
/**
|
|
835
|
+
* `okfit stale --format json`'s envelope, schema 1, snake_case — the same
|
|
836
|
+
* convention as `render/json.ts`'s `JsonEnvelope`. `as_of` and each item's
|
|
837
|
+
* `stale_after` are `DateTime.formatIso` strings (mirrors
|
|
838
|
+
* `packages/mcp/src/tools/staleReport.ts`). `stale` is always `0` (the
|
|
839
|
+
* report never fails a run).
|
|
840
|
+
*
|
|
841
|
+
* @public
|
|
842
|
+
*/
|
|
843
|
+
export declare const StaleEnvelope: Schema.Struct<{
|
|
844
|
+
readonly schema: Schema.Literal<1>;
|
|
845
|
+
readonly okfit_version: Schema.String;
|
|
846
|
+
readonly producer: Schema.String;
|
|
847
|
+
readonly okf_version: Schema.String;
|
|
848
|
+
readonly root: Schema.String;
|
|
849
|
+
readonly profile: Schema.NullOr<Schema.String>;
|
|
850
|
+
readonly as_of: Schema.String;
|
|
851
|
+
readonly summary: Schema.Struct<{
|
|
852
|
+
readonly concepts: Schema.Number;
|
|
853
|
+
readonly stale: Schema.Number;
|
|
854
|
+
}>;
|
|
855
|
+
readonly items: Schema.$Array<Schema.Struct<{
|
|
856
|
+
readonly id: Schema.String;
|
|
857
|
+
readonly stale_after: Schema.String;
|
|
858
|
+
readonly days_past: Schema.Number;
|
|
859
|
+
}>>;
|
|
860
|
+
}>;
|
|
861
|
+
/** @public */
|
|
862
|
+
export type StaleEnvelope = typeof StaleEnvelope.Type;
|
|
863
|
+
/**
|
|
864
|
+
* Build the envelope. `items` is `Derive.staleReport`'s output verbatim
|
|
865
|
+
* (already sorted by id); this just reshapes it to snake_case and formats
|
|
866
|
+
* the two `DateTime.Utc` fields.
|
|
867
|
+
*
|
|
868
|
+
* @public
|
|
869
|
+
*/
|
|
870
|
+
export declare const staleEnvelope: (input: {
|
|
871
|
+
readonly okfitVersion: string;
|
|
872
|
+
readonly producer: string;
|
|
873
|
+
readonly okfVersion: string;
|
|
874
|
+
readonly root: string;
|
|
875
|
+
readonly profile: string | null;
|
|
876
|
+
readonly now: DateTime.Utc;
|
|
877
|
+
readonly concepts: number;
|
|
878
|
+
readonly items: ReadonlyArray<StaleConcept>;
|
|
879
|
+
}) => StaleEnvelope;
|
|
880
|
+
//#endregion
|
|
720
881
|
//#region src/sync/run.d.ts
|
|
721
882
|
/** The three families `okfit sync` regenerates (contract §5). @public */
|
|
722
883
|
type SyncMode = "generated" | "index" | "log";
|
|
@@ -886,6 +1047,30 @@ export declare const verifyEnvelope: (input: {
|
|
|
886
1047
|
readonly dryRun: boolean;
|
|
887
1048
|
}) => VerifyEnvelope;
|
|
888
1049
|
//#endregion
|
|
1050
|
+
//#region src/stale/run.d.ts
|
|
1051
|
+
/** @public */
|
|
1052
|
+
interface StaleRunOptions {
|
|
1053
|
+
/** Absolute bundle root; `Bundle.load` never reads cwd (D-8). */
|
|
1054
|
+
readonly root: string;
|
|
1055
|
+
/** `OKFIT_NOW` or `DateTime.now`, from the caller's own `Now` service (K-47). */
|
|
1056
|
+
readonly now: DateTime.Utc;
|
|
1057
|
+
}
|
|
1058
|
+
/** @public */
|
|
1059
|
+
interface StaleRunResult {
|
|
1060
|
+
readonly bundle: LoadedBundle;
|
|
1061
|
+
/** `Derive.staleReport`'s output verbatim: every stale concept, sorted by id. */
|
|
1062
|
+
readonly items: ReadonlyArray<StaleConcept>;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Load the bundle and derive the stale report against `now` (D-10, D-36:
|
|
1066
|
+
* `Derive.staleReport` is pure and takes `now` as an argument, never a
|
|
1067
|
+
* clock). This is a report, not a check — `okfit stale` always exits `0`;
|
|
1068
|
+
* the `stale` lint rule is where staleness fails a run.
|
|
1069
|
+
*
|
|
1070
|
+
* @public
|
|
1071
|
+
*/
|
|
1072
|
+
export declare const runStale: (options: StaleRunOptions) => Effect.Effect<StaleRunResult, BundleLoadError, FileSystem.FileSystem | Path.Path>;
|
|
1073
|
+
//#endregion
|
|
889
1074
|
//#region src/validate/run.d.ts
|
|
890
1075
|
declare const Now_base: Context.ServiceClass<Now, "@okfit/engine/Now", DateTime.Utc>;
|
|
891
1076
|
/**
|
|
@@ -1016,5 +1201,5 @@ export declare const runVerify: (options: VerifyOptions) => Effect.Effect<{
|
|
|
1016
1201
|
fragment: string;
|
|
1017
1202
|
}, import("effect/PlatformError").PlatformError | VerifyConceptNotFoundError | VerifyUnsupportedFrontmatterError | import("@effected/yaml").YamlParseError | import("@okfit/core").BundleLoadError | import("@okfit/profiles").GeneratedByError, FileSystem.FileSystem | import("@effected/git").Git | Path.Path>;
|
|
1018
1203
|
//#endregion
|
|
1019
|
-
export type { ContextResult, ContextRunOptions, DiagnosticSource, DiscoveredConfig, RenderedDiagnostic, ResolveProjectConfigInput, ResolvedProjectConfig, RunOptions, RunResult, ScaffoldFile, ScaffoldOptions, SyncMode, SyncModeResult, SyncOptions, SyncResult, Tally, VerifyOptions, VerifyResult };
|
|
1204
|
+
export type { ContextResult, ContextRunOptions, DiagnosticSource, DiscoveredConfig, GraphRunOptions, GraphRunResult, RenderedDiagnostic, ResolveProjectConfigInput, ResolvedProjectConfig, RunOptions, RunResult, ScaffoldFile, ScaffoldOptions, StaleRunOptions, StaleRunResult, SyncMode, SyncModeResult, SyncOptions, SyncResult, Tally, VerifyOptions, VerifyResult };
|
|
1020
1205
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -3,16 +3,20 @@ import { ConfigMalformedError, ConfigPathNotFoundError, InitOverwriteError, Veri
|
|
|
3
3
|
import { buildConfigLayer, provideConfig } from "./config/layer.js";
|
|
4
4
|
import { DEFAULT_PROFILE_NAME, resolveProjectConfig } from "./config/resolve.js";
|
|
5
5
|
import { runContext } from "./context/run.js";
|
|
6
|
+
import { runGraph } from "./graph/run.js";
|
|
6
7
|
import { CONFIG_RELATIVE_PATH, SCHEMA_DIRECTIVE, configValue, files, targetPaths } from "./init/scaffold.js";
|
|
7
8
|
import { OkfitPlatform } from "./platform.js";
|
|
8
9
|
import { ContextEnvelope, ContextField, ContextFieldValue, ContextTag, ContextType, contextEnvelope } from "./render/context.js";
|
|
9
10
|
import { forDiagnostics, tally } from "./render/exit.js";
|
|
11
|
+
import { GraphEdgeEnvelope, GraphEnvelope, GraphNodeEnvelope, GraphSummary, graphEnvelope } from "./render/graph.js";
|
|
10
12
|
import { collect, sort } from "./render/sort.js";
|
|
11
13
|
import { JsonDiagnostic, JsonEnvelope, JsonErrorEnvelope, JsonSummary, json, jsonError } from "./render/json.js";
|
|
14
|
+
import { StaleEnvelope, StaleItem, StaleSummary, staleEnvelope } from "./render/stale.js";
|
|
12
15
|
import { SkipReason, runSync } from "./sync/run.js";
|
|
13
16
|
import { SyncEnvelope, SyncModeEnvelope, syncEnvelope } from "./render/sync.js";
|
|
14
17
|
import { VerifyEnvelope, verifyEnvelope } from "./render/verify.js";
|
|
18
|
+
import { runStale } from "./stale/run.js";
|
|
15
19
|
import { Now, run } from "./validate/run.js";
|
|
16
20
|
import { runVerify } from "./verify/run.js";
|
|
17
21
|
|
|
18
|
-
export { CONFIG_RELATIVE_PATH, ConfigMalformedError, ConfigPathNotFoundError, ContextEnvelope, ContextField, ContextFieldValue, ContextTag, ContextType, DEFAULT_PROFILE_NAME, InitOverwriteError, JsonDiagnostic, JsonEnvelope, JsonErrorEnvelope, JsonSummary, Now, OkfitPlatform, SCHEMA_DIRECTIVE, SkipReason, SyncEnvelope, SyncModeEnvelope, VerifyConceptNotFoundError, VerifyEnvelope, VerifyUnsupportedFrontmatterError, buildConfigLayer, collect, configValue, contextEnvelope, files, forDiagnostics, json, jsonError, provideConfig, resolveBundleRoot, resolveProjectConfig, resolveProjectRoot, run, runContext, runSync, runVerify, sort, syncEnvelope, tally, targetPaths, verifyEnvelope };
|
|
22
|
+
export { CONFIG_RELATIVE_PATH, ConfigMalformedError, ConfigPathNotFoundError, ContextEnvelope, ContextField, ContextFieldValue, ContextTag, ContextType, DEFAULT_PROFILE_NAME, GraphEdgeEnvelope, GraphEnvelope, GraphNodeEnvelope, GraphSummary, InitOverwriteError, JsonDiagnostic, JsonEnvelope, JsonErrorEnvelope, JsonSummary, Now, OkfitPlatform, SCHEMA_DIRECTIVE, SkipReason, StaleEnvelope, StaleItem, StaleSummary, SyncEnvelope, SyncModeEnvelope, VerifyConceptNotFoundError, VerifyEnvelope, VerifyUnsupportedFrontmatterError, buildConfigLayer, collect, configValue, contextEnvelope, files, forDiagnostics, graphEnvelope, json, jsonError, provideConfig, resolveBundleRoot, resolveProjectConfig, resolveProjectRoot, run, runContext, runGraph, runStale, runSync, runVerify, sort, staleEnvelope, syncEnvelope, tally, targetPaths, verifyEnvelope };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okfit/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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": [
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@effected/walker": "^0.9.0",
|
|
47
47
|
"@effected/xdg": "^0.5.1",
|
|
48
48
|
"@effected/yaml": "^0.15.1",
|
|
49
|
-
"@okfit/core": "0.4.
|
|
50
|
-
"@okfit/profiles": "0.
|
|
49
|
+
"@okfit/core": "0.4.1",
|
|
50
|
+
"@okfit/profiles": "0.5.0",
|
|
51
51
|
"effect": "4.0.0-rc.115"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
package/render/graph.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/render/graph.ts
|
|
4
|
+
/** One entry of the `nodes` array. @public */
|
|
5
|
+
const GraphNodeEnvelope = Schema.Struct({
|
|
6
|
+
id: Schema.String,
|
|
7
|
+
kind: Schema.Literals([
|
|
8
|
+
"concept",
|
|
9
|
+
"file",
|
|
10
|
+
"missing"
|
|
11
|
+
])
|
|
12
|
+
});
|
|
13
|
+
/** One entry of the `edges` array; `field` is omitted, never `null` (exactOptionalPropertyTypes). @public */
|
|
14
|
+
const GraphEdgeEnvelope = Schema.Struct({
|
|
15
|
+
from: Schema.String,
|
|
16
|
+
to: Schema.String,
|
|
17
|
+
source: Schema.Literals(["body", "frontmatter"]),
|
|
18
|
+
field: Schema.optionalKey(Schema.String),
|
|
19
|
+
raw: Schema.String
|
|
20
|
+
});
|
|
21
|
+
/** @public */
|
|
22
|
+
const GraphSummary = Schema.Struct({
|
|
23
|
+
nodes: Schema.Number,
|
|
24
|
+
edges: Schema.Number
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* `okfit graph --format json`'s envelope, schema 1, snake_case — the same
|
|
28
|
+
* convention as `render/json.ts`'s `JsonEnvelope`. Built from
|
|
29
|
+
* `LinkGraph.nodes`/`LinkGraph.edges` (D-26).
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
const GraphEnvelope = Schema.Struct({
|
|
34
|
+
schema: Schema.Literal(1),
|
|
35
|
+
okfit_version: Schema.String,
|
|
36
|
+
producer: Schema.String,
|
|
37
|
+
okf_version: Schema.String,
|
|
38
|
+
root: Schema.String,
|
|
39
|
+
profile: Schema.NullOr(Schema.String),
|
|
40
|
+
summary: GraphSummary,
|
|
41
|
+
nodes: Schema.Array(GraphNodeEnvelope),
|
|
42
|
+
edges: Schema.Array(GraphEdgeEnvelope)
|
|
43
|
+
});
|
|
44
|
+
const toNode = (node) => ({
|
|
45
|
+
id: node.id,
|
|
46
|
+
kind: node.kind
|
|
47
|
+
});
|
|
48
|
+
const toEdge = (edge) => ({
|
|
49
|
+
from: edge.from,
|
|
50
|
+
to: edge.to,
|
|
51
|
+
source: edge.data.source,
|
|
52
|
+
...edge.data.field === void 0 ? {} : { field: edge.data.field },
|
|
53
|
+
raw: edge.data.raw
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Build the envelope from a loaded `LinkGraph`'s own `nodes`/`edges`
|
|
57
|
+
* arrays.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
const graphEnvelope = (input) => ({
|
|
62
|
+
schema: 1,
|
|
63
|
+
okfit_version: input.okfitVersion,
|
|
64
|
+
producer: input.producer,
|
|
65
|
+
okf_version: input.okfVersion,
|
|
66
|
+
root: input.root,
|
|
67
|
+
profile: input.profile,
|
|
68
|
+
summary: {
|
|
69
|
+
nodes: input.nodes.length,
|
|
70
|
+
edges: input.edges.length
|
|
71
|
+
},
|
|
72
|
+
nodes: input.nodes.map(toNode),
|
|
73
|
+
edges: input.edges.map(toEdge)
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { GraphEdgeEnvelope, GraphEnvelope, GraphNodeEnvelope, GraphSummary, graphEnvelope };
|
package/render/json.js
CHANGED
|
@@ -29,13 +29,18 @@ const JsonSummary = Schema.Struct({
|
|
|
29
29
|
/**
|
|
30
30
|
* K-21's success envelope, snake_case. `exit_code` is `0 | 1 | 2` only: an
|
|
31
31
|
* infrastructure failure never produces this envelope, it produces the
|
|
32
|
-
* `JsonErrorEnvelope` (K-22).
|
|
32
|
+
* `JsonErrorEnvelope` (K-22). `okfit_version` names the version of the
|
|
33
|
+
* package that produced the report (J-2), so the CLI and the MCP server
|
|
34
|
+
* legitimately report different numbers over one bundle; `producer` names
|
|
35
|
+
* that package (`okfit` or `@okfit/mcp`) so the difference reads as two
|
|
36
|
+
* producers, not as drift (okfit #75).
|
|
33
37
|
*
|
|
34
38
|
* @public
|
|
35
39
|
*/
|
|
36
40
|
const JsonEnvelope = Schema.Struct({
|
|
37
41
|
schema: Schema.Literal(1),
|
|
38
42
|
okfit_version: Schema.String,
|
|
43
|
+
producer: Schema.String,
|
|
39
44
|
okf_version: Schema.String,
|
|
40
45
|
root: Schema.String,
|
|
41
46
|
profile: Schema.NullOr(Schema.String),
|
|
@@ -81,6 +86,7 @@ const json = (input) => {
|
|
|
81
86
|
return {
|
|
82
87
|
schema: 1,
|
|
83
88
|
okfit_version: input.okfitVersion,
|
|
89
|
+
producer: input.producer,
|
|
84
90
|
okf_version: input.okfVersion,
|
|
85
91
|
root: input.root,
|
|
86
92
|
profile: input.profile,
|
package/render/stale.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { DateTime, Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/render/stale.ts
|
|
4
|
+
/** One entry of the `items` array. @public */
|
|
5
|
+
const StaleItem = Schema.Struct({
|
|
6
|
+
id: Schema.String,
|
|
7
|
+
stale_after: Schema.String,
|
|
8
|
+
days_past: Schema.Number
|
|
9
|
+
});
|
|
10
|
+
/** @public */
|
|
11
|
+
const StaleSummary = Schema.Struct({
|
|
12
|
+
concepts: Schema.Number,
|
|
13
|
+
stale: Schema.Number
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* `okfit stale --format json`'s envelope, schema 1, snake_case — the same
|
|
17
|
+
* convention as `render/json.ts`'s `JsonEnvelope`. `as_of` and each item's
|
|
18
|
+
* `stale_after` are `DateTime.formatIso` strings (mirrors
|
|
19
|
+
* `packages/mcp/src/tools/staleReport.ts`). `stale` is always `0` (the
|
|
20
|
+
* report never fails a run).
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
const StaleEnvelope = Schema.Struct({
|
|
25
|
+
schema: Schema.Literal(1),
|
|
26
|
+
okfit_version: Schema.String,
|
|
27
|
+
producer: Schema.String,
|
|
28
|
+
okf_version: Schema.String,
|
|
29
|
+
root: Schema.String,
|
|
30
|
+
profile: Schema.NullOr(Schema.String),
|
|
31
|
+
as_of: Schema.String,
|
|
32
|
+
summary: StaleSummary,
|
|
33
|
+
items: Schema.Array(StaleItem)
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Build the envelope. `items` is `Derive.staleReport`'s output verbatim
|
|
37
|
+
* (already sorted by id); this just reshapes it to snake_case and formats
|
|
38
|
+
* the two `DateTime.Utc` fields.
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
const staleEnvelope = (input) => ({
|
|
43
|
+
schema: 1,
|
|
44
|
+
okfit_version: input.okfitVersion,
|
|
45
|
+
producer: input.producer,
|
|
46
|
+
okf_version: input.okfVersion,
|
|
47
|
+
root: input.root,
|
|
48
|
+
profile: input.profile,
|
|
49
|
+
as_of: DateTime.formatIso(input.now),
|
|
50
|
+
summary: {
|
|
51
|
+
concepts: input.concepts,
|
|
52
|
+
stale: input.items.length
|
|
53
|
+
},
|
|
54
|
+
items: input.items.map((item) => ({
|
|
55
|
+
id: item.id,
|
|
56
|
+
stale_after: DateTime.formatIso(item.staleAfter),
|
|
57
|
+
days_past: item.daysPast
|
|
58
|
+
}))
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { StaleEnvelope, StaleItem, StaleSummary, staleEnvelope };
|
package/stale/run.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Bundle, Derive } from "@okfit/core";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/stale/run.ts
|
|
5
|
+
/**
|
|
6
|
+
* Load the bundle and derive the stale report against `now` (D-10, D-36:
|
|
7
|
+
* `Derive.staleReport` is pure and takes `now` as an argument, never a
|
|
8
|
+
* clock). This is a report, not a check — `okfit stale` always exits `0`;
|
|
9
|
+
* the `stale` lint rule is where staleness fails a run.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
const runStale = (options) => Effect.gen(function* () {
|
|
14
|
+
const bundle = yield* Bundle.load({ root: options.root });
|
|
15
|
+
return {
|
|
16
|
+
bundle,
|
|
17
|
+
items: Derive.staleReport(bundle, options.now)
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { runStale };
|