@kungfu-tech/buildchain 3.0.6 → 3.0.7-alpha.0

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.
Files changed (64) hide show
  1. package/README.md +4 -2
  2. package/actions/release-tail/README.md +17 -0
  3. package/bin/buildchain.mjs +11 -0
  4. package/bin/internal/command-registry.mjs +2 -0
  5. package/contracts/fixtures/release-tail-capabilities-v1/kungfu-alpha.json +273 -0
  6. package/contracts/publication-rehearsal-capsule-v1.schema.json +173 -0
  7. package/contracts/release-tail-capabilities-v1.schema.json +199 -0
  8. package/contracts/release-tail-provider-bindings-v1.schema.json +56 -0
  9. package/dist/site/agent-index.json +3 -0
  10. package/dist/site/artifact-schemas.json +6 -0
  11. package/dist/site/buildchain-contract.json +35 -20
  12. package/dist/site/buildchain-site.json +307 -17
  13. package/dist/site/capability-registry.json +12 -9
  14. package/dist/site/cli-registry.json +102 -0
  15. package/dist/site/controller-registry.json +14 -2
  16. package/dist/site/kfd-claims.json +247 -16
  17. package/dist/site/kfd-upstream-aggregate.json +1 -1
  18. package/dist/site/manual-registry.json +48 -3
  19. package/dist/site/node-api-registry.json +3108 -1409
  20. package/dist/site/page-registry.json +275 -9
  21. package/dist/site/public-surface-audit.json +304 -15
  22. package/dist/site/publication-authority-registry.json +26 -1
  23. package/dist/site/publication-registry.json +4 -4
  24. package/dist/site/release-provenance.json +5 -0
  25. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +269 -0
  26. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +353 -0
  27. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +94 -0
  28. package/dist/site/site-manifest.json +31 -7
  29. package/dist/site/workflow-registry.json +86 -9
  30. package/docs/MAP.md +5 -2
  31. package/docs/cli-reference.md +136 -0
  32. package/docs/node-api-reference.md +233 -84
  33. package/docs/publication-rehearsal.md +94 -0
  34. package/docs/release-tail-contract.md +160 -0
  35. package/docs/release-tail-provider-plane.md +120 -0
  36. package/package.json +8 -3
  37. package/packages/core/buildchain-agent-manuals.js +3 -0
  38. package/packages/core/buildchain-kfd-claims.js +1 -1
  39. package/packages/core/buildchain-publication-authority.js +1 -0
  40. package/packages/core/index.js +39 -0
  41. package/packages/core/paper-agent-entry.js +11 -5
  42. package/packages/core/paper-repository.js +1 -0
  43. package/packages/core/paper-scaffold-content.js +21 -0
  44. package/packages/core/paper.js +28 -2
  45. package/packages/core/publication-rehearsal-projection.js +173 -0
  46. package/packages/core/publication-rehearsal-runtime.js +909 -0
  47. package/packages/core/release-tail-compatibility.js +60 -0
  48. package/packages/core/release-tail-provider-adapters.js +461 -0
  49. package/packages/core/release-tail-provider-plane.js +1228 -0
  50. package/scripts/assemble-publication-artifact-admission.mjs +1 -1
  51. package/scripts/assemble-self-publication-admission.mjs +1 -1
  52. package/scripts/buildchain-cli-help.mjs +13 -0
  53. package/scripts/check-core-mechanism-inventory.mjs +347 -0
  54. package/scripts/check-inventory.mjs +8 -8
  55. package/scripts/check-maintainability.mjs +9 -2
  56. package/scripts/check-release-tail-contract.mjs +435 -0
  57. package/scripts/generate-channel-promotion-workflow.mjs +10 -8
  58. package/scripts/generate-site-bundle.mjs +24 -0
  59. package/scripts/init-repo.mjs +26 -2
  60. package/scripts/materialize-self-release-candidate-version.mjs +131 -0
  61. package/scripts/release-tail.mjs +159 -0
  62. package/scripts/site-capability-metadata.mjs +11 -0
  63. package/scripts/v4-architecture.mjs +600 -0
  64. package/scripts/workflow-call-contract.mjs +184 -5
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import {
5
+ getVersionStrategy,
6
+ loadConfiguredAnchorManifest,
7
+ } from "../packages/core/buildchain-config.js";
8
+ import {
9
+ alignMajorBootstrapReleaseImpact,
10
+ currentConfiguredVersion,
11
+ discoverVersionStateFiles,
12
+ runVersionVerification,
13
+ updateVersionStateContents,
14
+ versionVerificationAllowedPathsForPromotion,
15
+ versionVerificationEnv,
16
+ } from "../actions/promote-buildchain-ref/internal/version-state.js";
17
+
18
+ function required(value, name) {
19
+ const normalized = String(value || "").trim();
20
+ if (!normalized) throw new Error(`${name} is required`);
21
+ return normalized;
22
+ }
23
+
24
+ function parseArgs(argv) {
25
+ const options = {};
26
+ for (let index = 0; index < argv.length; index += 1) {
27
+ const argument = argv[index];
28
+ if (!argument.startsWith("--")) throw new Error(`unexpected argument: ${argument}`);
29
+ const name = argument.slice(2);
30
+ const value = argv[index + 1];
31
+ if (!value || value.startsWith("--")) throw new Error(`--${name} requires a value`);
32
+ options[name] = value;
33
+ index += 1;
34
+ }
35
+ return options;
36
+ }
37
+
38
+ export function materializeSelfReleaseCandidateVersion({
39
+ cwd = process.cwd(),
40
+ version,
41
+ channel,
42
+ sourceSha,
43
+ generatedAt,
44
+ } = {}) {
45
+ const resolvedVersion = required(version, "version");
46
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(resolvedVersion)) {
47
+ throw new Error(`version must be an exact semantic version: ${resolvedVersion}`);
48
+ }
49
+ const resolvedChannel = required(channel, "channel");
50
+ if (!new Set(["alpha", "release", "major"]).has(resolvedChannel)) {
51
+ throw new Error(`channel must be alpha, release, or major: ${resolvedChannel}`);
52
+ }
53
+ const resolvedSourceSha = required(sourceSha, "sourceSha");
54
+ if (!/^[0-9a-f]{40}$/i.test(resolvedSourceSha)) {
55
+ throw new Error("sourceSha must be a 40-character Git SHA");
56
+ }
57
+ const resolvedGeneratedAt = required(generatedAt, "generatedAt");
58
+ if (Number.isNaN(Date.parse(resolvedGeneratedAt))) {
59
+ throw new Error(`generatedAt must be an ISO timestamp: ${resolvedGeneratedAt}`);
60
+ }
61
+
62
+ const discovered = discoverVersionStateFiles(cwd);
63
+ if (discovered.files.length === 0) {
64
+ throw new Error("self-release candidate requires declared version state");
65
+ }
66
+ const discoveredPaths = discovered.files.map((file) => file.path);
67
+ const versionStrategy = getVersionStrategy(discovered.config);
68
+ const anchorManifest = loadConfiguredAnchorManifest(cwd, discovered.config);
69
+ const lifecycleEnv = versionVerificationEnv(versionStrategy, anchorManifest, {
70
+ generatedAt: resolvedGeneratedAt,
71
+ sourceSha: resolvedSourceSha,
72
+ });
73
+ if (resolvedChannel === "major") {
74
+ lifecycleEnv.BUILDCHAIN_MAJOR_VERSION_BOOTSTRAP = "true";
75
+ }
76
+
77
+ let changedFiles = updateVersionStateContents(discovered.files, resolvedVersion);
78
+ if (resolvedChannel === "major") {
79
+ changedFiles = alignMajorBootstrapReleaseImpact(changedFiles, {
80
+ version: resolvedVersion,
81
+ });
82
+ }
83
+ const materializedFiles = runVersionVerification({
84
+ cwd,
85
+ loadedConfig: discovered.config,
86
+ version: resolvedVersion,
87
+ changedFiles,
88
+ allowedPaths: versionVerificationAllowedPathsForPromotion(
89
+ resolvedChannel,
90
+ discoveredPaths,
91
+ ),
92
+ env: lifecycleEnv,
93
+ runLifecycleVerify: false,
94
+ });
95
+ const materialized = discoverVersionStateFiles(cwd);
96
+ const actualVersion = currentConfiguredVersion(materialized.files);
97
+ if (actualVersion !== resolvedVersion) {
98
+ throw new Error(
99
+ `materialized self-release candidate version mismatch: expected ${resolvedVersion}, got ${actualVersion || "<empty>"}`,
100
+ );
101
+ }
102
+ return {
103
+ schemaVersion: 1,
104
+ contract: "kungfu-buildchain-self-release-candidate-version/v1",
105
+ version: resolvedVersion,
106
+ channel: resolvedChannel,
107
+ sourceSha: resolvedSourceSha,
108
+ generatedAt: resolvedGeneratedAt,
109
+ files: materializedFiles.map((file) => file.path),
110
+ };
111
+ }
112
+
113
+ export function materializeSelfReleaseCandidateVersionCli(argv = process.argv.slice(2)) {
114
+ const options = parseArgs(argv);
115
+ const result = materializeSelfReleaseCandidateVersion({
116
+ cwd: path.resolve(options.cwd || process.cwd()),
117
+ version: options.version,
118
+ channel: options.channel,
119
+ sourceSha: options["source-sha"],
120
+ generatedAt: options["generated-at"],
121
+ });
122
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
123
+ return result;
124
+ }
125
+
126
+ if (
127
+ process.argv[1] &&
128
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href
129
+ ) {
130
+ materializeSelfReleaseCandidateVersionCli();
131
+ }
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+
6
+ import {
7
+ compileReleaseTailDeclaration,
8
+ createReleaseTailTransaction,
9
+ readReleaseTailTransaction,
10
+ validateReleaseTailTransaction,
11
+ writeReleaseTailTransaction,
12
+ } from "../packages/core/release-tail-provider-plane.js";
13
+ import { diagnoseLegacyReleaseTailHooks } from "../packages/core/release-tail-compatibility.js";
14
+ import {
15
+ executePublicationRehearsal,
16
+ publicationRehearsalDiagnostic,
17
+ } from "../packages/core/publication-rehearsal-runtime.js";
18
+
19
+ function flag(args, name, fallback = "") {
20
+ const index = args.indexOf(`--${name}`);
21
+ return index < 0 ? fallback : args[index + 1] || "";
22
+ }
23
+
24
+ function readJson(value, label) {
25
+ if (!value) throw new Error(`${label} is required`);
26
+ const filePath = path.resolve(value);
27
+ if (fs.existsSync(filePath))
28
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
29
+ return JSON.parse(value);
30
+ }
31
+
32
+ function output(value, filePath = "") {
33
+ if (filePath) {
34
+ const resolved = path.resolve(filePath);
35
+ fs.mkdirSync(path.dirname(resolved), { recursive: true });
36
+ fs.writeFileSync(resolved, `${JSON.stringify(value, null, 2)}\n`);
37
+ }
38
+ process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
39
+ }
40
+
41
+ export async function runReleaseTailCli(args = process.argv.slice(2)) {
42
+ const [mode = "status", ...options] = args;
43
+ if (mode === "rehearse") {
44
+ const capsulePath = flag(options, "capsule");
45
+ const capsuleRoot = flag(options, "capsule-root");
46
+ const statePath = flag(options, "state");
47
+ const evidencePath = flag(options, "evidence");
48
+ for (const [name, value] of Object.entries({
49
+ "--capsule": capsulePath,
50
+ "--capsule-root": capsuleRoot,
51
+ "--state": statePath,
52
+ "--evidence": evidencePath,
53
+ })) {
54
+ if (!value || !path.isAbsolute(value)) {
55
+ throw new Error(`${name} must be an explicit absolute path`);
56
+ }
57
+ }
58
+ const capsule = readJson(capsulePath, "--capsule");
59
+ const rehearsalMode = flag(options, "mode", "simulate");
60
+ if (!new Set(["simulate", "replay"]).has(rehearsalMode)) {
61
+ throw new Error("local rehearsal --mode must be simulate or replay");
62
+ }
63
+ const environment = flag(options, "environment-json")
64
+ ? readJson(flag(options, "environment-json"), "--environment-json")
65
+ : {};
66
+ let result;
67
+ try {
68
+ result = await executePublicationRehearsal({
69
+ capsule,
70
+ capsuleRoot,
71
+ mode: rehearsalMode,
72
+ environment,
73
+ checkpoint: (transaction) =>
74
+ writeReleaseTailTransaction(statePath, transaction),
75
+ });
76
+ } catch (error) {
77
+ const diagnostic = publicationRehearsalDiagnostic(error, { capsule });
78
+ output(diagnostic, evidencePath);
79
+ throw error;
80
+ }
81
+ writeReleaseTailTransaction(statePath, result.transaction);
82
+ output(result.evidence, evidencePath);
83
+ return result;
84
+ }
85
+ if (mode === "plan") {
86
+ const plan = compileReleaseTailDeclaration(
87
+ readJson(flag(options, "declaration"), "--declaration"),
88
+ );
89
+ output(plan, flag(options, "output"));
90
+ return plan;
91
+ }
92
+ if (mode === "init") {
93
+ const transaction = createReleaseTailTransaction(
94
+ readJson(flag(options, "declaration"), "--declaration"),
95
+ );
96
+ const statePath = flag(
97
+ options,
98
+ "state",
99
+ ".buildchain/release-tail/state.json",
100
+ );
101
+ writeReleaseTailTransaction(statePath, transaction);
102
+ output(transaction);
103
+ return transaction;
104
+ }
105
+ if (mode === "status" || mode === "verify") {
106
+ const statePath = flag(
107
+ options,
108
+ "state",
109
+ ".buildchain/release-tail/state.json",
110
+ );
111
+ const transaction = readReleaseTailTransaction(statePath);
112
+ const validation = validateReleaseTailTransaction(transaction);
113
+ const nextOperation = transaction.operations.find(
114
+ (entry) => entry.status === "pending",
115
+ );
116
+ const report = {
117
+ schema: "kungfu.buildchain.release-tail.status/v1",
118
+ ok: validation.valid,
119
+ state: transaction.state,
120
+ stateRoot: transaction.stateRoot,
121
+ transactionRoot: transaction.transactionRoot,
122
+ nextOperation: nextOperation
123
+ ? {
124
+ operationId: nextOperation.operationId,
125
+ capabilityId: nextOperation.capabilityId,
126
+ adapter: nextOperation.effect.adapter,
127
+ }
128
+ : null,
129
+ receiptRoots: transaction.receipts.map((receipt) => receipt.receiptRoot),
130
+ issues: validation.issues,
131
+ };
132
+ output(report, flag(options, "output"));
133
+ return report;
134
+ }
135
+ if (mode === "compat") {
136
+ const report = diagnoseLegacyReleaseTailHooks(
137
+ readJson(flag(options, "hooks-json"), "--hooks-json"),
138
+ );
139
+ output(report, flag(options, "output"));
140
+ if (!report.compatible) process.exitCode = 1;
141
+ return report;
142
+ }
143
+ throw new Error(
144
+ "usage: buildchain release-tail <plan|init|status|verify|compat|rehearse> [--declaration <json-or-path>] [--capsule <path>] [--capsule-root <absolute-path>] [--mode <simulate|replay>] [--state <path>] [--evidence <path>] [--hooks-json <json-or-path>] [--output <path>]",
145
+ );
146
+ }
147
+
148
+ if (
149
+ !process.env.BUILDCHAIN_EMBEDDED_ENTRYPOINT &&
150
+ process.argv[1] &&
151
+ import.meta.url === pathToFileURL(process.argv[1]).href
152
+ ) {
153
+ try {
154
+ await runReleaseTailCli();
155
+ } catch (error) {
156
+ console.error(`release-tail: ${error.message}`);
157
+ process.exitCode = 1;
158
+ }
159
+ }
@@ -12,6 +12,11 @@ function capabilityGroup(id) {
12
12
  export function cliCommandMeta(id) {
13
13
  const map = new Map(Object.entries({
14
14
  audit: { group: "release-passport-trust", purpose: "Inspect read-only publication authority audit commands." },
15
+ architecture: { group: "governance-versioning", purpose: "Inspect and qualify the Buildchain v4 capability and state-machine architecture contract." },
16
+ "architecture-list": { group: "governance-versioning", purpose: "Generate the Agent-readable capability list from the validated v4 architecture manifest." },
17
+ "architecture-qualify": { group: "governance-versioning", purpose: "Qualify an exact candidate against a distinct N-1 Git authority revision without candidate self-qualification." },
18
+ "architecture-show": { group: "governance-versioning", purpose: "Generate one capability and its state-machine details from the validated v4 architecture manifest." },
19
+ "architecture-validate": { group: "governance-versioning", purpose: "Validate v4 dependency direction, ownership, writers, budgets, recovery declarations, and exception policy." },
15
20
  "audit-publication-control-plane": { group: "release-passport-trust", purpose: "Read GitHub publication controls, bind provider-enforced npm identity, and emit a sanitized expiring receipt." },
16
21
  "audit-github-governance": { group: "governance-versioning", purpose: "Read the managed GitHub zone, aggregate native protection and ownership, and emit sanitized fail-closed governance receipts." },
17
22
  badges: { group: "distribution-indexes", purpose: "Inspect README badge command families." },
@@ -134,6 +139,7 @@ export function cliCommandMeta(id) {
134
139
  "release-line-open": { group: "governance-versioning", purpose: "Plan or write the initial version-state commit for a new minor release line." },
135
140
  "release-governance": { group: "governance-versioning", purpose: "Reconcile a managed branch's Buildchain aggregate check to an already-tested pull request SHA." },
136
141
  "release-propagation": { group: "site-and-propagation", purpose: "Route exact Paper, KFD, Buildchain, or Core Site updates through one resumable propagation Work." },
142
+ "release-tail": { group: "release-passport-trust", purpose: "Plan, initialize, rehearse, resume, and verify one declarative provider-owned release-tail transaction." },
137
143
  "release-transaction": { group: "release-passport-trust", purpose: "Inspect, recover, finalize, or abort durable release transactions." },
138
144
  sample: { group: "observability-diagnostics", purpose: "Inspect sampler command families." },
139
145
  "sample-process-tree": { group: "observability-diagnostics", purpose: "Sample process-tree diagnostics for a wrapped command." },
@@ -197,6 +203,11 @@ export function nodeApiMeta(exportName) {
197
203
  "./stable-candidate-ledger": { group: "governance-versioning", summary: "Immutable alpha candidate ledger, qualification, revocation, selection, and exact stable source-lock APIs." },
198
204
  "./release-propagation": { group: "site-and-propagation", summary: "Release propagation graph, plan, and exact upstream lock APIs." },
199
205
  "./release-activation-transaction": { group: "release-passport-trust", summary: "Ordered cross-repository activation, exact receipt-set binding, retry, abort, rollback, and shadow-rehearsal APIs." },
206
+ "./release-tail-provider-plane": { group: "release-passport-trust", summary: "Versioned declarative release-tail parsing, deterministic effect planning, durable transaction execution, readback, retry, and rooted receipt APIs." },
207
+ "./release-tail-provider-adapters": { group: "release-passport-trust", summary: "Buildchain-owned GitHub Release, signed-channel, activation, and released-evidence provider adapters." },
208
+ "./release-tail-compatibility": { group: "release-passport-trust", summary: "Bounded v3 release-hook compatibility diagnostics that reject new executable release-tail inputs." },
209
+ "./publication-rehearsal-runtime": { group: "release-passport-trust", summary: "Content-addressed local, replay, and provider-recording publication rehearsal over the shared release-tail core." },
210
+ "./publication-rehearsal-projection": { group: "release-passport-trust", summary: "Canonical generated config, workflow, and Agent projections for release local constructibility." },
200
211
  "./release-line-bootstrap": { group: "governance-versioning", summary: "Semver release-line bootstrap planning and version-state APIs." },
201
212
  "./buildchain-contract": { group: "governance-versioning", summary: "Runtime contract world and compatibility digest APIs for floating-ref drift checks." },
202
213
  "./controller-evidence": { group: "reusable-build", summary: "Project-independent controller descriptors, source/runtime-bound plans, receipts, aggregates, and validation APIs." },