okf-kit 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/CHANGELOG.md +22 -0
- package/README.md +7 -4
- package/dist/cli.js +16 -1
- package/dist/cli.js.map +1 -1
- package/dist/rules/sources-fresh.js +22 -2
- package/dist/rules/sources-fresh.js.map +1 -1
- package/package.json +4 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `okf-kit` are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.4.0] - 2026-08-13
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `sources-fresh` no longer reports STALE when the doc file's own last-commit
|
|
13
|
+
time is at or after the source's last-commit time, in particular when doc
|
|
14
|
+
and sources landed in the same commit. Squash-merge PRs that ship a doc
|
|
15
|
+
re-stamp together with its changed sources previously made every such doc
|
|
16
|
+
stale-on-arrival: the merge gave all sources a commit time later than any
|
|
17
|
+
frontmatter timestamp set before the merge. The frontmatter timestamp
|
|
18
|
+
remains authoritative when a source changed after the doc's last commit,
|
|
19
|
+
and for docs without git history (e.g. uncommitted) the behavior is
|
|
20
|
+
unchanged. Accepted limitation (documented in the README): any commit
|
|
21
|
+
touching the doc suppresses staleness for all sources changed before it,
|
|
22
|
+
not only for same-commit sources.
|
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ Every template doc except `benchmark-template.md` ships with `sources: [path/to/
|
|
|
68
68
|
| `links-resolve` | error | Markdown links to other `.md` files in the bundle must resolve to a real file. Relative targets resolve against the containing file's directory; targets starting with `/` resolve against the bundle root. A relative target that climbs out of the bundle directory (`../outside.md`) and still resolves on disk is accepted; the rule checks resolution, not containment. |
|
|
69
69
|
| `no-absolute-links` | warning | Link targets should not start with `/`. GitHub resolves a leading slash against the repository root, not the bundle root, so an absolute link 404s once the bundle is viewed outside its own repository. Use a same-directory relative link instead. |
|
|
70
70
|
| `sources-shape` | error | Frontmatter `sources`, when present, must be a non-empty array of non-empty strings. With a repo root (explicit or auto-detected), each listed path (file or directory) must also exist under it. |
|
|
71
|
-
| `sources-fresh` | warning / notice | For docs with a `sources` list and a repo root, flags a source path whose last git commit is newer than the doc's `timestamp
|
|
71
|
+
| `sources-fresh` | warning / notice | For docs with a `sources` list and a repo root, flags a source path whose last git commit is newer than both the doc's `timestamp` and the doc file's own last commit. See "Staleness (sources-fresh)" below. |
|
|
72
72
|
|
|
73
73
|
## repo-root auto-detection
|
|
74
74
|
|
|
@@ -80,11 +80,12 @@ Pass `--repo-root` explicitly to pin a specific root (useful in CI when the bund
|
|
|
80
80
|
|
|
81
81
|
## Staleness (sources-fresh)
|
|
82
82
|
|
|
83
|
-
`sources-fresh` compares each frontmatter `sources` entry's last git commit time against the doc's `timestamp
|
|
83
|
+
`sources-fresh` compares each frontmatter `sources` entry's last git commit time against the doc's `timestamp`, and additionally against the doc file's own last commit time: a source committed at or before the doc file's last commit is treated as fresh even when the frontmatter `timestamp` is older. That keeps squash-merge PRs honest: when a doc re-stamp lands in the same commit as its changed sources, the merge gives every source a commit time later than any pre-merge `timestamp`, which used to make such docs stale-on-arrival. The rule never blocks a doc that has no `sources`, and it never invents an error where git can't give a real answer:
|
|
84
84
|
|
|
85
85
|
| Situation | Severity | Message |
|
|
86
86
|
|-----------|----------|---------|
|
|
87
|
-
| A source path's last commit is newer than the doc's `timestamp` | warning | `STALE: <path> changed <iso> after doc timestamp <iso>` |
|
|
87
|
+
| A source path's last commit is newer than the doc's `timestamp` and the doc file's last commit | warning | `STALE: <path> changed <iso> after doc timestamp <iso>` |
|
|
88
|
+
| A source path's last commit is newer than the doc's `timestamp` but at/before the doc file's last commit | (nothing) | fresh: doc and source landed together (or the doc was committed later) |
|
|
88
89
|
| A source path exists but has no git history (untracked) | notice | `untracked by git, staleness unknown: <path>` |
|
|
89
90
|
| The doc's `timestamp` is missing or not a parseable date, while `sources` is present | notice | `staleness not assessable: no valid timestamp` |
|
|
90
91
|
| No repo root available (see auto-detection above) | notice | `staleness skipped: not inside a git work tree` |
|
|
@@ -94,6 +95,8 @@ STALE findings are warnings, so they are advisory by default; run with `--strict
|
|
|
94
95
|
|
|
95
96
|
Known limitation: a `git log` call that fails for a reason other than "no history for this path" (for example a corrupt object or a transient git error) is reported the same way as a genuinely untracked path, the `untracked by git, staleness unknown` notice; okf-kit does not currently distinguish a real git failure from "no commits touch this path".
|
|
96
97
|
|
|
98
|
+
Known limitation: the doc-commit comparison suppresses staleness for every source older than the doc file's last commit, not only for sources from the same commit. For a multi-source doc that means any commit touching the doc (a typo fix, a repo-wide formatter run, a rename, which resets the doc's last-commit time because `git log` runs without `--follow`) silences drift on all sources changed before it, even ones nobody re-verified. The frontmatter `timestamp` still governs sources changed after the doc's last commit.
|
|
99
|
+
|
|
97
100
|
**Authoring guidance:** when you re-verify a doc against its sources, bump its frontmatter `timestamp` (and add a line to the bundle's `log.md`) so `sources-fresh` reflects that the doc is current again.
|
|
98
101
|
|
|
99
102
|
## Exit codes
|
|
@@ -110,7 +113,7 @@ This is advisory: don't fail the build on warnings unless you pass `--strict`. U
|
|
|
110
113
|
|
|
111
114
|
```yaml
|
|
112
115
|
- name: OKF bundle check
|
|
113
|
-
run: npx okf-kit@0.
|
|
116
|
+
run: npx okf-kit@0.4.0 check path/to/bundle
|
|
114
117
|
```
|
|
115
118
|
|
|
116
119
|
Pin the version: an unpinned `npx okf-kit` picks up new rules on their release day, which turns an unrelated PR red.
|
package/dist/cli.js
CHANGED
|
@@ -111,8 +111,23 @@ const PASSTHROUGH_EXIT_CODES = new Set([
|
|
|
111
111
|
// exported runCheck/UsageError (as tests do): otherwise importing this
|
|
112
112
|
// module would parse the importer's own process.argv and could exit the
|
|
113
113
|
// importing process.
|
|
114
|
+
// argv[1] is the path the shell invoked. Every real install path routes
|
|
115
|
+
// through a symlink (`node_modules/.bin/okf-kit` -> `../okf-kit/dist/cli.js`,
|
|
116
|
+
// which is what `npx` and `npm i -g` create), so comparing it verbatim against
|
|
117
|
+
// `import.meta.url` (always the resolved realpath) never matches and the CLI
|
|
118
|
+
// silently no-ops with exit 0. Resolve argv[1] before comparing. realpathSync
|
|
119
|
+
// throws on a path that does not exist; fall back to the raw value so a exotic
|
|
120
|
+
// argv[1] degrades to the old comparison rather than crashing at import time.
|
|
121
|
+
function resolvedArgvUrl(argv1) {
|
|
122
|
+
try {
|
|
123
|
+
return pathToFileURL(fs.realpathSync(argv1)).href;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return pathToFileURL(argv1).href;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
114
129
|
const isMainModule = process.argv[1] !== undefined &&
|
|
115
|
-
import.meta.url ===
|
|
130
|
+
import.meta.url === resolvedArgvUrl(process.argv[1]);
|
|
116
131
|
if (isMainModule) {
|
|
117
132
|
program.parseAsync().catch((err) => {
|
|
118
133
|
if (err instanceof CommanderError) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { getTimestampEpoch, getValidSources } from "../util.js";
|
|
|
5
5
|
const RULE_ID = "sources-fresh";
|
|
6
6
|
export const sourcesFreshRule = {
|
|
7
7
|
id: RULE_ID,
|
|
8
|
-
description: "Frontmatter `sources` paths must not have a last-commit time newer than the doc's `timestamp
|
|
8
|
+
description: "Frontmatter `sources` paths must not have a last-commit time newer than the doc's `timestamp` and the doc file's own last commit.",
|
|
9
9
|
run(ctx) {
|
|
10
10
|
const findings = [];
|
|
11
11
|
const docsWithSources = ctx.docs
|
|
@@ -50,6 +50,16 @@ export const sourcesFreshRule = {
|
|
|
50
50
|
});
|
|
51
51
|
continue;
|
|
52
52
|
}
|
|
53
|
+
// A doc whose own last commit is at or after the source's last commit
|
|
54
|
+
// (typically: both landed in one squash-merge) is not stale, even if
|
|
55
|
+
// its frontmatter timestamp is old. Lazy + memoized: the lookup costs a
|
|
56
|
+
// git process per doc but is only ever consulted on the stale path.
|
|
57
|
+
const repoRelDocPath = path
|
|
58
|
+
.relative(repoRoot, path.join(ctx.bundleDir, doc.relPath))
|
|
59
|
+
.split(path.sep)
|
|
60
|
+
.join("/");
|
|
61
|
+
let docCommitEpochMemo;
|
|
62
|
+
const docCommitEpochFor = () => (docCommitEpochMemo ??= getLastCommitEpoch(git, repoRoot, repoRelDocPath));
|
|
53
63
|
for (const source of sources) {
|
|
54
64
|
// A missing path on disk is sources-shape's job to report; avoid a
|
|
55
65
|
// duplicate/confusing finding here.
|
|
@@ -65,7 +75,17 @@ export const sourcesFreshRule = {
|
|
|
65
75
|
});
|
|
66
76
|
continue;
|
|
67
77
|
}
|
|
68
|
-
|
|
78
|
+
let isStale = commitEpoch > timestampEpoch;
|
|
79
|
+
// Doc committed at/after the source: not stale (see comment above).
|
|
80
|
+
// A doc without git history (null epoch, e.g. uncommitted) keeps the
|
|
81
|
+
// frontmatter-only comparison.
|
|
82
|
+
if (isStale) {
|
|
83
|
+
const docCommitEpoch = docCommitEpochFor();
|
|
84
|
+
if (docCommitEpoch !== null && docCommitEpoch >= commitEpoch) {
|
|
85
|
+
isStale = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (isStale) {
|
|
69
89
|
findings.push({
|
|
70
90
|
ruleId: RULE_ID,
|
|
71
91
|
severity: "warning",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources-fresh.js","sourceRoot":"","sources":["../../src/rules/sources-fresh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGhE,MAAM,OAAO,GAAG,eAAe,CAAC;AAEhC,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,OAAO;IACX,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"sources-fresh.js","sourceRoot":"","sources":["../../src/rules/sources-fresh.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "okf-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "CLI that validates OKF v0.1 knowledge bundles for structural correctness",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"CHANGELOG.md"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"build": "tsc",
|
|
15
16
|
"typecheck": "tsc --noEmit",
|
|
17
|
+
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
16
18
|
"dev": "tsx src/cli.ts",
|
|
17
19
|
"pretest": "npm run build",
|
|
18
20
|
"test": "vitest run",
|