clone

a personal forge on plain git: static pages, stacked-diff reviews, signed local ci, repo sites and releases

Insights exports give a build's reason as push or other

cat committed 43f0ccc
builds.parquet carried each build's reason, and the reasons private and removed said when a repo went private or away. The exports now say push, or other for everything else; the lake keeps the real reason. lib/insights.ts and the README also say what happens to a repo's facts when it goes public again: they are published with it, from while it was private too, as its whole history is then. Scenario: the lake has private and removed, the exports only push and other.
commit
43f0cccc60bb3c7c724c54b683f5b1a2feb998e8
parent
0573918c003ef590d27ecf8b263d254e423aa824
author
cat <admin@dev.site>
ci
✓ passed in 158s, signed by cat
kind
feat risk score 1.9 of 3, Jev's estimate
review
#30 Security: sign-in, invites, owner pages, lake, caps and the edge
ci attestation
forge-attestation 1
type ci
commit 43f0cccc60bb3c7c724c54b683f5b1a2feb998e8
tree 4f974807cf02ffdd39c05ba26a97b8c852333e3d
script .forge/ci 8d2000a416f8160bcf710d98b72af9eb76287f58
result pass
exit 0
started 2026-10-19T07:55:30Z
duration 158s
runner (not shown here; refs/notes/ci has it)
system Darwin 25.5.0 arm64
env host
log sha256:10a4b062811e966fdb94e6838f97323ec073a6c50f10ed9f44d089afbc8116ae 323 lines
|pushed wip/i18n
|a03c9af running .forge/ci: greet.sh: say what it is
|  | sh: /bin/sh
|  | ok   greet
|a03c9af pass in 0s, signed
|pushed main
|remote: review #4: /dami/greet/reviews/4/
|pushed wip/i18n
|a9d186f running .forge/ci: wave at the world
|  | sh: /bin/sh
|  | FAIL greet : got 'hello, world o/', want 'hello, world'
|a9d186f fail in 0s, signed
|forge: 1 commit(s) did not pass
|remote: review #6: /dami/greet/reviews/6/
|pushed ana/wave
|fa42011 running .forge/ci: update the test for the wave
|  | sh: /bin/sh
|  | ok   greet
|fa42011 pass in 0s, signed
|remote: review #6: /dami/greet/reviews/6/
|pushed ana/wave
|warning: You appear to have cloned an empty repository.
|site home: deployed aebef68 -> /sites/ana/dotfiles/home/
|created ana/notes
|remote: review #1: /ana/notes/reviews/1/
|pushed ana/todo
|landing #1 A todo list: ana/todo -> main
|debd0fb running .forge/ci: web, server and Python versions of greet
|  | sh: /bin/sh
|  | ok   greet
|debd0fb pass in 0s, signed
|pushed main
|98ef3b8 running .forge/ci: messages: notes for the later regions
|  | sh: /bin/sh
|  | ok   greet
|98ef3b8 pass in 0s, signed
|remote: review #7: /dami/greet/reviews/7/
|pushed dami/regions
|created dami/forge
|warning: You appear to have cloned an empty repository.
|site guide: mkdir -p guide/fonts && cp site/assets/fonts/*.woff2 guide/fonts/
|site guide: deployed d6e2009 -> /sites/dami/forge/guide/
|(node:73466) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time
|(Use `node --trace-warnings ...` to show where the warning was created)
|built ana/dotfiles in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www
|(node:73643) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time
|(Use `node --trace-warnings ...` to show where the warning was created)
|built ana/notes in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www
|(node:73830) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time
|(Use `node --trace-warnings ...` to show where the warning was created)
|built dami/forge in 0s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www
|(node:74010) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time
|(Use `node --trace-warnings ...` to show where the warning was created)
|built dami/greet in 1s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www
|(node:74752) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time
|(Use `node --trace-warnings ...` to show where the warning was created)
|built - in 0s -> /var/folders/b4/mv8w4c8j0zj0_mldppxdbdw00000gn/T/forge-ci.Z7x7e8/wt/demo/root/.forge/www
|235 of 235 pages render the same without 11ty
|guide: 8 files, links ok
|ok

Signature: good, cat

3 files changed, +35 -3
MREADME.md5++++-
Mlib/insights.ts10++++++++--
Atest/scenarios/insights-build-reason.sh23+++++++++++++++++++++++
M README.md +4 -1
M lib/insights.ts +8 -2
@@ -9,7 +9,13 @@
99 // whose readers alone see them. publishInsights also puts them straight into1010 // the live pages after each run, since the pages fetch them and need no1111 // rebuild. The forge's cover public repos only: a private repo's facts are12-// in no public export.12+// in no public export. A repo made public again publishes its facts from13+// while it was private too, as it publishes all of its history then (the14+// secret check of ssh public reads every commit first); a removed one's15+// leave the lake (forge repo rm, lib/lake.ts forget), so a new repo of the16+// same name starts with none. A build's reason is "push" or "other" in the17+// exports: the others (private, removed, profile...) would say when a repo18+// went private or away.1319 import fs from 'node:fs';1420 import path from 'node:path';1521 import { listRepos } from './lake-sources.ts';
@@ -94,7 +100,7 @@ async function exportScope(lake: Lake, s: Scope, publicRepos: string[]): Promise
94100 await lake.run(`COPY (${sql}) TO ${lit(path.join(tmp, file))} (FORMAT parquet, COMPRESSION zstd)`);95101 };96102 await copy('events.parquet', `SELECT t, repo, type, "user", review, refs, ms, rendered FROM lake.events WHERE ${s.where} ORDER BY t`);97- await copy('builds.parquet', `SELECT id, "at", code, reason, scope, ms_total, ms_data, ms_render, rss_mb, written, linked FROM lake.builds WHERE ${s.builds} ORDER BY "at"`);103+ await copy('builds.parquet', `SELECT id, "at", code, CASE reason WHEN 'push' THEN 'push' ELSE 'other' END AS reason, scope, ms_total, ms_data, ms_render, rss_mb, written, linked FROM lake.builds WHERE ${s.builds} ORDER BY "at"`);98104 await copy('reviews.parquet', `99105 SELECT repo, review, kind, ts, "user", rev, sha, base, tree, branch, title, NULL::BOOLEAN AS observed FROM lake.reviews WHERE ${s.where}100106 UNION ALL SELECT repo, review, kind, ts, "user", NULL, sha, NULL, NULL, NULL, NULL, observed FROM lake.review_ends WHERE ${s.where}
A test/scenarios/insights-build-reason.sh +23 -0