okf-kit 0.3.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 +124 -0
- package/dist/bundle.d.ts +2 -0
- package/dist/bundle.js +69 -0
- package/dist/bundle.js.map +1 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +142 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +3 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/git.d.ts +15 -0
- package/dist/git.js +30 -0
- package/dist/git.js.map +1 -0
- package/dist/init.d.ts +11 -0
- package/dist/init.js +63 -0
- package/dist/init.js.map +1 -0
- package/dist/links.d.ts +15 -0
- package/dist/links.js +82 -0
- package/dist/links.js.map +1 -0
- package/dist/report.d.ts +9 -0
- package/dist/report.js +51 -0
- package/dist/report.js.map +1 -0
- package/dist/rules/frontmatter-required.d.ts +2 -0
- package/dist/rules/frontmatter-required.js +46 -0
- package/dist/rules/frontmatter-required.js.map +1 -0
- package/dist/rules/index.d.ts +9 -0
- package/dist/rules/index.js +16 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/links-resolve.d.ts +2 -0
- package/dist/rules/links-resolve.js +39 -0
- package/dist/rules/links-resolve.js.map +1 -0
- package/dist/rules/no-absolute-links.d.ts +2 -0
- package/dist/rules/no-absolute-links.js +25 -0
- package/dist/rules/no-absolute-links.js.map +1 -0
- package/dist/rules/reserved-files-bare.d.ts +2 -0
- package/dist/rules/reserved-files-bare.js +22 -0
- package/dist/rules/reserved-files-bare.js.map +1 -0
- package/dist/rules/sources-fresh.d.ts +2 -0
- package/dist/rules/sources-fresh.js +99 -0
- package/dist/rules/sources-fresh.js.map +1 -0
- package/dist/rules/sources-shape.d.ts +2 -0
- package/dist/rules/sources-shape.js +41 -0
- package/dist/rules/sources-shape.js.map +1 -0
- package/dist/templates.d.ts +14 -0
- package/dist/templates.js +293 -0
- package/dist/templates.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +23 -0
- package/dist/util.js +50 -0
- package/dist/util.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold content for `okf-kit init`. Everything here is static except the
|
|
3
|
+
* `timestamp` value, which the caller (src/init.ts) fills in with the real
|
|
4
|
+
* current instant at generation time: never hardcode an artificial
|
|
5
|
+
* midnight datetime here, that is exactly the lesson this kit is built to
|
|
6
|
+
* enforce (see FRONTMATTER_GUIDANCE below).
|
|
7
|
+
*/
|
|
8
|
+
const FRONTMATTER_GUIDANCE = `<!--
|
|
9
|
+
okf-kit init guidance (delete this comment once the doc is written):
|
|
10
|
+
- \`timestamp\` means "last verified against sources", not "created on".
|
|
11
|
+
Bump it (and add a line to this bundle's log.md) every time you
|
|
12
|
+
re-verify this doc against its sources; never hand-write an artificial
|
|
13
|
+
midnight datetime, use the real instant you did the verification.
|
|
14
|
+
- \`sources\` lists the repo-root-relative paths this doc DESCRIBES (code,
|
|
15
|
+
config, or other docs elsewhere in the repo). Never list this bundle's
|
|
16
|
+
own directory: a bundle directory changes on every doc edit, so a
|
|
17
|
+
self-referential \`sources\` entry goes permanently stale. This happened
|
|
18
|
+
to the OKF pilot's own BENCHMARK.md (agent-tasks docs/okf/BENCHMARK.md),
|
|
19
|
+
which is why this template ships with a placeholder instead of a real
|
|
20
|
+
path: \`okf-kit check\` will report that placeholder as a missing source
|
|
21
|
+
path until you replace it, and that is intentional, not a bug.
|
|
22
|
+
-->`;
|
|
23
|
+
const BENCHMARK_FRONTMATTER_GUIDANCE = `<!--
|
|
24
|
+
okf-kit init guidance (delete this comment once the doc is written):
|
|
25
|
+
- \`timestamp\` means "last verified", not "created on"; bump it (and add a
|
|
26
|
+
line to this bundle's log.md) whenever this record is updated. Never
|
|
27
|
+
hand-write an artificial midnight datetime.
|
|
28
|
+
- This template intentionally has no \`sources:\` key. A benchmark record
|
|
29
|
+
documents a measurement protocol and its results, not a piece of the
|
|
30
|
+
codebase, so there is nothing it "describes" in the sources-shape sense.
|
|
31
|
+
The OKF pilot's own BENCHMARK.md carried \`sources: [docs/okf/]\`,
|
|
32
|
+
pointing at its own bundle directory; that "source" changed on every
|
|
33
|
+
edit to the bundle and was permanently, uselessly stale. Don't repeat
|
|
34
|
+
that mistake: omit \`sources\` here rather than pointing it at yourself.
|
|
35
|
+
-->`;
|
|
36
|
+
const BODY_GUIDANCE = `<!--
|
|
37
|
+
Write dense, source-verified prose: name exact mechanisms (function/class/
|
|
38
|
+
route names), exact file paths, and exact identifiers (config keys, env
|
|
39
|
+
vars, error codes). Avoid filler like "this module handles X" without
|
|
40
|
+
naming the function that does it. Every sentence here should be checkable
|
|
41
|
+
against a source in \`sources:\` above.
|
|
42
|
+
-->`;
|
|
43
|
+
export function indexTemplate() {
|
|
44
|
+
return `# Knowledge bundle index
|
|
45
|
+
|
|
46
|
+
Scaffolded by \`okf-kit init\`. Replace this placeholder index with a real
|
|
47
|
+
map of the docs in this bundle as you add and rename them.
|
|
48
|
+
|
|
49
|
+
## Overview
|
|
50
|
+
|
|
51
|
+
- [Overview template](overview-template.md), start here for the big picture: what this area covers and where to read next.
|
|
52
|
+
|
|
53
|
+
## Modules
|
|
54
|
+
|
|
55
|
+
- [Module template](module-template.md), one doc per module: responsibility, entry points, key files.
|
|
56
|
+
|
|
57
|
+
## Invariants
|
|
58
|
+
|
|
59
|
+
- [Invariant template](invariant-template.md), one doc per invariant: the guarantee, where it's enforced, what would break it.
|
|
60
|
+
|
|
61
|
+
## Runbooks
|
|
62
|
+
|
|
63
|
+
- [Runbook template](runbook-template.md), one doc per operational procedure: preconditions, steps, verification.
|
|
64
|
+
|
|
65
|
+
## Benchmark
|
|
66
|
+
|
|
67
|
+
- [Benchmark template](benchmark-template.md), measure whether this bundle actually improves discovery, before and after it lands.
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
export function logTemplate(timestamp) {
|
|
71
|
+
return `# Log
|
|
72
|
+
|
|
73
|
+
<!-- Add new entries at the top, newest first. -->
|
|
74
|
+
|
|
75
|
+
- ${timestamp}, bundle scaffolded by \`okf-kit init\`.
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
export function overviewTemplate(timestamp) {
|
|
79
|
+
return `---
|
|
80
|
+
type: overview
|
|
81
|
+
title: <component/area> overview
|
|
82
|
+
description: Orientation doc, what this area covers and where to start reading.
|
|
83
|
+
tags: [overview]
|
|
84
|
+
timestamp: ${timestamp}
|
|
85
|
+
sources:
|
|
86
|
+
- path/to/covered/source
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
${FRONTMATTER_GUIDANCE}
|
|
90
|
+
|
|
91
|
+
# <Component/area> overview
|
|
92
|
+
|
|
93
|
+
${BODY_GUIDANCE}
|
|
94
|
+
|
|
95
|
+
## What this covers
|
|
96
|
+
|
|
97
|
+
- <One or two sentences: what area of the system this overview orients a reader to.>
|
|
98
|
+
|
|
99
|
+
## Where to start reading
|
|
100
|
+
|
|
101
|
+
- <Exact entry-point file and function/route, e.g. \`src/server.ts\`, \`createApp()\`.>
|
|
102
|
+
|
|
103
|
+
## Key modules
|
|
104
|
+
|
|
105
|
+
- [Module template](module-template.md), <one line: what this module doc models, once renamed.>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
export function moduleTemplate(timestamp) {
|
|
109
|
+
return `---
|
|
110
|
+
type: module
|
|
111
|
+
title: <module name>
|
|
112
|
+
description: What this module owns, its entry points, and its key files.
|
|
113
|
+
tags: [module]
|
|
114
|
+
timestamp: ${timestamp}
|
|
115
|
+
sources:
|
|
116
|
+
- path/to/covered/source
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
${FRONTMATTER_GUIDANCE}
|
|
120
|
+
|
|
121
|
+
# <Module name>
|
|
122
|
+
|
|
123
|
+
${BODY_GUIDANCE}
|
|
124
|
+
|
|
125
|
+
## Responsibility
|
|
126
|
+
|
|
127
|
+
- <One sentence: what this module owns, and one sentence on what it explicitly does NOT own.>
|
|
128
|
+
|
|
129
|
+
## Entry points
|
|
130
|
+
|
|
131
|
+
- <Exact function/class/route name>, \`<file path>\`
|
|
132
|
+
|
|
133
|
+
## Key files
|
|
134
|
+
|
|
135
|
+
- \`<path>\`, <one line: what lives here>
|
|
136
|
+
|
|
137
|
+
## Invariants enforced here
|
|
138
|
+
|
|
139
|
+
- [Invariant template](invariant-template.md), <link to the specific invariant doc, once renamed, if this module enforces one>
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
export function invariantTemplate(timestamp) {
|
|
143
|
+
return `---
|
|
144
|
+
type: invariant
|
|
145
|
+
title: <invariant name>
|
|
146
|
+
description: A falsifiable invariant, where it is enforced, and what breaks it.
|
|
147
|
+
tags: [invariant]
|
|
148
|
+
timestamp: ${timestamp}
|
|
149
|
+
sources:
|
|
150
|
+
- path/to/covered/source
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
${FRONTMATTER_GUIDANCE}
|
|
154
|
+
|
|
155
|
+
# <Invariant name>
|
|
156
|
+
|
|
157
|
+
${BODY_GUIDANCE}
|
|
158
|
+
|
|
159
|
+
## The invariant
|
|
160
|
+
|
|
161
|
+
- <State the invariant as a single falsifiable sentence.>
|
|
162
|
+
|
|
163
|
+
## Where it's enforced
|
|
164
|
+
|
|
165
|
+
- \`<path>:<line or function>\`, <mechanism: a check, a type, a DB constraint, a migration, ...>
|
|
166
|
+
|
|
167
|
+
## What breaks it
|
|
168
|
+
|
|
169
|
+
- <A concrete scenario that would violate the invariant if the enforcement above were removed or bypassed.>
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
export function runbookTemplate(timestamp) {
|
|
173
|
+
return `---
|
|
174
|
+
type: runbook
|
|
175
|
+
title: <runbook name>
|
|
176
|
+
description: Step-by-step operational procedure with preconditions and verification.
|
|
177
|
+
tags: [runbook]
|
|
178
|
+
timestamp: ${timestamp}
|
|
179
|
+
sources:
|
|
180
|
+
- path/to/covered/source
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
${FRONTMATTER_GUIDANCE}
|
|
184
|
+
|
|
185
|
+
# <Runbook name>
|
|
186
|
+
|
|
187
|
+
${BODY_GUIDANCE}
|
|
188
|
+
|
|
189
|
+
## When to use this
|
|
190
|
+
|
|
191
|
+
- <Trigger condition or symptom that means this runbook applies.>
|
|
192
|
+
|
|
193
|
+
## Preconditions
|
|
194
|
+
|
|
195
|
+
- <Access, tools, or system state required before starting.>
|
|
196
|
+
|
|
197
|
+
## Steps
|
|
198
|
+
|
|
199
|
+
1. <Exact command or action.>
|
|
200
|
+
2. <Exact command or action.>
|
|
201
|
+
|
|
202
|
+
## Verification
|
|
203
|
+
|
|
204
|
+
- <How to confirm the runbook actually worked.>
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
export function benchmarkTemplate(timestamp) {
|
|
208
|
+
return `---
|
|
209
|
+
type: benchmark
|
|
210
|
+
title: <bundle name> discovery benchmark
|
|
211
|
+
description: Before/after measurement of discovery quality for this bundle.
|
|
212
|
+
tags: [benchmark]
|
|
213
|
+
timestamp: ${timestamp}
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
${BENCHMARK_FRONTMATTER_GUIDANCE}
|
|
217
|
+
|
|
218
|
+
# <Bundle name> discovery benchmark
|
|
219
|
+
|
|
220
|
+
${BODY_GUIDANCE}
|
|
221
|
+
|
|
222
|
+
Measures whether this curated OKF bundle improves discovery quality (for
|
|
223
|
+
example via [codebase-oracle](https://github.com/LanNguyenSi/codebase-oracle)
|
|
224
|
+
or whatever search/retrieval tool your agents use) for this repo. Distilled
|
|
225
|
+
from the OKF Phase-0 pilot protocol (agent-tasks \`docs/okf/BENCHMARK.md\`).
|
|
226
|
+
|
|
227
|
+
## Methodology
|
|
228
|
+
|
|
229
|
+
Two runs, identical protocol:
|
|
230
|
+
|
|
231
|
+
- **Baseline:** current index, no bundle concept docs present.
|
|
232
|
+
- **Post-bundle:** after the bundle is merged and the index has been rebuilt.
|
|
233
|
+
|
|
234
|
+
Record the environment for both runs (index/tool version, embeddings model,
|
|
235
|
+
answer-generation model) so a result can be attributed to the bundle and not
|
|
236
|
+
to environment drift between runs.
|
|
237
|
+
|
|
238
|
+
### Integrity rules
|
|
239
|
+
|
|
240
|
+
- Write the question set and scoring rubric, and commit them, BEFORE any
|
|
241
|
+
bundle authoring starts.
|
|
242
|
+
- Keep the bundle author blind to the question set.
|
|
243
|
+
- Verify the ground-truth answer key against source with exact evidence
|
|
244
|
+
(file path, line, or identifier), but do not commit it and do not let it
|
|
245
|
+
reach the index until scoring is complete.
|
|
246
|
+
- Filter out any search/query hit whose only source is this benchmark
|
|
247
|
+
document itself (self-match): it contains the questions verbatim and
|
|
248
|
+
would otherwise inflate its own post-bundle score.
|
|
249
|
+
|
|
250
|
+
### Scoring rubric
|
|
251
|
+
|
|
252
|
+
- **Answer correctness**, judged against the answer key, same judge both runs:
|
|
253
|
+
- 2 = correct: the key facts are present, no materially wrong claim is
|
|
254
|
+
made, AND the answer text itself names at least one concrete pointer to
|
|
255
|
+
a ground-truth file (a path, identifier, or line reference actually
|
|
256
|
+
written in the prose, not merely present in a separate citations list).
|
|
257
|
+
- 1 = partial: right area or mechanism, but a key fact is missing, a minor
|
|
258
|
+
claim is wrong, or the answer never names a concrete pointer in its own
|
|
259
|
+
text.
|
|
260
|
+
- 0 = wrong or missing.
|
|
261
|
+
- **Retrieval hit@5**: 1 if a ground-truth file appears in the top-5
|
|
262
|
+
retrieved chunks for that question, else 0.
|
|
263
|
+
|
|
264
|
+
Do not count citation metadata (a "sources" or "cited from" list attached by
|
|
265
|
+
the tool) as satisfying the pointer requirement above. The pilot's original
|
|
266
|
+
rubric did exactly that, and it rewarded answers whose retrieved chunks
|
|
267
|
+
happened to carry a \`sources:\` frontmatter pointer even when the answer
|
|
268
|
+
text itself never named a concrete file or identifier. That is a metric
|
|
269
|
+
artifact, not evidence the reader learned anything precise: require the
|
|
270
|
+
pointer in the text itself.
|
|
271
|
+
|
|
272
|
+
## Questions
|
|
273
|
+
|
|
274
|
+
| # | Question |
|
|
275
|
+
|---|----------|
|
|
276
|
+
| Q1 | <question> |
|
|
277
|
+
|
|
278
|
+
## Results
|
|
279
|
+
|
|
280
|
+
### Baseline
|
|
281
|
+
|
|
282
|
+
<!-- fill in after the baseline run -->
|
|
283
|
+
|
|
284
|
+
### Post-bundle
|
|
285
|
+
|
|
286
|
+
<!-- fill in after the post-bundle run -->
|
|
287
|
+
|
|
288
|
+
### Decision
|
|
289
|
+
|
|
290
|
+
<!-- go / no-go, and what you'd change next time -->
|
|
291
|
+
`;
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;IAczB,CAAC;AAEL,MAAM,8BAA8B,GAAG;;;;;;;;;;;;IAYnC,CAAC;AAEL,MAAM,aAAa,GAAG;;;;;;IAMlB,CAAC;AAEL,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAwBR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAO;;;;IAIL,SAAS;CACZ,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,OAAO;;;;;aAKI,SAAS;;;;;EAKpB,oBAAoB;;;;EAIpB,aAAa;;;;;;;;;;;;;CAad,CAAC;AACF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO;;;;;aAKI,SAAS;;;;;EAKpB,oBAAoB;;;;EAIpB,aAAa;;;;;;;;;;;;;;;;;CAiBd,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO;;;;;aAKI,SAAS;;;;;EAKpB,oBAAoB;;;;EAIpB,aAAa;;;;;;;;;;;;;CAad,CAAC;AACF,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO;;;;;aAKI,SAAS;;;;;EAKpB,oBAAoB;;;;EAIpB,aAAa;;;;;;;;;;;;;;;;;;CAkBd,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO;;;;;aAKI,SAAS;;;EAGpB,8BAA8B;;;;EAI9B,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuEd,CAAC;AACF,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type Severity = "error" | "warning" | "notice";
|
|
2
|
+
export interface Finding {
|
|
3
|
+
ruleId: string;
|
|
4
|
+
severity: Severity;
|
|
5
|
+
/** Bundle-relative path, forward-slash separated. */
|
|
6
|
+
file: string;
|
|
7
|
+
message: string;
|
|
8
|
+
detail?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface FrontmatterInfo {
|
|
11
|
+
present: boolean;
|
|
12
|
+
parsed?: unknown;
|
|
13
|
+
parseError?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface BundleDoc {
|
|
16
|
+
/** Bundle-relative path, forward-slash separated. */
|
|
17
|
+
relPath: string;
|
|
18
|
+
basename: string;
|
|
19
|
+
isReserved: boolean;
|
|
20
|
+
raw: string;
|
|
21
|
+
frontmatter: FrontmatterInfo;
|
|
22
|
+
body: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Runs `git <args>` in `cwd`. Returns trimmed stdout on success (git exit
|
|
26
|
+
* code 0), or null on any failure (non-zero exit, not a git work tree, git
|
|
27
|
+
* binary missing). Never throws. Injectable so rules that shell out to git
|
|
28
|
+
* (currently only sources-fresh) can be tested with a stub instead of a
|
|
29
|
+
* real git process.
|
|
30
|
+
*/
|
|
31
|
+
export type RunGit = (args: string[], cwd: string) => string | null;
|
|
32
|
+
export interface BundleContext {
|
|
33
|
+
bundleDir: string;
|
|
34
|
+
repoRoot?: string;
|
|
35
|
+
docs: BundleDoc[];
|
|
36
|
+
/** Defaults to a real `git` child-process call (see src/git.ts) when a rule needs it and none was injected. */
|
|
37
|
+
runGit?: RunGit;
|
|
38
|
+
}
|
|
39
|
+
export interface Rule {
|
|
40
|
+
id: string;
|
|
41
|
+
description: string;
|
|
42
|
+
run(ctx: BundleContext): Finding[];
|
|
43
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
2
|
+
/** Whether parsed frontmatter has a `sources` key at all, regardless of shape validity. */
|
|
3
|
+
export declare function hasSourcesKey(parsed: unknown): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the frontmatter `sources` array when it is shaped correctly (a
|
|
6
|
+
* non-empty array of non-empty strings), or undefined otherwise (absent, or
|
|
7
|
+
* present but malformed). Shared between sources-shape (which reports the
|
|
8
|
+
* shape violation) and sources-fresh (which only assesses staleness for a
|
|
9
|
+
* validly-shaped sources list, leaving the shape error itself to
|
|
10
|
+
* sources-shape).
|
|
11
|
+
*/
|
|
12
|
+
export declare function getValidSources(parsed: unknown): string[] | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the frontmatter `timestamp` as a Unix epoch (seconds), or
|
|
15
|
+
* undefined when absent, not a Date/string, or not parseable as a date.
|
|
16
|
+
* Used by sources-fresh to compare against a source path's last-commit
|
|
17
|
+
* time. Accepts a `Date` instance first: the `yaml` package's default
|
|
18
|
+
* (core) schema resolves timestamp scalars to strings, but a YAML 1.1
|
|
19
|
+
* `!!timestamp` tag (or a caller constructing frontmatter programmatically)
|
|
20
|
+
* can hand back a native `Date`, and that should be assessed rather than
|
|
21
|
+
* degrade to the no-valid-timestamp notice.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getTimestampEpoch(parsed: unknown): number | undefined;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
/** Whether parsed frontmatter has a `sources` key at all, regardless of shape validity. */
|
|
5
|
+
export function hasSourcesKey(parsed) {
|
|
6
|
+
return isRecord(parsed) && "sources" in parsed;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Returns the frontmatter `sources` array when it is shaped correctly (a
|
|
10
|
+
* non-empty array of non-empty strings), or undefined otherwise (absent, or
|
|
11
|
+
* present but malformed). Shared between sources-shape (which reports the
|
|
12
|
+
* shape violation) and sources-fresh (which only assesses staleness for a
|
|
13
|
+
* validly-shaped sources list, leaving the shape error itself to
|
|
14
|
+
* sources-shape).
|
|
15
|
+
*/
|
|
16
|
+
export function getValidSources(parsed) {
|
|
17
|
+
if (!hasSourcesKey(parsed))
|
|
18
|
+
return undefined;
|
|
19
|
+
const sources = parsed.sources;
|
|
20
|
+
const isValidShape = Array.isArray(sources) &&
|
|
21
|
+
sources.length > 0 &&
|
|
22
|
+
sources.every((s) => typeof s === "string" && s.trim() !== "");
|
|
23
|
+
return isValidShape ? sources : undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the frontmatter `timestamp` as a Unix epoch (seconds), or
|
|
27
|
+
* undefined when absent, not a Date/string, or not parseable as a date.
|
|
28
|
+
* Used by sources-fresh to compare against a source path's last-commit
|
|
29
|
+
* time. Accepts a `Date` instance first: the `yaml` package's default
|
|
30
|
+
* (core) schema resolves timestamp scalars to strings, but a YAML 1.1
|
|
31
|
+
* `!!timestamp` tag (or a caller constructing frontmatter programmatically)
|
|
32
|
+
* can hand back a native `Date`, and that should be assessed rather than
|
|
33
|
+
* degrade to the no-valid-timestamp notice.
|
|
34
|
+
*/
|
|
35
|
+
export function getTimestampEpoch(parsed) {
|
|
36
|
+
if (!isRecord(parsed))
|
|
37
|
+
return undefined;
|
|
38
|
+
const timestamp = parsed.timestamp;
|
|
39
|
+
if (timestamp instanceof Date) {
|
|
40
|
+
const ms = timestamp.getTime();
|
|
41
|
+
return Number.isNaN(ms) ? undefined : Math.floor(ms / 1000);
|
|
42
|
+
}
|
|
43
|
+
if (typeof timestamp !== "string" || timestamp.trim() === "")
|
|
44
|
+
return undefined;
|
|
45
|
+
const ms = Date.parse(timestamp);
|
|
46
|
+
if (Number.isNaN(ms))
|
|
47
|
+
return undefined;
|
|
48
|
+
return Math.floor(ms / 1000);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,IAAI,MAAM,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,MAAe;IAC7C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,MAAM,OAAO,GAAI,MAAkC,CAAC,OAAO,CAAC;IAC5D,MAAM,YAAY,GAChB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QACtB,OAAO,CAAC,MAAM,GAAG,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,OAAO,YAAY,CAAC,CAAC,CAAE,OAAoB,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,IAAI,SAAS,YAAY,IAAI,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;QAC1D,OAAO,SAAS,CAAC;IACnB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "okf-kit",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "CLI that validates OKF v0.1 knowledge bundles for structural correctness",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"okf-kit": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"dev": "tsx src/cli.ts",
|
|
17
|
+
"pretest": "npm run build",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
20
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\""
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"ai",
|
|
24
|
+
"agent",
|
|
25
|
+
"okf",
|
|
26
|
+
"knowledge",
|
|
27
|
+
"lint",
|
|
28
|
+
"dx"
|
|
29
|
+
],
|
|
30
|
+
"author": "Lan Nguyen Si",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/LanNguyenSi/agent-dx.git",
|
|
35
|
+
"directory": "packages/okf-kit"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"commander": "^12.0.0",
|
|
39
|
+
"yaml": "^2.5.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.11.0",
|
|
43
|
+
"prettier": "^3.8.1",
|
|
44
|
+
"tsx": "^4.22.4",
|
|
45
|
+
"typescript": "^5.3.3",
|
|
46
|
+
"vitest": "^4.1.6"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=20"
|
|
50
|
+
}
|
|
51
|
+
}
|