diff --git a/scripts/fetch-project-docs.mjs b/scripts/fetch-project-docs.mjs index 84b7ba7..14c7fce 100644 --- a/scripts/fetch-project-docs.mjs +++ b/scripts/fetch-project-docs.mjs @@ -15,16 +15,38 @@ import { // network: delegates exact-head reads to repository_public_projection // storage: generated projectDocs JSON plus last-known-good snapshot // authority: source repositories own document content; this website owns presentation only -// failure: same-head last-known-good data may be retained with fallback=true; non-public repositories never reuse cached document content +// failure: same-head last-known-good data may be retained per repository with fallback=true (online and OFFLINE=1); a different, unknown, or missing head, a missing snapshot entry, and a missing/unreadable/corrupt snapshot all emit unavailable projections; non-public repositories never reuse cached document content // === END BOUNDARIES === const GENERATED_REPOS = 'src/_data/generated/repos.json'; const GENERATED_OUT = 'src/_data/generated/projectDocs.json'; const SNAPSHOT_OUT = 'src/_data/snapshots/project-docs.last-known-good.json'; +// Returns { state, data, reason }: state is 'present', 'missing' (ENOENT), 'unreadable' +// (any other read error), or 'corrupt' (the file exists but is not a JSON object). async function readSnapshot() { - try { return JSON.parse(await readFile(SNAPSHOT_OUT, 'utf8')); } - catch { return null; } + let text; + try { text = await readFile(SNAPSHOT_OUT, 'utf8'); } + catch (error) { + if (error?.code === 'ENOENT') return { state: 'missing', data: null, reason: null }; + return { state: 'unreadable', data: null, reason: error?.code || error?.message || 'unknown read error' }; + } + try { + const data = JSON.parse(text); + if (!data || typeof data !== 'object' || Array.isArray(data)) { + return { state: 'corrupt', data: null, reason: 'snapshot root is not a JSON object' }; + } + return { state: 'present', data, reason: null }; + } catch (error) { + return { state: 'corrupt', data: null, reason: error?.message || 'JSON parse error' }; + } +} + +function snapshotBoundary(snapshot) { + if (snapshot.state === 'missing') return 'no last-known-good project documentation snapshot exists'; + if (snapshot.state === 'unreadable') return 'the last-known-good project documentation snapshot could not be read (' + snapshot.reason + ')'; + if (snapshot.state === 'corrupt') return 'the last-known-good project documentation snapshot is corrupt and was ignored (' + snapshot.reason + ')'; + return null; } function unavailableProjection(repo, message) { @@ -39,8 +61,8 @@ function unavailableProjection(repo, message) { documentation: { readme: null, documents: [], - projectedDocumentCount: 0, - projectedBytes: 0, + projectedDocumentCount: null, + projectedBytes: null, hmmm: [message] }, msdmd: null, @@ -50,23 +72,57 @@ function unavailableProjection(repo, message) { }; } -async function offlineWithoutSnapshot() { +// Offline projection is keyed by the current repos.json, never by the snapshot: a snapshot +// entry is reused only when its headSha equals the repository's current head_sha. +async function offlineProjection(snapshot) { const repoData = JSON.parse(await readFile(GENERATED_REPOS, 'utf8')); + const boundary = snapshotBoundary(snapshot); + const snapshotByRepo = snapshot.data?.byRepository && typeof snapshot.data.byRepository === 'object' + ? snapshot.data.byRepository + : {}; const byRepository = {}; + let fallbackCount = 0; + let unavailableCount = 0; + for (const repo of repoData.repositories || []) { - byRepository[repo.name] = unavailableProjection( - repo, - 'OFFLINE=1 and no last-known-good project documentation snapshot exists; repository document content remains unavailable.' - ); + const prior = snapshotByRepo[repo.name]; + if (!boundary && prior && !prior.unavailable && repo.head_sha && prior.headSha === repo.head_sha) { + fallbackCount += 1; + byRepository[repo.name] = { + ...prior, + fallback: true, + hmmm: [...new Set([...(prior.hmmm || []), 'OFFLINE=1: retained the same-head last-known-good documentation projection.'])] + }; + continue; + } + let message; + if (boundary) { + message = 'OFFLINE=1 and ' + boundary + '; repository document content remains unavailable.'; + } else if (!repo.head_sha) { + message = 'OFFLINE=1 and the current repository head is unknown; snapshot documentation cannot be matched to it and remains unavailable.'; + } else if (!prior || prior.unavailable) { + message = 'OFFLINE=1 and the last-known-good snapshot holds no observed documentation for this repository; document content remains unavailable.'; + } else { + message = 'OFFLINE=1 and the last-known-good snapshot was observed at a different head than the current repository head; stale documentation was not reused.'; + } + unavailableCount += 1; + byRepository[repo.name] = unavailableProjection(repo, message); + } + + const hmmm = []; + if (boundary) { + hmmm.push('OFFLINE=1: ' + boundary + '; emitted metadata-only unavailable projections without inventing document content.'); + } else { + hmmm.push('OFFLINE=1: reused ' + fallbackCount + ' same-head last-known-good projection(s); ' + unavailableCount + ' repository projection(s) are unavailable.'); } return { schema: 'interdependency.project-documentation-map/0.1.0', organization: 'The-Interdependency', - snapshotAt: null, - fallback: false, - fallbackCount: 0, + snapshotAt: boundary ? null : snapshot.data.snapshotAt ?? null, + fallback: fallbackCount > 0, + fallbackCount, byRepository, - hmmm: ['OFFLINE=1: no last-known-good project documentation snapshot exists; emitted metadata-only unavailable projections without inventing document content.'] + hmmm }; } @@ -74,22 +130,18 @@ async function main() { await mkdir('src/_data/generated', { recursive: true }); await mkdir('src/_data/snapshots', { recursive: true }); - const previous = await readSnapshot(); + const snapshot = await readSnapshot(); if (process.env.OFFLINE === '1') { - const fallback = previous - ? { - ...previous, - fallback: true, - hmmm: [...new Set([...(previous.hmmm || []), 'OFFLINE=1: displaying the last-known-good project documentation snapshot.'])] - } - : await offlineWithoutSnapshot(); - await writeFile(GENERATED_OUT, JSON.stringify(fallback, null, 2) + '\n'); - console.log(previous ? 'project-docs fallback' : 'project-docs metadata-only offline'); + const offline = await offlineProjection(snapshot); + await writeFile(GENERATED_OUT, JSON.stringify(offline, null, 2) + '\n'); + console.log(snapshot.state === 'present' + ? 'project-docs offline · ' + offline.fallbackCount + ' same-head fallback' + : 'project-docs metadata-only offline (' + snapshot.state + ' snapshot)'); return; } const repoData = JSON.parse(await readFile(GENERATED_REPOS, 'utf8')); - const previousByRepo = previous?.byRepository || {}; + const previousByRepo = snapshot.data?.byRepository || {}; const byRepository = {}; let fallbackCount = 0; diff --git a/src/_data/builder.json b/src/_data/builder.json index 7bdad6f..76a8179 100644 --- a/src/_data/builder.json +++ b/src/_data/builder.json @@ -33,5 +33,12 @@ "time": "10:33:29-07:00", "model": "GPT-5.6 Sol", "body": "Zero is an observation. Unavailable is a boundary. Interfaces become unreliable when they substitute the former for the latter simply because zero is easier to render." + }, + { + "id": "2026-09-26-a-copy-is-not-a-witness", + "date": "2026-09-26", + "time": "12:21:51-07:00", + "model": "hmmm: Grok Bot executor (xAI); the exact runtime model version is not exposed to this runtime", + "body": "A copy remembers what was seen, not when it stopped being true. Reusing it is honest only while the thing it describes has not moved; once the head changes, the copy is testimony about somewhere else. Saying \"unavailable\" is less satisfying than showing an old answer, but it keeps the page from speaking for a moment it did not witness." } ] diff --git a/src/projects/repo.njk b/src/projects/repo.njk index dfa6b6b..5cdf42b 100644 --- a/src/projects/repo.njk +++ b/src/projects/repo.njk @@ -55,8 +55,12 @@ title: "Project: {{ repo.name }}"

Documentation

{% if repoDocs and repoDocs.unavailable %}

Repository documentation was not observed for this build. No README or document absence is inferred from this unavailable projection.

- {% else %} + {% elif repoDocs and repoDocs.documentation and repoDocs.fallback %} +

README and Markdown documentation are retained from a last-known-good projection observed at the same repository head this site build records. A live refresh can replace this view with the repository's current public HEAD for this browser session.

+ {% elif repoDocs and repoDocs.documentation %}

README and Markdown documentation are copied from the exact repository head recorded by this site build. A live refresh can replace this view with the repository's current public HEAD for this browser session.

+ {% else %} +

Repository documentation is unavailable for this build: no documentation projection was emitted for this repository. No README or document absence is inferred.

{% endif %}
@@ -89,7 +93,7 @@ title: "Project: {{ repo.name }}"

hmmm

{% endif %} {% else %} -

hmmm

No project documentation projection was available for this build.

+

hmmm

Repository documentation is unavailable for this build: no documentation projection was emitted, so no document-content observation is claimed.

{% endif %}
@@ -99,8 +103,8 @@ title: "Project: {{ repo.name }}"
Repository
{{ repo.name }}
Consumed HEAD
{% if repoDocs and repoDocs.headSha %}{{ repoDocs.headSha }}{% else %}hmmm{% endif %}
Default branch
{{ repo.default_branch or 'hmmm' }}
-
Projected documents
{% if repoDocs and repoDocs.unavailable %}hmmm{% elif repoDocs and repoDocs.documentation %}{{ repoDocs.documentation.projectedDocumentCount }}{% else %}hmmm{% endif %}
-
Projection mode
{% if repoDocs and repoDocs.unavailable %}unavailable{% elif repoDocs and repoDocs.fallback %}same-head last-known-good fallback{% else %}exact-head build observation{% endif %}
+
Projected documents
{% if repoDocs and repoDocs.unavailable %}hmmm{% elif repoDocs and repoDocs.documentation and repoDocs.documentation.projectedDocumentCount is number %}{{ repoDocs.documentation.projectedDocumentCount }}{% else %}hmmm{% endif %}
+
Projection mode
{% if repoDocs and repoDocs.unavailable %}unavailable{% elif repoDocs and repoDocs.documentation and repoDocs.fallback %}same-head last-known-good fallback{% elif repoDocs and repoDocs.documentation %}exact-head build observation{% else %}unavailable{% endif %}
diff --git a/tests/generated-site.test.mjs b/tests/generated-site.test.mjs index 13e855c..84e281e 100644 --- a/tests/generated-site.test.mjs +++ b/tests/generated-site.test.mjs @@ -316,7 +316,7 @@ test('generated site exposes the AI context through redundant machine discovery' test('By the builder renders a collapsible date-time-model tree', async () => { const html = await readFile('_site/by-the-builder/index.html', 'utf8'); assert.match(html, /
/); - assert.match(html, /Builder journal · 5 entries<\/summary>/); + assert.match(html, /Builder journal · 6 entries<\/summary>/); assert.match(html, /
/); assert.match(html, /2026-09-23 · 23:38:45-07:00/); assert.match(html, /GPT-5\.6 Sol/); @@ -324,6 +324,8 @@ test('By the builder renders a collapsible date-time-model tree', async () => { assert.match(html, /2026-09-24 · 18:39:58-07:00/); assert.match(html, /2026-09-25-unavailable-is-not-zero/); assert.match(html, /2026-09-25 · 10:33:29-07:00/); + assert.match(html, /2026-09-26-a-copy-is-not-a-witness/); + assert.match(html, /2026-09-26 · 12:21:51-07:00/); assert.match(html, /legacy model record unavailable/); }); diff --git a/tests/offline-project-snapshot.test.mjs b/tests/offline-project-snapshot.test.mjs index 92e292a..82466ac 100644 --- a/tests/offline-project-snapshot.test.mjs +++ b/tests/offline-project-snapshot.test.mjs @@ -1,11 +1,12 @@ import test from 'node:test'; import assert from 'node:assert/strict'; import { execFile } from 'node:child_process'; -import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; +import { copyFile, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { promisify } from 'node:util'; +import Eleventy from '@11ty/eleventy'; const execFileAsync = promisify(execFile); const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); @@ -82,29 +83,105 @@ test('offline refresh preserves reviewed active fields and excludes archived rep }); -test('clean offline project documentation refresh emits unavailable observations without inventing absence', async () => { +const headA = 'a'.repeat(40); +const headB = 'b'.repeat(40); + +function repoRow(name, headSha) { + return { + name, + slug: name, + html_url: 'https://github.com/The-Interdependency/' + name, + category: 'Test', + status: 'implemented', + default_branch: 'main', + head_sha: headSha, + head_committed_at: '2026-09-25T00:00:00Z', + relationships: [], + hmmm: [] + }; +} + +function observedProjection(name, headSha) { + return { + schema: 'interdependency.repository-public-projection/0.1.0', + repository: 'The-Interdependency/' + name, + name, + defaultBranch: 'main', + headSha, + headCommittedAt: '2026-09-20T00:00:00Z', + refreshedAt: '2026-09-20T00:00:00Z', + documentation: { + readme: { + path: 'README.md', + content: '# Observed ' + name + '\n\nSnapshot README body.', + sourceUrl: 'https://github.com/The-Interdependency/' + name + '/blob/' + headSha + '/README.md' + }, + documents: [{ path: 'docs/guide.md', bytes: 42, sourceUrl: 'https://github.com/The-Interdependency/' + name + '/blob/' + headSha + '/docs/guide.md' }], + projectedDocumentCount: 1, + projectedBytes: 42, + hmmm: [] + }, + msdmd: null, + fallback: false, + hmmm: [] + }; +} + +// Usage: runs the real project-docs refresh with OFFLINE=1 in an isolated working tree. +// snapshot: undefined (no file), a string (raw file bytes), or an object (serialized JSON). +async function runOfflineProjectDocs(repositories, snapshot) { const root = await mkdtemp(join(tmpdir(), 'interdependency-project-docs-offline-')); - try { - await mkdir(join(root, 'src', '_data', 'generated'), { recursive: true }); + await mkdir(join(root, 'src', '_data', 'generated'), { recursive: true }); + await writeFile(join(root, 'src', '_data', 'generated', 'repos.json'), JSON.stringify({ repositories }, null, 2)); + if (snapshot !== undefined) { + await mkdir(join(root, 'src', '_data', 'snapshots'), { recursive: true }); await writeFile( - join(root, 'src', '_data', 'generated', 'repos.json'), - JSON.stringify({ - repositories: [{ - name: 'ucns', - default_branch: 'main', - head_sha: '0123456789abcdef0123456789abcdef01234567', - head_committed_at: '2026-09-25T00:00:00Z' - }] - }, null, 2) + join(root, 'src', '_data', 'snapshots', 'project-docs.last-known-good.json'), + typeof snapshot === 'string' ? snapshot : JSON.stringify(snapshot, null, 2) ); + } + const result = await execFileAsync(process.execPath, [projectDocsScriptPath], { + cwd: root, + env: { ...process.env, OFFLINE: '1', GITHUB_TOKEN: '' } + }); + const generated = JSON.parse(await readFile(join(root, 'src', '_data', 'generated', 'projectDocs.json'), 'utf8')); + return { root, stdout: result.stdout, generated }; +} - const result = await execFileAsync(process.execPath, [projectDocsScriptPath], { - cwd: root, - env: { ...process.env, OFFLINE: '1', GITHUB_TOKEN: '' } - }); - assert.match(result.stdout, /metadata-only offline/); +// Usage: renders the real src/projects/repo.njk through Eleventy with a minimal layout and +// stand-in filters, returning rendered HTML keyed by repository slug. +async function renderProjectPages(root, repositories, projectDocs) { + const input = join(root, 'render-src'); + await mkdir(join(input, 'projects'), { recursive: true }); + await mkdir(join(input, '_includes', 'layouts'), { recursive: true }); + await mkdir(join(input, '_data', 'generated'), { recursive: true }); + await copyFile(join(repositoryRoot, 'src', 'projects', 'repo.njk'), join(input, 'projects', 'repo.njk')); + await writeFile(join(input, '_includes', 'layouts', 'base.njk'), '{{ content | safe }}\n'); + await writeFile(join(input, '_data', 'generated', 'repos.json'), JSON.stringify({ repositories })); + await writeFile(join(input, '_data', 'generated', 'projectDocs.json'), JSON.stringify(projectDocs)); + await writeFile(join(input, '_data', 'generated', 'orgMsdmd.json'), JSON.stringify({ repositories: [] })); + const configPath = join(root, 'render.config.mjs'); + await writeFile(configPath, `export default function (eleventyConfig) { + eleventyConfig.addFilter('where', (items, key, value) => (items || []).filter(item => item?.[key] === value)); + eleventyConfig.addFilter('statusClass', value => 'status-' + String(value || 'hmmm')); + eleventyConfig.addFilter('projectDocMarkdown', document => '
' + String(document?.content || '') + '
'); +} +`); + const eleventy = new Eleventy(input, join(root, 'render-out'), { quietMode: true, configPath }); + const pages = await eleventy.toJSON(); + return Object.fromEntries(pages.map(page => [page.url.replace(/^\/projects\/|\/$/g, ''), page.content])); +} - const generated = JSON.parse(await readFile(join(root, 'src', '_data', 'generated', 'projectDocs.json'), 'utf8')); +function provenance(html, field) { + const match = html.match(new RegExp('data-project-doc-' + field + '>([^<]*)<')); + return match ? match[1] : null; +} + +test('clean offline project documentation refresh emits unavailable observations without inventing absence', async () => { + const repos = [repoRow('ucns', '0123456789abcdef0123456789abcdef01234567')]; + const { root, stdout, generated } = await runOfflineProjectDocs(repos); + try { + assert.match(stdout, /metadata-only offline \(missing snapshot\)/); assert.equal(generated.fallback, false); assert.equal(generated.fallbackCount, 0); assert.equal(generated.snapshotAt, null); @@ -116,17 +193,123 @@ test('clean offline project documentation refresh emits unavailable observations assert.equal(projection.headCommittedAt, null); assert.equal(projection.documentation.readme, null); assert.deepEqual(projection.documentation.documents, []); - assert.equal(projection.documentation.projectedDocumentCount, 0); + assert.equal(projection.documentation.projectedDocumentCount, null); assert.match(projection.documentation.hmmm.join(' '), /document content remains unavailable/); - const projectTemplate = await readFile(join(repositoryRoot, 'src', 'projects', 'repo.njk'), 'utf8'); - assert.match(projectTemplate, /Repository documentation was not observed for this build/); - assert.match(projectTemplate, /no document-content observation is claimed/); - assert.match( - projectTemplate, - /Projected documents<\/dt>
\{% if repoDocs and repoDocs\.unavailable %\}hmmm\{% elif repoDocs and repoDocs\.documentation %\}\{\{ repoDocs\.documentation\.projectedDocumentCount \}\}/ - ); - assert.match(projectTemplate, /repoDocs and repoDocs\.unavailable %\}unavailable/); + const pages = await renderProjectPages(root, repos, generated); + const html = pages.ucns; + assert.match(html, /Repository documentation was not observed for this build/); + assert.match(html, /no document-content observation is claimed/); + assert.doesNotMatch(html, /No root README\.md/); + assert.doesNotMatch(html, /copied from the exact repository head/); + assert.equal(provenance(html, 'count'), 'hmmm'); + assert.equal(provenance(html, 'mode'), 'unavailable'); + } finally { + await rm(root, { recursive: true, force: true }); + } +}); + +test('offline snapshot entry at the matching head is retained per repository as same-head fallback', async () => { + const repos = [repoRow('ucns', headA)]; + const snapshot = { snapshotAt: '2026-09-20T00:00:00Z', fallback: false, byRepository: { ucns: observedProjection('ucns', headA) }, hmmm: [] }; + const { root, stdout, generated } = await runOfflineProjectDocs(repos, snapshot); + try { + assert.match(stdout, /1 same-head fallback/); + assert.equal(generated.fallback, true); + assert.equal(generated.fallbackCount, 1); + assert.equal(generated.snapshotAt, '2026-09-20T00:00:00Z'); + const projection = generated.byRepository.ucns; + assert.equal(projection.fallback, true); + assert.equal(projection.headSha, headA); + assert.equal(projection.unavailable, undefined); + + const html = (await renderProjectPages(root, repos, generated)).ucns; + assert.match(html, /Snapshot README body\./); + assert.match(html, /retained from a last-known-good projection observed at the same repository head/); + assert.equal(provenance(html, 'head'), headA); + assert.equal(provenance(html, 'count'), '1'); + assert.equal(provenance(html, 'mode'), 'same-head last-known-good fallback'); + assert.doesNotMatch(html, /exact-head build observation/); + } finally { + await rm(root, { recursive: true, force: true }); + } +}); + +test('offline snapshot entry at a stale head is not reused and renders unavailable, not absence', async () => { + const repos = [repoRow('ucns', headB)]; + const snapshot = { snapshotAt: '2026-09-20T00:00:00Z', byRepository: { ucns: observedProjection('ucns', headA) }, hmmm: [] }; + const { root, generated } = await runOfflineProjectDocs(repos, snapshot); + try { + assert.equal(generated.fallback, false); + assert.equal(generated.fallbackCount, 0); + const projection = generated.byRepository.ucns; + assert.equal(projection.unavailable, true); + assert.equal(projection.headSha, null); + assert.equal(projection.documentation.projectedDocumentCount, null); + assert.match(projection.hmmm.join(' '), /different head/); + + const html = (await renderProjectPages(root, repos, generated)).ucns; + assert.doesNotMatch(html, /Snapshot README body\./); + assert.doesNotMatch(html, /No root README\.md/); + assert.doesNotMatch(html, /exact-head build observation/); + assert.match(html, /different head than the current repository head/); + assert.equal(provenance(html, 'head'), 'hmmm'); + assert.equal(provenance(html, 'count'), 'hmmm'); + assert.equal(provenance(html, 'mode'), 'unavailable'); + } finally { + await rm(root, { recursive: true, force: true }); + } +}); + +test('offline mixed snapshot keeps the matching repository and marks the missing repository unavailable', async () => { + const repos = [repoRow('present-project', headA), repoRow('missing-project', headB)]; + const snapshot = { snapshotAt: '2026-09-20T00:00:00Z', byRepository: { 'present-project': observedProjection('present-project', headA) }, hmmm: [] }; + const { root, generated } = await runOfflineProjectDocs(repos, snapshot); + try { + assert.deepEqual(Object.keys(generated.byRepository).sort(), ['missing-project', 'present-project']); + assert.equal(generated.fallbackCount, 1); + assert.equal(generated.byRepository['present-project'].fallback, true); + assert.equal(generated.byRepository['missing-project'].unavailable, true); + assert.match(generated.byRepository['missing-project'].hmmm.join(' '), /holds no observed documentation for this repository/); + + const pages = await renderProjectPages(root, repos, generated); + assert.equal(provenance(pages['present-project'], 'mode'), 'same-head last-known-good fallback'); + assert.equal(provenance(pages['missing-project'], 'mode'), 'unavailable'); + assert.equal(provenance(pages['missing-project'], 'count'), 'hmmm'); + assert.doesNotMatch(pages['missing-project'], /copied from the exact repository head/); + } finally { + await rm(root, { recursive: true, force: true }); + } +}); + +test('corrupt offline snapshot is reported as corrupt, not as absent, and reuses nothing', async () => { + const repos = [repoRow('ucns', headA)]; + const { root, stdout, generated } = await runOfflineProjectDocs(repos, '{"byRepository": {"ucns": '); + try { + assert.match(stdout, /metadata-only offline \(corrupt snapshot\)/); + assert.equal(generated.fallback, false); + assert.equal(generated.snapshotAt, null); + assert.match(generated.hmmm.join(' '), /snapshot is corrupt and was ignored/); + assert.doesNotMatch(generated.hmmm.join(' '), /no last-known-good project documentation snapshot exists/); + const projection = generated.byRepository.ucns; + assert.equal(projection.unavailable, true); + assert.match(projection.hmmm.join(' '), /corrupt and was ignored/); + } finally { + await rm(root, { recursive: true, force: true }); + } +}); + +test('repository with no emitted documentation projection renders unavailable rather than exact-head', async () => { + const root = await mkdtemp(join(tmpdir(), 'interdependency-project-docs-render-')); + try { + const repos = [repoRow('ucns', headA)]; + const html = (await renderProjectPages(root, repos, { byRepository: {} })).ucns; + assert.match(html, /no documentation projection was emitted/); + assert.doesNotMatch(html, /copied from the exact repository head/); + assert.doesNotMatch(html, /No root README\.md/); + assert.equal(provenance(html, 'head'), 'hmmm'); + assert.equal(provenance(html, 'count'), 'hmmm'); + assert.equal(provenance(html, 'mode'), 'unavailable'); } finally { await rm(root, { recursive: true, force: true }); }