Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
265 commits
Select commit Hold shift + click to select a range
6a4dd66
test(perf): reject benchmark input output alias
seonghobae Aug 20, 2026
a838dbe
fix(perf): preserve benchmark sample inputs
seonghobae Aug 20, 2026
fe61395
test(perf): reject hard-linked summary evidence aliases
seonghobae Aug 21, 2026
33d5c45
fix(perf): preserve hard-linked benchmark source evidence
seonghobae Aug 21, 2026
676555f
test(perf): prove oversized samples preflight whole-file reads
seonghobae Aug 21, 2026
72db249
fix(perf): bound benchmark sample reads before allocation
seonghobae Aug 21, 2026
9766bcf
test(perf): require immutable benchmark provenance
seonghobae Aug 21, 2026
738d3e7
feat(perf): bind summaries to immutable provenance
seonghobae Aug 21, 2026
864fa8b
test(perf): require strict UTF-8 benchmark evidence
seonghobae Aug 21, 2026
bc887c0
fix(perf): reject malformed UTF-8 benchmark evidence
seonghobae Aug 21, 2026
596c48e
test(perf): preflight invalid summary destinations
seonghobae Aug 21, 2026
f072e74
fix(perf): preflight benchmark output destinations
seonghobae Aug 21, 2026
3efb68c
test(perf): reject arbitrary benchmark metadata
seonghobae Aug 21, 2026
6cb6418
fix(perf): reject unsupported benchmark metadata
seonghobae Aug 21, 2026
ba35b28
test(perf): require explicit benchmark regression comparator
seonghobae Aug 21, 2026
9504ead
feat(perf): add explicit benchmark regression comparator
seonghobae Aug 21, 2026
f5439a1
test(perf): prove comparator rejects blocking FIFO inputs
seonghobae Aug 21, 2026
13c09c5
test(perf): prove summarizer rejects blocking FIFO inputs
seonghobae Aug 21, 2026
dbf5345
fix(perf): validate comparator inputs without blocking
seonghobae Aug 21, 2026
e98faee
fix(perf): validate sample inputs without blocking
seonghobae Aug 21, 2026
d820150
test(perf): reject dangling benchmark output symlinks
seonghobae Aug 21, 2026
42c9516
fix(perf): reject dangling benchmark output symlinks
seonghobae Aug 21, 2026
2b2f537
test(perf): fail closed on regression percentage overflow
seonghobae Aug 21, 2026
712cd9d
fix(perf): fail closed on regression percentage overflow
seonghobae Aug 21, 2026
1604f20
test(perf): require provenance-bound regression receipts
seonghobae Aug 21, 2026
ceac649
fix(perf): bind regression receipts to exact evidence
seonghobae Aug 21, 2026
4dc7984
test(perf): align comparator receipt contract
seonghobae Aug 21, 2026
36af472
test(perf): reject aliased summary destinations
seonghobae Aug 21, 2026
a869556
fix(perf): reject aliased summary outputs
seonghobae Aug 21, 2026
1902b63
test(perf): reject vacuous same-artifact comparisons
seonghobae Aug 21, 2026
a746787
fix(perf): reject same-artifact regression evidence
seonghobae Aug 22, 2026
8e32114
test(perf): use distinct artifacts in comparator receipts
seonghobae Aug 22, 2026
f6b87db
test(perf): reject private-looking benchmark evidence identifiers
seonghobae Aug 22, 2026
b6fef32
test(perf): keep hardware mismatch fixture privacy-safe
seonghobae Aug 22, 2026
4a7786c
fix(perf): constrain benchmark evidence identifiers
seonghobae Aug 22, 2026
37ec73e
fix(perf): validate comparison evidence identifiers
seonghobae Aug 22, 2026
142499d
test(perf): reject private-looking benchmark units
seonghobae Aug 22, 2026
7248c18
test(perf): reject private units at comparator boundary
seonghobae Aug 22, 2026
92eaeb1
fix(perf): constrain benchmark measurement units
seonghobae Aug 22, 2026
3fe89a3
fix(perf): validate comparator measurement units
seonghobae Aug 22, 2026
3e1f345
test(perf): require markdown measurement harness
seonghobae Aug 22, 2026
124e944
feat(perf): add bounded markdown runtime measurement
seonghobae Aug 22, 2026
a08eb09
test(perf): bind markdown measurements to measured artifact
seonghobae Aug 22, 2026
e29e569
test(perf): use exact measured module digests
seonghobae Aug 22, 2026
866ca00
fix(perf): verify measured markdown artifact provenance
seonghobae Aug 22, 2026
1ecdba3
test(perf): reject measurement output aliasing module
seonghobae Aug 22, 2026
b5373c9
fix(perf): preserve measured module from output writes
seonghobae Aug 22, 2026
4fb4f3f
test(perf): reject non-local file URL authorities
seonghobae Aug 22, 2026
2bcd1de
fix(perf): require local file URL authority
seonghobae Aug 22, 2026
398c16b
test(perf): redact measured module failures
seonghobae Aug 22, 2026
8369d42
fix(perf): redact measured module failures
seonghobae Aug 22, 2026
df31a76
test(perf): require deterministic demo chunking
seonghobae Aug 22, 2026
0ec9731
feat(perf): classify demo vendor chunks
seonghobae Aug 22, 2026
490795b
fix(perf): split oversized demo bundle
seonghobae Aug 22, 2026
84aab25
test(perf): require revision-evidence measurement harness
seonghobae Aug 22, 2026
1f64915
feat(perf): measure packed revision-evidence latency
seonghobae Aug 22, 2026
407b8a1
test(perf): reject symlinked summary inputs
seonghobae Aug 22, 2026
5882974
fix(perf): reject symlinked summary evidence
seonghobae Aug 22, 2026
24d05fd
test(perf): redact hostile revision result accessors
seonghobae Aug 22, 2026
10b071d
fix(perf): contain hostile revision result accessors
seonghobae Aug 22, 2026
286bc07
test(perf): define retained-memory settling RED contract
seonghobae Aug 22, 2026
ef33eba
feat(perf): analyze retained-memory settling
seonghobae Aug 22, 2026
e4cab92
test(perf): reject mismatched memory evidence profiles
seonghobae Aug 22, 2026
e671a5a
fix(perf): bind memory benchmark id to profile
seonghobae Aug 22, 2026
5a6944c
test(perf): reject inexact memory medians
seonghobae Aug 23, 2026
a1b5201
fix(perf): fail closed on inexact memory medians
seonghobae Aug 23, 2026
80c8bbb
test(perf): reject mismatched benchmark profiles
seonghobae Aug 23, 2026
dcf8b65
fix(perf): bind benchmark ids to document profiles
seonghobae Aug 23, 2026
b240eac
test(perf): reject mismatched sample profiles
seonghobae Aug 23, 2026
00b062e
fix(perf): bind sample ids to document profiles
seonghobae Aug 23, 2026
1a76294
test(perf): reject corpus output symlink escape
seonghobae Aug 23, 2026
abf7d89
fix(perf): protect corpus output paths
seonghobae Aug 23, 2026
4002bc4
test(perf): redact benchmark output path failures
seonghobae Aug 23, 2026
1528f0e
fix(perf): redact benchmark output path failures
seonghobae Aug 23, 2026
da69be6
test(perf): redact revision output path failures
seonghobae Aug 23, 2026
523c986
fix(perf): redact revision output path failures
seonghobae Aug 23, 2026
28a45ac
test(perf): redact summary output preparation failures
seonghobae Aug 23, 2026
d44925e
fix(perf): redact output directory preparation failures
seonghobae Aug 23, 2026
d454176
test(perf): redact Markdown output publication failures
seonghobae Aug 23, 2026
e066321
fix(perf): redact Markdown output publication failures
seonghobae Aug 23, 2026
0b724e0
test(perf): redact revision output publication failures
seonghobae Aug 23, 2026
12a48b4
fix(perf): redact revision output publication failures
seonghobae Aug 23, 2026
86a771e
test(perf): require single-command benchmark suite
seonghobae Aug 23, 2026
9a618bc
feat(perf): compose single-command benchmark suite
seonghobae Aug 23, 2026
c41f101
test(perf): reject symlink benchmark output directories
seonghobae Aug 23, 2026
18fe738
fix(perf): reject symlink suite output roots
seonghobae Aug 23, 2026
156b8e3
test(perf): reject symlink summary output directory
seonghobae Aug 23, 2026
52ba733
fix(perf): reject symlink summary directories
seonghobae Aug 23, 2026
bd3eb04
test(perf): reject symlinked summary ancestors
seonghobae Aug 23, 2026
3b722e4
fix(perf): reject symlinked summary ancestors
seonghobae Aug 23, 2026
eb15b2f
test(perf): reject symlinked suite ancestors
seonghobae Aug 23, 2026
0cfd5a9
fix(perf): reject symlinked suite ancestors
seonghobae Aug 23, 2026
f1adf74
test(perf): reject symlinked markdown output ancestors
seonghobae Aug 23, 2026
0ac8712
fix(perf): reject symlinked markdown output ancestors
seonghobae Aug 23, 2026
2bcf06c
test(perf): reject symlinked revision output ancestors
seonghobae Aug 23, 2026
2e9332e
fix(perf): reject symlinked revision output ancestors
seonghobae Aug 23, 2026
ea00fe9
fix(perf): preserve path-redacted summary failures
seonghobae Aug 23, 2026
dba7505
test(perf): reject symlinked sample input
seonghobae Aug 23, 2026
9afff91
fix(perf): reject symlinked summary sample input
seonghobae Aug 23, 2026
824561c
fix(perf): preserve nonregular input diagnostics
seonghobae Aug 23, 2026
a7b6bc9
test(perf): cover markdown input path privacy
seonghobae Aug 23, 2026
dd35f07
fix(perf): redact markdown input path errors
seonghobae Aug 23, 2026
1781400
test(perf): cover markdown module path privacy
seonghobae Aug 23, 2026
17bb601
fix(perf): redact markdown module path errors
seonghobae Aug 23, 2026
2d22587
test(perf): reproduce revision module path leak
seonghobae Aug 23, 2026
0547812
fix(perf): redact revision module path errors
seonghobae Aug 23, 2026
cecef7d
test(perf): reproduce revision input path leak
seonghobae Aug 23, 2026
f412c50
fix(perf): redact revision file-open path errors
seonghobae Aug 23, 2026
df1ac90
test(perf): reproduce existing-output alias path leaks
seonghobae Aug 23, 2026
9488aad
fix(perf): validate Markdown input before alias stat
seonghobae Aug 23, 2026
d2a7a1f
fix(perf): validate revision input before alias stat
seonghobae Aug 23, 2026
82155d3
test(perf): reproduce summary input path leak
seonghobae Aug 23, 2026
463f100
fix(perf): redact summary input inspection failures
seonghobae Aug 23, 2026
f4400a6
test(perf): expose retained-memory input path leakage
seonghobae Aug 23, 2026
5d1a62e
fix(perf): redact retained-memory input inspection failures
seonghobae Aug 23, 2026
6a6ee59
test(perf): expose comparator input path leakage
seonghobae Aug 23, 2026
00bdb5b
fix(perf): redact comparator input inspection failures
seonghobae Aug 23, 2026
45c6f41
test(perf): expose Office fixture output symlink overwrite
seonghobae Aug 23, 2026
e4d3478
fix(perf): fail closed on Office fixture output symlinks
seonghobae Aug 23, 2026
5fe6023
test(perf): expose Office fixture output directory symlinks
seonghobae Aug 23, 2026
7983e66
fix(perf): reject Office fixture output directory symlinks
seonghobae Aug 23, 2026
31dee74
test(perf): reject hard-linked Office fixture outputs
seonghobae Aug 23, 2026
233f81e
fix(perf): reject hard-linked Office fixture outputs
seonghobae Aug 23, 2026
cdd9e34
test(perf): expose summary output hard-link overwrite
seonghobae Aug 24, 2026
36d8830
fix(perf): reject hard-linked summary outputs
seonghobae Aug 24, 2026
2222364
chore(perf): preserve summary metadata formatting
seonghobae Aug 24, 2026
3ddee5a
fix(perf): preserve summary alias diagnostics
seonghobae Aug 24, 2026
399a67a
test(perf): expose producer output hard-link overwrite
seonghobae Aug 24, 2026
1b7da55
fix(perf): reject hard-linked Markdown output
seonghobae Aug 24, 2026
a48c1d4
fix(perf): reject hard-linked revision output
seonghobae Aug 24, 2026
2f94a6b
test(perf): require revision evidence in single-command suite
seonghobae Aug 24, 2026
49baff6
feat(perf): compose revision evidence in current benchmark suite
seonghobae Aug 24, 2026
2614a79
fix(perf): preserve measured-script argument order
seonghobae Aug 24, 2026
7ae8007
test(perf): keep suite symlink regression on current CLI
seonghobae Aug 24, 2026
eb6e8ac
test(perf): require atomic suite evidence publication
seonghobae Aug 24, 2026
0af333b
fix(perf): remove partial suite evidence on failure
seonghobae Aug 24, 2026
d609faa
test(perf): require packed artifact benchmark provenance
seonghobae Aug 24, 2026
a49ea9d
fix(perf): bind suite to packed npm artifact
seonghobae Aug 24, 2026
f0c9d8f
test(perf): reject mislabeled benchmark runtime provenance
seonghobae Aug 24, 2026
0c9f3f3
fix(perf): attest active benchmark runtime
seonghobae Aug 24, 2026
5c8f6f8
test(perf): bind suite manifest to run provenance
seonghobae Aug 24, 2026
946c715
fix(perf): bind suite manifest to run provenance
seonghobae Aug 24, 2026
413b0f3
test(perf): attest packed suite run provenance
seonghobae Aug 25, 2026
f136388
test(perf): bind benchmark source provenance to checkout
seonghobae Aug 25, 2026
9876531
fix(perf): verify benchmark source checkout provenance
seonghobae Aug 25, 2026
4a9661f
fix(perf): reject dirty benchmark provenance
seonghobae Aug 25, 2026
b376877
test(perf): isolate checkout provenance regression
seonghobae Aug 25, 2026
8b7b6df
test(perf): require Office duration and RSS evidence
seonghobae Aug 25, 2026
38a287c
test(perf): bind Office evidence to canonical fixtures
seonghobae Aug 25, 2026
a5275f9
feat(perf): measure canonical Office render latency and RSS
seonghobae Aug 25, 2026
e6598e8
test(perf): bound hung Office render sample RED
seonghobae Aug 25, 2026
7128b6c
fix(perf): bound Office render sample duration
seonghobae Aug 25, 2026
1572af1
test(perf): require child fixture re-verification
seonghobae Aug 25, 2026
28053fd
fix(perf): bind Office child to canonical fixture
seonghobae Aug 25, 2026
a6ab00f
test(perf): pass canonical child identity
seonghobae Aug 25, 2026
2251be8
test(perf): bind packed benchmark to verified tarball bytes
seonghobae Aug 25, 2026
0055f24
test(perf): exercise packed tarball interposition
seonghobae Aug 25, 2026
4033e2c
fix(perf): snapshot verified packed artifact before extraction
seonghobae Aug 25, 2026
c455ec1
fix(test): preserve generated benchmark source interpolation
seonghobae Aug 25, 2026
5abc237
test(perf): reject mutable existing suite evidence targets
seonghobae Aug 25, 2026
9621133
fix(perf): preserve existing benchmark evidence directories
seonghobae Aug 25, 2026
1949f18
test(perf): cover core existing-output race boundary
seonghobae Aug 25, 2026
92683c2
fix(perf): fail closed on existing evidence output
seonghobae Aug 25, 2026
c16fe9c
test(perf): preserve existing measurement evidence
seonghobae Aug 25, 2026
856c1e9
fix(perf): preserve existing markdown evidence
seonghobae Aug 25, 2026
1b7710a
fix(perf): preserve existing revision evidence
seonghobae Aug 25, 2026
71b1fc5
test(perf): require HTML serialization measurement
seonghobae Aug 25, 2026
8851d5d
feat(perf): measure HTML serialization direction
seonghobae Aug 25, 2026
cf8fd2e
test(perf): require HTML serialization in benchmark suite
seonghobae Aug 25, 2026
94ad4f8
feat(perf): include HTML serialization in suite
seonghobae Aug 25, 2026
0d8557d
test(perf): require packed HTML serialization evidence
seonghobae Aug 25, 2026
c220538
test(perf): reject mismatched benchmark source checkout
seonghobae Aug 25, 2026
67b499c
fix(perf): bind benchmark evidence to checked-out source
seonghobae Aug 25, 2026
fd73da7
test(perf): bind suite source provenance to checkout
seonghobae Aug 25, 2026
5547e4d
test(perf): use live checkout SHA for HTML suite
seonghobae Aug 25, 2026
aa9be79
fix(perf): reject wrong source SHA before benchmark evidence
seonghobae Aug 25, 2026
0001bb9
fix(perf): restore packed HTML benchmark composition
seonghobae Aug 25, 2026
48363ba
test(perf): reject false producer provenance
seonghobae Aug 26, 2026
a83a425
fix(perf): bind Markdown evidence to live source
seonghobae Aug 26, 2026
d4e7883
fix(perf): bind revision evidence to live source
seonghobae Aug 26, 2026
19c8c28
fix(test): preserve producer provenance typing
seonghobae Aug 26, 2026
fa91c06
fix(test): use live Markdown benchmark provenance
seonghobae Aug 26, 2026
d46dc2f
fix(test): use live revision benchmark provenance
seonghobae Aug 26, 2026
c3d9fa6
fix(test): use active suite runtime provenance
seonghobae Aug 26, 2026
65cb302
fix(test): bind producer immutability fixtures to active provenance
seonghobae Aug 26, 2026
8f1480a
fix(test): bind Markdown privacy fixtures to active provenance
seonghobae Aug 26, 2026
aba2d3b
fix(test): bind HTML serialization fixtures to active provenance
seonghobae Aug 26, 2026
d334b95
fix(test): bind HTML suite runtime to active provenance
seonghobae Aug 26, 2026
fc54c8c
test(perf): reject source movement during Office measurement
seonghobae Aug 26, 2026
227418d
fix(perf): bind Office evidence to stable source revision
seonghobae Aug 26, 2026
483c3fc
test(perf): reject source movement during direct measurement
seonghobae Aug 26, 2026
65e6327
test(perf): build isolated git shim for source-move RED
seonghobae Aug 26, 2026
8a7e49c
fix(perf): recheck source provenance after markdown measurement
seonghobae Aug 26, 2026
a5123c7
fix(perf): recheck source provenance after revision measurement
seonghobae Aug 26, 2026
0fc19a7
test(perf): reject symlinked corpus output directory
seonghobae Aug 28, 2026
30edf11
fix(perf): reject unsafe corpus directory ancestry
seonghobae Aug 28, 2026
b5ad1da
test(perf): keep benchmark contracts portable on Node 24
seonghobae Aug 28, 2026
d025d45
test(perf): allow slow benchmark contract processes
seonghobae Aug 28, 2026
97514db
test(perf): define autosave enqueue measurement contract
seonghobae Aug 28, 2026
690c039
fix(perf): implement autosave enqueue measurement
seonghobae Aug 28, 2026
8fc0ba4
test(perf): require bounded PR benchmark evidence workflow
seonghobae Aug 28, 2026
55a56bc
ci(perf): add bounded exact-head smoke evidence
seonghobae Aug 28, 2026
0ad9366
test(perf): bind smoke revision input to envelope schema
seonghobae Aug 28, 2026
a5b741b
fix(perf): benchmark a valid document envelope
seonghobae Aug 28, 2026
2d3acdd
test(perf): require packed autosave suite evidence
seonghobae Aug 29, 2026
4cb6c49
feat(perf): include autosave in packed benchmark suite
seonghobae Aug 29, 2026
4a68ae3
test(perf): require canonical autosave sample schema
seonghobae Aug 29, 2026
36ba0fa
fix(perf): standardize autosave benchmark evidence
seonghobae Aug 29, 2026
b3a1aff
test(perf): require hosted HTML serialization evidence
seonghobae Aug 29, 2026
f88ba74
ci(perf): smoke HTML serialization evidence
seonghobae Aug 29, 2026
e6659b2
fix(perf): keep path-stability fixture current with packed suite
seonghobae Aug 29, 2026
67fdc48
Merge remote-tracking branch 'origin/main' into HEAD
seonghobae Sep 4, 2026
3d5e739
test(perf): canonicalize the macOS temp root
seonghobae Sep 4, 2026
e2cc551
Merge remote-tracking branch 'origin/main' into HEAD
seonghobae Sep 4, 2026
a9804ae
fix(ci): preserve Python boundary coverage
seonghobae Sep 4, 2026
d22bcfc
fix(ci): restore full Python PR matrix
seonghobae Sep 4, 2026
8f8cd7d
fix(perf): bind revision evidence to corpus profiles
seonghobae Sep 4, 2026
b2cf91f
fix(perf): measure autosave with profile input
seonghobae Sep 4, 2026
d0e353a
fix(perf): measure autosave with profile input
seonghobae Sep 4, 2026
753775b
merge: preserve autosave measurement correction
seonghobae Sep 4, 2026
b434cc8
fix(perf): scale envelope structure by profile
seonghobae Sep 4, 2026
466326f
perf: measure packed transition evidence
seonghobae Sep 4, 2026
d36227a
fix(perf): redact transition result inspection
seonghobae Sep 4, 2026
f7da6b3
perf: measure autosave coalescing
seonghobae Sep 4, 2026
e22141c
perf: measure autosave commit classification
seonghobae Sep 4, 2026
f6875f4
perf: measure envelope canonicalization
seonghobae Sep 4, 2026
8402073
fix(perf): scale HTML benchmark corpus
seonghobae Sep 4, 2026
c05ca75
fix(perf): bind packed evidence to corpus
seonghobae Sep 4, 2026
50f0bff
test(perf): use locked packed corpus
seonghobae Sep 4, 2026
d978083
ci(perf): add full profile evidence matrix
seonghobae Sep 4, 2026
699808e
test(perf): require repository-scoped concurrency
seonghobae Sep 4, 2026
5701b7e
fix(perf): scope concurrency to repository
seonghobae Sep 4, 2026
9258bdb
experiment: reuse canonical UTF-8 encoder
seonghobae Sep 4, 2026
e5ff9c3
test(perf): validate changed document transition scenarios
seonghobae Sep 5, 2026
1879d20
merge: inherit canonical runtime and dependency prerequisite
seonghobae Sep 5, 2026
a51cd5f
merge: inherit canonical serialization owner without losing encoder r…
seonghobae Sep 5, 2026
03345b0
test(benchmarks): reject unmeasured operation invocations
seonghobae Sep 6, 2026
8f1b389
fix(benchmarks): record the first operation invocation
seonghobae Sep 6, 2026
b6d8340
test(benchmarks): distinguish measurement generations
seonghobae Sep 6, 2026
e74a8a7
fix(benchmarks): reject cross-generation latency comparisons
seonghobae Sep 6, 2026
43e946a
test: require document identity in Markdown measurements
seonghobae Sep 6, 2026
69bdcc5
test: bind revision and autosave measurements to their inputs
seonghobae Sep 6, 2026
ce48bad
test(performance): reject mismatched measurement input identities
seonghobae Sep 6, 2026
c4fba27
fix(performance): bind measurement comparisons to captured input bytes
seonghobae Sep 6, 2026
b866a1d
test(performance): distinguish captured and prepared input identities
seonghobae Sep 6, 2026
c7d829d
fix(performance): identify the prepared synthetic autosave payload
seonghobae Sep 6, 2026
75f195d
test(performance): verify packed input identity and document evidence…
seonghobae Sep 6, 2026
98f068a
test(perf): reject inconsistent serialization samples
seonghobae Sep 6, 2026
ea2e998
fix(perf): reject changing serialization results
seonghobae Sep 6, 2026
7fb2068
docs(perf): distinguish stable output from conversion fidelity
seonghobae Sep 6, 2026
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
106 changes: 106 additions & 0 deletions .github/workflows/performance-evidence.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Performance Evidence

