omakit 0.6.10 → 0.6.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omakit",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "description": "Tested plumbing, the marketplace's own checks, and a disposable Omarchy to test in.",
5
5
  "license": "MIT",
6
6
  "author": "Maarten Tolhuijs",
@@ -1,5 +1,5 @@
1
1
  {
2
- "commit": "517b87d52ba42465a12ab5722e979ed6f8d27805",
3
- "recordedAt": "2026-10-01T02:52:49.108Z",
2
+ "commit": "134073bfe9da1073721c0a7e9905c15dea0c7176",
3
+ "recordedAt": "2026-10-01T04:06:29.378Z",
4
4
  "how": "Written by `node tools/blocks/record-commit.mjs` in the release workflow before `npm pack`, so a packaged omakit, which has no Git checkout, still names the commit its block files come from. In a checkout this file is null and `git rev-parse HEAD` is the source; a package with null here was packed without the release step, and `omakit add` refuses to stamp a header it cannot name."
5
5
  }
@@ -19,6 +19,8 @@ local commit through the transport seam the marketplace tests itself
19
19
  | `plugin.mjs` | The root files the submission contract needs, and the declared plugin identity. |
20
20
  | `agent-control.mjs` | The recursive agent-control warning, and its remedy. |
21
21
  | `review-cost.mjs` | The advisory review-cost verdict, shared account discovery, and path classification between dated validated snapshots. M4 and M9 carry its evidence. |
22
+ | `measure-registry-figures.mjs` | Reproduces the registry figures of M4 and M6 at the pin: `baselineFigures()` recorded per pin in `docs/evidence/registry-figures.json`, newest first, and rendered from that record into the literal block of `tests/unit/registry-figures.test.mjs`, the M4 block and M6 row of `docs/MEASUREMENTS.md` and the Registry facts row of `docs/UPSTREAM_CONTRACT.md`. Without `--write` it names the files not yet rendered from the record (exit 1 when one is stale); with it, it writes them. Every outcome, capability and rule name it prints is a key of the registry's data. |
23
+ | `measure-pin-grades.mjs` | Reproduces M7's grades: each marketplace commit in a range that touched `scripts/` or the form, graded against its parent by the shipped `comparePin()` and `pinFreshness()` three ways (tree, 0.6.6's rule; blob, 0.6.7's; value, the shipped one), every request answered from a local clone of the marketplace history, so it fetches and runs nothing. |
22
24
  | `measure-review-cost.mjs` | Reproduces M9 across the open update population at live marketplace HEAD, with compare sources and explicit skipped reasons in JSON. |
23
25
  | `issue.mjs` | Renders the issue the way the form would, then has the marketplace's own parser judge it. |
