Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .eleventy.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import { installMathRenderer } from './scripts/markdown-math.mjs';
// then: the website publishes the generated presentation view without becoming a second source of repo canon
// class: evidence
// since: 2026-08-14
//
// id: website_org_msdmd_has_one_public_projection_copy
// given: commit-pinned repo-owned msdmd collections are joined into the generated organization map
// then: the website publishes that generated evidence artifact unchanged and uses it for the visual map without becoming repository metadata authority
// class: evidence
// since: 2026-08-16
// === END CONTRACTS ===
// Usage: run `npm run build`; Eleventy emits the static site, copies root machine instructions, and preserves dependency-free public reading paths.

Expand All @@ -30,6 +36,7 @@ export default function configureEleventy(eleventyConfig) {
'src/assets': 'assets',
'src/_data/gonol_relationship_display.json': 'assets/data/gonol-relationship-display-v1.json',
'src/_data/generated/sitrep.json': 'assets/data/sitrep.json',
'src/_data/generated/orgMsdmd.json': 'assets/data/org-msdmd.json',
'CNAME': 'CNAME',
'llms.txt': 'llms.txt',
'artifacts/four-cuts-1.html': 'artifacts/four-cuts/index.html',
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
"type": "module",
"scripts": {
"dev": "npm run refresh:data && eleventy --serve",
"refresh:data": "npm run refresh:canon && npm run refresh:github && npm run refresh:sitrep && npm run refresh:textbook && npm run refresh:works",
"refresh:data": "npm run refresh:canon && npm run refresh:github && npm run refresh:msdmd && npm run refresh:sitrep && npm run refresh:textbook && npm run refresh:works",
"refresh:canon": "node scripts/fetch-canon.mjs && node scripts/parse-canon.mjs",
"refresh:github": "node scripts/fetch-github-org.mjs",
"refresh:msdmd": "node scripts/fetch-org-msdmd.mjs",
"refresh:sitrep": "node scripts/fetch-sitrep.mjs",
"refresh:textbook": "node scripts/fetch-textbook.mjs",
"research:enrich": "node scripts/enrich-citations.mjs",
Expand All @@ -20,7 +21,7 @@
"validate": "node scripts/validate-content.mjs && node scripts/verify-generated-routes.mjs && node scripts/verify-article-canon.mjs",
"build": "npm run validate && eleventy && pagefind --site _site && node scripts/write-build-info.mjs",
"pretest": "node scripts/prepare-tests.mjs",
"test": "node --test tests/aicontext.test.mjs tests/edcm-mathematics.test.mjs tests/gonol-relationships.test.mjs tests/post-merge-reconciliation.test.mjs tests/llms-build.test.mjs tests/canon-parser.test.mjs tests/canon-integrity.test.mjs tests/textbook-integrity.test.mjs tests/math-rendering.test.mjs tests/narratives.test.mjs tests/offline-project-snapshot.test.mjs tests/repo-coverage.test.mjs tests/research-ledger.test.mjs tests/works-registry.test.mjs tests/site-contract.test.mjs tests/sitrep.test.mjs",
"test": "node --test tests/aicontext.test.mjs tests/edcm-mathematics.test.mjs tests/gonol-relationships.test.mjs tests/org-msdmd.test.mjs tests/post-merge-reconciliation.test.mjs tests/llms-build.test.mjs tests/canon-parser.test.mjs tests/canon-integrity.test.mjs tests/textbook-integrity.test.mjs tests/math-rendering.test.mjs tests/narratives.test.mjs tests/offline-project-snapshot.test.mjs tests/repo-coverage.test.mjs tests/research-ledger.test.mjs tests/works-registry.test.mjs tests/site-contract.test.mjs tests/sitrep.test.mjs",
"test:generated": "node --test tests/generated-site.test.mjs tests/human-ui-generated.test.mjs tests/textbook-generated.test.mjs tests/math-generated.test.mjs && node tests/links.test.mjs",
"test:browser": "playwright test",
"test:e2e": "playwright test tests/site.spec.mjs",
Expand Down
53 changes: 47 additions & 6 deletions scripts/fetch-github-org.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ import yaml from 'js-yaml';

// === MODULE_BUILD ===
// id: organization_project_map
// purpose: Build public project pages from GitHub facts plus reviewed repository manifests or central overrides.
// purpose: Build public project pages from GitHub facts plus reviewed repository manifests or central overrides, recording exact default-branch heads for reproducible downstream consumers.
// entrypoint: npm run refresh:github
// tests: tests/repo-coverage.test.mjs, tests/offline-project-snapshot.test.mjs
// === END MODULE_BUILD ===
// === BOUNDARIES ===
// id: github_public_metadata
// network: reads only allowlisted HTTPS GitHub API endpoints; optional token raises rate limits
// network: reads only allowlisted HTTPS GitHub API and raw.githubusercontent.com endpoints; optional token raises API rate limits
// storage: writes generated and last-known-good JSON snapshots
// failure: preserves last-known-good data with fallback=true, including reviewed editorial fields
// === END BOUNDARIES ===
// Usage: run `npm run refresh:github`; the generated repo snapshot records each exact default-branch head so later collectors can fetch commit-pinned source without repeating GitHub API lookups.

const org = 'The-Interdependency';
const githubApiOrigin = 'https://api.github.com';
const rawGithubOrigin = 'https://raw.githubusercontent.com';
const headers = ['-H', 'Accept: application/vnd.github+json', '-H', 'X-GitHub-Api-Version: 2022-11-28'];
if (process.env.GITHUB_TOKEN) headers.push('-H', `Authorization: Bearer ${process.env.GITHUB_TOKEN}`);

Expand All @@ -26,6 +28,11 @@ function githubApiUrl(pathname, search = {}) {
return url;
}

function rawGithubUrl(repoName, commit, path) {
const parts = [org, repoName, commit, ...String(path).split('/')].map(encodeURIComponent);
return new URL(`/${parts.join('/')}`, rawGithubOrigin);
}

function getJson(target) {
const url = target instanceof URL ? target : new URL(target);
if (url.protocol !== 'https:' || url.origin !== githubApiOrigin) {
Expand All @@ -38,19 +45,45 @@ function getJson(target) {
));
}

function getText(target) {
const url = target instanceof URL ? target : new URL(target);
if (url.protocol !== 'https:' || url.origin !== rawGithubOrigin) {
throw new Error(`refusing non-raw-GitHub target: ${url.origin}`);
}
return execFileSync(
'curl',
['-fsSL', '--retry', '2', '--max-time', '20', url.href],
{ encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }
);
}

function normalizeRepoName(value) {
const name = String(value || '');
if (!/^[A-Za-z0-9_.-]{1,100}$/.test(name)) throw new Error(`invalid GitHub repository name: ${name}`);
return name;
}

function getManifest(repoName) {
function getHead(repoName, defaultBranch) {
try {
if (!defaultBranch) return { sha: null, committed_at: null };
const safeRepo = normalizeRepoName(repoName);
const response = getJson(githubApiUrl(
`/repos/${encodeURIComponent(org)}/${encodeURIComponent(safeRepo)}/contents/.interdependency/project.yml`
`/repos/${encodeURIComponent(org)}/${encodeURIComponent(safeRepo)}/commits/${encodeURIComponent(defaultBranch)}`
));
return yaml.load(Buffer.from(response.content || '', 'base64').toString('utf8')) || null;
return {
sha: response.sha || null,
committed_at: response.commit?.committer?.date || response.commit?.author?.date || null
};
} catch {
return { sha: null, committed_at: null };
Comment on lines +77 to +78

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not treat head lookup errors as absent heads

If the organization repository listing succeeds but an individual commits API request transiently fails, this catch converts the error to a normal null head while leaving the overall snapshot in non-fallback mode. The refresh then skips that repository's reviewed manifest, marks its msdmd collection missing, and overwrites both last-known-good snapshots with the degraded data; distinguish a genuinely headless repository from an API failure and preserve the prior entry or fail into fallback for the latter.

Useful? React with 👍 / 👎.

}
}

function getManifest(repoName, headSha) {
try {
if (!headSha) return null;
const safeRepo = normalizeRepoName(repoName);
return yaml.load(getText(rawGithubUrl(safeRepo, headSha, '.interdependency/project.yml'))) || null;
} catch {
return null;
}
Expand Down Expand Up @@ -91,7 +124,10 @@ try {

const repositories = rawRepos.map(repo => {
const repoName = normalizeRepoName(repo.name);
const manifest = fallback ? null : getManifest(repoName);
const head = fallback
? { sha: repo.head_sha || null, committed_at: repo.head_committed_at || null }
: getHead(repoName, repo.default_branch);
const manifest = fallback ? null : getManifest(repoName, head.sha);
const inheritedEditorial = fallback ? {
category: repo.category,
status: repo.status,
Expand All @@ -113,6 +149,9 @@ const repositories = rawRepos.map(repo => {
if (!editorial.status && !hmmm.includes('Project maturity has not been explicitly declared.')) {
hmmm.push('Project maturity has not been explicitly declared.');
}
if (!fallback && !head.sha) {
hmmm.push('Exact default-branch head was unavailable during this snapshot; commit-pinned downstream collection is suspended for this repository.');
}
return {
name: repoName,
slug: repoName.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
Expand All @@ -127,6 +166,8 @@ const repositories = rawRepos.map(repo => {
archived: Boolean(repo.archived),
fork: Boolean(repo.fork),
default_branch: repo.default_branch || null,
head_sha: head.sha,
head_committed_at: head.committed_at,
topics: Array.isArray(repo.topics) ? repo.topics : [],
license: repo.license?.spdx_id || repo.license || null,
language: repo.language || null,
Expand Down
Loading
Loading