on:
pull_request:
paths:
- '.github/workflows/performance-evidence.yml'
- 'benchmarks/**'
- 'src/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'tsconfig.json'
- 'vite.config.ts'
schedule:
- cron: '17 3 * * 1'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'

jobs:
packed-artifact-smoke:
name: packed-artifact-${{ matrix.profile }}
runs-on: ubuntu-24.04
timeout-minutes: 20
strategy:
fail-fast: false
matrix: ${{ fromJSON(github.event_name == 'pull_request' && '{"include":[{"profile":"small","samples":3}]}' || '{"include":[{"profile":"small","samples":25},{"profile":"medium","samples":25},{"profile":"large","samples":25},{"profile":"stress","samples":25}]}') }}
steps:
- name: Checkout exact pull-request head
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false

- name: Verify exact checkout
shell: bash
env:
INKSPAN_EXPECTED_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
set -euo pipefail
actual_head="$(git rev-parse HEAD)"
test "$actual_head" = "$INKSPAN_EXPECTED_HEAD_SHA"

- name: Set up pnpm
uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22'
cache: pnpm

- name: Install immutable dependencies
run: pnpm install --frozen-lockfile

- name: Build packed library
run: pnpm build

- name: Produce bounded packed-artifact smoke evidence
shell: bash
run: |
set -euo pipefail
corpus_dir="${RUNNER_TEMP}/inkspan-benchmark-corpus"
package_dir="${RUNNER_TEMP}/inkspan-package"
evidence_dir="${RUNNER_TEMP}/inkspan-performance-evidence"

