diff --git a/src/competition-readiness.mjs b/src/competition-readiness.mjs index 43d4823..7b0c807 100644 --- a/src/competition-readiness.mjs +++ b/src/competition-readiness.mjs @@ -5,17 +5,17 @@ const IMPLEMENTATION_GATES = [ "cantonLifecycle", "negativeSecurity", "judgeUi", - "track1Package", + "colosseumPackage", ]; const EXTERNAL_GATES = [ - "publicRepository", - "publicArtifacts", - "mana1000", - "activity10Days", - "journalNonEmpty", + "repositoryAccess", + "presentationVideo", + "technicalDemoVideo", "projectProfileComplete", - "track1Selected", + "founderProfileComplete", + "preExistingWorkDisclosure", + "demandValidationDisclosure", ]; function normalizeStatus(value, kind) { diff --git a/tests/competition-readiness.test.mjs b/tests/competition-readiness.test.mjs index ab2c7f7..942949b 100644 --- a/tests/competition-readiness.test.mjs +++ b/tests/competition-readiness.test.mjs @@ -1,6 +1,6 @@ import test from "node:test"; import assert from "node:assert/strict"; -import { evaluateCompetitionReadiness } from "../src/competition-readiness.mjs"; +import { evaluateCompetitionReadiness, competitionGateNames } from "../src/competition-readiness.mjs"; const verifiedImplementation = { nodeTests: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, @@ -9,37 +9,47 @@ const verifiedImplementation = { cantonLifecycle: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, negativeSecurity: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, judgeUi: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, - track1Package: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, + colosseumPackage: { status: "verified", runId: "run-1", sourceCommit: "abc123" }, }; const verifiedExternal = { - publicRepository: { status: "verified" }, - publicArtifacts: { status: "verified" }, - mana1000: { status: "verified" }, - activity10Days: { status: "verified" }, - journalNonEmpty: { status: "verified" }, + repositoryAccess: { status: "verified" }, + presentationVideo: { status: "verified" }, + technicalDemoVideo: { status: "verified" }, projectProfileComplete: { status: "verified" }, - track1Selected: { status: "verified" }, + founderProfileComplete: { status: "verified" }, + preExistingWorkDisclosure: { status: "verified" }, + demandValidationDisclosure: { status: "verified" }, }; +test("uses Colosseum-specific implementation and submission gates", () => { + assert.deepEqual(competitionGateNames.implementation, [ + "nodeTests","damlBuild","damlTests","cantonLifecycle","negativeSecurity","judgeUi","colosseumPackage" + ]); + assert.deepEqual(competitionGateNames.external, [ + "repositoryAccess","presentationVideo","technicalDemoVideo","projectProfileComplete", + "founderProfileComplete","preExistingWorkDisclosure","demandValidationDisclosure" + ]); +}); + test("returns PASS only when implementation and external gates are verified", () => { const result = evaluateCompetitionReadiness({ implementation: verifiedImplementation, external: verifiedExternal }); assert.equal(result.status, "PASS"); assert.deepEqual(result.counts, { pass: 14, blocked: 0, fail: 0 }); }); -test("returns BLOCKED when an external gate is not yet verified", () => { +test("returns BLOCKED when a submission-side gate is not yet verified", () => { const result = evaluateCompetitionReadiness({ implementation: verifiedImplementation, - external: { ...verifiedExternal, mana1000: { status: "blocked", reason: "AppsFactory account not checked" } }, + external: { ...verifiedExternal, repositoryAccess: { status: "blocked", reason: "Judge repository access not yet confirmed" } }, }); assert.equal(result.status, "BLOCKED"); - assert.equal(result.gates.find(g => g.name === "mana1000").status, "BLOCKED"); + assert.equal(result.gates.find(g => g.name === "repositoryAccess").status, "BLOCKED"); }); -test("returns FAIL when an implementation gate fails even if external gates are blocked", () => { +test("returns FAIL when an implementation gate fails even if submission gates are blocked", () => { const result = evaluateCompetitionReadiness({ implementation: { ...verifiedImplementation, damlTests: { status: "failed", reason: "Daml test failed" } }, - external: { ...verifiedExternal, publicRepository: { status: "blocked" } }, + external: { ...verifiedExternal, repositoryAccess: { status: "blocked" } }, }); assert.equal(result.status, "FAIL"); assert.ok(result.counts.fail >= 1); diff --git a/tests/judge-ui-static.test.mjs b/tests/judge-ui-static.test.mjs index f4a5c2f..a2113b4 100644 --- a/tests/judge-ui-static.test.mjs +++ b/tests/judge-ui-static.test.mjs @@ -4,28 +4,29 @@ import fs from 'node:fs/promises'; const html = await fs.readFile(new URL('../web/index.html', import.meta.url), 'utf8'); -test('judge UI exposes competition readiness without claiming submission ready', () => { +test('judge UI marks the product ready without claiming submission ready', () => { assert.match(html, /id="competition-readiness"/); - assert.match(html, /BLOCKED · external gates pending/); + assert.match(html, /READY · product/); assert.doesNotMatch(html, /SUBMISSION READY/); + assert.doesNotMatch(html, /HackCanton S3|Track 1|Mana \/ activity \/ journal/); }); -test('judge UI maps all six official judging criteria', () => { - for (const label of ['Value \/ Problem','ICP \/ Audience','Metrics \/ Validation','GTM Materials','MVP Materials','Pitch Materials']) { +test('judge UI maps the six Colosseum judging criteria', () => { + for (const label of ['Functionality','Potential Impact','Novelty','UX','Open-source \/ Composability','Business Plan']) { assert.match(html, new RegExp(label)); } }); -test('judge UI identifies Track 1 and describes proof as evidence-first', () => { - assert.match(html, /Track 1/); - assert.match(html, /no sample transaction IDs or simulated settlement success/i); +test('judge UI presents the foundation settlement story and evidence-first proof', () => { + assert.match(html, /A foundation pays contributors only after independently verified work/); + assert.match(html, /Foundation \/ Maintainer/); + assert.match(html, /Independent Verifier/); + assert.match(html, /No simulated settlement success/i); }); -test('judge cockpit exposes current verified fixture and runtime proof state', () => { - for (const label of ['Source','Authorization','Settlement','Runtime']) { - assert.match(html, new RegExp(label)); - } +test('judge cockpit exposes the verified fixture and replay-rejection story', () => { assert.match(html, /GitHub #69 → PR #73/); - assert.match(html, /Runtime[\s\S]*VERIFIED/); - assert.match(html, /PASS[\s\S]*Daml \+ real Canton proof/); + assert.match(html, /REPLAY REJECTED/); + assert.match(html, /Daml authorization \+ real Canton proof/); + assert.match(html, /Crypto World's Fair 2026/); }); diff --git a/web/index.html b/web/index.html index 8cc36ec..56f577f 100644 --- a/web/index.html +++ b/web/index.html @@ -2,38 +2,39 @@ - -CommitLedger - Verified work, settled on Canton + +CommitLedger — Verified work, authorized settlement - +
-

GITHUB EVIDENCE / DAML AUTHORIZATION / CANTON SETTLEMENT

Work is not settled until the proof is verifiable.

From merged code to inspectable settlement: canonical GitHub evidence, explicit multi-party authorization, and a Canton receipt in one judgeable workflow.

Issue→Bounty→Claim→Pull request→Verify→Settle→Receipt
+

VERIFIED WORK / EXPLICIT AUTHORITY / AUDITABLE SETTLEMENT

A foundation pays contributors only after independently verified work.

CommitLedger turns a real GitHub issue and merged pull request into a role-authorized Canton settlement receipt, while blocking wrong evidence, unauthorized settlement and duplicate payment.

Issue→Bounty→Claim→Pull request→Verify→Settle→Receipt
-
SourceGitHub #69 → PR #73Open issue + canonical merged pull request
-
Authorization3 explicit rolesMaintainer · Contributor · Verifier
+
Real workGitHub #69 → PR #73Canonical issue + merged pull request
+
Authority3 explicit rolesFoundation · Contributor · Verifier
SettlementDEMO_CREDITNon-production test value
-
RuntimeVERIFIEDReal Canton proof captured during deploy
+
SecurityREPLAY REJECTEDDuplicate settlement fails on the ledger
-

COMPETITION READINESS

Technical proof is green; external gates remain fail-closed

BLOCKED · external gates pending
-

The runtime proof is verified independently. Repository publication, final video, Mana/activity, journal and project-profile requirements remain blocked until they are actually verified.

-
PASSNode verification
PASSDaml + real Canton proof
BLOCKEDMana / activity / journal
BLOCKEDFinal public submission materials
+

PRODUCT READINESS

The product is proof-backed and judgeable now

READY · product
+

This status covers the product itself: working flow, runtime evidence, authorization and security proof. Colosseum portal fields, videos and repository-review access are intentionally handled later as submission tasks.

+
PASSGitHub → Canton → receipt flow
PASSDaml authorization + real Canton proof
PASSWrong evidence, unauthorized action and replay rejected
READYFoundation contributor-settlement workflow
-

VERIFIED CANTON PROOF

Inspect the deployed six-step lifecycle

Loading proof artifact
-

A fresh Canton sandbox ran during this deployment. This page exposes the resulting read-only proof bundle. The build-time sandbox is intentionally ephemeral; no sample transaction IDs or simulated settlement success are shown. DEMO_CREDIT is not real money.

-
+

PROVEN SETTLEMENT

Inspect the complete six-step Canton lifecycle

Loading proof artifact
+

A fresh Canton sandbox executed the workflow during deployment. This page exposes the resulting source-bound proof bundle, including contract IDs, update IDs, the final SettlementReceipt and security rejections. No simulated settlement success is shown.

+

Loading deployment evidence…

Loading verified deployment proof…
-

CANONICAL ISSUE

Verify the work source

Waiting
Issue identity and state are fetched server-side from GitHub.
-

CANONICAL MERGE

Verify the merged pull request

Waiting
No merge evidence loaded.
+

1 · CANONICAL WORK SOURCE

Verify the exact GitHub issue

Waiting
Issue identity and state are fetched server-side from GitHub.
-

OFFICIAL JUDGING CRITERIA

Six questions, six visible answers

Value / ProblemGitHub proves code events; Canton enforces who may verify and settle.
ICP / AudienceOpen-source maintainers, foundations and contributor bounty programs.
Metrics / ValidationReal GitHub fixture, deterministic tests and a source-bound Canton proof.
GTM MaterialsSingle-repo pilot → foundation/ecosystem bounty program → settlement adapter.
MVP MaterialsGitHub verification + Daml authorization + Canton receipt + attack rejection.
Pitch MaterialsProblem → proof → rejected attacks → receipt → why Canton → pilot path.
-
+

2 · INDEPENDENT VERIFICATION

Verify the exact merged pull request

Waiting
No merge evidence loaded.
+ +

COLOSSEUM JUDGING FIT

Six criteria, visible in the product

FunctionalityEnd-to-end GitHub verification, Daml authorization, Canton lifecycle and final receipt are proven.
Potential ImpactTargets foundations, protocols and open-source programs that already pay contributors for verifiable work.
NoveltySeparates external work evidence from settlement authority instead of trusting one application server.
UXOne judgeable proof surface exposes the trust chain, ledger references, receipt and rejection cases.
Open-source / ComposabilityGitHub evidence, Daml contracts and a narrow settlement interface create a modular integration boundary.
Business PlanWedge: contributor bounties. Expansion: grants, policy controls, audit workflows and settlement adapters.
+ diff --git a/web/styles.css b/web/styles.css index d14ae22..0211e14 100644 --- a/web/styles.css +++ b/web/styles.css @@ -1,3 +1,5 @@ :root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#eef4f5;background:#061014;line-height:1.5}*{box-sizing:border-box}body{margin:0;background:radial-gradient(circle at 18% -8%,#153b43 0,transparent 32%),linear-gradient(#071216,#061014)}.nav{min-height:76px;display:flex;align-items:center;justify-content:space-between;max-width:1200px;margin:auto;padding:16px 24px;border-bottom:1px solid #1d3339;gap:12px}.brand{font-size:21px;font-weight:800;color:#fff;text-decoration:none;letter-spacing:-.035em}.nav-right{display:flex;gap:8px}.badge,.status{display:inline-flex;align-items:center;font-size:11px;border:1px solid #315058;border-radius:999px;padding:6px 10px;color:#b9ced3;background:#0b181d}main{max-width:1200px;margin:auto;padding:32px 24px 64px}.hero{max-width:1050px;padding:42px 0 48px}.eyebrow,.kicker{font-size:11px;letter-spacing:.15em;color:#91bac3;font-weight:800;margin:0 0 12px}.hero h1{font-size:clamp(40px,6.5vw,78px);line-height:1.03;letter-spacing:-.055em;margin:0}.lead{font-size:20px;color:#a9c0c6;max-width:820px;margin:24px 0}.flow{display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin-top:28px}.flow span{padding:8px 11px;background:#0b171c;border:1px solid #254149;border-radius:9px;color:#a9bec3;font-size:13px}.flow b{color:#55767e}.workspace{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(280px,.65fr);gap:18px;margin-bottom:18px}.panel{border:1px solid #203940;background:rgba(8,20,25,.88);border-radius:18px;padding:24px;min-width:0}.live-panel{margin-bottom:18px;border-color:#365f68;background:linear-gradient(135deg,rgba(11,31,36,.96),rgba(7,20,24,.9))}.panel-head{display:flex;justify-content:space-between;gap:18px;align-items:flex-start}.panel h2{font-size:26px;letter-spacing:-.03em;margin:0 0 18px}.metric{border-top:1px solid #213840;padding:14px 0;display:grid;gap:3px}.metric strong{font-size:14px}.metric span,.muted{color:#a0b6bc;font-size:14px}label{display:grid;gap:7px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:#a7bfc5;margin:12px 0;min-width:0}input{width:100%;min-width:0;border:1px solid #29474f;border-radius:10px;background:#061014;color:#eef5f6;padding:12px 13px;font:inherit;text-transform:none;letter-spacing:0}input:focus-visible,button:focus-visible{outline:2px solid #a3d6df;outline-offset:3px}input:disabled{opacity:.75}.row{display:grid;grid-template-columns:1fr 1fr;gap:12px}.row.three{grid-template-columns:.7fr 1.2fr .7fr}button{border:0;border-radius:10px;background:#e6f0f1;color:#061014;padding:12px 16px;font-weight:800;cursor:pointer;margin:6px 6px 0 0}button:disabled{cursor:not-allowed;opacity:.45}.secondary{background:#193740;color:#d8e9ed;border:1px solid #365963}.summary{display:grid;gap:4px;margin-top:18px;padding:15px;border:1px solid #2c4b53;border-radius:12px;background:#08171b}.output{min-height:150px;max-height:360px;overflow:auto;background:#040b0d;border:1px solid #1a3036;border-radius:10px;padding:14px;color:#b2d1d7;font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere}.timeline{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-top:22px}.timeline-empty,.timeline-error{grid-column:1/-1;padding:18px;border:1px dashed #315059;border-radius:12px;color:#a1b9bf}.timeline-error{border-color:#704047;color:#efbec2}.timeline-step{border:1px solid #29474e;border-radius:12px;padding:14px;background:#071519;min-width:0}.timeline-step strong,.timeline-step span{display:block}.timeline-step strong{font-size:14px;margin-bottom:5px}.timeline-step span{font-size:12px;color:#a1bac1}.timeline-step code,.receipt code{display:block;overflow-wrap:anywhere;font-size:11px;margin:5px 0;color:#c1dce2}details{margin-top:8px}summary{cursor:pointer;font-size:12px}.receipt{margin-top:16px;padding:20px;border:1px solid #47717a;border-radius:14px;background:rgba(15,38,44,.72);overflow-wrap:anywhere}.hidden{display:none}.receipt h3{margin:0 0 15px;font-size:22px}.receipt-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.receipt-grid span,.receipt-grid strong{display:block}.receipt-grid span{font-size:11px;color:#a2bdc5}.receipt-grid strong{font-size:13px;margin-top:4px}.negative{border-top:1px solid #35565e;margin-top:12px;padding-top:12px}footer{max-width:1200px;margin:auto;padding:24px;border-top:1px solid #1d3339;color:#98b0b7;font-size:12px}@media(max-width:900px){.workspace,.timeline,.receipt-grid,.row,.row.three{grid-template-columns:1fr}.hero{padding-top:18px}.panel-head{display:block}.status{margin-bottom:10px}.panel{padding:20px}main{padding:20px 16px 40px}.nav{padding:14px 16px}.nav-right .badge:last-child{display:none}.eyebrow{line-height:1.8}.lead{font-size:17px}} .readiness-panel,.criteria-panel{margin-bottom:18px}.status.blocked{border-color:#7a6540;color:#e4bc68}.readiness-grid,.criteria-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:18px}.readiness-grid>div,.criteria-grid article{border:1px solid #29474f;border-radius:12px;padding:14px;background:#071519;min-width:0}.readiness-grid strong,.readiness-grid span,.criteria-grid strong,.criteria-grid span{display:block}.readiness-grid strong,.criteria-grid strong{font-size:13px;margin-bottom:5px}.readiness-grid span,.criteria-grid span{font-size:12px;color:#a1bac1}.criteria-grid{grid-template-columns:repeat(3,minmax(0,1fr))}@media(max-width:900px){.readiness-grid,.criteria-grid{grid-template-columns:1fr}} .evidence-rail{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin:0 0 18px}.evidence-rail article{border:1px solid #29474f;border-radius:14px;padding:16px;background:linear-gradient(180deg,rgba(11,24,29,.94),rgba(7,21,25,.9));min-width:0}.evidence-rail span,.evidence-rail strong,.evidence-rail small{display:block}.evidence-rail span{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:#91bac3;font-weight:800}.evidence-rail strong{font-size:18px;letter-spacing:-.02em;margin:6px 0 3px;color:#eef4f5}.evidence-rail small{font-size:12px;color:#a0b6bc}.evidence-rail .runtime-verified{border-color:#3f7161}.evidence-rail .runtime-verified strong{color:#9fe0c4}@media(max-width:900px){.evidence-rail{grid-template-columns:1fr 1fr}}@media(max-width:560px){.evidence-rail{grid-template-columns:1fr}} + +.status.ready{border-color:#3f7161;color:#9fe0c4;background:#0b1d18}