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
-Source GitHub #69 → PR #73 Open issue + canonical merged pull request
-Authorization 3 explicit roles Maintainer · Contributor · Verifier
+Real work GitHub #69 → PR #73 Canonical issue + merged pull request
+Authority 3 explicit roles Foundation · Contributor · Verifier
Settlement DEMO_CREDIT Non-production test value
-Runtime VERIFIED Real Canton proof captured during deploy
+Security REPLAY REJECTED Duplicate 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.
-PASS Node verification
PASS Daml + real Canton proof
BLOCKED Mana / activity / journal
BLOCKED Final 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.
+PASS GitHub → Canton → receipt flow
PASS Daml authorization + real Canton proof
PASS Wrong evidence, unauthorized action and replay rejected
READY Foundation 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.
ROLE SEPARATION
Three parties. Three authorities. Maintainer creates, accepts, settles
Contributor claims, submits the PR
Verifier attests canonical merge evidence
Canton records authorized contract transitions
-CANONICAL MERGE
Verify the merged pull request Waiting No merge evidence loaded. TRUST BOUNDARY
GitHub proves the event. Canton controls the authority. Exact issue reference Cross-repository lookalikes are rejected.
Merge commit SHA Verified through GitHub and checked against the base branch.
Specific ledger rejection Network errors never count as security proof.
Demo authorization Local no-auth mode proves Daml choices, not production identity security.
+1 · CANONICAL WORK SOURCE
Verify the exact GitHub issue Waiting Issue identity and state are fetched server-side from GitHub.
WHO MAY ACT?
Three parties. Three authorities. Foundation / Maintainer creates, accepts and settles
Contributor claims work and submits the PR
Independent Verifier attests canonical merge evidence
Canton enforces authorized contract transitions
-OFFICIAL JUDGING CRITERIA
Six questions, six visible answers Value / Problem GitHub proves code events; Canton enforces who may verify and settle. ICP / Audience Open-source maintainers, foundations and contributor bounty programs. Metrics / Validation Real GitHub fixture, deterministic tests and a source-bound Canton proof. GTM Materials Single-repo pilot → foundation/ecosystem bounty program → settlement adapter. MVP Materials GitHub verification + Daml authorization + Canton receipt + attack rejection. Pitch Materials Problem → proof → rejected attacks → receipt → why Canton → pilot path.
- CommitLedger is independent. DEMO_CREDIT is non-production test value. No mainnet, real-money or traction claim is made.
+2 · INDEPENDENT VERIFICATION
Verify the exact merged pull request Waiting No merge evidence loaded. TRUST BOUNDARY
Evidence is not authority. GitHub proves the work event
Verifier binds the exact issue, PR, branch and merge evidence
Daml defines who may advance settlement state
Canton records the authorized result and blocks replay
+
+COLOSSEUM JUDGING FIT
Six criteria, visible in the product Functionality End-to-end GitHub verification, Daml authorization, Canton lifecycle and final receipt are proven. Potential Impact Targets foundations, protocols and open-source programs that already pay contributors for verifiable work. Novelty Separates external work evidence from settlement authority instead of trusting one application server. UX One judgeable proof surface exposes the trust chain, ledger references, receipt and rejection cases. Open-source / Composability GitHub evidence, Daml contracts and a narrow settlement interface create a modular integration boundary. Business Plan Wedge: contributor bounties. Expansion: grants, policy controls, audit workflows and settlement adapters.
+CommitLedger is independent. DEMO_CREDIT is non-production test value. No MainNet, real-money, customer or revenue claim is made.
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}