rm -rf "$corpus_dir" "$package_dir" "$evidence_dir"
node benchmarks/generate-corpus.mjs --output "$corpus_dir"

mkdir -p "$package_dir"
pnpm pack --pack-destination "$package_dir"
mapfile -t packages < <(find "$package_dir" -maxdepth 1 -type f -name '*.tgz' -print)
test "${#packages[@]}" -eq 1
package="${packages[0]}"
package_sha256="$(sha256sum "$package" | cut -d' ' -f1)"
source_sha="$(git rev-parse HEAD)"
runtime_id="node-$(node -p 'process.versions.node')"

node benchmarks/run-current-suite.mjs \
--input "$corpus_dir/${{ matrix.profile }}.md" \
--html-input "$corpus_dir/${{ matrix.profile }}.html" \
--revision-input "$corpus_dir/${{ matrix.profile }}.envelope.json" \
--package-tarball "$package" \
--package-sha256 "$package_sha256" \
--profile "${{ matrix.profile }}" \
--samples "${{ matrix.samples }}" \
--source-commit-sha "$source_sha" \
--runtime-id "$runtime_id" \
--reference-hardware-id github-actions-ubuntu-24.04-x64 \
--resulting-input "$corpus_dir/${{ matrix.profile }}.changed.envelope.json" \
--output "$evidence_dir"