24
26
  | `submit.mjs` | Assembles every check with its measured reason, and withholds the body when a blocking check fails. Three outcomes: `ready` (the body), `refused` (a blocking check failed) and `listed` (the plugin is already listed by its own repository: `identity.available` passes with the listing's record, the five body checks are omitted rather than drawn as waiting, no body exists on purpose, and `listing` carries the listed commit against the local one and the form to use for a newer commit). Decides the category and tags after the registry: a listed plugin, own or taken, is asked for neither; an unlisted one without them is asked through `ask.mjs` at a terminal, and is a usage error otherwise. Ends with `reproduce`, the command line that repeats the run without asking. Under `--offline` the validation-commit check is `skipped`, not passed: verdict `skipped`, listed under `skipped` and not `unknown`, never blocking, and the READY line says "1 check skipped (--offline)". |
@@ -0,0 +1,119 @@
1
+ // M7 reproduction: every marketplace commit in a range that touched a pinned
2
+ // path other than the two data files (scripts/ and the form), graded as a
3
+ // change from its parent, the parent as the pin and the commit as HEAD,
4
+ // under the three comparisons doctor has shipped: tree, 0.6.6's (any such
5
+ // path's tree or blob id moved); blob, 0.6.7's (pinFreshness without the
6
+ // text-read values); value, the one since 0.6.10 (pinFreshness as it
7
+ // ships). It runs the shipped comparePin() and pinFreshness() against a
8
+ // local clone of the marketplace's history (a blob-filtered clone is
9
+ // enough) and answers each request the comparison would make from that
10
+ // clone, counting it: nothing is fetched by this script and nothing from
11
+ // the clone is run. Measured on 2026-10-01: over the seven such commits
12
+ // since 38060f89, the three grades it gives equal those of the v0.6.6 and
13
+ // v0.6.7 tags' own code (docs/evidence/pin-freshness/2026-10-01-grades.json).
14
+ import { execFileSync } from "node:child_process"
15
+ import { resolve } from "node:path"
16
+ import { pathToFileURL } from "node:url"
17
+ import { PIN_PATHS, POLICY_MODULE, pinnedReadSet, policyConstants } from "./pin.mjs"
18
+ import { LIVE_PATHS } from "./registry.mjs"
19
+ import { comparePin, pinFreshness } from "./doctor.mjs"
20
+
21
+ /** The pinned paths a grade can turn on: PIN_PATHS less the two data files read live. */
22
+ export const GRADED_PATHS = Object.freeze(PIN_PATHS.map((pattern) => pattern.replace(/^\/|\/$/g, "")).filter((path) => !LIVE_PATHS.includes(path)))
23
+
24
+ /**
25
+ * The two kinds of request comparePin() makes, answered from the clone: a
26
+ * tree read by `git ls-tree`, a file's text at a commit by `git show`.
27
+ * `requests` lists each, in order.
28
+ */
29
+ export function cloneTransport(clone) {
30
+ const git = (...args) => execFileSync("git", ["-C", clone, ...args], { timeout: 60_000, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 })
31
+ const requests = []
32
+ const fetchJson = async (url) => {
33
+ requests.push(url)
34
+ const sha = String(url).match(/\/git\/trees\/([0-9a-f]{40})$/)?.[1]
35
+ if (!sha) throw new Error(`not a tree read at an object id: ${url}`)
36
+ const tree = git("ls-tree", sha).split("\n").filter(Boolean).map((line) => {
37
+ const [meta, path] = line.split("\t")
38
+ const [, type, id] = meta.split(" ")
39
+ return { path, type, sha: id }
40
+ })
41
+ return { sha, tree, truncated: false }
42
+ }
43
+ const fetchText = async (url) => {
44
+ requests.push(url)
45
+ const [, commit, path] = String(url).match(/\/([0-9a-f]{40})\/(.+)$/) || []
46
+ if (!commit) throw new Error(`not a file read at a commit: ${url}`)
47
+ return git("show", `${commit}:${path}`)
48
+ }
49
+ return { git, requests, fetchJson, fetchText }
50
+ }
51
+
52
+ /** One change graded three ways, with the read set resolved at `pin` and what the value comparison says of it. */
53
+ export async function gradeChange(clone, pin, head) {
54
+ const transport = cloneTransport(clone)
55
+ const reads = pinnedReadSet(clone, undefined, (path) => transport.git("show", `${pin}:${path}`))
56
+ const identity = { commit: pin, ...policyConstants(transport.git("show", `${pin}:${POLICY_MODULE}`)) }
57
+ const comparison = await comparePin({ pinDir: clone, headCommit: head, pinCommit: pin, fetchJson: transport.fetchJson, fetchText: transport.fetchText, reads })
58
+ const at = { commit: head, branch: null }
59
+ const value = pinFreshness(identity, at, comparison)
60
+ const blob = pinFreshness(identity, at, { ...comparison, textReads: {} })
61
+ return {
62
+ readSet: reads.map((read) => read.path),
63
+ requests: transport.requests.length,
64
+ tree: value.evidence.pinned.length ? "advice" : "ok",
65
+ blob: blob.state,
66
+ value: value.state,
67
+ detail: value.detail,
68
+ effective: value.evidence.effective,
69
+ textReads: value.evidence.textReads,
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Every commit in `since..until` that touched GRADED_PATHS, oldest first,
75
+ * each graded by gradeChange() against its first parent, and how many of
76
+ * those that touched a file in the read set each comparison grades advice.
77
+ */
78
+ export async function measurePinGrades({ clone, since, until }) {
79
+ const git = (...args) => execFileSync("git", ["-C", clone, ...args], { timeout: 60_000, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 })
80
+ const range = `${git("rev-parse", since).trim()}..${git("rev-parse", until).trim()}`
81
+ const listed = git("log", "--reverse", "--format=%H%x09%cI%x09%s", range, "--", ...GRADED_PATHS).split("\n").filter(Boolean)
82
+ const commits = []
83
+ for (const line of listed) {
84
+ const [commit, committedAt, subject] = line.split("\t")
85
+ const parent = git("rev-parse", `${commit}^`).trim()
86
+ const touched = git("log", "-1", "--format=", "--name-only", commit, "--", ...GRADED_PATHS).split("\n").filter(Boolean)
87
+ const { readSet, ...graded } = await gradeChange(clone, parent, commit)
88
+ commits.push({ commit, committedAt, subject, parent, touched, inReadSet: touched.filter((path) => readSet.includes(path)), ...graded })
89
+ }
90
+ const touching = commits.filter((row) => row.inReadSet.length)
91
+ const advice = (rows, rule) => rows.filter((row) => row[rule] === "advice").length
92
+ return {
93
+ measurement: "M7",
94
+ measuredAt: new Date().toISOString(),
95
+ range,
96
+ gradedPaths: GRADED_PATHS,
97
+ method: "Each commit in the range that touched a graded path, graded against its first parent by the shipped comparePin() and pinFreshness(), every request answered from the local clone: tree is 0.6.6's rule (a graded path's object id moved), blob 0.6.7's (pinFreshness without text-read values), value the shipped grade.",
98
+ commits,
99
+ touchingReadSet: touching.length,
100
+ advice: { tree: advice(touching, "tree"), blob: advice(touching, "blob"), value: advice(touching, "value") },
101
+ adviceOverAll: { commits: commits.length, tree: advice(commits, "tree"), blob: advice(commits, "blob"), value: advice(commits, "value") },
102
+ }
103
+ }
104
+
105
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
106
+ const args = process.argv.slice(2)
107
+ const option = (name) => {
108
+ const index = args.indexOf(name)
109
+ return index >= 0 ? args[index + 1] : undefined
110
+ }
111
+ const clone = option("--clone")
112
+ const since = option("--since")
113
+ const until = option("--until") || "HEAD"
114
+ if (!clone || !since || args.length !== (option("--until") ? 6 : 4)) {
115
+ process.stderr.write("usage: node tools/marketplace/measure-pin-grades.mjs --clone <marketplace clone> --since <commit> [--until <commit>]\n")
116
+ process.exit(2)
117
+ }
118
+ process.stdout.write(`${JSON.stringify(await measurePinGrades({ clone: resolve(clone), since, until }), null, 2)}\n`)
119
+ }
@@ -0,0 +1,160 @@
1
+ // M4 and M6 reproduction: the registry figures at the pin, recorded per pin
2
+ // in docs/evidence/registry-figures.json and rendered from that one record
3
+ // into the three places that cite them: the literal block in
4
+ // tests/unit/registry-figures.test.mjs, the M4 block and the M6 row of
5
+ // docs/MEASUREMENTS.md, and the Registry facts row of
6
+ // docs/UPSTREAM_CONTRACT.md. Measured on the 0.6.10 bump: the same
7
+ // figures were retyped by hand in nine files, and four of them
8
+ // (preflight.mjs, MARKETPLACE.md, HOW.md, INSPECT_DESIGN.md) no test reads.
9
+ // Without --write it prints the record entry for the pin and names each
10
+ // file that is not yet rendered from it; with --write it records the entry
11
+ // and rewrites those files.
12
+ //
13
+ // Every name in the output (outcomes, capabilities, finding rules) is a key
14
+ // of the registry's own data, never typed here.
15
+ import { execFileSync } from "node:child_process"
16
+ import { readFileSync, writeFileSync } from "node:fs"
17
+ import { join, resolve } from "node:path"
18
+ import { fileURLToPath, pathToFileURL } from "node:url"
19
+ import { MARKETPLACE_PIN, requirePin } from "./pin.mjs"
20
+ import { baselineFigures, figure } from "./registry.mjs"
21
+
22
+ const ROOT = resolve(fileURLToPath(new URL("../..", import.meta.url)))
23
+
24
+ export const RECORD_PATH = "docs/evidence/registry-figures.json"
25
+ export const TEST_PATH = "tests/unit/registry-figures.test.mjs"
26
+ export const MEASUREMENTS_PATH = "docs/MEASUREMENTS.md"
27
+ export const CONTRACT_PATH = "docs/UPSTREAM_CONTRACT.md"
28
+
29
+ const TEST_BLOCK = /\/\/ registry-figures:begin[^\n]*\n[\s\S]*?\/\/ registry-figures:end\n/
30
+ const M4_BLOCK = /<!-- registry-figures:m4 -->\n[\s\S]*?<!-- \/registry-figures:m4 -->\n/
31
+ const M6_ROW = /^\| Listed sources whose validated commit was superseded at least once \|.*\|$/m
32
+ const CONTRACT_ROW = /^\| Registry facts \|.*\|$/m
33
+
34
+ /** The record entry for the pinned checkout: its commit, when it was committed, and baselineFigures() over it. */
35
+ export function entryAtPin(pinDir) {
36
+ const commit = execFileSync("git", ["-C", pinDir, "rev-parse", "HEAD"], { timeout: 60_000, encoding: "utf8" }).trim()
37
+ const committedAt = execFileSync("git", ["-C", pinDir, "log", "-1", "--format=%cI", "HEAD"], { timeout: 60_000, encoding: "utf8" }).trim()
38
+ return { commit, committedAt: new Date(committedAt).toISOString().replace(/\.000Z$/, "Z"), figures: baselineFigures({ pinDir }) }
39
+ }
40
+
41
+ /** The record with `entry` first, replacing an entry for the same commit; the others keep their order, newest first. */
42
+ export function upsert(record, entry) {
43
+ return { ...record, pins: [entry, ...record.pins.filter((pin) => pin.commit !== entry.commit)] }
44
+ }
45
+
46
+ /** A table of counts, largest first and by name on a tie: the order every list here is printed in. */
47
+ const ranked = (table) => Object.entries(table).sort(([a, x], [b, y]) => y - x || a.localeCompare(b))
48
+ const short = (commit) => commit.slice(0, 8)
49
+ const when = (iso) => `${iso.slice(0, 10)} ${iso.slice(11, 16)} UTC`
50
+ const percent = (part, whole) => ((part / whole) * 100).toFixed(1)
51
+
52
+ /** Prose wrapped at 76 columns, the way the documents are written. */
53
+ function wrap(text, width = 76) {
54
+ const lines = []
55
+ let line = ""
56
+ for (const word of text.split(" ")) {
57
+ if (line && line.length + 1 + word.length > width) {
58
+ lines.push(line)
59
+ line = word
60
+ } else {
61
+ line = line ? `${line} ${word}` : word
62
+ }
63
+ }
64
+ if (line) lines.push(line)
65
+ return lines.join("\n")
66
+ }
67
+
68
+ /** The literal block the figures test holds the pin to. */
69
+ export function renderTest(text, record) {
70
+ const [current] = record.pins
71
+ const block = [
72
+ `// registry-figures:begin rendered from ${RECORD_PATH} by \`node tools/marketplace/measure-registry-figures.mjs --write\`; change the record, not this block`,
73
+ `const AT_PIN = Object.freeze(${JSON.stringify({ commit: current.commit, figures: current.figures }, null, 2)})`,
74
+ "// registry-figures:end",
75
+ "",
76
+ ].join("\n")
77
+ if (!TEST_BLOCK.test(text)) throw new Error(`${TEST_PATH} has no registry-figures block to render into`)
78
+ return text.replace(TEST_BLOCK, () => block)
79
+ }
80
+
81
+ /** M4's figures and the earlier pins' table, and M6's superseded row. */
82
+ export function renderMeasurements(text, record) {
83
+ const [current, ...earlier] = record.pins
84
+ const f = current.figures
85
+ const outcomes = ranked(f.outcomes)
86
+ const lines = [
87
+ "<!-- registry-figures:m4 -->",
88
+ wrap(`From \`registry.json\` at the pin (\`${short(current.commit)}\`, ${when(current.committedAt)}): ${figure(f.sources)} listed sources, of which ${figure(f.withBaseline)} carry a recorded baseline (the rest were listed before the baseline existed or have no record):`),
89
+ "",
90
+ "| Outcome | Count |",
91
+ "| --- | --- |",
92
+ ...outcomes.map(([name, n]) => `| \`${name}\` | ${figure(n)} |`),
93
+ `| Findings ever recorded, total | ${figure(f.findingsTotal)} (${ranked(f.findings).map(([name, n]) => `\`${name}\` ${figure(n)}`).join(", ")}) |`,
94
+ "",
95
+ wrap(`Capabilities recorded: ${ranked(f.capabilities).map(([name, n]) => `${name} ${figure(n)}`).join(", ")}.`),
96
+ ]
97
+ if (earlier.length) {
98
+ lines.push(
99
+ "",
100
+ "At the earlier pins, counted the same way from the same two files:",
101
+ "",
102
+ `| Pin | Sources | With a baseline | ${outcomes.map(([name]) => `\`${name}\``).join(" | ")} |`,
103
+ `| --- | --- | --- | ${outcomes.map(() => "---").join(" | ")} |`,
104
+ ...earlier.map((pin) => `| \`${short(pin.commit)}\` (${when(pin.committedAt)}) | ${figure(pin.figures.sources)} | ${figure(pin.figures.withBaseline)} | ${outcomes.map(([name]) => figure(pin.figures.outcomes[name] || 0)).join(" | ")} |`),
105
+ )
106
+ }
107
+ lines.push("<!-- /registry-figures:m4 -->", "")
108
+ const superseded = (pin) => `${figure(pin.figures.superseded.sources)} of ${figure(pin.figures.sources)}, ${percent(pin.figures.superseded.sources, pin.figures.sources)}%, ${figure(pin.figures.superseded.commits)} commits`
109
+ const row = `| Listed sources whose validated commit was superseded at least once | ${figure(f.superseded.sources)} of ${figure(f.sources)} (${percent(f.superseded.sources, f.sources)}%) at pin \`${short(current.commit)}\`, ${figure(f.superseded.commits)} superseded commits, one source revalidated ${f.superseded.most} times${earlier.length ? ` (${earlier.map((pin) => `at pin \`${short(pin.commit)}\`: ${superseded(pin)}`).join("; ")})` : ""} |`
110
+ if (!M4_BLOCK.test(text)) throw new Error(`${MEASUREMENTS_PATH} has no registry-figures:m4 block to render into`)
111
+ if (!M6_ROW.test(text)) throw new Error(`${MEASUREMENTS_PATH} has no superseded row in M6 to render into`)
112
+ return text.replace(M4_BLOCK, () => lines.join("\n")).replace(M6_ROW, () => row)
113
+ }
114
+
115
+ /** The Registry facts row of the pinned-checkout table. */
116
+ export function renderContract(text, record) {
117
+ const f = record.pins[0].figures
118
+ const row = `| Registry facts | ${figure(f.listingValidated)} sources with \`listingValidatedCommit\`; ${figure(f.withBaseline)} with an \`automatedSecurityBaseline\` record (${ranked(f.outcomes).map(([name, n]) => `${figure(n)} ${name}`).join(", ")}); ${figure(f.catalogPlugins)} catalog plugin ids; ${figure(f.retiredIds)} retired ids; ${figure(f.superseded.sources)} sources (${percent(f.superseded.sources, f.sources)}%) with at least one superseded validated commit, ${figure(f.superseded.commits)} superseded commits in all |`
119
+ if (!CONTRACT_ROW.test(text)) throw new Error(`${CONTRACT_PATH} has no Registry facts row to render into`)
120
+ return text.replace(CONTRACT_ROW, () => row)
121
+ }
122
+
123
+ /** Each file the record renders into, as it is and as the record would have it. */
124
+ export function renderAll(record, read = (path) => readFileSync(join(ROOT, path), "utf8")) {
125
+ return [
126
+ { path: RECORD_PATH, now: read(RECORD_PATH), next: `${JSON.stringify(record, null, 2)}\n` },
127
+ { path: TEST_PATH, now: read(TEST_PATH), next: renderTest(read(TEST_PATH), record) },
128
+ { path: MEASUREMENTS_PATH, now: read(MEASUREMENTS_PATH), next: renderMeasurements(read(MEASUREMENTS_PATH), record) },
129
+ { path: CONTRACT_PATH, now: read(CONTRACT_PATH), next: renderContract(read(CONTRACT_PATH), record) },
130
+ ]
131
+ }
132
+
133
+ /**
134
+ * The pin's entry recorded and every file rendered from the record. With
135
+ * `write`, the files that differ are written; without, nothing is. Returns
136
+ * the entry and, per file, whether it was (or would be) rewritten.
137
+ */
138
+ export function measureRegistryFigures({ repoRoot = ROOT, pinDir = requirePin(repoRoot).dir, write = false } = {}) {
139
+ const entry = entryAtPin(pinDir)
140
+ if (entry.commit !== MARKETPLACE_PIN.commit) throw new Error(`the checkout at ${pinDir} is at ${entry.commit}, not the pin ${MARKETPLACE_PIN.commit}`)
141
+ const read = (path) => readFileSync(join(repoRoot, path), "utf8")
142
+ const record = upsert(JSON.parse(read(RECORD_PATH)), entry)
143
+ const files = renderAll(record, read)
144
+ if (write) {
145
+ for (const file of files.filter((candidate) => candidate.next !== candidate.now)) writeFileSync(join(repoRoot, file.path), file.next)
146
+ }
147
+ return { entry, files: Object.fromEntries(files.map((file) => [file.path, file.next === file.now ? "current" : write ? "written" : "stale"])) }
148
+ }
149
+
150
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
151
+ const args = process.argv.slice(2)
152
+ const unknown = args.filter((arg) => arg !== "--write")
153
+ if (unknown.length) {
154
+ process.stderr.write(`usage: node tools/marketplace/measure-registry-figures.mjs [--write]; not ${unknown.join(" ")}\n`)
155
+ process.exit(2)
156
+ }
157
+ const result = measureRegistryFigures({ write: args.includes("--write") })
158
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`)
159
+ if (!args.includes("--write") && Object.values(result.files).includes("stale")) process.exitCode = 1
160
+ }
@@ -5,7 +5,7 @@
5
5
  // It fetches only what omakit reads. The marketplace at this commit is 325 MB,
6
6
  // of which 168 MB is preview imagery and 151 MB is history, and omakit reads
7
7
  // twenty files out of it, sixteen of them under scripts/ (PIN_READS). A
8
- // blob-filtered, sparsely checked out fetch of just those paths is 15 MB and
8
+ // blob-filtered, sparsely checked out fetch of just those paths was 15 MB and
9
9
  // takes 2 seconds instead of 17; at pin b441b4f0 (2026-10-01) the same fetch
10
10
  // was 23 MB on disk in 3.1 seconds. PIN_PATHS below is the whole list, and
11
11
  // tests/unit/pin.test.mjs fails if any module starts reading a path outside
@@ -32,6 +32,9 @@ export const MARKETPLACE_PIN = Object.freeze({
32
32
  commitSubject: "Add LINE for Omarchy plugin (#9470)",
33
33
  baselineVersion: "3",
34
34
  enforcementMode: "selective",
35
+ // What a fresh sparse fetch of this commit measured on disk, for the one
36
+ // line `omakit pin` prints before it fetches. A pin bump re-measures it.
37
+ fetchedMb: 23,
35
38
  })
36
39
 
37
40
  /**
@@ -179,10 +182,12 @@ export function unfollowedImports(pinDir, reads = pinnedReadSet(pinDir)) {
179
182
  * a package (`sharp`) is not followed: PIN_PATHS does not fetch it, so
180
183
  * omakit could not read it. Measured at pins b7b29654 and b441b4f0: 16 of
181
184
  * the 34 files under scripts/, 10 opened by omakit and 6 imported by those.
185
+ * `text` reads one file's text by its path; it defaults to the checkout in
186
+ * `pinDir`, and measure-pin-grades.mjs hands in a commit's blobs instead.
182
187
  *
183
188
  * @returns {{ path: string, imported: boolean, via: string|null }[]}
184
189
  */
185
- export function pinnedReadSet(pinDir, reads = PIN_READS) {
190
+ export function pinnedReadSet(pinDir, reads = PIN_READS, text = (path) => readFileSync(join(pinDir, path), "utf8")) {
186
191
  const set = new Map()
187
192
  const queue = []
188
193
  for (const read of reads) {
@@ -191,13 +196,13 @@ export function pinnedReadSet(pinDir, reads = PIN_READS) {
191
196
  }
192
197
  while (queue.length) {
193
198
  const from = queue.shift()
194
- let text
199
+ let source
195
200
  try {
196
- text = readFileSync(join(pinDir, from), "utf8")
201
+ source = text(from)
197
202
  } catch (error) {
198
203
  throw new PinError(`cannot read ${from} from the pinned checkout at ${pinDir}: ${error.message}`)
199
204
  }
200
- for (const match of text.matchAll(RELATIVE_IMPORT)) {
205
+ for (const match of source.matchAll(RELATIVE_IMPORT)) {
201
206
  const path = posix.normalize(posix.join(posix.dirname(from), match[1]))
202
207
  if (!path.startsWith("scripts/") || set.has(path)) continue
203
208
  set.set(path, { path, imported: true, via: from })
@@ -232,7 +237,7 @@ function pinMigration(repoRoot, env = process.env) {
232
237
  if (!existsSync(join(oldDir, ".git")) || existsSync(newDir)) return null
233
238
  const remedy = `mkdir -p -- ${shellQuote(dirname(newDir))} && mv -- ${shellQuote(oldDir)} ${shellQuote(newDir)}`
234
239
  return new PinError(
235
- `the marketplace pin is still at the old in-repository location ${oldDir}; the user-writable location ${newDir} does not exist. Omakit will not move the measured 15 MB checkout without you.`,
240
+ `the marketplace pin is still at the old in-repository location ${oldDir}; the user-writable location ${newDir} does not exist. Omakit will not move the checkout (${pinDiskUsage(oldDir, env)}) without you.`,
236
241
  { code: "marketplace-pin-migration-required", remedy },
237
242
  )
238
243
  }
@@ -409,7 +414,7 @@ function populatePin(dir, log) {
409
414
  mkdirSync(dir, { recursive: true })
410
415
  execFileSync("git", ["init", "-q", dir], { timeout: 60_000, encoding: "utf8" })
411
416
  git(dir, ["remote", "add", "origin", MARKETPLACE_PIN.repository])
412
- log({ state: "fetching", text: `fetching the pinned marketplace checkout, ${MARKETPLACE_PIN.commit.slice(0, 7)}, about 15 MB` })
417
+ log({ state: "fetching", text: `fetching the pinned marketplace checkout, ${MARKETPLACE_PIN.commit.slice(0, 7)}, about ${MARKETPLACE_PIN.fetchedMb} MB` })
413
418
  git(dir, ["config", "core.sparseCheckout", "true"])
414
419
  mkdirSync(join(dir, ".git/info"), { recursive: true })
415
420
  writeFileSync(join(dir, ".git/info/sparse-checkout"), `${PIN_PATHS.join("\n")}\n`)
@@ -524,7 +529,7 @@ export function ensurePin(repoRoot, log = () => {}, env = process.env, { populat
524
529
  export function pinDiskUsage(dir, env = process.env) {
525
530
  // -H follows a symlink given on the command line (POSIX; GNU's -D). Measured
526
531
  // without it: a checkout reached through a symlink reported 0.0 MB, the size
527
- // of the link, while the directory behind it was 15 MB.
532
+ // of the link, while the directory behind it was 15 MB (at pin 38060f89).
528
533
  //
529
534
  // The total is read whether or not du exited 0. du exits 1 when a file it
530
535
  // listed is gone by the time it reaches it, and still prints the total.
@@ -373,12 +373,13 @@ export function idUniverse(options = {}) {
373
373
  /**
374
374
  * The recorded baseline over every listed source, counted from registry.json at
375
375
  * the pin. This is the one place the figures cited by `baseline.preflight` and
376
- * docs/MEASUREMENTS.md M4 come from; tests/unit/registry-figures.test.mjs pins
377
- * the values, so a pin bump changes the printed number rather than leaving a
378
- * stale literal behind.
376
+ * docs/MEASUREMENTS.md M4 come from; measure-registry-figures.mjs records
377
+ * them per pin and renders the test and the two documents that cite them, so
378
+ * a pin bump changes the printed number rather than leaving a stale literal
379
+ * behind.
379
380
  *
380
381
  * @param {{ repoRoot?: string, pinDir?: string }} [options]
381
- * @returns {{ sources: number, withBaseline: number, outcomes: Record<string, number>,
382
+ * @returns {{ sources: number, listingValidated: number, withBaseline: number, outcomes: Record<string, number>,
382
383
  * capabilities: Record<string, number>, findings: Record<string, number>,
383
384
  * findingsTotal: number, superseded: { sources: number, commits: number, most: number },
384
385
  * retiredIds: number, catalogPlugins: number }}
@@ -393,11 +394,13 @@ export function baselineFigures(options = {}) {
393
394
  const capabilities = {}
394
395
  const findings = {}
395
396
  let withBaseline = 0
397
+ let listingValidated = 0
396
398
  let findingsTotal = 0
397
399
  let supersededSources = 0
398
400
  let supersededCommits = 0
399
401
  let most = 0
400
402
  for (const source of sources) {
403
+ if (typeof source?.listingValidatedCommit === "string" && source.listingValidatedCommit) listingValidated += 1
401
404
  const baseline = source?.automatedSecurityBaseline
402
405
  if (baseline && typeof baseline.outcome === "string") {
403
406
  withBaseline += 1
@@ -415,6 +418,7 @@ export function baselineFigures(options = {}) {
415
418
  }
416
419
  return {
417
420
  sources: sources.length,
421
+ listingValidated,
418
422
  withBaseline,
419
423
  outcomes,
420
424
  capabilities,