@kungfu-tech/buildchain 2.10.10 → 2.10.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/dist/site/buildchain-contract.json +5 -5
- package/dist/site/buildchain-site.json +6 -6
- package/dist/site/kfd-claims.json +7 -3
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/node-api-registry.json +1 -1
- package/dist/site/page-registry.json +2 -2
- package/dist/site/public-surface-audit.json +7 -3
- package/dist/site/site-manifest.json +4 -4
- package/dist/site/workflow-registry.json +5 -1
- package/docs/publication-artifacts.md +23 -2
- package/package.json +1 -1
- package/packages/core/buildchain-config.js +45 -0
- package/packages/core/publication-artifact.js +71 -9
- package/scripts/init-repo.mjs +5 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"product": {
|
|
5
5
|
"name": "Buildchain",
|
|
6
6
|
"package": "@kungfu-tech/buildchain",
|
|
7
|
-
"version": "2.10.
|
|
7
|
+
"version": "2.10.11",
|
|
8
8
|
"repository": "https://github.com/kungfu-systems/buildchain"
|
|
9
9
|
},
|
|
10
10
|
"majorLine": "v2",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"GitHub Release passport and evidence publication is delegated to promote-buildchain-ref after the semver release transaction completes"
|
|
93
93
|
],
|
|
94
94
|
"breakingDigest": "sha256:403d2fcdb0c5eabe749e89102defad69745f70a1556707bec7831fcc2e9fa8f8",
|
|
95
|
-
"auditDigest": "sha256:
|
|
95
|
+
"auditDigest": "sha256:db6fe83e886a04221cc2457d3bdf091cd8607083d5c5e4dc87f40220c2436581"
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
"contractVersion": 1,
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
"breaking contract drift fails closed before rendering, deployment, or release publication"
|
|
135
135
|
],
|
|
136
136
|
"breakingDigest": "sha256:82ee63cb336e40d832dfff4a1c5e6cbfa221a4fc8b2359990033bc931bffc43a",
|
|
137
|
-
"auditDigest": "sha256:
|
|
137
|
+
"auditDigest": "sha256:623e5222b8e649b40a05817fabf4c7fd8052a3e64636e74eb7a7bbcfd9de4998"
|
|
138
138
|
},
|
|
139
139
|
{
|
|
140
140
|
"contractVersion": 1,
|
|
@@ -456,9 +456,9 @@
|
|
|
456
456
|
"agents can discover supported Node APIs without importing internal file paths"
|
|
457
457
|
],
|
|
458
458
|
"breakingDigest": "sha256:48f925608d3e2131d90936b07dc2a30341204cae3e6e785c0f77d61ad755c945",
|
|
459
|
-
"auditDigest": "sha256:
|
|
459
|
+
"auditDigest": "sha256:983094d1f0d421294e6c542232a5483c408aa72352883b851e1e2ecff1f9e8b5"
|
|
460
460
|
}
|
|
461
461
|
],
|
|
462
462
|
"compatibilityDigest": "sha256:967df7e854fdf582294ddfb6403eff25c00db9518a24051e7d47cbd75527c785",
|
|
463
|
-
"contractDigest": "sha256:
|
|
463
|
+
"contractDigest": "sha256:b420ce7d38f966d3a2d72b31ef43490f9720bf0733d1848b1cc497c4a6ac5643"
|
|
464
464
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-bundle",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-09T03:20:50.735Z",
|
|
5
|
+
"publishedAt": "2026-07-09T03:20:50.735Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "c7e618f57355231a8f27fd628ee9499bd5b8e9fd",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "2.10.
|
|
40
|
+
"version": "2.10.11",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"source": {
|
|
@@ -965,7 +965,7 @@
|
|
|
965
965
|
],
|
|
966
966
|
"maturity": "stable",
|
|
967
967
|
"sourcePath": "docs/publication-artifacts.md",
|
|
968
|
-
"digest": "sha256:
|
|
968
|
+
"digest": "sha256:06ba810c9eb13d47e408c74d58442635727396da66ed90fd4d505f2ff031cc18",
|
|
969
969
|
"headings": [
|
|
970
970
|
{
|
|
971
971
|
"level": 1,
|
|
@@ -993,7 +993,7 @@
|
|
|
993
993
|
"anchor": "site-consumption"
|
|
994
994
|
}
|
|
995
995
|
],
|
|
996
|
-
"markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n## Reusable Workflow\n\nConsumer repositories can call the Buildchain wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n
|
|
996
|
+
"markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[publication.toolchain]\ntype = \"latex-docker\"\nimage = \"ghcr.io/kungfu-systems/latex\"\ndigest = \"sha256:0000000000000000000000000000000000000000000000000000000000000000\"\ncommand = \"latexmk -pdf -outdir=_build paper/main.tex\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n`publication.toolchain` makes the source-to-PDF transformation part of the\nmachine-readable contract. `latex-docker` is the preferred LaTeX profile: the\nworkflow pulls the declared image by digest and runs the declared command in\nthat pinned container. `custom-command` remains available for compatibility,\nbut the passport records it as lower trust because Buildchain can record the\ncommand boundary without proving the compiler or LaTeX distribution digest.\n\n## Reusable Workflow\n\nConsumer repositories can call the Buildchain wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n toolchain-type: config\n verify-command: make check\n artifact-name: observer-declared-timelines\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe workflow:\n\n- resolves the Buildchain runtime and checks the floating contract lock before\n any paper build runs;\n- resolves the declared publication toolchain from `[publication.toolchain]` or\n workflow inputs;\n- for `latex-docker`, pulls the pinned image digest and runs the declared\n command in the container;\n- for `custom-command`, runs the declared command and records the lower-trust\n boundary in the passport;\n- runs the verify command;\n- creates a source bundle from `publication.source_paths`;\n- writes `.buildchain/publication/publication-artifact.json`;\n- writes `.buildchain/publication/publication-artifact-passport.json`;\n- uploads one GitHub artifact containing the PDF, manifest, passport, and\n source bundle.\n\nThe wrapper is build-only. It does not publish npm packages, deploy web pages,\nor create GitHub Releases. Release publication can be layered later by a\nrepository-specific governance workflow that attaches the generated manifest\nand passport as release assets.\n\n## CLI And Node API\n\nGenerate the publication manifest locally or in CI:\n\n```sh\nbuildchain publication-artifact manifest --source-sha \"$(git rev-parse HEAD)\" --json\n```\n\nNode API:\n\n```js\nimport {\n collectPublicationArtifact,\n writePublicationArtifact,\n} from \"@kungfu-tech/buildchain/publication-artifact\";\n```\n\n`writePublicationArtifact()` is the single implementation used by the CLI and\nthe reusable workflow. The generated manifest records:\n\n- publication title, kind, authors, and primary artifact;\n- artifact paths, byte sizes, and SHA-256 digests;\n- metadata paths and SHA-256 digests;\n- source SHA, tree SHA, source files, and source bundle digest;\n- publication toolchain type, image, digest, command, invocation mode, and trust\n classification;\n- timestamp and reproducibility policy;\n- downstream site-consumption hints.\n\nThe companion publication artifact passport records the same source and\nartifact evidence plus an explicit responsibility split. Buildchain proves\ndeclared files and hashes; it does not peer-review paper claims.\n\n## Site Consumption\n\nA downstream papers site should treat the publication manifest as the single\nfact source for the artifact. The site owns rendering and navigation; it should\nnot reinterpret the paper repository as a web deployment source.\n\nFor `paper-observer-declared-timelines`, the expected adoption path is:\n\n```text\npaper repo builds PDF + manifest + source bundle\npapers site consumes publication-artifact.json\nsite renders paper page and links the PDF/source bundle\n```\n\nThis mirrors web-surface governance without mixing producer and renderer\nresponsibilities."
|
|
997
997
|
},
|
|
998
998
|
{
|
|
999
999
|
"id": "manual:publish-transaction",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
22
22
|
"path": "dist/site/public-surface-audit.json",
|
|
23
23
|
"status": "passed",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "a978e2407063ed5d118024da92e28916a90d7704d9948fea52b62e933f7387b4",
|
|
25
25
|
"summary": {
|
|
26
26
|
"cliCommandCount": 73,
|
|
27
27
|
"workflowCount": 36,
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
"contract": "kungfu-buildchain-public-surface-reverse-audit",
|
|
208
208
|
"path": "dist/site/public-surface-audit.json",
|
|
209
209
|
"status": "passed",
|
|
210
|
-
"sha256": "
|
|
210
|
+
"sha256": "a978e2407063ed5d118024da92e28916a90d7704d9948fea52b62e933f7387b4",
|
|
211
211
|
"summary": {
|
|
212
212
|
"cliCommandCount": 73,
|
|
213
213
|
"workflowCount": 36,
|
|
@@ -2895,7 +2895,7 @@
|
|
|
2895
2895
|
"visibility": "public",
|
|
2896
2896
|
"participantFacing": true,
|
|
2897
2897
|
"public": true,
|
|
2898
|
-
"inputCount":
|
|
2898
|
+
"inputCount": 17,
|
|
2899
2899
|
"inputs": [
|
|
2900
2900
|
"artifact-name",
|
|
2901
2901
|
"artifact-paths",
|
|
@@ -2908,6 +2908,10 @@
|
|
|
2908
2908
|
"buildchain-repository",
|
|
2909
2909
|
"node-version",
|
|
2910
2910
|
"setup-node",
|
|
2911
|
+
"toolchain-command",
|
|
2912
|
+
"toolchain-digest",
|
|
2913
|
+
"toolchain-image",
|
|
2914
|
+
"toolchain-type",
|
|
2911
2915
|
"verify-command",
|
|
2912
2916
|
"working-directory"
|
|
2913
2917
|
],
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
"specifier": "@kungfu-tech/buildchain/publication-artifact",
|
|
204
204
|
"export": "./publication-artifact",
|
|
205
205
|
"target": "./packages/core/publication-artifact.js",
|
|
206
|
-
"digest": "sha256:
|
|
206
|
+
"digest": "sha256:03cf19323cf8d4bd7726e07ab615ed74b4ff7ca0b58becd25963ff080993c6ea",
|
|
207
207
|
"summary": "Publication artifact manifest, source bundle, and publication passport APIs.",
|
|
208
208
|
"capabilityGroup": "reusable-build",
|
|
209
209
|
"audience": [
|
|
@@ -902,7 +902,7 @@
|
|
|
902
902
|
],
|
|
903
903
|
"maturity": "stable",
|
|
904
904
|
"sourcePath": "docs/publication-artifacts.md",
|
|
905
|
-
"digest": "sha256:
|
|
905
|
+
"digest": "sha256:06ba810c9eb13d47e408c74d58442635727396da66ed90fd4d505f2ff031cc18",
|
|
906
906
|
"headings": [
|
|
907
907
|
{
|
|
908
908
|
"level": 1,
|
|
@@ -930,7 +930,7 @@
|
|
|
930
930
|
"anchor": "site-consumption"
|
|
931
931
|
}
|
|
932
932
|
],
|
|
933
|
-
"markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n## Reusable Workflow\n\nConsumer repositories can call the Buildchain wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n
|
|
933
|
+
"markdown": "# Publication Artifact Workflow\n\nBuildchain supports `project.type = \"publication-artifact\"` for repositories\nthat produce auditable papers, reports, specifications, or similar publication\npackages. These repositories are artifact producers. They should not be forced\nto become `web-surface` repositories just because a downstream site later\nrenders the paper.\n\nThe split is:\n\n```text\npaper repo = source, PDF, metadata, source bundle, publication manifest\npapers site = layout, navigation, public web surface, downstream rendering\n```\n\n## Configuration\n\nThe paper repository owns `.buildchain/buildchain.toml`:\n\n```toml\nschema = 1\n\n[project]\ntype = \"publication-artifact\"\nname = \"paper-observer-declared-timelines\"\n\n[publication]\nkind = \"paper\"\ntitle = \"Observer-Declared Timelines for Real-World Agent Work\"\nprimary_artifact = \"_build/main.pdf\"\nartifact_paths = [\"_build/main.pdf\"]\nmetadata_paths = [\"README.md\", \"docs/MAP.md\"]\nsource_paths = [\"paper\", \"README.md\", \"LICENSE\", \"Makefile\"]\nsite_consumers = [\"papers.libkungfu.dev\"]\nmanifest_path = \".buildchain/publication/publication-artifact.json\"\nsource_bundle_path = \".buildchain/publication/source.tar.gz\"\n\n[publication.toolchain]\ntype = \"latex-docker\"\nimage = \"ghcr.io/kungfu-systems/latex\"\ndigest = \"sha256:0000000000000000000000000000000000000000000000000000000000000000\"\ncommand = \"latexmk -pdf -outdir=_build paper/main.tex\"\n\n[lifecycle.build]\ncommand = \"make pdf\"\n\n[lifecycle.verify]\ncommand = \"make check\"\n```\n\n`primary_artifact` is the human-facing publication output, usually a PDF.\n`source_paths` are archived into a source bundle. `metadata_paths` are hashed\nand recorded so a site can consume the paper facts without scraping prose.\n\n`publication.toolchain` makes the source-to-PDF transformation part of the\nmachine-readable contract. `latex-docker` is the preferred LaTeX profile: the\nworkflow pulls the declared image by digest and runs the declared command in\nthat pinned container. `custom-command` remains available for compatibility,\nbut the passport records it as lower trust because Buildchain can record the\ncommand boundary without proving the compiler or LaTeX distribution digest.\n\n## Reusable Workflow\n\nConsumer repositories can call the Buildchain wrapper directly:\n\n```yaml\njobs:\n publication:\n uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2\n with:\n toolchain-type: config\n verify-command: make check\n artifact-name: observer-declared-timelines\n buildchain-contract-lock-path: .buildchain/contract-lock.json\n```\n\nThe workflow:\n\n- resolves the Buildchain runtime and checks the floating contract lock before\n any paper build runs;\n- resolves the declared publication toolchain from `[publication.toolchain]` or\n workflow inputs;\n- for `latex-docker`, pulls the pinned image digest and runs the declared\n command in the container;\n- for `custom-command`, runs the declared command and records the lower-trust\n boundary in the passport;\n- runs the verify command;\n- creates a source bundle from `publication.source_paths`;\n- writes `.buildchain/publication/publication-artifact.json`;\n- writes `.buildchain/publication/publication-artifact-passport.json`;\n- uploads one GitHub artifact containing the PDF, manifest, passport, and\n source bundle.\n\nThe wrapper is build-only. It does not publish npm packages, deploy web pages,\nor create GitHub Releases. Release publication can be layered later by a\nrepository-specific governance workflow that attaches the generated manifest\nand passport as release assets.\n\n## CLI And Node API\n\nGenerate the publication manifest locally or in CI:\n\n```sh\nbuildchain publication-artifact manifest --source-sha \"$(git rev-parse HEAD)\" --json\n```\n\nNode API:\n\n```js\nimport {\n collectPublicationArtifact,\n writePublicationArtifact,\n} from \"@kungfu-tech/buildchain/publication-artifact\";\n```\n\n`writePublicationArtifact()` is the single implementation used by the CLI and\nthe reusable workflow. The generated manifest records:\n\n- publication title, kind, authors, and primary artifact;\n- artifact paths, byte sizes, and SHA-256 digests;\n- metadata paths and SHA-256 digests;\n- source SHA, tree SHA, source files, and source bundle digest;\n- publication toolchain type, image, digest, command, invocation mode, and trust\n classification;\n- timestamp and reproducibility policy;\n- downstream site-consumption hints.\n\nThe companion publication artifact passport records the same source and\nartifact evidence plus an explicit responsibility split. Buildchain proves\ndeclared files and hashes; it does not peer-review paper claims.\n\n## Site Consumption\n\nA downstream papers site should treat the publication manifest as the single\nfact source for the artifact. The site owns rendering and navigation; it should\nnot reinterpret the paper repository as a web deployment source.\n\nFor `paper-observer-declared-timelines`, the expected adoption path is:\n\n```text\npaper repo builds PDF + manifest + source bundle\npapers site consumes publication-artifact.json\nsite renders paper page and links the PDF/source bundle\n```\n\nThis mirrors web-surface governance without mixing producer and renderer\nresponsibilities."
|
|
934
934
|
},
|
|
935
935
|
{
|
|
936
936
|
"id": "manual:publish-transaction",
|
|
@@ -839,10 +839,14 @@
|
|
|
839
839
|
"buildchain-repository",
|
|
840
840
|
"node-version",
|
|
841
841
|
"setup-node",
|
|
842
|
+
"toolchain-command",
|
|
843
|
+
"toolchain-digest",
|
|
844
|
+
"toolchain-image",
|
|
845
|
+
"toolchain-type",
|
|
842
846
|
"verify-command",
|
|
843
847
|
"working-directory"
|
|
844
848
|
],
|
|
845
|
-
"inputCount":
|
|
849
|
+
"inputCount": 17
|
|
846
850
|
},
|
|
847
851
|
{
|
|
848
852
|
"id": "release-candidate-promote",
|
|
@@ -2435,8 +2439,8 @@
|
|
|
2435
2439
|
"workflowRegistryPath": "dist/site/workflow-registry.json",
|
|
2436
2440
|
"pageRegistryPath": "dist/site/page-registry.json",
|
|
2437
2441
|
"cliRegistryDigest": "1f7e1f7707a089f067175030fde6712b69ceece3df1b811eb542b0b4c8c1d4a9",
|
|
2438
|
-
"workflowRegistryDigest": "
|
|
2439
|
-
"pageRegistryDigest": "
|
|
2442
|
+
"workflowRegistryDigest": "67572429a83124370b9ffd46f56923aa2b252873c9624ded39a26675fb0ee815",
|
|
2443
|
+
"pageRegistryDigest": "c1ec998aced6612b9cf444b886d126a89b344954a1ecebf6908d11610dba3cf8"
|
|
2440
2444
|
},
|
|
2441
2445
|
"comparison": {
|
|
2442
2446
|
"missingCliRegistry": [],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"contract": "kungfu-buildchain-site-manifest",
|
|
4
|
-
"generatedAt": "2026-07-
|
|
5
|
-
"publishedAt": "2026-07-
|
|
4
|
+
"generatedAt": "2026-07-09T03:20:50.735Z",
|
|
5
|
+
"publishedAt": "2026-07-09T03:20:50.735Z",
|
|
6
6
|
"reproducible": true,
|
|
7
7
|
"timestampPolicy": "ci-injected",
|
|
8
8
|
"deterministicInputs": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"declared Buildchain surface manifest contract"
|
|
20
20
|
],
|
|
21
21
|
"sourceDateEpoch": "0",
|
|
22
|
-
"sourceRevision": "
|
|
22
|
+
"sourceRevision": "c7e618f57355231a8f27fd628ee9499bd5b8e9fd",
|
|
23
23
|
"timestampPolicyDetails": {
|
|
24
24
|
"contract": "kungfu-buildchain-surface-timestamp-policy",
|
|
25
25
|
"timestampFields": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"package": {
|
|
39
39
|
"name": "@kungfu-tech/buildchain",
|
|
40
|
-
"version": "2.10.
|
|
40
|
+
"version": "2.10.11",
|
|
41
41
|
"versionSource": "package.json#version"
|
|
42
42
|
},
|
|
43
43
|
"entrypoint": "buildchain-site.json",
|
|
@@ -544,10 +544,14 @@
|
|
|
544
544
|
"buildchain-repository",
|
|
545
545
|
"node-version",
|
|
546
546
|
"setup-node",
|
|
547
|
+
"toolchain-command",
|
|
548
|
+
"toolchain-digest",
|
|
549
|
+
"toolchain-image",
|
|
550
|
+
"toolchain-type",
|
|
547
551
|
"verify-command",
|
|
548
552
|
"working-directory"
|
|
549
553
|
],
|
|
550
|
-
"inputCount":
|
|
554
|
+
"inputCount": 17,
|
|
551
555
|
"surface": "repository-workflow",
|
|
552
556
|
"capabilityGroup": "reusable-build",
|
|
553
557
|
"status": "active"
|
|
@@ -35,6 +35,12 @@ site_consumers = ["papers.libkungfu.dev"]
|
|
|
35
35
|
manifest_path = ".buildchain/publication/publication-artifact.json"
|
|
36
36
|
source_bundle_path = ".buildchain/publication/source.tar.gz"
|
|
37
37
|
|
|
38
|
+
[publication.toolchain]
|
|
39
|
+
type = "latex-docker"
|
|
40
|
+
image = "ghcr.io/kungfu-systems/latex"
|
|
41
|
+
digest = "sha256:0000000000000000000000000000000000000000000000000000000000000000"
|
|
42
|
+
command = "latexmk -pdf -outdir=_build paper/main.tex"
|
|
43
|
+
|
|
38
44
|
[lifecycle.build]
|
|
39
45
|
command = "make pdf"
|
|
40
46
|
|
|
@@ -46,6 +52,13 @@ command = "make check"
|
|
|
46
52
|
`source_paths` are archived into a source bundle. `metadata_paths` are hashed
|
|
47
53
|
and recorded so a site can consume the paper facts without scraping prose.
|
|
48
54
|
|
|
55
|
+
`publication.toolchain` makes the source-to-PDF transformation part of the
|
|
56
|
+
machine-readable contract. `latex-docker` is the preferred LaTeX profile: the
|
|
57
|
+
workflow pulls the declared image by digest and runs the declared command in
|
|
58
|
+
that pinned container. `custom-command` remains available for compatibility,
|
|
59
|
+
but the passport records it as lower trust because Buildchain can record the
|
|
60
|
+
command boundary without proving the compiler or LaTeX distribution digest.
|
|
61
|
+
|
|
49
62
|
## Reusable Workflow
|
|
50
63
|
|
|
51
64
|
Consumer repositories can call the Buildchain wrapper directly:
|
|
@@ -55,7 +68,7 @@ jobs:
|
|
|
55
68
|
publication:
|
|
56
69
|
uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2
|
|
57
70
|
with:
|
|
58
|
-
|
|
71
|
+
toolchain-type: config
|
|
59
72
|
verify-command: make check
|
|
60
73
|
artifact-name: observer-declared-timelines
|
|
61
74
|
buildchain-contract-lock-path: .buildchain/contract-lock.json
|
|
@@ -65,7 +78,13 @@ The workflow:
|
|
|
65
78
|
|
|
66
79
|
- resolves the Buildchain runtime and checks the floating contract lock before
|
|
67
80
|
any paper build runs;
|
|
68
|
-
-
|
|
81
|
+
- resolves the declared publication toolchain from `[publication.toolchain]` or
|
|
82
|
+
workflow inputs;
|
|
83
|
+
- for `latex-docker`, pulls the pinned image digest and runs the declared
|
|
84
|
+
command in the container;
|
|
85
|
+
- for `custom-command`, runs the declared command and records the lower-trust
|
|
86
|
+
boundary in the passport;
|
|
87
|
+
- runs the verify command;
|
|
69
88
|
- creates a source bundle from `publication.source_paths`;
|
|
70
89
|
- writes `.buildchain/publication/publication-artifact.json`;
|
|
71
90
|
- writes `.buildchain/publication/publication-artifact-passport.json`;
|
|
@@ -101,6 +120,8 @@ the reusable workflow. The generated manifest records:
|
|
|
101
120
|
- artifact paths, byte sizes, and SHA-256 digests;
|
|
102
121
|
- metadata paths and SHA-256 digests;
|
|
103
122
|
- source SHA, tree SHA, source files, and source bundle digest;
|
|
123
|
+
- publication toolchain type, image, digest, command, invocation mode, and trust
|
|
124
|
+
classification;
|
|
104
125
|
- timestamp and reproducibility policy;
|
|
105
126
|
- downstream site-consumption hints.
|
|
106
127
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -49,6 +49,7 @@ const SUPPORTED_INFRA_ADOPTION_MODES = new Set([
|
|
|
49
49
|
const SUPPORTED_INFRA_APPLY_MODES = new Set(["disabled", "manual-approval", "environment-approval"]);
|
|
50
50
|
const SUPPORTED_FACT_VERSION_SOURCE_TYPES = new Set(["static", "json", "toml", "regex", "command"]);
|
|
51
51
|
const SUPPORTED_FACT_LEGACY_PROJECTIONS = new Set(["kungfu-buildinfo"]);
|
|
52
|
+
const SUPPORTED_PUBLICATION_TOOLCHAINS = new Set(["custom-command", "latex-docker"]);
|
|
52
53
|
|
|
53
54
|
function posixPath(value) {
|
|
54
55
|
return String(value || "").split(path.sep).join("/");
|
|
@@ -389,6 +390,7 @@ function normalizePublicationSection(publication) {
|
|
|
389
390
|
metadataPaths: normalizeStringArray(publication.metadata_paths, "publication.metadata_paths").map(posixPath),
|
|
390
391
|
sourcePaths: normalizeStringArray(publication.source_paths, "publication.source_paths").map(posixPath),
|
|
391
392
|
siteConsumers: normalizeStringArray(publication.site_consumers, "publication.site_consumers"),
|
|
393
|
+
toolchain: normalizePublicationToolchain(publication.toolchain),
|
|
392
394
|
manifestPath: publication.manifest_path === undefined
|
|
393
395
|
? ".buildchain/publication/publication-artifact.json"
|
|
394
396
|
: posixPath(assertString(publication.manifest_path, "publication.manifest_path")),
|
|
@@ -398,6 +400,49 @@ function normalizePublicationSection(publication) {
|
|
|
398
400
|
};
|
|
399
401
|
}
|
|
400
402
|
|
|
403
|
+
function normalizePublicationToolchain(toolchain = undefined) {
|
|
404
|
+
if (toolchain === undefined) {
|
|
405
|
+
return {
|
|
406
|
+
type: "custom-command",
|
|
407
|
+
image: "",
|
|
408
|
+
digest: "",
|
|
409
|
+
command: "",
|
|
410
|
+
trustClassification: "custom-command",
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
assertPlainObject(toolchain, "publication.toolchain");
|
|
414
|
+
const type = toolchain.type === undefined
|
|
415
|
+
? "custom-command"
|
|
416
|
+
: assertString(toolchain.type, "publication.toolchain.type");
|
|
417
|
+
if (!SUPPORTED_PUBLICATION_TOOLCHAINS.has(type)) {
|
|
418
|
+
throw new Error("publication.toolchain.type must be one of custom-command or latex-docker");
|
|
419
|
+
}
|
|
420
|
+
const command = toolchain.command === undefined
|
|
421
|
+
? ""
|
|
422
|
+
: assertString(toolchain.command, "publication.toolchain.command");
|
|
423
|
+
const image = toolchain.image === undefined
|
|
424
|
+
? ""
|
|
425
|
+
: assertString(toolchain.image, "publication.toolchain.image");
|
|
426
|
+
const digest = toolchain.digest === undefined
|
|
427
|
+
? ""
|
|
428
|
+
: assertString(toolchain.digest, "publication.toolchain.digest");
|
|
429
|
+
if (type === "latex-docker") {
|
|
430
|
+
if (!image) throw new Error("publication.toolchain.image is required for latex-docker");
|
|
431
|
+
if (!digest) throw new Error("publication.toolchain.digest is required for latex-docker");
|
|
432
|
+
if (!/^sha256:[0-9a-f]{64}$/i.test(digest)) {
|
|
433
|
+
throw new Error("publication.toolchain.digest must be a sha256:<64 hex> image digest");
|
|
434
|
+
}
|
|
435
|
+
if (!command) throw new Error("publication.toolchain.command is required for latex-docker");
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
type,
|
|
439
|
+
image,
|
|
440
|
+
digest,
|
|
441
|
+
command,
|
|
442
|
+
trustClassification: type === "latex-docker" ? "pinned-docker-toolchain" : "custom-command",
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
401
446
|
function normalizeInfraSection(infra) {
|
|
402
447
|
assertPlainObject(infra, "infra");
|
|
403
448
|
const adapter = assertString(infra.adapter, "infra.adapter");
|
|
@@ -6,6 +6,7 @@ import { loadBuildchainConfig } from "./buildchain-config.js";
|
|
|
6
6
|
|
|
7
7
|
export const PUBLICATION_ARTIFACT_MANIFEST_CONTRACT = "kungfu-buildchain-publication-artifact-manifest";
|
|
8
8
|
export const PUBLICATION_ARTIFACT_PASSPORT_CONTRACT = "kungfu-buildchain-publication-artifact-passport";
|
|
9
|
+
const KFD2_RESIDUAL_RISK_SCHEMA = "https://kfd.libkungfu.dev/schemas/kfd-2/trust-taxonomy.schema.json#/$defs/residualRisk";
|
|
9
10
|
|
|
10
11
|
function toPosix(value) {
|
|
11
12
|
return String(value || "").split(path.sep).join("/");
|
|
@@ -74,6 +75,69 @@ function createdAt(now = new Date()) {
|
|
|
74
75
|
return now.toISOString();
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
function publicationToolchainFacts(publication) {
|
|
79
|
+
const envType = String(process.env.BUILDCHAIN_PUBLICATION_TOOLCHAIN_TYPE || "").trim();
|
|
80
|
+
const envToolchain = envType
|
|
81
|
+
? {
|
|
82
|
+
type: envType,
|
|
83
|
+
image: process.env.BUILDCHAIN_PUBLICATION_TOOLCHAIN_IMAGE || "",
|
|
84
|
+
digest: process.env.BUILDCHAIN_PUBLICATION_TOOLCHAIN_DIGEST || "",
|
|
85
|
+
command: process.env.BUILDCHAIN_PUBLICATION_TOOLCHAIN_COMMAND || "",
|
|
86
|
+
trustClassification: envType === "latex-docker" ? "pinned-docker-toolchain" : "custom-command",
|
|
87
|
+
}
|
|
88
|
+
: undefined;
|
|
89
|
+
const toolchain = publication.toolchain || {
|
|
90
|
+
type: "custom-command",
|
|
91
|
+
image: "",
|
|
92
|
+
digest: "",
|
|
93
|
+
command: "",
|
|
94
|
+
trustClassification: "custom-command",
|
|
95
|
+
};
|
|
96
|
+
const resolved = envToolchain || toolchain;
|
|
97
|
+
const facts = {
|
|
98
|
+
type: resolved.type,
|
|
99
|
+
trustClassification: resolved.trustClassification || (resolved.type === "latex-docker" ? "pinned-docker-toolchain" : "custom-command"),
|
|
100
|
+
command: resolved.command || "",
|
|
101
|
+
image: resolved.image || "",
|
|
102
|
+
digest: resolved.digest || "",
|
|
103
|
+
machineVerifiable: resolved.type === "latex-docker" && Boolean(resolved.image && resolved.digest && resolved.command),
|
|
104
|
+
};
|
|
105
|
+
facts.invocation = facts.type === "latex-docker"
|
|
106
|
+
? "docker-image-digest"
|
|
107
|
+
: "caller-provided-command";
|
|
108
|
+
return facts;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function publicationResidualRisk(toolchainFacts) {
|
|
112
|
+
const risks = [
|
|
113
|
+
{
|
|
114
|
+
id: "publication-semantic-review",
|
|
115
|
+
definedBy: KFD2_RESIDUAL_RISK_SCHEMA,
|
|
116
|
+
riskType: "natural-language-semantic-risk",
|
|
117
|
+
trustImpact: "downgrade-warning",
|
|
118
|
+
machineProvability: "not-machine-verifiable",
|
|
119
|
+
agentAction: "semantic-review-required",
|
|
120
|
+
owner: "publication maintainers",
|
|
121
|
+
reason: "Buildchain verifies declared files and hashes; it does not peer-review paper claims.",
|
|
122
|
+
note: "Buildchain verifies declared files and hashes; it does not peer-review paper claims.",
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
if (toolchainFacts.type === "custom-command") {
|
|
126
|
+
risks.push({
|
|
127
|
+
id: "publication-custom-build-toolchain",
|
|
128
|
+
definedBy: KFD2_RESIDUAL_RISK_SCHEMA,
|
|
129
|
+
riskType: "natural-language-semantic-risk",
|
|
130
|
+
trustImpact: "downgrade-warning",
|
|
131
|
+
machineProvability: "not-machine-verifiable",
|
|
132
|
+
agentAction: "semantic-review-required",
|
|
133
|
+
owner: "publication maintainers",
|
|
134
|
+
reason: "The source-to-publication build is a caller-provided command, so Buildchain records the command boundary but cannot prove a pinned compiler or LaTeX image digest.",
|
|
135
|
+
note: "Use publication.toolchain.type = \"latex-docker\" with an image digest to make the PDF build toolchain machine-auditable.",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return risks;
|
|
139
|
+
}
|
|
140
|
+
|
|
77
141
|
export function createPublicationSourceBundle({
|
|
78
142
|
cwd = process.cwd(),
|
|
79
143
|
sourcePaths = [],
|
|
@@ -130,6 +194,7 @@ export function collectPublicationArtifact({
|
|
|
130
194
|
const resolvedSourceSha = sourceSha || gitValue(cwd, ["rev-parse", "HEAD"]);
|
|
131
195
|
const sourceTreeSha = gitValue(cwd, ["rev-parse", `${resolvedSourceSha}^{tree}`]);
|
|
132
196
|
const timestamp = generatedAt || createdAt();
|
|
197
|
+
const toolchain = publicationToolchainFacts(publication);
|
|
133
198
|
const manifest = {
|
|
134
199
|
schemaVersion: 1,
|
|
135
200
|
contract: PUBLICATION_ARTIFACT_MANIFEST_CONTRACT,
|
|
@@ -146,6 +211,7 @@ export function collectPublicationArtifact({
|
|
|
146
211
|
primaryArtifact: publication.primaryArtifact,
|
|
147
212
|
siteConsumers: publication.siteConsumers,
|
|
148
213
|
},
|
|
214
|
+
toolchain,
|
|
149
215
|
source: {
|
|
150
216
|
repository: gitValue(cwd, ["config", "--get", "remote.origin.url"]),
|
|
151
217
|
sha: resolvedSourceSha,
|
|
@@ -183,6 +249,7 @@ export function collectPublicationArtifact({
|
|
|
183
249
|
status: "passed",
|
|
184
250
|
manifestDigest: `sha256:${sha256Buffer(Buffer.from(JSON.stringify(manifest, null, 2)))}`,
|
|
185
251
|
source: manifest.source,
|
|
252
|
+
toolchain,
|
|
186
253
|
artifacts: manifest.artifacts,
|
|
187
254
|
responsibility: {
|
|
188
255
|
producer: "publication repository",
|
|
@@ -195,6 +262,9 @@ export function collectPublicationArtifact({
|
|
|
195
262
|
"declared publication metadata files exist",
|
|
196
263
|
"declared publication source files are hashed",
|
|
197
264
|
"source bundle digest is recorded",
|
|
265
|
+
toolchain.machineVerifiable
|
|
266
|
+
? "publication PDF build toolchain image digest is declared"
|
|
267
|
+
: "publication build command boundary is recorded",
|
|
198
268
|
],
|
|
199
269
|
outsideBoundary: [
|
|
200
270
|
"paper scientific claims",
|
|
@@ -202,15 +272,7 @@ export function collectPublicationArtifact({
|
|
|
202
272
|
"human review of publication content",
|
|
203
273
|
],
|
|
204
274
|
},
|
|
205
|
-
residualRisk:
|
|
206
|
-
{
|
|
207
|
-
riskType: "natural-language-semantic-risk",
|
|
208
|
-
trustImpact: "downgrade-warning",
|
|
209
|
-
machineProvability: "not-machine-verifiable",
|
|
210
|
-
agentAction: "semantic-review-required",
|
|
211
|
-
note: "Buildchain verifies declared files and hashes; it does not peer-review paper claims.",
|
|
212
|
-
},
|
|
213
|
-
],
|
|
275
|
+
residualRisk: publicationResidualRisk(toolchain),
|
|
214
276
|
},
|
|
215
277
|
};
|
|
216
278
|
}
|
package/scripts/init-repo.mjs
CHANGED
|
@@ -258,6 +258,10 @@ site_consumers = ["papers-site"]
|
|
|
258
258
|
manifest_path = ".buildchain/publication/publication-artifact.json"
|
|
259
259
|
source_bundle_path = ".buildchain/publication/source.tar.gz"
|
|
260
260
|
|
|
261
|
+
[publication.toolchain]
|
|
262
|
+
type = "custom-command"
|
|
263
|
+
command = "make pdf"
|
|
264
|
+
|
|
261
265
|
[lifecycle.build]
|
|
262
266
|
command = "make pdf"
|
|
263
267
|
|
|
@@ -343,7 +347,7 @@ jobs:
|
|
|
343
347
|
uses: kungfu-systems/buildchain/.github/workflows/publication-artifact.yml@v2
|
|
344
348
|
with:
|
|
345
349
|
buildchain-ref: \${{ inputs.buildchain-ref || '' }}
|
|
346
|
-
|
|
350
|
+
toolchain-type: config
|
|
347
351
|
verify-command: make check
|
|
348
352
|
artifact-name: publication-artifact
|
|
349
353
|
`;
|