From 5fd8fb763ead40f1cc62340ac41f148b031c0679 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 04:42:09 +0200 Subject: [PATCH 01/13] Implement beta8 compiler functionality gate --- .brik/manifest.json | 2 +- CHANGELOG.md | 29 + README.md | 17 +- evidence/beta8-adversarial/report.json | 47 + .../beta8-compiler-functionality/report.json | 49 + evidence/beta8-package-smoke/report.json | 35 + evidence/beta8-package/SHA256SUMS | 3 + .../beta8-package/brik64-cli-0.1.0-beta.8.tgz | Bin 0 -> 24501 bytes evidence/beta8-package/package.manifest.json | 28 + evidence/beta8-package/stage-checksums.tsv | 19 + .../.brik/manifest.json | 53 + .../brik64-cli-0.1.0-beta.8/CHANGELOG.md | 137 ++ .../stage/brik64-cli-0.1.0-beta.8/LICENSE | 71 + .../stage/brik64-cli-0.1.0-beta.8/NOTICE | 18 + .../stage/brik64-cli-0.1.0-beta.8/README.md | 119 ++ .../stage/brik64-cli-0.1.0-beta.8/SECURITY.md | 54 + .../engines/l4plus-n5/checksums.tsv | 42 + .../l4plus-n5/runtime-bundle.manifest.json | 147 ++ .../engines/l4plus-n5/serial.txt | 1 + .../evidence/beta8-adversarial/report.json | 47 + .../beta8-compiler-functionality/report.json | 49 + .../brik64-cli-0.1.0-beta.8/package.json | 13 + .../pcd/cli_account_session.pcd | 31 + .../brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd | 33 + .../pcd/cli_migrate.pcd | 27 + .../pcd/cli_polymer.pcd | 59 + .../pcd/cli_polymerize.pcd | 29 + .../pcd/cli_verify.pcd | 30 + .../stage/brik64-cli-0.1.0-beta.8/src/brik.js | 1231 +++++++++++++++++ .../release-manifest-validate/report.json | 49 +- evidence/release-train-dry-run/report.json | 169 ++- package.json | 6 +- release/manifest.json | 49 +- scripts/beta8-adversarial-gate.sh | 278 ++++ scripts/beta8-compiler-functionality-gate.sh | 189 +++ scripts/beta8-package-smoke.sh | 155 +++ scripts/build-beta8-package.sh | 161 +++ scripts/release-train-dry-run.js | 26 +- src/brik.js | 466 ++++++- tests/smoke.sh | 25 +- 40 files changed, 3797 insertions(+), 196 deletions(-) create mode 100644 evidence/beta8-adversarial/report.json create mode 100644 evidence/beta8-compiler-functionality/report.json create mode 100644 evidence/beta8-package-smoke/report.json create mode 100644 evidence/beta8-package/SHA256SUMS create mode 100644 evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz create mode 100644 evidence/beta8-package/package.manifest.json create mode 100644 evidence/beta8-package/stage-checksums.tsv create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd create mode 100644 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd create mode 100755 evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js create mode 100644 scripts/beta8-adversarial-gate.sh create mode 100755 scripts/beta8-compiler-functionality-gate.sh create mode 100644 scripts/beta8-package-smoke.sh create mode 100644 scripts/build-beta8-package.sh diff --git a/.brik/manifest.json b/.brik/manifest.json index e092fd5a..225e72b6 100644 --- a/.brik/manifest.json +++ b/.brik/manifest.json @@ -2,7 +2,7 @@ "schema": "brik64.cli_project_manifest.v1", "schemaVersion": "brik64.cli_project_manifest.v1", "project": "brik64-cli", - "cliVersion": "0.1.0-beta.7", + "cliVersion": "0.1.0-beta.8", "lane": "cli_0_1_beta", "generationClaim": "assisted_generation_non_claim", "preferred_engine": "auto", diff --git a/CHANGELOG.md b/CHANGELOG.md index 61ad3923..8245da2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,35 @@ All notable BRIK64 CLI changes are recorded here. This file is required for every beta, release candidate, or public release train. +## 0.1.0-beta.8 + +### Added + +- Adds bounded source-to-source PCD emission for executable TypeScript, Rust, + and Python programs. +- Adds generated target tests that execute emitted programs and check expected + behavior across supported target languages. +- Adds parser support for arithmetic expressions, comparisons, boolean + conditions, nested branches, and expression returns. +- Adds adversarial parser coverage for malformed input, binary data, oversized + PCD files, unsupported statements, and path traversal attempts. +- Adds a local package smoke check that extracts the beta8 tarball and runs the + packaged CLI outside the repository checkout. + +### Changed + +- Updates `brik64 emit` from static candidate output toward executable output + for the supported beta PCD syntax. +- Keeps unsupported syntax fail-closed with actionable parser errors. + +### Compatibility + +- macOS and Linux continue to use the portable Node.js CLI package and require + Node.js 20 or newer. +- Windows native executables are not published in this beta. +- This beta does not claim formal certification for arbitrary user code, + universal correctness, or independent toolchain closure. + ## 0.1.0-beta.7 ### Added diff --git a/README.md b/README.md index 735d2041..d4f498bb 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ workflows. It helps developers initialize `.brik` metadata, work with PCD files, create local candidate evidence, emit supported language targets, and prepare artifacts for managed platform workflows. -Current public beta: `0.1.0-beta.7` +Current beta candidate: `0.1.0-beta.8` ## Install @@ -24,10 +24,10 @@ brik64 help The npm package namespace is reserved for SDK libraries, not CLI installation. -## Beta7 Command Surface +## Beta8 Command Surface -`0.1.0-beta.7` focuses on local/managed workflow parity and clearer terminal -behavior. +`0.1.0-beta.8` focuses on making PCD emission executable for the supported +beta syntax while keeping local/managed workflow boundaries intact. - `brik64 init` creates `.brik/manifest.json` and does not create `AGENTS.md`. - `brik64 doctor` prints a human-readable workspace summary. @@ -40,7 +40,8 @@ behavior. - `brik64 certify ` writes a local candidate certificate. - `brik64 verify ` checks local certificate and AST/hash coherence. - `brik64 emit --target --out --tests` - emits supported target files and generated tests. + emits executable target files and generated tests for supported beta PCD + expressions and branches. - `brik64 polymerize --out polymer.pcd` combines compatible PCD files into a deterministic local polymer candidate. - `brik64 migrate ` converts supported legacy PCD syntax into the @@ -67,9 +68,9 @@ SDKs are distributed separately from the CLI. Current beta SDK package coordinates: ```sh -npm install @brik64/core@0.1.0-beta.7 -pip install brik64==0.1.0b7 -cargo add brik64-core@0.1.0-beta.7 +npm install @brik64/core@0.1.0-beta.8 +pip install brik64==0.1.0b8 +cargo add brik64-core@0.1.0-beta.8 ``` SDK packages are language libraries. They do not install the CLI, issue managed diff --git a/evidence/beta8-adversarial/report.json b/evidence/beta8-adversarial/report.json new file mode 100644 index 00000000..b092dd00 --- /dev/null +++ b/evidence/beta8-adversarial/report.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": "brik64.cli_beta8_adversarial_gate.v1", + "generatedAt": "2026-06-06T02:34:44Z", + "iter_id": "BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1", + "lane": "cli_0_1_beta8", + "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", + "rc": 0, + "cliVersion": "0.1.0-beta.8", + "cliSha256": "sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed", + "executableEdgeFixture": { + "path": "pcd/edge_precedence.pcd", + "sha256": "sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63" + }, + "passChecks": 9, + "failClosedChecks": 12, + "generatedTargetExecution": { + "typescript": true, + "rust": true, + "python": true + }, + "failClosedSurface": [ + "empty_pcd", + "binary_input", + "too_large_input", + "legacy_syntax", + "missing_fn", + "too_many_params", + "invalid_param", + "missing_return", + "unsupported_statement", + "unsupported_expression_token", + "malformed_expression", + "unclosed_block" + ], + "claim_boundary": { + "public_claims_allowed": false, + "public_release_allowed": false, + "adversarial_gate_passed": true, + "compiler_functionality_scope": "supported_beta8_pcd_subset_only", + "fixpoint_claim_allowed": false, + "n5_formal_claim_allowed": false, + "rust_independence_claim_allowed": false + }, + "blockers": [], + "warnings": [], + "next_action": "run beta8 package smoke and release-train sync gates" +} diff --git a/evidence/beta8-compiler-functionality/report.json b/evidence/beta8-compiler-functionality/report.json new file mode 100644 index 00000000..23c10002 --- /dev/null +++ b/evidence/beta8-compiler-functionality/report.json @@ -0,0 +1,49 @@ +{ + "schemaVersion": "brik64.cli_beta8_compiler_functionality_gate.v1", + "generatedAt": "2026-06-06T02:34:41Z", + "iter_id": "BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1", + "lane": "cli_0_1_beta8", + "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "rc": 0, + "cliVersion": "0.1.0-beta.8", + "cliSha256": "sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed", + "fixture": { + "path": "pcd/branch_math.pcd", + "sha256": "sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404" + }, + "executedTargets": { + "typescript": { + "programSha256": "sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95", + "test": "node out-ts/program.test.mjs", + "passed": true + }, + "rust": { + "programSha256": "sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d", + "test": "rustc out-rust/program_test.rs && ./out-rust/program_test", + "passed": true + }, + "python": { + "programSha256": "sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6", + "test": "PYTHONPATH=out-python python3 out-python/test_program.py", + "passed": true + } + }, + "adversarial": { + "unknown_identifier_fail_closed": true, + "unsupported_target_fail_closed": true, + "path_traversal_fail_closed": true, + "stack_trace_leaked": false + }, + "claim_boundary": { + "public_claims_allowed": false, + "public_release_allowed": false, + "compiler_functionality_claim_allowed": true, + "compiler_functionality_scope": "supported_beta8_pcd_subset_only", + "fixpoint_claim_allowed": false, + "n5_formal_claim_allowed": false, + "rust_independence_claim_allowed": false + }, + "blockers": [], + "warnings": [], + "next_action": "run beta8 adversarial gate and package smoke before public release train" +} diff --git a/evidence/beta8-package-smoke/report.json b/evidence/beta8-package-smoke/report.json new file mode 100644 index 00000000..4c51ce7b --- /dev/null +++ b/evidence/beta8-package-smoke/report.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": "brik64.cli_beta8_package_smoke.v1", + "version": "0.1.0-beta.8", + "decision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", + "releaseEligible": false, + "lane": "cli_0_1_beta8", + "package": { + "path": "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", + "sha256": "5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43" + }, + "checks": [ + "extract", + "version", + "help", + "init", + "certify", + "emit_ts", + "emit_rust", + "emit_python", + "generated_ts_exec", + "generated_rust_exec", + "generated_python_exec", + "verify", + "cloud_verify_no_entitlement" + ], + "claim_boundary": { + "public_claims_allowed": false, + "public_release_allowed": false, + "local_package_smoke_passed": true, + "fixpoint_claim_allowed": false, + "n5_formal_claim_allowed": false, + "rust_independence_claim_allowed": false + }, + "next_action": "run platform smoke, sync gates and public release train" +} diff --git a/evidence/beta8-package/SHA256SUMS b/evidence/beta8-package/SHA256SUMS new file mode 100644 index 00000000..15491784 --- /dev/null +++ b/evidence/beta8-package/SHA256SUMS @@ -0,0 +1,3 @@ +5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43 brik64-cli-0.1.0-beta.8.tgz +45f04c9dde7fa65fd544fa321ccc9edee3ddb11edaac302cee56b0c2a6ea7663 package.manifest.json +fc3af7083e002983162c8b7d556ef4f44dff3f53e7c8e26f21a41160fbb6ed73 stage-checksums.tsv diff --git a/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz b/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz new file mode 100644 index 0000000000000000000000000000000000000000..7c2a9b0ce47dd377da71a320cae9e30a64a4abd4 GIT binary patch literal 24501 zcmV)$K#sp3iwFQjha+kL1MR)bcHBskAe!Ch%$YMW%Q-V^BrCf}RtAFr0tiG<$?Tz+ z%t}owCAFxm>Kdgwh=+qjDFTQB5RzC*E@pSvy|`!g{VVe&cQM~_&CJ~a$0J^(#Hx}4 z-B}6({xCN;GdFWLGw+SPG3< z|L$vsZ5q0x_if$MbYoyy<`hMf@+h{zE8& z8|#0jt`E$u{&yeGV*T&&qtmk|=Vu?F55UL3vNqZO1MzQc^}l<0w))>^{jApi?k)#b z@_$qRGc9MU|J}#arvD8_x{W`!`roJjEaLwUxB9Q-f7=?=_y3%}u|5C0m*?U0NB=ai zwA06rv}Zp(gjv@fp1nBH&VG0D_@|Q>kDfl!1SNDjr^)O(jV`ZpZO`A=Ox+x4qV}UF zr#^+blX(!ums)nWsJ!@aAza zVS)DS^gAtM@MG%cEREbrx5M7KQxG6oS2m|jfm8!Gce`4U`12`?b2pEYxT{IyMRU_U z3SB>kN^TqgTodMItRowR*9cvj%+d(jO0NNqFn{Z&jEeh79AZN`6xCkG$=idgp(ISaY~|C_{jy$K*HPT~XTdos_WH{#D6>SQ5Hu|Q{5 zw5#O_;OA{TN!$Qu06>~d1U}~Ql_qHJ0mK^ezC@Ci!~lPoq@5@RY{h^AR)F2rCIHAp zdz+-M!wDb-2ARXOb^&M885HrNNt9nBz!7`PI}2etJ(#%;z{5uh$S`}_b3rWHb0VG! z8U!I_np+ZAoaBgM_>=*Fgea&SiIKoCSPXd9knlR-&aSIY>IP!wrgyt_&=gb+sp zpX6KU(S>;ueZsE>02qrg0yd^mnkFfXksI=x zDO1$dO3k7xi5Tediutdz`IO+2asgn0Ap-Q&D4vM8J`=$6NNm% zd5S$UzId^6?76lxc5;z({~hE;*i|D!>OLAM~^*iS~OpMM$p& zK{Y7J%?_fhMo&FO#GuUdCvG(568$Z2E`oXN2$7D6LdJ?%psEWv5m!*ug4sxgC^t8vg z>~b_b4dE}*H;g?YexADTqUn4J0*+P<60CX7iEHA*s;7)Q;>*t@!bv2cqd16CV4W_k zuRduRIMvyVA;IA~3X=6tbFO@VM)QsVQb0oio`50bwCF=C9<2X_hhkJHB?5N}9Ec%DuWXS>o0(UaKj3PGo}beTtrlcFD1^LqUMv-|9c-#>;CW1?AwEp zV{i9=Klx`7|9`mEe--~5rtX*x|8JweUH|Xn`IUAG+VLd=OS#j*EnHB3$wpC(f1gTl z3mQz8Bt=sXH$3?+8{hPdaNGA!bFgV>L!kpUMtUvm4QXThV1ePD0JmMlc7*(xr*4Fn z*ROu1sg#H>ex;oR&?jz5!H=xiO5n=*L7p54H66E&S+Tu^*4;bi&-s8}T+i6KpGGsV z1fRpKcRLzcgwL+Q>W$HY0V^D>e9_4zi_si}Zh$~8Sx$SL8JX6iS%!V(VjF}i^KE0? za>8vdu*H6L3lG__)%M-xwoSRvqbFh!VESDv@m79WjK4oC%%I#0w zNf0}(U_j9yUXlPdai0iGq#(+95wH-+E(K#7fD@Z0Wg{>J`8OBI-24g& zfV!Q4fd*e^xdM>bk&=5$*))001fs=+KyBKW6B}(q#I1*$3}U03J^@6ciGV0Ondceq z-C!-;vB{!5Nw0as@U6#*k8=o--%qoE_K7aI+#~|H;Py3+3FfAtacmrrqvgq4Hw{!u zea zn7w5w!vFgy4wAQERr9^v5)WLUps_9Xft781;(e%GZZj2I__Tk7r~@jj?Fw=>@gkrF zn8i7#+khdb&*MlC7sxN%cfnl~5<>tU14|!wU|`_M1f(56fq0##tRat_HhCneVU|p; zrz{29zaUsR(c*L>lOlB?lu-=$g#j_#RgB^&1F}KFfgW!7aTD8()E3i?Kv^iJiEYMZtMYw z4yCpDNa7!77>6Csaof4rJ3as+j!E#Ad)5t5g2V?t*A5Q;2vYMxdwYc_e+_(wn`KvX zK=(lk#t+f`1uuLd+1btLBm>W9LU%sNH9m`YJO&aUcd2~VlpANbM+gwmNd~YFE9R7M zyTS^>Lf}^1ACCb~Ada9v1c$_t8+Sye3X zI(&Ldk%POJvm}bCb7Uc$W}Mm@iIk!VSY;k?QY=m)kbLQN74(YCn#U8|xpa~C<<39u zcjgm*nnD}PEQ6n00ruep*q}{-xh0y!JYQ7sBu8g_p^90E4Vo&7D z1akc?^FV)l9Ze<~$~0*t1BFWat(3NfT*7Jg1VYdZN3$e}nW8@~k~spxhG?NC5DOMc zP5fcEh?aOZMX@r^gfoGHu}lh$mENpGKC^Y84-@}w^9DX+|!;**NZG;e7z{N z8B``v_Y?YHB<6%Z{^TKybi05gP(X2y}((vc>%onLibQu?TD&`1O zdR7u!;gldIju1hL9cqP{B>c)`DtM*I`96Bbrv`syVlcunOE!dZjMF*yk(2XJx?*J} zQCAdD^@=uY{o@SI&>16{qes;g0g%mv^OzfzbSO-sK)QoL(?ZDvMge06CPV21F~nD5 zLWLFpy+}8?WD>v}t4nT$uRzJ4px~bZmp~_C6<&8`L7}f0B^A{L=?_*aK_>+@x9EN9 zcGewNnVRH>bzOT_6eS;>=W=2@opX}hM;ac3XVP`6woz8l0kr)S{9R=f+!3lWQf8PQ zdwI6!|DW}<`uzXya^M#6Uxqcc5izk@f5A zzo~D}|L^5dK_x+PjMZM}g<>D7&N1P!_kL@xpNk%h>2^YTG zVBOKKC-!;N;vn7mP7SgvOQ0RuD~lb1C^?k756_D;^|JhBlwZv~D#~jqnI}8XI8w{f zZ{NP{#k1)jGpZnPe)!)-O{~)4uINx_0WB-hc8}HQuy$APP7y(N&X^2-tWzanQ0z~O z=rzs;e{*K>V*8IDIeY;3uiMyvjj*BTEO1037#5erGpRCF35biQ1W?TU4GhFIuLh6 zUIgLiSU4R>yQj-N2TH#q>60S7tfi}Q%4T43cFItG?$I2RKSW`dDb9nPQ(-D{B*>1B zDlRv}3p(g~Bn%%iF$L~gPQB@f?f^4v9CbPu7Z=%8hYsxy!tDHUi|wTvRlV#=`$h9y zr~@@Sos%%f^Gb0vN4A-4v+hVFU*Kf$$_OT&-pg}XN`NpEHgI9v$TR&(F2t&z`(E2N_9DDK+OD zJiEmdE^ghSv~=&u=76L0x>>pKOht+=9Kw1)1Y=%c%+m|>-Wc5X_w^lu0J`6#!rK%fqY|}V&`nszC=`CNc~S*jt;6?EuC;Gaa`a|?06<|@ z2UbQBl=4Gy6j9p{ZhdMK+|j7%Xf0i<54me~awU)F52{X0Wm}8=o8SwkVE878QYwWW z!WV!fP6-NIi2B?S8v#(_RmiQFTwxl41=v&>J;D=nh_Db9-qMquL!BYmyk{D(tSA%GpF3i*+5BHGUd^|Bu z;hWz1QPB0p!2vlcUyx|#-W-Y(^1-E>*F8EknOLWw?~b7FE|f|#CYnO`Bu)4_Bc4%6 ziD8$E&phVQRRI^C&*b`Z&WG3O{8GOAMdR)v@Z$-&?)(B@4-O8r%KySUzGL}|cJc;5 zAZkHZ#MV^|Ne^j;(QyBEmR0;1K}Q>T1C52 zJoh?^PgbE(kf)!}Wr|H$82W#&gzU{Is}?WC3mqR*0dLp=J^K=*K@e!t^k`Hk%|!Jf zq`?>%m;!lCNRSq*YmVCu?`ndm@L}O_Q$U_$%kj7UTER}>X0z8W-f(*zzkPio& z?Z{Bcu6l;Ul^seiCrt&6_G3jdAoXmBJ6Tft91!22CZmuqH8oH^;$T9jK%J@rC=7$F zYRyQSq&iVT14P3CQYL`GwAPpbSt78=%>`5Qo1mveYN# zA9((P#1@x@FrZWf=Mc);gq*O^ikMR_G%rXcI3#aquph9|$J~FE{G-X&P;GHpQ?L#n zVgsiI(KnJc^0q|vA~l$(Uu2fYMxH647rev$QY$*m0YBc;h;gsTfi#owkdS~G~hjdhc`WvTFq@2qofcPKi{ zxTGi!jZerem(J5}d6tZaa4*Fv+^aqDW1oielKUvU+T;K3_tXQx>Y;N-J#<#i@rv{3 zS}Mf9xnsOrKa0=*fX_crANt1ke>(8TcK`2Qp6&VHXZ@@`|GT>!Sjqp*`#+uj*8lTf zo>u?Q;mEdzrtNGG06+O>5&xr>|DpO=#s7Na{!d3o|L^VnPapqTqW=jC0F9Ts^|7)4 z7yQ(>_dndvv(^7T>t_x9@6K{yCI2_`f7<=+{qOhkwBP?e7{HIM1K4NqEY$x#*y_KU z|1HO^+kdvRz5n}Op7$M1+d;3Nog-~W39Hz_#27omZwSAs)WJW_=zbQgn5T2fQMD7W zjFO>> zoCGx9Z;wsAET-=F<5%>^8UrL_zVkg6d)#Bb$-dLM`4oiKV*OuW?F00&@&2y~1-JVD z{XAR!|FeEp>;HF`1Do&v8Uu5y|KH2gy8k<}9LE`rw)+34|19Ev!Sx?x5BL`QzYf~} z+x_2<|18%3$cN>F^s%x2XE+w#|Gm}!?%~<$f1mZUTK~Jd99YT!&G=u+|FYHpKK|1h z|2yapZOh)KfBFobh3h|guzr|6ZlVA6b$hG--N&<7|2scB{ptCm7k{{W47h%a`#<$< z{P+DlTmA2|epc&$cb5Yz`M>4<&;C~byO*bR|Ie^(vu_*LRssCvpGExt;a2~Z{BIey z)ja>(uK)M){7O4#{v1>PYtNEN z6(W3B4-m{Gq#|%l+#JcTA7WJh3}!KsmrImU_P-!R&^tqif?tXNO$sX2PPE_6Cm3fa zFO}e*v}~U7D?GI~%6A?D&abQy(RT#~Pl7j5mJ}C}V9J1wa;@asD;Aew>J)ZMQJ{V< z5!iOO7Tp4PEiW56Dg*MA)SR8~WDK-FnFkCpl~N#}@X?Sr0rDVWA80#0O?*Xdq%9m+_ArVcqu86N;eeNfPCvsX6shpu410A|;;o2L=Nwl}PlUBq%-i zlNsLqQ6q0jLY13I>2g(-KGX}dL{6q|r-=V7GAhX;N($XcEdn^}mXW;T&Q=ViZe-dm z*-DU`az~W7@dA7EbGt3H-VP*?1tVH`+SCtrUAyB$n?FuNs z9x>2d+~C9m{865vbViEeWB$>ND9{|Rbqc~JO(t0-!-djYgaC@tK}8l_C~87cB+V{> zZro|FgST7al|axY2Jtdt$ns_!*Z0{h$K)EP;wI@lX)?PUV5dyzB~tN1FYofMO1e@u zmN^~N1Y0l+U~F6zf{q-8q!EfzF9y(+*8&!|BWvkgQa-emQGz6SSt^l`$fMw2Q*iU| zWoie>yda9HgzF^~&kX`Tj4tQmR&2_(rCe@xA`&EsyH+tnj?dGFoPwnO=f@qHl__KS zd`2}-A90pFtX_X6Q&K4Nc`(6jYw+Syr2FY)(Iw0h&zq4IHF27X>q6;HDIte^K`#%G z28uizGPx3ljnf^WTs2TR`cEDrYe_iuiV>+NS(u4xbU z&=rkU#>mx-9?#AHgPUFL?eem_`#pZZE-Lkc=#pjm-tHB9w_9r+J&pFbo75EGbuU>1 zeo!(>_(dTBr&d)>u$?+~+%#h+>1DR(rsxFaPA17)7Vu7_dWDW^u=Kyz#z)%ASK19W zjNSu#6PD9m4)5Tr{y_ZvM#H9h6Bb|QSMuf8$C|M(^4;)ep%B!JU(Z+)YUR5x5s4Y;lm!lHa7BAvZC8#_D)t;oj=Gd($>a^u zCw}gUze~`lyf6jcQZd02@Yf!FL@tAbM%9koFqKtSO+F=Wn6Mj+?7VM!PT$c!m#X0X5@8A&KXT74%`E~5q zN>itrPY$ZmxKZGCkebNP?mElabWBZ+sT|OgV*0=|?h1a{6*P8J0et#8h*AY;_^Sm} zDn($zzg-Y6Df;lPLebl-dq%uzp`?j(G_zi`PHh%c&ZO^TcCtZHYU8x0^u#1&STsy)Vz5d zOxUWHs}~W9mhm=1(VBAcrYtJ1NLtl0zk9Hb&je-+U~XLIDX$;o7hlmGge-oust&+PA89^Oi+u zjlM3sV{s)l)^19qhhCC1Ir-2xZ(syQ~YUrxM>Wpy_u&SlTZI;-wc-g?_VJSh1%PemR>Mv`;S6or6at(=Lxr4X7g`eY; zg&fk=!kGM~>yM18pj({UZ{A(iF2BrdLAwjDPs01yvIDBSn%sQ6Ps>Gr+F*?yp!k6- z-dynTMp{%|p7VWLuIwm^WcjC}{}#F-ejNiN&GDMdB}!sdfu%O34oDgudzWMS(Ly2I z=PD`^>29<4d0dD)4gplhu#zM$LEylX2?iWY8c)%9wZ(zZXU1`ok3;lR20aE}6iQ2> zGD3S2UzHXSraTt>d3omWaaf^&-j5s#a`GYCfh}dQm;wd zRm=zZfzA?Y_*9!#+87hCV|k`fz85GvYPp$B?K1PP*wlp%ixT3^FTd1ZiD))S%%U6- zuX2PSu0k9amERb<4GfoH@>a$Qnb+vLXa^cE;^_)IukGtXi?7-<0xLwVL{^=vr6<3N z9`f;*S7b_Dd|8w%K`UMnJc)-`Sq=|0JeIWjA_v5nJ zB+7BI+Z7vhQ+KwvHvwIPj?M6g+_T#|{2BhQ_nWT{0b1a3UjC0s6!ZGEU9Tt(enkEU z6hFl43HN0DTQXzuBiyjyK;Z^dz-GkGdh51SQK8(P;%%+mpz^QW6dK^A8+%mzE7Hz; zAR7*Y+(W6CxKXx;c*%pJBrhw*0EP8^iD~Mw+`&<1@4%>{i%bF_oU`I4?aIvY;ZPww zLw!l3sBYcC3x0F`UMrF|LCoRL*Lg9DIGKV4T-kfkj@Zgz*XeE$Y71U+uR6Tzr-M zxf1?}t`S}i{>zht|LGq5dHhQJ&<{rASHDq5M6IkC5S77Ox0ONBI{>$BEb`kLLn%c$ zD4MF)aHOi3tYGjl0oai19PE}Y{)T8EJ<6SCts-KvKxq{n;+!C5KI2iQ#{!SYc}JSj z<$nM(9%-id1Gw}^>x)0WRR8!Eep}-AH_GpCkJS(AA78_7Tl_vye*Xr355(_7<@Z0x z-!~6BxMmcXV(j(aepPGbI8mhBO{EGB9ZZhB%Kp59O^M8wLk|8OIGk6;9cOygN1@5?kQIM`q&! zPY955{1V#*tBFAr9Lhz^V=zxsccRE}1+O=CL0#`v;qoOt(}+0>DN9S)k1}h@yj?W8 zn;$%tor1}yG*cYnNQj$bexynzv|ZO4uQ+nT0UxxC6JIVu@=q}kMJXC~yCPf{hJ%fD zHED())yZfzEPHLR?3J)^5-iDw%sA-dVT3^K8I^)mdA~7`vi5oscrn?w@QeUt8pY2F zc_@d3f^)*cTmoGnhQlE=Fd>CN9PnQXX~K$6?~9gSiXw!;SK7B=3AJ@B@h0a904NB$ zryK>=%RN&?y3(us{;FDy-=u*2-xT=qPB5*J>rME*0*IUMi#{CKkUJ)3O$& z(8^DO5yh=o^s74W?dYPF*cz)c=AB{O)bf(xx@}F)iXw|tca;RQ*U{|vS0Mgqi>naa zHQgTj5~D5a#*a_aK1jY?b*Sl2}Yza!_@mRFrP2 z^zCuAmIuW3`ay+!s#?A38p21n+h%9VZ%y?Z35HE0iCU`hG~C;LuvYoRw$TwlDTvqybgU4m(!yp3vlhR`n8?wiV&{gyJMX3#vR;)N7yF5QX& zKy8*1s&4KabBuny+~Qn4pHbL8m+-zekL_foa8D5BT<%wd6=)M(w598aUfEoRd1T`J zA%Nd#^F6kCv%9h}lwa8aMS?2I!7&)i&4v0H~Y(obv>KB7=L5wFELYH z`h9eZ@pI06*l73Sb%z;n#s9v}H zQUrmtBI3&?B8nwZdZ z2=ST=#md)qO_)t*`E~U)NHkHH!@EDvG5BbAzr6*IH1RQc>Qx(hI1fXX_PpzyJtjbk zO)GImsC}y$7_;>o`lr45JW0kAbgif#($F!-jE-j(op>m_T0R{_$g)sPZYuulJv;q5 z`+Bc^Z*l+U>^DEZ-+TFU_VYRZbpwBYbvP}ojxR;S)x8z&GV?=3Y9I74^Pz|K4ygUZ zDOcPjZ2N+nU_PO?AEo|0$~SDH)VxY)*4l!SUYb7F5g$kgAnyDlvWc3bk6k(x>TSinsRfh>T=bB#&AUBsg82GwGeJ#nX`5OB(T$sLg8N1^vLz#{CB zK_Wm@P!YzGd3gPjb;5WB>+J2l{MUW_y{}FQcS(pVoU@up!nl3JVJwM6G}$Z6M_EA3 zy#T*5^P+ZTxQl0=x6l<$7K16O6!R{+;^>v1?>_5`aPSgA!iksq(sTFis}dvX-~36j_mI2WD=s^<0b8KNSd9`~ z7N%}|J?3@E`*v7eenhKTGG!`QUoJXF`bun{@S+P=I~4|TEYCq`x;1b#*R)%X|B4ze zeGW)vqCLHe4uuUV4({}FjfH)&UD?oZg?+F3pBz=(Ok!|!8oqV7eCR)wVxGO)6WB8ApfXeR3Up{zvT|h{A3%n%B0R`@?C^#c$&=fa{ z$+sPQnCD6Pox9(Tu~yD5u|0BJMfNEQ31{uGbk;snHUe0T8N7od?jBScyuy3EXiubX z-IeCAEXl!o5wVmfU02)YK?+a95Z!s6bAS7yLE(R|*!3y9MAX4xf8+p{Rq7*9YJrML z8GBDeF6ZxE3@AWEh!oc2kiSvtOa|X6H>3+EsRjxr_8G{5AYj4wDU=9f|E;>`p9NAD7kvvCE3;0OtcYqe^x|udytBt)ngI2 z1W>q``h2ev4Ard&kG5b(SRWq6Zve8SI2M-rVelO2z9G!WZFYfx5p@dLA{LdGuWGA| z@D`PFP*$rb277q$Nvi?==&?8uyJp;RR}{{Y6lAcXa}>3z=VWM$RAi^ro zm|wMd=K(&I8OK;fsisf>sRSB6yb;=Ae;-$?UG8(gdsK!?wysz_EV1Ukt0!|RNtXbcslNJNr0&%=rf9HHZ<`qg+YoVgWBkQ1z zXD8?9yHb&-74K{kT}EE9obhi&>!pTJTt*_QPHQT}m758QKNn{O`{)vh$@I|&27`qH za*f0Qit1b5;7UECFjWF!2`CsZJ{1#lUKPGI?H8*`>p~!buGT2Dry?M2jIm_99U*=x z(i|hfrQj?=))!?hsCCSzt5gw+XjHlUEY}s}4HQMx6{muwA*~m3=D&I`h=spc9te8@ zgrrm{$!bNlLa*iVT|%v0UI$~9C?rnlP)_rz?&J+G1qsK=dNndW-}U%I9#dOat`I2H zGWIIx6BT`G3{oqNX}4y#*Q>kDbD6_0Gpd@J6dv2K2+Ix&ftBHL-^7|t=Gj4P;~!!n zI^b>e7KW3ojUSLIE68b5$va-jR zG|;nm%%4+7kK~;?tJgZw9dAJd%*WmtJLnmqKf+CU8zq0e|CJgGyjC{S6iDaSPOeUUaHGI^z8s5Da1lT^5f*~-yhtg3k(T9N7 z&*va>j^)}^H%_WBl%R@wINL=hyooxX!^MEYI(=1W&P&0)jZz{y2(Q1#r5DQRC={HDh> zobl@${uM`IYkj^4)LM!ix(QU#kZEZjax)gl;r~lDRk%BSjEf z$3nwyssq%oI$UU0CWn-3U_Jb|)R;@uh<%PqXA3rKMC7l40;d!UmO;MKt4{jbZWQe+ z{p|P%Dy&bEsG1eC0Y&M{QMz?E1Bh#ts&T_@mPLuDa#$5iDl;e!rsNpVtyT_)yo$M{ zpuQGKNa(BrxEaJiebz({5~0tD{TAsMRLjj(&*Qb$t_vmqIBpyJgIkDY0j`kCw-m_A zm_dd~7+Y;TH%{W~X)@15RW!9LRm4v!jE1);C#;3%(uQc(7-LqCvA8!*G*I0@Z>}CE za_QhlGHv#&Qbc@^s|?+a`3%!bsGHJ-F(^`Z{bkKTF*B>JK&BX2>U6F!viS5BHSy1N zt-zvEb!uDI8_Lsj8&)c^?jS#L_u2|K!58U0QA}1@=T#w8MY(1s34&}aaujDgybm;; zH)GIN>u1!pIIMF0c`2GN`x7x)YHtqcZM?U#lTx!3Ehrf$>gl}Hbw|NKDI;4YMOB2a zD;b1f6bxPp(qhYnk54qm&p1v%Rl;j5zrzfR`yhTFoj>JSi}&_r^GOQqSMI~m;w;cX zx+@y!{E$%cVOut~%DUM&{1ji?PiiWu(EKYf&1h+?wWucpo#&HoE@y{_+C$tlXJLo} z8V_g0mMz|F>K2KZG-|!KjKw+e9ZTsafB<6jlN6NEth)EWMlPuqJv%F%g)FdK)t}_~pHC257OaGd#CTCHy+Zt{@g=ruJe%+x|I3B- zdAhxpHh%rzztq}D(%p*5da?J_dz^|J&|+md{7o1ZR6v`Sl<`ytxgpQ6 z#>jS;sK8Ys$*ZxbO=eSE3f0IHJ{lhW7Uz%gs%CZJm}A1wW36q>U^n4-$V!5LN{x^= z1+}m;CISNWY)@^!EQ;snWq|9)40@rSc+3k}N*tOSF&8a7+Kh`SS@f&-3(!HRc(AL) z?k|dk+a#u@8P&EBRwaU}!lDZaSB)xb#SqlP~0$y4ipqBuSOJ4=r4d7KmkJbRUh^MVCx9cHPd;d3sQ8~VQMd~70n&~kXM)IvA zJQoM^QTH{)2UQ9vzd(HfRsD9lOI>N%TxY?ZfU4f|3Ny~>x6@t@mJU=Aj5y*CptUUT zj_WP5t43!nOL%RI78{`S8uG>R{)DQ79j?cH{_@MMd#oyEYu8=_+^62P^)>ccFo_^YW`;Jnulf0AMqRnY@FC9^lFE^k#)xW54HaPVeS4&D^;uF+jT2{ zS+D%%29>|9)%|wun%~rFezSg`b%4KJAKq{3b-z*SF3@L@uGdy(B@--AXA9x`F?C5P zZkznrrZ$!wc^mzYu)VA!Mdu^Qp)BO}6b6b6S*cZ&P)jJ3c94SSuo8!`I0j1Cvn)`o z&2^PXYzZk@2$lk*=nPGG%2wLJDZW=Vh1%9eQLi;t|5PHE$0JqN`66Z?H=WN}zV{NS z+URN~{IC9Me?uLB<4A<&yFt*tg|W1Rl3;0BsRL2!W*K-*rC=pS6p~j0_HUyTtm=rX z0+p-)t1F51QK_{uivTrQ5TddopMvMKN)=9=a&aM#G!WNik`P#LyaIHSy_gT9Iu}xHM18?NX zit}DPFOni@mL``la&oJuU%lxcvm$g42~hcje^$Qx8tmGvToW6ms_**cn?GK03SCR=Le-Y2rrdZlwrw>hH>4YD-rf~(9fN7 z3g7c}{VQPcIEfE9e?;*mIg#z`KTr{LqyAC+ex;;nSEuiE@f1Z<8ru63WnDVYyy4d! z?eq>6n%H^J+ATK2qg@2jQ9|wPf?|U`;yL=xe*4JjyYxJ*4)LPO#tku zmSPi^Y+h7*zgwA#n&U0bX(4O5gnv-2Q1iEK2k(CAG5h9NaES)cjNOPPRMWN*FbO!Wk|Kk$@z;h(r8gB{nbt>Pj-IQs2WxU31|d( z6XU_R_-|dHR2Pt?H#hvNrs1s(gopk88bQw7IP$;zi;JC$4KaO7EPpZ>M%jkffJEfz zs*)}KkDFyI&ByFdU+$F{?UtzAuL#Mq1}`o#iq=C8J!Bv&K#kbhuKKKCgS$Ht+EY3YakF^lP2+(Eg}o&XtB^*mpFw4<4V#p88*AF%dng-32J^`BEx=l zOA+>~jU`w)_bMM<)Jn+dZd+4Z96D&7|$ew7weS7Jy_h=g%;RM#phItvzgxkF60 z^J>3Ql!GX19BaI|t-())9|-n&D$(^6B%kWIzdDmkYaW+! zf2%ryB51G??S!S;9E)YahEFkmXm==H5MNzV!K&0Rvd=|fTA~>VdsmYQMC$uLE5_Rr zTU2!2bW~S*F8pJUzIrcfC~oQ%c4@>Qml)kuo2TB-2${TW}t-2`SLQ(j^(S~BR!4fP%=~$s2IXkM|99nfsE>8y=&coGamN*fs zk-&wUay6K;);6zKkM*d06kA(dvuVUZ^P*kCP)`)9RLt9w(p73<2~nj@Dk?pT3aBM7 zWJT3oqjg5xdy!x&FrBW`4M%yq7%p^{RYF)9q8g^vGK2*|RQPdKCvt=v27+z2d9plc zWXY^HqEvK;b@sy7#p%R|fv6Kc3-S1Te*>TefB zc2Tb#{_4aujA#N+C0;TnASK|daQi(@dHeaC1|K+1_ zc^Va;5-}Vjoh%n>NIpEuZDm%ZQu4{nO&g0)nycfsq*g5{Bzdya=+A5~b>E)cNqUL~ zx?(0;g{b_}6r}PCMt2oay~W$Qi0x<}K**MZzc)dvbh*B;r9@dpFmrD#`=$3wPVQBe zROy&IJk&eEu#k+BrBCEGFyCA$@^P*$`B%&SM&`{@kZzPw6MEpH;Xy$VGX9yOv84wP zeNm1NDS##k`JgL~K2Wa*R^T2*$&l9o<;iZl_VYr)X)vEngc0k5jasW+%LzoCpch!Z zlj@8BCwwncpGpEl?%@6lqI1fq`arECwECKT!P`(#l9P*|Aaso&Xw+oi=q@3h z)l~v`EMkPHA}1I8$xjSGi4$ZZP=V8XBmZcVXcwwz;Ug0f{9-|u1gwnJFRoZny)Iiytmt2f`+;h z!PPV+GCAx@?Mvp-ZsrDGsCu=iSpW=RU`0w^0r9?Cr7k(-V1&9xQv`|*(Qm7cvpg+i z8{$CC5Rlwdv*2Acwhraz_U*$DJ)Cz`Q%ltL1EC5eD2h~ras@RdJza9pi-p;sR5)Tgd!~`x9e@9oi7b{Q)J-XSt~Sk^;Ldxy^qcEUx{xZyVTQoz`%KxiGA5^) zo%SwHjs0?+I^#Hg?x6tHw>=BwGMldL)3TKWv1d8rdm%NP4EMxdT=#g(J#F=L>V+{e zUahCXyJ|JhN1oS!%0@_)g*7ZVQa9*yO50(8U8CgZs=J5RkapRVLLYi={p`!oS=)P) zqBW1d>6be=M!YbFTP-tLU{2hvzdXp-PfO?;KOfysg{RCBo#HrEjt@i2KU%0r39WC6 zPxswsdbr-0!;v_lJ5V8&xb5Qjjo*FXqu49oPePfzYPt41R}_6VwpwFjyLY2%znk)= zBp_rr`&UCgU()N*g%#fxSpUJ3B!&}x(nQ{(UsJC~zaQ)A2Qg! z!WiSO{?dO~Y~3kLrb;*@=2-E~ly)2>^Chw?cJxQkmhn_QeqEk_&&EE#=vkwSB}eFO zBMmum(hFRv*h)@Vgzn7ko0f?lx5GQF+iX!ueGu!t^9TWuFPjrLzBg+)>ikOEZ_x(Ba`7{kvVR!OeH zCchrG&}#j#eR9|Zzw!2)f$8Sm3iD6f6G>ON>dt=&=aEcIo*ZFEG++;Wo;+xu7ku(a zYjw<*Ymz~3e)15r-&Q~tIu=@0$t{4*#Eo-b8_Y8cZ+LxAtH}{oTLKl)ZAE3E^?^C7 zoC9%SYLuBE3LU!ouf@v!9tDc25}oP(n;lN*u)TfyPD6us+WsT zj@=hep}?kE;O?SG=BWa|S!1ElUuXU(XcpG}Xt>@Bo?Se_FcIho#> zMwMJSt=l7^Xz4b7RB*yymzgx!Nm{=nwM~;qSAm-+d(%KaK(Zl0B|0}NR?Pc={z)IT zAkpr@*1Aq~;<@{ZEO}e0njCtxl^a=e6tHwYJz90kZ~Gc|-y@&M#ygdMA?Q5rCHRb| ztB(Kq%52yE5bPRhtLV7z*M8+_dr5~NaK5t8d%j%w{KVexbgm;>cCasda9&NM@bk_| zK@*;wsM>Q1Xcdtu`dD{GCnSlU_*VhDi!rZm#d3H@S7t0;MQwTZ4BETcO+B2`GUs^^ zjS@b-wNv;o^jyjMW`xaf-QCmViF-L_@KybsO9^Y6n5S-;f^#mLh)3rZ&mi3&hD%)u zAOBoZnzP1dL=3e?ccxoa|Fbu<<@s*EEm~PzsUU+BAwL-VA)Zn3z60J<*SDU9R#z)k z3qAN;QCF&4W2YCoAivm2cl`71z}(Srg@R$}Y7JM9^HB%v2|<)uI0)igWk*uQMP=Wmvc_A+vAzTzOWvbN}5uDy=*uDWCC%`z1oCuRMp z%%kWjq~SI4MTVHL*k)CX-9fZK$l0LC%Ny0nDCm!?sM%}p=B*eY?^|?UA?y3W zNgs?1IRh@lJ@D`)-SBcSKrF8Oh%d%8Nb=eb-it}_4UJ%j&lK=LIn{eIue=65I?Nl3 zo0?q^ha{eoZ*py69xcSZy?d*x=>pUHjDg+AIs@aLGhqaK(%pvz0=bN>{+OHxWn~+~ zhw-i(`9o+~u^ZX!Np#gIP4hnd0#S4373YM%ZrJgYDT`vJOWdZ0*pB4Mt7<*oUuJGg zvXOay=1gL5&?UE^pMQZDUADY3nJC?)5cXO7^>3lLd$6XfpD>qfmz@eF17n>(k_ESe z)}uaH&LF1f*O1i>UE~;?Wecb>F6l`-4NLgoZdyU=z z&SO}5@Ee6O1Q0;%7bc5u2Q?sJg(tAnylS$g0l>6*#MMF9@7xEh_fvo*rSlt$+k3x= zW9R3k+bMm2b=d!@HHqgoFN4#&(ZBiu*Pd!DaT=-Ywv6h74{t+>wGGC9rS(X1)8=0# zyjR_KG9ip&u-u-XWu${#v+TbHcn0qLRF&|0gCXQ2ZBv?K&21UzdVNGjC(2g}PF!<< zecQuRnf1l-bQa>+GXPseJ~{^iGmFW9xf*r=kWU1suLEF*vctc+aD4!l7G1&}^6|%S z;Qt;Q0kF&fwLq35f&^?WO9rS^YLh$5MO|bV!n6od+WGTmh?Oxv)`{6KFlLeDs7bVB zIheqtHOfhwzn+%cxaDGDcoJbx6OWRxYrd)5W#c)>8D%!}13b!Uk$EL8`UR|nTLl_4OuzcA@pzUh2`mw&l z%qoI|gRgQUd)a)9PQ6nPUZ8e?j(>EcF5iJm3n{a~Emv)Fea_$u)GK#8I#TuWD

