okf-kit 0.10.0 → 0.11.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,116 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.11.0] - 2026-09-12
11
+
12
+ ### Added
13
+
14
+ - `check` gets `--dirty-as-now`: an opt-in flag under which every
15
+ uncommitted change (modified, staged, or untracked per `git status
16
+ --porcelain --untracked-files=all`) is modeled as though it landed in
17
+ ONE virtual commit made
18
+ right now, applied at a single shared choke point
19
+ (`commitEpochWithDirtyAsNow` in `src/rules/sources-fresh.ts`) so both
20
+ `sources-fresh` (a dirty `sources` path's epoch) AND `sources-fresh-future`
21
+ (a dirty DOC's own epoch) read the identical virtual instant, rather than
22
+ each rule -- or each path kind -- getting its own patch. Closes a gap
23
+ surfaced by the 2026-09-11 review-method dogfood (agent-dx PR #236): a
24
+ test file four OKF docs list as a source was edited, a pre-commit `check`
25
+ run reported 0 warnings because the source's last commit still predated
26
+ every doc's `timestamp`, and CI's strict freshness guard then failed once
27
+ the commit landed and gave the source a new, later commit time. Omit the
28
+ flag and both rules are unchanged; see the README's "Uncommitted edits
29
+ (`--dirty-as-now`)" section for the recommended pre-commit invocation and
30
+ the exact parity matrix (six working-tree states, each reproduced
31
+ through the built CLI with `--strict` exit codes, including the one
32
+ shape inherent to the model where a clean local run does NOT imply a
33
+ clean CI run: a source edit committed alone while its doc re-stamp stays
34
+ uncommitted). Carries a working-tree
35
+ analogue of `sources-fresh`'s own co-commit re-stamp rescue, evaluated
36
+ against that same virtual commit: a doc re-stamped locally (uncommitted,
37
+ on-disk `timestamp` differing -- in EITHER direction -- from the value
38
+ committed at `HEAD`; an untracked doc counts as re-stamped too) rescues a
39
+ dirty source exactly like a real re-stamp landing in the same commit
40
+ does, so the README's recommended `--dirty-as-now --strict` pre-commit
41
+ gate can actually be made green by following its own remedy (re-stamp,
42
+ then commit) while the source stays uncommitted. Reads the work tree's
43
+ dirty paths once per `check` run (`git --no-optional-locks status
44
+ --porcelain=v2 -z --untracked-files=all`), not once per unique source
45
+ path, and normalizes a `./`-prefixed or `/`-suffixed path spelling
46
+ before matching it against that dirty-paths set, so any spelling of the
47
+ same source or doc path matches consistently. `--untracked-files=all` is
48
+ load-bearing, not decoration: git's default untracked mode collapses a
49
+ brand-new directory into a single `? newdir/` record and never names the
50
+ files inside it, so a source or doc inside one matched nothing and the
51
+ flag reported `untracked by git` (exit 0) for content a plain `check`
52
+ reported STALE (exit 1) the moment it was committed -- the exact
53
+ divergence the flag exists to close. A `sources` entry spelled `.`/`./`
54
+ (the repo root) is matched by containment rather than by lookup, since
55
+ `git status` never reports the root as an entry; a `--repo-root` naming
56
+ a SUBDIRECTORY of the repository is handled by rebasing the queried path
57
+ onto the repository top level (`git rev-parse --show-prefix`, the run's
58
+ second and last extra git process) instead of silently matching nothing.
59
+ When git cannot be read at all (`status` failing, its output past the
60
+ 16 MiB `MAX_GIT_OUTPUT_BYTES` cap, git missing), the run emits one
61
+ bundle-level notice -- "`--dirty-as-now` not applied: git status could
62
+ not be read, judging by committed history only" -- rather than falling
63
+ back to committed history in a silence indistinguishable from a clean
64
+ tree. Distinguishes a genuinely untracked doc (no entry
65
+ for it at `HEAD` at all) from a real git failure reading an existing
66
+ `HEAD` blob when deciding whether a dirty doc's own re-stamp counts,
67
+ falling through to the ordinary not-assessable notice in the latter
68
+ case rather than guessing.
69
+
70
+ ### Documented
71
+
72
+ - Decision (task agent-dx 27c4f709): the anchored, path-less continuation
73
+ form the `orchestrator-workflow` package's dogfood bundle writes
74
+ (`` `:N-M#"anchor"` ``) is declared bundle-local, not ported into
75
+ `CONT_COLON_RE`/`SHORT_FORM_COLON_RE`. See the README's "Citation
76
+ resolution (citations-resolve)" section for the who-pays and the port
77
+ trigger.
78
+ - Decision, kept option (a): the rule stays as-is; two loosening
79
+ alternatives were considered and rejected. The README's "Staleness
80
+ (sources-fresh)" section now documents the two-branch squash-merge
81
+ interaction as the rule's own three-step decision procedure (the
82
+ doc-last-commit lookup under git's default history simplification, the
83
+ epoch gate, and the value-level re-stamp check) instead of an
84
+ enumeration of merge shapes, plus the one consequence that follows for
85
+ any branch merging a squash-carrying trunk. The two rejected
86
+ alternatives: (b) a source counts fresh whenever the doc's last commit
87
+ merely postdates it, with no re-stamp required -- readers pay, because
88
+ any merge or unrelated doc touch would silence real drift; (c) compare
89
+ against the doc's own last commit rather than the frontmatter stamp when
90
+ they disagree -- readers pay, because the stamp stops being the
91
+ verification claim. Under the kept option (a), branch authors pay
92
+ instead: one re-verify-and-re-stamp commit after merging a
93
+ squash-carrying trunk (or after changing a source past a trunk squash
94
+ the doc's history resolved through), the recipe now in the README.
95
+ Reproduced with a fixture repo (the trunk and eight branch variants:
96
+ doc untouched, B1; doc untouched with a second source changed after the
97
+ squash, B3; own-older-stamp kept wholesale before the squash, B2, and
98
+ after it, B2late, discriminating the epoch gate from the re-stamp
99
+ check; own-older-stamp with a mixed conflict resolution that changes
100
+ the stamp value, B2a, or does not, B2b; and both re-verify-and-re-stamp
101
+ recipe follow-ups, B2r and B3r) before writing the decision text, then
102
+ checked the procedure's own prediction against all eight plus the
103
+ trunk; no rule change. No fleet pin bump needed (no rule/behavior
104
+ change).
105
+ - Concrete case that motivated this decision: in the `agent-grounding`
106
+ repo, `docs/okf/grounding-stack-overview.md` read STALE after merging
107
+ master (batch-42 task branch `f31ad37f`'s squash-merged re-stamp) into a
108
+ second, longer-lived task branch (`d341afd5`), which carried its own
109
+ older stamp of the same doc; the batch-42 orchestrator run (pandora
110
+ workspace) recorded the resolution as decision D-015, exactly the
111
+ re-verify-and-re-stamp commit this README section now generalizes as
112
+ the recipe.
113
+
114
+ ### Security
115
+
116
+ - devDependencies: vitest and @vitest/mocker 4.1.6 -> 4.1.11
117
+ (GHSA-82fw-gwwq-j7x9), lockfile only, no runtime dependency changed
118
+ (CVE sweep 2026-09-11, agent-dx PR #235).
119
+
10
120
  ## [0.10.0] - 2026-09-06
11
121
 
12
122
  ### Added
package/README.md CHANGED
@@ -34,6 +34,10 @@ okf-kit check path/to/bundle --strict
34
34
 
35
35
  # narrow sources-fresh-future's default 10-minute clock-skew allowance
36
36
  okf-kit check path/to/bundle --future-skew-minutes 2
37
+
38
+ # pre-commit: treat an uncommitted source edit as happening now, so this run
39
+ # reports the same staleness CI will report once you commit
40
+ okf-kit check path/to/bundle --dirty-as-now
37
41
  ```
38
42
 
39
43
  ## Scaffold a bundle (`init`)
@@ -72,7 +76,7 @@ Every template doc except `benchmark-template.md` ships with `sources: [path/to/
72
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. |
73
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. |
74
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. |
75
- | `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). 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 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. |
76
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. |
77
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. |
78
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. |
@@ -107,8 +111,60 @@ Known limitation: a `git log` call that fails for a reason other than "no histor
107
111
 
108
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.
109
113
 
114
+ **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
+
116
+ 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
+ 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.
119
+
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).
121
+
122
+ 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
+
124
+ | Branch shape | Doc commit the lookup resolves to | Verdict | Why |
125
+ |---|---|---|---|
126
+ | B never touched the doc | The trunk's squash commit (the merge is skipped: its doc content matches the trunk's) | Fresh for a source at/before the squash; STALE for a source B itself changes after the squash and after the stamp | The squash's own re-stamp (step 3) only covers sources the epoch gate lets reach it (step 2); a later change on B's own branch fails that gate |
127
+ | B carries its own older doc edit and keeps it through the merge | B's own doc-edit commit (the merge is skipped: its doc content matches B's pre-merge copy) | STALE when the edit predates the squash; fresh when it postdates the squash and changed the stamp value (the re-stamp exception); STALE when it postdates the squash but left the stamp alone | Step 3 only asks whether B's edit changed the value against its OWN first parent, never what the edit verified; an edit that lands after the squash and differs from its own prior value passes the gate and reads re-stamped regardless |
128
+
129
+ **Recipe:** after merging a trunk that carries a squash into any branch whose bundle declares the sources that squash re-dated, re-verify each such doc against its current `sources` and bump its `timestamp` in one dedicated commit, whatever `sources-fresh` currently reports for it -- the same recipe as the Authoring guidance below, just triggered by the merge. Seen in practice on a long-lived second branch after a squash-merged re-stamp landed on the trunk; see the CHANGELOG for the concrete case.
130
+
110
131
  **Authoring guidance:** when you re-verify a doc against its sources, bump its frontmatter `timestamp` (and add a line to the bundle's `log.md`) so `sources-fresh` reflects that the doc is current again.
111
132
 
133
+ ### Uncommitted edits (`--dirty-as-now`)
134
+
135
+ `sources-fresh` and `sources-fresh-future` normally judge every path by its last GIT COMMIT time, so a source or doc you have edited but not yet committed still reads by whatever it looked like at its last commit -- often still "fresh" relative to an already-stale doc `timestamp`. Once you commit, that same path gets a brand-new commit time, and CI's freshness guard (typically run in strict mode) can fail on a doc your local, pre-commit `check` run reported as clean. `--dirty-as-now` closes that gap by modeling every uncommitted change -- modified, staged, or untracked, i.e. anything `git status --porcelain --untracked-files=all` reports -- as though it landed in ONE VIRTUAL COMMIT made right now: a dirty `sources` path's epoch becomes now, and a dirty DOC's OWN epoch becomes now too, both read from the exact same shared instant so two dirty paths in one `check` run never disagree about what "now" was. Both rules read a dirty path's epoch this same way -- there is exactly one place in the code that applies the substitution, not a separate patch per rule -- so a pre-commit run reports the same verdict CI will report once the commit lands, for either rule. It has no effect on a path with no uncommitted change (judged exactly as before), and it is entirely opt-in: omit it and both rules are byte-for-byte unchanged. One consequence worth calling out: an untracked source's ordinary `untracked by git, staleness unknown` notice (see the table above) becomes a STALE warning under this flag instead, since an untracked path is itself an uncommitted change; symmetrically, an untracked DOC -- which `sources-fresh-future` otherwise leaves unassessed entirely (see that rule's table above) -- gets a real `sources-fresh-future` verdict too, since its virtual epoch is now a real "now" to compare its `timestamp` against. Both hold for a file inside a BRAND-NEW untracked directory as well, which is why the status read passes `--untracked-files=all`: git's default untracked mode reports a new directory as one single `? newdir/` record and never names the files in it, so a source or doc inside one used to be invisible to this flag (reported merely `untracked by git`, exit 0) right up until the commit that made it STALE in CI. The cost of `--untracked-files=all` is a longer status output in a work tree carrying many untracked, non-ignored files; if it ever exceeds the internal 16 MiB git-output cap, the run reports the not-applied notice below rather than pretending the tree is clean.
136
+
137
+ 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: dirty paths are reported relative to the repository's top level and are rebased onto the passed root (via `git rev-parse --show-prefix`) before matching, so dirty-path detection works there instead of silently matching nothing; the doc re-stamp rescue does not yet read the doc blob relative to such a root (it reads `HEAD:<path>` relative to the top level), so under a subdirectory root a locally re-stamped doc can still read as STALE and a dirty-but-not-re-stamped doc as clean; prefer the repository top level as `--repo-root` until that is fixed. 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
+
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.
140
+
141
+ **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
+
143
+ ```bash
144
+ okf-kit check path/to/bundle --dirty-as-now --strict
145
+ ```
146
+
147
+ If it reports a doc STALE, re-verify that doc against its current `sources` and bump its `timestamp` in the same commit as the source edit (or its own dedicated commit), THEN commit -- exactly the measure-after-commit discipline described above, just checked before the commit exists rather than after CI runs.
148
+
149
+ **What this actually produces for the recipe above, reproduced through the built CLI (source committed, doc committed with a matching `timestamp`, then):**
150
+
151
+ | Working-tree state | `check --dirty-as-now --strict` |
152
+ |---|---|
153
+ | Source edited, doc re-stamped on disk to now (a few seconds to a minute after writing the stamp) | exit 0, clean -- neither `sources-fresh` nor `sources-fresh-future` fires |
154
+ | Source edited, doc left alone (not re-stamped) | exit 1, `sources-fresh` STALE |
155
+ | Source edit and doc re-stamp committed TOGETHER, flag OFF | exit 0, clean (the committed-history co-commit rescue, unaffected by this flag) |
156
+ | 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) |
158
+ | 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
+
160
+ 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.
161
+
162
+ What "matches CI" actually means here: `--dirty-as-now` makes a local run compute the same `sources-fresh`/`sources-fresh-future` VERDICT (fresh, STALE, or not-assessable) that a post-commit `check` run would compute for the same content -- it says nothing about whether a given CI setup turns that verdict into a failed build, and nothing about warning classes outside these two rules. Whether it does depends entirely on how that CI wires up `okf-kit check`: this package's own CI runs it two different ways for the same bundle -- `.github/workflows/okf-staleness.yml` calls `check` warn-only (findings surface in the job summary and as annotations, but the job never fails on them), while `.github/workflows/ci.yml`'s freshness guard step runs `check --require-anchors` and then filters the JSON report through `jq` for `sources-fresh`/`sources-fresh-future` findings, only failing the build on THOSE. `--strict` is broader than either: it fails on every warning-severity finding from EVERY rule (including ones this flag says nothing about, like `citations-resolve`), so a locally-strict, CI-clean bundle is not a contradiction -- it means the CI in question does not block on every warning class `--strict` does. Read the target repo's actual CI wiring before treating `--dirty-as-now --strict` as equivalent to "will this pass CI".
163
+
164
+ `--dirty-as-now` ships in the same `okf-kit` release as everything else in this CHANGELOG entry; a CI step that installs a PINNED `okf-kit` version (as both workflows above do) only gains the flag once that pin is bumped to a release that includes it.
165
+
166
+ **Known limitations, stated rather than hidden.** Ignored files (`.gitignore`) are deliberately NOT treated as dirty here (`git status` is run without `--ignored`): an ignored source keeps its ordinary `untracked by git, staleness unknown` notice rather than becoming newly dirty under this flag. A source living inside a dirty SUBMODULE is likewise not detected as dirty: `git status` reports a submodule with uncommitted changes as one single record for the submodule's own path, not per file inside it, and this flag's path-matching does not currently descend into that report to find the individual dirty files a `sources` entry might name.
167
+
112
168
  ### Future-dated timestamps (`sources-fresh-future`)
113
169
 
114
170
  `sources-fresh` catches a `timestamp` that is too OLD relative to a source's last commit. `sources-fresh-future` catches the opposite mistake: a `timestamp` that is too NEW relative to the doc file's OWN last commit -- in practice, almost always a local wall-clock time hand-written with a trailing `Z` (or another UTC marker) it does not actually have, rather than a genuine future date. It never looks at `sources` commit times at all, only at the doc file's own git history, so it has nothing to say about whether any source is stale; the two rules are complementary, not overlapping, and are assessed over the same population of docs (a validly-shaped `sources` list and a repo root available, exactly like `sources-fresh` above).
@@ -118,7 +174,7 @@ Known limitation: the doc-commit comparison suppresses staleness for every sourc
118
174
  | The doc's `timestamp` is later than the doc file's own last commit by more than the skew allowance | warning | `FUTURE-DATED: doc timestamp <iso> is after the doc's own last commit <iso> (skew allowance <n>s)` |
119
175
  | The doc's `timestamp` is at or within the skew allowance of the doc file's own last commit | (nothing) | fresh: an ordinary write-then-commit gap, not a mistake |
120
176
  | The doc's `timestamp` string has no `Z`/UTC designator or numeric offset (e.g. `2026-01-01T00:00:00`, no offset) | notice | future-dated check skipped: timestamp has no UTC designator (`Z`) or numeric offset, can't be compared reliably across timezones |
121
- | The doc has no git history yet (uncommitted) | (nothing) | unknown, not flagged: there is no real commit time to compare against |
177
+ | The doc has no git history yet (uncommitted) | (nothing) | unknown, not flagged: there is no real commit time to compare against -- UNLESS `--dirty-as-now` is passed, in which case a dirty (including untracked) doc gets a real verdict against the shared virtual-commit "now" instant instead (see "Uncommitted edits" below) |
122
178
  | The doc's `timestamp` is missing or not a parseable date | (nothing) | left to `sources-fresh`'s own notice, not duplicated here |
123
179
  | No repo root available (see auto-detection above) | (nothing) | left to `sources-fresh`'s single bundle-level notice, not duplicated here |
124
180
 
@@ -180,6 +236,8 @@ Anchors are checked only once the base checks above (blank-start-line, closing-b
180
236
 
181
237
  **Continuation citations.** Once a sentence states a full `path:N` citation, prose commonly repeats just the line (or range) for a later reference in the same sentence: `` `:N` ``/`` `:N-M` `` (bare colon-prefixed), `` -`M` ``/`` –`M` `` (hyphen- or en-dash-led, the tail of a split range like `` `path:N`-`M` ``), or `` (`N`) `` (parenthesized). Each resolves against the nearest preceding citation in the same doc that resolved to a real file; a continuation right after an unresolved, ambiguous, or out-of-scope citation is silently skipped, not misattributed to an earlier, unrelated file. A heading-section citation (see above) carries no line number and is never a continuation's target: it never sets or clears which citation a later continuation resolves against.
182
238
 
239
+ **Anchored path-less continuation form: not recognised (bundle-local).** The `orchestrator-workflow` package's own dogfood bundle writes a backtick-wrapped, path-less continuation with a content anchor, e.g. `` `:913-923#"..."` ``, distinct from the two forms above. `CONT_COLON_RE` needs its closing backtick immediately after the digit range, so a trailing `#"anchor"` before the backtick never matches it; `SHORT_FORM_COLON_RE` excludes any match immediately preceded by a backtick and otherwise requires a serial-connective prefix, neither of which this form carries. So this rule sees the form as nothing at all, not merely as unresolved. Recognising it (an opt-in rule, or folding it into this one) would move the cost to okf-kit's maintainers: the rule itself, an allowlist/anchor-geometry contract as public API, and a fleet-wide pin bump on every fix. Declaring it bundle-local instead leaves the cost where it already sits: only the `orchestrator-workflow` package's own `test/docs-consistency.test.ts` guard checks the form, and every other fleet bundle that might someday write it stays unguarded until it grows the same check by hand. Port trigger, restated from the orchestrator-workflow CHANGELOG's "Citation-sibling-drift guard, okf-kit-porting decision" entry: a second fleet bundle observed carrying real sibling-citation drift in a review pass (not merely plausible in the abstract) reopens the port decision. A fleet count at the time of this decision found the live form only in that one bundle (`docs/okf/model-preselection.md`, 4 occurrences); other apparent hits were historical prose in a `log.md` narrating a re-point, not live citations.
240
+
183
241
  **Short-form citations.** Distinct from a continuation above: a *bare* (no backtick, no file name at all) colon-range `:N-M`, e.g. `:580-588` in running prose. A short-form citation binds to **the last full `path:N-M` citation named earlier in the same paragraph** -- not the nearest preceding citation anywhere in the doc (that is what a continuation does); a paragraph boundary is a blank (empty or whitespace-only) line. A short-form citation with no full citation earlier in its own paragraph is reported `short-form-unbound`, not silently skipped. Only a range is recognised, never a bare single number (`:5`): a bare number is too easily an unrelated enumeration marker (e.g. a numbered list item) to detect mechanically without a large false-positive cost. A resolved short-form citation gets every check a full citation gets, plus the test-file/Markdown block-boundary check above (`test-range-*` / `markdown-range-boundary-bracket-or-fence`).
184
242
 
185
243
  **Serial-connective gate, and why the paren form is not collected at all.** Three earlier rounds each tried to separate a real short-form citation from ordinary prose that merely contains an N-M-shaped number pair ("the window (2026-2027)", "follow steps (2-4)", "three engineers (1-3)") by deciding from the range's *values*: an inverted-pair check, a span cap plus a year/well-known-port plausibility gate, then a containment-or-adjacency check against the paragraph's last full citation. All three were eventually defeated by the same class of false positive, because every real paren-form citation this rule was ever built against has the identical shape `<English word> (N-M)` as ordinary prose -- there is no lexical signal that tells them apart. The bare parenthesized form `(N-M)` is therefore not collected as a short-form citation candidate at all; measured against this repo's own dogfood bundle, dropping it changed nothing (39 findings / 17 warnings / 22 notices, identical with and without it).
@@ -262,7 +320,7 @@ This is advisory: don't fail the build on warnings unless you pass `--strict`. U
262
320
  with:
263
321
  fetch-depth: 0
264
322
  - name: OKF bundle check
265
- run: npx okf-kit@0.10.0 check path/to/bundle
323
+ run: npx okf-kit@0.11.0 check path/to/bundle
266
324
  ```
267
325
 
268
326
  Pin the version: an unpinned `npx okf-kit` picks up new rules on their release day, which turns an unrelated PR red.
package/dist/cli.d.ts CHANGED
@@ -40,6 +40,18 @@ export interface CheckOptions {
40
40
  * `ctx.freshnessFutureSkewSeconds`.
41
41
  */
42
42
  futureSkewMinutes?: number;
43
+ /**
44
+ * Opt-in for `sources-fresh` AND `sources-fresh-future`: model every
45
+ * uncommitted change (modified, staged, or untracked) as though it
46
+ * landed in ONE virtual commit made right now, instead of at its last
47
+ * real commit. Both a dirty `sources` path and a dirty DOC read their
48
+ * commit time from that same shared instant, so a pre-commit run reports
49
+ * the verdict CI will report once the commit lands -- for either rule.
50
+ * Stored on `ctx.dirtyAsNow`; see its jsdoc in `src/types.ts` (the
51
+ * canonical description of the model) and the README's "Uncommitted
52
+ * edits (`--dirty-as-now`)" section.
53
+ */
54
+ dirtyAsNow?: boolean;
43
55
  /** Test-only override for git access; production code shells out to the real `git` binary. */
44
56
  runGit?: RunGit;
45
57
  }
package/dist/cli.js CHANGED
@@ -36,6 +36,9 @@ export function runCheck(bundleDir, options = {}) {
36
36
  if (options.futureSkewMinutes !== undefined) {
37
37
  ctx.freshnessFutureSkewSeconds = Math.round(options.futureSkewMinutes * 60);
38
38
  }
39
+ if (options.dirtyAsNow) {
40
+ ctx.dirtyAsNow = true;
41
+ }
39
42
  const findings = allRules.flatMap((rule) => rule.run(ctx));
40
43
  const summary = summarize(findings);
41
44
  const exitCode = summary.errors > 0 || (Boolean(options.strict) && summary.warnings > 0)
@@ -72,6 +75,9 @@ program
72
75
  "the remedy to lift it into a backtick citation or a symbol name (ignored unless --prose-line-references is also passed)")
73
76
  .option("--future-skew-minutes <n>", "sources-fresh-future: clock-skew allowance in minutes before a doc `timestamp` later than " +
74
77
  "the doc's own last commit is flagged as future-dated (default 10)")
78
+ .option("--dirty-as-now", "sources-fresh + sources-fresh-future: model every uncommitted change (modified, staged, or " +
79
+ "untracked) -- a `sources` path and the doc itself alike -- as one virtual commit made right " +
80
+ "now, so a pre-commit run matches what CI reports after the commit lands (opt-in, see README)")
75
81
  .exitOverride()
76
82
  .action((bundleDir, opts) => {
77
83
  try {
@@ -95,6 +101,7 @@ program
95
101
  proseLineReferences: opts.proseLineReferences,
96
102
  proseLineReferencesStrict: opts.proseLineReferencesStrict,
97
103
  futureSkewMinutes,
104
+ dirtyAsNow: opts.dirtyAsNow,
98
105
  });
99
106
  const output = opts.json
100
107
  ? renderJson(result.bundleDir, result.findings)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -29,9 +29,16 @@ export declare const sourcesFreshRule: Rule;
29
29
  * rather than duplicating it) and no valid `timestamp` (`sources-fresh`
30
30
  * already reports that per-doc notice, so this rule silently skips such a
31
31
  * doc rather than reporting it twice). An uncommitted doc (no own commit
32
- * yet) is likewise "unknown, not flagged": there is no real commit time to
33
- * compare the timestamp against, and flagging every hand-authored,
34
- * not-yet-committed doc as "future-dated" would be a false positive on
35
- * every fresh draft.
32
+ * yet) is likewise "unknown, not flagged" by DEFAULT: there is no real
33
+ * commit time to compare the timestamp against, and flagging every
34
+ * hand-authored, not-yet-committed doc as "future-dated" would be a false
35
+ * positive on every fresh draft. Under `--dirty-as-now` (`ctx.dirtyAsNow`),
36
+ * this changes: `getDocCommitEpochShared` below substitutes the shared
37
+ * virtual-commit "now" instant for ANY dirty doc's epoch (untracked
38
+ * included -- see `commitEpochWithDirtyAsNow`), so a dirty doc DOES get a
39
+ * real comparison here, exactly the working-tree parity `--dirty-as-now`
40
+ * exists for: a `timestamp` re-stamped to "now" reads fresh (within the
41
+ * skew allowance), while one still carrying an implausible future value
42
+ * gets caught before the commit that would otherwise make it so in CI.
36
43
  */
37
44
  export declare const sourcesFreshFutureRule: Rule;
@@ -39,17 +39,39 @@ export const sourcesFreshRule = {
39
39
  }
40
40
  const repoRoot = ctx.repoRoot;
41
41
  const git = ctx.runGit ?? defaultRunGit;
42
+ // `--dirty-as-now` asked for, but git could not tell us what is dirty
43
+ // (a `status` past RunGit's output cap, a `rev-parse` failure, git
44
+ // missing): every path below then falls through to committed history,
45
+ // which is the RIGHT fallback but the WRONG silence -- "the flag found
46
+ // nothing dirty" and "the flag never ran" produce the identical empty
47
+ // finding list. Say so once, bundle-level, in the same style as the
48
+ // "not inside a git work tree" notice above (and, like that one,
49
+ // emitted only here: `sources-fresh-future` shares the same degraded
50
+ // state and relies on this single notice instead of duplicating it).
51
+ if (ctx.dirtyAsNow && getDirtyStateShared(ctx, git, repoRoot) === null) {
52
+ findings.push({
53
+ ruleId: RULE_ID,
54
+ severity: "notice",
55
+ file: "",
56
+ message: "`--dirty-as-now` not applied: git status could not be read, judging by committed history only",
57
+ });
58
+ }
42
59
  // One git call per unique source path across all docs, even though a
43
60
  // STALE/untracked finding is reported per (doc, path) below.
44
61
  const commitEpochCache = new Map();
45
- const commitEpochFor = (source) => {
62
+ // `--dirty-as-now`: every dirty path's "commit epoch" is the SAME
63
+ // virtual-commit instant, shared (by `ctx` identity) with
64
+ // `sources-fresh-future`'s doc-epoch lookup below -- see
65
+ // `commitEpochWithDirtyAsNow`'s doc comment for why this lives in one
66
+ // place instead of being reimplemented per rule.
67
+ const commitEpochFor = (source) => commitEpochWithDirtyAsNow(ctx, git, repoRoot, source, () => {
46
68
  const cached = commitEpochCache.get(source);
47
69
  if (cached !== undefined)
48
70
  return cached;
49
71
  const epoch = getLastCommitEpoch(git, repoRoot, source);
50
72
  commitEpochCache.set(source, epoch);
51
73
  return epoch;
52
- };
74
+ });
53
75
  for (const { doc, sources } of docsWithSources) {
54
76
  const timestampEpoch = getTimestampEpoch(doc.frontmatter.parsed);
55
77
  if (timestampEpoch === undefined) {
@@ -72,9 +94,11 @@ export const sourcesFreshRule = {
72
94
  // rules don't each spawn their own `git log` for the same doc in one
73
95
  // `check` run.
74
96
  //
75
- // GIT PROCESS BUDGET, per doc, per `check` run: 1 (the shared
76
- // `git log -1 --format=%ct` epoch lookup, always) + at most 4 more on
77
- // the re-stamp path (`git log -1 --format=%H%n%P`, then `git diff-tree`,
97
+ // GIT PROCESS BUDGET, per doc, per `check` run, with `--dirty-as-now`
98
+ // OFF (this figure is measured with the flag off; see below for its
99
+ // extra cost with the flag on): 1 (the shared `git log -1
100
+ // --format=%ct` epoch lookup, always) + at most 4 more on the
101
+ // re-stamp path (`git log -1 --format=%H%n%P`, then `git diff-tree`,
78
102
  // then two `git show`s), i.e. AT MOST 5 -- regardless of how many
79
103
  // sources the doc declares, since both lookups are memoized per doc.
80
104
  // A doc created by its last commit (or by the repo's root commit)
@@ -85,10 +109,40 @@ export const sourcesFreshRule = {
85
109
  // --is-shallow-repository` for the ENTIRE run, not per doc (see
86
110
  // isShallowRepoShared below) -- only spent at all when some doc's
87
111
  // re-stamp lookup actually reaches a root commit.
112
+ //
113
+ // With `--dirty-as-now` ON, add 2 for the ENTIRE run (not per doc,
114
+ // not per source -- see readDirtyState): 1 `git status --porcelain`
115
+ // and 1 `git rev-parse --show-prefix`. Plus, PER DOC, at most 1 `git
116
+ // ls-tree HEAD -- <doc>` (and, only when the doc already existed at
117
+ // HEAD, one more `git show HEAD:<doc>`), spent only when that doc is
118
+ // itself dirty AND some source of its reads stale (see restampFor
119
+ // below).
88
120
  const repoRelDocPath = toRepoRelDocPath(repoRoot, ctx.bundleDir, doc);
89
121
  const docCommitEpochFor = () => getDocCommitEpochShared(ctx, git, repoRoot, repoRelDocPath);
122
+ // The single decision point for "did the doc's last commit -- real or
123
+ // virtual -- actually re-stamp it": a dirty doc (under
124
+ // `--dirty-as-now`) is judged by its WORKING-TREE value against the
125
+ // value committed at HEAD (`dirtyDocRestampVerdict`, the virtual
126
+ // commit's implicit "first parent" is simply HEAD); a doc that is not
127
+ // itself dirty is judged the ordinary way, against its real last
128
+ // commit's first parent (`restampedByOwnLastCommit`). This replaces
129
+ // the round-2 approach of a SEPARATE rescue branch checked before the
130
+ // co-commit path: once `docCommitEpochFor` above already reports the
131
+ // dirty doc's epoch as "now" (see `commitEpochWithDirtyAsNow`), the
132
+ // ordinary `docCommitEpoch >= commitEpoch` gate below fires for a
133
+ // dirty doc exactly the way it fires for a real co-commit, so only
134
+ // ONE verdict function needs to be picked here, not two independent
135
+ // mechanisms answering overlapping questions.
90
136
  let restampMemo;
91
- const restampFor = () => (restampMemo ??= restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, () => isShallowRepoShared(ctx, git, repoRoot)));
137
+ const restampFor = () => {
138
+ if (restampMemo !== undefined)
139
+ return restampMemo;
140
+ restampMemo =
141
+ ctx.dirtyAsNow && isDirtyForShared(ctx, git, repoRoot, repoRelDocPath)
142
+ ? dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, getTimestampIdentity(doc.frontmatter.parsed))
143
+ : restampedByOwnLastCommit(git, repoRoot, repoRelDocPath, () => isShallowRepoShared(ctx, git, repoRoot));
144
+ return restampMemo;
145
+ };
92
146
  // At most one "not assessable" notice per doc, however many of its
93
147
  // sources hit the unanswerable re-stamp question.
94
148
  let notAssessableReported = false;
@@ -108,14 +162,16 @@ export const sourcesFreshRule = {
108
162
  continue;
109
163
  }
110
164
  let isStale = commitEpoch > timestampEpoch;
111
- // Doc committed at/after the source, AND that commit actually
112
- // re-stamped it: not stale (see comment above). A doc without git
113
- // history (null epoch, e.g. uncommitted) keeps the frontmatter-only
114
- // comparison. When git cannot answer the re-stamp question at all,
115
- // the doc is reported as not assessable rather than being guessed
116
- // either way: calling it STALE would turn a git hiccup into a red
117
- // build, and calling it fresh would be a silent pass.
118
165
  if (isStale) {
166
+ // Doc committed (or, under `--dirty-as-now`, virtually committed
167
+ // right now) at/after the source, AND that commit actually
168
+ // re-stamped it: not stale (see comment above). A doc without git
169
+ // history (null epoch, e.g. uncommitted and clean, no dirty
170
+ // status at all) keeps the frontmatter-only comparison. When git
171
+ // cannot answer the re-stamp question at all, the doc is reported
172
+ // as not assessable rather than being guessed either way: calling
173
+ // it STALE would turn a git hiccup into a red build, and calling
174
+ // it fresh would be a silent pass.
119
175
  const docCommitEpoch = docCommitEpochFor();
120
176
  if (docCommitEpoch !== null && docCommitEpoch >= commitEpoch) {
121
177
  const verdict = restampFor();
@@ -173,10 +229,17 @@ export const sourcesFreshRule = {
173
229
  * rather than duplicating it) and no valid `timestamp` (`sources-fresh`
174
230
  * already reports that per-doc notice, so this rule silently skips such a
175
231
  * doc rather than reporting it twice). An uncommitted doc (no own commit
176
- * yet) is likewise "unknown, not flagged": there is no real commit time to
177
- * compare the timestamp against, and flagging every hand-authored,
178
- * not-yet-committed doc as "future-dated" would be a false positive on
179
- * every fresh draft.
232
+ * yet) is likewise "unknown, not flagged" by DEFAULT: there is no real
233
+ * commit time to compare the timestamp against, and flagging every
234
+ * hand-authored, not-yet-committed doc as "future-dated" would be a false
235
+ * positive on every fresh draft. Under `--dirty-as-now` (`ctx.dirtyAsNow`),
236
+ * this changes: `getDocCommitEpochShared` below substitutes the shared
237
+ * virtual-commit "now" instant for ANY dirty doc's epoch (untracked
238
+ * included -- see `commitEpochWithDirtyAsNow`), so a dirty doc DOES get a
239
+ * real comparison here, exactly the working-tree parity `--dirty-as-now`
240
+ * exists for: a `timestamp` re-stamped to "now" reads fresh (within the
241
+ * skew allowance), while one still carrying an implausible future value
242
+ * gets caught before the commit that would otherwise make it so in CI.
180
243
  */
181
244
  export const sourcesFreshFutureRule = {
182
245
  id: FUTURE_RULE_ID,
@@ -267,33 +330,367 @@ function getLastCommitEpoch(git, repoRoot, source) {
267
330
  const epoch = Number.parseInt(out, 10);
268
331
  return Number.isNaN(epoch) ? null : epoch;
269
332
  }
333
+ /**
334
+ * The full SET of repo-root-relative paths `git status --porcelain`
335
+ * reports as dirty (modified, staged, or untracked) across the WHOLE work
336
+ * tree, read via a SINGLE `status` process for the entire `check` run --
337
+ * not one process per unique `sources` path (the original, pre-review
338
+ * implementation), and not one per doc for the local-restamp rescue
339
+ * below. Used only behind `--dirty-as-now` (`ctx.dirtyAsNow`): a dirty
340
+ * path has no "last commit" yet that reflects its current content, so
341
+ * `sources-fresh` substitutes the current time for it instead of falling
342
+ * through to `getLastCommitEpoch`'s answer (the LAST commit's time, which
343
+ * for a locally-edited-but-uncommitted file is necessarily stale).
344
+ *
345
+ * `--no-optional-locks` skips git's opportunistic index refresh (which can
346
+ * otherwise rewrite the on-disk index file as a side effect of a plain
347
+ * `status`) -- unwanted here since this runs as a read-only check, often
348
+ * from a hook or CI step that should not perturb the index. Ignored files
349
+ * are deliberately NOT included (no `--ignored`): an ignored source keeps
350
+ * today's "untracked by git, staleness unknown" notice instead of being
351
+ * newly reported dirty by this option.
352
+ *
353
+ * `--untracked-files=all` (`-uall`) is NOT optional decoration. Under
354
+ * git's default untracked mode (`normal`), a brand-new directory is
355
+ * collapsed into ONE record for the directory itself (`? newdir/`) and the
356
+ * files inside it are never listed. The matcher below matches a queried
357
+ * path that IS a reported entry or is an ANCESTOR of one, so under that
358
+ * default a `sources` entry (or a doc) INSIDE a new untracked directory
359
+ * matched nothing at all and silently kept its committed-history verdict:
360
+ * `check --dirty-as-now` reported a brand-new source as merely `untracked
361
+ * by git, staleness unknown` (exit 0) while a plain `check` after
362
+ * committing it reported STALE (exit 1) -- the precise local/CI divergence
363
+ * this flag exists to remove. `-uall` makes git enumerate every untracked
364
+ * FILE as its own record, so the ordinary exact/descendant matching sees
365
+ * them. The cost is output size: `-uall` prints one record per untracked
366
+ * file rather than per untracked directory, which in a work tree carrying
367
+ * a large untracked build or dependency tree (anything not covered by
368
+ * `.gitignore` -- ignored paths are still excluded, see above) can run to
369
+ * many thousands of records. That output travels through RunGit's 16 MiB
370
+ * cap (`MAX_GIT_OUTPUT_BYTES` in src/git.ts), and a status that exceeds it
371
+ * resolves to null like any other git failure -- reported as the
372
+ * bundle-level "not applied" notice the rule emits, never as a silent
373
+ * "nothing is dirty".
374
+ *
375
+ * `git rev-parse --show-prefix` is the SECOND (and last) git process this
376
+ * costs per run. `git status` always reports paths relative to the
377
+ * repository's TOP LEVEL, while a `sources` entry is relative to
378
+ * `ctx.repoRoot` -- the same directory only when `--repo-root` names the
379
+ * top level. Pointed at a SUBDIRECTORY (`--repo-root packages/foo`), every
380
+ * status path carries a `packages/foo/` prefix the queried path does not,
381
+ * so nothing ever matched and the flag silently did nothing. Reading the
382
+ * prefix once and prepending it at match time makes that case work instead
383
+ * of quietly no-opping.
384
+ *
385
+ * Uses `--porcelain=v2 -z`, not the more familiar `--porcelain` (v1) line
386
+ * format, for one reason that is NOT about renames or quoting (`-z` alone
387
+ * would fix both): RunGit (src/git.ts) `.trim()`s every git invocation's
388
+ * output, and a v1 line for an unstaged-only change starts with a LITERAL
389
+ * SPACE (` M path`, index clean, worktree modified) -- an entirely common
390
+ * case. When that happens to be the FIRST line of the whole status output,
391
+ * `.trim()` strips that leading space as ordinary boundary whitespace,
392
+ * silently shifting every fixed-offset field in that one line and
393
+ * corrupting its path (verified against real git output: a lone `M
394
+ * source.ts` line, meant to be ` M source.ts`, parses to the wrong path
395
+ * with a fixed `line.slice(3)` cut). Every v2 record instead starts with a
396
+ * digit or letter (`1`, `2`, `u`, `?`) that is never whitespace, so the
397
+ * SAME `.trim()` can never eat a leading field byte. NUL (`-z`) delimits
398
+ * every record and untracked/rename path field can safely contain a space,
399
+ * tab, or non-ASCII byte, mirroring previousPathIn's `-z` rationale
400
+ * elsewhere in this file. Record shapes actually seen here (verified
401
+ * against real git output; XY, sub, mode and hash fields are read
402
+ * positionally, never re-split by content, since a path can itself
403
+ * legitimately contain a space): `? path` (untracked); `1 XY sub mH mI mW
404
+ * hH hI path` (ordinary; 8 fixed fields before path); `2 XY sub mH mI mW
405
+ * hH hI score path\0origPath` (rename/copy; 9 fixed fields before path,
406
+ * origPath is the FOLLOWING NUL-delimited token verbatim); `u XY sub m1 m2
407
+ * m3 mW h1 h2 h3 path` (unmerged; 10 fixed fields before path) -- both
408
+ * sides of a rename count as dirty. `!` (ignored) records are never
409
+ * produced since `--ignored` is not passed.
410
+ *
411
+ * A failed git call (either one: `null`) makes the WHOLE state null, which
412
+ * every path then falls through on -- it keeps its ordinary commit-epoch
413
+ * verdict rather than this function inventing a dirty one. Unlike every
414
+ * other git failure in this file that is silent, this one is surfaced: the
415
+ * rule turns a null state into a single bundle-level "`--dirty-as-now` not
416
+ * applied" notice, because "the flag silently did nothing" and "nothing
417
+ * was dirty" are indistinguishable to a reader of an empty finding list.
418
+ */
419
+ function readDirtyState(git, repoRoot) {
420
+ // `""` (this IS the top level) is a valid answer, so only an outright
421
+ // failure (`null`) disables the flag here.
422
+ const rawPrefix = git(["rev-parse", "--show-prefix"], repoRoot);
423
+ if (rawPrefix === null)
424
+ return null;
425
+ const prefix = rawPrefix === "" ? "" : `${normalizeRelPath(rawPrefix)}/`;
426
+ const out = git([
427
+ "--no-optional-locks",
428
+ "status",
429
+ "--porcelain=v2",
430
+ "-z",
431
+ "--untracked-files=all",
432
+ ], repoRoot);
433
+ if (out === null)
434
+ return null;
435
+ const paths = new Set();
436
+ // `-z` NUL-terminates every record, including the last -- RunGit's
437
+ // `.trim()` does not strip NUL, so splitting always leaves one empty
438
+ // trailing token.
439
+ const tokens = out.split("\0").filter((t) => t !== "");
440
+ let i = 0;
441
+ while (i < tokens.length) {
442
+ const token = tokens[i];
443
+ const kind = token[0];
444
+ if (kind === "?") {
445
+ paths.add(normalizeRelPath(token.slice(2)));
446
+ i += 1;
447
+ }
448
+ else if (kind === "1") {
449
+ paths.add(normalizeRelPath(token.split(" ").slice(8).join(" ")));
450
+ i += 1;
451
+ }
452
+ else if (kind === "2") {
453
+ paths.add(normalizeRelPath(token.split(" ").slice(9).join(" ")));
454
+ const origPath = tokens[i + 1];
455
+ if (origPath !== undefined)
456
+ paths.add(normalizeRelPath(origPath));
457
+ i += 2;
458
+ }
459
+ else if (kind === "u") {
460
+ paths.add(normalizeRelPath(token.split(" ").slice(10).join(" ")));
461
+ i += 1;
462
+ }
463
+ else {
464
+ // An unrecognized record kind (should not occur without --ignored,
465
+ // which is never passed): skip rather than mis-parse it as a path.
466
+ i += 1;
467
+ }
468
+ }
469
+ return { prefix, paths };
470
+ }
471
+ /**
472
+ * Canonicalizes a repo-relative path spelling before it is used as a dirty
473
+ * lookup key or matched against one: strips a leading `./`, strips a
474
+ * trailing `/`, converts backslashes to forward slashes, and collapses `.`
475
+ * / `..` segments and duplicate slashes via `path.posix.normalize`. `git
476
+ * status` itself always reports canonical forward-slash paths with neither
477
+ * a leading `./` nor a trailing `/`, but a frontmatter-authored `sources`
478
+ * entry (or a doc's own bundle-relative path, joined with `path.join`) is
479
+ * under no such obligation -- `./srcdir` and `srcdir/` name the exact same
480
+ * directory `srcdir` does, and MUST match the same dirty entries it does.
481
+ * Applied on BOTH sides of every dirty-path comparison in this file (here,
482
+ * at insertion into the dirty-paths Set, and in `isDirtyForShared` on the
483
+ * queried path already joined with the repo prefix), so any spelling of
484
+ * the same path always matches.
485
+ *
486
+ * `.`, `./` and the empty string all normalize to `.`, the root directory
487
+ * itself. That is a legal `sources` spelling but never a `git status`
488
+ * entry, so `isDirtyForShared` answers it by containment instead of by
489
+ * lookup -- see the `normalized === "."` branch there.
490
+ *
491
+ * A round-1-then-round-2 regression this closes: the per-run status
492
+ * refactor introduced exact-path (`paths.has`) and prefix (`startsWith`)
493
+ * matching against the RAW `source` string, so `srcdir/` built a
494
+ * self-defeating double-slash prefix (`srcdir//`) and `./srcdir` never
495
+ * matched a `git status` path at all (which never carries a `./` prefix) --
496
+ * both spellings silently lost dirty detection entirely.
497
+ */
498
+ function normalizeRelPath(relPath) {
499
+ let p = relPath.replace(/\\/g, "/");
500
+ while (p.startsWith("./"))
501
+ p = p.slice(2);
502
+ p = path.posix.normalize(p);
503
+ while (p.length > 1 && p.endsWith("/"))
504
+ p = p.slice(0, -1);
505
+ return p;
506
+ }
507
+ /**
508
+ * Per-run cache (keyed by `BundleContext`, same pattern as
509
+ * `docCommitEpochCache` below) of `readDirtyState`'s answer, so the WHOLE
510
+ * `check` run -- both rules, every doc, every source -- spends at most one
511
+ * `git status` (plus one `git rev-parse --show-prefix`) process, not one
512
+ * per rule. A cached `null` (the git read failed) is a real cached answer,
513
+ * hence the `.has` check rather than a truthiness test: a failed read is
514
+ * not retried per source.
515
+ */
516
+ const dirtyStateCache = new WeakMap();
517
+ function getDirtyStateShared(ctx, git, repoRoot) {
518
+ if (dirtyStateCache.has(ctx))
519
+ return dirtyStateCache.get(ctx) ?? null;
520
+ const state = readDirtyState(git, repoRoot);
521
+ dirtyStateCache.set(ctx, state);
522
+ return state;
523
+ }
524
+ /**
525
+ * Whether `relPath` (a `sources` entry OR a doc's own path relative to
526
+ * `ctx.repoRoot`, in any spelling `normalizeRelPath` accepts) is dirty per
527
+ * `git status`. The queried path is first rebased onto the repository top
528
+ * level with `state.prefix` (a no-op in the ordinary case where
529
+ * `--repo-root` IS the top level), since that is the frame every reported
530
+ * dirty path is expressed in. A dirty FILE then matches by exact
531
+ * (normalized) path; a dirty DIRECTORY source matches if any reported
532
+ * dirty path lives under it (a `/`-terminated prefix, so a sibling
533
+ * directory whose name merely starts with the same characters -- `srcdir`
534
+ * vs `srcdirX/x.ts` -- never falsely matches).
535
+ *
536
+ * `.` (or `./`, or any spelling that normalizes to `.`) names the root
537
+ * directory itself, which `git status` never reports as an entry and which
538
+ * no `"./"`-prefix test can match either -- so it is matched explicitly as
539
+ * "any dirty path at all lives under this root", the same containment
540
+ * question the directory case asks, just with an empty prefix. Without
541
+ * that branch a bundle declaring `.` as its source silently lost dirty
542
+ * detection entirely.
543
+ *
544
+ * A failed state read (`null`) is treated as "nothing is dirty": every
545
+ * path falls through to its ordinary (real) commit-epoch path rather than
546
+ * this function inventing a dirty verdict either way. The rule reports
547
+ * that case once, bundle-level, rather than letting the flag no-op in
548
+ * silence (see `readDirtyState`).
549
+ */
550
+ function isDirtyForShared(ctx, git, repoRoot, relPath) {
551
+ const state = getDirtyStateShared(ctx, git, repoRoot);
552
+ if (state === null)
553
+ return false;
554
+ const { paths } = state;
555
+ const normalized = normalizeRelPath(`${state.prefix}${relPath}`);
556
+ if (normalized === ".")
557
+ return paths.size > 0;
558
+ if (paths.has(normalized))
559
+ return true;
560
+ const prefix = `${normalized}/`;
561
+ for (const p of paths) {
562
+ if (p.startsWith(prefix))
563
+ return true;
564
+ }
565
+ return false;
566
+ }
567
+ /**
568
+ * Per-run cache (keyed by `BundleContext`) of the SINGLE "now" instant
569
+ * `--dirty-as-now` substitutes for every dirty path's commit epoch, shared
570
+ * across BOTH rules in this file and every doc/source they assess: every
571
+ * dirty path in one `check` invocation is treated as landing in the exact
572
+ * same virtual commit, so two dirty sources (or a dirty source and a dirty
573
+ * doc) never disagree with each other about what "now" was.
574
+ *
575
+ * THE CACHE IS THE GUARANTEE, not the order the callers happen to run in.
576
+ * The rescue gate above is an INEQUALITY on epochs (`docCommitEpoch >=
577
+ * commitEpoch`) whose two sides are BOTH this value when a dirty doc is
578
+ * paired with a dirty source. Reading the clock afresh on each side
579
+ * instead would leave the gate resting on call order: as the rule is
580
+ * written today the source's epoch is read before the doc's
581
+ * (`commitEpochFor`, then `docCommitEpochFor`), so a second-boundary
582
+ * crossing between them could only ever raise the DOC's side and the gate
583
+ * would survive by accident -- but read in the other order (a reordering
584
+ * nothing in the rule forbids) the doc's side would be the older one, and
585
+ * a run that straddled a whole second would flip to a silent,
586
+ * unreproducible STALE. The cache removes the ordering question entirely:
587
+ * every dirty path in one run reads the identical integer, so the gate
588
+ * holds with equality no matter who asks first. Any future caller wanting
589
+ * "now" here must therefore go through this accessor rather than reading
590
+ * the clock again.
591
+ */
592
+ const nowEpochCache = new WeakMap();
593
+ function getNowEpochShared(ctx) {
594
+ let epoch = nowEpochCache.get(ctx);
595
+ if (epoch === undefined) {
596
+ epoch = Math.floor(Date.now() / 1000);
597
+ nowEpochCache.set(ctx, epoch);
598
+ }
599
+ return epoch;
600
+ }
601
+ /**
602
+ * THE single choke point where `--dirty-as-now`'s virtual-commit model is
603
+ * applied: a dirty `relPath` (source or doc, see `isDirtyForShared`) is
604
+ * judged as committed at the shared "now" instant (`getNowEpochShared`)
605
+ * instead of consulting `actualEpoch` at all; anything else -- the flag
606
+ * off, or `relPath` not dirty -- defers to `actualEpoch` (typically a
607
+ * memoized real `git log` lookup), byte-identical to pre-flag behavior.
608
+ * Every commit-epoch read in this file that is meant to honor
609
+ * `--dirty-as-now` MUST go through this function (directly, or via
610
+ * `getDocCommitEpochShared` below, which is itself built on it) rather
611
+ * than re-implementing the dirty check inline, so a source's epoch and a
612
+ * doc's own epoch are always read the same way, by both rules.
613
+ */
614
+ function commitEpochWithDirtyAsNow(ctx, git, repoRoot, relPath, actualEpoch) {
615
+ if (ctx.dirtyAsNow && isDirtyForShared(ctx, git, repoRoot, relPath)) {
616
+ return getNowEpochShared(ctx);
617
+ }
618
+ return actualEpoch();
619
+ }
620
+ /**
621
+ * `--dirty-as-now` only: the verdict for "did the doc's OWN uncommitted
622
+ * working-tree state re-stamp it" -- the virtual-commit analogue of
623
+ * `restampedByOwnLastCommit`'s co-commit check, used in its place (see
624
+ * `restampFor` in the rule above) whenever the doc itself is dirty. The
625
+ * virtual commit's implicit "first parent" is simply HEAD, so this compares
626
+ * the doc's CURRENT (working-tree) parsed `timestamp` identity -- already
627
+ * read from disk by the caller, since `BundleDoc` always reflects the
628
+ * working tree, dirty or not -- against the value committed at HEAD for the
629
+ * same path. Any change of value, in EITHER direction (including a
630
+ * backwards re-stamp), counts as re-stamped, mirroring the committed
631
+ * rescue's "changed, not corrected" semantics documented on
632
+ * `restampedByOwnLastCommit` below.
633
+ *
634
+ * Distinguishes a genuinely untracked/new doc (no entry for this path at
635
+ * HEAD at all -- `git ls-tree HEAD -- <path>` succeeds with EMPTY output,
636
+ * never a git failure) from a real git failure reading an EXISTING HEAD
637
+ * blob (`git show` itself failing -- a corrupt object, an unreadable blob):
638
+ * the former counts as "restamped" (there is no prior committed value to
639
+ * compare against, so its whole content, stamp included, is new -- the
640
+ * working-tree equivalent of "the doc being created there"); the latter is
641
+ * `unknown`, falling through to the rule's existing not-assessable notice
642
+ * rather than being silently treated the same as "created". `git ls-tree`
643
+ * itself failing (an unborn HEAD, git unavailable) is likewise `unknown`.
644
+ */
645
+ function dirtyDocRestampVerdict(git, repoRoot, repoRelDocPath, onDiskTimestamp) {
646
+ const treeEntry = git(["ls-tree", "-z", "HEAD", "--", repoRelDocPath], repoRoot);
647
+ if (treeEntry === null)
648
+ return "unknown";
649
+ if (treeEntry === "")
650
+ return "restamped";
651
+ const committed = git(["show", `HEAD:${repoRelDocPath}`], repoRoot);
652
+ if (committed === null)
653
+ return "unknown";
654
+ const committedStamp = getTimestampIdentity(parseFrontmatter(committed).frontmatter.parsed);
655
+ return committedStamp !== onDiskTimestamp ? "restamped" : "not-restamped";
656
+ }
270
657
  function epochToIso(epochSeconds) {
271
658
  return new Date(epochSeconds * 1000).toISOString();
272
659
  }
273
660
  /**
274
- * Per-run cache of a doc's own last-commit epoch, keyed by the
275
- * `BundleContext` instance so `sources-fresh`'s doc-commit comparison and
276
- * `sources-fresh-future`'s timestamp comparison -- both need the IDENTICAL
277
- * (repoRoot, doc path) `getLastCommitEpoch` lookup for every doc in one
278
- * `check` invocation -- share one `git log` process per doc instead of each
279
- * rule spawning its own. Safe to key on the context object itself: a fresh
280
- * `BundleContext` is built per `runCheck`/`loadBundle` call, so nothing
281
- * reuses a stale cache entry across invocations, and the WeakMap lets the
282
- * cache be garbage-collected with the context once a run is done.
661
+ * Per-run cache of a doc's own REAL (committed) last-commit epoch, keyed by
662
+ * the `BundleContext` instance so `sources-fresh`'s doc-commit comparison
663
+ * and `sources-fresh-future`'s timestamp comparison -- both need the
664
+ * IDENTICAL (repoRoot, doc path) `getLastCommitEpoch` lookup for every doc
665
+ * in one `check` invocation -- share one `git log` process per doc instead
666
+ * of each rule spawning its own. Safe to key on the context object itself:
667
+ * a fresh `BundleContext` is built per `runCheck`/`loadBundle` call, so
668
+ * nothing reuses a stale cache entry across invocations, and the WeakMap
669
+ * lets the cache be garbage-collected with the context once a run is done.
670
+ *
671
+ * `getDocCommitEpochShared` below is the single place BOTH rules read a
672
+ * doc's commit epoch from, and it is itself built on
673
+ * `commitEpochWithDirtyAsNow`: under `--dirty-as-now`, a dirty doc's epoch
674
+ * is the shared virtual "now" instant instead of this real cache's answer,
675
+ * so `sources-fresh`'s co-commit rescue and `sources-fresh-future`'s
676
+ * timestamp comparison always see the identical (real-or-virtual) epoch
677
+ * for the same doc in the same `check` run.
283
678
  */
284
679
  const docCommitEpochCache = new WeakMap();
285
680
  function getDocCommitEpochShared(ctx, git, repoRoot, repoRelDocPath) {
286
- let cache = docCommitEpochCache.get(ctx);
287
- if (!cache) {
288
- cache = new Map();
289
- docCommitEpochCache.set(ctx, cache);
290
- }
291
- const cached = cache.get(repoRelDocPath);
292
- if (cached !== undefined)
293
- return cached;
294
- const epoch = getLastCommitEpoch(git, repoRoot, repoRelDocPath);
295
- cache.set(repoRelDocPath, epoch);
296
- return epoch;
681
+ return commitEpochWithDirtyAsNow(ctx, git, repoRoot, repoRelDocPath, () => {
682
+ let cache = docCommitEpochCache.get(ctx);
683
+ if (!cache) {
684
+ cache = new Map();
685
+ docCommitEpochCache.set(ctx, cache);
686
+ }
687
+ const cached = cache.get(repoRelDocPath);
688
+ if (cached !== undefined)
689
+ return cached;
690
+ const epoch = getLastCommitEpoch(git, repoRoot, repoRelDocPath);
691
+ cache.set(repoRelDocPath, epoch);
692
+ return epoch;
693
+ });
297
694
  }
298
695
  /**
299
696
  * Per-run cache (keyed by `BundleContext`, same pattern as
@@ -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/types.d.ts CHANGED
@@ -79,6 +79,25 @@ export interface BundleContext {
79
79
  * was not passed, in which case the rule applies its own default.
80
80
  */
81
81
  freshnessFutureSkewSeconds?: number;
82
+ /**
83
+ * Opt-in for `sources-fresh` AND `sources-fresh-future` (see
84
+ * `--dirty-as-now` in `src/cli.ts`): every uncommitted change (modified,
85
+ * staged, or untracked per `git status --porcelain --untracked-files=all`) is modeled as though
86
+ * it landed in ONE virtual commit made right now, instead of at its last
87
+ * real commit's time. That virtual-commit epoch is the SINGLE place both
88
+ * rules read a dirty path's "commit time" from (see
89
+ * `getDocCommitEpochShared`/`commitEpochFor` in
90
+ * `src/rules/sources-fresh.ts`): a dirty `sources` path's epoch becomes
91
+ * now (`sources-fresh`'s base comparison), and a dirty DOC's own epoch
92
+ * becomes now too (both `sources-fresh`'s co-commit rescue and
93
+ * `sources-fresh-future`'s timestamp comparison read that same virtual
94
+ * epoch). Closes the gap between a pre-commit `check` run (which sees
95
+ * only committed history) and CI's post-commit run (which sees the new
96
+ * commit time) for content edited but not yet committed. Undefined (the
97
+ * default) leaves both rules looking only at committed history,
98
+ * byte-identical to behavior before this option existed.
99
+ */
100
+ dirtyAsNow?: boolean;
82
101
  }
83
102
  export interface Rule {
84
103
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okf-kit",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "CLI that validates OKF v0.1 knowledge bundles for structural correctness",
5
5
  "type": "module",
6
6
  "bin": {