okf-kit 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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.13.0] - 2026-09-17
11
+
12
+ ### Changed
13
+
14
+ - `sources-fresh`'s re-stamp escape hatch now requires the new frontmatter
15
+ `timestamp` value to be a strictly LATER instant than the value it
16
+ replaced, on both the committed path (`restampedByOwnLastCommit`) and the
17
+ `--dirty-as-now` working-tree path (`dirtyDocRestampVerdict`). A commit
18
+ (or working-tree edit) that moves the stamp BACKWARDS no longer counts as
19
+ a re-verification: the affected sources stay STALE, and the doc gets one
20
+ additional `re-stamp moved backwards: timestamp <prev-iso> -> <new-iso>
21
+ <where> is not a re-verification` warning naming both instants. A rewrite
22
+ to the same instant in a different raw spelling (`...00Z` to
23
+ `...00.000Z`) also no longer counts as a re-stamp, correcting a known
24
+ limitation the README previously documented the other way; that case gets
25
+ its own `re-stamp did not move the timestamp forward: <prev-raw> was
26
+ rewritten as <new-raw> <where>, but both name the same instant (<iso>),
27
+ so this is not a re-verification` notice (not a warning, so `--strict` is
28
+ unaffected), guarded once per doc the same way the backwards warning is.
29
+ An unchanged, byte-identical timestamp value still gets neither: it was
30
+ never a re-stamp attempt. The comparison reads both instants at
31
+ MILLISECOND resolution (a new `getTimestampEpochMs` helper in
32
+ `src/util.ts`, used only here), so two re-stamps less than a second apart
33
+ are not misread as the same instant. Direction is judged only where both
34
+ values name the same instant on every machine: a value that cannot be
35
+ parsed to an instant at all, or one spelled without a UTC designator
36
+ (`2026-01-01T13:00:00`, which `Date.parse` resolves in the machine's own
37
+ timezone), falls back to comparing the raw values' identity exactly as
38
+ before this direction rule existed, so no direction verdict, and no
39
+ `--strict` exit code arising from one, can depend on the runner's `TZ`;
40
+ that holds for either side of the comparison, the new value and the one
41
+ it replaced alike. The rule's day-wide staleness comparison still
42
+ resolves a designator-less stamp in local time, unchanged by this
43
+ release, and a native YAML date (`!!timestamp`) needs no designator and
44
+ is judged normally. Tracker: agent-dx task `ccdf051b`.
45
+
46
+ - CI: the agent-dx `okf-anchor-guard` job (`.github/workflows/ci.yml`) and
47
+ `okf-staleness` job (`.github/workflows/okf-staleness.yml`)'s "Install
48
+ okf-kit" step now probes the pinned version with `npm view
49
+ okf-kit@<pin> version`, confirms a failed probe with a second,
50
+ package-level `npm view okf-kit versions --json` probe before deciding
51
+ anything, then installs the published pin, builds
52
+ `packages/okf-kit` from the PR tree when the pin is confirmed
53
+ unpublished and equal to `packages/okf-kit/package.json`'s version, or
54
+ fails loudly otherwise. Previously the step installed the pinned
55
+ version unconditionally with no fallback. See
56
+ `packages/orchestrator-workflow/docs/okf/log.md` for the full behavior
57
+ and the design considered and rejected along the way.
58
+
59
+ ## [0.12.1] - 2026-09-15
60
+
61
+ - The npm tarball now ships a `LICENSE` file matching the repo root LICENSE
62
+ (MIT), asserted by the monorepo's `lint-package-licenses` CI job.
63
+
10
64
  ## [0.12.0] - 2026-09-13
11
65
 
12
66
  ### Added
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lan Nguyen Si
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -76,7 +76,7 @@ Every template doc except `benchmark-template.md` ships with `sources: [path/to/
76
76
  | `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. |
77
77
  | `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. |
78
78
  | `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. |
79
- | `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 re-stamping commit (re-stamp decided by comparing frontmatter `timestamp` values across that commit's first-parent boundary). With `--dirty-as-now`, a source with an uncommitted change is judged as of right now instead of its last commit. See "Staleness (sources-fresh)" below. |
79
+ | `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 re-stamping commit (re-stamp decided by comparing frontmatter `timestamp` values, read as instants at millisecond resolution, across that commit's first-parent boundary: the new value must be strictly LATER, a backwards move is not a re-stamp and is separately reported as a warning, a rewrite to the same instant is separately reported as a notice). With `--dirty-as-now`, a source with an uncommitted change is judged as of right now instead of its last commit. See "Staleness (sources-fresh)" below. |
80
80
  | `sources-fresh-future` | warning | For the same docs as `sources-fresh`, flags a `timestamp` later than the doc file's own last commit by more than a clock-skew allowance (default 10 minutes, `--future-skew-minutes`). Catches a local wall-clock time mistakenly written with a `Z`/UTC suffix. See "Staleness (sources-fresh)" below. |
81
81
  | `citations-resolve` | warning / notice | For docs with a repo root, flags a `` `path:N`/`path:N-M` `` citation (and its `` `:N` ``/`` -`M` ``/`` (`N`) `` continuations, and bare paragraph-bound short forms `:N-M`/`(N-M)`) whose target file is missing, whose range is inverted or exceeds the file, or whose start line is blank or (for a non-markdown target) only a closing brace. A full citation may also carry an optional `#anchor` (e.g. `` `CHANGELOG.md:50-144#0.24.0` ``), checked against the target's own structure/content instead of just its line numbers. A backtick-delimited `` `path:#heading` `` citation (`.md` targets only) resolves to a whole Markdown section instead of a line range, immune to every line-number shift above it; see "Heading-section citations" below. A short-form citation's range into a test file is also checked for a describe/it block boundary. `--require-anchors` opts into five additional checks; see "Anchor strictness (opt-in, `--require-anchors`)" below. See "Citation resolution (citations-resolve)" below. |
82
82
  | `prose-line-references` | (opt-in, `--prose-line-references`) warning / notice | Off by default. Flags a prose-embedded line reference outside `citations-resolve`'s own backtick grammar (`line N`, `lines N-M`, `lines N to M`) that is drifted, unresolvable, or ambiguous once bound to the nearest named file. `--prose-line-references-strict` additionally flags every such reference as a formatting policy violation. See "Prose line references (opt-in, `--prose-line-references`)" below. |
@@ -91,13 +91,15 @@ Pass `--repo-root` explicitly to pin a specific root (useful in CI when the bund
91
91
 
92
92
  ## Staleness (sources-fresh)
93
93
 
94
- `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, PROVIDED that same commit actually re-stamped the doc. "Re-stamped" is decided by VALUE, not by diff text: okf-kit reads the doc's frontmatter at that commit and in the commit's first parent, parses both, and compares the `timestamp` values -- they differ, or the doc did not exist in the parent at all (it was created there), and it counts as re-stamped. The lookup follows a rename, so `git mv`ing a doc is not a creation, and it reads trees rather than a patch, so a merge commit (including the `refs/pull/N/merge` ref CI checks out) is assessed like any other commit. 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. It does NOT extend to a commit that merely happens to also touch the doc file -- a typo fix, a co-committed prose edit, a repo-wide formatter run -- without rewriting the stamp: that commit carries no verification claim, so staleness stands. "Created" is trusted only in a genuinely unshallow repository: in a shallow clone (`git clone --depth`), a commit with an empty parent list can simply be the boundary history was grafted onto, not the doc's real first commit, so this case gets the same not-assessable notice as any other unanswerable re-stamp question rather than an assumed pass (see "CI usage" below for the `fetch-depth: 0` remedy). The rule never blocks a doc that has no `sources`, and it never invents an error where git can't give a real answer:
94
+ `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, PROVIDED that same commit actually re-stamped the doc. "Re-stamped" is decided by VALUE, not by diff text: okf-kit reads the doc's frontmatter at that commit and in the commit's first parent, parses both, and compares the `timestamp` VALUES as parsed instants, read at millisecond resolution -- the doc did not exist in the parent at all (it was created there), or the commit's value is strictly LATER than the parent's, and it counts as re-stamped. A value that moves to an EARLIER instant is not a re-stamp, and is additionally reported as its own warning (`re-stamp moved backwards`) naming the previous and new instants. A value that is actually REWRITTEN to the SAME instant in a different raw spelling (adding milliseconds that round to nothing, or switching between a quoted string and a native YAML date) is likewise not a re-stamp, and is additionally reported as its own notice naming both raw spellings; an unchanged value (the frontmatter timestamp is byte-identical across the commit, the common case for a co-committed body edit or formatter run) gets neither the warning nor the notice, since it was never a re-stamp attempt at all. Direction is judged only where BOTH sides name the same instant on every machine; a side that does not takes a raw-identity fallback instead of a verdict that depends on `TZ` (see **Designator gate**). The lookup follows a rename, so `git mv`ing a doc is not a creation, and it reads trees rather than a patch, so a merge commit (including the `refs/pull/N/merge` ref CI checks out) is assessed like any other commit. 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. It does NOT extend to a commit that merely happens to also touch the doc file -- a typo fix, a co-committed prose edit, a repo-wide formatter run -- without moving the stamp strictly forward: that commit carries no verification claim, so staleness stands. "Created" is trusted only in a genuinely unshallow repository: in a shallow clone (`git clone --depth`), a commit with an empty parent list can simply be the boundary history was grafted onto, not the doc's real first commit, so this case gets the same not-assessable notice as any other unanswerable re-stamp question rather than an assumed pass (see "CI usage" below for the `fetch-depth: 0` remedy). The rule never blocks a doc that has no `sources`, and it never invents an error where git can't give a real answer:
95
95
 
96
96
  | Situation | Severity | Message |
97
97
  |-----------|----------|---------|
98
98
  | 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>` |
99
99
  | A source path's last commit is newer than the doc's `timestamp`, at/before the doc file's last commit, AND that commit re-stamped the doc | (nothing) | fresh: doc and source landed together with a real re-stamp (or the doc was committed later, or created there) |
100
100
  | A source path's last commit is newer than the doc's `timestamp`, at/before the doc file's last commit, but that commit did NOT re-stamp the doc | warning | `STALE: <path> changed <iso> after doc timestamp <iso>` (co-commit with no re-stamp is not an exception) |
101
+ | Same, but that commit (or, under `--dirty-as-now`, the working tree) moved the `timestamp` value BACKWARDS to an EARLIER instant (when both values are direction-comparable; see **Designator gate**) | warning (STALE) + warning (extra) | the same `STALE: ...` warning above, PLUS one `re-stamp moved backwards: timestamp <prev-iso> -> <new-iso> <where> is not a re-verification` warning per doc |
102
+ | Same, but that commit (or, under `--dirty-as-now`, the working tree) rewrote the `timestamp` value to the SAME instant in a different raw spelling | warning (STALE) + notice (extra) | the same `STALE: ...` warning above, PLUS one `re-stamp did not move the timestamp forward: <prev-raw> was rewritten as <new-raw> <where>, but both name the same instant (<iso>), so this is not a re-verification` notice per doc |
101
103
  | A source path's last commit is newer than the doc's `timestamp`, at/before the doc file's last commit, and git could not be asked whether that commit re-stamped the doc | notice | `staleness not assessable: git could not read the doc's own last commit to decide whether it re-stamped the doc` (once per doc, never a STALE warning and never a silent pass) |
102
104
  | Same, but the repository is a shallow clone and the doc's last commit is the grafted history boundary (an empty parent list that is not really a root commit) | notice | `staleness not assessable: this is a shallow clone ... use fetch-depth: 0 ... to assess it` (once per doc) |
103
105
  | A source path exists but has no git history (untracked) | notice | `untracked by git, staleness unknown: <path>` |
@@ -109,15 +111,17 @@ STALE findings are warnings, so they are advisory by default; run with `--strict
109
111
 
110
112
  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".
111
113
 
112
- Known limitation: the doc-commit comparison suppresses staleness for every source older than the doc file's last re-stamping commit, not only for sources from the same commit -- provided that commit is the one that rewrote the stamp. For a multi-source doc that means a re-stamp silences drift on every source changed before it, even ones that specific re-stamp did not itself verify. The frontmatter `timestamp` still governs sources changed after the doc's last commit. Also note: the check only looks at WHETHER the `timestamp` value changed, never at whether the new value is itself correct -- a hand-typed or deliberately backdated stamp still counts as a re-stamp (`sources-fresh-future` is the rule that catches an implausible value). "Changed" means the parsed frontmatter VALUE changed: a rewrite to the same instant in another representation (`...00Z` to `...00.000Z`) still counts as a re-stamp, since the raw string differs even though it names the same instant, while adding or removing quotes around an otherwise-unchanged value does NOT count, since YAML parsing already normalizes those away before the comparison ever sees them. And the comparison is against the FIRST parent only: a merge that takes the doc wholesale from its second parent is judged against the first-parent baseline, which is the baseline the pull request under review is measured against anyway.
114
+ Known limitation: the doc-commit comparison suppresses staleness for every source older than the doc file's last re-stamping commit, not only for sources from the same commit -- provided that commit is the one that moved the stamp strictly forward. For a multi-source doc that means a re-stamp silences drift on every source changed before it, even ones that specific re-stamp did not itself verify. The frontmatter `timestamp` still governs sources changed after the doc's last commit. Also note: the check only looks at WHETHER the `timestamp` value moved to a strictly LATER instant, never at whether the new value is itself plausible -- a hand-typed FORWARD-dated stamp still counts as a re-stamp (`sources-fresh-future` is the rule that catches an implausible future value), while a stamp moved BACKWARDS never does (it stays STALE and gets its own `re-stamp moved backwards` warning, see the table above), however the value was written. "Moved forward" means the parsed frontmatter VALUE, read as an instant at MILLISECOND resolution, is strictly greater: a rewrite to the same instant in another spelling (`...00Z` to `...00.000Z`) is neither forward nor backward, so it does NOT count as a re-stamp even though the raw string differs -- that case gets its own notice (see the table above), while an unchanged value gets neither. Adding or removing quotes around an otherwise-unchanged value likewise counts as neither, and never triggers the notice, since YAML parsing already normalizes those away before the comparison ever sees them. And the comparison is against the FIRST parent only: a merge that takes the doc wholesale from its second parent is judged against the first-parent baseline, which is the baseline the pull request under review is measured against anyway.
115
+
116
+ **Designator gate** (the one description of this gate; everything else in this README points here). Direction is judged only when BOTH sides name the same instant on every machine. Two cases fall short of that, and both fall back to the pre-direction-rule behavior of asking only whether the raw value CHANGED -- any textual change counts as a re-stamp, and neither the backwards warning nor the same-instant notice can fire. First, a side that cannot be parsed to an instant at all (missing, blank, or a string `Date.parse` rejects). Second, a side spelled without a UTC designator (`2026-01-01T13:00:00`: no `Z`, no numeric offset), which `Date.parse` resolves in the MACHINE'S own timezone -- judged directly, one repository would read as re-stamped on a UTC runner and as moved backwards on a UTC+9 laptop, so the fallback is what keeps the direction verdict a property of the repository rather than of `TZ`. The gate applies to whichever side carries the ambiguity, the new value or the one it replaced. A numeric offset (`+02:00`) is unambiguous and IS judged normally, and so is a native YAML date (`!!timestamp`), which carries no designator because it needs none: the parser already resolved it to a fixed instant. The same test gates `sources-fresh-future`'s clock-skew check, whose allowance is minutes wide, narrower than the hours a timezone shifts; what stays UNGATED is `sources-fresh`'s own day-wide staleness comparison, where a few hours are immaterial and gating them would turn a harmless ambiguity into a skipped check. See `compareRestampDirection`'s doc comment in `src/rules/sources-fresh.ts` for the fallback's exact behavior.
113
117
 
114
118
  **Two-branch squash interaction:** the rule follows one decision procedure, never a catalog of merge shapes, and the procedure is what to read a squash-merge scenario against, not a list of named cases:
115
119
 
116
120
  1. **The doc's last commit.** `git log -1 -- <doc>` under git's default history simplification: a merge whose result for the doc path is identical to one of its parents is skipped, and the walk continues on that side to the real content-changing commit instead; only a merge that changed the doc against every parent is itself returned. The epoch lookup and the re-stamp check below both start from this same resolved commit.
117
121
  2. **The epoch gate.** A source whose own last commit is at or before the resolved doc commit is judged by step 3; a source committed after the resolved doc commit skips step 3 and is judged by the frontmatter `timestamp` alone: STALE whenever the source change also postdates that stamp (the normal case, since nothing the doc showed as of its last commit could reflect a change that had not happened yet), fresh in the rare case that the stamp itself is later than the source change, because the frontmatter comparison is the first thing the rule evaluates.
118
- 3. **The re-stamp check (`restampedByOwnLastCommit`).** Compare the resolved commit's parsed frontmatter `timestamp` VALUE against its value in that SAME commit's first parent (rename-aware); a difference, or the doc being created there, counts as re-stamped.
122
+ 3. **The re-stamp check (`restampedByOwnLastCommit`).** Compare the resolved commit's parsed frontmatter `timestamp` VALUE against its value in that SAME commit's first parent (rename-aware); a value strictly LATER than the parent's, or the doc being created there, counts as re-stamped -- an earlier or equal value does not.
119
123
 
120
- One sentence for the outcome: a source reads fresh when its own last commit is at or before the doc's resolved last commit and that commit re-stamped the value, or when the source's own last commit is at or before the frontmatter `timestamp`; every other assessable case is STALE (the notice outcomes in the table above are neither fresh nor STALE).
124
+ One sentence for the outcome: a source reads fresh when its own last commit is at or before the doc's resolved last commit and that commit moved the `timestamp` value strictly forward (or created the doc), or when the source's own last commit is at or before the frontmatter `timestamp`; every other assessable case is STALE, including a backwards or same-instant "re-stamp" (the not-assessable and no-valid-timestamp notices are neither fresh nor STALE; the backwards warning and the same-instant notice accompany a STALE verdict, they do not replace it).
121
125
 
122
126
  The one consequence that follows for a branch merging a trunk carrying a squash: the squash re-dates every source it touched to the merge instant, and steps 1-3 can only ever see the MERGING branch's own resolved doc commit, never the trunk's route to that squash. So after such a merge, a clean verdict is not evidence the branch's doc was verified against the re-dated source (the known limitation above already says a re-stamp silences drift on sources it never itself checked, and step 3 only asks whether the value moved, never what it verified); a STALE verdict means the branch's resolved doc commit is older than the re-dated source, or newer but carrying no re-stamp of its own. Which of the two the rule reports depends only on where the branch's resolved doc commit falls relative to the squash (steps 1 and 2), never on who edited what:
123
127
 
@@ -136,7 +140,7 @@ The one consequence that follows for a branch merging a trunk carrying a squash:
136
140
 
137
141
  Three smaller behaviors worth knowing. A `sources` entry spelled `.` or `./` (the repo root itself) is dirty whenever ANY path in the work tree is dirty -- it is matched by containment, since `git status` never reports the root as an entry of its own. `--repo-root` may name a SUBDIRECTORY of the repository: `git status` reports dirty paths relative to the repository's top level, and `git show <rev>:<path>` reads a blob by a top-level-relative path too, so the rule respells every path it hands to either (via `git rev-parse --show-prefix`, read once per run) before matching a dirty path or reading a doc's committed value; dirty-path detection and both re-stamp rescues (the working-tree one here and the committed co-commit one above) then behave under a subdirectory root exactly as under the top level, and a same-named doc at the top level is never read in the subdirectory doc's place. And if git cannot be read at all (`status` failing, output past the cap, git missing), `check` emits one bundle-level `sources-fresh` notice reading "`--dirty-as-now` not applied: git status could not be read, judging by committed history only", and both rules fall back to committed history; the flag never reports a silent all-clear it did not actually verify.
138
142
 
139
- The flag also carries a working-tree analogue of the doc-commit re-stamp rescue described above, evaluated against that same virtual commit: a doc re-stamped LOCALLY (its on-disk frontmatter `timestamp` value differs from the value committed at `HEAD` -- a change in EITHER direction, including a backwards move, counts -- and the doc file itself is dirty; an untracked doc counts as re-stamped too, the working-tree equivalent of "the doc being created there") rescues a dirty source exactly like a real re-stamp landing in the same commit does. Without this, bumping a doc's `timestamp` locally and re-running `check --dirty-as-now` could still report STALE, purely because a few seconds pass between writing the new timestamp and running the check -- defeating the point of the recommended invocation below. A doc that is dirty for some OTHER reason (a body edit that leaves the `timestamp` value unchanged) is not rescued: that case still reports STALE, same as before. Reading the doc's committed value distinguishes a genuinely untracked doc (no entry for it at `HEAD` at all -- always a re-stamp) from a real git failure reading an EXISTING `HEAD` blob (a corrupt object, an unreadable blob): only the former is treated as "created"; the latter falls through to the ordinary `staleness not assessable` notice instead of being silently guessed either way.
143
+ The flag also carries a working-tree analogue of the doc-commit re-stamp rescue described above, evaluated against that same virtual commit: a doc re-stamped LOCALLY rescues a dirty source exactly like a real re-stamp landing in the same commit does, judged by the SAME direction rule: the on-disk frontmatter `timestamp` value must be a strictly LATER instant, at millisecond resolution, than the value committed at `HEAD`, and the doc file itself must be dirty for any of this to apply. A backwards move does not count and gets one `re-stamp moved backwards` warning naming the previous and new instants (the source stays STALE); a rewrite to the same instant in a different raw spelling does not count either and gets one `did not move the timestamp forward` notice instead (also STALE); an untracked doc counts as re-stamped, the working-tree equivalent of "the doc being created there". Without the rescue itself, bumping a doc's `timestamp` locally and re-running `check --dirty-as-now` could still report STALE, purely because a few seconds pass between writing the new timestamp and running the check -- defeating the point of the recommended invocation below. A doc that is dirty for some OTHER reason (a body edit that leaves the `timestamp` value unchanged) is not rescued: that case still reports STALE, same as before. Reading the doc's committed value distinguishes a genuinely untracked doc (no entry for it at `HEAD` at all -- always a re-stamp) from a real git failure reading an EXISTING `HEAD` blob (a corrupt object, an unreadable blob): only the former is treated as "created"; the latter falls through to the ordinary `staleness not assessable` notice instead of being silently guessed either way.
140
144
 
141
145
  **Recommended pre-commit invocation**, matching the "re-verify, bump `timestamp`, then commit" discipline above -- run this on the working tree BEFORE committing an edit to any file a bundle lists as a `sources` entry, so a doc that needs re-stamping is caught before the commit that would otherwise make it stale in CI:
142
146
 
@@ -154,7 +158,8 @@ If it reports a doc STALE, re-verify that doc against its current `sources` and
154
158
  | Source edited, doc left alone (not re-stamped) | exit 1, `sources-fresh` STALE |
155
159
  | Source edit and doc re-stamp committed TOGETHER, flag OFF | exit 0, clean (the committed-history co-commit rescue, unaffected by this flag) |
156
160
  | Doc dirty for an unrelated reason (a body edit, `timestamp` value unchanged), source edited | exit 1, `sources-fresh` STALE -- not rescued |
157
- | Doc re-stamped on disk to a value BEFORE the one committed at `HEAD` (a backwards move), source edited | exit 0, clean -- still counts as a re-stamp (see above) |
161
+ | Doc re-stamped on disk to a value BEFORE the one committed at `HEAD` (a backwards move), source edited (when both values are direction-comparable; see **Designator gate** under "Staleness (sources-fresh)") | exit 1, `sources-fresh` STALE, PLUS one `re-stamp moved backwards: timestamp <prev-iso> -> <new-iso> in the working tree is not a re-verification` warning -- a backwards move is NOT a re-verification (see above) |
162
+ | Doc re-stamped on disk to the SAME instant as the one committed at `HEAD`, just in a different raw spelling, source edited | exit 1, `sources-fresh` STALE, PLUS one `re-stamp did not move the timestamp forward: ...` notice -- a rewrite that never moves the instant is NOT a re-verification either (see above) |
158
163
  | Source edit committed ALONE, the doc's re-stamp left uncommitted in the working tree | exit 0, clean locally -- but CI is RED (`sources-fresh` STALE) until that re-stamp is committed too |
159
164
 
160
165
  That last row is the one shape where a clean local run does NOT imply a clean CI run, and it is inherent to the model rather than a gap to be fixed: the flag judges the content in YOUR WORKING TREE, while CI judges only what you actually pushed. Commit the source edit without its doc re-stamp and CI sees a source newer than the doc's committed `timestamp`, exactly as it should. The remedy is the one this section already recommends: commit the re-stamp, in the same commit as the source edit or its own.
@@ -182,7 +187,7 @@ The skew allowance defaults to 10 minutes (600 seconds), absorbing the ordinary
182
187
 
183
188
  **The measure-after-commit discipline both rules enforce:** re-verify the doc against its sources, THEN bump `timestamp` to the real instant of that verification (`new Date().toISOString()` or equivalent, never a hand-written value), THEN commit -- committing without re-stamping is what `sources-fresh` catches, and hand-writing a local time with a `Z` suffix it doesn't have is what `sources-fresh-future` catches.
184
189
 
185
- **Why the UTC-designator gate exists:** a bare local datetime string (no `Z`, no numeric offset) parses under `Date.parse` in the machine's OWN timezone, so the same frontmatter value would compare differently on a UTC+2 laptop than on a UTC CI runner -- unusable against a default allowance measured in minutes. A numeric offset (`+02:00`, `-0500`) is unambiguous and IS assessed normally (`Date.parse` already normalizes it to a real UTC instant); only a fully bare datetime is skipped. `sources-fresh`'s own thresholds are days wide, so this ambiguity doesn't practically matter there and the gate applies only to `sources-fresh-future`.
190
+ **Why a bare datetime is skipped here:** it is the same gate `sources-fresh` applies to its re-stamp direction comparison; of the comparisons in either rule, only `sources-fresh`'s day-wide staleness comparison stays ungated. See **Designator gate** under "Staleness (sources-fresh)" for what the gate tests, which values pass it, and why.
186
191
 
187
192
  **What these two rules catch, precisely, and what they don't:** a source path committed after the doc's `timestamp` (`sources-fresh`'s base case); a source and the doc co-committed together where that commit did NOT re-stamp the doc (`sources-fresh`'s narrowed co-commit exception, see "Staleness (sources-fresh)" above); and a local wall-clock time hand-written with a `Z`/UTC suffix it doesn't actually have (`sources-fresh-future`). What they do NOT catch: a doc-only prose edit that leaves `sources` untouched and the `timestamp` stale -- neither rule has a source-side signal to compare against in that case, so it is not mechanically assessable and stays a reviewer judgment call, the same as before this pair of rules existed.
188
193
 
@@ -320,7 +325,7 @@ This is advisory: don't fail the build on warnings unless you pass `--strict`. U
320
325
  with:
321
326
  fetch-depth: 0
322
327
  - name: OKF bundle check
323
- run: npx okf-kit@0.12.0 check path/to/bundle
328
+ run: npx okf-kit@0.13.0 check path/to/bundle
324
329
  ```
325
330
 
326
331
  Pin the version: an unpinned `npx okf-kit` picks up new rules on their release day, which turns an unrelated PR red.
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { parseFrontmatter } from "../bundle.js";
4
4
  import { runGit as defaultRunGit } from "../git.js";
5
- import { getRawTimestampString, getTimestampEpoch, getTimestampIdentity, getValidSources, hasUtcDesignator, } from "../util.js";
5
+ import { getRawTimestampString, getTimestampEpoch, getTimestampEpochMs, getTimestampIdentity, getValidSources, hasUtcDesignator, } from "../util.js";
6
6
  const RULE_ID = "sources-fresh";
7
7
  const FUTURE_RULE_ID = "sources-fresh-future";
8
8
  /**
@@ -15,7 +15,7 @@ const FUTURE_RULE_ID = "sources-fresh-future";
15
15
  export const DEFAULT_FUTURE_SKEW_SECONDS = 600;
16
16
  export const sourcesFreshRule = {
17
17
  id: RULE_ID,
18
- description: "Frontmatter `sources` paths must not have a last-commit time newer than the doc's `timestamp`, unless the doc's own last commit lands at/after the source's and that same commit actually re-stamped the doc: the doc's parsed frontmatter `timestamp` VALUE at that commit differs from its value in the commit's first parent (rename-aware; creating the doc counts as re-stamping it). Creation is trusted only in a genuinely unshallow repository: in a shallow clone, a commit with no parents can simply be where history was cut off, not a real root commit, so it gets the same `not assessable` notice instead of being assumed created. When git cannot answer the question at all, the doc gets a `not assessable` notice instead of either a STALE warning or a silent pass.",
18
+ description: "Frontmatter `sources` paths must not have a last-commit time newer than the doc's `timestamp`, unless the doc's own last commit lands at/after the source's and that same commit actually re-stamped the doc: the doc's parsed frontmatter `timestamp` VALUE at that commit is strictly LATER than its value in the commit's first parent (rename-aware; creating the doc counts as re-stamping it). A commit that moves the stamp BACKWARDS is not a re-stamp: the affected sources stay STALE, and the doc additionally gets a `re-stamp moved backwards` warning naming the previous and new values. Creation is trusted only in a genuinely unshallow repository: in a shallow clone, a commit with no parents can simply be where history was cut off, not a real root commit, so it gets the same `not assessable` notice instead of being assumed created. When git cannot answer the question at all, the doc gets a `not assessable` notice instead of either a STALE warning or a silent pass.",
19
19
  run(ctx) {
20
20
  const findings = [];
21
21
  const docsWithSources = getDocsWithSources(ctx);
@@ -131,13 +131,18 @@ export const sourcesFreshRule = {
131
131
  return restampMemo;
132
132
  restampMemo =
133
133
  ctx.dirtyAsNow && isDirtyForShared(ctx, git, repoRoot, repoRelDocPath)
134
- ? dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, getTimestampIdentity(doc.frontmatter.parsed), showPrefixFor)
134
+ ? dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, doc.frontmatter.parsed, showPrefixFor)
135
135
  : restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, () => isShallowRepoShared(ctx, git, repoRoot), showPrefixFor);
136
136
  return restampMemo;
137
137
  };
138
138
  // At most one "not assessable" notice per doc, however many of its
139
- // sources hit the unanswerable re-stamp question.
139
+ // sources hit the unanswerable re-stamp question. Likewise at most
140
+ // one "moved backwards" warning per doc, and at most one "same
141
+ // instant" notice per doc (D-009) -- see the isStale branch below --
142
+ // independent of each other and of the not-assessable notice.
140
143
  let notAssessableReported = false;
144
+ let backwardsReported = false;
145
+ let sameInstantReported = false;
141
146
  for (const source of sources) {
142
147
  // A missing path on disk is sources-shape's job to report; avoid a
143
148
  // duplicate/confusing finding here.
@@ -166,25 +171,60 @@ export const sourcesFreshRule = {
166
171
  // it fresh would be a silent pass.
167
172
  const docCommitEpoch = docCommitEpochFor();
168
173
  if (docCommitEpoch !== null && docCommitEpoch >= commitEpoch) {
169
- const verdict = restampFor();
170
- if (verdict === "restamped") {
174
+ const result = restampFor();
175
+ if (result.verdict === "restamped") {
171
176
  isStale = false;
172
177
  }
173
- else if (verdict === "unknown" ||
174
- verdict === "unknown-shallow-root") {
178
+ else if (result.verdict === "unknown" ||
179
+ result.verdict === "unknown-shallow-root") {
175
180
  if (!notAssessableReported) {
176
181
  notAssessableReported = true;
177
182
  findings.push({
178
183
  ruleId: RULE_ID,
179
184
  severity: "notice",
180
185
  file: doc.relPath,
181
- message: verdict === "unknown-shallow-root"
186
+ message: result.verdict === "unknown-shallow-root"
182
187
  ? "staleness not assessable: this is a shallow clone (`git clone --depth`), so git cannot tell whether the doc's earliest available commit really created it or is just where history was cut off -- use `fetch-depth: 0` (or an unshallow checkout) to assess it"
183
188
  : "staleness not assessable: git could not read the doc's own last commit to decide whether it re-stamped the doc",
184
189
  });
185
190
  }
186
191
  continue;
187
192
  }
193
+ else if (result.backwards && !backwardsReported) {
194
+ // Not restamped (isStale stays true, reported as the usual
195
+ // STALE warning below), PLUS one extra warning per doc
196
+ // naming the doc and both instants: a backwards move is not
197
+ // a re-verification and must not blend silently into the
198
+ // ordinary STALE wording (AC-002).
199
+ backwardsReported = true;
200
+ const locationPhrase = result.backwards.location === "working-tree"
201
+ ? "in the working tree"
202
+ : "in the doc's last commit";
203
+ findings.push({
204
+ ruleId: RULE_ID,
205
+ severity: "warning",
206
+ file: doc.relPath,
207
+ message: `re-stamp moved backwards: timestamp ${result.backwards.previousIso} -> ${result.backwards.newIso} ${locationPhrase} is not a re-verification`,
208
+ });
209
+ }
210
+ else if (result.sameInstant && !sameInstantReported) {
211
+ // Not restamped (isStale stays true, reported as the usual
212
+ // STALE warning below), PLUS one extra NOTICE per doc: the
213
+ // value was rewritten but never moved forward, so it carries
214
+ // no verification claim either, but it is not a mistake in
215
+ // the same sense a backwards move is -- a notice, not a
216
+ // warning, so --strict is unaffected (D-009).
217
+ sameInstantReported = true;
218
+ const rewriteLocationPhrase = result.sameInstant.location === "working-tree"
219
+ ? "in the working tree"
220
+ : "in the doc's last commit";
221
+ findings.push({
222
+ ruleId: RULE_ID,
223
+ severity: "notice",
224
+ file: doc.relPath,
225
+ message: `re-stamp did not move the timestamp forward: ${result.sameInstant.previousValue} was rewritten as ${result.sameInstant.newValue} ${rewriteLocationPhrase}, but both name the same instant (${result.sameInstant.instantIso}), so this is not a re-verification`,
226
+ });
227
+ }
188
228
  }
189
229
  }
190
230
  if (isStale) {
@@ -577,13 +617,14 @@ function commitEpochWithDirtyAsNow(ctx, git, repoRoot, relPath, actualEpoch) {
577
617
  * `restampedByOwnLastCommit`'s co-commit check, used in its place (see
578
618
  * `restampFor` in the rule above) whenever the doc itself is dirty. The
579
619
  * virtual commit's implicit "first parent" is simply HEAD, so this compares
580
- * the doc's CURRENT (working-tree) parsed `timestamp` identity -- already
581
- * read from disk by the caller, since `BundleDoc` always reflects the
582
- * working tree, dirty or not -- against the value committed at HEAD for the
583
- * same path. Any change of value, in EITHER direction (including a
584
- * backwards re-stamp), counts as re-stamped, mirroring the committed
585
- * rescue's "changed, not corrected" semantics documented on
586
- * `restampedByOwnLastCommit` below.
620
+ * the doc's CURRENT (working-tree) parsed `timestamp` value -- already read
621
+ * from disk by the caller, since `BundleDoc` always reflects the working
622
+ * tree, dirty or not -- against the value committed at HEAD for the same
623
+ * path. Per D-004, only a value that moves STRICTLY LATER than the one
624
+ * committed at HEAD counts as re-stamped; a backwards move is
625
+ * `not-restamped` and flagged via `compareRestampDirection`'s `backwards`
626
+ * field (`location: "working-tree"`), mirroring the committed rescue's
627
+ * direction rule documented on `restampedByOwnLastCommit` below.
587
628
  *
588
629
  * Distinguishes a genuinely untracked/new doc (no entry for this path at
589
630
  * HEAD at all -- `git ls-tree HEAD -- <path>` succeeds with EMPTY output,
@@ -596,25 +637,30 @@ function commitEpochWithDirtyAsNow(ctx, git, repoRoot, relPath, actualEpoch) {
596
637
  * rather than being silently treated the same as "created". `git ls-tree`
597
638
  * itself failing (an unborn HEAD, git unavailable) is likewise `unknown`.
598
639
  */
599
- function dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, onDiskTimestamp, showPrefix) {
640
+ function dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, onDiskParsed, showPrefix) {
600
641
  // A pathspec (`--`), cwd-relative: stays in the root-relative frame.
601
642
  const treeEntry = git(["ls-tree", "-z", "HEAD", "--", repoRelDocPath], repoRoot);
602
643
  if (treeEntry === null)
603
- return "unknown";
644
+ return { verdict: "unknown" };
604
645
  if (treeEntry === "")
605
- return "restamped";
646
+ return { verdict: "restamped" };
606
647
  const prefix = showPrefix();
607
648
  if (prefix === null)
608
- return "unknown";
649
+ return { verdict: "unknown" };
609
650
  const committed = showBlob(git, repoRoot, "HEAD", toTopLevelPath(prefix, repoRelDocPath));
610
651
  if (committed === null)
611
- return "unknown";
612
- const committedStamp = getTimestampIdentity(parseFrontmatter(committed).frontmatter.parsed);
613
- return committedStamp !== onDiskTimestamp ? "restamped" : "not-restamped";
652
+ return { verdict: "unknown" };
653
+ return compareRestampDirection(onDiskParsed, parseFrontmatter(committed).frontmatter.parsed, "working-tree");
614
654
  }
615
655
  function epochToIso(epochSeconds) {
616
656
  return new Date(epochSeconds * 1000).toISOString();
617
657
  }
658
+ /** Like `epochToIso`, but for a millisecond epoch (`getTimestampEpochMs`,
659
+ * D-008) -- used only by `compareRestampDirection`'s `backwards` and
660
+ * `sameInstant` results. */
661
+ function epochMsToIso(epochMs) {
662
+ return new Date(epochMs).toISOString();
663
+ }
618
664
  /**
619
665
  * Per-run cache of a doc's own REAL (committed) last-commit epoch, keyed by
620
666
  * the `BundleContext` instance so `sources-fresh`'s doc-commit comparison
@@ -673,10 +719,141 @@ function isShallowRepoShared(ctx, git, repoRoot) {
673
719
  shallowRepoCache.set(ctx, isShallow);
674
720
  return isShallow;
675
721
  }
722
+ /**
723
+ * Whether one side of the direction comparison resolves to an instant that
724
+ * is the SAME on every machine, which is what `compareRestampDirection` has
725
+ * to have before it may call one value earlier or later than another
726
+ * (D-013). BOTH sides go through it, not just the newer one.
727
+ *
728
+ * A native `Date` (`getRawTimestampString` returns undefined for it) is
729
+ * comparable: the YAML parser already resolved it to a fixed instant (a
730
+ * `!!timestamp` scalar without a zone is UTC by the YAML 1.1 spec, not
731
+ * local time), and `Date#getTime()` is that instant on every machine.
732
+ * Undefined for any OTHER reason (missing, blank, non-scalar) cannot reach
733
+ * here: this is only consulted for a side `getTimestampEpochMs` already
734
+ * resolved, and those cases resolve to undefined there.
735
+ *
736
+ * What `hasUtcDesignator` tests, which comparisons this gate covers, and
737
+ * why, is written down once: see the README's "Designator gate" paragraph
738
+ * under "Staleness (sources-fresh)".
739
+ */
740
+ function isDirectionComparable(parsed) {
741
+ const raw = getRawTimestampString(parsed);
742
+ return raw === undefined || hasUtcDesignator(raw);
743
+ }
744
+ /**
745
+ * How the same-instant notice names ONE side's frontmatter value: its raw
746
+ * spelling, quoted, so the reader sees the two different strings that
747
+ * resolve to the one instant. A native `Date` has no raw spelling to quote
748
+ * (`getRawTimestampString` returns undefined), so it is named by shape plus
749
+ * the instant it resolved to -- which is what makes the string-to-date
750
+ * rewrite readable as the distinct change it is rather than as one value
751
+ * printed twice.
752
+ */
753
+ function describeTimestampValue(parsed, epochMs) {
754
+ const raw = getRawTimestampString(parsed);
755
+ return raw === undefined
756
+ ? `a native YAML date naming ${epochMsToIso(epochMs)}`
757
+ : `"${raw}"`;
758
+ }
759
+ /**
760
+ * Decides the value-comparison branch of a restamp verdict from two parsed
761
+ * frontmatter values: `beforeParsed` (the older side: the first parent's
762
+ * committed value, or the value committed at HEAD for the dirty path) and
763
+ * `currentParsed` (the newer side: the commit's own value, or the on-disk
764
+ * working-tree value for the dirty path).
765
+ *
766
+ * D-004: a re-stamp only counts when the new value is STRICTLY LATER than
767
+ * the value it replaced -- comparing PARSED INSTANTS, never raw strings, so
768
+ * a squash that re-dates sources (and the doc) to the merge instant still
769
+ * passes (later than any pre-merge stamp) while a genuinely backdated
770
+ * re-stamp does not. D-008: that comparison reads both instants at
771
+ * MILLISECOND resolution (`getTimestampEpochMs`), not the whole-second
772
+ * floor `getTimestampEpoch` uses for every other caller in this file, so a
773
+ * genuine forward move of a few hundred milliseconds (two re-stamps inside
774
+ * the same second) is never misread as the same instant. Three outcomes:
775
+ *
776
+ * - new instant > old instant: `restamped` (a real re-verification).
777
+ * - new instant < old instant: `not-restamped`, AND flagged via
778
+ * `backwards` -- a backwards move is never a re-verification and is
779
+ * additionally reported as its own WARNING by the caller.
780
+ * - new instant === old instant, at millisecond resolution: `not-restamped`
781
+ * always (nothing was certified newer). Additionally flagged via
782
+ * `sameInstant` (D-009) ONLY when the raw VALUE was actually rewritten
783
+ * to a different representation of that same instant (switching between
784
+ * a quoted string and a native YAML date, or adding milliseconds that
785
+ * round to nothing -- decided by `getTimestampIdentity`, since two equal
786
+ * instants can still have differently-spelled raw values) -- the caller
787
+ * reports THAT case as its own NOTICE (not a warning, so `--strict` is
788
+ * unaffected) rather than silently folding it into the ordinary STALE
789
+ * wording. A byte-identical value (the common case: a co-committed body
790
+ * edit or formatter run that never touches the stamp at all) was never a
791
+ * re-stamp ATTEMPT, so it gets neither `backwards` nor `sameInstant` --
792
+ * there is nothing to notice.
793
+ *
794
+ * When EITHER side's `timestamp` cannot be parsed to an instant at all
795
+ * (missing, blank, or a string `Date.parse` rejects), OR either side is a
796
+ * string the designator gate rejects (D-013, see `isDirectionComparable`),
797
+ * direction cannot be judged: this falls back to today's pre-D-004
798
+ * behaviour of comparing the two values' raw IDENTITY
799
+ * (`getTimestampIdentity`) instead of guessing a direction -- any textual
800
+ * change still counts as `restamped`, exactly as before this decision
801
+ * existed, and never triggers `backwards` or `sameInstant` (there is no
802
+ * direction to report either way).
803
+ */
804
+ function compareRestampDirection(currentParsed, beforeParsed, location) {
805
+ const currentEpochMs = getTimestampEpochMs(currentParsed);
806
+ const beforeEpochMs = getTimestampEpochMs(beforeParsed);
807
+ if (currentEpochMs === undefined ||
808
+ beforeEpochMs === undefined ||
809
+ !isDirectionComparable(currentParsed) ||
810
+ !isDirectionComparable(beforeParsed)) {
811
+ const currentStamp = getTimestampIdentity(currentParsed);
812
+ const beforeStamp = getTimestampIdentity(beforeParsed);
813
+ return {
814
+ verdict: currentStamp !== beforeStamp ? "restamped" : "not-restamped",
815
+ };
816
+ }
817
+ if (currentEpochMs > beforeEpochMs)
818
+ return { verdict: "restamped" };
819
+ if (currentEpochMs < beforeEpochMs) {
820
+ return {
821
+ verdict: "not-restamped",
822
+ backwards: {
823
+ previousIso: epochMsToIso(beforeEpochMs),
824
+ newIso: epochMsToIso(currentEpochMs),
825
+ location,
826
+ },
827
+ };
828
+ }
829
+ // Same instant. An UNCHANGED value (byte-identical frontmatter, the
830
+ // common case: a co-committed body edit or formatter run that never
831
+ // touches the doc's timestamp at all) reports nothing extra here -- it
832
+ // was never a re-stamp ATTEMPT, so there is nothing to notice. Only a
833
+ // value that was actually rewritten to a DIFFERENT raw representation of
834
+ // the same instant (getTimestampIdentity differs) gets the D-009 notice:
835
+ // that is the case someone touched the stamp but the instant never
836
+ // actually moved.
837
+ const currentStamp = getTimestampIdentity(currentParsed);
838
+ const beforeStamp = getTimestampIdentity(beforeParsed);
839
+ if (currentStamp === beforeStamp)
840
+ return { verdict: "not-restamped" };
841
+ return {
842
+ verdict: "not-restamped",
843
+ sameInstant: {
844
+ previousValue: describeTimestampValue(beforeParsed, beforeEpochMs),
845
+ newValue: describeTimestampValue(currentParsed, currentEpochMs),
846
+ instantIso: epochMsToIso(currentEpochMs),
847
+ location,
848
+ },
849
+ };
850
+ }
676
851
  /**
677
852
  * Whether `doc`'s own last commit actually re-stamped it, decided by
678
853
  * comparing the doc's PARSED FRONTMATTER `timestamp` VALUE at that commit
679
- * against its value in the commit's FIRST PARENT. A doc created by that
854
+ * against its value in the commit's FIRST PARENT (see
855
+ * `compareRestampDirection`: the new value must be strictly LATER, not
856
+ * merely different, D-004). A doc created by that
680
857
  * commit (or by a genuine root commit of an unshallow repository) counts as
681
858
  * re-stamped: its stamp arrived with it. In a SHALLOW clone (`git clone
682
859
  * --depth`), the doc's last commit can have an EMPTY parent list purely
@@ -688,9 +865,10 @@ function isShallowRepoShared(ctx, git, repoRoot) {
688
865
  *
689
866
  * This is what narrows `sources-fresh`'s co-commit staleness exception: a
690
867
  * commit that merely happens to also touch the doc file (a typo fix, a
691
- * repo-wide formatter run, a rename) without changing the stamp carries no
692
- * verification claim and must NOT suppress staleness; only a commit that
693
- * actually rewrote the stamp (or created the doc) does.
868
+ * repo-wide formatter run, a rename) without moving the stamp strictly
869
+ * forward carries no verification claim and must NOT suppress staleness;
870
+ * only a commit that actually moved the stamp to a later instant (or
871
+ * created the doc) does.
694
872
  *
695
873
  * WHY VALUES AND NOT DIFF TEXT. An earlier version of this check scanned
696
874
  * `git log -1 -p -- <doc>` for a `^\+timestamp:` line. Scanning diff TEXT is
@@ -712,13 +890,13 @@ function isShallowRepoShared(ctx, git, repoRoot) {
712
890
  * an invisible false-positive STALE. Both trees are perfectly readable
713
891
  * via `git show`, merge or not.
714
892
  *
715
- * Its limits, stated rather than hidden: this answers "did the value
716
- * change", never "is the new value right". A hand-typed or backdated stamp
717
- * still counts as a re-stamp (`sources-fresh-future` is the rule that
718
- * catches an implausible value), and comparing against only the FIRST parent
719
- * means a merge that takes its doc content wholesale from the second parent
720
- * is judged against the first-parent baseline, which is the same baseline
721
- * the PR under review is measured against.
893
+ * Its limits, stated rather than hidden: this answers "did the value move
894
+ * strictly forward", never "is the new value plausible". A hand-typed
895
+ * forward-dated stamp still counts as a re-stamp (`sources-fresh-future` is
896
+ * the rule that catches an implausible future value), and comparing against
897
+ * only the FIRST parent means a merge that takes its doc content wholesale
898
+ * from the second parent is judged against the first-parent baseline, which
899
+ * is the same baseline the PR under review is measured against.
722
900
  *
723
901
  * Spends at most 4 git processes and returns early before most of them: 1
724
902
  * for the commit + parents, 1 for the rename-aware name-status lookup
@@ -734,10 +912,10 @@ function restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, isShallowRepo,
734
912
  // to a parent resolves to the real content-changing commit on that side.
735
913
  const head = git(["log", "-1", "--format=%H%n%P", "--", repoRelDocPath], repoRoot);
736
914
  if (head === null)
737
- return "unknown";
915
+ return { verdict: "unknown" };
738
916
  const [sha, parentLine] = head.split("\n");
739
917
  if (!sha)
740
- return "unknown";
918
+ return { verdict: "unknown" };
741
919
  const parents = (parentLine ?? "").split(" ").filter((p) => p !== "");
742
920
  // An empty parent list means "the doc arrived with the repo's first
743
921
  // commit, stamp and all" ONLY in a genuinely unshallow repository. In a
@@ -749,7 +927,7 @@ function restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, isShallowRepo,
749
927
  // staleness. isShallowRepo() is checked here, not unconditionally at the
750
928
  // top of this function, so an unshallow repo never pays for it.
751
929
  if (parents.length === 0) {
752
- return isShallowRepo() ? "unknown-shallow-root" : "restamped";
930
+ return { verdict: isShallowRepo() ? "unknown-shallow-root" : "restamped" };
753
931
  }
754
932
  const firstParent = parents[0];
755
933
  // From here on everything git reports or takes is in the top-level frame
@@ -757,24 +935,23 @@ function restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, isShallowRepo,
757
935
  // against, and both `<rev>:<path>` blob reads.
758
936
  const prefix = showPrefix();
759
937
  if (prefix === null)
760
- return "unknown";
938
+ return { verdict: "unknown" };
761
939
  const topLevelDocPath = toTopLevelPath(prefix, repoRelDocPath);
762
940
  const previous = previousPathIn(git, repoRoot, firstParent, sha, topLevelDocPath);
763
941
  if (previous.kind === "unknown")
764
- return "unknown";
942
+ return { verdict: "unknown" };
765
943
  if (previous.kind === "created")
766
- return "restamped";
944
+ return { verdict: "restamped" };
767
945
  const current = showBlob(git, repoRoot, sha, topLevelDocPath);
768
946
  if (current === null)
769
- return "unknown";
947
+ return { verdict: "unknown" };
770
948
  const before = showBlob(git, repoRoot, firstParent, previous.path);
771
949
  if (before === null)
772
- return "unknown";
773
- const currentStamp = getTimestampIdentity(parseFrontmatter(current).frontmatter.parsed);
774
- const beforeStamp = getTimestampIdentity(parseFrontmatter(before).frontmatter.parsed);
775
- // Both undefined (no parseable stamp on either side) compares equal, i.e.
776
- // "not re-stamped" -- nothing was rewritten, so nothing is claimed.
777
- return currentStamp !== beforeStamp ? "restamped" : "not-restamped";
950
+ return { verdict: "unknown" };
951
+ // Both undefined (no parseable stamp on either side) compares equal in
952
+ // compareRestampDirection's identity fallback, i.e. "not re-stamped" --
953
+ // nothing was rewritten, so nothing is claimed.
954
+ return compareRestampDirection(parseFrontmatter(current).frontmatter.parsed, parseFrontmatter(before).frontmatter.parsed, "commit");
778
955
  }
779
956
  /**
780
957
  * Where the doc lived in `parentSha`, so its previous revision can be read
@@ -1 +1 @@
1
- {"version":3,"file":"sources-fresh.js","sourceRoot":"","sources":["../../src/rules/sources-fresh.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sources-fresh.js","sourceRoot":"","sources":["../../src/rules/sources-fresh.ts"],"names":[],"mappings":"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"}
package/dist/util.d.ts CHANGED
@@ -21,55 +21,84 @@ export declare function getValidSources(parsed: unknown): string[] | undefined;
21
21
  * degrade to the no-valid-timestamp notice.
22
22
  */
23
23
  export declare function getTimestampEpoch(parsed: unknown): number | undefined;
24
+ /**
25
+ * Like `getTimestampEpoch`, but at MILLISECOND resolution instead of
26
+ * floored to the second. Used ONLY by `compareRestampDirection` (D-008):
27
+ * flooring to whole seconds would treat two distinct re-stamps less than a
28
+ * second apart (`...00.000Z` -> `...00.500Z`) as the SAME instant, which is
29
+ * wrong for a comparison whose whole job is deciding "strictly later or
30
+ * not" (a genuine forward move at that resolution must read as
31
+ * `restamped`, not as the D-009 same-instant notice). Every OTHER
32
+ * `getTimestampEpoch` caller keeps calling that function unchanged: their
33
+ * thresholds (days, not milliseconds) make the distinction this function
34
+ * exists for immaterial there, so there was no reason to touch them. Read
35
+ * as an instant at millisecond resolution, exactly like `getTimestampEpoch`
36
+ * otherwise -- same `Date` vs. string handling, same undefined cases.
37
+ */
38
+ export declare function getTimestampEpochMs(parsed: unknown): number | undefined;
24
39
  /**
25
40
  * The frontmatter `timestamp`'s raw string form, or undefined when it is
26
41
  * absent, blank, or not a string -- notably, a native `Date` instance (see
27
42
  * `getTimestampEpoch`'s doc comment) returns undefined here too, since a
28
- * `Date`'s `getTime()` is always UTC-unambiguous and carries none of the
29
- * local-timezone risk `hasUtcDesignator` exists to catch. Used only by
30
- * `sources-fresh-future`'s UTC-designator gate; `sources-fresh` itself has
31
- * no need for the raw string, only the resolved epoch.
43
+ * `Date`'s `getTime()` already names one instant on every machine, so
44
+ * there is no raw spelling left for a caller to inspect. Callers:
45
+ * `hasUtcDesignator`'s two gates (`sources-fresh-future`'s clock-skew
46
+ * check and `isDirectionComparable`, D-013), and `describeTimestampValue`,
47
+ * which names each side's raw spelling in the same-instant notice.
32
48
  */
33
49
  export declare function getRawTimestampString(parsed: unknown): string | undefined;
34
50
  /**
35
51
  * Whether an ISO-ish timestamp string carries an explicit UTC designator
36
- * (`Z`) or a numeric UTC offset (`+02:00`, `-0500`) at its end. A timestamp
37
- * with neither ("2026-01-01T00:00:00", "2026-01-01 00:00:00") parses in
38
- * the machine's LOCAL timezone under `Date.parse`, which would make
39
- * `sources-fresh-future`'s clock-skew comparison swing by hours depending
40
- * on which machine runs the check -- not usable for a check whose default
41
- * allowance is only 10 minutes. A numeric offset, unlike a bare local
42
- * time, is unambiguous: `Date.parse`/`Date#getTime()` already normalizes
43
- * it to a real UTC instant, so no extra conversion is needed here beyond
44
- * recognizing it as present. `sources-fresh`'s own thresholds are in
45
- * days, wide enough that this ambiguity doesn't practically matter there,
46
- * so this helper is deliberately NOT applied to that rule's comparison.
52
+ * (`Z`) or a numeric UTC offset (`+02:00`, `-0500`) at its end. A string
53
+ * with neither ("2026-01-01T00:00:00", "2026-01-01 00:00:00") is resolved
54
+ * by `Date.parse` in the machine's LOCAL timezone; a string with either
55
+ * already names a real UTC instant, so nothing beyond recognizing it is
56
+ * needed here.
57
+ *
58
+ * Two callers gate on this predicate: `sources-fresh-future`'s clock-skew
59
+ * check, and `compareRestampDirection`'s re-stamp direction comparison
60
+ * (through `isDirectionComparable`, D-013). Which comparisons the gate
61
+ * covers, which one stays ungated, and why, is written down once: see the
62
+ * README's "Designator gate" paragraph under "Staleness (sources-fresh)".
47
63
  */
48
64
  export declare function hasUtcDesignator(raw: string): boolean;
49
65
  /**
50
66
  * A canonical identity string for the frontmatter `timestamp` VALUE, or
51
67
  * undefined when the key is absent, blank, or not a scalar this tool
52
- * understands. Two docs (or two revisions of one doc) are "stamped the same"
53
- * iff this returns the same value for both.
68
+ * understands. Two docs (or two revisions of one doc) are "stamped the
69
+ * same" iff this returns the same value for both.
70
+ *
71
+ * `compareRestampDirection` (sources-fresh) consults it in exactly two
72
+ * places, both of them comparing identities rather than instants:
73
+ *
74
+ * - as its FALLBACK, when direction cannot be judged at all: either side
75
+ * unparseable to an instant (`getTimestampEpochMs` returns undefined),
76
+ * or either side a string the designator gate rejects
77
+ * (`isDirectionComparable`, D-013). With nothing comparable to order,
78
+ * the question becomes "did the raw value change", and any textual
79
+ * change counts as `restamped` -- see that function's doc comment for
80
+ * the full three-way split.
81
+ * - when both sides ARE direction-comparable and name the SAME instant,
82
+ * to tell a rewrite (a different spelling of that one instant, e.g.
83
+ * `2026-01-01T00:00:00Z` to `2026-01-01T00:00:00+00:00`, which gets
84
+ * the D-009 notice) from a byte-identical value (never a re-stamp
85
+ * attempt, so it gets nothing).
54
86
  *
55
- * Used by `sources-fresh` to decide whether a commit actually re-stamped a
56
- * doc, by comparing the doc's frontmatter at that commit against its
57
- * frontmatter in the commit's first parent. Comparing VALUES, not diff text,
58
- * is what makes the test immune to the three shapes a diff-text scan gets
59
- * wrong: a `timestamp:` line inside a fenced YAML example in the doc BODY (it
60
- * is not the frontmatter key, so it never reaches this function at all), a
61
- * rename (the two revisions are read by path, not from a diff header), and a
62
- * merge commit (whose combined-diff output is empty while its trees are
63
- * perfectly readable).
87
+ * Comparing VALUES, not diff text, is what makes the identity test immune
88
+ * to the three shapes a diff-text scan gets wrong: a `timestamp:` line
89
+ * inside a fenced YAML example in the doc BODY (it is not the frontmatter
90
+ * key, so it never reaches this function at all), a rename (the two
91
+ * revisions are read by path, not from a diff header), and a merge commit
92
+ * (whose combined-diff output is empty while its trees are perfectly
93
+ * readable).
64
94
  *
65
- * The `date:`/`string:` prefixes keep the two YAML shapes distinguishable: a
66
- * `!!timestamp`-tagged scalar resolving to a native `Date` and a plain string
67
- * are different frontmatter, so rewriting one into the other counts as a
68
- * re-stamp rather than silently comparing equal. Deliberately NOT normalized
69
- * to an epoch: this is an identity test ("did the value change"), not a
70
- * chronological one, so re-writing `2026-01-01T00:00:00Z` as
71
- * `2026-01-01T00:00:00+00:00` counts as a re-stamp -- the author touched the
72
- * stamp. Whether the new value is CORRECT is a separate question this
73
- * function deliberately does not answer (see the README's known limitations).
95
+ * The `date:`/`string:` prefixes keep the two YAML shapes distinguishable:
96
+ * a `!!timestamp`-tagged scalar resolving to a native `Date` and a plain
97
+ * string are different frontmatter, so rewriting one into the other counts
98
+ * as a changed identity here. Deliberately NOT normalized to an epoch:
99
+ * this is an identity test ("did the raw value change"), not a
100
+ * chronological one. Whether the new value is CORRECT is a separate
101
+ * question this function deliberately does not answer (see the README's
102
+ * known limitations).
74
103
  */
75
104
  export declare function getTimestampIdentity(parsed: unknown): string | undefined;
package/dist/util.js CHANGED
@@ -47,14 +47,42 @@ export function getTimestampEpoch(parsed) {
47
47
  return undefined;
48
48
  return Math.floor(ms / 1000);
49
49
  }
50
+ /**
51
+ * Like `getTimestampEpoch`, but at MILLISECOND resolution instead of
52
+ * floored to the second. Used ONLY by `compareRestampDirection` (D-008):
53
+ * flooring to whole seconds would treat two distinct re-stamps less than a
54
+ * second apart (`...00.000Z` -> `...00.500Z`) as the SAME instant, which is
55
+ * wrong for a comparison whose whole job is deciding "strictly later or
56
+ * not" (a genuine forward move at that resolution must read as
57
+ * `restamped`, not as the D-009 same-instant notice). Every OTHER
58
+ * `getTimestampEpoch` caller keeps calling that function unchanged: their
59
+ * thresholds (days, not milliseconds) make the distinction this function
60
+ * exists for immaterial there, so there was no reason to touch them. Read
61
+ * as an instant at millisecond resolution, exactly like `getTimestampEpoch`
62
+ * otherwise -- same `Date` vs. string handling, same undefined cases.
63
+ */
64
+ export function getTimestampEpochMs(parsed) {
65
+ if (!isRecord(parsed))
66
+ return undefined;
67
+ const timestamp = parsed.timestamp;
68
+ if (timestamp instanceof Date) {
69
+ const ms = timestamp.getTime();
70
+ return Number.isNaN(ms) ? undefined : ms;
71
+ }
72
+ if (typeof timestamp !== "string" || timestamp.trim() === "")
73
+ return undefined;
74
+ const ms = Date.parse(timestamp);
75
+ return Number.isNaN(ms) ? undefined : ms;
76
+ }
50
77
  /**
51
78
  * The frontmatter `timestamp`'s raw string form, or undefined when it is
52
79
  * absent, blank, or not a string -- notably, a native `Date` instance (see
53
80
  * `getTimestampEpoch`'s doc comment) returns undefined here too, since a
54
- * `Date`'s `getTime()` is always UTC-unambiguous and carries none of the
55
- * local-timezone risk `hasUtcDesignator` exists to catch. Used only by
56
- * `sources-fresh-future`'s UTC-designator gate; `sources-fresh` itself has
57
- * no need for the raw string, only the resolved epoch.
81
+ * `Date`'s `getTime()` already names one instant on every machine, so
82
+ * there is no raw spelling left for a caller to inspect. Callers:
83
+ * `hasUtcDesignator`'s two gates (`sources-fresh-future`'s clock-skew
84
+ * check and `isDirectionComparable`, D-013), and `describeTimestampValue`,
85
+ * which names each side's raw spelling in the same-instant notice.
58
86
  */
59
87
  export function getRawTimestampString(parsed) {
60
88
  if (!isRecord(parsed))
@@ -66,17 +94,17 @@ export function getRawTimestampString(parsed) {
66
94
  }
67
95
  /**
68
96
  * Whether an ISO-ish timestamp string carries an explicit UTC designator
69
- * (`Z`) or a numeric UTC offset (`+02:00`, `-0500`) at its end. A timestamp
70
- * with neither ("2026-01-01T00:00:00", "2026-01-01 00:00:00") parses in
71
- * the machine's LOCAL timezone under `Date.parse`, which would make
72
- * `sources-fresh-future`'s clock-skew comparison swing by hours depending
73
- * on which machine runs the check -- not usable for a check whose default
74
- * allowance is only 10 minutes. A numeric offset, unlike a bare local
75
- * time, is unambiguous: `Date.parse`/`Date#getTime()` already normalizes
76
- * it to a real UTC instant, so no extra conversion is needed here beyond
77
- * recognizing it as present. `sources-fresh`'s own thresholds are in
78
- * days, wide enough that this ambiguity doesn't practically matter there,
79
- * so this helper is deliberately NOT applied to that rule's comparison.
97
+ * (`Z`) or a numeric UTC offset (`+02:00`, `-0500`) at its end. A string
98
+ * with neither ("2026-01-01T00:00:00", "2026-01-01 00:00:00") is resolved
99
+ * by `Date.parse` in the machine's LOCAL timezone; a string with either
100
+ * already names a real UTC instant, so nothing beyond recognizing it is
101
+ * needed here.
102
+ *
103
+ * Two callers gate on this predicate: `sources-fresh-future`'s clock-skew
104
+ * check, and `compareRestampDirection`'s re-stamp direction comparison
105
+ * (through `isDirectionComparable`, D-013). Which comparisons the gate
106
+ * covers, which one stays ungated, and why, is written down once: see the
107
+ * README's "Designator gate" paragraph under "Staleness (sources-fresh)".
80
108
  */
81
109
  export function hasUtcDesignator(raw) {
82
110
  return /(?:Z|[+-]\d{2}:?\d{2})$/i.test(raw.trim());
@@ -84,28 +112,41 @@ export function hasUtcDesignator(raw) {
84
112
  /**
85
113
  * A canonical identity string for the frontmatter `timestamp` VALUE, or
86
114
  * undefined when the key is absent, blank, or not a scalar this tool
87
- * understands. Two docs (or two revisions of one doc) are "stamped the same"
88
- * iff this returns the same value for both.
115
+ * understands. Two docs (or two revisions of one doc) are "stamped the
116
+ * same" iff this returns the same value for both.
117
+ *
118
+ * `compareRestampDirection` (sources-fresh) consults it in exactly two
119
+ * places, both of them comparing identities rather than instants:
120
+ *
121
+ * - as its FALLBACK, when direction cannot be judged at all: either side
122
+ * unparseable to an instant (`getTimestampEpochMs` returns undefined),
123
+ * or either side a string the designator gate rejects
124
+ * (`isDirectionComparable`, D-013). With nothing comparable to order,
125
+ * the question becomes "did the raw value change", and any textual
126
+ * change counts as `restamped` -- see that function's doc comment for
127
+ * the full three-way split.
128
+ * - when both sides ARE direction-comparable and name the SAME instant,
129
+ * to tell a rewrite (a different spelling of that one instant, e.g.
130
+ * `2026-01-01T00:00:00Z` to `2026-01-01T00:00:00+00:00`, which gets
131
+ * the D-009 notice) from a byte-identical value (never a re-stamp
132
+ * attempt, so it gets nothing).
89
133
  *
90
- * Used by `sources-fresh` to decide whether a commit actually re-stamped a
91
- * doc, by comparing the doc's frontmatter at that commit against its
92
- * frontmatter in the commit's first parent. Comparing VALUES, not diff text,
93
- * is what makes the test immune to the three shapes a diff-text scan gets
94
- * wrong: a `timestamp:` line inside a fenced YAML example in the doc BODY (it
95
- * is not the frontmatter key, so it never reaches this function at all), a
96
- * rename (the two revisions are read by path, not from a diff header), and a
97
- * merge commit (whose combined-diff output is empty while its trees are
98
- * perfectly readable).
134
+ * Comparing VALUES, not diff text, is what makes the identity test immune
135
+ * to the three shapes a diff-text scan gets wrong: a `timestamp:` line
136
+ * inside a fenced YAML example in the doc BODY (it is not the frontmatter
137
+ * key, so it never reaches this function at all), a rename (the two
138
+ * revisions are read by path, not from a diff header), and a merge commit
139
+ * (whose combined-diff output is empty while its trees are perfectly
140
+ * readable).
99
141
  *
100
- * The `date:`/`string:` prefixes keep the two YAML shapes distinguishable: a
101
- * `!!timestamp`-tagged scalar resolving to a native `Date` and a plain string
102
- * are different frontmatter, so rewriting one into the other counts as a
103
- * re-stamp rather than silently comparing equal. Deliberately NOT normalized
104
- * to an epoch: this is an identity test ("did the value change"), not a
105
- * chronological one, so re-writing `2026-01-01T00:00:00Z` as
106
- * `2026-01-01T00:00:00+00:00` counts as a re-stamp -- the author touched the
107
- * stamp. Whether the new value is CORRECT is a separate question this
108
- * function deliberately does not answer (see the README's known limitations).
142
+ * The `date:`/`string:` prefixes keep the two YAML shapes distinguishable:
143
+ * a `!!timestamp`-tagged scalar resolving to a native `Date` and a plain
144
+ * string are different frontmatter, so rewriting one into the other counts
145
+ * as a changed identity here. Deliberately NOT normalized to an epoch:
146
+ * this is an identity test ("did the raw value change"), not a
147
+ * chronological one. Whether the new value is CORRECT is a separate
148
+ * question this function deliberately does not answer (see the README's
149
+ * known limitations).
109
150
  */
110
151
  export function getTimestampIdentity(parsed) {
111
152
  if (!isRecord(parsed))
package/dist/util.js.map CHANGED
@@ -1 +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;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;QAC1D,OAAO,SAAS,CAAC;IACnB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,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,QAAQ,EAAE,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;QAC1D,OAAO,SAAS,CAAC;IACnB,OAAO,UAAU,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;AACtC,CAAC"}
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;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,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,EAAE,CAAC;IAC3C,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,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;QAC1D,OAAO,SAAS,CAAC;IACnB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,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,QAAQ,EAAE,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;QAC1D,OAAO,SAAS,CAAC;IACnB,OAAO,UAAU,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;AACtC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okf-kit",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "CLI that validates OKF v0.1 knowledge bundles for structural correctness",
5
5
  "type": "module",
6
6
  "bin": {