@okfit/profiles 0.7.4 → 0.8.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/Provenance.js +17 -15
- package/SoftwareProject.js +11 -5
- package/index.d.ts +4 -2
- package/package.json +5 -5
package/Provenance.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Derivation } from "./Derivation.js";
|
|
2
|
-
import { Diagnostic, OkfitConfig, Timestamp } from "@okfit/core";
|
|
2
|
+
import { Diagnostic, DiagnosticRange, OkfitConfig, Timestamp } from "@okfit/core";
|
|
3
3
|
import { DateTime, Effect, Path, Schema } from "effect";
|
|
4
4
|
|
|
5
5
|
//#region src/Provenance.ts
|
|
@@ -27,8 +27,10 @@ const encodeAt = Schema.encodeSync(Timestamp);
|
|
|
27
27
|
* The tier-2 fallback returns `[]` the moment a `NotARepositoryError`
|
|
28
28
|
* surfaces: a bundle outside git has nothing to derive for any concept still
|
|
29
29
|
* on tier 2, so the first occurrence short-circuits the whole walk, not just
|
|
30
|
-
* the concept that triggered it (S-8).
|
|
31
|
-
*
|
|
30
|
+
* the concept that triggered it (S-8). Ranges at the `generated.at` value
|
|
31
|
+
* (phase 4 decision 2) via `DiagnosticRange.forFrontmatterPath`; omitted
|
|
32
|
+
* (`Diagnostic.range` is `Schema.optionalKey`) when the concept's document has
|
|
33
|
+
* no frontmatter block at all.
|
|
32
34
|
*
|
|
33
35
|
* `Provenance.lint` is total over severity (S-28, amending Judge note 3):
|
|
34
36
|
* when `OkfitConfig.severityFor(config, "generated-at-drift")` resolves to
|
|
@@ -58,18 +60,23 @@ var Provenance = class {
|
|
|
58
60
|
const skipGitTier = options?.skipGitTier === true;
|
|
59
61
|
const path = yield* Path.Path;
|
|
60
62
|
const diagnostics = [];
|
|
63
|
+
/** Pushes a `generated-at-drift` diagnostic, ranged at `generated.at`'s own value when found. */
|
|
64
|
+
const pushDrift = (file, message, range) => {
|
|
65
|
+
diagnostics.push(Diagnostic.make({
|
|
66
|
+
file,
|
|
67
|
+
code: "generated-at-drift",
|
|
68
|
+
severity,
|
|
69
|
+
message,
|
|
70
|
+
...range === void 0 ? {} : { range }
|
|
71
|
+
}));
|
|
72
|
+
};
|
|
61
73
|
for (const [, concept] of bundle.concepts) {
|
|
62
74
|
if (concept.frontmatter.generated === void 0) continue;
|
|
63
75
|
const recordedDigest = concept.frontmatter.generated.body_sha256;
|
|
64
76
|
if (recordedDigest !== void 0) {
|
|
65
77
|
const currentDigest = yield* Derivation.bodyDigest(concept.document.source);
|
|
66
78
|
if (currentDigest === recordedDigest) continue;
|
|
67
|
-
|
|
68
|
-
file: concept.path,
|
|
69
|
-
code: "generated-at-drift",
|
|
70
|
-
severity,
|
|
71
|
-
message: `the body has changed since generated.at was last stamped: generated.body_sha256 is ${recordedDigest}, the current body hashes to ${currentDigest}`
|
|
72
|
-
}));
|
|
79
|
+
pushDrift(concept.path, `the body has changed since generated.at was last stamped: generated.body_sha256 is ${recordedDigest}, the current body hashes to ${currentDigest}`, DiagnosticRange.forFrontmatterPath(concept.document, ["generated", "at"]));
|
|
73
80
|
continue;
|
|
74
81
|
}
|
|
75
82
|
if (skipGitTier) continue;
|
|
@@ -79,12 +86,7 @@ var Provenance = class {
|
|
|
79
86
|
if (derived._tag === "uncommitted") continue;
|
|
80
87
|
const recorded = concept.frontmatter.generated.at;
|
|
81
88
|
if (recorded !== void 0 && DateTime.Equivalence(recorded, derived.at)) continue;
|
|
82
|
-
|
|
83
|
-
file: concept.path,
|
|
84
|
-
code: "generated-at-drift",
|
|
85
|
-
severity,
|
|
86
|
-
message: `generated.at is ${recorded === void 0 ? "missing" : encodeAt(recorded)}; the last body change was ${encodeAt(derived.at)} (${derived.sha.slice(0, 7)})`
|
|
87
|
-
}));
|
|
89
|
+
pushDrift(concept.path, `generated.at is ${recorded === void 0 ? "missing" : encodeAt(recorded)}; the last body change was ${encodeAt(derived.at)} (${derived.sha.slice(0, 7)})`, DiagnosticRange.forFrontmatterPath(concept.document, ["generated", "at"]));
|
|
88
90
|
}
|
|
89
91
|
return diagnostics;
|
|
90
92
|
});
|
package/SoftwareProject.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { DiagnosticRange } from "@okfit/core";
|
|
2
|
+
|
|
1
3
|
//#region src/SoftwareProject.ts
|
|
2
4
|
/**
|
|
3
5
|
* Hand-authored, typed `OkfitConfig` (P-25). Sets ONLY `concepts`, `types`,
|
|
@@ -258,11 +260,12 @@ const layout = {
|
|
|
258
260
|
]
|
|
259
261
|
};
|
|
260
262
|
const PROJECT_TYPE = "Project";
|
|
261
|
-
const diagnostic = (file, code, message) => ({
|
|
263
|
+
const diagnostic = (file, code, message, range) => ({
|
|
262
264
|
file,
|
|
263
265
|
code,
|
|
264
266
|
severity: "error",
|
|
265
|
-
message
|
|
267
|
+
message,
|
|
268
|
+
...range === void 0 ? {} : { range }
|
|
266
269
|
});
|
|
267
270
|
/** Plain code-unit order on `file` then `code` (decision 6); never locale-dependent. */
|
|
268
271
|
const compare = (a, b) => {
|
|
@@ -277,7 +280,10 @@ const compare = (a, b) => {
|
|
|
277
280
|
* (`CORE/Bundle.ts:98`; `Concept.type` `CORE/Concept.ts:27`). The rules are
|
|
278
281
|
* independent: two Projects with one nested yield three diagnostics. The file
|
|
279
282
|
* name `project.md` is layout guidance, not checked. Severity is always
|
|
280
|
-
* `error
|
|
283
|
+
* `error`. `project-multiple` and `project-not-at-root` range at the
|
|
284
|
+
* misplaced concept's `type` value (phase 4 decision 2, via
|
|
285
|
+
* `DiagnosticRange.forFrontmatterPath`); `project-missing` is bundle-level
|
|
286
|
+
* (`file: ""`) and stays range-less. Output is sorted by `file` then `code`.
|
|
281
287
|
*/
|
|
282
288
|
const check = (bundle) => {
|
|
283
289
|
const projects = [...bundle.concepts.values()].filter((concept) => concept.frontmatter.type === PROJECT_TYPE);
|
|
@@ -285,9 +291,9 @@ const check = (bundle) => {
|
|
|
285
291
|
if (projects.length === 0) out.push(diagnostic("", "project-missing", `No Project concept in the bundle; software-project expects exactly one at the bundle root (${layout.root.project})`));
|
|
286
292
|
if (projects.length > 1) for (const project of projects) {
|
|
287
293
|
const others = projects.filter((other) => other !== project).map((other) => other.path).sort();
|
|
288
|
-
out.push(diagnostic(project.path, "project-multiple", `Project concept "${project.path}" is one of ${projects.length}; software-project expects exactly one (others: ${others.join(", ")})
|
|
294
|
+
out.push(diagnostic(project.path, "project-multiple", `Project concept "${project.path}" is one of ${projects.length}; software-project expects exactly one (others: ${others.join(", ")})`, DiagnosticRange.forFrontmatterPath(project.document, ["type"])));
|
|
289
295
|
}
|
|
290
|
-
for (const project of projects) if (project.path.includes("/")) out.push(diagnostic(project.path, "project-not-at-root", `Project concept "${project.path}" is below the bundle root; software-project expects it beside ${layout.root.index}
|
|
296
|
+
for (const project of projects) if (project.path.includes("/")) out.push(diagnostic(project.path, "project-not-at-root", `Project concept "${project.path}" is below the bundle root; software-project expects it beside ${layout.root.index}`, DiagnosticRange.forFrontmatterPath(project.document, ["type"])));
|
|
291
297
|
return out.sort(compare);
|
|
292
298
|
};
|
|
293
299
|
/**
|
package/index.d.ts
CHANGED
|
@@ -410,8 +410,10 @@ export declare class Profiles {
|
|
|
410
410
|
* The tier-2 fallback returns `[]` the moment a `NotARepositoryError`
|
|
411
411
|
* surfaces: a bundle outside git has nothing to derive for any concept still
|
|
412
412
|
* on tier 2, so the first occurrence short-circuits the whole walk, not just
|
|
413
|
-
* the concept that triggered it (S-8).
|
|
414
|
-
*
|
|
413
|
+
* the concept that triggered it (S-8). Ranges at the `generated.at` value
|
|
414
|
+
* (phase 4 decision 2) via `DiagnosticRange.forFrontmatterPath`; omitted
|
|
415
|
+
* (`Diagnostic.range` is `Schema.optionalKey`) when the concept's document has
|
|
416
|
+
* no frontmatter block at all.
|
|
415
417
|
*
|
|
416
418
|
* `Provenance.lint` is total over severity (S-28, amending Judge note 3):
|
|
417
419
|
* when `OkfitConfig.severityFor(config, "generated-at-drift")` resolves to
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okfit/profiles",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Named OKF configuration profiles for okfit, starting with the software-project profile.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"./package.json": "./package.json"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@effected/git": "^0.
|
|
39
|
-
"@effected/markdown": "^0.
|
|
40
|
-
"@okfit/core": "^0.
|
|
41
|
-
"effect": "4.0.0-rc.
|
|
38
|
+
"@effected/git": "^0.17.0",
|
|
39
|
+
"@effected/markdown": "^0.12.0",
|
|
40
|
+
"@okfit/core": "^0.8.0",
|
|
41
|
+
"effect": "4.0.0-rc.117"
|
|
42
42
|
},
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=24.11.0"
|