etymd 0.15.0 → 0.17.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 +64 -16
- package/README.md +121 -47
- package/dist/{approve-MA4Z3TBT.js → approve-VN4EDBR5.js} +2 -2
- package/dist/{audit-YSALDC2L.js → audit-PHAK5HEW.js} +5 -5
- package/dist/{brief-DPZYSAMC.js → brief-7MWP35UI.js} +2 -2
- package/dist/{chunk-Y6RZRED3.js → chunk-446EZNAQ.js} +1 -1
- package/dist/{chunk-CEO3BXQB.js → chunk-ANFNXFRI.js} +2 -2
- package/dist/{chunk-DBWDMIYO.js → chunk-BUMOGHQA.js} +1 -1
- package/dist/{chunk-IWG77WV3.js → chunk-FNA4R5KT.js} +31 -6
- package/dist/{fleet-4FYZ3GBK.js → chunk-LVR2DPR7.js} +438 -469
- package/dist/{chunk-UFNETE6P.js → chunk-PIJZUDDQ.js} +6 -2
- package/dist/{chunk-2RNQ6OLV.js → chunk-WKP7M2B3.js} +2 -2
- package/dist/cli.js +58 -23
- package/dist/{doctor-Y3DWDEBT.js → doctor-R4QDCAN5.js} +5 -5
- package/dist/fleet-WPYEVHVL.js +489 -0
- package/dist/{gates-IBQ7HCAN.js → gates-3HRGYCYY.js} +7 -4
- package/dist/{generate-KEX75XNG.js → generate-FSJQFQPV.js} +1 -1
- package/dist/index.d.ts +146 -20
- package/dist/index.js +497 -95
- package/dist/{init-H57H2JBE.js → init-6RULX5JZ.js} +3 -3
- package/dist/{premise-VMC3UUIB.js → premise-GFWHSR3K.js} +59 -24
- package/dist/propose-IYNOIWAO.js +252 -0
- package/dist/scan-5SC47FSM.js +5 -0
- package/dist/{scan-XBOHDXAH.js → scan-LLWW4YOU.js} +2 -2
- package/dist/{screen-E4FC7W5N.js → screen-S736DXQ5.js} +56 -24
- package/package.json +4 -4
- package/dist/scan-W4US23MU.js +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# etymd
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- The content screen's allow file accepts a `generated <path-regex>` record: a path declared
|
|
8
|
+
as regenerated data is still read and still screened, but vocabulary-class patterns drop
|
|
9
|
+
for it — secret-class patterns and the machine-path check stay — and the exempted paths
|
|
10
|
+
are named in the output, so a clean run never reads as fully screened. Provenance
|
|
11
|
+
(reason, date, author) is required.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 2bceef1: The fleet's gate-drift check now derives the pre-push audit tier the same way `etymd gates`
|
|
16
|
+
does. In a repo where no risk-tier rule can fire (no package manifest, no state doc) the
|
|
17
|
+
generator lowers the audit line to `--fail-on gap`; the drift comparison planned with the raw
|
|
18
|
+
config tier (`risk`), so its expectation permanently differed from the hook the generator
|
|
19
|
+
itself writes — a `gate-stale` finding on every repo of that shape, unclearable by the action
|
|
20
|
+
it names. The derivation now lives in `planWorkflow` itself, where the hook is built, so every
|
|
21
|
+
caller (the drift check, `etymd init`, the programmatic surface) generates identical bytes; a
|
|
22
|
+
tier the repo pinned in config is still never lowered.
|
|
23
|
+
- 7221fea: The content screen's machine-path rule now fires only at a path boundary (line start,
|
|
24
|
+
whitespace, a quote, `=`, `(`, `[` or `:`). A home path inside a longer token or a URL —
|
|
25
|
+
a test fixture's temp root (`$ROOT/home/‹x›/`), a docs URL with a home segment — is not a
|
|
26
|
+
machine path, and no longer prints the same advisory line on every push. A bare
|
|
27
|
+
`/Users/<name>/…` or `/home/<name>/…` still hits.
|
|
28
|
+
|
|
29
|
+
## 0.16.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- dc77a1f: `contract.milestones` and `etymd fleet board` — a project declares its plan in `MILESTONES.md`
|
|
34
|
+
(`# Milestones`, then `| id | milestone | goal | status | next | effort | depends-on |`); the sweep
|
|
35
|
+
files a gap when a declared file is absent or off-shape; `fleet add` registers the file when
|
|
36
|
+
present; `fleet board --initiatives <file> --out <file>` renders every project's rows plus a ranked
|
|
37
|
+
initiatives table and totals, deterministic, guarded entries excluded, exit 1 on holes.
|
|
38
|
+
- b3fb81a: The fleet manifest's second profile is now `guarded` (it had another name before), with every derived name
|
|
39
|
+
following: `guardedHosts` in the local file, `--profile guarded`, the `guarded/<name>/` persistence
|
|
40
|
+
zone beside the manifest, and the guarded-worktree wall checks. No alias for the old value: a
|
|
41
|
+
manifest still carrying it fails `fleet check` and names the entry. Prose and examples describe the
|
|
42
|
+
feature as a second, guarded workspace whose entries stay alias-only and machine-pinned.
|
|
43
|
+
- 79af085: `etymd propose` — score the sweep's improvement findings and recurring classes against a
|
|
44
|
+
fleet-authored rubric file (`criterion: <weight>` labeled lines; criteria: severity, economy,
|
|
45
|
+
confidence, breadth — an unknown criterion is refused quoting the line) and emit deterministic,
|
|
46
|
+
read-only `proposal/1` records carrying score, the fired rubric lines, and an implications block
|
|
47
|
+
(projects, files, gates, reversibility) extracted from finding evidence. Guarded entries are
|
|
48
|
+
excluded from the output entire. `--manifest` (fresh read-only sweep) or `--from <fleet.json>`
|
|
49
|
+
(stored sweep), `--json`. Decision record: docs/decisions/012.
|
|
50
|
+
|
|
3
51
|
## 0.15.0
|
|
4
52
|
|
|
5
53
|
### Minor Changes
|
|
@@ -422,18 +470,18 @@ so a pack number cited in a baseline always means exactly one pack.
|
|
|
422
470
|
|
|
423
471
|
### Minor Changes
|
|
424
472
|
|
|
425
|
-
- e265713: `fleet add --profile
|
|
473
|
+
- e265713: `fleet add --profile guarded` now records the alias-to-directory mapping too, not just the entry.
|
|
426
474
|
|
|
427
|
-
A
|
|
428
|
-
what keeps
|
|
429
|
-
nothing on its own. Registering wrote only that half, so every
|
|
475
|
+
A guarded entry in the tracked manifest is deliberately alias-only — no path, no remote — which is
|
|
476
|
+
what keeps guarded-side names out of a file that gets pushed. It also means the entry resolves to
|
|
477
|
+
nothing on its own. Registering wrote only that half, so every guarded registration ended as a
|
|
430
478
|
dangling entry that `fleet check` reported immediately and the user had to fix by hand, in the
|
|
431
479
|
one file the tool otherwise never asks anyone to hand-edit.
|
|
432
480
|
|
|
433
481
|
The mapping is written `~`-relative, so the local manifest stays portable between machines, and
|
|
434
482
|
merged into the existing document so hand-maintained entries survive.
|
|
435
483
|
|
|
436
|
-
Two refusals guard it, because this file is the one place real
|
|
484
|
+
Two refusals guard it, because this file is the one place real guarded-side directory names are
|
|
437
485
|
written down. If the local manifest is not gitignored, registration refuses rather than creating
|
|
438
486
|
a file git would track — a leak the tool creates is worse than a registration it declines to
|
|
439
487
|
finish. If the file exists but is not valid JSON, it refuses rather than overwriting mappings
|
|
@@ -452,7 +500,7 @@ so a pack number cited in a baseline always means exactly one pack.
|
|
|
452
500
|
It is also the field that turned a mis-profiled entry into a real disclosure. A raw remote URL
|
|
453
501
|
carries the host and the internal group path; `path` carries a bare directory name. Removing a
|
|
454
502
|
field no consumer reads retires that class outright, with no host-matching heuristic, and unlike
|
|
455
|
-
the
|
|
503
|
+
the guarded-host guard it keeps working on a machine that has no local manifest to read guarded hosts
|
|
456
504
|
from. The remote stays derivable from the checkout at any time, which is where it came from.
|
|
457
505
|
|
|
458
506
|
Existing entries that already carry a remote are left alone — nothing reads them, and rewriting
|
|
@@ -462,20 +510,20 @@ so a pack number cited in a baseline always means exactly one pack.
|
|
|
462
510
|
|
|
463
511
|
### Patch Changes
|
|
464
512
|
|
|
465
|
-
- 88492b5: Fix: `fleet add --profile
|
|
513
|
+
- 88492b5: Fix: `fleet add --profile guarded` was silently ignored, registering guarded repos as personal.
|
|
466
514
|
|
|
467
515
|
`fleet` declares its own `--profile` (the sweep filter), and commander hands a parent-declared
|
|
468
|
-
option the value even when it is typed after the subcommand. So `fleet add <dir> --profile
|
|
516
|
+
option the value even when it is typed after the subcommand. So `fleet add <dir> --profile guarded`
|
|
469
517
|
left the subcommand's own option undefined, the placement fell back to personal, and the
|
|
470
|
-
personal branch records `path` and the RAW `remote` — writing the
|
|
518
|
+
personal branch records `path` and the RAW `remote` — writing the guarded host and its internal
|
|
471
519
|
group structure into a manifest that is tracked and pushed. That is precisely the disclosure the
|
|
472
520
|
alias convention exists to prevent. The same shadowing class was already fixed for `--manifest`
|
|
473
521
|
and `--json`; `--profile` was missed.
|
|
474
522
|
|
|
475
523
|
Two changes, because the flag alone is not enough. The CLI now reads the merged option view, so
|
|
476
|
-
the flag works. And `fleet add` refuses outright when the target's remote matches a
|
|
477
|
-
declared in the local manifest while the profile is not
|
|
478
|
-
hosts are the
|
|
524
|
+
the flag works. And `fleet add` refuses outright when the target's remote matches a guarded host
|
|
525
|
+
declared in the local manifest while the profile is not guarded — the manifest already knows which
|
|
526
|
+
hosts are the guarded side's and the remote has just been read, so the tool has every fact needed to
|
|
479
527
|
prevent this without anyone remembering a flag. It refuses rather than auto-correcting:
|
|
480
528
|
placement is the user's decision, but it may not be made by omission.
|
|
481
529
|
|
|
@@ -612,7 +660,7 @@ so a pack number cited in a baseline always means exactly one pack.
|
|
|
612
660
|
value it explains changes, because a stale reason misleads exactly where it meant to inform.
|
|
613
661
|
|
|
614
662
|
**`etymd fleet add`** registers a project, prompting for what no scan can derive and refusing to
|
|
615
|
-
write an incomplete entry. Fleet manifests gain a mandatory `trust` level on non-
|
|
663
|
+
write an incomplete entry. Fleet manifests gain a mandatory `trust` level on non-guarded entries —
|
|
616
664
|
absence is a finding, never a silent default — a manifest-level `orientation.root` replacing
|
|
617
665
|
per-entry links, and a gate-drift check that reports a repository missing a gate its siblings
|
|
618
666
|
install.
|
|
@@ -672,9 +720,9 @@ so a pack number cited in a baseline always means exactly one pack.
|
|
|
672
720
|
|
|
673
721
|
- New `state-freshness` truth lens: state/decisions artifacts dated by git committer dates only (never mtime); staleness is relative, so a dormant repo's old state is current; state char budget against the ~10k session-hook truncation; marker-gated decisions format checks (`Scope:`, duplicate/out-of-order `D-NNN` ids, past `Revisit:` dates as due review debt); ADR conventions (`docs/adr/`, `docs/decisions/`, `NNNN-*.md`) recognized natively.
|
|
674
722
|
- New `etymd fleet` command family. The sweep runs a read-only audit per registered repo (`--manifest` required unless the cwd holds `registry.json` — no env var, no global pointer) and renders one line per project with a delta against `last.fleet.json`; detail only for new or risk findings. `fleet check` validates the manifest pair alone (dangling mappings, duplicate names, privacy leaks, machine paths). `fleet dismiss`/`fleet accept` resolve a project's finding from any cwd.
|
|
675
|
-
- The manifest loader (`src/core/fleet.ts`) resolves both the fleet registry pair (`registry.json` + gitignored `registry.local.json`) and the legacy corpus pair (`sources.json` + `sources.local.json`);
|
|
676
|
-
- Persistence invariants, pinned by tests: the sweep never creates `.etymd` anywhere; `--persist-ledgers` only persists into personal repos that already opted in;
|
|
677
|
-
- Fleet-scope wall findings (lens id `fleet-manifest`):
|
|
723
|
+
- The manifest loader (`src/core/fleet.ts`) resolves both the fleet registry pair (`registry.json` + gitignored `registry.local.json`) and the legacy corpus pair (`sources.json` + `sources.local.json`); guarded entries are opaque aliases resolved only through the local file, and every resolution failure is disclosed, never silently skipped.
|
|
724
|
+
- Persistence invariants, pinned by tests: the sweep never creates `.etymd` anywhere; `--persist-ledgers` only persists into personal repos that already opted in; guarded worktrees take zero writes under every flag combination — guarded findings persist (and stay dismissible) at `<manifestDir>/guarded/<name>/.etymd/`; zero guarded-resolved content under the manifest repo's tracked paths.
|
|
725
|
+
- Fleet-scope wall findings (lens id `fleet-manifest`): guarded contract files inside a guarded worktree, unregistered guarded-remote checkouts under the fleet root, tracked `/Users/` paths in the manifest's own repo, private needles inside `trust: "public-repo"` entries, guarded-host commit emails on personal entries.
|
|
678
726
|
- Fork-aware freshness: entries with `upstream` are dated on fork-authored commits only (`HEAD --not --remotes=<upstream>`), with a disclosed fallback when the remote is absent.
|
|
679
727
|
|
|
680
728
|
## 0.1.0 — 2026-07-31
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Etymd
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<img src="https://raw.githubusercontent.com/
|
|
4
|
+
<img src="https://raw.githubusercontent.com/fleetorders/etymd/main/media/etymd-logo.png" width="520" alt="Etymd — a papyrus of written instructions, each line checked against the repository it describes">
|
|
5
5
|
<p>
|
|
6
6
|
<a href="https://www.npmjs.com/package/etymd"><img src="https://img.shields.io/npm/v/etymd.svg?label=npm&color=cb3837" alt="npm version"></a>
|
|
7
|
-
<a href="https://github.com/
|
|
8
|
-
<a href="https://github.com/
|
|
7
|
+
<a href="https://github.com/fleetorders/etymd/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/fleetorders/etymd/ci.yml?branch=main&label=CI" alt="CI"></a>
|
|
8
|
+
<a href="https://github.com/fleetorders/etymd/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT license"></a>
|
|
9
9
|
</p>
|
|
10
10
|
</div>
|
|
11
11
|
|
|
@@ -167,29 +167,31 @@ append race is a defect in the file's own convention, not a format opinion.
|
|
|
167
167
|
|
|
168
168
|
**`fleet-manifest`** (via `etymd fleet`) — one truth guard across every repo you registered:
|
|
169
169
|
per-repo audits plus checks on the fleet manifest itself and on the placement wall between
|
|
170
|
-
personal and
|
|
170
|
+
personal and guarded repos. See [the fleet manifest](#the-fleet-manifest-experimental) below.
|
|
171
171
|
|
|
172
172
|
## Commands
|
|
173
173
|
|
|
174
|
-
| Command | What it does
|
|
175
|
-
| -------------------------------- |
|
|
176
|
-
| `etymd audit` | Verify every claim; ranked findings (risk → gap → polish) + ledger diff. `--lens`, `--truth`, `--json`, `--no-ledger`, `--fail-on <tier>`.
|
|
177
|
-
| `etymd init` | Onboard: approve the committed baseline; scaffold a minimal AGENTS.md **only if missing**. Never overwrites.
|
|
178
|
-
| `etymd doctor` | Alias for `audit --truth`.
|
|
179
|
-
| `etymd context` | The economy view: per-file always-loaded footprint + extraction candidates.
|
|
180
|
-
| `etymd gates` | Install local git-hook gates (pre-commit / commit-msg / pre-push, plus a publish screen where something ships) built from your own check scripts — and from the repo's shell surface, where it has one.
|
|
181
|
-
| `etymd screen` | Content screen: find text that must never be published. Four scopes — `--staged`, `--message`, `--tree`, `--dir`. Bring your own patterns; etymd ships none.
|
|
182
|
-
| `etymd scan` | The deterministic reckoning behind everything. `--json`.
|
|
183
|
-
| `etymd brief` | A grounded briefing your in-repo agent completes to author the semantic layer.
|
|
184
|
-
| `etymd premise` | `premise "<task>"` — is this the right task? What it names, verified against the repo; a brief for what only the agent can verify. `--file` (`-` = stdin), `--json`, `--no-brief`, `--fail-on <tier>`. No ledger.
|
|
185
|
-
| `etymd approve` | Refresh the committed baseline non-interactively after intentional structural changes.
|
|
186
|
-
| `etymd ledger` | The findings memory: every tracked finding with status and history.
|
|
187
|
-
| `etymd dismiss` | `dismiss <id> --reason <text>` — a dismissed finding never resurfaces without regressing.
|
|
188
|
-
| `etymd accept` | `accept <id>` — record a finding as accepted reality; visible in the ledger, out of the report.
|
|
189
|
-
| `etymd fleet` | Sweep every project in a fleet manifest: read-only per-repo audits + manifest/wall checks. `--manifest`, `--only`, `--profile`, `--truth`, `--persist-ledgers`, `--json`, `--fail-on`.
|
|
190
|
-
| `etymd fleet check` | Validate the manifest pair alone (no lenses): dangling mappings, duplicate names, privacy leaks, undeclared trust, machine paths. Non-zero exit on any finding.
|
|
191
|
-
| `etymd fleet add` | `add <dir>` — register a project: scans it, asks for what no scan can derive, and refuses to write an entry missing a mandatory field. `--name`, `--kind`, `--profile`, `--trust`, `-y`.
|
|
192
|
-
| `etymd fleet
|
|
174
|
+
| Command | What it does |
|
|
175
|
+
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
176
|
+
| `etymd audit` | Verify every claim; ranked findings (risk → gap → polish) + ledger diff. `--lens`, `--truth`, `--json`, `--no-ledger`, `--fail-on <tier>`. |
|
|
177
|
+
| `etymd init` | Onboard: approve the committed baseline; scaffold a minimal AGENTS.md **only if missing**. Never overwrites. |
|
|
178
|
+
| `etymd doctor` | Alias for `audit --truth`. |
|
|
179
|
+
| `etymd context` | The economy view: per-file always-loaded footprint + extraction candidates. |
|
|
180
|
+
| `etymd gates` | Install local git-hook gates (pre-commit / commit-msg / pre-push, plus a publish screen where something ships) built from your own check scripts — and from the repo's shell surface, where it has one. |
|
|
181
|
+
| `etymd screen` | Content screen: find text that must never be published. Four scopes — `--staged`, `--message`, `--tree`, `--dir`. Bring your own patterns; etymd ships none. |
|
|
182
|
+
| `etymd scan` | The deterministic reckoning behind everything. `--json`. |
|
|
183
|
+
| `etymd brief` | A grounded briefing your in-repo agent completes to author the semantic layer. |
|
|
184
|
+
| `etymd premise` | `premise "<task>"` — is this the right task? What it names, verified against the repo; a brief for what only the agent can verify. `--file` (`-` = stdin), `--json`, `--no-brief`, `--fail-on <tier>`. No ledger. |
|
|
185
|
+
| `etymd approve` | Refresh the committed baseline non-interactively after intentional structural changes. |
|
|
186
|
+
| `etymd ledger` | The findings memory: every tracked finding with status and history. |
|
|
187
|
+
| `etymd dismiss` | `dismiss <id> --reason <text>` — a dismissed finding never resurfaces without regressing. |
|
|
188
|
+
| `etymd accept` | `accept <id>` — record a finding as accepted reality; visible in the ledger, out of the report. |
|
|
189
|
+
| `etymd fleet` | Sweep every project in a fleet manifest: read-only per-repo audits + manifest/wall checks. `--manifest`, `--only`, `--profile`, `--truth`, `--persist-ledgers`, `--json`, `--fail-on`. |
|
|
190
|
+
| `etymd fleet check` | Validate the manifest pair alone (no lenses): dangling mappings, duplicate names, privacy leaks, undeclared trust, machine paths. Non-zero exit on any finding. |
|
|
191
|
+
| `etymd fleet add` | `add <dir>` — register a project: scans it, asks for what no scan can derive, and refuses to write an entry missing a mandatory field. `--name`, `--kind`, `--profile`, `--trust`, `-y`. |
|
|
192
|
+
| `etymd fleet board` | Render the fleet board: every project's `MILESTONES.md` (contract key `milestones`, shape-checked by the sweep) plus a ranked initiatives table on one page. `--initiatives <file>`, `--out <file>`, `--json`. |
|
|
193
|
+
| `etymd propose` | Score the sweep's improvement findings + recurring classes against a fleet-authored rubric — stable `proposal/1` records, read-only, deterministic, guarded entries excluded. `--rubric <file>` (required), `--manifest <file>` or `--from <fleet.json>`, `--json`. |
|
|
194
|
+
| `etymd fleet dismiss` / `accept` | `<name> <id>` — resolve a project's finding from any cwd; guarded findings persist beside the manifest, never in the guarded worktree. |
|
|
193
195
|
|
|
194
196
|
`--cwd <dir>` targets another directory. Read-only probing of any repo leaves **zero trace**
|
|
195
197
|
(`audit --no-ledger` writes nothing).
|
|
@@ -324,7 +326,7 @@ the generated pre-push now carries a `shellcheck` step. Three properties are del
|
|
|
324
326
|
### The content screen (`etymd screen`)
|
|
325
327
|
|
|
326
328
|
A separate question from "are the instructions true?": **does this repo carry text that must
|
|
327
|
-
never be published?** Absolute home paths, an
|
|
329
|
+
never be published?** Absolute home paths, an organisation's name, an internal hostname, an account
|
|
328
330
|
identifier — permanent the moment they are committed, because publishing exposes all history,
|
|
329
331
|
not the current tree.
|
|
330
332
|
|
|
@@ -358,7 +360,7 @@ inline marker would not survive into the artifact. Those live in `.etymd-screen-
|
|
|
358
360
|
repo root — one labeled line per field, so the pattern is never delimited:
|
|
359
361
|
|
|
360
362
|
```
|
|
361
|
-
pattern ^
|
|
363
|
+
pattern ^AcmeInc|BetaInc$
|
|
362
364
|
reason fixture proving the detector fires on either name
|
|
363
365
|
date 2026-08-15
|
|
364
366
|
author someone
|
|
@@ -373,6 +375,24 @@ missing a field is reported and does not apply: an exemption is a hole in the ga
|
|
|
373
375
|
nobody signed cannot be audited later. The file is read from the repo being screened, never a
|
|
374
376
|
shared location, and it screens itself out (it necessarily contains every string it exempts).
|
|
375
377
|
|
|
378
|
+
The file carries a second record kind, for paths rather than lines:
|
|
379
|
+
|
|
380
|
+
```
|
|
381
|
+
generated ^src/data/corpus\.json$
|
|
382
|
+
reason public-domain corpus, regenerated by scripts/corpus each January
|
|
383
|
+
date 2026-09-04
|
|
384
|
+
author someone
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
A `generated` path is data a pipeline rebuilds — a public-domain corpus, generated fixtures —
|
|
388
|
+
and period English trips credential vocabulary (`passkey`, `secret`) on a schedule, training
|
|
389
|
+
exactly the `--no-verify` habit the screen exists to prevent. The file is still read and still
|
|
390
|
+
screened: only vocabulary-class patterns drop for it, while secret-class patterns and the
|
|
391
|
+
machine-path check stay — a generated file is precisely where a real credential would be least
|
|
392
|
+
visible. Provenance is unconditional (a path is never the repo naming itself), and the paths
|
|
393
|
+
that took the exemption are named in the output, so a clean run never reads as fully screened
|
|
394
|
+
where it was screened narrower.
|
|
395
|
+
|
|
376
396
|
### The commit subject, if you ask for it
|
|
377
397
|
|
|
378
398
|
Off unless you turn it on:
|
|
@@ -418,10 +438,10 @@ steps:
|
|
|
418
438
|
`etymd fleet` extends the one objective across every repository you work in — your fleet of
|
|
419
439
|
**repositories**, not a fleet of agents. The manifest, `registry.json`, is itself an
|
|
420
440
|
agent-context file: claims about your fleet (what exists, where, under which **profile** — the
|
|
421
|
-
side of the wall an entry belongs to, `personal` or `
|
|
422
|
-
boundary between personal and
|
|
441
|
+
side of the wall an entry belongs to, `personal` or `guarded`; the **wall** is the placement
|
|
442
|
+
boundary between personal and guarded content that the sweep polices). It rots like any
|
|
423
443
|
AGENTS.md does, and `etymd fleet` keeps it true. Decision record:
|
|
424
|
-
[`docs/decisions/004-fleet-truth-guard.md`](https://github.com/
|
|
444
|
+
[`docs/decisions/004-fleet-truth-guard.md`](https://github.com/fleetorders/etymd/blob/main/docs/decisions/004-fleet-truth-guard.md). Both the
|
|
425
445
|
registry schema and the fleet `--json` schema are **experimental through 0.2.x**.
|
|
426
446
|
|
|
427
447
|
Two files beside each other — the split is the privacy model:
|
|
@@ -446,7 +466,7 @@ Two files beside each other — the split is the privacy model:
|
|
|
446
466
|
"kind": "docs",
|
|
447
467
|
"profile": "personal",
|
|
448
468
|
"path": "notes",
|
|
449
|
-
"trust": "private", // mandatory on every non-
|
|
469
|
+
"trust": "private", // mandatory on every non-guarded entry — see below
|
|
450
470
|
"staleAfterDays": 45, // per-entry freshness window
|
|
451
471
|
"contract": { "state": "STATUS.md" }, // native conventions register, never migrate
|
|
452
472
|
},
|
|
@@ -458,8 +478,14 @@ Two files beside each other — the split is the privacy model:
|
|
|
458
478
|
"upstream": "origin", // freshness measured on fork-authored commits only
|
|
459
479
|
"trust": "public-repo", // hygiene needles apply (see below)
|
|
460
480
|
},
|
|
461
|
-
//
|
|
462
|
-
{
|
|
481
|
+
// Guarded entries: opaque alias, private, NO path — real dirs live only in the local file.
|
|
482
|
+
{
|
|
483
|
+
"name": "c-one",
|
|
484
|
+
"kind": "repo",
|
|
485
|
+
"profile": "guarded",
|
|
486
|
+
"private": true,
|
|
487
|
+
"staleAfterDays": 45,
|
|
488
|
+
},
|
|
463
489
|
],
|
|
464
490
|
}
|
|
465
491
|
```
|
|
@@ -468,23 +494,23 @@ Two files beside each other — the split is the privacy model:
|
|
|
468
494
|
|
|
469
495
|
```jsonc
|
|
470
496
|
{
|
|
471
|
-
"machineProfile": "
|
|
497
|
+
"machineProfile": "guarded", // which profile this machine resolves; "personal" resolves guarded entries disclosed-absent
|
|
472
498
|
"root": "~/projects", // optional per-machine root override
|
|
473
|
-
"dirs": { "c-one": "~/projects/real-
|
|
474
|
-
"labels": { "c-one": "real-
|
|
475
|
-
"
|
|
499
|
+
"dirs": { "c-one": "~/projects/real-guarded-dir" },
|
|
500
|
+
"labels": { "c-one": "real-guarded-dir" },
|
|
501
|
+
"guardedHosts": ["git.example-guarded.com"],
|
|
476
502
|
}
|
|
477
503
|
```
|
|
478
504
|
|
|
479
505
|
Two fields the scan can never derive, so the manifest must declare them:
|
|
480
506
|
|
|
481
|
-
- **`trust` — mandatory on every non-
|
|
507
|
+
- **`trust` — mandatory on every non-guarded entry** (`public-repo` | `public-bound` | `private`).
|
|
482
508
|
It is a _safety predicate_, not a label: it decides whether content screening applies, so an
|
|
483
509
|
absent value is reported (`fleet check` flags it), never read as a silent `private`.
|
|
484
510
|
`public-bound` means private today, plausibly public later — screened exactly as hard as
|
|
485
511
|
public, because publishing exposes _all_ history: the scrub has to precede the first commit,
|
|
486
512
|
not the visibility flip. A value outside the vocabulary is flagged rather than coerced, so a
|
|
487
|
-
typo can never quietly disable screening.
|
|
513
|
+
typo can never quietly disable screening. Guarded entries omit it — `profile: "guarded"` already
|
|
488
514
|
implies the answer.
|
|
489
515
|
- **`orientation.root` — optional, declared once.** Names the one entry every other entry is
|
|
490
516
|
guided by. Declared at the manifest level rather than repeated per entry, because a per-entry
|
|
@@ -499,10 +525,10 @@ CI) must pass every mandatory value as a flag — there is deliberately no defau
|
|
|
499
525
|
How the sweep behaves:
|
|
500
526
|
|
|
501
527
|
- **Read-only by default, everywhere.** The sweep never creates `.etymd` anywhere.
|
|
502
|
-
`--persist-ledgers` persists only into personal repos that already opted in, and a **
|
|
528
|
+
`--persist-ledgers` persists only into personal repos that already opted in, and a **guarded
|
|
503
529
|
worktree is never written** — regardless of flags, even if a stray `.etymd` exists inside it
|
|
504
|
-
(pinned by test).
|
|
505
|
-
`<manifest-dir>/
|
|
530
|
+
(pinned by test). Guarded findings stay dismissible: their ledger lives at
|
|
531
|
+
`<manifest-dir>/guarded/<name>/.etymd/`, beside the manifest.
|
|
506
532
|
- **Deltas.** Each sweep compares against `last.fleet.json` stored beside the manifest and
|
|
507
533
|
renders `Δ +new −resolved` per project. Add `*.fleet.json` to the manifest repo's
|
|
508
534
|
`.gitignore` — sweep output is local-only and never tracked.
|
|
@@ -514,17 +540,64 @@ How the sweep behaves:
|
|
|
514
540
|
that instruction files are legitimately absent in that project — the sweep drops its
|
|
515
541
|
missing-contract finding instead of re-reporting a decision every run. Absence disclosed on
|
|
516
542
|
purpose is a state, not a gap.
|
|
517
|
-
- **Wall checks.**
|
|
518
|
-
under the fleet root whose remotes match `
|
|
543
|
+
- **Wall checks.** Guarded contract files found inside a guarded worktree, unregistered checkouts
|
|
544
|
+
under the fleet root whose remotes match `guardedHosts`, tracked `/Users/` paths in the manifest
|
|
519
545
|
repo, private **needles** — the identifiers the local file holds (labels, dir names, hosts) —
|
|
520
|
-
inside `trust: "public-repo"` entries, and
|
|
546
|
+
inside `trust: "public-repo"` entries, and guarded-host commit emails on personal entries — each
|
|
521
547
|
a risk finding; each check that cannot run is disclosed.
|
|
522
548
|
- **No global pointer.** `--manifest` is required unless the cwd holds `registry.json` — there
|
|
523
549
|
is deliberately no env var and no home-directory pointer.
|
|
550
|
+
- **Milestones and the fleet board.** A project declares its plan in one file — `MILESTONES.md`,
|
|
551
|
+
registered as `"contract": { "milestones": "MILESTONES.md" }` (`fleet add` registers it when the
|
|
552
|
+
file is present; `"none"` declares a project deliberately carries no plan). The file has a fixed
|
|
553
|
+
shape so the fleet can read every plan without an agent: a `# Milestones` heading, then a table
|
|
554
|
+
`| id | milestone | goal | status | next | effort | depends-on |` — `id` is `M<n>`, `goal` is 1, 2
|
|
555
|
+
or 3 (your fleet's own ordered goals, declared outside this tool), `status` is planned | active |
|
|
556
|
+
blocked | done, `next` is the one concrete next step, `effort` the S | M | L remaining,
|
|
557
|
+
`depends-on` a list of ids or `—`. Prose after the table is free. The sweep files a gap when a
|
|
558
|
+
declared file is absent or off-shape. `etymd fleet board --initiatives <file> --out <file>`
|
|
559
|
+
renders every project's rows, a ranked initiatives table (`| rank | id | initiative | goal |
|
|
560
|
+
status | next | effort | projects | depends-on |`, the one hand-edited fleet-level surface), and
|
|
561
|
+
totals; guarded entries never appear on it. Day-precision stamp, deterministic output, exit code 1
|
|
562
|
+
when any project is missing or invalid — a board with holes still renders, and says so.
|
|
524
563
|
|
|
525
564
|
Formatter interop for the `.etymd` state the sweep resolves: same rule as everywhere — see
|
|
526
565
|
[the files Etymd keeps](#the-files-etymd-keeps).
|
|
527
566
|
|
|
567
|
+
### Rubric-scored proposals (`etymd propose`)
|
|
568
|
+
|
|
569
|
+
The sweep already gives every improvement finding an action, an effort and a confidence, and
|
|
570
|
+
names the classes open in two or more projects. `etymd propose` adds the scoring step — against
|
|
571
|
+
a rubric **your fleet authors**, because what is worth doing is your call, not the tool's:
|
|
572
|
+
|
|
573
|
+
```
|
|
574
|
+
severity: 2 # risk=3 · gap=2 · polish=1
|
|
575
|
+
economy: 3 # S=3 · M=2 · L=1
|
|
576
|
+
confidence: 1 # high=3 · medium=2 · low=1
|
|
577
|
+
breadth: 4 # projects carrying it, capped at 3
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
One criterion per line (`#` comments and blanks ignored). Those four criteria are the whole
|
|
581
|
+
vocabulary — each is computed from finding facts, so a score is arithmetic, not an opinion; a
|
|
582
|
+
line naming anything else is refused quoting the line. `score` is Σ weight × value; a line
|
|
583
|
+
**fires** (listed in `matched`) when the subject reads at/above the criterion's midpoint.
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
etymd propose --manifest registry.json --rubric opportunity.rubric --json
|
|
587
|
+
# or, without re-sweeping: --from <fleet.json> (a stored `etymd fleet --json` output)
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Subjects are every `kind: improvement` finding from personal projects plus every recurring
|
|
591
|
+
class, recomputed over personal projects only — **guarded entries are excluded from the output
|
|
592
|
+
entire, by name**. A class is scored conservatively (worst tier, dearest effort, weakest
|
|
593
|
+
confidence). Each `proposal/1` record carries id, class, projects, action, effort, confidence,
|
|
594
|
+
score, the fired rubric lines, and an `implications` block (projects, files, gates,
|
|
595
|
+
reversibility) extracted from the findings' evidence — files are path-shaped evidence tokens,
|
|
596
|
+
and `undetermined` reversibility says so rather than guessing. Read-only and deterministic: no
|
|
597
|
+
timestamps, nothing written, identical input → identical bytes, so a filed proposal can be
|
|
598
|
+
re-derived and compared. Decision record:
|
|
599
|
+
[`docs/decisions/012-propose-rubric-scored-proposals.md`](https://github.com/fleetorders/etymd/blob/main/docs/decisions/012-propose-rubric-scored-proposals.md).
|
|
600
|
+
|
|
528
601
|
## Programmatic use
|
|
529
602
|
|
|
530
603
|
```ts
|
|
@@ -537,7 +610,7 @@ console.log(audit.findings) // one schema: claim · evidence · why · action ·
|
|
|
537
610
|
## The corpus (how this is validated)
|
|
538
611
|
|
|
539
612
|
Etymd is developed against a corpus of real sibling repos rather than fixtures alone —
|
|
540
|
-
[`sources.json`](https://github.com/
|
|
613
|
+
[`sources.json`](https://github.com/fleetorders/etymd/blob/main/sources.json) lists them by shape. Every heuristic here exists because a real
|
|
541
614
|
repo proved the previous one wrong, and each skip class in the truth lens is a false positive that
|
|
542
615
|
a corpus run caught.
|
|
543
616
|
|
|
@@ -555,11 +628,12 @@ Without it — on a fresh clone or in CI — those suites skip cleanly and the r
|
|
|
555
628
|
|
|
556
629
|
## Decision record & roadmap
|
|
557
630
|
|
|
558
|
-
[`docs/decisions/`](https://github.com/
|
|
631
|
+
[`docs/decisions/`](https://github.com/fleetorders/etymd/tree/main/docs/decisions) — 001 founding · 002 foundation re-lock · **003 the truth-guard
|
|
559
632
|
pivot** (the current identity; includes the state-of-the-field investigation it rests on) ·
|
|
560
633
|
**004 fleet mode** (the truth guard across your repositories) · 005 declared rules (design only) ·
|
|
561
|
-
**006 local gate provenance** (what the tool may read, and what it may rewrite)
|
|
562
|
-
|
|
634
|
+
**006 local gate provenance** (what the tool may read, and what it may rewrite) · 011 milestones
|
|
635
|
+
& the fleet board · 012 `etymd propose` (rubric-scored proposals).
|
|
636
|
+
[`ROADMAP.md`](https://github.com/fleetorders/etymd/blob/main/ROADMAP.md) — what's now / next / later, and the accepted heuristic
|
|
563
637
|
trade-offs.
|
|
564
638
|
|
|
565
639
|
## License
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { section, theme, print, renderBaselineDrift, glyph } from './chunk-HI7NWPRA.js';
|
|
3
|
-
import { scanProject } from './chunk-
|
|
4
|
-
import { VERSION } from './chunk-
|
|
3
|
+
import { scanProject } from './chunk-446EZNAQ.js';
|
|
4
|
+
import { VERSION } from './chunk-BUMOGHQA.js';
|
|
5
5
|
import { readBaseline, summarizeBaselineDrift, isDriftEmpty, writeBaseline, deriveProfile } from './chunk-P6ATKV2R.js';
|
|
6
6
|
import { PACK_VERSION } from './chunk-YQZDYDAK.js';
|
|
7
7
|
import './chunk-4VPBP6K6.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export { run } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
2
|
+
export { run } from './chunk-ANFNXFRI.js';
|
|
3
|
+
import './chunk-WKP7M2B3.js';
|
|
4
|
+
import './chunk-FNA4R5KT.js';
|
|
5
5
|
import './chunk-3E2IPCRY.js';
|
|
6
6
|
import './chunk-HI7NWPRA.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
7
|
+
import './chunk-446EZNAQ.js';
|
|
8
|
+
import './chunk-BUMOGHQA.js';
|
|
9
9
|
import './chunk-P6ATKV2R.js';
|
|
10
10
|
import './chunk-YQZDYDAK.js';
|
|
11
11
|
import './chunk-4VPBP6K6.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { print, theme } from './chunk-HI7NWPRA.js';
|
|
3
|
-
import { scanProject } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
import { scanProject } from './chunk-446EZNAQ.js';
|
|
4
|
+
import './chunk-BUMOGHQA.js';
|
|
5
5
|
import { ETYMD_DIR } from './chunk-P6ATKV2R.js';
|
|
6
6
|
import './chunk-YQZDYDAK.js';
|
|
7
7
|
import './chunk-4VPBP6K6.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { VERSION } from './chunk-
|
|
2
|
+
import { VERSION } from './chunk-BUMOGHQA.js';
|
|
3
3
|
import { PACK_VERSION } from './chunk-YQZDYDAK.js';
|
|
4
4
|
import { normalizeRelPath, isDirectory, readJson, git, matchesAnyGlob, pathExists, readText } from './chunk-4VPBP6K6.js';
|
|
5
5
|
import path from 'path';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { runAudit } from './chunk-
|
|
3
|
-
import { parseFailOnTier, meetsFailOn } from './chunk-
|
|
2
|
+
import { runAudit } from './chunk-WKP7M2B3.js';
|
|
3
|
+
import { parseFailOnTier, meetsFailOn } from './chunk-FNA4R5KT.js';
|
|
4
4
|
import { print, section, theme, renderLensCoverage, renderFindings, renderLedgerDiff } from './chunk-HI7NWPRA.js';
|
|
5
5
|
|
|
6
6
|
// src/commands/audit.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { expandFileGlobs } from './chunk-
|
|
2
|
+
import { expandFileGlobs } from './chunk-446EZNAQ.js';
|
|
3
3
|
import { DEFAULT_CONFIG, CONFIG_FILE } from './chunk-P6ATKV2R.js';
|
|
4
4
|
import { readText, isDirectory, matchesAnyGlob, normalizeRelPath, readJson, pathExists, git } from './chunk-4VPBP6K6.js';
|
|
5
5
|
import path3 from 'path';
|
|
@@ -448,6 +448,13 @@ var PLACEHOLDER_PREFIX_RE = /^(?:my|your)-/i;
|
|
|
448
448
|
function isPlaceholderClaim(token) {
|
|
449
449
|
return token.split("/").some((seg) => PLACEHOLDER_PREFIX_RE.test(seg) || PLACEHOLDER_SEGMENTS.has(seg.toLowerCase()));
|
|
450
450
|
}
|
|
451
|
+
var NAMESPACE_IDENT = "[A-Za-z][A-Za-z0-9-]{0,15}";
|
|
452
|
+
var NAMESPACE_STOP = new Set(
|
|
453
|
+
"note notes see warning caution caveat caveats example examples ex eg ie nb ps re per file files path paths hint tip tips todo fixme step steps rule rules ref refs fact facts output outputs input inputs result results summary status overview next prev then thus hence plus goal goals spec specs context".split(" ")
|
|
454
|
+
);
|
|
455
|
+
function isNamespace(ident) {
|
|
456
|
+
return Boolean(ident) && !NAMESPACE_STOP.has(ident.toLowerCase());
|
|
457
|
+
}
|
|
451
458
|
function claimContext(text, index) {
|
|
452
459
|
const start = text.lastIndexOf("\n", index) + 1;
|
|
453
460
|
const endRaw = text.indexOf("\n", index);
|
|
@@ -467,8 +474,9 @@ ${line}`;
|
|
|
467
474
|
}
|
|
468
475
|
return line;
|
|
469
476
|
}
|
|
470
|
-
function extractPathClaims(text) {
|
|
477
|
+
function extractPathClaims(text, opts = {}) {
|
|
471
478
|
const prospectiveOnly = /* @__PURE__ */ new Map();
|
|
479
|
+
const namespacedOnly = /* @__PURE__ */ new Map();
|
|
472
480
|
const placeholder = /* @__PURE__ */ new Set();
|
|
473
481
|
for (const m of text.matchAll(/`([^`\n]+)`/g)) {
|
|
474
482
|
const token = m[1].trim();
|
|
@@ -490,14 +498,21 @@ function extractPathClaims(text) {
|
|
|
490
498
|
}
|
|
491
499
|
const prospective2 = CREATION_CONTEXT_RE.test(claimContext(text, m.index ?? 0));
|
|
492
500
|
prospectiveOnly.set(claim, (prospectiveOnly.get(claim) ?? true) && prospective2);
|
|
501
|
+
if (opts.namespaces) {
|
|
502
|
+
const nsLead = new RegExp(`(${NAMESPACE_IDENT}):[ \\t]*$`).exec(text.slice(0, m.index ?? 0));
|
|
503
|
+
const prefixed = isNamespace(nsLead?.[1]);
|
|
504
|
+
namespacedOnly.set(claim, (namespacedOnly.get(claim) ?? true) && prefixed);
|
|
505
|
+
}
|
|
493
506
|
}
|
|
494
507
|
const paths = [];
|
|
495
508
|
const prospective = [];
|
|
509
|
+
const namespaced = [];
|
|
496
510
|
for (const [claim, only] of prospectiveOnly) {
|
|
497
511
|
if (only) prospective.push(claim);
|
|
512
|
+
else if (namespacedOnly.get(claim)) namespaced.push(claim);
|
|
498
513
|
else paths.push(claim);
|
|
499
514
|
}
|
|
500
|
-
return { paths, prospective, placeholder: [...placeholder] };
|
|
515
|
+
return { paths, prospective, namespaced, placeholder: [...placeholder] };
|
|
501
516
|
}
|
|
502
517
|
var LOCAL_REF_LEADINS = new Set(
|
|
503
518
|
"decision decisions entry entries ruling rulings record records ledger id ids item items see per in of on at by to as is was are were the a an and or but not with under over from via vs than after before since between through against latest newest earliest only also still now supersedes superseded superseding amends amended extends extended cites cited citing adds added adding wrote written writes locked locks closed closes opened opens resolves resolved reopened recorded number numbers".split(" ")
|
|
@@ -604,7 +619,9 @@ function emptyCounters() {
|
|
|
604
619
|
prospectiveSkipped: 0,
|
|
605
620
|
placeholderSkipped: 0,
|
|
606
621
|
qualifiedRefsSkipped: 0,
|
|
607
|
-
unresolvableRefs: 0
|
|
622
|
+
unresolvableRefs: 0,
|
|
623
|
+
namespacedSkipped: 0,
|
|
624
|
+
outsideRepoSkipped: 0
|
|
608
625
|
};
|
|
609
626
|
}
|
|
610
627
|
async function checkTextClaims(env, file, opts, counters) {
|
|
@@ -642,9 +659,12 @@ async function checkTextClaims(env, file, opts, counters) {
|
|
|
642
659
|
confidence: "high"
|
|
643
660
|
});
|
|
644
661
|
}
|
|
645
|
-
const { paths, prospective, placeholder } = extractPathClaims(file.text
|
|
662
|
+
const { paths, prospective, placeholder, namespaced } = extractPathClaims(file.text, {
|
|
663
|
+
namespaces: opts.treatNamespacedPrefixes
|
|
664
|
+
});
|
|
646
665
|
counters.prospectiveSkipped += prospective.length;
|
|
647
666
|
counters.placeholderSkipped += placeholder.length;
|
|
667
|
+
counters.namespacedSkipped += namespaced.length;
|
|
648
668
|
const missing = [];
|
|
649
669
|
for (const claim of paths) {
|
|
650
670
|
if (await env.pathResolves(claim)) examined.push({ kind: "path", value: claim, exists: true });
|
|
@@ -654,6 +674,11 @@ async function checkTextClaims(env, file, opts, counters) {
|
|
|
654
674
|
const gitignored = new Set((ignoredOut ?? "").split("\n").filter(Boolean));
|
|
655
675
|
let pathFindings = 0;
|
|
656
676
|
for (const claim of missing) {
|
|
677
|
+
if (opts.rootedFirstSegments && !opts.rootedFirstSegments.has(claim.split("/")[0] ?? claim)) {
|
|
678
|
+
counters.outsideRepoSkipped += 1;
|
|
679
|
+
examined.push({ kind: "path", value: claim, exists: null });
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
657
682
|
if (gitignored.has(claim)) {
|
|
658
683
|
counters.gitignoredSkipped += 1;
|
|
659
684
|
examined.push({ kind: "path", value: claim, exists: null });
|
|
@@ -755,4 +780,4 @@ function checkDecisionRefs(file, ledger, opts, counters) {
|
|
|
755
780
|
return { findings, examined };
|
|
756
781
|
}
|
|
757
782
|
|
|
758
|
-
export { KNOWN_EXTENSIONS, PATH_TOKEN_RE, buildTruthEnv, checkDecisionRefs, checkDocRefs, checkTextClaims, emptyCounters, listInstructionFiles, listStateDocuments, loadDecisionLedger, meetsFailOn, packageManagerUsage, parseFailOnTier, rankFindings, stateFreshnessLens };
|
|
783
|
+
export { KNOWN_EXTENSIONS, NAMESPACE_IDENT, NAMESPACE_STOP, PATH_TOKEN_RE, buildTruthEnv, checkDecisionRefs, checkDocRefs, checkTextClaims, emptyCounters, listInstructionFiles, listStateDocuments, loadDecisionLedger, meetsFailOn, packageManagerUsage, parseFailOnTier, rankFindings, stateFreshnessLens };
|