- name: Upload bounded performance evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v6.0.0
with:
name: performance-${{ matrix.profile }}-${{ github.event.pull_request.head.sha || github.sha }}
path: ${{ runner.temp }}/inkspan-performance-evidence
if-no-files-found: error
retention-days: 5
86 changes: 86 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Performance evidence development harness

This harness is research infrastructure, not a published latency or supported
document-size guarantee. The generated corpus is synthetic and suitable for
repeatable regression probes and harness contract tests. It does not establish
buyer-workload performance, real-device input behavior, or the 20 ms target.
Envelope fixtures contain plain paragraphs; Markdown list, table, and image
syntax inside those paragraphs is not a rich editor document tree.

The [captured-input identity research record](../docs/doctoring/performance-input-identity.md)
documents the failure, rejected alternatives and exact-source regression evidence.

## First-invocation accounting

The revision, Markdown/HTML, and autosave latency producers record the first
operation invocation and every subsequent requested sample, without an
unrecorded warmup invocation. Each result must pass its scenario checks before
samples can be published. Module loading and input preparation remain outside
the timer; autosave queue setup and coalescing-scenario preparation retain
their existing timer boundaries. This is not process-startup latency.

Markdown/HTML producers also require every measured output to equal the first
measured output for the same captured input. Empty strings are valid reference
outputs. A changed result rejects the entire acquisition without publishing
samples or output content; there is no extra warmup call. Equality is checked
after the timer and retains one output in memory. Start a fresh baseline after
this validation change: process state can differ even though the operation's
timer boundaries and sample schema remain unchanged. Equal outputs alone do
not prove conversion fidelity; workload-specific correctness checks remain
required, and a one-sample run cannot establish repeatability.