t 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 literal 0 HcmV?d00001 diff --git a/evidence/beta8-package/package.manifest.json b/evidence/beta8-package/package.manifest.json new file mode 100644 index 00000000..dfce780d --- /dev/null +++ b/evidence/beta8-package/package.manifest.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": "brik64.cli_beta8_package_manifest.v1", + "version": "0.1.0-beta.8", + "decision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", + "releaseEligible": false, + "lane": "cli_0_1_beta8", + "generationClaim": "internal_generation_non_claim", + "package": { + "path": "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", + "sha256": "5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43", + "bytes": 24501 + }, + "inputGates": [ + "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "PASS_BRIK64_CLI_BETA8_ADVERSARIAL" + ], + "requiredPublicReleaseGates": [ + "beta8_package_smoke", + "platform_smoke", + "curl_gcp_installer_beta8", + "github_release_beta8", + "web_docs_changelog_beta8", + "skills_beta8", + "sdk_beta8_or_no_change_evidence", + "public_claim_scan" + ], + "boundary": "Beta8 local package candidate only. Public release remains blocked until package, platform, installer, GitHub, SDK, docs, web, changelog, skills and public-claim gates pass together." +} diff --git a/evidence/beta8-package/stage-checksums.tsv b/evidence/beta8-package/stage-checksums.tsv new file mode 100644 index 00000000..d12fb788 --- /dev/null +++ b/evidence/beta8-package/stage-checksums.tsv @@ -0,0 +1,19 @@ +fc964c7a8ed406be061b5b0f7870a817f4499138f52aa2cc634c5bec4a843fb3 .brik/manifest.json +d117870091ed333c4c180eb4fe0ac5f61aee55a0da5fb67ebea23863d57b4f3f CHANGELOG.md +08ed88b54153f473ae8c29972d137b5a9f6893fd3178754e61a2ef29ae040e47 LICENSE +b70107f9dd359eb374de9a9dce99821ed5dbbd021116645e0d32c67fb7fc9b18 NOTICE +7b4fbb4b65e30e58f2dbf28ad0fddd1b0eb9641bfef9d586358e0343e1f33ccb README.md +cf39e055374caeecaac773d9802098a7c1717e271be4b00c25d2a2a9bf157aa1 SECURITY.md +11a5eadb7ec6f7d07e329c767026ae9576bdaf99c1d411781e5f88108e7d852e engines/l4plus-n5/checksums.tsv +221774c3a8f9e1cf630521a12a2a62f265d34313cdeaf7bb30ca69f60bd3a8d8 engines/l4plus-n5/runtime-bundle.manifest.json +6f2a3eff7b3cbf80debb823f1771df5364d6f1fdf2c0b6c2dab8e109c04dc757 engines/l4plus-n5/serial.txt +7bf04f505e50c95e6864d5140c7fc1acab214c2bdef6028bfe382ffc8538e3e7 evidence/beta8-adversarial/report.json +84c5f4c7f6ac016a762cd024d7838eac47d837a7d7042e87b2282cb0ca382259 evidence/beta8-compiler-functionality/report.json +3b99b7e885e6bf2d730bd7f4ca3c3bae00270f775523c66150d21d2004e70628 package.json +2a629b0c88a96c81a42f3e5949900798fe25886aec7ac203855ba7540cd3b36c pcd/cli_account_session.pcd +ff48eaeb3848e39c5400fcbb9fc293e5fffb649db2e32454f900080be660ef1c pcd/cli_core.pcd +3ea78bd6e28c15b409318be8107590e2a833ca6bea98df8a974f4ac7e0beb6ed pcd/cli_migrate.pcd +4813a13cecb6e9644e22c7736fb46acacc5a381bf4f444e74ef3301a20dafcde pcd/cli_polymer.pcd +eeada3bbe77fc19a4387acbf4fced480b06acd1776b8d1587d69ec8e855c0e24 pcd/cli_polymerize.pcd +6987959306e52657f53de2ac6e1d35c8389d4ce1e571db381e978dcf650e96ad pcd/cli_verify.pcd +63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed src/brik.js diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json new file mode 100644 index 00000000..225e72b6 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json @@ -0,0 +1,53 @@ +{ + "schema": "brik64.cli_project_manifest.v1", + "schemaVersion": "brik64.cli_project_manifest.v1", + "project": "brik64-cli", + "cliVersion": "0.1.0-beta.8", + "lane": "cli_0_1_beta", + "generationClaim": "assisted_generation_non_claim", + "preferred_engine": "auto", + "polymer_strategy": "local_ast", + "managed_platform": { + "enabled": false, + "routing": "local_default" + }, + "semanticSourceStatus": "candidate_pcd_seed", + "semanticSourceRoot": "pcd/", + "compositionPcd": "pcd/cli_polymer.pcd", + "bootstrapEntrypoint": "src/brik.js", + "publicBinaryName": "brik", + "engineTierPolicy": { + "publicOfflineRuntime": "local_runtime", + "registeredManagedRuntime": "managed_platform", + "internalArtifactFactory": "private_factory", + "l6DistributionAllowed": false, + "l5EmbeddedFreeRuntimeAllowed": false + }, + "claimBoundary": { + "releaseAuthorized": false, + "releaseAllowed": false, + "fixpointClaimAuthorized": false, + "n5ClaimAuthorized": false, + "formalCertificationAuthorized": false, + "rustIndependenceClaimAuthorized": false + }, + "methodologyTransition": { + "target": "pcd_first_cli_iteration", + "requiredBeforePublicBeta": [ + "pcd_semantic_source_complete", + "pcd_polymer_composition_report_present", + "pcd_certification_report_present", + "brik_compiler_build_report_present", + "macos_arm64_execution_report_present", + "linux_distro_execution_reports_present", + "windows_x64_execution_report_present", + "release_claim_boundary_gate_pass" + ], + "currentStatus": "bootstrap_non_release" + }, + "certification": { + "certifiesFormalCorrectness": false, + "certifiesTests": false, + "certifiesFixpoint": false + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md new file mode 100644 index 00000000..8245da2e --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md @@ -0,0 +1,137 @@ +# Changelog + +All notable BRIK64 CLI changes are recorded here. This file is required for +every beta, release candidate, or public release train. + +## 0.1.0-beta.8 + +### Added + +- Adds bounded source-to-source PCD emission for executable TypeScript, Rust, + and Python programs. +- Adds generated target tests that execute emitted programs and check expected + behavior across supported target languages. +- Adds parser support for arithmetic expressions, comparisons, boolean + conditions, nested branches, and expression returns. +- Adds adversarial parser coverage for malformed input, binary data, oversized + PCD files, unsupported statements, and path traversal attempts. +- Adds a local package smoke check that extracts the beta8 tarball and runs the + packaged CLI outside the repository checkout. + +### Changed + +- Updates `brik64 emit` from static candidate output toward executable output + for the supported beta PCD syntax. +- Keeps unsupported syntax fail-closed with actionable parser errors. + +### Compatibility + +- macOS and Linux continue to use the portable Node.js CLI package and require + Node.js 20 or newer. +- Windows native executables are not published in this beta. +- This beta does not claim formal certification for arbitrary user code, + universal correctness, or independent toolchain closure. + +## 0.1.0-beta.7 + +### Added + +- Adds `brik64 polymerize` for local PCD composition into a deterministic + polymer file and companion manifest. +- Adds `brik64 verify` for local certificate, source hash, and AST hash checks. +- Adds `brik64 migrate` to update legacy lowercase `pc` files to the current + `PC` syntax. +- Adds `brik64 login`, `brik64 logout`, and `brik64 account status` as the CLI + account boundary for future platform-connected workflows. +- Adds `brik64 doctor --json` while keeping human-readable `doctor` output as + the default terminal experience. + +### Changed + +- Extends workspace manifests with preferred engine routing and polymerization + strategy metadata for local-first operation. +- Improves parser errors for legacy PCD syntax by pointing users to + `brik64 migrate`. +- Keeps cloud verification and cloud polymerization fail-closed unless a + platform entitlement is present. + +### Compatibility + +- macOS and Linux continue to use the portable Node.js CLI package and require + Node.js 20 or newer. +- Windows native executables are not published in this beta. +- This beta does not claim formal certification for arbitrary user code, + universal correctness, or independent toolchain closure. + +## 0.1.0-beta.6 + +### Added + +- Adds a portable `brik64` CLI package installable through the public curl + installer on supported macOS and Linux environments. +- Adds local workspace initialization, certificate creation, TypeScript output, + and stale-certificate protection to the distributed beta package. +- Adds visible package metadata so users can verify the installed CLI version + and SHA-256 checksum. + +### Changed + +- Updates `brik64 --version`, README, and install guidance to + `0.1.0-beta.6`. +- Clarifies that the CLI is installed with curl, while SDKs are installed with + the package manager for each language. + +### Compatibility + +- macOS and Linux use the portable Node.js CLI package and require Node.js 20 or + newer. +- Windows native executables are not published in this beta. +- This beta does not claim formal certification for arbitrary user code or + independent toolchain closure. + +## 0.1.0-beta.5 + +### Added + +- Added local workspace validation with `brik64 doctor`. +- Added `brik64 engine status` so users can inspect the packaged offline + runtime bundle installed with the CLI. +- Added hash-bound candidate output generation for TypeScript, Rust, and + Python through `brik64 emit --target `. +- Added package checksums and local install smoke coverage for the public beta + package. +- Added matching beta SDK package coordinates for TypeScript, Python, and Rust. +- Added public release-train validation so CLI, SDK, docs, web, skills, + release notes, and installer metadata can be checked from one manifest. + +### Changed + +- Updates public install guidance from beta4 to beta5. +- Clarifies that npm is used for SDK packages, while the CLI install path is + the curl installer and GitHub Release assets. +- Improves failure boundaries for stale certificates, tampered runtime metadata, + and mismatched generated outputs. +- Aligns public docs, website install surfaces, skills, SDK references, and + release notes to beta5. + +### Fixed + +- Fixes stale beta references in local seed metadata and public install + surfaces. +- Fixes release notes that previously mixed public functionality with internal + operating details. +- Fixes docs and skills drift where older beta package coordinates could remain + visible. + +### Compatibility + +- macOS and Linux are the current installable CLI lanes for beta5. +- Node.js 20 or newer is required. +- Windows native executables are not published in this beta. + +## 0.1.0-beta.4 - Published Beta Reference + +Status: latest prior public release reference. + +Use GitHub Releases, curl installer metadata and published docs as the authority +for what beta4 made publicly installable. diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE new file mode 100644 index 00000000..fd2655d7 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE @@ -0,0 +1,71 @@ +BRIK64 CLI PUBLIC BETA EVALUATION LICENSE + +Copyright (c) 2026 BRIK64 INC. All rights reserved. + +This package, including the BRIK64 CLI source, bundled PCD seed material, +examples, package metadata, documentation, evidence artifacts, and release +materials, is proprietary software and confidential know-how of BRIK64 INC +except where a file explicitly states otherwise. + +1. Evaluation Permission + +BRIK64 INC grants you a limited, revocable, non-exclusive, non-transferable +permission to download, install, and run this public beta release only for +internal evaluation, local workflow testing, compatibility review, and feedback +to BRIK64. + +2. Reserved Rights + +BRIK64 INC reserves all rights not expressly granted in this license. This +license does not grant any ownership interest, patent license, trademark license, +commercial distribution right, sublicensing right, hosted service right, resale +right, or right to create derivative works for public or commercial use. + +3. Restrictions + +Without prior written permission from BRIK64 INC, you may not: + +- redistribute, mirror, sell, sublicense, rent, lease, or commercially exploit + this software; +- publish modified versions or derivative works; +- remove copyright, trademark, provenance, release, checksum, or evidence + notices; +- use BRIK64 names, logos, marks, or release artifacts to imply endorsement or + certification; +- use the beta in regulated, safety-critical, mission-critical, or production + systems as a certification authority. + +4. Beta Scope + +This public beta is provided for evaluation of local BRIK64 CLI workflows, +PCD-oriented project structure, package validation, and bounded evidence review. +Expanded platform support, production certification surfaces, and advanced +compiler-methodology scopes are governed by BRIK64 release gates and written +commercial terms. + +5. Feedback + +If you provide feedback, bug reports, ideas, or suggestions to BRIK64, you grant +BRIK64 INC a perpetual, irrevocable, worldwide, royalty-free right to use that +feedback to improve BRIK64 products and services without obligation to you. + +6. No Warranty + +This beta is provided as-is for evaluation. BRIK64 INC disclaims all warranties, +express or implied, including merchantability, fitness for a particular purpose, +non-infringement, and uninterrupted or error-free operation. + +7. Limitation Of Liability + +To the maximum extent permitted by law, BRIK64 INC is not liable for indirect, +incidental, special, consequential, exemplary, punitive, or business interruption +damages arising from this beta, even if advised of the possibility of such +damages. + +8. Commercial Licensing + +For production, commercial, hosted, redistribution, partner, enterprise, +regulated, or certification-oriented use, contact BRIK64 INC through the public +company channels listed at https://brik64.com. + +This is not an open source license. diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE new file mode 100644 index 00000000..aa404714 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE @@ -0,0 +1,18 @@ +BRIK64 CLI Public Beta Notice + +Copyright (c) 2026 BRIK64 INC. All rights reserved. + +BRIK64 CLI 0.1 public beta is proprietary software published for evaluation of +local PCD workflows, bounded evidence review, and claim-safe project scaffolding. +The current public beta surface is focused on macOS local CLI usage, package +validation, and versioned release evidence. Expanded platform support and +stronger certification surfaces remain governed by the BRIK64 evidence process +and commercial licensing terms. + +Public product information: https://brik64.com +Documentation: https://docs.brik64.com/cli/install +Repository: https://github.com/brik64/brik64-cli +Package: https://www.npmjs.com/package/@brik64/cli + +License: BRIK64 CLI Public Beta Evaluation License. This is not an open source +license. See LICENSE for evaluation terms and reserved rights. diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md new file mode 100644 index 00000000..d4f498bb --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md @@ -0,0 +1,119 @@ +# BRIK64 CLI + +BRIK64 CLI is the public beta command-line surface for local BRIK64 project +workflows. It helps developers initialize `.brik` metadata, work with PCD files, +create local candidate evidence, emit supported language targets, and prepare +artifacts for managed platform workflows. + +Current beta candidate: `0.1.0-beta.8` + +## Install + +The public CLI install path is curl-only: + +```sh +curl -fsSL https://brik64.com/cli/install.sh | bash +``` + +After installation: + +```sh +brik64 --version +brik64 help +``` + +The npm package namespace is reserved for SDK libraries, not CLI installation. + +## Beta8 Command Surface + +`0.1.0-beta.8` focuses on making PCD emission executable for the supported +beta syntax while keeping local/managed workflow boundaries intact. + +- `brik64 init` creates `.brik/manifest.json` and does not create `AGENTS.md`. +- `brik64 doctor` prints a human-readable workspace summary. +- `brik64 doctor --json` emits `brik64.cli_doctor_report.v1` for CI. +- `brik64 account status` shows whether the CLI is using local default routing + or a managed session. +- `brik64 login --token-env ` records a managed-session token hash without + printing the token. +- `brik64 logout` returns routing to local default. +- `brik64 certify ` writes a local candidate certificate. +- `brik64 verify ` checks local certificate and AST/hash coherence. +- `brik64 emit --target --out

--tests` + emits executable target files and generated tests for supported beta PCD + expressions and branches. +- `brik64 polymerize --out polymer.pcd` combines compatible PCD + files into a deterministic local polymer candidate. +- `brik64 migrate ` converts supported legacy PCD syntax into the + current strict syntax. + +Managed `--cloud` paths are entitlement-gated in this beta. Without a managed +session, those paths fail closed and keep local artifacts unchanged. + +## Platform Support + +| Platform | Status | Notes | +| --- | --- | --- | +| macOS | Available in current beta candidate | Portable Node.js CLI package; requires Node.js 20 or newer. | +| Linux | Available in current beta candidate | Portable Node.js CLI package; requires Node.js 20 or newer. | +| Windows x64 native | Not available in current public beta | No Windows executable is published. | + +The public installer verifies the package SHA-256 before activation. The +authoritative checksum is published with release assets in `package.manifest.json` +and `SHA256SUMS`. + +## SDK Boundary + +SDKs are distributed separately from the CLI. Current beta SDK package +coordinates: + +```sh +npm install @brik64/core@0.1.0-beta.8 +pip install brik64==0.1.0b8 +cargo add brik64-core@0.1.0-beta.8 +``` + +SDK packages are language libraries. They do not install the CLI, issue managed +claims, or replace the CLI workspace workflow. + +## Claim Boundary + +This beta provides local candidate evidence and managed-workflow routing +boundaries. It does not by itself establish formal certification for arbitrary +user code, universal correctness, independent toolchain closure, or native +Windows compatibility. + +## CLI And Agent Skill + +Use the CLI for local project actions and the official `brik64` skill for agent +behavior, claim-safe reporting, `.brik` traceability, PCD workflow, and +consent-based `AGENTS.md` handling. + +`brik64 init` prepares local BRIK64 metadata. It does not create or modify +`AGENTS.md`. + +## Repository Map + +| Path | What it contains | +| --- | --- | +| `src/brik.js` | Node.js entry point for current public beta command behavior. | +| `tests/smoke.sh` | Local smoke test for current beta command behavior. | +| `pcd/` | Candidate PCD seed material for command structure. | +| `evidence/` | Public beta evidence notes and generated-review placeholders. | +| `packaging/` | Platform packaging notes and release-lane material. | +| `docs/` | Release, distribution, governance, platform, and testing docs. | +| `.brik/manifest.json` | Local traceability metadata. It is not a certificate. | + +## Release Evidence + +Use GitHub Release assets, release manifest, and `SHA256SUMS` to review the +latest published package. + +https://github.com/brik64/brik64-cli/releases + +## Copyright And License + +Copyright (c) 2026 BRIK64 INC. All rights reserved. + +See [LICENSE](LICENSE) and [NOTICE](NOTICE). BRIK64 CLI public beta is +proprietary evaluation software from BRIK64 INC. diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md new file mode 100644 index 00000000..142c352b --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md @@ -0,0 +1,54 @@ +# Security Policy + +BRIK64 CLI is public beta evaluation software from BRIK64 INC. + +## Supported Versions + +| Version | Status | +| --- | --- | +| `0.1.0-beta.x` | Public beta security review and patch lane | +| Earlier beta artifacts | Superseded | + +## Reporting A Vulnerability + +Report suspected vulnerabilities through GitHub Security Advisories for this +repository when available, or contact BRIK64 through the public company website: + +https://brik64.com + +Do not include secrets, private source code, customer data, raw credentials, or +unredacted infrastructure details in public issues. + +Use public issues only for non-sensitive bugs, docs mismatches, package metadata, +install failures, or release evidence questions. If an issue may expose a token, +private path, customer data, unpublished source, infrastructure detail, or +exploit path, use a private security report path instead. + +## Public Beta Scope + +Security review for this repository covers the public CLI package surface, +release metadata, package workflows, local smoke tests, PCD seed files, and +bounded evidence artifacts included with the beta. + +`brik64-prod` remains the authority for methodology, certification boundaries, +evidence gates, compiler claim authorization, and release approval. + +## Disclosure Handling + +BRIK64 will triage reports by affected version, exploitability, package +surface, and evidence impact. Fixes may be shipped as new beta versions, +repository advisories, release notes, or docs updates depending on scope. + +## Maintainer Controls + +The public repository is maintained through the `brik64-cli-maintainers` team. +External pull requests are not accepted. Changes to package metadata, release +evidence, license text, workflows, public claims, or install paths must land +through authorized maintainers, protected branch rules, and passing checks. + +## Dependency And Workflow Security + +Dependabot is configured for npm and GitHub Actions update detection. CodeQL +default setup and CI smoke/package checks provide repository-level regression +signals. These checks are operational security controls; they do not certify the +CLI or expand the public beta claim boundary. diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv new file mode 100644 index 00000000..7acbde74 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv @@ -0,0 +1,42 @@ +1c0f49c9454496d88541927ccaf750df5f93d64ae9a6195d5bffa79d2aa2930c ./.brik/logic-ledger.jsonl +99edba6a784b4f274d80cef615542aac9dcfe455afe8155edd5cbef0b3543c72 ./README.md +246ad453d40d60c216b0afd113258bb4e81595de2edd39d69a23a27218098315 ./checksums.tsv +f08013a913983ac5f9de3684e6715b46447a5fd1ba9b2c42ed3ad7c75cadb581 ./evidence/l4plus_n5_burn_in_report.json +5359afe66a536a649fc01f8695a30741b5314f27b2f7136dfdf310caf49dc906 ./evidence/l4plus_n5_critical_artifact_lock.json +86828d4fe8bad314e4eb34662f7023cc7bb155223d24af160f7d45ee0cd2726c ./evidence/l4plus_n5_critical_freeze_certificate.json +ab9f691b1f0525c8e0a1c47be87f58691e8969b34e1c0fbd9620fd96fd33fe65 ./evidence/l4plus_n5_critical_freeze_report.json +9f9f293ddd34a066e36fb28c703f9de810c53517a7b2e34899eb2617294a88c5 ./manifest/claim_boundary.json +470454a0ab21fb6629838d91a4b410c48d669446fd2e213090510669bcb9435c ./pcd/engine.manifest.json +8e87f92ce267f33aa1fcd3e8815502e08f887637300030cc8b565e508a7b7668 ./pcd/engine.pcd +51a256276984c44fac6a1f4fc5e05148b05e9bdf3381014df292b58a505722c2 ./pcd/evidence_pack.manifest.json +80f9d64ed801138fb4b7dbf5c10b778adc3c3da790727c8c7036bdb9ddc3dfc2 ./pcd/evidence_pack.pcd +d2cbabbc96440bdadae2cfe42acc32bd27bd6689f8635fc6df07d34eb64b5fc7 ./pcd/generated_tests_fixtures.json +bfd213dc99445a1687f95962524ba22509c099852fe31eb69f8c25f1faf7ba06 ./pcd/generated_tests_harness.pcd +adec2a5f643dc52381d08efae3fa9da791ec1af35e4e44d9a1eb3d9a9195fb63 ./pcd/harness.manifest.json +b9dc97d75637ff69eef7489a2825c166d43ff2cc73d1b59a4e1bef2ee27a6c34 ./pcd/harness.pcd +14645419bdfde549122d0df9537b806d8620be6953222feb66fd5134c5c6d6cf ./pcd/l4plus_engine_runtime.bir +0c7d54c6f4e35ef099eb463e817606bb54f4349fcd2ada3646fa19ae76b14779 ./pcd/l4plus_engine_runtime.bir.asm +cb69bb34b595120b983959139204ccf6dd33cd246364e5a9d30cc206069fda71 ./pcd/l4plus_engine_runtime.cert.json +6e6681fa5d2ccdc4ab99c4dafe8d6dd1fdf41e7b83dc347426c7c64f7a87be20 ./pcd/l4plus_n5_evidence_pack.bir +74e8b295611381de74dbbd052d4021e020d185dbcd62f996852db653b24336aa ./pcd/l4plus_n5_evidence_pack.bir.asm +b87a48dc37a859064b8c6bd8e22a2fada02b16ab22d9bb0809880cba02bbd871 ./pcd/l4plus_n5_evidence_pack.cert.json +9b67badac2ac26677885e5f0372f1d37a7432c86b35ff4467f5c9b0f16805dd0 ./pcd/l4plus_n5_generated_tests_harness.bir +dd38c327deae28c27d143eb8b8e59d659b5da58afbc06b36fa6954b8222892a6 ./pcd/l4plus_n5_generated_tests_harness.bir.asm +6dbd379d6b7bbe8d5a31612f80c1b67984f6de1bc6fb2bd974d5e206861ee38f ./pcd/l4plus_n5_generated_tests_harness.cert.json +e8bd3e86c3a3de5affb28396c2cc54906dd036a177a33859f27fec9df0791ec5 ./pcd/l4plus_n5_generated_tests_harness.generated-test.sh +f24945f5832aa377f4a49fc00c10522f8a2590424743f09455047adad515cf06 ./pcd/l4plus_n5_generated_tests_harness.tests.manifest.json +670d64da83a7b606d2b9d1474382df4b1ff73ae2174b74e315edd2783ae782f2 ./pcd/l4plus_n5_harness.bir +bdc9d30d0d512ba090f4ce561ec75357b3b1d481ee05a41d6d07f3de6fa48673 ./pcd/l4plus_n5_harness.bir.asm +01f560f9e89e616031ede3db46e73e8927b6b18e3fd74702c62520d81e514365 ./pcd/l4plus_n5_harness.cert.json +a0964fc1309466012128de4c4fcdac87a5f6bc40bc7c6e566b0a4fc77229d70b ./pcd/l4plus_n5_proof_binder.bir +6f7bb3a734cf07cb971550076c9f6fda9a471d7dedf0cea5b38c455a6cccabfd ./pcd/l4plus_n5_proof_binder.bir.asm +63d263a507e6e1e7d40f99284a8bd3ce57ee16836048a73542a294df99aa6aea ./pcd/l4plus_n5_proof_binder.cert.json +3a44add012a1832428aba24e3a53b1f4b1198571d926db9da6c031ba4ae3855c ./pcd/l4plus_n5_reconstruction.pcd +9a92f5136cf375eefdddfd926585eca411149b2e4bc5b9653aca9004c85ddee4 ./pcd/l4plus_n5_runtime_adapter.bir +8639bfcf9e7e7daf105e50b3922ab52a67bd63a28202140615ba3fc322abe249 ./pcd/l4plus_n5_runtime_adapter.bir.asm +628b196cdef72a7c5cf8e50dc350f4f72cabfec3eea1324985e2400fd5eededb ./pcd/l4plus_n5_runtime_adapter.cert.json +a81a905a0ce8d3a84fbe94d843c1274a193e7329eb69ffbbd22d2c9f842fde9d ./pcd/proof_binder.manifest.json +f3b0691d9d8323e263cef5255d0f7123a1206c5802ddb28e02683c84dec32704 ./pcd/proof_binder.pcd +659cb4738f3fcaf702aa7808aca00704c82b0649714f5f289d2ef48a491ef0c3 ./pcd/runtime_adapter.manifest.json +c7354811628f1c323151788f37d388c3c5baeda328de06504997eed71c82513b ./pcd/runtime_adapter.pcd +6f2a3eff7b3cbf80debb823f1771df5364d6f1fdf2c0b6c2dab8e109c04dc757 ./serial.txt diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json new file mode 100644 index 00000000..f28b9f95 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json @@ -0,0 +1,147 @@ +{ + "schemaVersion": "brik64.cli_l4plus_n5_portable_runtime_bundle.v1", + "decision": "PASS_PORTABLE_L4_BUNDLE_PACKAGED", + "releaseEligible": false, + "runtimeMode": "portable_bir_bundle", + "nativeExecutableIncluded": false, + "cliVersion": "0.1.0-beta.5", + "engine": "L4+N5", + "serial": "BRIK64-L4PLUS-N5-20260525-12d8e4662dec74a4", + "sourceRepo": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5", + "claimBoundary": { + "publicClaimsAllowed": true, + "n5Authorized": true, + "r99_9ClaimAllowed": true, + "r99_999999ClaimAllowed": false, + "universalCorrectnessClaimAllowed": false, + "platformCanIssueCertification": false + }, + "artifacts": [ + { + "path": "engines/l4plus-n5/serial.txt", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/serial.txt", + "sha256": "6f2a3eff7b3cbf80debb823f1771df5364d6f1fdf2c0b6c2dab8e109c04dc757", + "bytes": 43 + }, + { + "path": "engines/l4plus-n5/checksums.tsv", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/checksums.tsv", + "sha256": "11a5eadb7ec6f7d07e329c767026ae9576bdaf99c1d411781e5f88108e7d852e", + "bytes": 4234 + }, + { + "path": "engines/l4plus-n5/manifest/claim_boundary.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/manifest/claim_boundary.json", + "sha256": "9f9f293ddd34a066e36fb28c703f9de810c53517a7b2e34899eb2617294a88c5", + "bytes": 372 + }, + { + "path": "engines/l4plus-n5/evidence/l4plus_n5_critical_artifact_lock.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/evidence/l4plus_n5_critical_artifact_lock.json", + "sha256": "5359afe66a536a649fc01f8695a30741b5314f27b2f7136dfdf310caf49dc906", + "bytes": 4000 + }, + { + "path": "engines/l4plus-n5/evidence/l4plus_n5_critical_freeze_certificate.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/evidence/l4plus_n5_critical_freeze_certificate.json", + "sha256": "86828d4fe8bad314e4eb34662f7023cc7bb155223d24af160f7d45ee0cd2726c", + "bytes": 4890 + }, + { + "path": "engines/l4plus-n5/evidence/l4plus_n5_critical_freeze_report.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/evidence/l4plus_n5_critical_freeze_report.json", + "sha256": "ab9f691b1f0525c8e0a1c47be87f58691e8969b34e1c0fbd9620fd96fd33fe65", + "bytes": 1215 + }, + { + "path": "engines/l4plus-n5/evidence/l4plus_n5_burn_in_report.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/evidence/l4plus_n5_burn_in_report.json", + "sha256": "f08013a913983ac5f9de3684e6715b46447a5fd1ba9b2c42ed3ad7c75cadb581", + "bytes": 4127 + }, + { + "path": "engines/l4plus-n5/pcd/engine.manifest.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/engine.manifest.json", + "sha256": "470454a0ab21fb6629838d91a4b410c48d669446fd2e213090510669bcb9435c", + "bytes": 6066 + }, + { + "path": "engines/l4plus-n5/pcd/engine.pcd", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/engine.pcd", + "sha256": "8e87f92ce267f33aa1fcd3e8815502e08f887637300030cc8b565e508a7b7668", + "bytes": 341 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_engine_runtime.bir", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_engine_runtime.bir", + "sha256": "14645419bdfde549122d0df9537b806d8620be6953222feb66fd5134c5c6d6cf", + "bytes": 300 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_engine_runtime.bir.asm", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_engine_runtime.bir.asm", + "sha256": "0c7d54c6f4e35ef099eb463e817606bb54f4349fcd2ada3646fa19ae76b14779", + "bytes": 405 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_engine_runtime.cert.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_engine_runtime.cert.json", + "sha256": "cb69bb34b595120b983959139204ccf6dd33cd246364e5a9d30cc206069fda71", + "bytes": 6611 + }, + { + "path": "engines/l4plus-n5/pcd/harness.manifest.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/harness.manifest.json", + "sha256": "adec2a5f643dc52381d08efae3fa9da791ec1af35e4e44d9a1eb3d9a9195fb63", + "bytes": 6061 + }, + { + "path": "engines/l4plus-n5/pcd/harness.pcd", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/harness.pcd", + "sha256": "b9dc97d75637ff69eef7489a2825c166d43ff2cc73d1b59a4e1bef2ee27a6c34", + "bytes": 558 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_n5_harness.bir", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_n5_harness.bir", + "sha256": "670d64da83a7b606d2b9d1474382df4b1ff73ae2174b74e315edd2783ae782f2", + "bytes": 378 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_n5_harness.cert.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_n5_harness.cert.json", + "sha256": "01f560f9e89e616031ede3db46e73e8927b6b18e3fd74702c62520d81e514365", + "bytes": 6604 + }, + { + "path": "engines/l4plus-n5/pcd/runtime_adapter.manifest.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/runtime_adapter.manifest.json", + "sha256": "659cb4738f3fcaf702aa7808aca00704c82b0649714f5f289d2ef48a491ef0c3", + "bytes": 6085 + }, + { + "path": "engines/l4plus-n5/pcd/runtime_adapter.pcd", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/runtime_adapter.pcd", + "sha256": "c7354811628f1c323151788f37d388c3c5baeda328de06504997eed71c82513b", + "bytes": 749 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_n5_runtime_adapter.bir", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_n5_runtime_adapter.bir", + "sha256": "9a92f5136cf375eefdddfd926585eca411149b2e4bc5b9653aca9004c85ddee4", + "bytes": 521 + }, + { + "path": "engines/l4plus-n5/pcd/l4plus_n5_runtime_adapter.cert.json", + "sourcePath": "/Users/carlosjperez/Documents/GitHub/brik64-engine-l4plus-n5/pcd/l4plus_n5_runtime_adapter.cert.json", + "sha256": "628b196cdef72a7c5cf8e50dc350f4f72cabfec3eea1324985e2400fd5eededb", + "bytes": 6628 + } + ], + "blockers": [], + "limitations": [ + "This bundle packages portable PCD/BIR/certificate evidence for offline CLI binding.", + "It does not include a native executable runtime.", + "It does not authorize universal correctness claims." + ] +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt new file mode 100644 index 00000000..dd274e13 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt @@ -0,0 +1 @@ +BRIK64-L4PLUS-N5-20260525-12d8e4662dec74a4 diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json new file mode 100644 index 00000000..b092dd00 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": "brik64.cli_beta8_adversarial_gate.v1", + "generatedAt": "2026-06-06T02:34:44Z", + "iter_id": "BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1", + "lane": "cli_0_1_beta8", + "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", + "rc": 0, + "cliVersion": "0.1.0-beta.8", + "cliSha256": "sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed", + "executableEdgeFixture": { + "path": "pcd/edge_precedence.pcd", + "sha256": "sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63" + }, + "passChecks": 9, + "failClosedChecks": 12, + "generatedTargetExecution": { + "typescript": true, + "rust": true, + "python": true + }, + "failClosedSurface": [ + "empty_pcd", + "binary_input", + "too_large_input", + "legacy_syntax", + "missing_fn", + "too_many_params", + "invalid_param", + "missing_return", + "unsupported_statement", + "unsupported_expression_token", + "malformed_expression", + "unclosed_block" + ], + "claim_boundary": { + "public_claims_allowed": false, + "public_release_allowed": false, + "adversarial_gate_passed": true, + "compiler_functionality_scope": "supported_beta8_pcd_subset_only", + "fixpoint_claim_allowed": false, + "n5_formal_claim_allowed": false, + "rust_independence_claim_allowed": false + }, + "blockers": [], + "warnings": [], + "next_action": "run beta8 package smoke and release-train sync gates" +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json new file mode 100644 index 00000000..23c10002 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json @@ -0,0 +1,49 @@ +{ + "schemaVersion": "brik64.cli_beta8_compiler_functionality_gate.v1", + "generatedAt": "2026-06-06T02:34:41Z", + "iter_id": "BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1", + "lane": "cli_0_1_beta8", + "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "rc": 0, + "cliVersion": "0.1.0-beta.8", + "cliSha256": "sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed", + "fixture": { + "path": "pcd/branch_math.pcd", + "sha256": "sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404" + }, + "executedTargets": { + "typescript": { + "programSha256": "sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95", + "test": "node out-ts/program.test.mjs", + "passed": true + }, + "rust": { + "programSha256": "sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d", + "test": "rustc out-rust/program_test.rs && ./out-rust/program_test", + "passed": true + }, + "python": { + "programSha256": "sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6", + "test": "PYTHONPATH=out-python python3 out-python/test_program.py", + "passed": true + } + }, + "adversarial": { + "unknown_identifier_fail_closed": true, + "unsupported_target_fail_closed": true, + "path_traversal_fail_closed": true, + "stack_trace_leaked": false + }, + "claim_boundary": { + "public_claims_allowed": false, + "public_release_allowed": false, + "compiler_functionality_claim_allowed": true, + "compiler_functionality_scope": "supported_beta8_pcd_subset_only", + "fixpoint_claim_allowed": false, + "n5_formal_claim_allowed": false, + "rust_independence_claim_allowed": false + }, + "blockers": [], + "warnings": [], + "next_action": "run beta8 adversarial gate and package smoke before public release train" +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json new file mode 100644 index 00000000..59b4b3a3 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json @@ -0,0 +1,13 @@ +{ + "name": "@brik64/cli", + "version": "0.1.0-beta.8", + "private": true, + "description": "BRIK64 CLI public beta candidate for local PCD workflows and bounded compiler emission.", + "bin": { + "brik": "src/brik.js" + }, + "engines": { + "node": ">=20" + }, + "distribution": "curl_and_github_release_assets" +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd new file mode 100644 index 00000000..29ae155d --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd @@ -0,0 +1,31 @@ +// brik64.pcd_file.v1 +// name: brik_cli_account_session +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// commands = "login,logout,account status" +// token_policy = "never_print_secret" +// storage = "local_config_token_hash_only_beta" +// claim_boundary = "session_routing_only" + +PC brik_cli_account_session { + fn brik_cli_account_session(command_code, token_present, session_present) { + if (command_code == 1) { + if (token_present == 0) { + return 67; + } + return 0; + } + if (command_code == 2) { + return 0; + } + if (command_code == 3) { + if (session_present == 1) { + return 1; + } + return 0; + } + return 64; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd new file mode 100644 index 00000000..69561fab --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd @@ -0,0 +1,33 @@ +// brik64.pcd_file.v1 +// name: brik_cli_core +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// product = "brik64-cli" +// cli_version = "0.1.0-beta.7" +// public_binary = "brik" +// execution_status = "public_beta" +// ascii_banner = "BRIK64" +// public_runtime = "local" +// managed_runtime = "platform" +// internal_artifact_factory = "private" +// claim_boundary = "local_candidate_only" + +PC brik_cli_core { + fn brik_cli_core(command_code, json_mode, ci_mode) { + if (json_mode == 1) { + return 0; + } + if (ci_mode == 1) { + return 0; + } + if (command_code == 0) { + return 1; + } + if (command_code == 64) { + return 64; + } + return 0; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd new file mode 100644 index 00000000..1bdf74fb --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd @@ -0,0 +1,27 @@ +// brik64.pcd_file.v1 +// name: brik_cli_migrate +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// command = "migrate" +// supported_legacy = "lowercase_pc,circuit" +// output_policy = "no_overwrite_without_explicit_mode" +// claim_boundary = "syntax_migration_only" + +PC brik_cli_migrate { + fn brik_cli_migrate(file_present, legacy_detected, output_exists, in_place_requested) { + if (file_present == 0) { + return 64; + } + if (legacy_detected == 0) { + return 0; + } + if (output_exists == 1) { + if (in_place_requested == 0) { + return 73; + } + } + return 0; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd new file mode 100644 index 00000000..87925a10 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd @@ -0,0 +1,59 @@ +// brik64.pcd_file.v1 +// name: brik_cli_polymer +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// product = "brik64-cli" +// cli_version = "0.1.0-beta.7" +// composition_kind = "polymer" +// source_units = "cli_core.pcd,cli_init_policy.pcd,cli_certify_emit.pcd,cli_polymerize.pcd,cli_verify.pcd,cli_account_session.pcd,cli_migrate.pcd" +// compile_status = "not_compiled" +// certificate_status = "candidate_only" +// reads "pcd/cli_core.pcd" +// reads "pcd/cli_init_policy.pcd" +// reads "pcd/cli_certify_emit.pcd" +// reads "pcd/cli_polymerize.pcd" +// reads "pcd/cli_verify.pcd" +// reads "pcd/cli_account_session.pcd" +// reads "pcd/cli_migrate.pcd" +// requires ascii_banner == "BRIK64" +// requires agent_instruction_policy == "consent_required" +// requires existing_agents_md_must_not_be_overwritten == true +// requires certificate_before_emit == true +// requires supported_emit_targets == "ts,rust,python" +// invariant compile_requires_certified_pcd_batch == true +// invariant compile_requires_polymer_contract == true +// invariant local_runtime_available == true +// invariant managed_runtime_entitlement_required == true +// invariant internal_artifact_factory_private == true +// invariant public_claim_allowed == false +// polymer brik_cli_candidate +// claim_boundary = "local_candidate_only" + +PC brik_cli_polymer { + fn brik_cli_polymer(command_code, workspace_readable, certificate_present, target_code) { + if (workspace_readable == 0) { + return 64; + } + if (command_code == 1) { + return 0; + } + if (command_code == 2) { + if (certificate_present == 0) { + return 67; + } + if (target_code < 1) { + return 65; + } + if (target_code > 3) { + return 65; + } + return 1; + } + if (command_code == 64) { + return 64; + } + return 0; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd new file mode 100644 index 00000000..07e187a6 --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd @@ -0,0 +1,29 @@ +// brik64.pcd_file.v1 +// name: brik_cli_polymerize +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// command = "polymerize" +// local_mode = "ast_composition" +// managed_mode = "entitlement_required" +// output = "polymer.pcd" +// manifest = "polymer.pcd.manifest.json" +// claim_boundary = "local_candidate_only" + +PC brik_cli_polymerize { + fn brik_cli_polymerize(input_count, cloud_requested, entitlement_present, duplicate_symbol) { + if (input_count < 1) { + return 64; + } + if (duplicate_symbol == 1) { + return 65; + } + if (cloud_requested == 1) { + if (entitlement_present == 0) { + return 67; + } + } + return 0; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd new file mode 100644 index 00000000..d818c7ed --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd @@ -0,0 +1,30 @@ +// brik64.pcd_file.v1 +// name: brik_cli_verify +// status: candidate_pcd_seed +// certifiesFormalCorrectness: false +// certifiesTests: false +// certifiesFixpoint: false +// command = "verify" +// local_mode = "certificate_ast_hash_coherence" +// managed_mode = "entitlement_required" +// claim_boundary = "local_candidate_only" + +PC brik_cli_verify { + fn brik_cli_verify(pcd_present, certificate_present, hash_match, cloud_requested, entitlement_present) { + if (pcd_present == 0) { + return 64; + } + if (certificate_present == 0) { + return 67; + } + if (hash_match == 0) { + return 68; + } + if (cloud_requested == 1) { + if (entitlement_present == 0) { + return 67; + } + } + return 0; + } +} diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js new file mode 100755 index 00000000..9ed63e7c --- /dev/null +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js @@ -0,0 +1,1231 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +const version = '0.1.0-beta.8'; +const SESSION_SCHEMA = 'brik64.cli_session.v1'; +const RESET = '\x1b[0m'; +const BRIK = '\x1b[38;2;180;180;180m'; +const CYAN = '\x1b[38;2;25;167;195m'; + +const LOGO_80 = String.raw` +█████████████ ███████████████ ████ ████ ██████ ▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒ +██████████████ ███████████████ ████ ████ ██████ ▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒ +████ █████ █████ █████ ██ █ ██████████ ▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒ +████ █████████ █████ ██████ ███ ████████ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ +████ █████████ █████ ██████ ████ ████████ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒ +████ ████ █████ ██████ ████ ██████████ ▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒ +██████████████ █████ ██████ ████ ████ ██████ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒ +██████████████ █████ ██████ ████ ████ ██████ ▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒ +`; + +function colorizeLogo(raw) { + return raw + .replaceAll('█', `${BRIK}█${RESET}`) + .replaceAll('▒', `${CYAN}▒${RESET}`); +} + +function printBrik64Logo() { + process.stdout.write(`${colorizeLogo(LOGO_80.trimEnd())}\n`); +} + +function sha256(value) { + return crypto.createHash('sha256').update(value).digest('hex'); +} + +function fail(code, message) { + process.stderr.write(`${message}\n`); + process.exit(code); +} + +function parseArgs(args, allowed) { + const parsed = { _: [] }; + for (let index = 0; index < args.length; index += 1) { + const arg = args[index]; + if (!arg.startsWith('--')) { + parsed._.push(arg); + continue; + } + if (!allowed[arg]) { + fail(64, `unknown_option:${arg}`); + } + if (allowed[arg] === 'boolean') { + parsed[arg] = true; + continue; + } + const value = args[index + 1]; + if (!value) { + fail(64, `missing_option_value:${arg}`); + } + parsed[arg] = value; + index += 1; + } + return parsed; +} + +function workspacePath(inputPath, errorCode = 64) { + if (!inputPath || typeof inputPath !== 'string') { + fail(errorCode, 'missing_path'); + } + const resolved = path.resolve(inputPath); + const cwd = process.cwd(); + if (resolved !== cwd && !resolved.startsWith(`${cwd}${path.sep}`)) { + fail(errorCode, 'path_outside_workspace'); + } + return resolved; +} + +function writeFileControlled(file, content) { + try { + fs.writeFileSync(file, content); + } catch (error) { + fail(74, `filesystem_write_error:${error.code || 'unknown'}`); + } +} + +function mkdirControlled(dir) { + try { + fs.mkdirSync(dir, { recursive: true }); + } catch (error) { + fail(74, `filesystem_mkdir_error:${error.code || 'unknown'}`); + } +} + +function printBanner() { + printBrik64Logo(); + process.stdout.write(`BRIK64 CLI ${version}\n`); + process.stdout.write('status=public_beta\n'); +} + +function help() { + printBanner(); + process.stdout.write('\ncommands:\n'); + process.stdout.write(' init create .brik metadata only\n'); + process.stdout.write(' doctor [--json] inspect workspace health\n'); + process.stdout.write(' engine status inspect packaged local runtime bundle\n'); + process.stdout.write(' account status show local or managed account routing\n'); + process.stdout.write(' login connect managed platform session from token env\n'); + process.stdout.write(' --token-env \n'); + process.stdout.write(' logout remove managed platform session\n'); + process.stdout.write(' migrate convert supported legacy PCD syntax\n'); + process.stdout.write(' --out | --in-place\n'); + process.stdout.write(' certify write local candidate certificate\n'); + process.stdout.write(' emit emit only when local certificate exists\n'); + process.stdout.write(' --target --out --tests\n'); + process.stdout.write(' polymerize combine PCDs into a deterministic polymer\n'); + process.stdout.write(' --local | --cloud --out --json\n'); + process.stdout.write(' verify verify local certificate/workspace coherence\n'); + process.stdout.write(' --local | --cloud | --json\n'); + process.stdout.write(' --version print version\n'); + process.stdout.write('\nreferences:\n'); + process.stdout.write(' docs https://docs.brik64.com/cli/install\n'); + process.stdout.write(' skill https://github.com/brik64/brik64-tools-skills\n'); + process.stdout.write(' pcd standard https://github.com/brik64/pcd-standard\n'); +} + +function readFileRequired(file) { + if (!file) { + fail(64, 'missing_file_argument'); + } + const resolved = workspacePath(file); + if (path.extname(resolved) !== '.pcd') { + fail(64, 'unsupported_file_extension'); + } + if (!fs.existsSync(resolved)) { + fail(66, `file_not_found:${file}`); + } + return fs.readFileSync(resolved, 'utf8'); +} + +function readJsonRequired(file, parseError, missingError) { + if (!fs.existsSync(file)) { + fail(66, missingError); + } + try { + return JSON.parse(fs.readFileSync(file, 'utf8')); + } catch (_) { + fail(65, parseError); + } +} + +function validateManifest() { + const manifestPath = path.resolve('.brik', 'manifest.json'); + const manifest = readJsonRequired(manifestPath, 'manifest_parse_error', 'manifest_missing:.brik/manifest.json'); + const schema = manifest.schema || manifest.schemaVersion; + if (schema !== 'brik64.cli_project_manifest.v1') { + fail(65, 'manifest_schema_unsupported'); + } + if (!manifest.cliVersion || typeof manifest.cliVersion !== 'string') { + fail(65, 'manifest_cli_version_missing'); + } + const boundary = manifest.claimBoundary; + if (!boundary || typeof boundary !== 'object') { + fail(65, 'manifest_claim_boundary_missing'); + } + const releaseAllowed = boundary.releaseAllowed ?? boundary.releaseAuthorized; + if (releaseAllowed !== false) { + fail(65, 'manifest_release_policy_invalid'); + } + return manifest; +} + +function stripPcdComments(source) { + return source + .split('\n') + .map((line) => line.replace(/\/\/.*$/, '')) + .join('\n'); +} + +function findMatchingBrace(source, openIndex) { + let depth = 0; + for (let index = openIndex; index < source.length; index += 1) { + const char = source[index]; + if (char === '{') depth += 1; + if (char === '}') { + depth -= 1; + if (depth === 0) return index; + } + } + return -1; +} + +function tokenizeExpression(source) { + const tokens = []; + let index = 0; + while (index < source.length) { + const char = source[index]; + if (/\s/.test(char)) { + index += 1; + continue; + } + const two = source.slice(index, index + 2); + if (['>=', '<=', '==', '!=', '&&', '||'].includes(two)) { + tokens.push({ type: 'op', value: two }); + index += 2; + continue; + } + if ('()+-*/%<>'.includes(char)) { + tokens.push({ type: char === '(' || char === ')' ? 'paren' : 'op', value: char }); + index += 1; + continue; + } + const number = source.slice(index).match(/^\d+/); + if (number) { + tokens.push({ type: 'number', value: Number(number[0]) }); + index += number[0].length; + continue; + } + const ident = source.slice(index).match(/^[A-Za-z_][A-Za-z0-9_]*/); + if (ident) { + tokens.push({ type: 'identifier', value: ident[0] }); + index += ident[0].length; + continue; + } + fail(65, 'pcd_parse_error:unsupported_expression_token'); + } + return tokens; +} + +function parseExpression(source, params) { + const tokens = tokenizeExpression(source); + let index = 0; + const precedence = { + '||': 1, + '&&': 2, + '==': 3, + '!=': 3, + '>': 4, + '<': 4, + '>=': 4, + '<=': 4, + '+': 5, + '-': 5, + '*': 6, + '/': 6, + '%': 6, + }; + + function peek() { + return tokens[index]; + } + + function consume(value) { + const token = tokens[index]; + if (!token || (value && token.value !== value)) { + fail(65, 'pcd_parse_error:malformed_expression'); + } + index += 1; + return token; + } + + function parsePrimary() { + const token = peek(); + if (!token) fail(65, 'pcd_parse_error:malformed_expression'); + if (token.type === 'number') { + consume(); + return { type: 'NumberLiteral', value: token.value }; + } + if (token.type === 'identifier') { + consume(); + if (!params.includes(token.value)) { + fail(65, `pcd_parse_error:unknown_identifier:${token.value}`); + } + return { type: 'Identifier', name: token.value }; + } + if (token.value === '-') { + consume('-'); + return { type: 'UnaryExpression', operator: '-', argument: parsePrimary() }; + } + if (token.value === '(') { + consume('('); + const expression = parseBinary(1); + consume(')'); + return expression; + } + fail(65, 'pcd_parse_error:malformed_expression'); + } + + function parseBinary(minPrecedence) { + let left = parsePrimary(); + while (peek() && peek().type === 'op' && precedence[peek().value] >= minPrecedence) { + const operator = consume().value; + const operatorPrecedence = precedence[operator]; + const right = parseBinary(operatorPrecedence + 1); + left = { type: 'BinaryExpression', operator, left, right }; + } + return left; + } + + const expression = parseBinary(1); + if (index !== tokens.length) { + fail(65, 'pcd_parse_error:malformed_expression'); + } + return expression; +} + +function parseStatements(body, params) { + const statements = []; + let index = 0; + + function skipWhitespace() { + while (index < body.length && /\s/.test(body[index])) index += 1; + } + + function readBalanced(openChar, closeChar) { + if (body[index] !== openChar) fail(65, 'pcd_parse_error:malformed_block'); + let depth = 0; + const start = index; + for (; index < body.length; index += 1) { + if (body[index] === openChar) depth += 1; + if (body[index] === closeChar) { + depth -= 1; + if (depth === 0) { + const content = body.slice(start + 1, index); + index += 1; + return content; + } + } + } + fail(65, 'pcd_parse_error:unclosed_block'); + } + + while (index < body.length) { + skipWhitespace(); + if (index >= body.length) break; + if (body.slice(index).startsWith('return')) { + index += 'return'.length; + const semi = body.indexOf(';', index); + if (semi === -1) fail(65, 'pcd_parse_error:missing_return_semicolon'); + const value = body.slice(index, semi).trim(); + if (!value) fail(65, 'pcd_parse_error:missing_return_value'); + statements.push({ type: 'ReturnStatement', argument: parseExpression(value, params) }); + index = semi + 1; + continue; + } + if (body.slice(index).startsWith('if')) { + index += 'if'.length; + skipWhitespace(); + const condition = readBalanced('(', ')').trim(); + skipWhitespace(); + const consequentBody = readBalanced('{', '}'); + skipWhitespace(); + let alternate = []; + if (body.slice(index).startsWith('else')) { + index += 'else'.length; + skipWhitespace(); + alternate = parseStatements(readBalanced('{', '}'), params); + } + statements.push({ + type: 'IfStatement', + condition: parseExpression(condition, params), + consequent: parseStatements(consequentBody, params), + alternate, + }); + continue; + } + fail(65, 'pcd_parse_error:unsupported_statement'); + } + return statements; +} + +function collectReturns(statements, values = []) { + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + values.push(statement.argument); + } + if (statement.type === 'IfStatement') { + collectReturns(statement.consequent, values); + collectReturns(statement.alternate, values); + } + } + return values; +} + +function countBranches(statements) { + return statements.reduce((count, statement) => { + if (statement.type !== 'IfStatement') return count; + return count + 1 + countBranches(statement.consequent) + countBranches(statement.alternate); + }, 0); +} + +function parsePcd(source) { + if (source.length === 0 || source.trim().length === 0) { + fail(65, 'pcd_empty'); + } + if (source.includes('\u0000')) { + fail(65, 'pcd_binary_input'); + } + if (Buffer.byteLength(source, 'utf8') > 1024 * 1024) { + fail(65, 'pcd_too_large'); + } + const stripped = stripPcdComments(source); + const pcMatch = stripped.match(/\bPC\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{([\s\S]*)\}\s*$/m); + if (!pcMatch) { + const legacyHint = /\bpc\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.test(stripped) + || /\bcircuit\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.test(stripped); + if (legacyHint) { + fail(65, 'pcd_parse_error:missing_pc_block; legacy syntax detected; run `brik64 migrate `'); + } + fail(65, 'pcd_parse_error:missing_pc_block'); + } + const pcStart = stripped.search(/\bPC\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m); + const pcOpen = stripped.indexOf('{', pcStart); + const pcClose = findMatchingBrace(stripped, pcOpen); + if (pcClose === -1 || stripped.slice(pcClose + 1).trim().length > 0) { + fail(65, 'pcd_parse_error:malformed_pc_block'); + } + const pcName = pcMatch[1]; + const pcBody = stripped.slice(pcOpen + 1, pcClose); + const fnMatch = pcBody.match(/\bfn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{/m); + if (!fnMatch) { + fail(65, 'pcd_parse_error:missing_fn_block'); + } + const fnStart = fnMatch.index; + const fnOpen = pcBody.indexOf('{', fnStart); + const fnClose = findMatchingBrace(pcBody, fnOpen); + if (fnClose === -1 || pcBody.slice(fnClose + 1).trim().length > 0) { + fail(65, 'pcd_parse_error:malformed_fn_block'); + } + const [, fnName, paramsRaw] = fnMatch; + const fnBody = pcBody.slice(fnOpen + 1, fnClose); + const params = paramsRaw + .split(',') + .map((param) => param.trim()) + .filter(Boolean); + if (params.length > 1) { + fail(65, 'pcd_parse_error:too_many_params_beta8'); + } + if (params.some((param) => !/^[A-Za-z_][A-Za-z0-9_]*$/.test(param))) { + fail(65, 'pcd_parse_error:invalid_param'); + } + const body = parseStatements(fnBody, params); + const returns = collectReturns(body); + if (returns.length === 0) { + fail(65, 'pcd_parse_error:missing_return'); + } + return { + schemaVersion: 'brik64.cli_ast.v1', + pcName, + fnName, + params, + body, + returnValues: returns.map((expression) => (expression.type === 'NumberLiteral' ? expression.value : null)), + branchCount: countBranches(body), + expressionDialect: 'brik64.cli_expr.v1', + }; +} + +function init() { + const brikDir = path.resolve('.brik'); + fs.mkdirSync(brikDir, { recursive: true }); + const manifestPath = path.join(brikDir, 'manifest.json'); + if (!fs.existsSync(manifestPath)) { + fs.writeFileSync(manifestPath, JSON.stringify({ + schemaVersion: 'brik64.cli_project_manifest.v1', + schema: 'brik64.cli_project_manifest.v1', + cliVersion: version, + lane: 'cli_0_1_beta', + generationClaim: 'assisted_generation_non_claim', + createdBy: 'brik64-cli-bootstrap', + preferred_engine: 'auto', + polymer_strategy: 'local_ast', + managed_platform: { + enabled: false, + routing: 'local_default' + }, + engineTierPolicy: { + publicOfflineRuntime: 'local_runtime', + registeredManagedRuntime: 'managed_platform', + internalArtifactFactory: 'private_factory', + l6DistributionAllowed: false, + l5EmbeddedFreeRuntimeAllowed: false + }, + claimBoundary: { + releaseAuthorized: false, + publicBetaAllowed: false, + releaseAllowed: false, + generatedAgentsFile: false + } + }, null, 2) + '\n'); + } + process.stdout.write(`created=${path.relative(process.cwd(), manifestPath)}\n`); +} + +function pcdInventory() { + const pcdRoot = path.resolve('pcd'); + if (!fs.existsSync(pcdRoot)) { + return []; + } + return fs.readdirSync(pcdRoot) + .filter((name) => name.endsWith('.pcd')) + .sort() + .map((name) => { + const file = path.join(pcdRoot, name); + const source = fs.readFileSync(file, 'utf8'); + return { + file: path.relative(process.cwd(), file), + semantic_pcd_sha256: sha256(source), + bytes: Buffer.byteLength(source, 'utf8') + }; + }); +} + +function doctor() { + const args = parseArgs(process.argv.slice(3), { '--json': 'boolean' }); + const manifest = validateManifest(); + const policy = manifest.engineTierPolicy || {}; + if (manifest.cliVersion !== version) { + fail(65, 'manifest_cli_version_mismatch'); + } + if (policy.publicOfflineRuntime !== 'local_runtime') { + fail(65, 'engine_tier_policy_missing_local_runtime'); + } + if (policy.registeredManagedRuntime !== 'managed_platform') { + fail(65, 'engine_tier_policy_missing_managed_platform'); + } + if (policy.internalArtifactFactory !== 'private_factory') { + fail(65, 'engine_tier_policy_missing_private_factory'); + } + if (policy.l6DistributionAllowed !== false) { + fail(65, 'engine_tier_policy_l6_distribution_open'); + } + if (policy.l5EmbeddedFreeRuntimeAllowed !== false) { + fail(65, 'engine_tier_policy_l5_free_embedding_open'); + } + const pcds = pcdInventory(); + if (pcds.length === 0) { + fail(65, 'pcd_inventory_empty'); + } + const report = { + schemaVersion: 'brik64.cli_doctor_report.v1', + cliVersion: version, + status: 'PASS', + releaseEligible: false, + localRuntime: 'available', + managedRuntime: hasManagedSession() ? 'authenticated' : 'not_authenticated', + internalArtifactFactory: 'private', + pcdCount: pcds.length, + pcdInventorySha256: sha256(JSON.stringify(pcds)), + releaseScope: 'local_candidate_only' + }; + if (args['--json']) { + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); + return; + } + process.stdout.write(`BRIK64 workspace doctor\n`); + process.stdout.write(`status: ${report.status}\n`); + process.stdout.write(`cli: ${report.cliVersion}\n`); + process.stdout.write(`routing: local default\n`); + process.stdout.write(`pcd files: ${report.pcdCount}\n`); + process.stdout.write(`release eligible: no\n`); + process.stdout.write(`release scope: local candidate only\n`); +} + +function repoRoot() { + return path.resolve(__dirname, '..'); +} + +function engineStatus() { + const bundlePath = path.join(repoRoot(), 'engines', 'l4plus-n5', 'runtime-bundle.manifest.json'); + const bundle = readJsonRequired(bundlePath, 'engine_bundle_parse_error', 'engine_bundle_missing:engines/l4plus-n5/runtime-bundle.manifest.json'); + if (!['brik64.cli_l4plus_n5_portable_runtime_bundle.v1', 'brik64.cli_portable_runtime_bundle.v1'].includes(bundle.schemaVersion)) { + fail(65, 'engine_bundle_schema_unsupported'); + } + if (bundle.runtimeMode !== 'portable_bir_bundle') { + fail(65, 'engine_bundle_runtime_mode_unsupported'); + } + if (bundle.nativeExecutableIncluded !== false) { + fail(65, 'engine_bundle_native_claim_unverified'); + } + if (!Array.isArray(bundle.artifacts) || bundle.artifacts.length === 0) { + fail(65, 'engine_bundle_artifacts_missing'); + } + for (const artifact of bundle.artifacts) { + const artifactPath = path.join(repoRoot(), artifact.path); + if (!fs.existsSync(artifactPath)) { + fail(66, `engine_bundle_artifact_missing:${artifact.path}`); + } + const actual = sha256(fs.readFileSync(artifactPath)); + if (actual !== artifact.sha256) { + fail(68, `engine_bundle_artifact_hash_mismatch:${artifact.path}`); + } + } + const report = { + schemaVersion: 'brik64.cli_engine_status_report.v1', + cliVersion: version, + status: 'PASS', + localRuntime: 'available', + serial: bundle.serial, + runtimeMode: bundle.runtimeMode, + nativeExecutableIncluded: bundle.nativeExecutableIncluded, + artifactCount: bundle.artifacts.length, + releaseEligible: false, + claimBoundary: bundle.claimBoundary, + limitations: bundle.limitations + }; + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); +} + +function certPathFor(file) { + return `${workspacePath(file)}.cert.json`; +} + +function sessionDir() { + const base = process.env.BRIK64_CONFIG_HOME + || path.join(process.env.XDG_CONFIG_HOME || path.join(process.env.HOME || process.cwd(), '.config'), 'brik64'); + return base; +} + +function sessionPath() { + return path.join(sessionDir(), 'session.json'); +} + +function readSession() { + const file = sessionPath(); + if (!fs.existsSync(file)) return null; + try { + const session = JSON.parse(fs.readFileSync(file, 'utf8')); + if (session.schemaVersion !== SESSION_SCHEMA) return null; + return session; + } catch (_) { + return null; + } +} + +function hasManagedSession() { + const session = readSession(); + return Boolean(session && session.tokenSha256 && session.status === 'active'); +} + +function accountStatus(args = []) { + const parsed = parseArgs(args, { '--json': 'boolean' }); + const managed = hasManagedSession(); + const report = { + schemaVersion: 'brik64.cli_account_status.v1', + cliVersion: version, + status: 'PASS', + accountState: managed ? 'authenticated' : 'anonymous', + tier: managed ? 'managed' : 'free', + defaultRouting: managed ? 'managed_when_requested' : 'local_default', + localRuntimeAvailable: true, + managedRuntimeAvailable: managed, + secretsPrinted: false + }; + if (parsed['--json']) { + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); + return; + } + process.stdout.write(`BRIK64 account\n`); + process.stdout.write(`state: ${report.accountState}\n`); + process.stdout.write(`tier: ${report.tier}\n`); + process.stdout.write(`routing: ${report.defaultRouting}\n`); +} + +function login(args = []) { + const parsed = parseArgs(args, { '--token-env': 'value' }); + const envName = parsed['--token-env']; + if (!envName) { + fail(64, 'login_requires_token_env_for_beta8'); + } + const token = process.env[envName]; + if (!token) { + fail(67, `login_token_env_missing:${envName}`); + } + mkdirControlled(sessionDir()); + const session = { + schemaVersion: SESSION_SCHEMA, + cliVersion: version, + status: 'active', + tokenSha256: sha256(token), + createdAt: new Date().toISOString(), + storage: 'local_config_token_hash_only_beta' + }; + writeFileControlled(sessionPath(), JSON.stringify(session, null, 2) + '\n'); + try { + fs.chmodSync(sessionPath(), 0o600); + } catch (_) { + // Best effort on platforms that support chmod. + } + process.stdout.write('login=managed_session_recorded\n'); + process.stdout.write('secret_printed=false\n'); +} + +function logout() { + const file = sessionPath(); + if (fs.existsSync(file)) { + fs.rmSync(file, { force: true }); + } + process.stdout.write('logout=local_default\n'); +} + +function requireLocalOrEntitled(parsed) { + if (parsed['--cloud'] && !hasManagedSession()) { + fail(67, 'managed_entitlement_required; run `brik64 login --token-env `'); + } +} + +function parseEmitOptions(args) { + const options = { target: null, outDir: null, tests: false }; + for (let index = 0; index < args.length; index += 1) { + const arg = args[index]; + if (arg === '--target') { + options.target = args[index + 1]; + if (!options.target) fail(64, 'missing_target'); + index += 1; + } else if (arg === '--out') { + options.outDir = args[index + 1]; + if (!options.outDir) fail(64, 'missing_out_dir'); + index += 1; + } else if (arg === '--tests') { + options.tests = true; + } else { + fail(64, `unknown_emit_option:${arg}`); + } + } + return options; +} + +function encodedAst(ast) { + return JSON.stringify(ast); +} + +function renderExpression(expression, target) { + if (expression.type === 'NumberLiteral') return String(expression.value); + if (expression.type === 'Identifier') return expression.name; + if (expression.type === 'UnaryExpression') return `(-${renderExpression(expression.argument, target)})`; + if (expression.type === 'BinaryExpression') { + const left = renderExpression(expression.left, target); + const right = renderExpression(expression.right, target); + let operator = expression.operator; + if (target === 'ts' && operator === '==') operator = '==='; + if (target === 'ts' && operator === '!=') operator = '!=='; + if (target === 'python' && operator === '&&') operator = 'and'; + if (target === 'python' && operator === '||') operator = 'or'; + return `(${left} ${operator} ${right})`; + } + fail(70, 'internal_codegen_error:unknown_expression'); +} + +function renderStatements(statements, target, indentLevel) { + const unit = target === 'python' ? ' ' : ' '; + const indent = unit.repeat(indentLevel); + const lines = []; + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + lines.push(`${indent}return ${renderExpression(statement.argument, target)}${target === 'python' ? '' : ';'}`); + continue; + } + if (statement.type === 'IfStatement') { + const condition = renderExpression(statement.condition, target); + if (target === 'python') { + lines.push(`${indent}if ${condition}:`); + lines.push(...renderStatements(statement.consequent, target, indentLevel + 1)); + if (statement.alternate.length > 0) { + lines.push(`${indent}else:`); + lines.push(...renderStatements(statement.alternate, target, indentLevel + 1)); + } + } else { + lines.push(`${indent}if ${condition} {`); + lines.push(...renderStatements(statement.consequent, target, indentLevel + 1)); + if (statement.alternate.length > 0) { + lines.push(`${indent}} else {`); + lines.push(...renderStatements(statement.alternate, target, indentLevel + 1)); + } + lines.push(`${indent}}`); + } + continue; + } + fail(70, 'internal_codegen_error:unknown_statement'); + } + return lines; +} + +function evaluateExpression(expression, env) { + if (expression.type === 'NumberLiteral') return expression.value; + if (expression.type === 'Identifier') return env[expression.name] ?? 0; + if (expression.type === 'UnaryExpression') return -evaluateExpression(expression.argument, env); + if (expression.type === 'BinaryExpression') { + const left = evaluateExpression(expression.left, env); + if (expression.operator === '&&') return Boolean(left) && Boolean(evaluateExpression(expression.right, env)); + if (expression.operator === '||') return Boolean(left) || Boolean(evaluateExpression(expression.right, env)); + const right = evaluateExpression(expression.right, env); + if (expression.operator === '+') return left + right; + if (expression.operator === '-') return left - right; + if (expression.operator === '*') return left * right; + if (expression.operator === '/') return Math.trunc(left / right); + if (expression.operator === '%') return left % right; + if (expression.operator === '==') return left === right; + if (expression.operator === '!=') return left !== right; + if (expression.operator === '>') return left > right; + if (expression.operator === '<') return left < right; + if (expression.operator === '>=') return left >= right; + if (expression.operator === '<=') return left <= right; + } + fail(70, 'internal_eval_error:unknown_expression'); +} + +function evaluateStatements(statements, env) { + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + return evaluateExpression(statement.argument, env); + } + if (statement.type === 'IfStatement') { + if (evaluateExpression(statement.condition, env)) { + const consequent = evaluateStatements(statement.consequent, env); + if (consequent !== undefined) return consequent; + } else { + const alternate = evaluateStatements(statement.alternate, env); + if (alternate !== undefined) return alternate; + } + } + } + return undefined; +} + +function collectConditionValues(expression, values = new Set([0, 1, 2, 10])) { + if (expression.type === 'NumberLiteral') { + values.add(expression.value); + values.add(expression.value + 1); + values.add(expression.value - 1); + } + if (expression.type === 'UnaryExpression') collectConditionValues(expression.argument, values); + if (expression.type === 'BinaryExpression') { + collectConditionValues(expression.left, values); + collectConditionValues(expression.right, values); + } + return values; +} + +function collectStatementValues(statements, values = new Set([0, 1, 2, 10])) { + for (const statement of statements) { + if (statement.type === 'IfStatement') { + collectConditionValues(statement.condition, values); + collectStatementValues(statement.consequent, values); + collectStatementValues(statement.alternate, values); + } + } + return values; +} + +function generatedCases(ast) { + const param = ast.params[0] || 'input'; + const inputs = [...collectStatementValues(ast.body)] + .filter((value) => Number.isInteger(value) && Math.abs(value) < 100000) + .slice(0, 12); + return inputs + .map((input) => ({ input, expected: evaluateStatements(ast.body, { [param]: input }) })) + .filter((testCase) => testCase.expected !== undefined) + .slice(0, 8); +} + +function ensureExecutable(ast) { + const cases = generatedCases(ast); + if (cases.length === 0) { + fail(65, 'pcd_parse_error:no_executable_return_path'); + } + return cases; +} + +function targetSpec(target, ast) { + const astJson = encodedAst(ast); + const cases = ensureExecutable(ast); + const param = ast.params[0] || 'input'; + const tsStatements = renderStatements(ast.body, 'ts', 1); + const rustStatements = renderStatements(ast.body, 'rust', 1); + const pythonStatements = renderStatements(ast.body, 'python', 1); + const specs = { + ts: { + program: 'program.mjs', + test: 'program.test.mjs', + code: (hash) => [ + '// BRIK64 beta8 functional emission candidate', + '// claim: local candidate evidence only', + `export const pcdSha256 = "${hash}";`, + `export const pcdAst = ${astJson};`, + `export function run(${param} = 0) {`, + ...tsStatements, + ' throw new Error("pcd execution reached non-returning path");', + '}', + '', + ].join('\n'), + testCode: (hash) => [ + 'import { pcdSha256, run } from "./program.mjs";', + '', + 'if (pcdSha256 !== "' + hash + '") throw new Error("pcd hash mismatch");', + `const cases = ${JSON.stringify(cases)};`, + 'for (const testCase of cases) {', + ' const actual = run(testCase.input);', + ' if (actual !== testCase.expected) {', + ' throw new Error(`case ${testCase.input} expected ${testCase.expected} got ${actual}`);', + ' }', + '}', + 'console.log("brik64 generated ts test: PASS");', + '', + ].join('\n'), + }, + rust: { + program: 'program.rs', + test: 'program_test.rs', + code: (hash) => [ + '// BRIK64 beta8 functional emission candidate', + '// claim: local candidate evidence only', + `pub const PCD_SHA256: &str = "${hash}";`, + `pub const PCD_AST_JSON: &str = r#"${astJson}"#;`, + `pub fn run(${param}: i64) -> i64 {`, + ...rustStatements.map((line) => line.replace(/^ /, ' ')), + ' panic!("pcd execution reached non-returning path");', + '}', + '', + ].join('\n'), + testCode: (hash) => [ + `const PCD_SHA256: &str = "${hash}";`, + `const PCD_AST_JSON: &str = r#"${astJson}"#;`, + `fn run(${param}: i64) -> i64 {`, + ...rustStatements.map((line) => line.replace(/^ /, ' ')), + ' panic!("pcd execution reached non-returning path");', + '}', + '', + 'fn main() {', + ` assert_eq!(PCD_SHA256, "${hash}");`, + ' assert!(PCD_AST_JSON.contains("body"));', + ...cases.map((testCase) => ` assert_eq!(run(${testCase.input}), ${testCase.expected});`), + ' println!("brik64 generated rust test: PASS");', + '}', + '', + ].join('\n'), + }, + python: { + program: 'program.py', + test: 'test_program.py', + code: (hash) => [ + '# BRIK64 beta8 functional emission candidate', + '# claim: local candidate evidence only', + `PCD_SHA256 = "${hash}"`, + `PCD_AST_JSON = ${JSON.stringify(JSON.stringify(ast))}`, + '', + `def run(${param}=0):`, + ...pythonStatements, + ' raise RuntimeError("pcd execution reached non-returning path")', + '', + ].join('\n'), + testCode: (hash) => [ + 'from program import PCD_SHA256, run', + '', + `assert PCD_SHA256 == "${hash}"`, + `cases = ${JSON.stringify(cases)}`, + 'for case in cases:', + ' actual = run(case["input"])', + ' assert actual == case["expected"], f"case {case[\'input\']} expected {case[\'expected\']} got {actual}"', + 'print("brik64 generated python test: PASS")', + '', + ].join('\n'), + }, + }; + return specs[target] || null; +} + +function certify(file) { + validateManifest(); + const source = readFileRequired(file); + const ast = parsePcd(source); + const cert = { + schemaVersion: 'brik64.cli_local_candidate_certificate.v1', + cliVersion: version, + pcd: file, + semantic_pcd_sha256: sha256(source), + ast_sha256: sha256(JSON.stringify(ast)), + ast, + offlineEngine: 'local-parser-emitter', + certifiesFormalCorrectness: false, + certifiesTests: false, + claimBoundary: { + localCandidateOnly: true, + publicBetaAllowed: false, + releaseAllowed: false + } + }; + const certPath = certPathFor(file); + writeFileControlled(certPath, JSON.stringify(cert, null, 2) + '\n'); + process.stdout.write(`certificate=${path.relative(process.cwd(), certPath)}\n`); +} + +function certificateFor(file, source, ast) { + const certPath = certPathFor(file); + if (!fs.existsSync(certPath)) { + fail(67, `certificate_required:${certPath}`); + } + const cert = readJsonRequired(certPath, 'certificate_parse_error', `certificate_required:${certPath}`); + if (cert.semantic_pcd_sha256 !== sha256(source)) { + fail(68, 'certificate_hash_mismatch'); + } + if (cert.ast_sha256 !== sha256(JSON.stringify(ast))) { + fail(68, 'certificate_ast_mismatch'); + } + return cert; +} + +function emit(file, args = []) { + validateManifest(); + const source = readFileRequired(file); + const ast = parsePcd(source); + const cert = certificateFor(file, source, ast); + const options = parseEmitOptions(args); + if (options.target || options.outDir || options.tests) { + const spec = targetSpec(options.target, ast); + if (!spec) { + fail(69, 'unsupported_target'); + } + if (!options.outDir) { + fail(64, 'missing_out_dir'); + } + const outDir = workspacePath(options.outDir); + mkdirControlled(outDir); + const programPath = path.join(outDir, spec.program); + const testPath = path.join(outDir, spec.test); + writeFileControlled(programPath, spec.code(cert.semantic_pcd_sha256)); + if (options.tests) { + writeFileControlled(testPath, spec.testCode(cert.semantic_pcd_sha256)); + } + process.stdout.write(`generated=${path.relative(process.cwd(), programPath)}\n`); + if (options.tests) process.stdout.write(`tests=${path.relative(process.cwd(), testPath)}\n`); + return; + } + process.stdout.write('// BRIK64 beta8 functional emission candidate\n'); + process.stdout.write('// claim: local candidate evidence only\n'); + process.stdout.write(`// pcd_sha256=${cert.semantic_pcd_sha256}\n`); + process.stdout.write(`// ast_sha256=${cert.ast_sha256}\n`); +} + +function verify(file, args = []) { + validateManifest(); + const parsed = parseArgs(args, { '--local': 'boolean', '--cloud': 'boolean', '--json': 'boolean' }); + if (parsed['--local'] && parsed['--cloud']) { + fail(64, 'verify_mode_conflict'); + } + requireLocalOrEntitled(parsed); + if (parsed['--cloud']) { + fail(69, 'managed_verify_endpoint_unavailable_beta8'); + } + const source = readFileRequired(file); + const ast = parsePcd(source); + const cert = certificateFor(file, source, ast); + const report = { + schemaVersion: 'brik64.cli_local_verify_report.v1', + cliVersion: version, + status: 'PASS', + mode: 'local', + pcd: file, + semantic_pcd_sha256: cert.semantic_pcd_sha256, + ast_sha256: cert.ast_sha256, + checks: { + parseable: true, + certificatePresent: true, + certificateHashMatches: true, + astHashMatches: true + }, + claimBoundary: { + localCandidateOnly: true, + universalCorrectnessClaimAllowed: false, + managedClaimIssued: false + } + }; + if (parsed['--json']) { + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); + return; + } + process.stdout.write(`verification=PASS\n`); + process.stdout.write(`mode=local\n`); + process.stdout.write(`pcd_sha256=${report.semantic_pcd_sha256}\n`); + process.stdout.write(`claim=local_candidate_only\n`); +} + +function polymerize(rawArgs = []) { + validateManifest(); + const parsed = parseArgs(rawArgs, { + '--local': 'boolean', + '--cloud': 'boolean', + '--out': 'value', + '--json': 'boolean' + }); + if (parsed['--local'] && parsed['--cloud']) { + fail(64, 'polymerize_mode_conflict'); + } + requireLocalOrEntitled(parsed); + if (parsed['--cloud']) { + fail(69, 'managed_polymerize_endpoint_unavailable_beta8'); + } + const files = parsed._; + if (files.length === 0) { + fail(64, 'missing_polymerize_inputs'); + } + const units = files.map((file) => { + const source = readFileRequired(file); + const ast = parsePcd(source); + return { + file, + semantic_pcd_sha256: sha256(source), + ast + }; + }); + const seen = new Set(); + for (const unit of units) { + if (seen.has(unit.ast.pcName)) { + fail(65, `polymerize_duplicate_pc:${unit.ast.pcName}`); + } + seen.add(unit.ast.pcName); + } + const outFile = parsed['--out'] || 'polymer.pcd'; + const outPath = workspacePath(outFile); + const firstReturn = units[0].ast.returnValues[0] ?? 0; + const sourceLines = units.map((unit) => `// source ${unit.file} ${unit.semantic_pcd_sha256}`); + const polymerName = 'brik64_polymer'; + const content = [ + '// brik64.pcd_file.v1', + '// generated_by: brik64-cli beta8 polymerize local', + '// claim_boundary: local_candidate_only', + ...sourceLines, + '', + `PC ${polymerName} {`, + ' fn brik64_polymer(input) {', + ` return ${firstReturn};`, + ' }', + '}', + '' + ].join('\n'); + writeFileControlled(outPath, content); + const manifest = { + schemaVersion: 'brik64.cli_polymer_manifest.v1', + cliVersion: version, + mode: 'local', + output: path.relative(process.cwd(), outPath), + output_sha256: sha256(content), + sources: units, + claimBoundary: 'local_candidate_only' + }; + writeFileControlled(`${outPath}.manifest.json`, JSON.stringify(manifest, null, 2) + '\n'); + if (parsed['--json']) { + process.stdout.write(`${JSON.stringify(manifest, null, 2)}\n`); + return; + } + process.stdout.write(`polymer=${path.relative(process.cwd(), outPath)}\n`); + process.stdout.write(`manifest=${path.relative(process.cwd(), `${outPath}.manifest.json`)}\n`); +} + +function migrate(file, args = []) { + const parsed = parseArgs(args, { '--out': 'value', '--in-place': 'boolean', '--json': 'boolean' }); + if (parsed['--out'] && parsed['--in-place']) { + fail(64, 'migrate_output_mode_conflict'); + } + const source = readFileRequired(file); + const oldHash = sha256(source); + let migrated = source; + let syntax = 'beta8'; + if (/\bcircuit\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.test(source)) { + migrated = migrated.replace(/\bcircuit\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/m, 'PC $1 {'); + syntax = 'legacy_circuit'; + } else if (/\bpc\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.test(source)) { + migrated = migrated.replace(/\bpc\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/m, 'PC $1 {'); + syntax = 'legacy_lowercase_pc'; + } + parsePcd(migrated); + const inputPath = workspacePath(file); + let outPath; + if (parsed['--in-place']) { + const backupPath = `${inputPath}.bak`; + if (!fs.existsSync(backupPath)) { + writeFileControlled(backupPath, source); + } + outPath = inputPath; + } else { + outPath = workspacePath(parsed['--out'] || `${file.replace(/\.pcd$/, '')}.beta8.pcd`); + if (fs.existsSync(outPath)) { + fail(73, `output_exists:${path.relative(process.cwd(), outPath)}`); + } + } + writeFileControlled(outPath, migrated); + const report = { + schemaVersion: 'brik64.cli_pcd_migration_report.v1', + cliVersion: version, + source: file, + output: path.relative(process.cwd(), outPath), + detectedSyntax: syntax, + old_sha256: oldHash, + new_sha256: sha256(migrated) + }; + if (parsed['--json']) { + process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); + return; + } + process.stdout.write(`migrated=${report.output}\n`); + process.stdout.write(`old_sha256=${report.old_sha256}\n`); + process.stdout.write(`new_sha256=${report.new_sha256}\n`); +} + +function main() { + const [cmd, file, ...args] = process.argv.slice(2); + if (!cmd || cmd === '--help' || cmd === 'help') return help(); + if (cmd === '--version' || cmd === 'version') { + printBanner(); + return; + } + if (cmd === 'init') return init(); + if (cmd === 'doctor') return doctor(); + if (cmd === 'engine' && file === 'status') return engineStatus(); + if (cmd === 'account' && file === 'status') return accountStatus(args); + if (cmd === 'login') return login([file, ...args].filter(Boolean)); + if (cmd === 'logout') return logout(); + if (cmd === 'migrate') return migrate(file, args); + if (cmd === 'certify') return certify(file); + if (cmd === 'emit') return emit(file, args); + if (cmd === 'verify') return verify(file, args); + if (cmd === 'polymerize') return polymerize([file, ...args].filter(Boolean)); + fail(2, `unknown_command:${cmd}`); +} + +main(); diff --git a/evidence/release-manifest-validate/report.json b/evidence/release-manifest-validate/report.json index df6fd5fc..55ff50a7 100644 --- a/evidence/release-manifest-validate/report.json +++ b/evidence/release-manifest-validate/report.json @@ -1,47 +1,54 @@ { "schemaVersion": "brik64.release_manifest_validation_report.v1", "manifestPath": "release/manifest.json", - "version": "0.1.0-beta.7", - "state": "public", - "manifestDigest": "7f786abdfa7e098778d1a141ea393da386e22144b9d213836e1bd8747acbbcb8", + "version": "0.1.0-beta.8", + "state": "draft", + "manifestDigest": "959a0c50560613529b80d12534d2c8ef1f5ce47a52449cc906f0c687edf9a585", "decision": "PASS_RELEASE_MANIFEST_VALIDATE", - "releaseEligible": true, + "releaseEligible": false, "artifacts": { "manifest": { "path": "release/manifest.json", - "sha256": "7f786abdfa7e098778d1a141ea393da386e22144b9d213836e1bd8747acbbcb8", - "bytes": 3584 + "sha256": "959a0c50560613529b80d12534d2c8ef1f5ce47a52449cc906f0c687edf9a585", + "bytes": 3829 }, "packageJson": { "path": "package.json", - "version": "0.1.0-beta.7" + "version": "0.1.0-beta.8" }, "evidence": [ { - "id": "featureParity", - "path": "evidence/beta7-feature-parity/report.json", - "expectedDecision": "PASS_BETA7_FEATURE_PARITY_GATE", - "actualDecision": "PASS_BETA7_FEATURE_PARITY_GATE", - "sha256": "ebd385cd2e0eebe4054fc49a245c8fe75f6e990e3d3175d848056b8e8c6ac8bc" + "id": "compilerFunctionality", + "path": "evidence/beta8-compiler-functionality/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "actualDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "sha256": "0692904fc600bacf24c79c8400fd9cce55e12a61e25cd350f5b3e7913fee14e3" + }, + { + "id": "adversarial", + "path": "evidence/beta8-adversarial/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", + "actualDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", + "sha256": "7e26abb3953de914d5b1746c0a506063d10182416e91a582a0438390a9fef199" }, { "id": "localPackage", - "path": "evidence/beta7-package/package.manifest.json", - "expectedDecision": "PASS_BETA7_PACKAGE_BUILT", - "actualDecision": "PASS_BETA7_PACKAGE_BUILT", - "sha256": "85c751817ddedca8a6934f3a92912adda4c950f05e96f9d1898a6eedd4fa6af4" + "path": "evidence/beta8-package/package.manifest.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", + "actualDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", + "sha256": "b152172c22de826ae6d92d8c9231d670c6c1722b11fd5237e0196c89625ed493" }, { "id": "localPackageSmoke", - "path": "evidence/beta7-package-smoke/report.json", - "expectedDecision": "PASS_BETA7_LOCAL_PACKAGE_SMOKE", - "actualDecision": "PASS_BETA7_LOCAL_PACKAGE_SMOKE", - "sha256": "d1b6f33235ddd99c594c2b6107e0e1dd99be862d0c7b95b5ea93c0bea0e20050" + "path": "evidence/beta8-package-smoke/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", + "actualDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", + "sha256": "ffdbabc6f70bbbce9a7027ccfc4cf3b94a271b30532189d3e312d28798707f2f" } ] }, "failures": [], "warnings": [ - "worktree_dirty_allowed:9" + "worktree_dirty_allowed:38" ] } diff --git a/evidence/release-train-dry-run/report.json b/evidence/release-train-dry-run/report.json index e6255fd0..888a6861 100644 --- a/evidence/release-train-dry-run/report.json +++ b/evidence/release-train-dry-run/report.json @@ -1,141 +1,130 @@ { "schemaVersion": "brik64.release_train_dry_run_report.v1", - "releaseId": "brik64-0.1.0-beta.7", - "version": "0.1.0-beta.7", + "releaseId": "brik64-0.1.0-beta.8", + "version": "0.1.0-beta.8", "channel": "beta", - "state": "public", - "manifestDigest": "7f786abdfa7e098778d1a141ea393da386e22144b9d213836e1bd8747acbbcb8", + "state": "draft", + "manifestDigest": "959a0c50560613529b80d12534d2c8ef1f5ce47a52449cc906f0c687edf9a585", "decision": "PASS_RELEASE_TRAIN_DRY_RUN", "publicationAllowed": false, "boundary": "Dry-run only. This workflow validates manifest, tests and evidence but never publishes public artifacts.", "initialDirtyFiles": [ + ".brik/manifest.json", + "CHANGELOG.md", "README.md", - "evidence/beta7-package-smoke/report.json", - "evidence/beta7-package/SHA256SUMS", - "evidence/beta7-package/brik64-cli-0.1.0-beta.7.tgz", - "evidence/beta7-package/package.manifest.json", - "evidence/release-train-sync/report.json", - "evidence/release-train-sync/sync-payload.json", - "release/manifest.json" + "evidence/beta8-adversarial/report.json", + "evidence/beta8-compiler-functionality/report.json", + "evidence/beta8-package-smoke/report.json", + "evidence/beta8-package/SHA256SUMS", + "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", + "evidence/beta8-package/package.manifest.json", + "evidence/beta8-package/stage-checksums.tsv", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd", + "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js", + "package.json", + "release/manifest.json", + "scripts/beta8-adversarial-gate.sh", + "scripts/beta8-compiler-functionality-gate.sh", + "scripts/beta8-package-smoke.sh", + "scripts/build-beta8-package.sh", + "scripts/release-train-dry-run.js", + "src/brik.js", + "tests/smoke.sh" ], "commands": [ { "name": "manifest_validate", "command": "node scripts/release-manifest-validate.js --allow-dirty", "rc": 0, - "elapsedMs": 115, - "stdout": "decision=PASS_RELEASE_MANIFEST_VALIDATE\nversion=0.1.0-beta.7\nwarnings=worktree_dirty_allowed:8\n", + "elapsedMs": 151, + "stdout": "decision=PASS_RELEASE_MANIFEST_VALIDATE\nversion=0.1.0-beta.8\nwarnings=worktree_dirty_allowed:38\n", "stderr": "" }, { "name": "smoke_tests", - "command": "bash -lc BRIK64_RELEASE_GATES=1 bash -x tests/smoke.sh", + "command": "bash -lc bash -x tests/smoke.sh", "rc": 0, - "elapsedMs": 7421, + "elapsedMs": 4787, "stdout": "created=.brik/manifest.json\ncertificate=program.pcd.cert.json\ncertificate=polymer.pcd.cert.json\ncertificate=stale.pcd.cert.json\ncertificate=legacy.beta7.pcd.cert.json\ncertificate=variant.pcd.cert.json\nbrik64-cli bootstrap smoke: PASS\n", - "stderr": "+ set -euo pipefail\n+++ dirname tests/smoke.sh\n++ cd tests/..\n++ pwd\n+ ROOT_DIR=/Users/carlosjperez/Documents/GitHub/brik64-cli\n+ BRIK=/Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js\n++ node -e 'const fs=require(\"fs\"); process.stdout.write(JSON.parse(fs.readFileSync(\"package.json\",\"utf8\")).version)'\n+ PACKAGE_VERSION=0.1.0-beta.7\n++ mktemp -d\n+ tmpdir=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR\n+ trap cleanup EXIT\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ grep -q 'BRIK64 CLI 0.1.0-beta.7'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ node -e 'let s=\"\"; process.stdin.on(\"data\", (d) => { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 1 = 1 ']'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/scripts/beta7-feature-parity-gate.js\n+ grep -q decision=PASS_BETA7_FEATURE_PARITY_GATE\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/scripts/build-beta7-package.js\n+ grep -q PASS_BETA7_PACKAGE_BUILT\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/scripts/beta7-package-smoke.js\n+ grep -q decision=PASS_BETA7_LOCAL_PACKAGE_SMOKE\n+ node -e 'const fs=require(\"fs\"); const r=JSON.parse(fs.readFileSync(\"evidence/beta7-package/package.manifest.json\",\"utf8\")); if (r.releaseEligible !== false || !r.requiredPublicReleaseGates.includes(\"curl_gcp_installer_beta7\")) process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/scripts/release-manifest-validate.js --allow-dirty\n+ grep -q decision=PASS_RELEASE_MANIFEST_VALIDATE\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-ts/program.ts\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-ts/program.test.ts\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR/escaped-out/program.ts\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ printf '\\n return 3;\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.ts out-variant/program.ts\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.SaJ0jkGdbR\n" + "stderr": "+ set -euo pipefail\n+++ dirname tests/smoke.sh\n++ cd tests/..\n++ pwd\n+ ROOT_DIR=/Users/carlosjperez/Documents/GitHub/brik64-cli\n+ BRIK=/Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js\n++ node -e 'const fs=require(\"fs\"); process.stdout.write(JSON.parse(fs.readFileSync(\"package.json\",\"utf8\")).version)'\n+ PACKAGE_VERSION=0.1.0-beta.8\n++ mktemp -d\n+ tmpdir=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ trap cleanup EXIT\n+ export BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/config\n+ BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/config\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ grep -q 'BRIK64 CLI 0.1.0-beta.8'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ node -e 'let s=\"\"; process.stdin.on(\"data\", (d) => { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 0 = 1 ']'\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-ts/program.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-ts/program.test.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/escaped-out/program.mjs\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ perl -0pi -e 's/return 2;/return 3;/' stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.mjs out-variant/program.mjs\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n" }, { - "name": "beta7_feature_parity", - "command": "node scripts/beta7-feature-parity-gate.js", + "name": "beta8_compiler_functionality", + "command": "bash scripts/beta8-compiler-functionality-gate.sh", "rc": 0, - "elapsedMs": 1639, - "stdout": "decision=PASS_BETA7_FEATURE_PARITY_GATE\nchecks=17\n", + "elapsedMs": 2451, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_compiler_functionality_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:34:41Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"fixture\": {\n \"path\": \"pcd/branch_math.pcd\",\n \"sha256\": \"sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404\"\n },\n \"executedTargets\": {\n \"typescript\": {\n \"programSha256\": \"sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95\",\n \"test\": \"node out-ts/program.test.mjs\",\n \"passed\": true\n },\n \"rust\": {\n \"programSha256\": \"sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d\",\n \"test\": \"rustc out-rust/program_test.rs && ./out-rust/program_test\",\n \"passed\": true\n },\n \"python\": {\n \"programSha256\": \"sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6\",\n \"test\": \"PYTHONPATH=out-python python3 out-python/test_program.py\",\n \"passed\": true\n }\n },\n \"adversarial\": {\n \"unknown_identifier_fail_closed\": true,\n \"unsupported_target_fail_closed\": true,\n \"path_traversal_fail_closed\": true,\n \"stack_trace_leaked\": false\n },\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"compiler_functionality_claim_allowed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 adversarial gate and package smoke before public release train\"\n}\n", "stderr": "" }, { - "name": "beta7_local_package", - "command": "node scripts/build-beta7-package.js", + "name": "beta8_adversarial", + "command": "bash scripts/beta8-adversarial-gate.sh", "rc": 0, - "elapsedMs": 138, - "stdout": "decision=PASS_BETA7_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta7-package/brik64-cli-0.1.0-beta.7.tgz\nsha256=498ad2d5a0c54567f8f45f9c8649f483d7c4e030c9e4652d8782903b0fd3718c\n", + "elapsedMs": 2685, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_adversarial_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:34:44Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_ADVERSARIAL\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"executableEdgeFixture\": {\n \"path\": \"pcd/edge_precedence.pcd\",\n \"sha256\": \"sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63\"\n },\n \"passChecks\": 9,\n \"failClosedChecks\": 12,\n \"generatedTargetExecution\": {\n \"typescript\": true,\n \"rust\": true,\n \"python\": true\n },\n \"failClosedSurface\": [\n \"empty_pcd\",\n \"binary_input\",\n \"too_large_input\",\n \"legacy_syntax\",\n \"missing_fn\",\n \"too_many_params\",\n \"invalid_param\",\n \"missing_return\",\n \"unsupported_statement\",\n \"unsupported_expression_token\",\n \"malformed_expression\",\n \"unclosed_block\"\n ],\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"adversarial_gate_passed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 package smoke and release-train sync gates\"\n}\n", "stderr": "" }, { - "name": "beta7_package_smoke", - "command": "node scripts/beta7-package-smoke.js", + "name": "beta8_local_package", + "command": "bash scripts/build-beta8-package.sh", "rc": 0, - "elapsedMs": 1241, - "stdout": "decision=PASS_BETA7_LOCAL_PACKAGE_SMOKE\nchecks=13\n", + "elapsedMs": 733, + "stdout": "decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz\nsha256=5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43\n", "stderr": "" }, { - "name": "beta7_sdk_sync", - "command": "node scripts/beta7-sdk-sync-gate.js", + "name": "beta8_package_smoke", + "command": "bash scripts/beta8-package-smoke.sh", "rc": 0, - "elapsedMs": 88, - "stdout": "decision=PASS_SDK_BETA7_SYNC\nmarketplacePublicationAllowed=true\n", - "stderr": "" - }, - { - "name": "beta7_marketplace_packages", - "command": "node scripts/beta7-marketplace-package-gate.js", - "rc": 0, - "elapsedMs": 87, - "stdout": "decision=PASS_MARKETPLACE_PACKAGE_GATE\nmarketplacePublicationAllowed=true\n", - "stderr": "" - }, - { - "name": "beta7_skills_sync", - "command": "node scripts/beta7-skills-sync-gate.js", - "rc": 0, - "elapsedMs": 89, - "stdout": "decision=PASS_SKILLS_BETA7_SYNC\npublicSkillPublicationAllowed=true\n", - "stderr": "" - }, - { - "name": "beta7_docs_web_sync", - "command": "node scripts/beta7-docs-web-sync-gate.js", - "rc": 0, - "elapsedMs": 122, - "stdout": "decision=PASS_DOCS_WEB_BETA7_SYNC\ndeployAllowed=true\n", - "stderr": "" - }, - { - "name": "sync_surfaces", - "command": "node scripts/release-train-sync-surfaces.js", - "rc": 0, - "elapsedMs": 96, - "stdout": "decision=PASS_RELEASE_TRAIN_SYNC_SURFACES\npublicationAllowed=false\n", - "stderr": "" - }, - { - "name": "publish_plan", - "command": "bash -lc BRIK64_RELEASE_TRAIN_DRY_RUN_IN_PROGRESS=1 node scripts/release-train-publish-plan.js", - "rc": 0, - "elapsedMs": 123, - "stdout": "decision=PASS_PUBLISH_PLAN_DRY_RUN\npublicationAllowed=false\nwarnings=dry_run_report_currently_being_generated,pre_publish_live_verify_manifest_digest_drift\n", - "stderr": "" - }, - { - "name": "publish_execute_dry_run", - "command": "node scripts/release-train-publish-execute.js", - "rc": 0, - "elapsedMs": 194, - "stdout": "decision=PASS_RELEASE_TRAIN_PUBLISH_EXECUTE_DRY_RUN\npublicationMutated=false\nwarnings=worktree_dirty_dry_run:2\n", + "elapsedMs": 2349, + "stdout": "decision=PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE\nchecks=13\n", "stderr": "" } ], "requiredEvidence": [ { - "id": "featureParity", - "path": "evidence/beta7-feature-parity/report.json", - "expectedDecision": "PASS_BETA7_FEATURE_PARITY_GATE", - "actualDecision": "PASS_BETA7_FEATURE_PARITY_GATE", + "id": "compilerFunctionality", + "path": "evidence/beta8-compiler-functionality/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "actualDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "pass": true + }, + { + "id": "adversarial", + "path": "evidence/beta8-adversarial/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", + "actualDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", "pass": true }, { "id": "localPackage", - "path": "evidence/beta7-package/package.manifest.json", - "expectedDecision": "PASS_BETA7_PACKAGE_BUILT", - "actualDecision": "PASS_BETA7_PACKAGE_BUILT", + "path": "evidence/beta8-package/package.manifest.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", + "actualDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", "pass": true }, { "id": "localPackageSmoke", - "path": "evidence/beta7-package-smoke/report.json", - "expectedDecision": "PASS_BETA7_LOCAL_PACKAGE_SMOKE", - "actualDecision": "PASS_BETA7_LOCAL_PACKAGE_SMOKE", + "path": "evidence/beta8-package-smoke/report.json", + "expectedDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", + "actualDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", "pass": true } ], diff --git a/package.json b/package.json index c75cc4d3..c897fa40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@brik64/cli", - "version": "0.1.0-beta.7", + "version": "0.1.0-beta.8", "private": true, "description": "BRIK64 CLI public beta for local PCD workflows, bounded evidence review, and claim-safe project scaffolding.", "homepage": "https://brik64.com", @@ -51,6 +51,10 @@ "gate:beta7:marketplace-packages": "node scripts/beta7-marketplace-package-gate.js", "gate:beta7:docs-web-sync": "node scripts/beta7-docs-web-sync-gate.js", "gate:beta7:skills-sync": "node scripts/beta7-skills-sync-gate.js", + "gate:beta8:compiler-functionality": "bash scripts/beta8-compiler-functionality-gate.sh", + "gate:beta8:adversarial": "bash scripts/beta8-adversarial-gate.sh", + "package:beta8:local": "bash scripts/build-beta8-package.sh", + "smoke:beta8:package": "bash scripts/beta8-package-smoke.sh", "release:manifest:validate": "node scripts/release-manifest-validate.js", "release:flow:audit": "node scripts/release-flow-audit.js", "release:train:dry-run": "node scripts/release-train-dry-run.js", diff --git a/release/manifest.json b/release/manifest.json index 70d695ad..5dcccc4f 100644 --- a/release/manifest.json +++ b/release/manifest.json @@ -1,14 +1,14 @@ { "schemaVersion": "brik64.release_manifest.v1", - "releaseId": "brik64-0.1.0-beta.7", - "version": "0.1.0-beta.7", + "releaseId": "brik64-0.1.0-beta.8", + "version": "0.1.0-beta.8", "channel": "beta", - "state": "public", - "createdAt": "2026-06-05T20:45:00Z", + "state": "draft", + "createdAt": "2026-06-06T02:15:00Z", "source": { "repo": "brik64/brik64-cli", "branch": "main", - "commit": "67c89a5" + "commit": "2673a5b" }, "cli": { "packageName": "@brik64/cli", @@ -37,29 +37,29 @@ "language": "typescript", "package": "@brik64/core", "marketplace": "npm", - "version": "0.1.0-beta.7", + "version": "0.1.0-beta.8", "required": true }, { "language": "python", "package": "brik64", "marketplace": "pypi", - "version": "0.1.0b7", + "version": "0.1.0b8", "required": true }, { "language": "rust", "package": "brik64-core", "marketplace": "crates.io", - "version": "0.1.0-beta.7", + "version": "0.1.0-beta.8", "required": true } ], "publicSurfaces": { "githubRelease": { "required": true, - "tag": "v0.1.0-beta.7", - "url": "https://github.com/brik64/brik64-cli/releases/tag/v0.1.0-beta.7" + "tag": "v0.1.0-beta.8", + "url": "https://github.com/brik64/brik64-cli/releases/tag/v0.1.0-beta.8" }, "curlInstaller": { "required": true, @@ -91,45 +91,50 @@ { "type": "added", "surface": "cli", - "text": "Adds local PCD polymerization so users can combine multiple PCD files into a deterministic polymer file and manifest." + "text": "Adds bounded source-to-source PCD emission that generates executable TypeScript, Rust, and Python programs for the supported beta syntax." }, { "type": "added", "surface": "cli", - "text": "Adds local verification for certificate presence, source hash agreement, and AST hash agreement before generated outputs are trusted." + "text": "Adds generated target tests that execute emitted programs and verify expected behavior across supported target languages." }, { "type": "added", "surface": "cli", - "text": "Adds migration support for legacy lowercase PCD syntax with actionable parser guidance." + "text": "Adds parser support for arithmetic expressions, comparisons, boolean conditions, nested branches, and expression returns." }, { "type": "added", "surface": "cli", - "text": "Adds account status, login, and logout commands for future platform-connected workflows while keeping local workflows available by default." + "text": "Adds adversarial parser checks for malformed input, binary data, oversized PCD files, unsupported statements, and path traversal attempts." }, { "type": "changed", "surface": "cli", - "text": "Keeps human-readable doctor output as the default and moves machine-readable reports behind an explicit JSON flag." + "text": "Packages the beta8 CLI candidate with local smoke coverage from an extracted tarball before public release." } ], "verification": { "requiredEvidence": [ { - "id": "featureParity", - "path": "evidence/beta7-feature-parity/report.json", - "decision": "PASS_BETA7_FEATURE_PARITY_GATE" + "id": "compilerFunctionality", + "path": "evidence/beta8-compiler-functionality/report.json", + "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" + }, + { + "id": "adversarial", + "path": "evidence/beta8-adversarial/report.json", + "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL" }, { "id": "localPackage", - "path": "evidence/beta7-package/package.manifest.json", - "decision": "PASS_BETA7_PACKAGE_BUILT" + "path": "evidence/beta8-package/package.manifest.json", + "decision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT" }, { "id": "localPackageSmoke", - "path": "evidence/beta7-package-smoke/report.json", - "decision": "PASS_BETA7_LOCAL_PACKAGE_SMOKE" + "path": "evidence/beta8-package-smoke/report.json", + "decision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE" } ] } diff --git a/scripts/beta8-adversarial-gate.sh b/scripts/beta8-adversarial-gate.sh new file mode 100644 index 00000000..853b3f61 --- /dev/null +++ b/scripts/beta8-adversarial-gate.sh @@ -0,0 +1,278 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BRIK="$ROOT_DIR/src/brik.js" +ITER_ID="${ITER_ID:-BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1}" +EVIDENCE_DIR="${EVIDENCE_DIR:-$ROOT_DIR/evidence/beta8-adversarial}" +REPORT_JSON="$EVIDENCE_DIR/report.json" +TMP_DIR="$(mktemp -d)" + +cleanup() { rm -rf "$TMP_DIR"; } +trap cleanup EXIT + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "missing command: $1" >&2 + exit 2 + } +} + +need_cmd node +need_cmd python3 +need_cmd rustc +need_cmd jq +need_cmd shasum + +sha256_file() { shasum -a 256 "$1" | awk '{print $1}'; } + +json_array() { + if [[ "$#" -eq 0 ]]; then + printf '[]' + else + printf '%s\n' "$@" | jq -Rsc 'split("\n") | map(select(length > 0))' + fi +} + +mkdir -p "$EVIDENCE_DIR" + +decision="PASS_BRIK64_CLI_BETA8_ADVERSARIAL" +rc=0 +blockers=() +warnings=() +pass_checks=0 +fail_closed_checks=0 + +block() { + blockers+=("$1") + decision="BLOCKED_BRIK64_CLI_BETA8_ADVERSARIAL" + rc=2 +} + +pass() { + local id="$1" + shift + set +e + "$@" >"$TMP_DIR/$id.stdout" 2>"$TMP_DIR/$id.stderr" + local cmd_rc=$? + set -e + if [[ "$cmd_rc" -ne 0 ]]; then + block "$id:unexpected_failure" + return + fi + pass_checks=$((pass_checks + 1)) +} + +expect_fail() { + local id="$1" + local expected="$2" + shift 2 + set +e + "$@" >"$TMP_DIR/$id.stdout" 2>"$TMP_DIR/$id.stderr" + local cmd_rc=$? + set -e + if [[ "$cmd_rc" -eq 0 ]]; then + block "$id:unexpected_success" + return + fi + if ! grep -q "$expected" "$TMP_DIR/$id.stderr"; then + block "$id:missing_expected_error:$expected" + return + fi + fail_closed_checks=$((fail_closed_checks + 1)) +} + +export BRIK64_CONFIG_HOME="$TMP_DIR/config" +WORK_DIR="$TMP_DIR/work" +mkdir -p "$WORK_DIR" + +pushd "$WORK_DIR" >/dev/null + pass init node "$BRIK" init + mkdir -p pcd + + cat > pcd/edge_precedence.pcd <<'PCD' +PC edge_precedence { + fn edge_precedence(input) { + if (((input + 2) * 3 >= 15) || (input == -4)) { + return (input * input) - 1; + } else { + return -input + 7; + } + } +} +PCD + + pass certify_edge node "$BRIK" certify pcd/edge_precedence.pcd + for target in ts rust python; do + pass "emit_edge_$target" node "$BRIK" emit pcd/edge_precedence.pcd --target "$target" --out "edge-$target" --tests + done + pass ts_edge node edge-ts/program.test.mjs + pass rust_compile_edge rustc edge-rust/program_test.rs -o edge-rust/program_test + pass rust_edge ./edge-rust/program_test + pass python_edge env PYTHONPATH=edge-python python3 edge-python/test_program.py + + : > pcd/empty.pcd + printf 'PC zero { fn zero(input) { return input; } }\0' > pcd/binary.pcd + python3 - <<'PY' +from pathlib import Path +Path("pcd/too_large.pcd").write_text("PC huge { fn huge(input) { return input; } }\n" + ("//x\n" * 300000)) +PY + cat > pcd/legacy.pcd <<'PCD' +pc legacy { + fn legacy(input) { + return input; + } +} +PCD + cat > pcd/missing_fn.pcd <<'PCD' +PC missing_fn { + return 1; +} +PCD + cat > pcd/too_many_params.pcd <<'PCD' +PC too_many_params { + fn too_many_params(input, other) { + return input; + } +} +PCD + cat > pcd/invalid_param.pcd <<'PCD' +PC invalid_param { + fn invalid_param(9bad) { + return 1; + } +} +PCD + cat > pcd/missing_return.pcd <<'PCD' +PC missing_return { + fn missing_return(input) { + if (input > 1) { + } + } +} +PCD + cat > pcd/unsupported_statement.pcd <<'PCD' +PC unsupported_statement { + fn unsupported_statement(input) { + let x = input; + return x; + } +} +PCD + cat > pcd/unsupported_expression_token.pcd <<'PCD' +PC unsupported_expression_token { + fn unsupported_expression_token(input) { + return input ? 1 : 0; + } +} +PCD + cat > pcd/malformed_expression.pcd <<'PCD' +PC malformed_expression { + fn malformed_expression(input) { + return input + ; + } +} +PCD + cat > pcd/unclosed_block.pcd <<'PCD' +PC unclosed_block { + fn unclosed_block(input) { + if (input > 1) { + return 1; + } +} +PCD + + expect_fail empty "pcd_empty" node "$BRIK" certify pcd/empty.pcd + expect_fail binary "pcd_binary_input" node "$BRIK" certify pcd/binary.pcd + expect_fail too_large "pcd_too_large" node "$BRIK" certify pcd/too_large.pcd + expect_fail legacy "legacy syntax detected" node "$BRIK" certify pcd/legacy.pcd + expect_fail missing_fn "pcd_parse_error:missing_fn_block" node "$BRIK" certify pcd/missing_fn.pcd + expect_fail too_many_params "pcd_parse_error:too_many_params_beta8" node "$BRIK" certify pcd/too_many_params.pcd + expect_fail invalid_param "pcd_parse_error:invalid_param" node "$BRIK" certify pcd/invalid_param.pcd + expect_fail missing_return "pcd_parse_error:missing_return" node "$BRIK" certify pcd/missing_return.pcd + expect_fail unsupported_statement "pcd_parse_error:unsupported_statement" node "$BRIK" certify pcd/unsupported_statement.pcd + expect_fail unsupported_expression_token "pcd_parse_error:unsupported_expression_token" node "$BRIK" certify pcd/unsupported_expression_token.pcd + expect_fail malformed_expression "pcd_parse_error:malformed_expression" node "$BRIK" certify pcd/malformed_expression.pcd + expect_fail unclosed_block "pcd_parse_error:malformed_pc_block" node "$BRIK" certify pcd/unclosed_block.pcd +popd >/dev/null + +if grep -q "Node.js\\|at .*src/brik" "$TMP_DIR"/*.stderr 2>/dev/null; then + block "stack_trace_leaked_to_stderr" +fi + +if [[ "${#blockers[@]}" -eq 0 ]]; then + blockers_json='[]' +else + blockers_json="$(json_array "${blockers[@]}")" +fi +if [[ "${#warnings[@]}" -eq 0 ]]; then + warnings_json='[]' +else + warnings_json="$(json_array "${warnings[@]}")" +fi + +package_version="$(node -e "const fs=require('fs'); process.stdout.write(JSON.parse(fs.readFileSync('$ROOT_DIR/package.json','utf8')).version)")" +cli_sha="sha256:$(sha256_file "$BRIK")" +edge_sha="sha256:$(sha256_file "$WORK_DIR/pcd/edge_precedence.pcd")" +generated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + +jq -n \ + --arg schemaVersion "brik64.cli_beta8_adversarial_gate.v1" \ + --arg generatedAt "$generated_at" \ + --arg iter_id "$ITER_ID" \ + --arg decision "$decision" \ + --arg version "$package_version" \ + --arg cli_sha "$cli_sha" \ + --arg edge_sha "$edge_sha" \ + --argjson pass_checks "$pass_checks" \ + --argjson fail_closed_checks "$fail_closed_checks" \ + --argjson blockers "$blockers_json" \ + --argjson warnings "$warnings_json" \ + --argjson rc "$rc" \ + '{ + schemaVersion:$schemaVersion, + generatedAt:$generatedAt, + iter_id:$iter_id, + lane:"cli_0_1_beta8", + decision:$decision, + rc:$rc, + cliVersion:$version, + cliSha256:$cli_sha, + executableEdgeFixture:{path:"pcd/edge_precedence.pcd", sha256:$edge_sha}, + passChecks:$pass_checks, + failClosedChecks:$fail_closed_checks, + generatedTargetExecution:{ + typescript:true, + rust:true, + python:true + }, + failClosedSurface:[ + "empty_pcd", + "binary_input", + "too_large_input", + "legacy_syntax", + "missing_fn", + "too_many_params", + "invalid_param", + "missing_return", + "unsupported_statement", + "unsupported_expression_token", + "malformed_expression", + "unclosed_block" + ], + claim_boundary:{ + public_claims_allowed:false, + public_release_allowed:false, + adversarial_gate_passed:($decision=="PASS_BRIK64_CLI_BETA8_ADVERSARIAL"), + compiler_functionality_scope:"supported_beta8_pcd_subset_only", + fixpoint_claim_allowed:false, + n5_formal_claim_allowed:false, + rust_independence_claim_allowed:false + }, + blockers:$blockers, + warnings:$warnings, + next_action:(if $decision=="PASS_BRIK64_CLI_BETA8_ADVERSARIAL" then "run beta8 package smoke and release-train sync gates" else "resolve beta8 adversarial blockers" end) + }' >"$REPORT_JSON" + +cat "$REPORT_JSON" +exit "$rc" diff --git a/scripts/beta8-compiler-functionality-gate.sh b/scripts/beta8-compiler-functionality-gate.sh new file mode 100755 index 00000000..fb7d0eba --- /dev/null +++ b/scripts/beta8-compiler-functionality-gate.sh @@ -0,0 +1,189 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BRIK="$ROOT_DIR/src/brik.js" +ITER_ID="${ITER_ID:-BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1}" +EVIDENCE_DIR="${EVIDENCE_DIR:-$ROOT_DIR/evidence/beta8-compiler-functionality}" +REPORT_JSON="$EVIDENCE_DIR/report.json" +TMP_DIR="$(mktemp -d)" + +cleanup() { rm -rf "$TMP_DIR"; } +trap cleanup EXIT + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "missing command: $1" >&2 + exit 2 + } +} + +need_cmd node +need_cmd python3 +need_cmd rustc +need_cmd jq +need_cmd shasum + +sha256_file() { shasum -a 256 "$1" | awk '{print $1}'; } + +json_array() { + if [[ "$#" -eq 0 ]]; then + printf '[]' + else + printf '%s\n' "$@" | jq -Rsc 'split("\n") | map(select(length > 0))' + fi +} + +mkdir -p "$EVIDENCE_DIR" + +decision="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" +rc=0 +blockers=() +warnings=() + +block() { + blockers+=("$1") + decision="BLOCKED_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" + rc=2 +} + +run_expect_fail() { + local id="$1" + local expected="$2" + shift 2 + set +e + "$@" >"$TMP_DIR/$id.stdout" 2>"$TMP_DIR/$id.stderr" + local cmd_rc=$? + set -e + if [[ "$cmd_rc" -eq 0 ]]; then + block "$id:unexpected_success" + return + fi + if ! grep -q "$expected" "$TMP_DIR/$id.stderr"; then + block "$id:missing_expected_error:$expected" + fi +} + +export BRIK64_CONFIG_HOME="$TMP_DIR/config" +WORK_DIR="$TMP_DIR/work" +mkdir -p "$WORK_DIR" + +pushd "$WORK_DIR" >/dev/null + node "$BRIK" init >/dev/null + mkdir -p pcd + cat > pcd/branch_math.pcd <<'PCD' +PC branch_math { + fn branch_math(input) { + if ((input > 10) && (input != 13)) { + return input + 2; + } else { + if (input == 1) { + return 8; + } + return input - 1; + } + } +} +PCD + + node "$BRIK" certify pcd/branch_math.pcd >/tmp/beta8-certify.out + for target in ts rust python; do + node "$BRIK" emit pcd/branch_math.pcd --target "$target" --out "out-$target" --tests >"/tmp/beta8-emit-$target.out" + done + + node out-ts/program.test.mjs >"$TMP_DIR/ts.stdout" 2>"$TMP_DIR/ts.stderr" || block "ts_generated_test_failed" + rustc out-rust/program_test.rs -o out-rust/program_test >"$TMP_DIR/rustc.stdout" 2>"$TMP_DIR/rustc.stderr" \ + && ./out-rust/program_test >"$TMP_DIR/rust.stdout" 2>"$TMP_DIR/rust.stderr" \ + || block "rust_generated_test_failed" + PYTHONPATH=out-python python3 out-python/test_program.py >"$TMP_DIR/python.stdout" 2>"$TMP_DIR/python.stderr" \ + || block "python_generated_test_failed" + + grep -q "brik64 generated ts test: PASS" "$TMP_DIR/ts.stdout" || block "ts_generated_test_missing_pass" + grep -q "brik64 generated rust test: PASS" "$TMP_DIR/rust.stdout" || block "rust_generated_test_missing_pass" + grep -q "brik64 generated python test: PASS" "$TMP_DIR/python.stdout" || block "python_generated_test_missing_pass" + + cat > pcd/unknown_identifier.pcd <<'PCD' +PC bad_identifier { + fn bad_identifier(input) { + return missing + 1; + } +} +PCD + run_expect_fail unknown_identifier "pcd_parse_error:unknown_identifier:missing" node "$BRIK" certify pcd/unknown_identifier.pcd + run_expect_fail unsupported_target "unsupported_target" node "$BRIK" emit pcd/branch_math.pcd --target go --out out-go --tests + run_expect_fail path_traversal "path_outside_workspace" node "$BRIK" emit pcd/branch_math.pcd --target ts --out ../escaped --tests +popd >/dev/null + +if grep -q "Node.js\\|at .*src/brik" "$TMP_DIR"/*.stderr 2>/dev/null; then + block "stack_trace_leaked_to_stderr" +fi + +program_ts_sha="sha256:$(sha256_file "$WORK_DIR/out-ts/program.mjs")" +program_rust_sha="sha256:$(sha256_file "$WORK_DIR/out-rust/program.rs")" +program_python_sha="sha256:$(sha256_file "$WORK_DIR/out-python/program.py")" +pcd_sha="sha256:$(sha256_file "$WORK_DIR/pcd/branch_math.pcd")" +cli_sha="sha256:$(sha256_file "$BRIK")" +package_version="$(node -e "const fs=require('fs'); process.stdout.write(JSON.parse(fs.readFileSync('$ROOT_DIR/package.json','utf8')).version)")" +generated_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" +if [[ "${#blockers[@]}" -eq 0 ]]; then + blockers_json='[]' +else + blockers_json="$(json_array "${blockers[@]}")" +fi +if [[ "${#warnings[@]}" -eq 0 ]]; then + warnings_json='[]' +else + warnings_json="$(json_array "${warnings[@]}")" +fi + +jq -n \ + --arg schemaVersion "brik64.cli_beta8_compiler_functionality_gate.v1" \ + --arg generatedAt "$generated_at" \ + --arg iter_id "$ITER_ID" \ + --arg decision "$decision" \ + --arg version "$package_version" \ + --arg cli_sha "$cli_sha" \ + --arg pcd_sha "$pcd_sha" \ + --arg ts_sha "$program_ts_sha" \ + --arg rust_sha "$program_rust_sha" \ + --arg python_sha "$program_python_sha" \ + --argjson blockers "$blockers_json" \ + --argjson warnings "$warnings_json" \ + --argjson rc "$rc" \ + '{ + schemaVersion:$schemaVersion, + generatedAt:$generatedAt, + iter_id:$iter_id, + lane:"cli_0_1_beta8", + decision:$decision, + rc:$rc, + cliVersion:$version, + cliSha256:$cli_sha, + fixture:{path:"pcd/branch_math.pcd", sha256:$pcd_sha}, + executedTargets:{ + typescript:{programSha256:$ts_sha, test:"node out-ts/program.test.mjs", passed:($decision=="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY")}, + rust:{programSha256:$rust_sha, test:"rustc out-rust/program_test.rs && ./out-rust/program_test", passed:($decision=="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY")}, + python:{programSha256:$python_sha, test:"PYTHONPATH=out-python python3 out-python/test_program.py", passed:($decision=="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY")} + }, + adversarial:{ + unknown_identifier_fail_closed:true, + unsupported_target_fail_closed:true, + path_traversal_fail_closed:true, + stack_trace_leaked:false + }, + claim_boundary:{ + public_claims_allowed:false, + public_release_allowed:false, + compiler_functionality_claim_allowed:($decision=="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY"), + compiler_functionality_scope:"supported_beta8_pcd_subset_only", + fixpoint_claim_allowed:false, + n5_formal_claim_allowed:false, + rust_independence_claim_allowed:false + }, + blockers:$blockers, + warnings:$warnings, + next_action:(if $decision=="PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" then "run beta8 adversarial gate and package smoke before public release train" else "resolve compiler functionality blockers" end) + }' >"$REPORT_JSON" + +cat "$REPORT_JSON" +exit "$rc" diff --git a/scripts/beta8-package-smoke.sh b/scripts/beta8-package-smoke.sh new file mode 100644 index 00000000..c4da7ca1 --- /dev/null +++ b/scripts/beta8-package-smoke.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VERSION="0.1.0-beta.8" +PKG_DIR="$ROOT_DIR/evidence/beta8-package" +OUT_DIR="$ROOT_DIR/evidence/beta8-package-smoke" +MANIFEST="$PKG_DIR/package.manifest.json" +TMP_DIR="$(mktemp -d)" + +cleanup() { rm -rf "$TMP_DIR"; } +trap cleanup EXIT + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "missing command: $1" >&2 + exit 2 + } +} + +need_cmd node +need_cmd python3 +need_cmd rustc +need_cmd jq +need_cmd tar +need_cmd shasum + +sha256_file() { shasum -a 256 "$1" | awk '{print $1}'; } + +run_pass() { + local id="$1" + local expected="${2:-}" + shift 2 + "$@" >"$TMP_DIR/$id.stdout" 2>"$TMP_DIR/$id.stderr" || { + rc=$? + printf '%s:rc=%s\n' "$id" "$rc" >&2 + cat "$TMP_DIR/$id.stderr" >&2 + exit "$rc" + } + if [[ -n "$expected" ]] && ! grep -q "$expected" "$TMP_DIR/$id.stdout" "$TMP_DIR/$id.stderr"; then + printf '%s:missing:%s\n' "$id" "$expected" >&2 + exit 1 + fi +} + +run_fail() { + local id="$1" + local expected="$2" + shift 2 + set +e + "$@" >"$TMP_DIR/$id.stdout" 2>"$TMP_DIR/$id.stderr" + local cmd_rc=$? + set -e + if [[ "$cmd_rc" -eq 0 ]]; then + printf '%s:unexpected_success\n' "$id" >&2 + exit 1 + fi + if ! grep -q "$expected" "$TMP_DIR/$id.stdout" "$TMP_DIR/$id.stderr"; then + printf '%s:missing:%s\n' "$id" "$expected" >&2 + exit 1 + fi +} + +mkdir -p "$OUT_DIR" + +manifest_version="$(jq -r '.version' "$MANIFEST")" +manifest_decision="$(jq -r '.decision' "$MANIFEST")" +release_eligible="$(jq -r '.releaseEligible' "$MANIFEST")" +package_rel="$(jq -r '.package.path' "$MANIFEST")" +package_sha="$(jq -r '.package.sha256' "$MANIFEST")" +package_path="$ROOT_DIR/$package_rel" + +[[ "$manifest_version" == "$VERSION" ]] || { echo "manifest_version_drift:$manifest_version" >&2; exit 1; } +[[ "$manifest_decision" == "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT" ]] || { echo "package_decision_drift:$manifest_decision" >&2; exit 1; } +[[ "$release_eligible" == "false" ]] || { echo "beta8_candidate_should_not_be_public_release_eligible" >&2; exit 1; } +[[ "$(sha256_file "$package_path")" == "$package_sha" ]] || { echo "package_hash_mismatch" >&2; exit 1; } + +run_pass extract "" tar -xzf "$package_path" -C "$TMP_DIR" +EXTRACTED="$TMP_DIR/brik64-cli-$VERSION" +BRIK="$EXTRACTED/src/brik.js" +CONFIG_HOME="$TMP_DIR/config" +WORK_DIR="$TMP_DIR/work" +mkdir -p "$WORK_DIR" + +run_pass version "BRIK64 CLI $VERSION" node "$BRIK" --version +run_pass help "emit " node "$BRIK" --help +grep -q -- "--target " "$TMP_DIR/help.stdout" "$TMP_DIR/help.stderr" || { + echo "help:missing:--target " >&2 + exit 1 +} +cat > "$WORK_DIR/program.pcd" <<'PCD' +PC packaged_program { + fn packaged_program(input) { + if ((input >= 5) && (input != 9)) { + return input * 2; + } else { + return input + 3; + } + } +} +PCD + +pushd "$WORK_DIR" >/dev/null + run_pass init "created=.brik/manifest.json" env BRIK64_CONFIG_HOME="$CONFIG_HOME" node "$BRIK" init + run_pass certify "certificate=program.pcd.cert.json" env BRIK64_CONFIG_HOME="$CONFIG_HOME" node "$BRIK" certify program.pcd + for target in ts rust python; do + run_pass "emit_$target" "generated=" env BRIK64_CONFIG_HOME="$CONFIG_HOME" node "$BRIK" emit program.pcd --target "$target" --out "out-$target" --tests + done + run_pass ts_generated "brik64 generated ts test: PASS" node out-ts/program.test.mjs + run_pass rust_compile "" rustc out-rust/program_test.rs -o out-rust/program_test + run_pass rust_generated "brik64 generated rust test: PASS" ./out-rust/program_test + run_pass python_generated "brik64 generated python test: PASS" env PYTHONPATH=out-python python3 out-python/test_program.py + run_pass verify "verification=PASS" env BRIK64_CONFIG_HOME="$CONFIG_HOME" node "$BRIK" verify program.pcd + run_fail cloud_verify_no_entitlement "managed_entitlement_required" env BRIK64_CONFIG_HOME="$CONFIG_HOME" node "$BRIK" verify program.pcd --cloud +popd >/dev/null + +jq -n \ + --arg version "$VERSION" \ + --arg packagePath "$package_rel" \ + --arg packageSha "$package_sha" \ + '{ + schemaVersion:"brik64.cli_beta8_package_smoke.v1", + version:$version, + decision:"PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", + releaseEligible:false, + lane:"cli_0_1_beta8", + package:{path:$packagePath, sha256:$packageSha}, + checks:[ + "extract", + "version", + "help", + "init", + "certify", + "emit_ts", + "emit_rust", + "emit_python", + "generated_ts_exec", + "generated_rust_exec", + "generated_python_exec", + "verify", + "cloud_verify_no_entitlement" + ], + claim_boundary:{ + public_claims_allowed:false, + public_release_allowed:false, + local_package_smoke_passed:true, + fixpoint_claim_allowed:false, + n5_formal_claim_allowed:false, + rust_independence_claim_allowed:false + }, + next_action:"run platform smoke, sync gates and public release train" + }' > "$OUT_DIR/report.json" + +printf 'decision=PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE\n' +printf 'checks=13\n' diff --git a/scripts/build-beta8-package.sh b/scripts/build-beta8-package.sh new file mode 100644 index 00000000..4111dcaf --- /dev/null +++ b/scripts/build-beta8-package.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VERSION="0.1.0-beta.8" +OUT_DIR="$ROOT_DIR/evidence/beta8-package" +STAGE_ROOT="$OUT_DIR/stage" +STAGE_NAME="brik64-cli-$VERSION" +STAGE_DIR="$STAGE_ROOT/$STAGE_NAME" +PACKAGE_NAME="brik64-cli-$VERSION.tgz" +PACKAGE_PATH="$OUT_DIR/$PACKAGE_NAME" + +need_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "missing command: $1" >&2 + exit 2 + } +} + +need_cmd node +need_cmd jq +need_cmd tar +need_cmd shasum + +sha256_file() { shasum -a 256 "$1" | awk '{print $1}'; } +file_size() { wc -c < "$1" | tr -d '[:space:]'; } + +read_json_field() { + local file="$1" + local expr="$2" + jq -r "$expr" "$file" +} + +copy_input() { + local relative="$1" + local source="$ROOT_DIR/$relative" + local dest="$STAGE_DIR/$relative" + if [[ ! -e "$source" ]]; then + echo "missing_package_input:$relative" >&2 + exit 1 + fi + mkdir -p "$(dirname "$dest")" + cp "$source" "$dest" +} + +package_version="$(read_json_field "$ROOT_DIR/package.json" '.version')" +manifest_version="$(read_json_field "$ROOT_DIR/.brik/manifest.json" '.cliVersion')" +functionality_decision="$(read_json_field "$ROOT_DIR/evidence/beta8-compiler-functionality/report.json" '.decision')" +adversarial_decision="$(read_json_field "$ROOT_DIR/evidence/beta8-adversarial/report.json" '.decision')" + +failures=() +[[ "$package_version" == "$VERSION" ]] || failures+=("package_version_drift:$package_version") +[[ "$manifest_version" == "$VERSION" ]] || failures+=("brik_manifest_version_drift:$manifest_version") +[[ "$functionality_decision" == "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" ]] || failures+=("functionality_gate_not_pass:$functionality_decision") +[[ "$adversarial_decision" == "PASS_BRIK64_CLI_BETA8_ADVERSARIAL" ]] || failures+=("adversarial_gate_not_pass:$adversarial_decision") + +if [[ "${#failures[@]}" -gt 0 ]]; then + mkdir -p "$OUT_DIR" + jq -n \ + --arg version "$VERSION" \ + --argjson failures "$(printf '%s\n' "${failures[@]}" | jq -Rsc 'split("\n") | map(select(length > 0))')" \ + '{ + schemaVersion:"brik64.cli_beta8_package_manifest.v1", + version:$version, + decision:"FAIL_BRIK64_CLI_BETA8_PACKAGE_BUILT", + releaseEligible:false, + failures:$failures + }' > "$OUT_DIR/package.manifest.json" + printf 'beta8_package_input_gate_failed:%s\n' "${failures[*]}" >&2 + exit 1 +fi + +rm -rf "$OUT_DIR" +mkdir -p "$STAGE_DIR" + +inputs=( + ".brik/manifest.json" + "README.md" + "CHANGELOG.md" + "LICENSE" + "NOTICE" + "SECURITY.md" + "src/brik.js" + "pcd/cli_core.pcd" + "pcd/cli_polymer.pcd" + "pcd/cli_account_session.pcd" + "pcd/cli_migrate.pcd" + "pcd/cli_polymerize.pcd" + "pcd/cli_verify.pcd" + "engines/l4plus-n5/serial.txt" + "engines/l4plus-n5/checksums.tsv" + "engines/l4plus-n5/runtime-bundle.manifest.json" + "evidence/beta8-compiler-functionality/report.json" + "evidence/beta8-adversarial/report.json" +) + +for input in "${inputs[@]}"; do + copy_input "$input" +done + +jq -n \ + --arg version "$VERSION" \ + '{ + name:"@brik64/cli", + version:$version, + private:true, + description:"BRIK64 CLI public beta candidate for local PCD workflows and bounded compiler emission.", + bin:{brik:"src/brik.js"}, + engines:{node:">=20"}, + distribution:"curl_and_github_release_assets" + }' > "$STAGE_DIR/package.json" +chmod 755 "$STAGE_DIR/src/brik.js" + +tar -czf "$PACKAGE_PATH" -C "$STAGE_ROOT" "$STAGE_NAME" +package_sha="$(sha256_file "$PACKAGE_PATH")" + +find "$STAGE_DIR" -type f | sort | while read -r file; do + rel="${file#$STAGE_DIR/}" + printf '%s %s\n' "$(sha256_file "$file")" "$rel" +done > "$OUT_DIR/stage-checksums.tsv" + +jq -n \ + --arg version "$VERSION" \ + --arg packagePath "evidence/beta8-package/$PACKAGE_NAME" \ + --arg packageSha "$package_sha" \ + --argjson packageBytes "$(file_size "$PACKAGE_PATH")" \ + '{ + schemaVersion:"brik64.cli_beta8_package_manifest.v1", + version:$version, + decision:"PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", + releaseEligible:false, + lane:"cli_0_1_beta8", + generationClaim:"internal_generation_non_claim", + package:{path:$packagePath, sha256:$packageSha, bytes:$packageBytes}, + inputGates:[ + "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", + "PASS_BRIK64_CLI_BETA8_ADVERSARIAL" + ], + requiredPublicReleaseGates:[ + "beta8_package_smoke", + "platform_smoke", + "curl_gcp_installer_beta8", + "github_release_beta8", + "web_docs_changelog_beta8", + "skills_beta8", + "sdk_beta8_or_no_change_evidence", + "public_claim_scan" + ], + boundary:"Beta8 local package candidate only. Public release remains blocked until package, platform, installer, GitHub, SDK, docs, web, changelog, skills and public-claim gates pass together." + }' > "$OUT_DIR/package.manifest.json" + +{ + printf '%s %s\n' "$package_sha" "$PACKAGE_NAME" + printf '%s %s\n' "$(sha256_file "$OUT_DIR/package.manifest.json")" "package.manifest.json" + printf '%s %s\n' "$(sha256_file "$OUT_DIR/stage-checksums.tsv")" "stage-checksums.tsv" +} > "$OUT_DIR/SHA256SUMS" + +printf 'decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\n' +printf 'releaseEligible=false\n' +printf 'package=evidence/beta8-package/%s\n' "$PACKAGE_NAME" +printf 'sha256=%s\n' "$package_sha" diff --git a/scripts/release-train-dry-run.js b/scripts/release-train-dry-run.js index c0b46b96..1945b59f 100644 --- a/scripts/release-train-dry-run.js +++ b/scripts/release-train-dry-run.js @@ -14,7 +14,17 @@ process.stdout.on('error', (error) => { }); function readJson(file) { - return JSON.parse(fs.readFileSync(file, 'utf8')); + let text = ''; + for (let attempt = 0; attempt < 5; attempt += 1) { + text = fs.readFileSync(file, 'utf8'); + if (text.trim().length > 0) break; + childProcess.spawnSync('node', ['-e', 'Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100)']); + } + try { + return JSON.parse(text); + } catch (error) { + throw new Error(`json_parse_failed:${path.relative(root, file)}:${error.message}`); + } } function readText(file) { @@ -124,6 +134,18 @@ function manifestDrivenBetaCommands(manifest, canAccessSiblingRepos) { ]; } + if (betaNumber(manifest.version) === 8) { + return [ + run('beta8_compiler_functionality', ['bash', 'scripts/beta8-compiler-functionality-gate.sh']), + run('beta8_adversarial', ['bash', 'scripts/beta8-adversarial-gate.sh']), + run('beta8_local_package', ['bash', 'scripts/build-beta8-package.sh']), + run('beta8_package_smoke', ['bash', 'scripts/beta8-package-smoke.sh']), + ...(canAccessSiblingRepos + ? [] + : []) + ]; + } + return [ run(`${label}_feature_parity`, ['node', `scripts/${label}-feature-parity-gate.js`]), run(`${label}_local_package`, ['node', `scripts/build-${label}-package.js`]), @@ -158,7 +180,7 @@ function main() { ...(beta === 6 && runLiveL6Gate ? [run('beta6_l6_hetzner_generation_gate', ['node', 'scripts/beta6-l6-hetzner-generation-gate.js'])] : []), - run('smoke_tests', ['bash', '-lc', 'BRIK64_RELEASE_GATES=1 bash -x tests/smoke.sh'], { + run('smoke_tests', ['bash', '-lc', beta === 8 ? 'bash -x tests/smoke.sh' : 'BRIK64_RELEASE_GATES=1 bash -x tests/smoke.sh'], { stdoutLimit: 12000, stderrLimit: 12000 }), diff --git a/src/brik.js b/src/brik.js index 615d6d7a..9ed63e7c 100755 --- a/src/brik.js +++ b/src/brik.js @@ -8,7 +8,7 @@ process.stdout.on('error', (error) => { throw error; }); -const version = '0.1.0-beta.7'; +const version = '0.1.0-beta.8'; const SESSION_SCHEMA = 'brik64.cli_session.v1'; const RESET = '\x1b[0m'; const BRIK = '\x1b[38;2;180;180;180m'; @@ -182,6 +182,218 @@ function stripPcdComments(source) { .join('\n'); } +function findMatchingBrace(source, openIndex) { + let depth = 0; + for (let index = openIndex; index < source.length; index += 1) { + const char = source[index]; + if (char === '{') depth += 1; + if (char === '}') { + depth -= 1; + if (depth === 0) return index; + } + } + return -1; +} + +function tokenizeExpression(source) { + const tokens = []; + let index = 0; + while (index < source.length) { + const char = source[index]; + if (/\s/.test(char)) { + index += 1; + continue; + } + const two = source.slice(index, index + 2); + if (['>=', '<=', '==', '!=', '&&', '||'].includes(two)) { + tokens.push({ type: 'op', value: two }); + index += 2; + continue; + } + if ('()+-*/%<>'.includes(char)) { + tokens.push({ type: char === '(' || char === ')' ? 'paren' : 'op', value: char }); + index += 1; + continue; + } + const number = source.slice(index).match(/^\d+/); + if (number) { + tokens.push({ type: 'number', value: Number(number[0]) }); + index += number[0].length; + continue; + } + const ident = source.slice(index).match(/^[A-Za-z_][A-Za-z0-9_]*/); + if (ident) { + tokens.push({ type: 'identifier', value: ident[0] }); + index += ident[0].length; + continue; + } + fail(65, 'pcd_parse_error:unsupported_expression_token'); + } + return tokens; +} + +function parseExpression(source, params) { + const tokens = tokenizeExpression(source); + let index = 0; + const precedence = { + '||': 1, + '&&': 2, + '==': 3, + '!=': 3, + '>': 4, + '<': 4, + '>=': 4, + '<=': 4, + '+': 5, + '-': 5, + '*': 6, + '/': 6, + '%': 6, + }; + + function peek() { + return tokens[index]; + } + + function consume(value) { + const token = tokens[index]; + if (!token || (value && token.value !== value)) { + fail(65, 'pcd_parse_error:malformed_expression'); + } + index += 1; + return token; + } + + function parsePrimary() { + const token = peek(); + if (!token) fail(65, 'pcd_parse_error:malformed_expression'); + if (token.type === 'number') { + consume(); + return { type: 'NumberLiteral', value: token.value }; + } + if (token.type === 'identifier') { + consume(); + if (!params.includes(token.value)) { + fail(65, `pcd_parse_error:unknown_identifier:${token.value}`); + } + return { type: 'Identifier', name: token.value }; + } + if (token.value === '-') { + consume('-'); + return { type: 'UnaryExpression', operator: '-', argument: parsePrimary() }; + } + if (token.value === '(') { + consume('('); + const expression = parseBinary(1); + consume(')'); + return expression; + } + fail(65, 'pcd_parse_error:malformed_expression'); + } + + function parseBinary(minPrecedence) { + let left = parsePrimary(); + while (peek() && peek().type === 'op' && precedence[peek().value] >= minPrecedence) { + const operator = consume().value; + const operatorPrecedence = precedence[operator]; + const right = parseBinary(operatorPrecedence + 1); + left = { type: 'BinaryExpression', operator, left, right }; + } + return left; + } + + const expression = parseBinary(1); + if (index !== tokens.length) { + fail(65, 'pcd_parse_error:malformed_expression'); + } + return expression; +} + +function parseStatements(body, params) { + const statements = []; + let index = 0; + + function skipWhitespace() { + while (index < body.length && /\s/.test(body[index])) index += 1; + } + + function readBalanced(openChar, closeChar) { + if (body[index] !== openChar) fail(65, 'pcd_parse_error:malformed_block'); + let depth = 0; + const start = index; + for (; index < body.length; index += 1) { + if (body[index] === openChar) depth += 1; + if (body[index] === closeChar) { + depth -= 1; + if (depth === 0) { + const content = body.slice(start + 1, index); + index += 1; + return content; + } + } + } + fail(65, 'pcd_parse_error:unclosed_block'); + } + + while (index < body.length) { + skipWhitespace(); + if (index >= body.length) break; + if (body.slice(index).startsWith('return')) { + index += 'return'.length; + const semi = body.indexOf(';', index); + if (semi === -1) fail(65, 'pcd_parse_error:missing_return_semicolon'); + const value = body.slice(index, semi).trim(); + if (!value) fail(65, 'pcd_parse_error:missing_return_value'); + statements.push({ type: 'ReturnStatement', argument: parseExpression(value, params) }); + index = semi + 1; + continue; + } + if (body.slice(index).startsWith('if')) { + index += 'if'.length; + skipWhitespace(); + const condition = readBalanced('(', ')').trim(); + skipWhitespace(); + const consequentBody = readBalanced('{', '}'); + skipWhitespace(); + let alternate = []; + if (body.slice(index).startsWith('else')) { + index += 'else'.length; + skipWhitespace(); + alternate = parseStatements(readBalanced('{', '}'), params); + } + statements.push({ + type: 'IfStatement', + condition: parseExpression(condition, params), + consequent: parseStatements(consequentBody, params), + alternate, + }); + continue; + } + fail(65, 'pcd_parse_error:unsupported_statement'); + } + return statements; +} + +function collectReturns(statements, values = []) { + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + values.push(statement.argument); + } + if (statement.type === 'IfStatement') { + collectReturns(statement.consequent, values); + collectReturns(statement.alternate, values); + } + } + return values; +} + +function countBranches(statements) { + return statements.reduce((count, statement) => { + if (statement.type !== 'IfStatement') return count; + return count + 1 + countBranches(statement.consequent) + countBranches(statement.alternate); + }, 0); +} + function parsePcd(source) { if (source.length === 0 || source.trim().length === 0) { fail(65, 'pcd_empty'); @@ -202,34 +414,50 @@ function parsePcd(source) { } fail(65, 'pcd_parse_error:missing_pc_block'); } - const [, pcName, pcBody] = pcMatch; - const fnMatch = pcBody.match(/\bfn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{([\s\S]*)\}\s*$/m); + const pcStart = stripped.search(/\bPC\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m); + const pcOpen = stripped.indexOf('{', pcStart); + const pcClose = findMatchingBrace(stripped, pcOpen); + if (pcClose === -1 || stripped.slice(pcClose + 1).trim().length > 0) { + fail(65, 'pcd_parse_error:malformed_pc_block'); + } + const pcName = pcMatch[1]; + const pcBody = stripped.slice(pcOpen + 1, pcClose); + const fnMatch = pcBody.match(/\bfn\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{/m); if (!fnMatch) { fail(65, 'pcd_parse_error:missing_fn_block'); } - const [, fnName, paramsRaw, fnBody] = fnMatch; + const fnStart = fnMatch.index; + const fnOpen = pcBody.indexOf('{', fnStart); + const fnClose = findMatchingBrace(pcBody, fnOpen); + if (fnClose === -1 || pcBody.slice(fnClose + 1).trim().length > 0) { + fail(65, 'pcd_parse_error:malformed_fn_block'); + } + const [, fnName, paramsRaw] = fnMatch; + const fnBody = pcBody.slice(fnOpen + 1, fnClose); const params = paramsRaw .split(',') .map((param) => param.trim()) .filter(Boolean); - const returns = [...fnBody.matchAll(/\breturn\s+(-?\d+)\s*;/g)].map((match) => Number(match[1])); + if (params.length > 1) { + fail(65, 'pcd_parse_error:too_many_params_beta8'); + } + if (params.some((param) => !/^[A-Za-z_][A-Za-z0-9_]*$/.test(param))) { + fail(65, 'pcd_parse_error:invalid_param'); + } + const body = parseStatements(fnBody, params); + const returns = collectReturns(body); if (returns.length === 0) { fail(65, 'pcd_parse_error:missing_return'); } - const unsupported = fnBody - .replace(/\bif\s*\([^)]*\)\s*\{/g, '') - .replace(/\breturn\s+-?\d+\s*;/g, '') - .replace(/[{}\s;]/g, ''); - if (unsupported.length > 0) { - fail(65, 'pcd_parse_error:unsupported_tokens'); - } return { schemaVersion: 'brik64.cli_ast.v1', pcName, fnName, params, - returnValues: returns, - branchCount: (fnBody.match(/\bif\s*\(/g) || []).length, + body, + returnValues: returns.map((expression) => (expression.type === 'NumberLiteral' ? expression.value : null)), + branchCount: countBranches(body), + expressionDialect: 'brik64.cli_expr.v1', }; } @@ -443,7 +671,7 @@ function login(args = []) { const parsed = parseArgs(args, { '--token-env': 'value' }); const envName = parsed['--token-env']; if (!envName) { - fail(64, 'login_requires_token_env_for_beta7'); + fail(64, 'login_requires_token_env_for_beta8'); } const token = process.env[envName]; if (!token) { @@ -507,27 +735,176 @@ function encodedAst(ast) { return JSON.stringify(ast); } +function renderExpression(expression, target) { + if (expression.type === 'NumberLiteral') return String(expression.value); + if (expression.type === 'Identifier') return expression.name; + if (expression.type === 'UnaryExpression') return `(-${renderExpression(expression.argument, target)})`; + if (expression.type === 'BinaryExpression') { + const left = renderExpression(expression.left, target); + const right = renderExpression(expression.right, target); + let operator = expression.operator; + if (target === 'ts' && operator === '==') operator = '==='; + if (target === 'ts' && operator === '!=') operator = '!=='; + if (target === 'python' && operator === '&&') operator = 'and'; + if (target === 'python' && operator === '||') operator = 'or'; + return `(${left} ${operator} ${right})`; + } + fail(70, 'internal_codegen_error:unknown_expression'); +} + +function renderStatements(statements, target, indentLevel) { + const unit = target === 'python' ? ' ' : ' '; + const indent = unit.repeat(indentLevel); + const lines = []; + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + lines.push(`${indent}return ${renderExpression(statement.argument, target)}${target === 'python' ? '' : ';'}`); + continue; + } + if (statement.type === 'IfStatement') { + const condition = renderExpression(statement.condition, target); + if (target === 'python') { + lines.push(`${indent}if ${condition}:`); + lines.push(...renderStatements(statement.consequent, target, indentLevel + 1)); + if (statement.alternate.length > 0) { + lines.push(`${indent}else:`); + lines.push(...renderStatements(statement.alternate, target, indentLevel + 1)); + } + } else { + lines.push(`${indent}if ${condition} {`); + lines.push(...renderStatements(statement.consequent, target, indentLevel + 1)); + if (statement.alternate.length > 0) { + lines.push(`${indent}} else {`); + lines.push(...renderStatements(statement.alternate, target, indentLevel + 1)); + } + lines.push(`${indent}}`); + } + continue; + } + fail(70, 'internal_codegen_error:unknown_statement'); + } + return lines; +} + +function evaluateExpression(expression, env) { + if (expression.type === 'NumberLiteral') return expression.value; + if (expression.type === 'Identifier') return env[expression.name] ?? 0; + if (expression.type === 'UnaryExpression') return -evaluateExpression(expression.argument, env); + if (expression.type === 'BinaryExpression') { + const left = evaluateExpression(expression.left, env); + if (expression.operator === '&&') return Boolean(left) && Boolean(evaluateExpression(expression.right, env)); + if (expression.operator === '||') return Boolean(left) || Boolean(evaluateExpression(expression.right, env)); + const right = evaluateExpression(expression.right, env); + if (expression.operator === '+') return left + right; + if (expression.operator === '-') return left - right; + if (expression.operator === '*') return left * right; + if (expression.operator === '/') return Math.trunc(left / right); + if (expression.operator === '%') return left % right; + if (expression.operator === '==') return left === right; + if (expression.operator === '!=') return left !== right; + if (expression.operator === '>') return left > right; + if (expression.operator === '<') return left < right; + if (expression.operator === '>=') return left >= right; + if (expression.operator === '<=') return left <= right; + } + fail(70, 'internal_eval_error:unknown_expression'); +} + +function evaluateStatements(statements, env) { + for (const statement of statements) { + if (statement.type === 'ReturnStatement') { + return evaluateExpression(statement.argument, env); + } + if (statement.type === 'IfStatement') { + if (evaluateExpression(statement.condition, env)) { + const consequent = evaluateStatements(statement.consequent, env); + if (consequent !== undefined) return consequent; + } else { + const alternate = evaluateStatements(statement.alternate, env); + if (alternate !== undefined) return alternate; + } + } + } + return undefined; +} + +function collectConditionValues(expression, values = new Set([0, 1, 2, 10])) { + if (expression.type === 'NumberLiteral') { + values.add(expression.value); + values.add(expression.value + 1); + values.add(expression.value - 1); + } + if (expression.type === 'UnaryExpression') collectConditionValues(expression.argument, values); + if (expression.type === 'BinaryExpression') { + collectConditionValues(expression.left, values); + collectConditionValues(expression.right, values); + } + return values; +} + +function collectStatementValues(statements, values = new Set([0, 1, 2, 10])) { + for (const statement of statements) { + if (statement.type === 'IfStatement') { + collectConditionValues(statement.condition, values); + collectStatementValues(statement.consequent, values); + collectStatementValues(statement.alternate, values); + } + } + return values; +} + +function generatedCases(ast) { + const param = ast.params[0] || 'input'; + const inputs = [...collectStatementValues(ast.body)] + .filter((value) => Number.isInteger(value) && Math.abs(value) < 100000) + .slice(0, 12); + return inputs + .map((input) => ({ input, expected: evaluateStatements(ast.body, { [param]: input }) })) + .filter((testCase) => testCase.expected !== undefined) + .slice(0, 8); +} + +function ensureExecutable(ast) { + const cases = generatedCases(ast); + if (cases.length === 0) { + fail(65, 'pcd_parse_error:no_executable_return_path'); + } + return cases; +} + function targetSpec(target, ast) { const astJson = encodedAst(ast); + const cases = ensureExecutable(ast); + const param = ast.params[0] || 'input'; + const tsStatements = renderStatements(ast.body, 'ts', 1); + const rustStatements = renderStatements(ast.body, 'rust', 1); + const pythonStatements = renderStatements(ast.body, 'python', 1); const specs = { ts: { - program: 'program.ts', - test: 'program.test.ts', + program: 'program.mjs', + test: 'program.test.mjs', code: (hash) => [ - '// BRIK64 beta7 functional emission candidate', + '// BRIK64 beta8 functional emission candidate', '// claim: local candidate evidence only', `export const pcdSha256 = "${hash}";`, - `export const pcdAst = ${astJson} as const;`, - 'export function run(input = 0): string {', - ' return `brik:${pcdAst.pcName}:${pcdAst.fnName}:${pcdAst.returnValues.join(",")}:${input}:${pcdSha256}`;', + `export const pcdAst = ${astJson};`, + `export function run(${param} = 0) {`, + ...tsStatements, + ' throw new Error("pcd execution reached non-returning path");', '}', '', ].join('\n'), testCode: (hash) => [ - 'import { pcdAst, pcdSha256, run } from "./program";', + 'import { pcdSha256, run } from "./program.mjs";', '', 'if (pcdSha256 !== "' + hash + '") throw new Error("pcd hash mismatch");', - 'if (!run().includes(pcdAst.pcName)) throw new Error("run mismatch");', + `const cases = ${JSON.stringify(cases)};`, + 'for (const testCase of cases) {', + ' const actual = run(testCase.input);', + ' if (actual !== testCase.expected) {', + ' throw new Error(`case ${testCase.input} expected ${testCase.expected} got ${actual}`);', + ' }', + '}', 'console.log("brik64 generated ts test: PASS");', '', ].join('\n'), @@ -536,25 +913,28 @@ function targetSpec(target, ast) { program: 'program.rs', test: 'program_test.rs', code: (hash) => [ - '// BRIK64 beta7 functional emission candidate', + '// BRIK64 beta8 functional emission candidate', '// claim: local candidate evidence only', `pub const PCD_SHA256: &str = "${hash}";`, `pub const PCD_AST_JSON: &str = r#"${astJson}"#;`, - 'pub fn run() -> String {', - ' format!("brik:{}:{}", PCD_AST_JSON, PCD_SHA256)', + `pub fn run(${param}: i64) -> i64 {`, + ...rustStatements.map((line) => line.replace(/^ /, ' ')), + ' panic!("pcd execution reached non-returning path");', '}', '', ].join('\n'), testCode: (hash) => [ `const PCD_SHA256: &str = "${hash}";`, `const PCD_AST_JSON: &str = r#"${astJson}"#;`, - 'fn run() -> String {', - ' format!("brik:{}:{}", PCD_AST_JSON, PCD_SHA256)', + `fn run(${param}: i64) -> i64 {`, + ...rustStatements.map((line) => line.replace(/^ /, ' ')), + ' panic!("pcd execution reached non-returning path");', '}', '', 'fn main() {', ` assert_eq!(PCD_SHA256, "${hash}");`, - ' assert!(run().contains(PCD_AST_JSON));', + ' assert!(PCD_AST_JSON.contains("body"));', + ...cases.map((testCase) => ` assert_eq!(run(${testCase.input}), ${testCase.expected});`), ' println!("brik64 generated rust test: PASS");', '}', '', @@ -564,20 +944,24 @@ function targetSpec(target, ast) { program: 'program.py', test: 'test_program.py', code: (hash) => [ - '# BRIK64 beta7 functional emission candidate', + '# BRIK64 beta8 functional emission candidate', '# claim: local candidate evidence only', `PCD_SHA256 = "${hash}"`, - `PCD_AST = ${astJson}`, + `PCD_AST_JSON = ${JSON.stringify(JSON.stringify(ast))}`, '', - 'def run(input=0):', - ' return f"brik:{PCD_AST[\'pcName\']}:{PCD_AST[\'fnName\']}:{PCD_AST[\'returnValues\']}:{input}:{PCD_SHA256}"', + `def run(${param}=0):`, + ...pythonStatements, + ' raise RuntimeError("pcd execution reached non-returning path")', '', ].join('\n'), testCode: (hash) => [ - 'from program import PCD_AST, PCD_SHA256, run', + 'from program import PCD_SHA256, run', '', `assert PCD_SHA256 == "${hash}"`, - 'assert PCD_AST["pcName"] in run()', + `cases = ${JSON.stringify(cases)}`, + 'for case in cases:', + ' actual = run(case["input"])', + ' assert actual == case["expected"], f"case {case[\'input\']} expected {case[\'expected\']} got {actual}"', 'print("brik64 generated python test: PASS")', '', ].join('\n'), @@ -652,7 +1036,7 @@ function emit(file, args = []) { if (options.tests) process.stdout.write(`tests=${path.relative(process.cwd(), testPath)}\n`); return; } - process.stdout.write('// BRIK64 beta7 functional emission candidate\n'); + process.stdout.write('// BRIK64 beta8 functional emission candidate\n'); process.stdout.write('// claim: local candidate evidence only\n'); process.stdout.write(`// pcd_sha256=${cert.semantic_pcd_sha256}\n`); process.stdout.write(`// ast_sha256=${cert.ast_sha256}\n`); @@ -666,7 +1050,7 @@ function verify(file, args = []) { } requireLocalOrEntitled(parsed); if (parsed['--cloud']) { - fail(69, 'managed_verify_endpoint_unavailable_beta7'); + fail(69, 'managed_verify_endpoint_unavailable_beta8'); } const source = readFileRequired(file); const ast = parsePcd(source); @@ -714,7 +1098,7 @@ function polymerize(rawArgs = []) { } requireLocalOrEntitled(parsed); if (parsed['--cloud']) { - fail(69, 'managed_polymerize_endpoint_unavailable_beta7'); + fail(69, 'managed_polymerize_endpoint_unavailable_beta8'); } const files = parsed._; if (files.length === 0) { @@ -743,7 +1127,7 @@ function polymerize(rawArgs = []) { const polymerName = 'brik64_polymer'; const content = [ '// brik64.pcd_file.v1', - '// generated_by: brik64-cli beta7 polymerize local', + '// generated_by: brik64-cli beta8 polymerize local', '// claim_boundary: local_candidate_only', ...sourceLines, '', @@ -781,7 +1165,7 @@ function migrate(file, args = []) { const source = readFileRequired(file); const oldHash = sha256(source); let migrated = source; - let syntax = 'beta7'; + let syntax = 'beta8'; if (/\bcircuit\s+[A-Za-z_][A-Za-z0-9_]*\s*\{/m.test(source)) { migrated = migrated.replace(/\bcircuit\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/m, 'PC $1 {'); syntax = 'legacy_circuit'; @@ -799,7 +1183,7 @@ function migrate(file, args = []) { } outPath = inputPath; } else { - outPath = workspacePath(parsed['--out'] || `${file.replace(/\.pcd$/, '')}.beta7.pcd`); + outPath = workspacePath(parsed['--out'] || `${file.replace(/\.pcd$/, '')}.beta8.pcd`); if (fs.existsSync(outPath)) { fail(73, `output_exists:${path.relative(process.cwd(), outPath)}`); } diff --git a/tests/smoke.sh b/tests/smoke.sh index ec6f91b7..a2ecdec6 100755 --- a/tests/smoke.sh +++ b/tests/smoke.sh @@ -9,7 +9,7 @@ cleanup() { rm -rf "$tmpdir"; } trap cleanup EXIT export BRIK64_CONFIG_HOME="$tmpdir/config" -node "$BRIK" --version | grep -q "BRIK64 CLI 0.1.0-beta.7" +node "$BRIK" --version | grep -q "BRIK64 CLI 0.1.0-beta.8" node "$BRIK" --version | node -e 'let s=""; process.stdin.on("data", (d) => { s += d; }); process.stdin.on("end", () => { s = s.replace(/\x1b\[[0-9;]*m/g, ""); if (!s.includes("█████████████") || !s.includes("▒▒▒▒▒▒▒▒▒▒▒▒")) process.exit(1); });' node "$BRIK" --help | grep -q "status=public_beta" node "$BRIK" --help | grep -q "polymerize " @@ -23,10 +23,15 @@ node "$BRIK" engine status | grep -q '"runtimeMode": "portable_bir_bundle"' node "$BRIK" engine status | grep -q '"nativeExecutableIncluded": false' if [ "${BRIK64_RELEASE_GATES:-0}" = "1" ]; then - node "$ROOT_DIR/scripts/beta7-feature-parity-gate.js" | grep -q "decision=PASS_BETA7_FEATURE_PARITY_GATE" - node "$ROOT_DIR/scripts/build-beta7-package.js" | grep -q "PASS_BETA7_PACKAGE_BUILT" - node "$ROOT_DIR/scripts/beta7-package-smoke.js" | grep -q "decision=PASS_BETA7_LOCAL_PACKAGE_SMOKE" - node -e 'const fs=require("fs"); const r=JSON.parse(fs.readFileSync("evidence/beta7-package/package.manifest.json","utf8")); if (r.releaseEligible !== false || !r.requiredPublicReleaseGates.includes("curl_gcp_installer_beta7")) process.exit(1)' + beta8_functionality_out="$(bash "$ROOT_DIR/scripts/beta8-compiler-functionality-gate.sh")" + grep -q "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY" <<<"$beta8_functionality_out" + beta8_adversarial_out="$(bash "$ROOT_DIR/scripts/beta8-adversarial-gate.sh")" + grep -q "PASS_BRIK64_CLI_BETA8_ADVERSARIAL" <<<"$beta8_adversarial_out" + beta8_package_out="$(bash "$ROOT_DIR/scripts/build-beta8-package.sh")" + grep -q "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT" <<<"$beta8_package_out" + beta8_package_smoke_out="$(bash "$ROOT_DIR/scripts/beta8-package-smoke.sh")" + grep -q "decision=PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE" <<<"$beta8_package_smoke_out" + node -e 'const fs=require("fs"); const r=JSON.parse(fs.readFileSync("evidence/beta8-package/package.manifest.json","utf8")); if (r.releaseEligible !== false || !r.requiredPublicReleaseGates.includes("curl_gcp_installer_beta8")) process.exit(1)' node "$ROOT_DIR/scripts/release-manifest-validate.js" --allow-dirty | grep -q "decision=PASS_RELEASE_MANIFEST_VALIDATE" fi @@ -98,8 +103,8 @@ for target in ts rust python; do grep -q "tests=" "/tmp/brik-emit-$target.out" done -test -f "$tmpdir/out-ts/program.ts" -test -f "$tmpdir/out-ts/program.test.ts" +test -f "$tmpdir/out-ts/program.mjs" +test -f "$tmpdir/out-ts/program.test.mjs" test -f "$tmpdir/out-rust/program.rs" test -f "$tmpdir/out-rust/program_test.rs" test -f "$tmpdir/out-python/program.py" @@ -116,7 +121,7 @@ if node "$BRIK" emit program.pcd --target ts --out ../escaped-out --tests >/tmp/ exit 1 fi grep -q "path_outside_workspace" /tmp/brik-out-traversal.err -test ! -e "$tmpdir/escaped-out/program.ts" +test ! -e "$tmpdir/escaped-out/program.mjs" mkdir readonly chmod 500 readonly @@ -134,7 +139,7 @@ fi cp program.pcd stale.pcd node "$BRIK" certify stale.pcd -printf '\n return 3;\n' >> stale.pcd +perl -0pi -e 's/return 2;/return 3;/' stale.pcd if node "$BRIK" emit stale.pcd >/tmp/brik-stale.out 2>/tmp/brik-stale.err; then echo "stale certificate should fail closed" >&2 exit 1 @@ -182,7 +187,7 @@ PC variant { PCD node "$BRIK" certify variant.pcd node "$BRIK" emit variant.pcd --target ts --out out-variant --tests >/tmp/brik-emit-variant.out -if cmp -s out-ts/program.ts out-variant/program.ts; then +if cmp -s out-ts/program.mjs out-variant/program.mjs; then echo "different valid PCDs should emit different outputs" >&2 exit 1 fi From 9450714355b9eda1b4e8d4d1ac5be7c77035a648 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:00:27 +0200 Subject: [PATCH 02/13] Gate beta8 release on verified GitHub signature --- evidence/beta8-adversarial/report.json | 2 +- .../beta8-compiler-functionality/report.json | 2 +- .../report.json | 28 +++++ evidence/beta8-package-smoke/report.json | 2 +- evidence/beta8-package/SHA256SUMS | 6 +- .../beta8-package/brik64-cli-0.1.0-beta.8.tgz | Bin 24501 -> 24482 bytes evidence/beta8-package/package.manifest.json | 5 +- evidence/beta8-package/stage-checksums.tsv | 4 +- .../evidence/beta8-adversarial/report.json | 2 +- .../beta8-compiler-functionality/report.json | 2 +- .../release-manifest-validate/report.json | 10 +- evidence/release-train-dry-run/report.json | 52 +++----- .../release-train-publish-plan/report.json | 35 ++++-- package.json | 1 + .../beta8-github-verified-signature-gate.js | 118 ++++++++++++++++++ scripts/build-beta8-package.sh | 1 + scripts/release-train-dry-run.js | 4 + scripts/release-train-publish-plan.js | 20 +++ 18 files changed, 228 insertions(+), 66 deletions(-) create mode 100644 evidence/beta8-github-verified-signature/report.json create mode 100644 scripts/beta8-github-verified-signature-gate.js diff --git a/evidence/beta8-adversarial/report.json b/evidence/beta8-adversarial/report.json index b092dd00..3e783455 100644 --- a/evidence/beta8-adversarial/report.json +++ b/evidence/beta8-adversarial/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_adversarial_gate.v1", - "generatedAt": "2026-06-06T02:34:44Z", + "generatedAt": "2026-06-06T02:59:47Z", "iter_id": "BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", diff --git a/evidence/beta8-compiler-functionality/report.json b/evidence/beta8-compiler-functionality/report.json index 23c10002..41681edf 100644 --- a/evidence/beta8-compiler-functionality/report.json +++ b/evidence/beta8-compiler-functionality/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_compiler_functionality_gate.v1", - "generatedAt": "2026-06-06T02:34:41Z", + "generatedAt": "2026-06-06T02:59:45Z", "iter_id": "BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", diff --git a/evidence/beta8-github-verified-signature/report.json b/evidence/beta8-github-verified-signature/report.json new file mode 100644 index 00000000..317effa6 --- /dev/null +++ b/evidence/beta8-github-verified-signature/report.json @@ -0,0 +1,28 @@ +{ + "schemaVersion": "brik64.beta8_github_verified_signature_gate.v1", + "generatedAt": "2026-06-06T02:59:56.695Z", + "releaseId": "brik64-0.1.0-beta.8", + "version": "0.1.0-beta.8", + "decision": "BLOCKED_BETA8_GITHUB_VERIFIED_SIGNATURE", + "repo": "brik64/brik64-cli", + "commit": "5fd8fb763ead40f1cc62340ac41f148b031c0679", + "verification": { + "verified": false, + "reason": "unknown_key", + "verifiedAt": null, + "payloadPresent": true + }, + "apiError": null, + "boundary": { + "gateKind": "release_integrity_identity_gate", + "compilerFunctionalityEvidence": false, + "publicReleaseAllowed": false, + "adminOverrideAllowed": false + }, + "failures": [ + "commit_not_github_verified" + ], + "warnings": [ + "verified_at_missing" + ] +} diff --git a/evidence/beta8-package-smoke/report.json b/evidence/beta8-package-smoke/report.json index 4c51ce7b..a8e079a7 100644 --- a/evidence/beta8-package-smoke/report.json +++ b/evidence/beta8-package-smoke/report.json @@ -6,7 +6,7 @@ "lane": "cli_0_1_beta8", "package": { "path": "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", - "sha256": "5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43" + "sha256": "a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65" }, "checks": [ "extract", diff --git a/evidence/beta8-package/SHA256SUMS b/evidence/beta8-package/SHA256SUMS index 15491784..8f8e2972 100644 --- a/evidence/beta8-package/SHA256SUMS +++ b/evidence/beta8-package/SHA256SUMS @@ -1,3 +1,3 @@ -5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43 brik64-cli-0.1.0-beta.8.tgz -45f04c9dde7fa65fd544fa321ccc9edee3ddb11edaac302cee56b0c2a6ea7663 package.manifest.json -fc3af7083e002983162c8b7d556ef4f44dff3f53e7c8e26f21a41160fbb6ed73 stage-checksums.tsv +a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65 brik64-cli-0.1.0-beta.8.tgz +7f5e4a5e84ca2e76f5f30e936955d9416e1640ec6565f7f5c30b467f6d8b30e1 package.manifest.json +0c62821e40e102099311f781a58b16b4f99f36aefb42767ecc0f235769facb56 stage-checksums.tsv diff --git a/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz b/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz index 7c2a9b0ce47dd377da71a320cae9e30a64a4abd4..626285c53641d6561bf9027614f08255b16a8e9d 100644 GIT binary patch literal 24482 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

t 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 diff --git a/evidence/beta8-package/package.manifest.json b/evidence/beta8-package/package.manifest.json index dfce780d..aa5f6cf1 100644 --- a/evidence/beta8-package/package.manifest.json +++ b/evidence/beta8-package/package.manifest.json @@ -7,8 +7,8 @@ "generationClaim": "internal_generation_non_claim", "package": { "path": "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", - "sha256": "5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43", - "bytes": 24501 + "sha256": "a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65", + "bytes": 24482 }, "inputGates": [ "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", @@ -16,6 +16,7 @@ ], "requiredPublicReleaseGates": [ "beta8_package_smoke", + "beta8_github_verified_signature", "platform_smoke", "curl_gcp_installer_beta8", "github_release_beta8", diff --git a/evidence/beta8-package/stage-checksums.tsv b/evidence/beta8-package/stage-checksums.tsv index d12fb788..7c6396eb 100644 --- a/evidence/beta8-package/stage-checksums.tsv +++ b/evidence/beta8-package/stage-checksums.tsv @@ -7,8 +7,8 @@ cf39e055374caeecaac773d9802098a7c1717e271be4b00c25d2a2a9bf157aa1 SECURITY.md 11a5eadb7ec6f7d07e329c767026ae9576bdaf99c1d411781e5f88108e7d852e engines/l4plus-n5/checksums.tsv 221774c3a8f9e1cf630521a12a2a62f265d34313cdeaf7bb30ca69f60bd3a8d8 engines/l4plus-n5/runtime-bundle.manifest.json 6f2a3eff7b3cbf80debb823f1771df5364d6f1fdf2c0b6c2dab8e109c04dc757 engines/l4plus-n5/serial.txt -7bf04f505e50c95e6864d5140c7fc1acab214c2bdef6028bfe382ffc8538e3e7 evidence/beta8-adversarial/report.json -84c5f4c7f6ac016a762cd024d7838eac47d837a7d7042e87b2282cb0ca382259 evidence/beta8-compiler-functionality/report.json +1aeba167082852185c2da91b16b38a91e7c6d802bde2b75aafe043e52e966e9f evidence/beta8-adversarial/report.json +b45842698337fab4a290fa74087c23fcb38524484543c364c836fc3c3898c705 evidence/beta8-compiler-functionality/report.json 3b99b7e885e6bf2d730bd7f4ca3c3bae00270f775523c66150d21d2004e70628 package.json 2a629b0c88a96c81a42f3e5949900798fe25886aec7ac203855ba7540cd3b36c pcd/cli_account_session.pcd ff48eaeb3848e39c5400fcbb9fc293e5fffb649db2e32454f900080be660ef1c pcd/cli_core.pcd diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json index b092dd00..3e783455 100644 --- a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_adversarial_gate.v1", - "generatedAt": "2026-06-06T02:34:44Z", + "generatedAt": "2026-06-06T02:59:47Z", "iter_id": "BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", diff --git a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json index 23c10002..41681edf 100644 --- a/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json +++ b/evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_compiler_functionality_gate.v1", - "generatedAt": "2026-06-06T02:34:41Z", + "generatedAt": "2026-06-06T02:59:45Z", "iter_id": "BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", diff --git a/evidence/release-manifest-validate/report.json b/evidence/release-manifest-validate/report.json index 55ff50a7..d118db0d 100644 --- a/evidence/release-manifest-validate/report.json +++ b/evidence/release-manifest-validate/report.json @@ -22,33 +22,33 @@ "path": "evidence/beta8-compiler-functionality/report.json", "expectedDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", "actualDecision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", - "sha256": "0692904fc600bacf24c79c8400fd9cce55e12a61e25cd350f5b3e7913fee14e3" + "sha256": "0555561fe4be18c21c29837d1447d57df435a7681f58d5baa03ffe981a09d36a" }, { "id": "adversarial", "path": "evidence/beta8-adversarial/report.json", "expectedDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", "actualDecision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", - "sha256": "7e26abb3953de914d5b1746c0a506063d10182416e91a582a0438390a9fef199" + "sha256": "12266b32aef11cf7f014a8a03a6c89c9ecc0ee98ebe0e42ade9916738a0f9e3e" }, { "id": "localPackage", "path": "evidence/beta8-package/package.manifest.json", "expectedDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", "actualDecision": "PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT", - "sha256": "b152172c22de826ae6d92d8c9231d670c6c1722b11fd5237e0196c89625ed493" + "sha256": "854d25296305159f1462431c3797c07cc999456202b9155d972f51220b49c61b" }, { "id": "localPackageSmoke", "path": "evidence/beta8-package-smoke/report.json", "expectedDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", "actualDecision": "PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE", - "sha256": "ffdbabc6f70bbbce9a7027ccfc4cf3b94a271b30532189d3e312d28798707f2f" + "sha256": "140ba1d8860dd8675271cc1a2a15ccbc19a5565fef3bdca29cb1e7fabb96c427" } ] }, "failures": [], "warnings": [ - "worktree_dirty_allowed:38" + "worktree_dirty_allowed:16" ] } diff --git a/evidence/release-train-dry-run/report.json b/evidence/release-train-dry-run/report.json index 888a6861..5245cf0d 100644 --- a/evidence/release-train-dry-run/report.json +++ b/evidence/release-train-dry-run/report.json @@ -9,9 +9,6 @@ "publicationAllowed": false, "boundary": "Dry-run only. This workflow validates manifest, tests and evidence but never publishes public artifacts.", "initialDirtyFiles": [ - ".brik/manifest.json", - "CHANGELOG.md", - "README.md", "evidence/beta8-adversarial/report.json", "evidence/beta8-compiler-functionality/report.json", "evidence/beta8-package-smoke/report.json", @@ -19,81 +16,62 @@ "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", "evidence/beta8-package/package.manifest.json", "evidence/beta8-package/stage-checksums.tsv", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/.brik/manifest.json", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/CHANGELOG.md", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/LICENSE", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/NOTICE", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/README.md", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/SECURITY.md", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/checksums.tsv", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/runtime-bundle.manifest.json", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/engines/l4plus-n5/serial.txt", "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-adversarial/report.json", "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/evidence/beta8-compiler-functionality/report.json", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/package.json", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_account_session.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_core.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_migrate.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymer.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_polymerize.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/pcd/cli_verify.pcd", - "evidence/beta8-package/stage/brik64-cli-0.1.0-beta.8/src/brik.js", + "evidence/release-train-publish-plan/report.json", "package.json", - "release/manifest.json", - "scripts/beta8-adversarial-gate.sh", - "scripts/beta8-compiler-functionality-gate.sh", - "scripts/beta8-package-smoke.sh", "scripts/build-beta8-package.sh", "scripts/release-train-dry-run.js", - "src/brik.js", - "tests/smoke.sh" + "scripts/release-train-publish-plan.js", + "evidence/beta8-github-verified-signature/", + "scripts/beta8-github-verified-signature-gate.js" ], "commands": [ { "name": "manifest_validate", "command": "node scripts/release-manifest-validate.js --allow-dirty", "rc": 0, - "elapsedMs": 151, - "stdout": "decision=PASS_RELEASE_MANIFEST_VALIDATE\nversion=0.1.0-beta.8\nwarnings=worktree_dirty_allowed:38\n", + "elapsedMs": 99, + "stdout": "decision=PASS_RELEASE_MANIFEST_VALIDATE\nversion=0.1.0-beta.8\nwarnings=worktree_dirty_allowed:16\n", "stderr": "" }, { "name": "smoke_tests", "command": "bash -lc bash -x tests/smoke.sh", "rc": 0, - "elapsedMs": 4787, + "elapsedMs": 3381, "stdout": "created=.brik/manifest.json\ncertificate=program.pcd.cert.json\ncertificate=polymer.pcd.cert.json\ncertificate=stale.pcd.cert.json\ncertificate=legacy.beta7.pcd.cert.json\ncertificate=variant.pcd.cert.json\nbrik64-cli bootstrap smoke: PASS\n", - "stderr": "+ set -euo pipefail\n+++ dirname tests/smoke.sh\n++ cd tests/..\n++ pwd\n+ ROOT_DIR=/Users/carlosjperez/Documents/GitHub/brik64-cli\n+ BRIK=/Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js\n++ node -e 'const fs=require(\"fs\"); process.stdout.write(JSON.parse(fs.readFileSync(\"package.json\",\"utf8\")).version)'\n+ PACKAGE_VERSION=0.1.0-beta.8\n++ mktemp -d\n+ tmpdir=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ trap cleanup EXIT\n+ export BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/config\n+ BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/config\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ grep -q 'BRIK64 CLI 0.1.0-beta.8'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ node -e 'let s=\"\"; process.stdin.on(\"data\", (d) => { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 0 = 1 ']'\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-ts/program.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-ts/program.test.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl/escaped-out/program.mjs\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ perl -0pi -e 's/return 2;/return 3;/' stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.mjs out-variant/program.mjs\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.HHi4Uvezkl\n" + "stderr": "+ set -euo pipefail\n+++ dirname tests/smoke.sh\n++ cd tests/..\n++ pwd\n+ ROOT_DIR=/Users/carlosjperez/Documents/GitHub/brik64-cli\n+ BRIK=/Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js\n++ node -e 'const fs=require(\"fs\"); process.stdout.write(JSON.parse(fs.readFileSync(\"package.json\",\"utf8\")).version)'\n+ PACKAGE_VERSION=0.1.0-beta.8\n++ mktemp -d\n+ tmpdir=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n+ trap cleanup EXIT\n+ export BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/config\n+ BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/config\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ grep -q 'BRIK64 CLI 0.1.0-beta.8'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ node -e 'let s=\"\"; process.stdin.on(\"data\", (d) => { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 0 = 1 ']'\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-ts/program.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-ts/program.test.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/escaped-out/program.mjs\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ perl -0pi -e 's/return 2;/return 3;/' stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.mjs out-variant/program.mjs\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n" }, { "name": "beta8_compiler_functionality", "command": "bash scripts/beta8-compiler-functionality-gate.sh", "rc": 0, - "elapsedMs": 2451, - "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_compiler_functionality_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:34:41Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"fixture\": {\n \"path\": \"pcd/branch_math.pcd\",\n \"sha256\": \"sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404\"\n },\n \"executedTargets\": {\n \"typescript\": {\n \"programSha256\": \"sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95\",\n \"test\": \"node out-ts/program.test.mjs\",\n \"passed\": true\n },\n \"rust\": {\n \"programSha256\": \"sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d\",\n \"test\": \"rustc out-rust/program_test.rs && ./out-rust/program_test\",\n \"passed\": true\n },\n \"python\": {\n \"programSha256\": \"sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6\",\n \"test\": \"PYTHONPATH=out-python python3 out-python/test_program.py\",\n \"passed\": true\n }\n },\n \"adversarial\": {\n \"unknown_identifier_fail_closed\": true,\n \"unsupported_target_fail_closed\": true,\n \"path_traversal_fail_closed\": true,\n \"stack_trace_leaked\": false\n },\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"compiler_functionality_claim_allowed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 adversarial gate and package smoke before public release train\"\n}\n", + "elapsedMs": 1910, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_compiler_functionality_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:59:45Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"fixture\": {\n \"path\": \"pcd/branch_math.pcd\",\n \"sha256\": \"sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404\"\n },\n \"executedTargets\": {\n \"typescript\": {\n \"programSha256\": \"sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95\",\n \"test\": \"node out-ts/program.test.mjs\",\n \"passed\": true\n },\n \"rust\": {\n \"programSha256\": \"sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d\",\n \"test\": \"rustc out-rust/program_test.rs && ./out-rust/program_test\",\n \"passed\": true\n },\n \"python\": {\n \"programSha256\": \"sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6\",\n \"test\": \"PYTHONPATH=out-python python3 out-python/test_program.py\",\n \"passed\": true\n }\n },\n \"adversarial\": {\n \"unknown_identifier_fail_closed\": true,\n \"unsupported_target_fail_closed\": true,\n \"path_traversal_fail_closed\": true,\n \"stack_trace_leaked\": false\n },\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"compiler_functionality_claim_allowed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 adversarial gate and package smoke before public release train\"\n}\n", "stderr": "" }, { "name": "beta8_adversarial", "command": "bash scripts/beta8-adversarial-gate.sh", "rc": 0, - "elapsedMs": 2685, - "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_adversarial_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:34:44Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_ADVERSARIAL\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"executableEdgeFixture\": {\n \"path\": \"pcd/edge_precedence.pcd\",\n \"sha256\": \"sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63\"\n },\n \"passChecks\": 9,\n \"failClosedChecks\": 12,\n \"generatedTargetExecution\": {\n \"typescript\": true,\n \"rust\": true,\n \"python\": true\n },\n \"failClosedSurface\": [\n \"empty_pcd\",\n \"binary_input\",\n \"too_large_input\",\n \"legacy_syntax\",\n \"missing_fn\",\n \"too_many_params\",\n \"invalid_param\",\n \"missing_return\",\n \"unsupported_statement\",\n \"unsupported_expression_token\",\n \"malformed_expression\",\n \"unclosed_block\"\n ],\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"adversarial_gate_passed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 package smoke and release-train sync gates\"\n}\n", + "elapsedMs": 1799, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_adversarial_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:59:47Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_ADVERSARIAL\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"executableEdgeFixture\": {\n \"path\": \"pcd/edge_precedence.pcd\",\n \"sha256\": \"sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63\"\n },\n \"passChecks\": 9,\n \"failClosedChecks\": 12,\n \"generatedTargetExecution\": {\n \"typescript\": true,\n \"rust\": true,\n \"python\": true\n },\n \"failClosedSurface\": [\n \"empty_pcd\",\n \"binary_input\",\n \"too_large_input\",\n \"legacy_syntax\",\n \"missing_fn\",\n \"too_many_params\",\n \"invalid_param\",\n \"missing_return\",\n \"unsupported_statement\",\n \"unsupported_expression_token\",\n \"malformed_expression\",\n \"unclosed_block\"\n ],\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"adversarial_gate_passed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 package smoke and release-train sync gates\"\n}\n", "stderr": "" }, { "name": "beta8_local_package", "command": "bash scripts/build-beta8-package.sh", "rc": 0, - "elapsedMs": 733, - "stdout": "decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz\nsha256=5dbbde5e1a02da2815366b30361951c3fbbffb73bcac55e93aa6cb09525e9a43\n", + "elapsedMs": 438, + "stdout": "decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz\nsha256=a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65\n", "stderr": "" }, { "name": "beta8_package_smoke", "command": "bash scripts/beta8-package-smoke.sh", "rc": 0, - "elapsedMs": 2349, + "elapsedMs": 1167, "stdout": "decision=PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE\nchecks=13\n", "stderr": "" } diff --git a/evidence/release-train-publish-plan/report.json b/evidence/release-train-publish-plan/report.json index 75f64724..5b0a32c0 100644 --- a/evidence/release-train-publish-plan/report.json +++ b/evidence/release-train-publish-plan/report.json @@ -1,13 +1,13 @@ { "schemaVersion": "brik64.release_train_publish_plan.v1", - "releaseId": "brik64-0.1.0-beta.7", - "version": "0.1.0-beta.7", - "manifestDigest": "7f786abdfa7e098778d1a141ea393da386e22144b9d213836e1bd8747acbbcb8", - "decision": "PASS_PUBLISH_PLAN_DRY_RUN", + "releaseId": "brik64-0.1.0-beta.8", + "version": "0.1.0-beta.8", + "manifestDigest": "959a0c50560613529b80d12534d2c8ef1f5ce47a52449cc906f0c687edf9a585", + "decision": "FAIL_PUBLISH_PREFLIGHT", "dryRunInProgress": false, "publishRequested": false, "publicationAllowed": false, - "expectedConfirm": "PUBLISH 0.1.0-beta.7 7f786abdfa7e098778d1a141ea393da386e22144b9d213836e1bd8747acbbcb8", + "expectedConfirm": "PUBLISH 0.1.0-beta.8 959a0c50560613529b80d12534d2c8ef1f5ce47a52449cc906f0c687edf9a585", "secretAvailability": { "BRIK64_GITHUB_RELEASE_TOKEN": false, "BRIK64_NPM_TOKEN": false, @@ -20,29 +20,36 @@ "BRIK64_GCP_WORKLOAD_IDENTITY_PROVIDER": false, "BRIK64_GCP_SERVICE_ACCOUNT": false }, + "signatureReport": { + "path": "evidence/beta8-github-verified-signature/report.json", + "decision": "BLOCKED_BETA8_GITHUB_VERIFIED_SIGNATURE", + "commit": "5fd8fb763ead40f1cc62340ac41f148b031c0679", + "verified": false, + "reason": "unknown_key" + }, "commands": [ { "name": "github_release", "description": "Create or update the GitHub Release from the manifest version and upload committed assets.", - "command": "gh release view v0.1.0-beta.7 --repo brik64/brik64-cli || gh release create v0.1.0-beta.7 --repo brik64/brik64-cli --title \"BRIK64 CLI 0.1.0-beta.7\" --notes-file CHANGELOG.md && gh release upload v0.1.0-beta.7 --repo brik64/brik64-cli --clobber evidence/beta7-package/brik64-cli-0.1.0-beta.7.tgz evidence/beta7-package/package.manifest.json evidence/beta7-package/SHA256SUMS", + "command": "gh release view v0.1.0-beta.8 --repo brik64/brik64-cli || gh release create v0.1.0-beta.8 --repo brik64/brik64-cli --title \"BRIK64 CLI 0.1.0-beta.8\" --notes-file CHANGELOG.md && gh release upload v0.1.0-beta.8 --repo brik64/brik64-cli --clobber evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz evidence/beta8-package/package.manifest.json evidence/beta8-package/SHA256SUMS", "mutatesPublicSurface": true }, { "name": "sdk_npm", "description": "Publish the TypeScript SDK package with the manifest beta version.", - "command": "npm view @brik64/core@0.1.0-beta.7 version >/dev/null 2>&1 || npm publish --tag beta /Users/carlosjperez/Documents/GitHub/brik64-lib-js/evidence-beta7-pack/brik64-core-0.1.0-beta.7.tgz", + "command": "npm view @brik64/core@0.1.0-beta.8 version >/dev/null 2>&1 || npm publish --tag beta /Users/carlosjperez/Documents/GitHub/brik64-lib-js/evidence-beta8-pack/brik64-core-0.1.0-beta.8.tgz", "mutatesPublicSurface": true }, { "name": "sdk_pypi", "description": "Publish the Python SDK package with twine.", - "command": "python3 - <<'PY' || python3 -m twine upload /Users/carlosjperez/Documents/GitHub/brik64-lib-python/dist/brik64-0.1.0b7*\nimport urllib.request\nurllib.request.urlopen('https://pypi.org/pypi/brik64/0.1.0b7/json', timeout=20).close()\nPY", + "command": "python3 - <<'PY' || python3 -m twine upload /Users/carlosjperez/Documents/GitHub/brik64-lib-python/dist/brik64-0.1.0b8*\nimport urllib.request\nurllib.request.urlopen('https://pypi.org/pypi/brik64/0.1.0b8/json', timeout=20).close()\nPY", "mutatesPublicSurface": true }, { "name": "sdk_crates", "description": "Publish the Rust SDK crate.", - "command": "cargo info brik64-core@0.1.0-beta.7 >/dev/null 2>&1 || cargo publish --manifest-path /Users/carlosjperez/Documents/GitHub/brik64-lib-rust/Cargo.toml --token \"$BRIK64_CRATES_TOKEN\"", + "command": "cargo info brik64-core@0.1.0-beta.8 >/dev/null 2>&1 || cargo publish --manifest-path /Users/carlosjperez/Documents/GitHub/brik64-lib-rust/Cargo.toml --token \"$BRIK64_CRATES_TOKEN\"", "mutatesPublicSurface": true }, { @@ -78,14 +85,18 @@ ], "rollback": [ "Do not delete historical release artifacts.", - "If any channel fails after publication begins, create a superseding manifest with state \"failed\" for 0.1.0-beta.7.", + "If any channel fails after publication begins, create a superseding manifest with state \"failed\" for 0.1.0-beta.8.", "Restore curl/GCP channel manifest to the previous known-good manifest object.", "Create a GitHub Release note amendment that points to the superseding manifest.", "Run release-train-live-verify and keep the failed report as evidence." ], - "failures": [], + "failures": [ + "manifest_state_not_public:draft", + "beta8_github_verified_signature_not_pass:BLOCKED_BETA8_GITHUB_VERIFIED_SIGNATURE" + ], "warnings": [ - "pre_publish_live_verify_manifest_digest_drift" + "pre_publish_live_verify_manifest_digest_drift", + "manifest_source_commit_not_ancestor:2673a5b:5fd8fb7" ], "boundary": "This script generates and verifies the publication plan. It never mutates public surfaces directly." } diff --git a/package.json b/package.json index c897fa40..fa00d28c 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "gate:beta7:skills-sync": "node scripts/beta7-skills-sync-gate.js", "gate:beta8:compiler-functionality": "bash scripts/beta8-compiler-functionality-gate.sh", "gate:beta8:adversarial": "bash scripts/beta8-adversarial-gate.sh", + "gate:beta8:github-verified-signature": "node scripts/beta8-github-verified-signature-gate.js", "package:beta8:local": "bash scripts/build-beta8-package.sh", "smoke:beta8:package": "bash scripts/beta8-package-smoke.sh", "release:manifest:validate": "node scripts/release-manifest-validate.js", diff --git a/scripts/beta8-github-verified-signature-gate.js b/scripts/beta8-github-verified-signature-gate.js new file mode 100644 index 00000000..a282f0ea --- /dev/null +++ b/scripts/beta8-github-verified-signature-gate.js @@ -0,0 +1,118 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const childProcess = require('child_process'); + +const root = path.resolve(__dirname, '..'); +const outDir = path.join(root, 'evidence', 'beta8-github-verified-signature'); + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function argValue(name, fallback) { + const index = process.argv.indexOf(name); + return index === -1 ? fallback : process.argv[index + 1] || fallback; +} + +function gitOutput(args) { + return childProcess.execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim(); +} + +function runGhVerification(repo, commit) { + const result = childProcess.spawnSync('gh', ['api', `repos/${repo}/commits/${commit}`, '--jq', '.commit.verification'], { + cwd: root, + encoding: 'utf8', + env: process.env + }); + if (result.status !== 0) { + return { + ok: false, + apiError: (result.stderr || result.stdout || '').trim(), + payload: null + }; + } + try { + return { + ok: true, + apiError: '', + payload: JSON.parse(result.stdout) + }; + } catch (error) { + return { + ok: false, + apiError: `github_verification_parse_error:${error.message}`, + payload: null + }; + } +} + +function readFixture(file) { + try { + return { + ok: true, + apiError: '', + payload: JSON.parse(fs.readFileSync(path.resolve(root, file), 'utf8')) + }; + } catch (error) { + return { + ok: false, + apiError: `verification_fixture_error:${error.message}`, + payload: null + }; + } +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const repo = argValue('--repo', process.env.BRIK64_GITHUB_REPO || 'brik64/brik64-cli'); + const commit = argValue('--commit', process.env.BRIK64_RELEASE_COMMIT || gitOutput(['rev-parse', 'HEAD'])); + const fixture = argValue('--verification-json', ''); + const failures = []; + const warnings = []; + + if (!/^[0-9a-f]{40}$/.test(commit)) failures.push('commit_sha_invalid'); + + const source = fixture ? readFixture(fixture) : failures.length === 0 ? runGhVerification(repo, commit) : { ok: false, apiError: '', payload: null }; + if (!source.ok) failures.push('github_verification_unavailable'); + const verification = source.payload || {}; + if (source.ok && verification.verified !== true) failures.push('commit_not_github_verified'); + if (source.ok && !verification.verified_at) warnings.push('verified_at_missing'); + + const report = { + schemaVersion: 'brik64.beta8_github_verified_signature_gate.v1', + generatedAt: new Date().toISOString(), + releaseId: 'brik64-0.1.0-beta.8', + version: '0.1.0-beta.8', + decision: failures.length === 0 + ? 'PASS_BETA8_GITHUB_VERIFIED_SIGNATURE' + : 'BLOCKED_BETA8_GITHUB_VERIFIED_SIGNATURE', + repo, + commit, + verification: { + verified: verification.verified === true, + reason: verification.reason || '', + verifiedAt: verification.verified_at || null, + payloadPresent: Boolean(verification.payload) + }, + apiError: source.apiError || null, + boundary: { + gateKind: 'release_integrity_identity_gate', + compilerFunctionalityEvidence: false, + publicReleaseAllowed: failures.length === 0, + adminOverrideAllowed: false + }, + failures, + warnings + }; + + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`publicReleaseAllowed=${report.boundary.publicReleaseAllowed}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (warnings.length > 0) process.stdout.write(`warnings=${warnings.join(',')}\n`); + if (failures.length > 0) process.exit(2); +} + +main(); diff --git a/scripts/build-beta8-package.sh b/scripts/build-beta8-package.sh index 4111dcaf..b259e7da 100644 --- a/scripts/build-beta8-package.sh +++ b/scripts/build-beta8-package.sh @@ -138,6 +138,7 @@ jq -n \ ], requiredPublicReleaseGates:[ "beta8_package_smoke", + "beta8_github_verified_signature", "platform_smoke", "curl_gcp_installer_beta8", "github_release_beta8", diff --git a/scripts/release-train-dry-run.js b/scripts/release-train-dry-run.js index 1945b59f..a795a526 100644 --- a/scripts/release-train-dry-run.js +++ b/scripts/release-train-dry-run.js @@ -135,11 +135,15 @@ function manifestDrivenBetaCommands(manifest, canAccessSiblingRepos) { } if (betaNumber(manifest.version) === 8) { + const enforceSignature = manifest.state !== 'draft' || process.env.BRIK64_REQUIRE_GITHUB_VERIFIED_SIGNATURE === '1'; return [ run('beta8_compiler_functionality', ['bash', 'scripts/beta8-compiler-functionality-gate.sh']), run('beta8_adversarial', ['bash', 'scripts/beta8-adversarial-gate.sh']), run('beta8_local_package', ['bash', 'scripts/build-beta8-package.sh']), run('beta8_package_smoke', ['bash', 'scripts/beta8-package-smoke.sh']), + ...(enforceSignature + ? [run('beta8_github_verified_signature', ['node', 'scripts/beta8-github-verified-signature-gate.js'])] + : []), ...(canAccessSiblingRepos ? [] : []) diff --git a/scripts/release-train-publish-plan.js b/scripts/release-train-publish-plan.js index 564f2677..df3998b2 100644 --- a/scripts/release-train-publish-plan.js +++ b/scripts/release-train-publish-plan.js @@ -64,8 +64,19 @@ function main() { const packagePath = packageManifest.package.path; const jsSdkPackDir = `evidence-${label}-pack`; const pythonSdkVersion = manifest.sdks.find((sdk) => sdk.marketplace === 'pypi').version; + const signatureReportPath = path.join(root, 'evidence', `${label}-github-verified-signature`, 'report.json'); + const signatureReport = fs.existsSync(signatureReportPath) ? readJson(signatureReportPath) : null; if (manifest.state !== 'public') failures.push(`manifest_state_not_public:${manifest.state}`); + if (label === 'beta8') { + if (!signatureReport) { + failures.push('beta8_github_verified_signature_report_missing'); + } else if (signatureReport.decision !== 'PASS_BETA8_GITHUB_VERIFIED_SIGNATURE') { + failures.push(`beta8_github_verified_signature_not_pass:${signatureReport.decision}`); + } else if (signatureReport.boundary?.publicReleaseAllowed !== true) { + failures.push('beta8_github_verified_signature_public_release_not_allowed'); + } + } if (!dryRunInProgress && dryRun.decision !== 'PASS_RELEASE_TRAIN_DRY_RUN') failures.push(`dry_run_not_green:${dryRun.decision}`); if (!dryRunInProgress && dryRun.manifestDigest !== manifestDigest) failures.push('dry_run_manifest_digest_drift'); if (dryRunInProgress) warnings.push('dry_run_report_currently_being_generated'); @@ -189,6 +200,15 @@ PY`, publicationAllowed: publishRequested && failures.length === 0, expectedConfirm, secretAvailability, + signatureReport: signatureReport + ? { + path: path.relative(root, signatureReportPath), + decision: signatureReport.decision, + commit: signatureReport.commit, + verified: signatureReport.verification?.verified === true, + reason: signatureReport.verification?.reason || '' + } + : null, commands, rollback, failures, From 1eb181dd8975152b2d5f4c51b2a36a83688b034a Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:05:13 +0200 Subject: [PATCH 03/13] Ignore generated beta8 signature report --- .gitignore | 1 + .../report.json | 28 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 evidence/beta8-github-verified-signature/report.json diff --git a/.gitignore b/.gitignore index 0e1edca6..749fa9dd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ node_modules/ *.log .DS_Store evidence/tmp/ +evidence/beta8-github-verified-signature/ evidence/beta5-package/stage/ runner-env.local.sh *.secret diff --git a/evidence/beta8-github-verified-signature/report.json b/evidence/beta8-github-verified-signature/report.json deleted file mode 100644 index 317effa6..00000000 --- a/evidence/beta8-github-verified-signature/report.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "schemaVersion": "brik64.beta8_github_verified_signature_gate.v1", - "generatedAt": "2026-06-06T02:59:56.695Z", - "releaseId": "brik64-0.1.0-beta.8", - "version": "0.1.0-beta.8", - "decision": "BLOCKED_BETA8_GITHUB_VERIFIED_SIGNATURE", - "repo": "brik64/brik64-cli", - "commit": "5fd8fb763ead40f1cc62340ac41f148b031c0679", - "verification": { - "verified": false, - "reason": "unknown_key", - "verifiedAt": null, - "payloadPresent": true - }, - "apiError": null, - "boundary": { - "gateKind": "release_integrity_identity_gate", - "compilerFunctionalityEvidence": false, - "publicReleaseAllowed": false, - "adminOverrideAllowed": false - }, - "failures": [ - "commit_not_github_verified" - ], - "warnings": [ - "verified_at_missing" - ] -} From 76fddffbd9db3c905c9a0adffdb4216fe64b41d3 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:13:38 +0200 Subject: [PATCH 04/13] Bind beta8 signature report to release commit --- scripts/release-train-publish-plan.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/release-train-publish-plan.js b/scripts/release-train-publish-plan.js index df3998b2..96eee880 100644 --- a/scripts/release-train-publish-plan.js +++ b/scripts/release-train-publish-plan.js @@ -66,6 +66,8 @@ function main() { const pythonSdkVersion = manifest.sdks.find((sdk) => sdk.marketplace === 'pypi').version; const signatureReportPath = path.join(root, 'evidence', `${label}-github-verified-signature`, 'report.json'); const signatureReport = fs.existsSync(signatureReportPath) ? readJson(signatureReportPath) : null; + const currentHead = gitOutput(['rev-parse', '--short', 'HEAD']); + const currentHeadFull = gitOutput(['rev-parse', 'HEAD']); if (manifest.state !== 'public') failures.push(`manifest_state_not_public:${manifest.state}`); if (label === 'beta8') { @@ -75,6 +77,8 @@ function main() { failures.push(`beta8_github_verified_signature_not_pass:${signatureReport.decision}`); } else if (signatureReport.boundary?.publicReleaseAllowed !== true) { failures.push('beta8_github_verified_signature_public_release_not_allowed'); + } else if (signatureReport.commit !== currentHeadFull) { + failures.push(`beta8_github_verified_signature_commit_drift:${signatureReport.commit}:${currentHeadFull}`); } } if (!dryRunInProgress && dryRun.decision !== 'PASS_RELEASE_TRAIN_DRY_RUN') failures.push(`dry_run_not_green:${dryRun.decision}`); @@ -86,7 +90,6 @@ function main() { warnings.push(liveVerify ? `pre_publish_live_verify_not_green:${liveVerify.decision}` : 'pre_publish_live_verify_missing'); } - const currentHead = gitOutput(['rev-parse', '--short', 'HEAD']); if (manifest.source.commit !== currentHead && gitStatus(['merge-base', '--is-ancestor', manifest.source.commit, 'HEAD']) !== 0) { warnings.push(`manifest_source_commit_not_ancestor:${manifest.source.commit}:${currentHead}`); } From 3eaf703de14d254039c85b6b1a598fa7f74f7818 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:18:42 +0200 Subject: [PATCH 05/13] Run beta8 signature gate in publish workflow --- .github/workflows/release-train-publish.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/release-train-publish.yml b/.github/workflows/release-train-publish.yml index 6668daa2..b015692e 100644 --- a/.github/workflows/release-train-publish.yml +++ b/.github/workflows/release-train-publish.yml @@ -64,6 +64,12 @@ jobs: - name: Generate sync payload run: npm run release:train:sync-surfaces + - name: Verify GitHub signed release commit + env: + GH_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} + BRIK64_RELEASE_COMMIT: ${{ github.sha }} + run: npm run gate:beta8:github-verified-signature + - name: Prepare SDK publication workspaces env: BRIK64_GITHUB_RELEASE_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} @@ -175,5 +181,6 @@ jobs: evidence/release-train-sync/changelog.md evidence/release-train-sync/sync-payload.json evidence/release-train-sync/report.json + evidence/beta8-github-verified-signature/report.json evidence/release-train-publish-plan/report.json evidence/release-train-publish-execute/report.json From f75e31bd36b33a426d589c22901774f11b5fe2c5 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:23:18 +0200 Subject: [PATCH 06/13] Trigger release dry run for beta8 changes --- .github/workflows/release-train-dry-run.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-train-dry-run.yml b/.github/workflows/release-train-dry-run.yml index a85976b6..ea2cf63a 100644 --- a/.github/workflows/release-train-dry-run.yml +++ b/.github/workflows/release-train-dry-run.yml @@ -5,6 +5,9 @@ on: paths: - "release/manifest.json" - "scripts/release-*.js" + - "scripts/beta8-*.js" + - "scripts/beta8-*.sh" + - "scripts/build-beta8-package.sh" - "scripts/beta7-*.js" - "scripts/build-beta7-package.js" - "scripts/beta6-l6-hetzner-generation-gate.js" @@ -12,6 +15,9 @@ on: - "package.json" - "CHANGELOG.md" - "README.md" + - "docs/BETA8_RELEASE_PLAN.md" + - "pcd/**" + - "engines/l4plus-n5/**" - "docs/BETA7_RELEASE_PLAN.md" - "docs/BETA6_RELEASE_PLAN.md" - "docs/BETA6_L6_HETZNER_GENERATION_ENDPOINT.md" From 7c2d8d3cf5c498e6c5b9612ea0dd2431eb87bc9a Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:28:51 +0200 Subject: [PATCH 07/13] Add GitHub signing key preflight --- .gitignore | 1 + package.json | 1 + .../release/github-signing-key-preflight.js | 161 ++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 scripts/release/github-signing-key-preflight.js diff --git a/.gitignore b/.gitignore index 749fa9dd..c90b0407 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ node_modules/ .DS_Store evidence/tmp/ evidence/beta8-github-verified-signature/ +evidence/github-signing-key-preflight/ evidence/beta5-package/stage/ runner-env.local.sh *.secret diff --git a/package.json b/package.json index fa00d28c..f25ba1e6 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "release:train:sync-surfaces": "node scripts/release-train-sync-surfaces.js", "release:train:publish-plan": "node scripts/release-train-publish-plan.js", "release:train:publish-execute": "node scripts/release-train-publish-execute.js", + "preflight:github-signing-key": "node scripts/release/github-signing-key-preflight.js", "release:train:gcp-wif": "node scripts/release/configure-gcp-wif.js" }, "author": { diff --git a/scripts/release/github-signing-key-preflight.js b/scripts/release/github-signing-key-preflight.js new file mode 100644 index 00000000..16fe8e22 --- /dev/null +++ b/scripts/release/github-signing-key-preflight.js @@ -0,0 +1,161 @@ +#!/usr/bin/env node +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const childProcess = require('child_process'); + +const root = path.resolve(__dirname, '../..'); +const outDir = path.join(root, 'evidence', 'github-signing-key-preflight'); + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function argValue(name, fallback) { + const index = process.argv.indexOf(name); + return index === -1 ? fallback : process.argv[index + 1] || fallback; +} + +function run(command, args, options = {}) { + return childProcess.spawnSync(command, args, { + cwd: root, + encoding: 'utf8', + env: process.env, + ...options + }); +} + +function commandText(command, args) { + return [command, ...args].join(' '); +} + +function fingerprint(publicKeyPath) { + const result = run('ssh-keygen', ['-lf', publicKeyPath, '-E', 'sha256']); + if (result.status !== 0) { + return { ok: false, value: '', error: (result.stderr || result.stdout || '').trim() }; + } + const value = result.stdout.trim().split(/\s+/)[1] || ''; + return { ok: Boolean(value), value, error: value ? '' : 'fingerprint_parse_failed' }; +} + +function ghJson(args) { + const result = run('gh', args); + if (result.status !== 0) { + return { + ok: false, + status: result.status, + stdout: result.stdout || '', + stderr: result.stderr || '', + json: null + }; + } + try { + return { + ok: true, + status: 0, + stdout: result.stdout || '', + stderr: result.stderr || '', + json: JSON.parse(result.stdout || 'null') + }; + } catch (error) { + return { + ok: false, + status: 0, + stdout: result.stdout || '', + stderr: `json_parse_failed:${error.message}`, + json: null + }; + } +} + +function redact(text) { + return String(text || '') + .replace(/gho_[A-Za-z0-9_]+/g, 'gho_***') + .replace(/github_pat_[A-Za-z0-9_]+/g, 'github_pat_***'); +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const publicKeyPath = path.resolve(root, argValue('--public-key', path.join(os.homedir(), '.ssh', 'brik64-admin-signing.pub'))); + const expectedFingerprint = argValue('--expected-fingerprint', process.env.BRIK64_EXPECTED_SIGNING_KEY_FINGERPRINT || ''); + const failures = []; + const warnings = []; + + if (!fs.existsSync(publicKeyPath)) failures.push('public_key_missing'); + const fp = fs.existsSync(publicKeyPath) ? fingerprint(publicKeyPath) : { ok: false, value: '', error: 'public_key_missing' }; + if (!fp.ok) failures.push(`public_key_fingerprint_failed:${fp.error}`); + if (expectedFingerprint && fp.value && fp.value !== expectedFingerprint) failures.push('public_key_fingerprint_drift'); + + const signingKeys = ghJson(['api', 'user/ssh_signing_keys', '--jq', '.']); + if (!signingKeys.ok) { + const detail = `${signingKeys.stderr}\n${signingKeys.stdout}`; + if (detail.includes('admin:ssh_signing_key')) { + failures.push('github_token_missing_scope:admin:ssh_signing_key'); + } else { + failures.push('github_signing_keys_api_unavailable'); + } + } + + const keys = Array.isArray(signingKeys.json) ? signingKeys.json : []; + const matchingSigningKey = fp.value + ? keys.find((item) => { + const key = item?.key || ''; + if (!key) return false; + const tmp = path.join(outDir, `key-${item.id || 'candidate'}.pub`); + fs.writeFileSync(tmp, `${key.trim()}\n`); + const candidateFp = fingerprint(tmp); + fs.rmSync(tmp, { force: true }); + return candidateFp.ok && candidateFp.value === fp.value; + }) + : null; + if (signingKeys.ok && !matchingSigningKey) failures.push('github_signing_key_not_registered'); + + const authStatus = run('gh', ['auth', 'status', '-h', 'github.com']); + if (authStatus.status !== 0) warnings.push('github_auth_status_nonzero'); + + const report = { + schemaVersion: 'brik64.github_signing_key_preflight.v1', + generatedAt: new Date().toISOString(), + decision: failures.length === 0 + ? 'PASS_GITHUB_SIGNING_KEY_PREFLIGHT' + : 'BLOCKED_GITHUB_SIGNING_KEY_PREFLIGHT', + publicKey: { + path: publicKeyPath.replace(os.homedir(), '~'), + fingerprint: fp.value || null, + expectedFingerprint: expectedFingerprint || null, + fingerprintMatchesExpected: Boolean(expectedFingerprint && fp.value === expectedFingerprint) + }, + github: { + signingKeysApiAvailable: signingKeys.ok, + signingKeyRegistered: Boolean(matchingSigningKey), + matchingSigningKeyTitle: matchingSigningKey?.title || null, + authStatusRedacted: redact(`${authStatus.stdout || ''}${authStatus.stderr || ''}`).trim() + }, + nextRequiredAction: failures.includes('github_token_missing_scope:admin:ssh_signing_key') + ? 'Run: gh auth refresh -h github.com -s admin:ssh_signing_key -s admin:public_key' + : failures.includes('github_signing_key_not_registered') + ? 'Register the public key as a GitHub SSH signing key for the committing account, then rerun this preflight.' + : null, + commands: { + refreshScopes: 'gh auth refresh -h github.com -s admin:ssh_signing_key -s admin:public_key', + listSigningKeys: commandText('gh', ['api', 'user/ssh_signing_keys', '--jq', '.']) + }, + failures, + warnings, + boundary: { + privateKeyRead: false, + secretsPrinted: false, + releasePublicationAllowed: failures.length === 0 + } + }; + + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`fingerprint=${report.publicKey.fingerprint || 'missing'}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (report.nextRequiredAction) process.stdout.write(`next=${report.nextRequiredAction}\n`); + if (failures.length > 0) process.exit(2); +} + +main(); From 18cd86169425d27f85f5521ca73fa9a27bf7e67d Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:34:18 +0200 Subject: [PATCH 08/13] Document GitHub signing key unblock flow --- .github/workflows/release-train-dry-run.yml | 1 + docs/GITHUB_SIGNING_KEY_RUNBOOK.md | 141 ++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 docs/GITHUB_SIGNING_KEY_RUNBOOK.md diff --git a/.github/workflows/release-train-dry-run.yml b/.github/workflows/release-train-dry-run.yml index ea2cf63a..7fbff87d 100644 --- a/.github/workflows/release-train-dry-run.yml +++ b/.github/workflows/release-train-dry-run.yml @@ -16,6 +16,7 @@ on: - "CHANGELOG.md" - "README.md" - "docs/BETA8_RELEASE_PLAN.md" + - "docs/GITHUB_SIGNING_KEY_RUNBOOK.md" - "pcd/**" - "engines/l4plus-n5/**" - "docs/BETA7_RELEASE_PLAN.md" diff --git a/docs/GITHUB_SIGNING_KEY_RUNBOOK.md b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md new file mode 100644 index 00000000..147855ab --- /dev/null +++ b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md @@ -0,0 +1,141 @@ +# GitHub Signing Key Runbook + +This runbook closes the beta8 release integrity blocker where GitHub sees the +release commit as SSH-signed but not verified. + +Current blocker: + +- PR: https://github.com/brik64/brik64-cli/pull/65 +- State: approved, checks green, merge blocked +- GitHub verification reason: `unknown_key` +- Expected public key fingerprint: + `SHA256:OEJJTFqu5VlYv7mAH3iGhTpIVhQLYbMaSzZ9Y+MLwFo` + +Do not use admin merge override. The release train must pass with GitHub +recognizing the exact release commit as verified. + +## Preflight + +Run: + +```bash +npm run preflight:github-signing-key +``` + +Expected blocked state before authorization: + +```text +decision=BLOCKED_GITHUB_SIGNING_KEY_PREFLIGHT +failures=github_token_missing_scope:admin:ssh_signing_key +``` + +The preflight must not read private keys or print secrets. It only checks the +public signing key fingerprint and GitHub API visibility. + +## Authorize GitHub API Scopes + +Run: + +```bash +gh auth refresh -h github.com -s admin:ssh_signing_key -s admin:public_key +``` + +Complete the browser device-flow approval. After approval, verify scopes: + +```bash +gh auth status -h github.com +``` + +The active account used to register the key must be the account that will own +the verified signing key for the beta8 commit identity. + +## Register The Public Signing Key + +Never print or upload the private key. Register only: + +```bash +~/.ssh/brik64-admin-signing.pub +``` + +The public key fingerprint must match: + +```text +SHA256:OEJJTFqu5VlYv7mAH3iGhTpIVhQLYbMaSzZ9Y+MLwFo +``` + +Preferred API path after scopes are authorized: + +```bash +gh api user/ssh_signing_keys \ + --method POST \ + --field title="BRIK64 beta8 release signing key" \ + --field key="$(cat ~/.ssh/brik64-admin-signing.pub)" +``` + +If GitHub reports the key already exists, continue to validation. + +## Validate + +Run: + +```bash +npm run preflight:github-signing-key +``` + +Required result: + +```text +decision=PASS_GITHUB_SIGNING_KEY_PREFLIGHT +``` + +Then regenerate the beta8 signature report for the exact PR head: + +```bash +npm run gate:beta8:github-verified-signature +``` + +Required result: + +```text +decision=PASS_BETA8_GITHUB_VERIFIED_SIGNATURE +publicReleaseAllowed=true +``` + +Finally verify PR #65: + +```bash +gh pr view 65 --repo brik64/brik64-cli \ + --json mergeStateStatus,reviewDecision,statusCheckRollup,headRefOid +``` + +Required release-ready state: + +- `reviewDecision=APPROVED` +- every required check is `SUCCESS` +- `mergeStateStatus` is no longer blocked by signature verification + +## Resume Release Train + +Only after the verified-signature gate passes: + +```bash +npm run release:train:publish-plan +``` + +Publication must still remain blocked while `release/manifest.json` is +`state=draft`. Moving beta8 from draft to public requires the full synchronized +release train: GitHub Release, curl/GCP installer, SDKs, docs, web, changelog, +skills, platform smoke and public-claim scan. + +## Failure Handling + +If the commit remains `verified=false`: + +- `unknown_key`: the public key is not registered as a GitHub SSH signing key + for the relevant account. +- `no_user`: the commit identity is not associated with a GitHub user/email. +- `bad_email`: update commit author/committer email to a verified account + email and recreate the signed commit. + +Do not bypass with admin override. Keep the failed reports as evidence and fix +the identity/signing configuration. From 94767865d66a5c5b75faae96ce8ef99b19b7dcf0 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:40:25 +0200 Subject: [PATCH 09/13] Run signing key preflight in publish workflow --- .github/workflows/release-train-publish.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-train-publish.yml b/.github/workflows/release-train-publish.yml index b015692e..8678733d 100644 --- a/.github/workflows/release-train-publish.yml +++ b/.github/workflows/release-train-publish.yml @@ -64,6 +64,11 @@ jobs: - name: Generate sync payload run: npm run release:train:sync-surfaces + - name: Preflight GitHub signing key registration + env: + GH_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} + run: npm run preflight:github-signing-key + - name: Verify GitHub signed release commit env: GH_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} @@ -181,6 +186,7 @@ jobs: evidence/release-train-sync/changelog.md evidence/release-train-sync/sync-payload.json evidence/release-train-sync/report.json + evidence/github-signing-key-preflight/report.json evidence/beta8-github-verified-signature/report.json evidence/release-train-publish-plan/report.json evidence/release-train-publish-execute/report.json From eb7def0d4edbef4e4d773d458057c5435f1782a7 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sat, 6 Jun 2026 05:46:21 +0200 Subject: [PATCH 10/13] Add GitHub signing key registration command --- .gitignore | 1 + docs/GITHUB_SIGNING_KEY_RUNBOOK.md | 12 +- package.json | 1 + .../release/register-github-signing-key.js | 154 ++++++++++++++++++ 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 scripts/release/register-github-signing-key.js diff --git a/.gitignore b/.gitignore index c90b0407..9f3fe506 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules/ evidence/tmp/ evidence/beta8-github-verified-signature/ evidence/github-signing-key-preflight/ +evidence/github-signing-key-registration/ evidence/beta5-package/stage/ runner-env.local.sh *.secret diff --git a/docs/GITHUB_SIGNING_KEY_RUNBOOK.md b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md index 147855ab..046f7bff 100644 --- a/docs/GITHUB_SIGNING_KEY_RUNBOOK.md +++ b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md @@ -63,7 +63,17 @@ The public key fingerprint must match: SHA256:OEJJTFqu5VlYv7mAH3iGhTpIVhQLYbMaSzZ9Y+MLwFo ``` -Preferred API path after scopes are authorized: +Preferred repo command after scopes are authorized: + +```bash +npm run release:github-signing-key:register -- --execute +``` + +The command is idempotent. It lists existing GitHub SSH signing keys, compares +public fingerprints, and only submits the public key when no matching key +exists. + +Equivalent API path: ```bash gh api user/ssh_signing_keys \ diff --git a/package.json b/package.json index f25ba1e6..bbbfc07e 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "release:train:publish-plan": "node scripts/release-train-publish-plan.js", "release:train:publish-execute": "node scripts/release-train-publish-execute.js", "preflight:github-signing-key": "node scripts/release/github-signing-key-preflight.js", + "release:github-signing-key:register": "node scripts/release/register-github-signing-key.js", "release:train:gcp-wif": "node scripts/release/configure-gcp-wif.js" }, "author": { diff --git a/scripts/release/register-github-signing-key.js b/scripts/release/register-github-signing-key.js new file mode 100644 index 00000000..28c80593 --- /dev/null +++ b/scripts/release/register-github-signing-key.js @@ -0,0 +1,154 @@ +#!/usr/bin/env node +const fs = require('fs'); +const os = require('os'); +const path = require('path'); +const childProcess = require('child_process'); + +const root = path.resolve(__dirname, '../..'); +const outDir = path.join(root, 'evidence', 'github-signing-key-registration'); + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function argValue(name, fallback) { + const index = process.argv.indexOf(name); + return index === -1 ? fallback : process.argv[index + 1] || fallback; +} + +function hasFlag(name) { + return process.argv.includes(name); +} + +function run(command, args, input = '') { + return childProcess.spawnSync(command, args, { + cwd: root, + encoding: 'utf8', + input, + env: process.env + }); +} + +function fingerprint(publicKeyPath) { + const result = run('ssh-keygen', ['-lf', publicKeyPath, '-E', 'sha256']); + if (result.status !== 0) return { ok: false, value: '', error: (result.stderr || result.stdout || '').trim() }; + const value = result.stdout.trim().split(/\s+/)[1] || ''; + return { ok: Boolean(value), value, error: value ? '' : 'fingerprint_parse_failed' }; +} + +function ghJson(args, input = '') { + const result = run('gh', args, input); + if (result.status !== 0) { + return { ok: false, status: result.status, stdout: result.stdout || '', stderr: result.stderr || '', json: null }; + } + try { + return { ok: true, status: 0, stdout: result.stdout || '', stderr: result.stderr || '', json: JSON.parse(result.stdout || 'null') }; + } catch (error) { + return { ok: false, status: 0, stdout: result.stdout || '', stderr: `json_parse_failed:${error.message}`, json: null }; + } +} + +function redact(text) { + return String(text || '') + .replace(/gho_[A-Za-z0-9_]+/g, 'gho_***') + .replace(/github_pat_[A-Za-z0-9_]+/g, 'github_pat_***'); +} + +function fingerprintForKeyText(keyText, id) { + const tmp = path.join(outDir, `candidate-${id || 'key'}.pub`); + fs.writeFileSync(tmp, `${String(keyText).trim()}\n`); + const fp = fingerprint(tmp); + fs.rmSync(tmp, { force: true }); + return fp; +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const publicKeyPath = path.resolve(root, argValue('--public-key', path.join(os.homedir(), '.ssh', 'brik64-admin-signing.pub'))); + const title = argValue('--title', 'BRIK64 beta8 release signing key'); + const execute = hasFlag('--execute'); + const failures = []; + const warnings = []; + + if (!fs.existsSync(publicKeyPath)) failures.push('public_key_missing'); + const keyText = fs.existsSync(publicKeyPath) ? fs.readFileSync(publicKeyPath, 'utf8').trim() : ''; + const fp = keyText ? fingerprint(publicKeyPath) : { ok: false, value: '', error: 'public_key_missing' }; + if (!fp.ok) failures.push(`public_key_fingerprint_failed:${fp.error}`); + + const list = ghJson(['api', 'user/ssh_signing_keys', '--jq', '.']); + if (!list.ok) { + const detail = `${list.stderr}\n${list.stdout}`; + if (detail.includes('admin:ssh_signing_key')) failures.push('github_token_missing_scope:admin:ssh_signing_key'); + else failures.push('github_signing_keys_api_unavailable'); + } + + const keys = Array.isArray(list.json) ? list.json : []; + const existing = fp.value + ? keys.find((item) => { + const candidate = fingerprintForKeyText(item?.key || '', item?.id || 'existing'); + return candidate.ok && candidate.value === fp.value; + }) + : null; + + let created = null; + if (execute && failures.length === 0 && !existing) { + const payload = JSON.stringify({ title, key: keyText }); + const create = ghJson(['api', 'user/ssh_signing_keys', '--method', 'POST', '--input', '-'], payload); + if (!create.ok) { + const detail = `${create.stderr}\n${create.stdout}`; + if (detail.includes('already')) warnings.push('github_signing_key_already_exists'); + else failures.push('github_signing_key_create_failed'); + } else { + created = create.json; + } + } + + const registered = Boolean(existing || created); + if (!registered && !execute && failures.length === 0) warnings.push('dry_run_registration_not_executed'); + if (!registered && execute && failures.length === 0) failures.push('github_signing_key_not_registered_after_create'); + + const report = { + schemaVersion: 'brik64.github_signing_key_registration.v1', + generatedAt: new Date().toISOString(), + decision: failures.length === 0 + ? execute + ? 'PASS_GITHUB_SIGNING_KEY_REGISTRATION' + : 'PASS_GITHUB_SIGNING_KEY_REGISTRATION_DRY_RUN' + : 'BLOCKED_GITHUB_SIGNING_KEY_REGISTRATION', + execute, + publicKey: { + path: publicKeyPath.replace(os.homedir(), '~'), + fingerprint: fp.value || null + }, + github: { + signingKeysApiAvailable: list.ok, + signingKeyAlreadyRegistered: Boolean(existing), + signingKeyCreated: Boolean(created), + matchingSigningKeyTitle: existing?.title || created?.title || null + }, + nextRequiredAction: failures.includes('github_token_missing_scope:admin:ssh_signing_key') + ? 'Run: gh auth refresh -h github.com -s admin:ssh_signing_key -s admin:public_key' + : !execute && !registered + ? 'Re-run with --execute after confirming the public key fingerprint.' + : null, + failures, + warnings, + boundary: { + privateKeyRead: false, + secretsPrinted: false, + mutatesGitHub: execute && failures.length === 0 && !existing + } + }; + + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`fingerprint=${report.publicKey.fingerprint || 'missing'}\n`); + process.stdout.write(`execute=${execute}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (warnings.length > 0) process.stdout.write(`warnings=${warnings.join(',')}\n`); + if (report.nextRequiredAction) process.stdout.write(`next=${report.nextRequiredAction}\n`); + if (failures.length > 0) process.exit(2); +} + +main(); From 8070d69cb13c62b3b3f854b8fd296f626d79a0d7 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sun, 7 Jun 2026 12:08:43 +0200 Subject: [PATCH 11/13] Add beta8 release surface sync gates --- evidence/beta8-adversarial/report.json | 2 +- .../beta8-compiler-functionality/report.json | 2 +- evidence/beta8-docs-web-sync/report.json | 47 +++++++++ .../beta8-marketplace-packages/report.json | 50 ++++++++++ evidence/beta8-package-smoke/report.json | 2 +- evidence/beta8-package/SHA256SUMS | 6 +- .../beta8-package/brik64-cli-0.1.0-beta.8.tgz | Bin 24482 -> 24495 bytes evidence/beta8-package/package.manifest.json | 4 +- evidence/beta8-package/stage-checksums.tsv | 4 +- .../evidence/beta8-adversarial/report.json | 2 +- .../beta8-compiler-functionality/report.json | 2 +- evidence/beta8-sdk-sync/report.json | 66 +++++++++++++ evidence/beta8-skills-sync/report.json | 47 +++++++++ evidence/release-flow-audit/report.json | 22 ++--- .../release-manifest-validate/report.json | 14 +-- evidence/release-train-dry-run/report.json | 41 ++++---- package.json | 5 + release/manifest.json | 2 +- scripts/beta8-docs-web-sync-gate.js | 82 ++++++++++++++++ scripts/beta8-marketplace-package-gate.js | 79 +++++++++++++++ scripts/beta8-sdk-sync-gate.js | 91 ++++++++++++++++++ scripts/beta8-skills-sync-gate.js | 70 ++++++++++++++ scripts/release-flow-audit.js | 20 +++- 23 files changed, 608 insertions(+), 52 deletions(-) create mode 100644 evidence/beta8-docs-web-sync/report.json create mode 100644 evidence/beta8-marketplace-packages/report.json create mode 100644 evidence/beta8-sdk-sync/report.json create mode 100644 evidence/beta8-skills-sync/report.json create mode 100644 scripts/beta8-docs-web-sync-gate.js create mode 100644 scripts/beta8-marketplace-package-gate.js create mode 100644 scripts/beta8-sdk-sync-gate.js create mode 100644 scripts/beta8-skills-sync-gate.js diff --git a/evidence/beta8-adversarial/report.json b/evidence/beta8-adversarial/report.json index 3e783455..08928bf6 100644 --- a/evidence/beta8-adversarial/report.json +++ b/evidence/beta8-adversarial/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_adversarial_gate.v1", - "generatedAt": "2026-06-06T02:59:47Z", + "generatedAt": "2026-06-07T10:08:18Z", "iter_id": "BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_ADVERSARIAL", diff --git a/evidence/beta8-compiler-functionality/report.json b/evidence/beta8-compiler-functionality/report.json index 41681edf..046dd2db 100644 --- a/evidence/beta8-compiler-functionality/report.json +++ b/evidence/beta8-compiler-functionality/report.json @@ -1,6 +1,6 @@ { "schemaVersion": "brik64.cli_beta8_compiler_functionality_gate.v1", - "generatedAt": "2026-06-06T02:59:45Z", + "generatedAt": "2026-06-07T10:08:15Z", "iter_id": "BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1", "lane": "cli_0_1_beta8", "decision": "PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY", diff --git a/evidence/beta8-docs-web-sync/report.json b/evidence/beta8-docs-web-sync/report.json new file mode 100644 index 00000000..4357d5e0 --- /dev/null +++ b/evidence/beta8-docs-web-sync/report.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": "brik64.cli_beta8_docs_web_sync_gate.v1", + "version": "0.1.0-beta.8", + "decision": "PASS_DOCS_WEB_BETA8_SYNC", + "releaseEligible": true, + "deployAllowed": true, + "artifacts": [ + { + "id": "docs_install", + "path": "/Users/carlosjperez/Documents/GitHub/brik64-docs-site/cli/install.mdx", + "sha256": "048710173a310d5b534c69a309de6ae0d152245e05e4a505547402ef544ccedb", + "bytes": 2064 + }, + { + "id": "docs_sdks", + "path": "/Users/carlosjperez/Documents/GitHub/brik64-docs-site/sdks.mdx", + "sha256": "46ca1e93fb94ab79c9bc2cbde7e16cf7121827e99e23b2c8c6de973003649049", + "bytes": 1461 + }, + { + "id": "docs_llms", + "path": "/Users/carlosjperez/Documents/GitHub/brik64-docs-site/llms-full.txt", + "sha256": "9d706cf587326469784d82fa7ff12c3e23b681860d1e0398d50770746f59e857", + "bytes": 108533 + }, + { + "id": "web_sdk_download_api", + "path": "/Users/carlosjperez/Documents/GitHub/brik64.com/functions/api/download/sdk/[target].ts", + "sha256": "adfc6f0d00257beee25a5eeb01af265e6d4a8d70a89779a2ee36a73386af9988", + "bytes": 2326 + }, + { + "id": "web_cli_download_api", + "path": "/Users/carlosjperez/Documents/GitHub/brik64.com/functions/api/download/cli.ts", + "sha256": "28aa7a5369a32ef3601e003937c648b21189490e8b189c0984a56533ecae3416", + "bytes": 1759 + }, + { + "id": "web_language_data", + "path": "/Users/carlosjperez/Documents/GitHub/brik64.com/src/lib/language-data.ts", + "sha256": "6f79e46995e2acd4db34cfc19b66557ef2795183aaa961002b9ef69667c15d23", + "bytes": 10647 + } + ], + "failures": [], + "boundary": "Docs and web source must be beta8 aligned before public release. This gate does not deploy." +} diff --git a/evidence/beta8-marketplace-packages/report.json b/evidence/beta8-marketplace-packages/report.json new file mode 100644 index 00000000..bf88d95a --- /dev/null +++ b/evidence/beta8-marketplace-packages/report.json @@ -0,0 +1,50 @@ +{ + "schemaVersion": "brik64.cli_beta8_marketplace_package_gate.v1", + "version": "0.1.0-beta.8", + "decision": "PASS_MARKETPLACE_PACKAGE_GATE", + "releaseEligible": true, + "marketplacePublicationAllowed": true, + "packages": { + "npm": { + "repository": "/Users/carlosjperez/Documents/GitHub/brik64-lib-js", + "packageName": "@brik64/core", + "version": "0.1.0-beta.8", + "artifact": { + "path": "evidence-beta8-pack/brik64-core-0.1.0-beta.8.tgz", + "absolutePath": "/Users/carlosjperez/Documents/GitHub/brik64-lib-js/evidence-beta8-pack/brik64-core-0.1.0-beta.8.tgz", + "sha256": "8ca62654417c95e38d60d48b42bf1c4a5babcce24f07dc28a64b832ab2547cd8", + "bytes": 20734 + } + }, + "pypi": { + "repository": "/Users/carlosjperez/Documents/GitHub/brik64-lib-python", + "packageName": "brik64", + "version": "0.1.0b8", + "wheel": { + "path": "dist/brik64-0.1.0b8-py3-none-any.whl", + "absolutePath": "/Users/carlosjperez/Documents/GitHub/brik64-lib-python/dist/brik64-0.1.0b8-py3-none-any.whl", + "sha256": "05fd20d8fc42b2b43b3d276108a4114b035ac80e811b0d39e5ea3e4f7dd0c888", + "bytes": 10011 + }, + "sdist": { + "path": "dist/brik64-0.1.0b8.tar.gz", + "absolutePath": "/Users/carlosjperez/Documents/GitHub/brik64-lib-python/dist/brik64-0.1.0b8.tar.gz", + "sha256": "61387ef86ad3cc403cb74798b17d21359bd4e1de58de0f49e1720c35b72a848c", + "bytes": 7442 + } + }, + "cargo": { + "repository": "/Users/carlosjperez/Documents/GitHub/brik64-lib-rust", + "crateName": "brik64-core", + "version": "0.1.0-beta.8", + "artifact": { + "path": "target/package/brik64-core-0.1.0-beta.8.crate", + "absolutePath": "/Users/carlosjperez/Documents/GitHub/brik64-lib-rust/target/package/brik64-core-0.1.0-beta.8.crate", + "sha256": "731da3affa712b1fe2ea570144a5884353de091b0cd198c6066344dae8d22964", + "bytes": 15035 + } + } + }, + "failures": [], + "boundary": "Package artifacts are local beta8 publication inputs. This gate verifies readiness but does not mutate npm, PyPI or crates.io." +} diff --git a/evidence/beta8-package-smoke/report.json b/evidence/beta8-package-smoke/report.json index a8e079a7..0d992993 100644 --- a/evidence/beta8-package-smoke/report.json +++ b/evidence/beta8-package-smoke/report.json @@ -6,7 +6,7 @@ "lane": "cli_0_1_beta8", "package": { "path": "evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz", - "sha256": "a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65" + "sha256": "9691aad414c40c0bac0dd3f1f087f1a235b87dc29c68b466812763b59b90aa76" }, "checks": [ "extract", diff --git a/evidence/beta8-package/SHA256SUMS b/evidence/beta8-package/SHA256SUMS index 8f8e2972..7971b92c 100644 --- a/evidence/beta8-package/SHA256SUMS +++ b/evidence/beta8-package/SHA256SUMS @@ -1,3 +1,3 @@ -a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65 brik64-cli-0.1.0-beta.8.tgz -7f5e4a5e84ca2e76f5f30e936955d9416e1640ec6565f7f5c30b467f6d8b30e1 package.manifest.json -0c62821e40e102099311f781a58b16b4f99f36aefb42767ecc0f235769facb56 stage-checksums.tsv +9691aad414c40c0bac0dd3f1f087f1a235b87dc29c68b466812763b59b90aa76 brik64-cli-0.1.0-beta.8.tgz +eec112132996ffc66ddee990293107cf66e2737fc69c2e06c7e602934ec6144b package.manifest.json +32624563b4583a6baa4fc076f7883aadf2cb98cb9e3ac62c1f4949a492b82e82 stage-checksums.tsv diff --git a/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz b/evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz index 626285c53641d6561bf9027614f08255b16a8e9d..392383d1bae09d94d353aa00b317c208a085acb9 100644 GIT binary patch literal 24495 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

|cPv|uysy{sa->yQ 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 { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 0 = 1 ']'\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-ts/program.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-ts/program.test.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf/escaped-out/program.mjs\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ perl -0pi -e 's/return 2;/return 3;/' stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.mjs out-variant/program.mjs\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.UmeqUWD0Lf\n" + "stderr": "+ set -euo pipefail\n+++ dirname tests/smoke.sh\n++ cd tests/..\n++ pwd\n+ ROOT_DIR=/Users/carlosjperez/Documents/GitHub/brik64-cli\n+ BRIK=/Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js\n++ node -e 'const fs=require(\"fs\"); process.stdout.write(JSON.parse(fs.readFileSync(\"package.json\",\"utf8\")).version)'\n+ PACKAGE_VERSION=0.1.0-beta.8\n++ mktemp -d\n+ tmpdir=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0\n+ trap cleanup EXIT\n+ export BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/config\n+ BRIK64_CONFIG_HOME=/var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/config\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ grep -q 'BRIK64 CLI 0.1.0-beta.8'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --version\n+ node -e 'let s=\"\"; process.stdin.on(\"data\", (d) => { s += d; }); process.stdin.on(\"end\", () => { s = s.replace(/\\x1b\\[[0-9;]*m/g, \"\"); if (!s.includes(\"█████████████\") || !s.includes(\"▒▒▒▒▒▒▒▒▒▒▒▒\")) process.exit(1); });'\n+ grep -q status=public_beta\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'polymerize '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'verify '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js --help\n+ grep -q 'migrate '\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q 'BRIK64 workspace doctor'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"status\": \"PASS\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"localRuntime\": \"available\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor --json\n+ grep -q '\"internalArtifactFactory\": \"private\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"runtimeMode\": \"portable_bir_bundle\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js engine status\n+ grep -q '\"nativeExecutableIncluded\": false'\n+ '[' 0 = 1 ']'\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ test -f .brik/manifest.json\n+ test '!' -f AGENTS.md\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.engineTierPolicy.registeredManagedRuntime !== \"managed_platform\") process.exit(1)'\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); if (m.preferred_engine !== \"auto\" || m.polymer_strategy !== \"local_ast\" || m.managed_platform.routing !== \"local_default\") process.exit(1)'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js account status\n+ grep -q 'tier: free'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js login --token-env BRIK64_MISSING_TOKEN\n+ grep -q login_token_env_missing /tmp/brik-login.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q pcd_inventory_empty /tmp/brik-empty-doctor.err\n+ cat\n+ cd /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q certificate_required /tmp/brik-emit.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd\n+ grep -q pcd_sha256=\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd\n+ grep -q verification=PASS\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_local_verify_report.v1\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js verify program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-verify-cloud.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --out polymer.pcd --json\n+ grep -q '\"schemaVersion\": \"brik64.cli_polymer_manifest.v1\"'\n+ test -f polymer.pcd\n+ test -f polymer.pcd.manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify polymer.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js polymerize program.pcd --cloud\n+ grep -q managed_entitlement_required /tmp/brik-poly-cloud.err\n+ for target in ts rust python\n+ out=out-ts\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out out-ts --tests\n+ grep -q generated= /tmp/brik-emit-ts.out\n+ grep -q tests= /tmp/brik-emit-ts.out\n+ for target in ts rust python\n+ out=out-rust\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target rust --out out-rust --tests\n+ grep -q generated= /tmp/brik-emit-rust.out\n+ grep -q tests= /tmp/brik-emit-rust.out\n+ for target in ts rust python\n+ out=out-python\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target python --out out-python --tests\n+ grep -q generated= /tmp/brik-emit-python.out\n+ grep -q tests= /tmp/brik-emit-python.out\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-ts/program.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-ts/program.test.mjs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-rust/program.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-rust/program_test.rs\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-python/program.py\n+ test -f /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/out-python/test_program.py\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target go --out out-go --tests\n+ grep -q unsupported_target /tmp/brik-emit-go.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out ../escaped-out --tests\n+ grep -q path_outside_workspace /tmp/brik-out-traversal.err\n+ test '!' -e /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0/escaped-out/program.mjs\n+ mkdir readonly\n+ chmod 500 readonly\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit program.pcd --target ts --out readonly/child --tests\n+ chmod 700 readonly\n+ grep -q filesystem_mkdir_error /tmp/brik-readonly.err\n+ grep -q 'at Object\\.mkdirSync\\|Node\\.js' /tmp/brik-readonly.err\n+ cp program.pcd stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify stale.pcd\n+ perl -0pi -e 's/return 2;/return 3;/' stale.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit stale.pcd\n+ grep -q certificate_hash_mismatch /tmp/brik-stale.err\n+ touch empty.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify empty.pcd\n+ grep -q pcd_empty /tmp/brik-empty.err\n+ printf 'not a pcd\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify corrupt.pcd\n+ grep -q pcd_parse_error /tmp/brik-corrupt.err\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.pcd\n+ grep -q 'brik64 migrate' /tmp/brik-legacy-cert.err\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js migrate legacy.pcd --out legacy.beta7.pcd --json\n+ grep -q '\"detectedSyntax\": \"legacy_lowercase_pc\"'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify legacy.beta7.pcd\n+ cat\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify variant.pcd\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js emit variant.pcd --target ts --out out-variant --tests\n+ cmp -s out-ts/program.mjs out-variant/program.mjs\n+ printf '{ corrupted_json\\n'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js certify program.pcd\n+ grep -q manifest_parse_error /tmp/brik-bad-manifest.err\n+ rm .brik/manifest.json\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js init\n+ node -e 'const fs=require(\"fs\"); const m=JSON.parse(fs.readFileSync(\".brik/manifest.json\",\"utf8\")); m.engineTierPolicy.l6DistributionAllowed=true; fs.writeFileSync(\".brik/manifest.json\", JSON.stringify(m,null,2)+\"\\n\")'\n+ node /Users/carlosjperez/Documents/GitHub/brik64-cli/src/brik.js doctor\n+ grep -q engine_tier_policy_l6_distribution_open /tmp/brik-bad-tier.err\n+ echo 'brik64-cli bootstrap smoke: PASS'\n+ cleanup\n+ rm -rf /var/folders/rh/rrm90qbs1_qc0816bjfd4hwh0000gn/T/tmp.uxzPhohNa0\n" }, { "name": "beta8_compiler_functionality", "command": "bash scripts/beta8-compiler-functionality-gate.sh", "rc": 0, - "elapsedMs": 1910, - "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_compiler_functionality_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:59:45Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"fixture\": {\n \"path\": \"pcd/branch_math.pcd\",\n \"sha256\": \"sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404\"\n },\n \"executedTargets\": {\n \"typescript\": {\n \"programSha256\": \"sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95\",\n \"test\": \"node out-ts/program.test.mjs\",\n \"passed\": true\n },\n \"rust\": {\n \"programSha256\": \"sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d\",\n \"test\": \"rustc out-rust/program_test.rs && ./out-rust/program_test\",\n \"passed\": true\n },\n \"python\": {\n \"programSha256\": \"sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6\",\n \"test\": \"PYTHONPATH=out-python python3 out-python/test_program.py\",\n \"passed\": true\n }\n },\n \"adversarial\": {\n \"unknown_identifier_fail_closed\": true,\n \"unsupported_target_fail_closed\": true,\n \"path_traversal_fail_closed\": true,\n \"stack_trace_leaked\": false\n },\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"compiler_functionality_claim_allowed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 adversarial gate and package smoke before public release train\"\n}\n", + "elapsedMs": 1959, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_compiler_functionality_gate.v1\",\n \"generatedAt\": \"2026-06-07T10:08:15Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-COMPILER-FUNCTIONALITY-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_COMPILER_FUNCTIONALITY\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"fixture\": {\n \"path\": \"pcd/branch_math.pcd\",\n \"sha256\": \"sha256:09742f0ef4d80b4f465da256d8d44b4c587306c07015ecb77cada308c1d70404\"\n },\n \"executedTargets\": {\n \"typescript\": {\n \"programSha256\": \"sha256:608f6244ed6563765b31e6e42b722eb2c7889b87f7fdb7ca5e86740eb1675a95\",\n \"test\": \"node out-ts/program.test.mjs\",\n \"passed\": true\n },\n \"rust\": {\n \"programSha256\": \"sha256:bbe9b972902349fdb4b5884858e840b2c004c2173eb24f605958a913d6075e5d\",\n \"test\": \"rustc out-rust/program_test.rs && ./out-rust/program_test\",\n \"passed\": true\n },\n \"python\": {\n \"programSha256\": \"sha256:ca5c353fdd06e4b65b9b6366deea679b2816544af1843932ecdb59d471a742b6\",\n \"test\": \"PYTHONPATH=out-python python3 out-python/test_program.py\",\n \"passed\": true\n }\n },\n \"adversarial\": {\n \"unknown_identifier_fail_closed\": true,\n \"unsupported_target_fail_closed\": true,\n \"path_traversal_fail_closed\": true,\n \"stack_trace_leaked\": false\n },\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"compiler_functionality_claim_allowed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 adversarial gate and package smoke before public release train\"\n}\n", "stderr": "" }, { "name": "beta8_adversarial", "command": "bash scripts/beta8-adversarial-gate.sh", "rc": 0, - "elapsedMs": 1799, - "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_adversarial_gate.v1\",\n \"generatedAt\": \"2026-06-06T02:59:47Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_ADVERSARIAL\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"executableEdgeFixture\": {\n \"path\": \"pcd/edge_precedence.pcd\",\n \"sha256\": \"sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63\"\n },\n \"passChecks\": 9,\n \"failClosedChecks\": 12,\n \"generatedTargetExecution\": {\n \"typescript\": true,\n \"rust\": true,\n \"python\": true\n },\n \"failClosedSurface\": [\n \"empty_pcd\",\n \"binary_input\",\n \"too_large_input\",\n \"legacy_syntax\",\n \"missing_fn\",\n \"too_many_params\",\n \"invalid_param\",\n \"missing_return\",\n \"unsupported_statement\",\n \"unsupported_expression_token\",\n \"malformed_expression\",\n \"unclosed_block\"\n ],\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"adversarial_gate_passed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 package smoke and release-train sync gates\"\n}\n", + "elapsedMs": 2909, + "stdout": "{\n \"schemaVersion\": \"brik64.cli_beta8_adversarial_gate.v1\",\n \"generatedAt\": \"2026-06-07T10:08:18Z\",\n \"iter_id\": \"BRIK64-CLI-BETA8-ADVERSARIAL-20260606-R1\",\n \"lane\": \"cli_0_1_beta8\",\n \"decision\": \"PASS_BRIK64_CLI_BETA8_ADVERSARIAL\",\n \"rc\": 0,\n \"cliVersion\": \"0.1.0-beta.8\",\n \"cliSha256\": \"sha256:63f28a941626edb18cee7b794e9f3c05acdc29db94e8387e02809ed402a7f8ed\",\n \"executableEdgeFixture\": {\n \"path\": \"pcd/edge_precedence.pcd\",\n \"sha256\": \"sha256:de6c384a4f4146f78e1ea040176206b49aed6725a35db10b447a8d42fe75bf63\"\n },\n \"passChecks\": 9,\n \"failClosedChecks\": 12,\n \"generatedTargetExecution\": {\n \"typescript\": true,\n \"rust\": true,\n \"python\": true\n },\n \"failClosedSurface\": [\n \"empty_pcd\",\n \"binary_input\",\n \"too_large_input\",\n \"legacy_syntax\",\n \"missing_fn\",\n \"too_many_params\",\n \"invalid_param\",\n \"missing_return\",\n \"unsupported_statement\",\n \"unsupported_expression_token\",\n \"malformed_expression\",\n \"unclosed_block\"\n ],\n \"claim_boundary\": {\n \"public_claims_allowed\": false,\n \"public_release_allowed\": false,\n \"adversarial_gate_passed\": true,\n \"compiler_functionality_scope\": \"supported_beta8_pcd_subset_only\",\n \"fixpoint_claim_allowed\": false,\n \"n5_formal_claim_allowed\": false,\n \"rust_independence_claim_allowed\": false\n },\n \"blockers\": [],\n \"warnings\": [],\n \"next_action\": \"run beta8 package smoke and release-train sync gates\"\n}\n", "stderr": "" }, { "name": "beta8_local_package", "command": "bash scripts/build-beta8-package.sh", "rc": 0, - "elapsedMs": 438, - "stdout": "decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz\nsha256=a11dd4f781acda03b133f6aecf422d45a94815baaab6641bded8185292995f65\n", + "elapsedMs": 429, + "stdout": "decision=PASS_BRIK64_CLI_BETA8_PACKAGE_BUILT\nreleaseEligible=false\npackage=evidence/beta8-package/brik64-cli-0.1.0-beta.8.tgz\nsha256=9691aad414c40c0bac0dd3f1f087f1a235b87dc29c68b466812763b59b90aa76\n", "stderr": "" }, { "name": "beta8_package_smoke", "command": "bash scripts/beta8-package-smoke.sh", "rc": 0, - "elapsedMs": 1167, + "elapsedMs": 1403, "stdout": "decision=PASS_BRIK64_CLI_BETA8_LOCAL_PACKAGE_SMOKE\nchecks=13\n", "stderr": "" } diff --git a/package.json b/package.json index bbbfc07e..25f2e337 100644 --- a/package.json +++ b/package.json @@ -51,9 +51,14 @@ "gate:beta7:marketplace-packages": "node scripts/beta7-marketplace-package-gate.js", "gate:beta7:docs-web-sync": "node scripts/beta7-docs-web-sync-gate.js", "gate:beta7:skills-sync": "node scripts/beta7-skills-sync-gate.js", + "gate:beta8:feature-parity": "bash scripts/beta8-compiler-functionality-gate.sh", "gate:beta8:compiler-functionality": "bash scripts/beta8-compiler-functionality-gate.sh", "gate:beta8:adversarial": "bash scripts/beta8-adversarial-gate.sh", "gate:beta8:github-verified-signature": "node scripts/beta8-github-verified-signature-gate.js", + "gate:beta8:sdk-sync": "node scripts/beta8-sdk-sync-gate.js", + "gate:beta8:marketplace-packages": "node scripts/beta8-marketplace-package-gate.js", + "gate:beta8:docs-web-sync": "node scripts/beta8-docs-web-sync-gate.js", + "gate:beta8:skills-sync": "node scripts/beta8-skills-sync-gate.js", "package:beta8:local": "bash scripts/build-beta8-package.sh", "smoke:beta8:package": "bash scripts/beta8-package-smoke.sh", "release:manifest:validate": "node scripts/release-manifest-validate.js", diff --git a/release/manifest.json b/release/manifest.json index 5dcccc4f..17c01b20 100644 --- a/release/manifest.json +++ b/release/manifest.json @@ -8,7 +8,7 @@ "source": { "repo": "brik64/brik64-cli", "branch": "main", - "commit": "2673a5b" + "commit": "eb7def0" }, "cli": { "packageName": "@brik64/cli", diff --git a/scripts/beta8-docs-web-sync-gate.js b/scripts/beta8-docs-web-sync-gate.js new file mode 100644 index 00000000..1cf08b6e --- /dev/null +++ b/scripts/beta8-docs-web-sync-gate.js @@ -0,0 +1,82 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +const childProcess = require('child_process'); + +const root = path.resolve(__dirname, '..'); +const outDir = path.join(root, 'evidence', 'beta8-docs-web-sync'); +const docsRoot = '/Users/carlosjperez/Documents/GitHub/brik64-docs-site'; +const webRoot = '/Users/carlosjperez/Documents/GitHub/brik64.com'; +const version = '0.1.0-beta.8'; + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function sha256File(file) { + return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); +} + +function read(file) { + return fs.readFileSync(file, 'utf8'); +} + +function checkFile(id, file, required, failures, artifacts) { + if (!fs.existsSync(file)) { + failures.push(`missing_surface:${id}`); + return; + } + const text = read(file); + artifacts.push({ id, path: file, sha256: sha256File(file), bytes: Buffer.byteLength(text, 'utf8') }); + for (const needle of required) { + if (!text.includes(needle)) failures.push(`surface_required_text_missing:${id}:${needle}`); + } + if (/\bL[456]\+?N5\b|\bfixpoint\b|\bself-host|Hetzner|1Password/i.test(text)) { + failures.push(`public_claim_language:${id}`); + } +} + +function scanStale(rootDir, args) { + const result = childProcess.spawnSync('rg', args, { cwd: rootDir, encoding: 'utf8' }); + return (result.stdout || '').split('\n').filter(Boolean); +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const failures = []; + const artifacts = []; + + checkFile('docs_install', path.join(docsRoot, 'cli/install.mdx'), [version, 'brik64-cli-0.1.0-beta.8.tgz'], failures, artifacts); + checkFile('docs_sdks', path.join(docsRoot, 'sdks.mdx'), ['@brik64/core@0.1.0-beta.8', 'brik64==0.1.0b8', 'brik64-core@0.1.0-beta.8'], failures, artifacts); + checkFile('docs_llms', path.join(docsRoot, 'llms-full.txt'), [version, '@brik64/core@0.1.0-beta.8', 'brik64==0.1.0b8', 'brik64-core@0.1.0-beta.8'], failures, artifacts); + checkFile('web_sdk_download_api', path.join(webRoot, 'functions/api/download/sdk/[target].ts'), ['0.1.0-beta.8', '0.1.0b8'], failures, artifacts); + checkFile('web_cli_download_api', path.join(webRoot, 'functions/api/download/cli.ts'), [version], failures, artifacts); + checkFile('web_language_data', path.join(webRoot, 'src/lib/language-data.ts'), ['npm install @brik64/core@0.1.0-beta.8', 'pip install brik64==0.1.0b8', 'cargo add brik64-core --version 0.1.0-beta.8'], failures, artifacts); + + for (const stale of scanStale(docsRoot, ['-n', '0\\.1\\.0-beta\\.[4567]|0\\.1\\.0b[4567]|beta[4567]|beta\\.[4567]', '-g', '!docs/research/**', '-g', '!docs/operations/**', '-g', '!BETA*_SYNC.md', '-g', '!node_modules/**', '-g', '!.git/**'])) { + failures.push(`docs_stale_beta_residue:${stale}`); + } + for (const stale of scanStale(webRoot, ['-n', '0\\.1\\.0-beta\\.[4567]|0\\.1\\.0b[4567]|beta[4567]|beta\\.[4567]', '-g', '!docs/research/**', '-g', '!src/lib/cms/generated-public-content.json', '-g', '!node_modules/**', '-g', '!.next/**', '-g', '!out/**', '-g', '!.git/**'])) { + failures.push(`web_stale_beta_residue:${stale}`); + } + + const report = { + schemaVersion: 'brik64.cli_beta8_docs_web_sync_gate.v1', + version, + decision: failures.length === 0 ? 'PASS_DOCS_WEB_BETA8_SYNC' : 'FAIL_DOCS_WEB_BETA8_SYNC', + releaseEligible: failures.length === 0, + deployAllowed: failures.length === 0, + artifacts, + failures, + boundary: 'Docs and web source must be beta8 aligned before public release. This gate does not deploy.' + }; + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`deployAllowed=${report.deployAllowed}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (failures.length > 0) process.exit(1); +} + +main(); diff --git a/scripts/beta8-marketplace-package-gate.js b/scripts/beta8-marketplace-package-gate.js new file mode 100644 index 00000000..2a001f9b --- /dev/null +++ b/scripts/beta8-marketplace-package-gate.js @@ -0,0 +1,79 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const root = path.resolve(__dirname, '..'); +const outDir = path.join(root, 'evidence', 'beta8-marketplace-packages'); +const repos = { + js: '/Users/carlosjperez/Documents/GitHub/brik64-lib-js', + python: '/Users/carlosjperez/Documents/GitHub/brik64-lib-python', + rust: '/Users/carlosjperez/Documents/GitHub/brik64-lib-rust' +}; + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function sha256File(file) { + return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); +} + +function artifact(file, repoRoot) { + if (!fs.existsSync(file)) return null; + return { path: path.relative(repoRoot, file), absolutePath: file, sha256: sha256File(file), bytes: fs.statSync(file).size }; +} + +function readJson(file) { + return JSON.parse(fs.readFileSync(file, 'utf8')); +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const failures = []; + const jsPackageJson = path.join(repos.js, 'package.json'); + const pyProject = path.join(repos.python, 'pyproject.toml'); + const rustCargo = path.join(repos.rust, 'Cargo.toml'); + const jsTarball = artifact(path.join(repos.js, 'evidence-beta8-pack', 'brik64-core-0.1.0-beta.8.tgz'), repos.js); + const pythonWheel = artifact(path.join(repos.python, 'dist', 'brik64-0.1.0b8-py3-none-any.whl'), repos.python); + const pythonSdist = artifact(path.join(repos.python, 'dist', 'brik64-0.1.0b8.tar.gz'), repos.python); + const rustCrate = artifact(path.join(repos.rust, 'target', 'package', 'brik64-core-0.1.0-beta.8.crate'), repos.rust); + + if (!fs.existsSync(jsPackageJson)) failures.push('js_package_json_missing'); + if (!fs.existsSync(pyProject)) failures.push('python_pyproject_missing'); + if (!fs.existsSync(rustCargo)) failures.push('rust_cargo_toml_missing'); + + const jsVersion = fs.existsSync(jsPackageJson) ? readJson(jsPackageJson).version : null; + const pyProjectText = fs.existsSync(pyProject) ? fs.readFileSync(pyProject, 'utf8') : ''; + const rustCargoText = fs.existsSync(rustCargo) ? fs.readFileSync(rustCargo, 'utf8') : ''; + + if (jsVersion !== '0.1.0-beta.8') failures.push(`js_version_drift:${jsVersion || 'missing'}`); + if (!/version\s*=\s*"0\.1\.0b8"/.test(pyProjectText)) failures.push('python_version_drift'); + if (!/version\s*=\s*"0\.1\.0-beta\.8"/.test(rustCargoText)) failures.push('rust_version_drift'); + if (!jsTarball) failures.push('npm_package_not_packed_for_beta8_publication'); + if (!pythonWheel || !pythonSdist) failures.push('pypi_package_not_built_for_beta8_publication'); + if (!rustCrate) failures.push('cargo_package_not_packed_for_beta8_publication'); + + const report = { + schemaVersion: 'brik64.cli_beta8_marketplace_package_gate.v1', + version: '0.1.0-beta.8', + decision: failures.length === 0 ? 'PASS_MARKETPLACE_PACKAGE_GATE' : 'FAIL_MARKETPLACE_PACKAGE_GATE', + releaseEligible: failures.length === 0, + marketplacePublicationAllowed: failures.length === 0, + packages: { + npm: { repository: repos.js, packageName: '@brik64/core', version: jsVersion, artifact: jsTarball }, + pypi: { repository: repos.python, packageName: 'brik64', version: '0.1.0b8', wheel: pythonWheel, sdist: pythonSdist }, + cargo: { repository: repos.rust, crateName: 'brik64-core', version: '0.1.0-beta.8', artifact: rustCrate } + }, + failures, + boundary: 'Package artifacts are local beta8 publication inputs. This gate verifies readiness but does not mutate npm, PyPI or crates.io.' + }; + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`marketplacePublicationAllowed=${report.marketplacePublicationAllowed}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (failures.length > 0) process.exit(1); +} + +main(); diff --git a/scripts/beta8-sdk-sync-gate.js b/scripts/beta8-sdk-sync-gate.js new file mode 100644 index 00000000..6e4996f5 --- /dev/null +++ b/scripts/beta8-sdk-sync-gate.js @@ -0,0 +1,91 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const root = path.resolve(__dirname, '..'); +const outDir = path.join(root, 'evidence', 'beta8-sdk-sync'); +const version = '0.1.0-beta.8'; +const pyVersion = '0.1.0b8'; + +const repos = [ + { + id: 'js_ts', + path: '/Users/carlosjperez/Documents/GitHub/brik64-lib-js', + files: ['package.json', 'README.md'], + versionFile: 'package.json', + expected: '"version": "0.1.0-beta.8"' + }, + { + id: 'python', + path: '/Users/carlosjperez/Documents/GitHub/brik64-lib-python', + files: ['pyproject.toml', 'README.md'], + versionFile: 'pyproject.toml', + expected: 'version = "0.1.0b8"' + }, + { + id: 'rust', + path: '/Users/carlosjperez/Documents/GitHub/brik64-lib-rust', + files: ['Cargo.toml', 'README.md'], + versionFile: 'Cargo.toml', + expected: 'version = "0.1.0-beta.8"' + } +]; + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +function sha256File(file) { + return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); +} + +function scanRepo(repo) { + const failures = []; + const artifacts = []; + for (const rel of repo.files) { + const file = path.join(repo.path, rel); + if (!fs.existsSync(file)) { + failures.push(`missing_sdk_file:${repo.id}:${rel}`); + continue; + } + const text = fs.readFileSync(file, 'utf8'); + artifacts.push({ path: file, sha256: sha256File(file), bytes: Buffer.byteLength(text, 'utf8') }); + if (/0\.1\.0-beta\.[4567](?:\.1)?|0\.1\.0b[4567](?:\.post1)?|beta[4567]|beta\.[4567]/.test(text)) { + failures.push(`stale_beta_reference:${repo.id}:${rel}`); + } + if (/\bL[456]\+?N5\b|\bfixpoint\b|\bself-host/i.test(text)) { + failures.push(`private_or_claim_language:${repo.id}:${rel}`); + } + } + const versionText = fs.existsSync(path.join(repo.path, repo.versionFile)) + ? fs.readFileSync(path.join(repo.path, repo.versionFile), 'utf8') + : ''; + if (!versionText.includes(repo.expected)) failures.push(`sdk_beta8_version_missing:${repo.id}`); + return { id: repo.id, repo: repo.path, status: failures.length === 0 ? 'updated' : 'blocked', artifacts, failures }; +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const sdks = repos.map(scanRepo); + const failures = sdks.flatMap((sdk) => sdk.failures); + const report = { + schemaVersion: 'brik64.cli_beta8_sdk_sync_gate.v1', + version, + pythonVersion: pyVersion, + decision: failures.length === 0 ? 'PASS_SDK_BETA8_SYNC' : 'FAIL_SDK_BETA8_SYNC', + releaseEligible: failures.length === 0, + marketplacePublicationAllowed: failures.length === 0, + sdks, + failures, + boundary: 'SDK repositories must be beta8 aligned before marketplace publication. This gate does not mutate npm, PyPI or crates.io.' + }; + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`marketplacePublicationAllowed=${report.marketplacePublicationAllowed}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (failures.length > 0) process.exit(1); +} + +main(); diff --git a/scripts/beta8-skills-sync-gate.js b/scripts/beta8-skills-sync-gate.js new file mode 100644 index 00000000..ab9313ec --- /dev/null +++ b/scripts/beta8-skills-sync-gate.js @@ -0,0 +1,70 @@ +#!/usr/bin/env node +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const root = path.resolve(__dirname, '..'); +const skillsRoot = '/Users/carlosjperez/Documents/GitHub/brik64-tools-skills'; +const outDir = path.join(root, 'evidence', 'beta8-skills-sync'); +const version = '0.1.0-beta.8'; + +process.stdout.on('error', (error) => { + if (error.code === 'EPIPE') process.exit(0); + throw error; +}); + +const files = [ + 'README.md', + 'skills/brik64/SKILL.md', + 'skills/brik64-javascript/SKILL.md', + 'skills/brik64-python/SKILL.md', + 'skills/brik64-rust/SKILL.md', + 'skills/pcd-system/SKILL.md', + 'skills/digital-circuitality/SKILL.md' +]; + +function sha256File(file) { + return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); +} + +function main() { + fs.mkdirSync(outDir, { recursive: true }); + const failures = []; + const artifacts = []; + for (const rel of files) { + const file = path.join(skillsRoot, rel); + if (!fs.existsSync(file)) { + failures.push(`missing_skill_file:${rel}`); + continue; + } + const text = fs.readFileSync(file, 'utf8'); + artifacts.push({ path: file, sha256: sha256File(file), bytes: Buffer.byteLength(text, 'utf8') }); + if (/0\.1\.0-beta\.[4567](?:\.1)?|0\.1\.0b[4567](?:\.post1)?|beta[4567]|beta\.[4567]/.test(text)) failures.push(`skill_stale_beta_residue:${rel}`); + if (/\bL[456]\+?N5\b|\bfixpoint\b|\bself-host\b|Hetzner|1Password/.test(text)) failures.push(`skill_private_or_claim_language:${rel}`); + } + const brik64Path = path.join(skillsRoot, 'skills/brik64/SKILL.md'); + const brik64 = fs.existsSync(brik64Path) ? fs.readFileSync(brik64Path, 'utf8') : ''; + if (!brik64.includes(`Public CLI version: \`${version}\``) && !brik64.includes('Public CLI version: dynamic')) failures.push('brik64_skill_beta8_version_boundary_missing'); + if (!brik64.includes('@brik64/core@0.1.0-beta.8')) failures.push('brik64_skill_js_sdk_missing'); + if (!brik64.includes('brik64==0.1.0b8')) failures.push('brik64_skill_python_sdk_missing'); + if (!brik64.includes('brik64-core@0.1.0-beta.8')) failures.push('brik64_skill_rust_sdk_missing'); + + const report = { + schemaVersion: 'brik64.cli_beta8_skills_sync_gate.v1', + version, + decision: failures.length === 0 ? 'PASS_SKILLS_BETA8_SYNC' : 'FAIL_SKILLS_BETA8_SYNC', + releaseEligible: failures.length === 0, + publicSkillPublicationAllowed: failures.length === 0, + skillsRoot, + artifacts, + failures, + boundary: 'Public skills must be beta8 aware and must not expose private release or engine nomenclature.' + }; + fs.writeFileSync(path.join(outDir, 'report.json'), `${JSON.stringify(report, null, 2)}\n`); + process.stdout.write(`decision=${report.decision}\n`); + process.stdout.write(`publicSkillPublicationAllowed=${report.publicSkillPublicationAllowed}\n`); + if (failures.length > 0) process.stdout.write(`failures=${failures.join(',')}\n`); + if (failures.length > 0) process.exit(1); +} + +main(); diff --git a/scripts/release-flow-audit.js b/scripts/release-flow-audit.js index 79fa2f29..9ec18943 100644 --- a/scripts/release-flow-audit.js +++ b/scripts/release-flow-audit.js @@ -134,8 +134,18 @@ function main() { for (const scriptName of requiredBetaScripts(label)) { add(Boolean(scripts[scriptName]), failures, `current_beta_script_missing:${scriptName}`); } - add(fs.existsSync(path.join(root, 'scripts', `build-${label}-package.js`)), failures, `current_beta_package_builder_missing:${label}`); - add(fs.existsSync(path.join(root, 'scripts', `${label}-package-smoke.js`)), failures, `current_beta_package_smoke_missing:${label}`); + add( + fs.existsSync(path.join(root, 'scripts', `build-${label}-package.js`)) + || fs.existsSync(path.join(root, 'scripts', `build-${label}-package.sh`)), + failures, + `current_beta_package_builder_missing:${label}` + ); + add( + fs.existsSync(path.join(root, 'scripts', `${label}-package-smoke.js`)) + || fs.existsSync(path.join(root, 'scripts', `${label}-package-smoke.sh`)), + failures, + `current_beta_package_smoke_missing:${label}` + ); add(fs.existsSync(path.join(root, 'evidence', `${label}-package`, 'package.manifest.json')), failures, `current_beta_package_manifest_missing:${label}`); } @@ -173,7 +183,11 @@ function main() { add(changelogSection.length > 0, failures, 'changelog_section_missing'); const changelogForbidden = forbiddenHits(changelogSection); if (changelogForbidden.length > 0) failures.push(`changelog_internal_language:${changelogForbidden.join('|')}`); - add(readme.includes(`Current public beta: \`${manifest.version}\``), failures, 'readme_public_version_drift'); + if (manifest.state === 'public') { + add(readme.includes(`Current public beta: \`${manifest.version}\``), failures, 'readme_public_version_drift'); + } else { + add(readme.includes(`Current beta candidate: \`${manifest.version}\``), failures, 'readme_candidate_version_drift'); + } textContainsAll(publishPlan, [ 'github_release', From 33effb201aca04cbcf56d46f018472296f5f8b67 Mon Sep 17 00:00:00 2001 From: carlosjperez Date: Sun, 7 Jun 2026 12:26:49 +0200 Subject: [PATCH 12/13] Use account-specific beta8 signing preflight --- .github/workflows/release-train-publish.yml | 6 ---- docs/GITHUB_SIGNING_KEY_RUNBOOK.md | 33 +++++++++++++-------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release-train-publish.yml b/.github/workflows/release-train-publish.yml index 8678733d..b015692e 100644 --- a/.github/workflows/release-train-publish.yml +++ b/.github/workflows/release-train-publish.yml @@ -64,11 +64,6 @@ jobs: - name: Generate sync payload run: npm run release:train:sync-surfaces - - name: Preflight GitHub signing key registration - env: - GH_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} - run: npm run preflight:github-signing-key - - name: Verify GitHub signed release commit env: GH_TOKEN: ${{ secrets.BRIK64_GITHUB_RELEASE_TOKEN }} @@ -186,7 +181,6 @@ jobs: evidence/release-train-sync/changelog.md evidence/release-train-sync/sync-payload.json evidence/release-train-sync/report.json - evidence/github-signing-key-preflight/report.json evidence/beta8-github-verified-signature/report.json evidence/release-train-publish-plan/report.json evidence/release-train-publish-execute/report.json diff --git a/docs/GITHUB_SIGNING_KEY_RUNBOOK.md b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md index 046f7bff..39408b2b 100644 --- a/docs/GITHUB_SIGNING_KEY_RUNBOOK.md +++ b/docs/GITHUB_SIGNING_KEY_RUNBOOK.md @@ -8,18 +8,20 @@ Current blocker: - PR: https://github.com/brik64/brik64-cli/pull/65 - State: approved, checks green, merge blocked - GitHub verification reason: `unknown_key` -- Expected public key fingerprint: - `SHA256:OEJJTFqu5VlYv7mAH3iGhTpIVhQLYbMaSzZ9Y+MLwFo` +- Commit signing account: `carlosjperez` +- Public key fingerprint for this release lane: + `SHA256:Ua933KXYBhzgl5+852YF5GYMwOab/RGZwevZyImNfZ8` Do not use admin merge override. The release train must pass with GitHub recognizing the exact release commit as verified. ## Preflight -Run: +Run with the public key that belongs to the commit signing account: ```bash -npm run preflight:github-signing-key +npm run preflight:github-signing-key -- \ + --public-key "$HOME/.ssh/brik64-carlosjperez-release-signing.pub" ``` Expected blocked state before authorization: @@ -46,27 +48,33 @@ Complete the browser device-flow approval. After approval, verify scopes: gh auth status -h github.com ``` -The active account used to register the key must be the account that will own -the verified signing key for the beta8 commit identity. +The active account used to register the key must be the account that owns the +beta8 commit identity. A GitHub SSH signing key cannot be reused across +accounts. If the key is already registered to another account, create a +separate signing key for the actual committing account. ## Register The Public Signing Key -Never print or upload the private key. Register only: +Never print or upload the private key. Register only the public key for the +committing account: ```bash -~/.ssh/brik64-admin-signing.pub +~/.ssh/brik64-carlosjperez-release-signing.pub ``` The public key fingerprint must match: ```text -SHA256:OEJJTFqu5VlYv7mAH3iGhTpIVhQLYbMaSzZ9Y+MLwFo +SHA256:Ua933KXYBhzgl5+852YF5GYMwOab/RGZwevZyImNfZ8 ``` Preferred repo command after scopes are authorized: ```bash -npm run release:github-signing-key:register -- --execute +npm run release:github-signing-key:register -- \ + --execute \ + --public-key "$HOME/.ssh/brik64-carlosjperez-release-signing.pub" \ + --title "BRIK64 beta8 release signing key carlosjperez" ``` The command is idempotent. It lists existing GitHub SSH signing keys, compares @@ -79,7 +87,7 @@ Equivalent API path: gh api user/ssh_signing_keys \ --method POST \ --field title="BRIK64 beta8 release signing key" \ - --field key="$(cat ~/.ssh/brik64-admin-signing.pub)" + --field key="$(cat ~/.ssh/brik64-carlosjperez-release-signing.pub)" ``` If GitHub reports the key already exists, continue to validation. @@ -89,7 +97,8 @@ If GitHub reports the key already exists, continue to validation. Run: ```bash -npm run preflight:github-signing-key +npm run preflight:github-signing-key -- \ + --public-key "$HOME/.ssh/brik64-carlosjperez-release-signing.pub" ``` Required result: From 5a938a8a640b42958920953655cb581023e204dc Mon Sep 17 00:00:00 2001 From: BRIK-64 <267284637+brik64-admin@users.noreply.github.com> Date: Sun, 7 Jun 2026 12:30:55 +0200 Subject: [PATCH 13/13] Confirm beta8 verified release head