File size: 9,826 Bytes
601688c 48eff88 44d9a27 601688c 44d9a27 601688c 44d9a27 601688c 15d2011 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Cortex Loop - one tick, end to end</title>
<meta name="description" content="A minimal walkthrough of one loop tick: tick, propose, check, try-complete, using a synthetic page-edit ledger.">
<style>
:root{--ink:#111318;--muted:#5b6472;--line:#e3e7ee;--bg:#fbfcfe;--ok:#1a7f4b;--warn:#b45309;--bad:#b91c1c;--accent:#3b4cca}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
.wrap{max-width:960px;margin:0 auto;padding:48px 24px 80px}
h1{font-size:34px;line-height:1.2;margin:0 0 12px;letter-spacing:-.02em}
.sub{color:var(--muted);font-size:17px;margin:0 0 28px;max-width:70ch}
.flow{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 32px;padding:0;list-style:none}
.flow li{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;padding:6px 12px;border:1px solid var(--line);border-radius:999px;background:#fff;color:var(--muted)}
.flow li.on{border-color:var(--accent);color:var(--accent);font-weight:600}
.card{background:#fff;border:1px solid var(--line);border-radius:14px;padding:22px;margin:0 0 20px}
.card h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:0 0 14px}
button{font:inherit;font-weight:600;padding:11px 20px;border-radius:10px;border:1px solid var(--accent);background:var(--accent);color:#fff;cursor:pointer}
button:hover{filter:brightness(1.08)}
button[disabled]{opacity:.45;cursor:not-allowed}
button.ghost{background:#fff;color:var(--accent)}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
table{width:100%;border-collapse:collapse;font-size:14px}
th,td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);font-weight:600}
td.mono,th.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}
.pill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:600}
.p-pending{background:#eef1f6;color:#475569}
.p-check{background:#fff7e6;color:var(--warn)}
.p-done{background:#e8f7ee;color:var(--ok)}
.p-blocked{background:#fdeaea;color:var(--bad)}
.log{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;background:#0f1420;color:#d7e0ee;border-radius:12px;padding:18px;min-height:190px;white-space:pre-wrap;overflow:auto}
.log .k{color:#8fb4ff}
.log .g{color:#66d19e}
.log .y{color:#f0c86b}
.log .r{color:#ff8f8f}
.foot{color:var(--muted);font-size:14px;margin-top:36px;padding-top:22px;border-top:1px solid var(--line)}
a{color:var(--accent)}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;background:#eef1f6;padding:1px 6px;border-radius:5px}
</style>
</head>
<body>
<div class="wrap">
<p style="margin:0 0 6px;font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:#5b6472">Cortex Loop</p><h1>Done is a check result, not a claim.</h1>
<p class="sub" style="font-size:18px;color:#111318">A loop should not be able to finish by asserting that it finished. Here is one that cannot.</p>
<p class="sub"><strong>The problem:</strong> an AI agent can always <em>say</em> it finished. Saying it is free. That is why so much "progress" evaporates on inspection.</p><p class="sub"><strong>What this page proves:</strong> a loop that refuses to mark work complete until the evidence matches. Pick a tick, and watch it succeed on three items and <strong>refuse</strong> on two - because the evidence was not there.</p><p class="sub" style="font-size:15px">No model call, no server: the whole state machine runs in your browser over a synthetic ledger.</p>
<ul class="flow" id="flow">
<li data-p="tick">1 tick</li>
<li data-p="propose">2 propose</li>
<li data-p="check">3 check</li>
<li data-p="complete">4 try-complete</li>
</ul>
<div class="card">
<h2>Synthetic ledger</h2><p style="margin:0 0 14px;padding:10px 14px;background:#fff7e6;border-radius:9px;font-size:14px;color:#7a4b00"><strong>Note:</strong> items <code>edit-2044</code> and <code>edit-2045</code> are designed to <strong>fail</strong> their check. The loop will refuse them. That refusal is the feature.</p>
<table>
<thead><tr><th class="mono">item</th><th>intent</th><th class="mono">state</th></tr></thead>
<tbody id="ledger"></tbody>
</table>
</div>
<div class="card">
<h2>Run one tick</h2>
<div class="row">
<button id="run">Run tick</button>
<button id="reset" class="ghost">Reset ledger</button>
<span id="hint" style="color:var(--muted);font-size:14px">Idle. Press Run tick.</span>
</div>
</div>
<div class="card">
<h2>Trace</h2>
<div class="log" id="log">waiting for tick...</div>
</div>
<p class="foot" style="border-top:none;padding-top:0;margin-top:8px"><strong>Why it matters:</strong> once completion requires evidence, "done" stops being a claim and starts being a check result. That is the difference between an agent that reports progress and one that produces it.</p><p class="foot">
The loop engine is open source: <a href="https://github.com/mobfish-ai/cortex-loop" target="_blank" rel="noopener">cortex-loop</a>
and the harness it drives: <a href="https://github.com/mobfish-ai/cortex-harness-open" target="_blank" rel="noopener">cortex-harness-open</a>.
Example targets come from a public storefront, <a href="https://www.themossriver.com/pages/fit-finder?utm_source=huggingface&utm_medium=space&utm_campaign=cortex_loop_demo" target="_blank" rel="noopener">fit finder</a>
and <a href="https://www.themossriver.com/pages/todays-agent-deal?utm_source=huggingface&utm_medium=space&utm_campaign=cortex_loop_demo" target="_blank" rel="noopener">today's deal</a>.
All ledger rows here are synthetic. No customer records, contact details, hostnames, or internal identifiers are used.
</p>
</div>
<script>
const LEDGER_SEED = [
{id:'edit-2041', intent:'Add a size note beside the buy button', state:'pending'},
{id:'edit-2042', intent:'Point the article entry link at the product page', state:'pending'},
{id:'edit-2043', intent:'Rewrite the promo block copy for the current SKU', state:'pending'},
{id:'edit-2044', intent:'Link a low-traffic landing page into the deal page', state:'pending'},
{id:'edit-2045', intent:'Refresh the stock badge on a variant', state:'pending'}
];
const CHECKS = {
'edit-2041': {evidence:'note rendered in page body near the buy button', pass:true},
'edit-2042': {evidence:'entry anchor resolves to /products/... with tracking', pass:true},
'edit-2043': {evidence:'copy names only the linked product', pass:true},
'edit-2044': {evidence:'landing page returns 200 and contains the link', pass:false},
'edit-2045': {evidence:'variant stock count differs from source of truth', pass:false}
};
let ledger = JSON.parse(JSON.stringify(LEDGER_SEED));
const el = id => document.getElementById(id);
const sleep = ms => new Promise(r => setTimeout(r, ms));
function paint(){
el('ledger').innerHTML = ledger.map(r =>
'<tr><td class="mono">'+r.id+'</td><td>'+r.intent+'</td><td class="mono"><span class="pill p-'+stateClass(r.state)+'">'+r.state+'</span></td></tr>'
).join('');
}
function stateClass(s){
if(s==='pending') return 'pending';
if(s==='checking') return 'check';
if(s==='complete') return 'done';
return 'blocked';
}
function mark(id, s){
const r = ledger.find(x => x.id === id);
if(r) r.state = s;
paint();
}
function phase(p){
document.querySelectorAll('#flow li').forEach(li => li.classList.toggle('on', li.dataset.p === p));
}
function log(html){
const box = el('log');
box.innerHTML += '\n' + html;
box.scrollTop = box.scrollHeight;
}
async function tick(){
el('run').disabled = true;
el('log').textContent = '';
phase('tick');
const next = ledger.find(r => r.state === 'pending');
if(!next){
log('<span class="g">tick: ledger drained, nothing runnable</span>');
el('hint').textContent = 'Ledger drained.';
el('run').disabled = false;
return;
}
log('<span class="k">tick</span> picked '+next.id+' from '+ledger.length+' items (rule: first pending)');
el('hint').textContent = 'Picked ' + next.id;
await sleep(700);
phase('propose');
log('<span class="k">propose</span> '+next.intent+' -> one concrete change, no side effects yet');
await sleep(700);
phase('check');
mark(next.id, 'checking');
log('<span class="k">check</span> evidence: '+CHECKS[next.id].evidence);
await sleep(900);
phase('complete');
const ok = CHECKS[next.id].pass;
if(ok){
mark(next.id, 'complete');
log('<span class="g">try-complete accepted</span> evidence matched -> state=complete');
} else {
mark(next.id, 'blocked');
log('<span class="r">try-complete refused</span> evidence did not match -> state=blocked, tick ends here');
}
await sleep(500);
const left = ledger.filter(r => r.state === 'pending').length;
log('<span class="y">summary</span> completed='+ledger.filter(r=>r.state==='complete').length+
' blocked='+ledger.filter(r=>r.state==='blocked').length+
' pending='+left);
el('hint').textContent = ok ? 'Accepted. Press Run tick again.' : 'Refused. This is the point of the check.';
el('run').disabled = false;
}
el('run').addEventListener('click', tick);
el('reset').addEventListener('click', () => {
ledger = JSON.parse(JSON.stringify(LEDGER_SEED));
paint();
phase('');
el('log').textContent = 'waiting for tick...';
el('hint').textContent = 'Idle. Press Run tick.';
el('run').disabled = false;
});
paint();
</script>
</body>
</html>
|