Samples recorded before this change retain their original meaning. Start a
new baseline for the new measurement method; a difference between those
generations is not evidence of a product speedup. Keep each generation's raw
samples and exact source revision. Office rendering and the separate memory
settling analysis are unchanged.

Version 2 introduced this first-invocation method. New JavaScript latency samples
use `contractVersion: 3` and additionally identify the captured input bytes with
`inputSha256`. The digest is derived before measurement from the same bounded
read used by the operation, not a caller-supplied claim or a later file read.
Changed transitions also record `resultingInputSha256` in its distinct resulting
role. Autosave with no input file hashes the UTF-8 JSON representation of its
fixed prepared revision-evidence payload (envelope and revision), not a file-mode
envelope; that input remains synthetic regardless of profile.
Input digests are workload identifiers, not anonymization or authenticity proofs.

The summarizer preserves these identities in JSON and text. The comparator
rejects different versions or input identities before calculating a verdict,
even when document profiles match. Versions 1 and 2 remain readable with their
original meanings; Office output remains version 1. Do not backfill identities,
relabel historical samples, or present a cross-generation difference as a
speedup. Update producers and evidence readers together. The suite inventory and
corpus locks retain their independent version 1 contracts; published editor APIs
and timer boundaries are unchanged. This does not establish a real-world corpus.

## Transition scenarios

| Operation | Inputs | Required result | Metric prefix |
| --- | --- | --- | --- |
| `transition` | Same captured envelope twice | Unchanged, equal revision digests | `transition-evidence` |
| `transition-changed` | Explicit previous and resulting envelopes | Changed, unequal revision digests | `transition-changed-evidence` |

The profile suffix remains `small`, `medium`, `large`, or `stress`. Existing
transition samples retain their no-op meaning. Never compare the two scenarios
as an optimization result; the comparison tool rejects mismatched metric IDs.

For `measure-revision-evidence.mjs`, append
`--operation transition-changed --resulting-input <resulting-envelope.json>`
immediately before `--output`. Other operations reject `--resulting-input`.
Both inputs use the same bounded, non-symlink file reader. An output cannot
overwrite either input, including through a hard link. Invalid results publish
no sample file, and sample output contains neither document content nor paths.

The packed `run-current-suite.mjs` accepts `--resulting-input` immediately before
`--output`, with or without `--html-input`. It verifies the resulting fixture
against `changedEnvelopeBytes` and `changedEnvelopeSha256` in `corpus.lock.json`.
The generator adds one plain paragraph to produce each
`<profile>.changed.envelope.json`; all earlier fixture bytes and digests remain
unchanged. Omitting the new flag preserves the earlier suite. The
`performance-evidence.yml` workflow exercises both transition scenarios.

Commit a clean source checkout and rebuild the package before recording evidence.
Keep raw samples with the exact source SHA, packed-artifact digest, Node runtime,
hardware identity, and sample count. A new scenario starts a separate baseline;
synthetic smoke evidence cannot close the realistic-workload support-envelope gap.
Loading